feat(ci): generic never-track rule for every root underscore path (_*)

This commit is contained in:
backryun
2026-08-12 13:11:58 -03:00
parent f831fc5a68
commit c92ac73cd4
4 changed files with 39 additions and 5 deletions

1
.gitignore vendored
View File

@@ -44,6 +44,7 @@ memory-bank/
# Root-level underscore-prefixed directories (private/draft — never commit)
/_*/
/_*
# Draft features documentation (internal only)
docs/new-features/

View File

@@ -258,6 +258,15 @@ Read the nearest `AGENTS.md` and the linked deep-dive before making a non-trivia
When creating _any_ validation tests or one-off logic scripts, default to `scripts/ad-hoc/` or `tests/unit/` according to your goals. Do not pollute the `/` root context.
- **Root `_*` paths are private and NEVER tracked** (`_tasks/`, `_references/`, `_mono_repo/`,
`_ideia/`, `_cache/` and any future `_<name>`): they live on disk only, are gitignored by the
anchored patterns `/_*/` + `/_*`, and some are full git repositories of their own (`_tasks`
private remote `_tasks_omniroute`). Never `git add` anything inside them (a plain `add` is
already blocked by the ignore; never use `-f`), and never "clean them up" from the main repo —
untracking is done with `git rm --cached` so the disk content stays. The
`check:tracked-artifacts` gate (pre-commit + CI) fails on ANY tracked root path starting with
`_`, present or future. See Hard Rule #23 for the `_tasks` specifics.
---
## Key Conventions

View File

@@ -27,11 +27,9 @@ const FORBIDDEN_PREFIXES = [
"node_modules/",
".next/",
"coverage/",
"_tasks/",
"_references/",
"_mono_repo/",
"_ideia/",
"_cache/",
// "_" na raiz é GENÉRICO (regra abaixo em checkTrackedArtifacts): _tasks/, _references/,
// _mono_repo/, _ideia/, _cache/ e qualquer _<novo>/ futuro — dirs privados, alguns com
// repo git próprio (_tasks). Nunca rastrear nada dentro deles (Hard Rule #23).
".claude/worktrees/",
"docs/superpowers/",
".eslintcache", // matches .eslintcache, .eslintcache-complexity, .eslintcache-probe, …
@@ -63,6 +61,13 @@ export function checkTrackedArtifacts(trackedFiles, trackedSymlinks = []) {
violations.push(`forbidden tracked artifact: ${file}`);
continue;
}
// Regra genérica: NENHUM caminho de raiz prefixado com "_" pode ser rastreado
// (dir ou arquivo). Cobre _tasks, _references, _mono_repo e qualquer _<novo> futuro;
// paths aninhados legítimos (src/lib/_x) não são atingidos.
if (file.startsWith("_")) {
violations.push(`forbidden tracked artifact (root underscore path): ${file}`);
continue;
}
for (const prefix of FORBIDDEN_PREFIXES) {
if (file.startsWith(prefix)) {
violations.push(`forbidden tracked artifact (${prefix}*): ${file}`);

View File

@@ -84,6 +84,25 @@ test("checkTrackedArtifacts: private root underscore dirs are flagged", () => {
assert.equal(result.length, 4);
});
test("checkTrackedArtifacts: ANY future root underscore dir is flagged (generic rule)", () => {
const result = checkTrackedArtifacts([
"_nova-pasta-futura/qualquer/arquivo.md",
"_scratch/notes.txt",
]);
assert.equal(result.length, 2);
assert.ok(result[0].includes("root underscore path"));
});
test("checkTrackedArtifacts: root underscore FILE is flagged; nested underscore paths pass", () => {
const flagged = checkTrackedArtifacts(["_notas-soltas.md"]);
assert.equal(flagged.length, 1);
const nested = checkTrackedArtifacts([
"src/lib/_internal/helper.ts",
"open-sse/services/_shared/util.ts",
]);
assert.deepEqual(nested, []);
});
test("checkTrackedArtifacts: .claude/worktrees/ prefix is flagged", () => {
const result = checkTrackedArtifacts([".claude/worktrees/fix-123/src/app.ts"]);
assert.equal(result.length, 1);