diff --git a/.gitignore b/.gitignore index 6b4352f871..345762d7e3 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ memory-bank/ # Root-level underscore-prefixed directories (private/draft — never commit) /_*/ +/_* # Draft features documentation (internal only) docs/new-features/ diff --git a/AGENTS.md b/AGENTS.md index 45af3cafd7..cff6d85c3f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 `_`): 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 diff --git a/scripts/check/check-tracked-artifacts.mjs b/scripts/check/check-tracked-artifacts.mjs index cd6dd8414f..fc8370af80 100644 --- a/scripts/check/check-tracked-artifacts.mjs +++ b/scripts/check/check-tracked-artifacts.mjs @@ -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 _/ 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 _ 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}`); diff --git a/tests/unit/build/check-tracked-artifacts.test.ts b/tests/unit/build/check-tracked-artifacts.test.ts index 62a5ed4b52..aaeb8f4162 100644 --- a/tests/unit/build/check-tracked-artifacts.test.ts +++ b/tests/unit/build/check-tracked-artifacts.test.ts @@ -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);