* enhance(#4095): checkpoint:decision auto-selection is opt-in via auto_select Auto-mode used to auto-select a checkpoint:decision's first <option> unconditionally, making a decision checkpoint's safety depend on option presentation order rather than an authored choice. Add an optional auto_select="<option-id>" attribute on the <task> tag: absent, auto-mode now escalates to a human exactly like gate="blocking-human" does; present, it names the option auto-mode selects; naming an id with no matching <option id> is a hard structural-validation error at plan-parse time rather than a silent fallback to the first option. gate="blocking-human" continues to win over everything, unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(#4095): anchor auto_select/id attribute regexes past hyphenated decoys An isolated adversarial review of the auto_select work found that both new attribute regexes used \b as their left anchor, which is a word boundary, not a "start of attribute name" boundary. A decoy attribute ending in the same word (e.g. data-id="...") sitting before the real id="..." on the same <option> tag matched first, silently corrupting the extracted option id. Anchor on (?:^|\s) instead so only the real attribute name can match. Adds a regression test reproducing the exact decoy-attribute shape, plus a Unicode option-id test from the same review pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test(#4095): register auto-select-attribute.test.cjs in the docs-guard lane lint-docs-guard-registration failed: the new test reads docs/reference/ plan-md.md but was not registered, so a future edit to that doc could silently desync from the test without the guard catching it on the PR that changed the doc. Registered alongside its direct precedents (precondition-element.test.cjs, reversibility-tagging.test.cjs), which read the same file for the same reason. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(#4095): fit the decision bullet under execute-phase.md's frozen byte ceiling The remote gsd-test run caught what local checks missed: execute-phase.md carries a frozen ADR-857 Phase-6 byte ceiling (93600) with only 36 bytes of headroom before this change, and the original checkpoint:decision wording pushed it to 93772 (over the ceiling). Cascaded into failures in phase6-capstone-conformance, execute-phase-completion-reconciliation, claude-orchestration, and the compact-content drift-report test. Also caught: tests/package-legitimacy-gate.test.cjs anchors a "decision is conditional, not unconditional" safety check on the literal phrase "first option" in the decision bullet — which #4095 deliberately removes, since there is no more unconditional first-option pick. The test was asserting an assumption this change intentionally makes obsolete; re-anchored on tokens that still identify the bullet ('decision', 'auto-spawn') without weakening what the test actually verifies (the bullet must still carry a blocking-human carve-out). Also fixed a word-order mismatch between my own new test's regex and the actual doc text it was asserting against (tests/auto-select-attribute.test.cjs). Regenerated the compact-content benchmark baseline (tests/fixtures/compact-content-benchmark-baseline.json) to match the new byte counts. Emitted-Drift-Ack-Growth: gsd-executor.md — +7 bytes (49138 -> 49145), from the auto_select carve-out added to the checkpoint:decision auto-mode bullet; already trimmed once to fit the 49152 hard cap. Emitted-Drift-Ack-Growth: execute-phase.md — +12 bytes (93564 -> 93576), from the same carve-out in the orchestrator's decision bullet; kept 24 bytes under the frozen 93600 ADR-857 ceiling after two rounds of trimming for clarity vs. margin. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * chore(#4095): backfill changeset PR number Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: sim <sim@local> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
440 lines
21 KiB
JavaScript
440 lines
21 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
/**
|
|
* docs-guard-registry.cjs — the sole source of truth for which doc-reading
|
|
* test files the docs-guard lane must run.
|
|
*
|
|
* ## Why this is its own module, not a `scripts/ci-test-scope.cjs` RULE
|
|
*
|
|
* A prior version of this PR added a `docs guards` RULE to `RULES` in
|
|
* scripts/ci-test-scope.cjs, on the theory that classify()'s `!codeChanged`
|
|
* normalization (which at the time zeroed fullMatrix/targeted_tests/
|
|
* windows_tests for docs-only diffs) made the RULE inert to classify()'s
|
|
* scope decision. (#4641 later removed `windows_tests` from classify()'s
|
|
* output entirely; the normalization today only zeroes fullMatrix and
|
|
* targeted_tests. This paragraph is historical narration of a rejected
|
|
* design, not a description of current behaviour.)
|
|
*
|
|
* That is true for docs-ONLY diffs and FALSE for MIXED docs+code diffs:
|
|
* `codeChanged` is true whenever ANY changed file is product/pipeline code,
|
|
* so the normalization never runs, and every one of this registry's test
|
|
* files joined `targeted_tests` for every mixed PR. Probed on that version:
|
|
* `node scripts/ci-test-scope.cjs --files "docs/a.md src/semver.cts"`
|
|
* returned 25 targeted_tests, vs. 3 on `origin/next` — an unstated blowup
|
|
* of the scoped/targeted lane on every mixed docs+code PR.
|
|
*
|
|
* Root cause: `RULES` answers "given these changed files, what should
|
|
* test.yml run" for the MAIN scoped-lane pipeline. The docs-guard registry
|
|
* is a LANE MANIFEST for a completely different consumer (the `docs-lint`
|
|
* job in .github/workflows/docs-required.yml, gated on a `docs_changed`
|
|
* step output). Putting a lane manifest inside a scope-classification rule
|
|
* set was the defect; extracting it here removes any path by which it can
|
|
* influence classify() at all.
|
|
*
|
|
* ## Who reads this
|
|
*
|
|
* - .github/workflows/docs-required.yml (`docs-lint` job) — derives the
|
|
* PER-PR-SELECTED subset of this registry from scripts/select-docs-guards.cjs,
|
|
* which is itself driven by this module's DOCS_GUARD_TESTS map. This job has
|
|
* no `paths:` filter, so it always reports a status and can supply the
|
|
* already-required `docs-lint` context; a dedicated `paths:`-filtered
|
|
* workflow cannot be made required without hanging non-docs PRs forever.
|
|
* - scripts/lint-docs-guard-registration.cjs — derives its registration
|
|
* lint's comparison set from this module (so a docs-reading test file
|
|
* that is neither registered here nor exempted fails the lint).
|
|
* - scripts/select-docs-guards.cjs — the pure selector that maps a PR's
|
|
* changed docs/ paths to the subset of this registry that actually needs
|
|
* to run (#3753 follow-up: a flat "run everything" list is disproportionate
|
|
* for a single-file docs typo fix).
|
|
*
|
|
* ## Registry shape (#3753 follow-up)
|
|
*
|
|
* `DOCS_GUARD_TESTS` is a MAP from test file path to the array of docs/
|
|
* paths it actually reads, so a changed-docs-file can be resolved to the
|
|
* narrow subset of guards that read it, instead of always running the
|
|
* entire registry. Each value is a non-empty array of PATTERNS:
|
|
*
|
|
* - a plain path (e.g. `'docs/AGENTS.md'`) matches that exact file only;
|
|
* - a trailing-slash path (e.g. `'docs/adr/'`) matches any changed path
|
|
* under that directory prefix — use this for a test that walks or
|
|
* `readdirSync`s a whole docs/ subdirectory;
|
|
* - the sentinel `'*'` means "run on ANY docs/ change" — reserved for a
|
|
* test that cannot be resolved to a narrower set of paths (the path is
|
|
* computed, looped over an unresolvable variable, or the test walks
|
|
* docs/ generally). Conservative fallback: when in doubt, use `'*'`,
|
|
* never a guessed-narrow path — a false negative here (a guard that
|
|
* silently stops running) is exactly the #3753 defect class this
|
|
* registry exists to prevent.
|
|
*
|
|
* `DOCS_GUARD_TEST_FILES` (derived: `Object.keys(DOCS_GUARD_TESTS)`) is kept
|
|
* as a flat array export so the registration lint and its parity test
|
|
* continue to consume a plain file list without needing to know about the
|
|
* map shape.
|
|
*
|
|
* ## Adding a docs guard
|
|
*
|
|
* Add the test file's path (relative to the repo root, `tests/<file>`) as a
|
|
* key in DOCS_GUARD_TESTS below, with the docs/ paths it reads as the value
|
|
* (or `['*']` if that cannot be resolved narrowly). Do not duplicate this
|
|
* list anywhere else — a second, independently maintained list is exactly
|
|
* the #3753 defect class (10 registered-but-not-run guards, silently
|
|
* drifted) this registry exists to prevent from recurring.
|
|
*
|
|
* Sorted alphabetically by basename for unambiguous diffs.
|
|
*/
|
|
|
|
/**
|
|
* Duplicate of scripts/run-tests.cjs:50's `SUITES` array. That array is not
|
|
* exported by run-tests.cjs (module.exports there is deliberately narrow;
|
|
* run-tests.cjs's own behavior is intentional and out of scope for this
|
|
* registry to alter), so it cannot be imported directly without changing a
|
|
* shared, behavior-locked file.
|
|
*
|
|
* Why this must exist at all: `run-tests.cjs`'s `selectExplicitFiles`
|
|
* (scripts/run-tests.cjs:651) treats any registry entry that EQUALS a
|
|
* SUITES member (e.g. `all`, `unit`) as a suite selector, not a filename —
|
|
* so a typo in DOCS_GUARD_TESTS matching a suite name would silently run
|
|
* the ENTIRE suite inside the required `docs-lint` job instead of erroring.
|
|
* `assertNoSuiteCollision` below rejects that at the registry boundary
|
|
* instead.
|
|
*
|
|
* Divergence risk: if run-tests.cjs's real SUITES list ever changes and this
|
|
* copy is not updated, this check could under- or over-reject. That risk is
|
|
* covered by a parity test (tests/ci-docs-guard-registry.test.cjs) that
|
|
* drives run-tests.cjs's own exported `selectExplicitFiles` behaviorally —
|
|
* for every token here it asserts run-tests.cjs treats it as a suite
|
|
* selector (never "file not found"), and for a control non-member it
|
|
* asserts the opposite — so a real divergence fails that test rather than
|
|
* silently drifting.
|
|
*/
|
|
const RUN_TESTS_SUITES = ['all', 'unit', 'integration', 'install', 'security', 'slow', 'qa'];
|
|
|
|
/**
|
|
* Normalize a registry entry EXACTLY the way scripts/run-tests.cjs's
|
|
* `splitFileList` (:617-625) normalizes a requested token before its SUITES
|
|
* check (:651): strip a leading `tests/` and normalize `\`->`/`. Without this,
|
|
* comparing RAW registry keys (which all carry the `tests/` prefix by
|
|
* convention) against RUN_TESTS_SUITES misses the realistic typo `'tests/all'`
|
|
* entirely — proven by probe: `assertNoSuiteCollision(['tests/all'])` did not
|
|
* throw, and `selectExplicitFiles(allFiles, 'tests/all')` selected all 824
|
|
* files (the whole suite) inside the required docs-lint job.
|
|
*
|
|
* @param {string} t
|
|
* @returns {string}
|
|
*/
|
|
function normalizeForSuiteCheck(t) {
|
|
return t.replace(/\\/g, '/').replace(/^tests\//, '');
|
|
}
|
|
|
|
/**
|
|
* Reject any docs-guard registry entry that collides with a run-tests.cjs
|
|
* suite token (see RUN_TESTS_SUITES doc comment above). Throws with every
|
|
* offending entry named, rather than failing on only the first. Compares
|
|
* entries AFTER normalizeForSuiteCheck, mirroring run-tests.cjs's own
|
|
* splitFileList normalization, so a `tests/`-prefixed or backslash-spelled
|
|
* entry that would collide post-normalization is caught here too.
|
|
*
|
|
* @param {string[]} tests
|
|
*/
|
|
function assertNoSuiteCollision(tests) {
|
|
const collisions = tests.filter((t) => RUN_TESTS_SUITES.includes(normalizeForSuiteCheck(t)));
|
|
if (collisions.length > 0) {
|
|
throw new Error(
|
|
'docs-guard-registry: DOCS_GUARD_TESTS entry collides with a run-tests.cjs SUITES token ' +
|
|
`(${collisions.join(', ')}) — scripts/run-tests.cjs:651's selectExplicitFiles treats a ` +
|
|
'registry entry that equals a suite name as a suite selector, not a filename, so this ' +
|
|
'would silently run the entire suite instead of the intended file(s). Fix the registry entry.',
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Map from docs-guard test file to the docs/ path patterns it reads. See
|
|
* this module's header comment for pattern semantics (exact / trailing-slash
|
|
* dir-prefix / `'*'` sentinel). Every value here was derived by reading the
|
|
* test file's actual read call(s) — not guessed — per #3753's own lesson: an
|
|
* unresolvable read is recorded as `'*'`, never a narrowed guess.
|
|
*/
|
|
const DOCS_GUARD_TESTS = {
|
|
'tests/adr-15-progress-converge.test.cjs': [
|
|
'docs/COMMANDS.md',
|
|
'docs/how-to/run-phases-autonomously.md',
|
|
],
|
|
// Walks docs/adr/ as a directory (builds/reads docs/adr/README.md and
|
|
// fixture ADRs throughout) and separately reads docs/contributor-standards.md.
|
|
'tests/adr-index-gate.test.cjs': ['docs/adr/', 'docs/contributor-standards.md'],
|
|
|
|
// Walks docs/features/ as a directory (the fragment corpus) and asserts the
|
|
// committed docs/FEATURES.md equals the generated projection of it (#3840).
|
|
'tests/features-index-gate.test.cjs': ['docs/features/', 'docs/FEATURES.md'],
|
|
'tests/agent-classification-parity.test.cjs': ['docs/AGENTS.md', 'docs/INVENTORY.md'],
|
|
// #3683: pins the learnings feature section's agreement with the canonical
|
|
// artifact registry (reads docs/FEATURES.md around the extract-learnings
|
|
// entry).
|
|
'tests/learnings.test.cjs': ['docs/FEATURES.md'],
|
|
'tests/analyze-dependencies.test.cjs': ['docs/COMMANDS.md'],
|
|
'tests/auto-select-attribute.test.cjs': ['docs/reference/plan-md.md'],
|
|
'tests/autonomous-converge.test.cjs': [
|
|
'docs/COMMANDS.md',
|
|
'docs/how-to/run-phases-autonomously.md',
|
|
],
|
|
'tests/capability-matrix-sync.test.cjs': ['docs/reference/capability-matrix.md'],
|
|
'tests/capability-registry.test.cjs': [
|
|
'docs/tutorials/build-your-first-capability.md',
|
|
'docs/tutorials/install-your-first-capability.md',
|
|
'docs/reference/capability-manifest.md',
|
|
],
|
|
'tests/claude-md.test.cjs': ['docs/COMMANDS.md'],
|
|
'tests/claude-orchestration.test.cjs': ['docs/explanation/claude-orchestration-capability.md'],
|
|
'tests/command-contract.test.cjs': [
|
|
'docs/INVENTORY.md',
|
|
'docs/ja-JP/INVENTORY.md',
|
|
'docs/ko-KR/INVENTORY.md',
|
|
'docs/zh-CN/INVENTORY.md',
|
|
'docs/pt-BR/INVENTORY.md',
|
|
],
|
|
// uncoveredFiles(...) scans 'docs' as a generic coverage-scan root
|
|
// (commit-files-pathspec.test.cjs:1618) — cannot be resolved to specific
|
|
// files without re-deriving the scan's own file-discovery logic.
|
|
'tests/commit-files-pathspec.test.cjs': ['*'],
|
|
'tests/compact-content-4139.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/config-field-docs.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/config.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/context-index-sync.test.cjs': ['docs/CONTEXT-INDEX.json'],
|
|
'tests/context-predicates-query.test.cjs': ['docs/contributor-standards.md'],
|
|
// SCAN_DIRS includes 'docs' and recursively walks every .md file under it
|
|
// (context7-tool-name-parity.test.cjs:31-38) — a generic tree walk, not a
|
|
// fixed file set.
|
|
'tests/context7-tool-name-parity.test.cjs': ['*'],
|
|
'tests/contributor-standards.test.cjs': ['docs/contributor-standards.md'],
|
|
'tests/cursor-reviewer.test.cjs': [
|
|
'docs/COMMANDS.md',
|
|
'docs/FEATURES.md',
|
|
'docs/ja-JP/COMMANDS.md',
|
|
'docs/ja-JP/FEATURES.md',
|
|
'docs/ko-KR/COMMANDS.md',
|
|
'docs/ko-KR/FEATURES.md',
|
|
],
|
|
'tests/discuss-all-flag.test.cjs': ['docs/COMMANDS.md'],
|
|
'tests/discuss-mode.test.cjs': ['docs/workflow-discuss-mode.md'],
|
|
// Walks docs/*.md and every docs/<locale>/*.md dir dynamically
|
|
// (docs-parity-live-registry.test.cjs:42, 428) — deliberately generic.
|
|
'tests/docs-parity-live-registry.test.cjs': ['*'],
|
|
// #3839: pins every hook-table Event cell in the five locales' ARCHITECTURE
|
|
// and INVENTORY files against src/runtime-hooks-surface.cts registrations.
|
|
'tests/docs-hooks-table-parity.test.cjs': [
|
|
'docs/ARCHITECTURE.md',
|
|
'docs/INVENTORY.md',
|
|
'docs/ja-JP/ARCHITECTURE.md',
|
|
'docs/ja-JP/INVENTORY.md',
|
|
'docs/zh-CN/ARCHITECTURE.md',
|
|
'docs/zh-CN/INVENTORY.md',
|
|
'docs/ko-KR/ARCHITECTURE.md',
|
|
'docs/ko-KR/INVENTORY.md',
|
|
'docs/pt-BR/ARCHITECTURE.md',
|
|
'docs/pt-BR/INVENTORY.md',
|
|
],
|
|
'tests/docs-state-md-locale-parity.test.cjs': [
|
|
'docs/reference/state-md.md',
|
|
'docs/ja-JP/reference/state-md.md',
|
|
'docs/zh-CN/reference/state-md.md',
|
|
'docs/ko-KR/reference/state-md.md',
|
|
'docs/pt-BR/reference/state-md.md',
|
|
],
|
|
'tests/drift-detection.test.cjs': ['docs/CONFIGURATION.md', 'docs/AGENTS.md'],
|
|
'tests/edge-probe-docs-fixtures.test.cjs': ['docs/adr/550-spec-phase-probe-contract.md'],
|
|
'tests/edit-phase.test.cjs': [
|
|
'docs/INVENTORY.md',
|
|
'docs/INVENTORY-MANIFEST.json',
|
|
'docs/COMMANDS.md',
|
|
],
|
|
'tests/effort-surface-axis.test.cjs': ['docs/reference/host-integration-capability-matrix.md'],
|
|
'tests/execute-phase-active-flags.test.cjs': [
|
|
'docs/reference/host-integration-capability-matrix.md',
|
|
],
|
|
'tests/execute-phase-wave.test.cjs': ['docs/COMMANDS.md'],
|
|
// #3913 (ADR-3889 terminal phase): reads the generated docs/reference/exit-codes.md
|
|
// (content invariants, F1/F3) and docs/README.md (F4, the index link).
|
|
'tests/exit-code-registry.test.cjs': ['docs/reference/exit-codes.md', 'docs/README.md'],
|
|
'tests/external-job-waiting.test.cjs': ['docs/reference/planning-artifacts.md'],
|
|
// Rows 8/9 (negative controls) read real docs/registries/eos.json and
|
|
// docs/adr/0001-dispatch-policy-module.md and assert on their EXACT
|
|
// committed content (an entry's name field, ADR-0001's H1 title) as a
|
|
// sanity check before mutating an overlay fixture — a content edit to
|
|
// either file changes the string this test asserts on.
|
|
'tests/fragment-single-edit-propagation.install.test.cjs': [
|
|
'docs/registries/eos.json',
|
|
'docs/adr/0001-dispatch-policy-module.md',
|
|
],
|
|
// Seeds a temp fixture copy of these five files (never mutates the real
|
|
// tree) to exercise scripts/gen-state-md-docs.cjs's marked-region splicing
|
|
// against them — #3873 (ADR-3473 §8.8), rows 10-22/27. Read for fixture
|
|
// seeding, so a content edit to any of them (e.g. renaming a landmark
|
|
// heading/string a hostile-input test targets) can change this test's
|
|
// fixture assumptions.
|
|
// #4728: pins the retirement of Gemini CLI prose from every localized
|
|
// how-to/ARCHITECTURE/USER-GUIDE/CONFIGURATION/context-monitor mirror, plus
|
|
// the PRESERVE (Antigravity) and MODEL-AXIS (Gemini 2.5 Pro) negative-space
|
|
// checks in the same locales.
|
|
'tests/gemini-runtime-removed.test.cjs': [
|
|
'docs/ja-JP/how-to/install-on-your-runtime.md',
|
|
'docs/ko-KR/how-to/install-on-your-runtime.md',
|
|
'docs/pt-BR/how-to/install-on-your-runtime.md',
|
|
'docs/zh-CN/how-to/install-on-your-runtime.md',
|
|
'docs/ja-JP/ARCHITECTURE.md',
|
|
'docs/ko-KR/ARCHITECTURE.md',
|
|
'docs/pt-BR/ARCHITECTURE.md',
|
|
'docs/zh-CN/ARCHITECTURE.md',
|
|
'docs/ja-JP/USER-GUIDE.md',
|
|
'docs/ko-KR/USER-GUIDE.md',
|
|
'docs/pt-BR/USER-GUIDE.md',
|
|
'docs/zh-CN/USER-GUIDE.md',
|
|
'docs/ja-JP/CONFIGURATION.md',
|
|
'docs/ko-KR/CONFIGURATION.md',
|
|
'docs/pt-BR/CONFIGURATION.md',
|
|
'docs/zh-CN/CONFIGURATION.md',
|
|
'docs/ja-JP/context-monitor.md',
|
|
'docs/ko-KR/context-monitor.md',
|
|
'docs/pt-BR/context-monitor.md',
|
|
'docs/zh-CN/context-monitor.md',
|
|
],
|
|
'tests/gen-state-md-docs.test.cjs': [
|
|
'docs/reference/state-md.md',
|
|
'docs/ja-JP/reference/state-md.md',
|
|
'docs/zh-CN/reference/state-md.md',
|
|
'docs/ko-KR/reference/state-md.md',
|
|
'docs/pt-BR/reference/state-md.md',
|
|
],
|
|
'tests/gsd-write-guard.test.cjs': ['docs/USER-GUIDE.md'],
|
|
'tests/host-integration-descriptors.test.cjs': [
|
|
'docs/reference/host-integration-capability-matrix.md',
|
|
],
|
|
'tests/install.test.cjs': ['docs/AGENTS.md', 'docs/INVENTORY.md', 'docs/INVENTORY-MANIFEST.json'],
|
|
// SOURCE_DIRS includes 'docs' and walks it recursively for every .md file
|
|
// (intel.test.cjs:1223-1228) — a generic tree walk.
|
|
'tests/intel.test.cjs': ['*'],
|
|
'tests/inventory-headings-countfree.test.cjs': ['docs/INVENTORY.md'],
|
|
'tests/inventory-manifest-sync.test.cjs': ['docs/INVENTORY.md', 'docs/INVENTORY-MANIFEST.json'],
|
|
'tests/kilo-upgrades.test.cjs': ['docs/how-to/connect-gsd-mcp-server.md'],
|
|
'tests/live-config-guard.test.cjs': ['docs/TESTING-SUITES.md'],
|
|
// #3726: pins the `milestone complete` synopsis (English + four localized
|
|
// mirrors), the `--confirm` flag row and the guard-override instructions —
|
|
// `type: Fixed` exempts that PR from the docs-required lint, so this is the
|
|
// only gate on that prose.
|
|
'tests/milestone.test.cjs': [
|
|
'docs/CLI-TOOLS.md',
|
|
'docs/COMMANDS.md',
|
|
'docs/ja-JP/CLI-TOOLS.md',
|
|
'docs/ko-KR/CLI-TOOLS.md',
|
|
'docs/pt-BR/CLI-TOOLS.md',
|
|
'docs/zh-CN/CLI-TOOLS.md',
|
|
],
|
|
'tests/model-catalog-runtime-defaults.test.cjs': ['docs/CONFIGURATION.md'],
|
|
// Scans every git-tracked file in the whole repo via `git ls-files`
|
|
// (no-pending-3212-markers.test.cjs:37-46), which includes all of docs/ —
|
|
// cannot be resolved to a fixed docs/ path set.
|
|
'tests/no-pending-3212-markers.test.cjs': ['*'],
|
|
'tests/phase6-capability-docs.test.cjs': ['docs/how-to/develop-a-capability.md', 'docs/README.md'],
|
|
'tests/phase6-review-capabilities.test.cjs': [
|
|
'docs/reference/review-verification-capabilities.md',
|
|
'docs/how-to/develop-a-capability.md',
|
|
'docs/README.md',
|
|
],
|
|
'tests/plan-checker-coupling.test.cjs': ['docs/AGENTS.md'],
|
|
'tests/plan-phase-drift-guard.test.cjs': [
|
|
'docs/CONFIGURATION.md',
|
|
'docs/COMMANDS.md',
|
|
'docs/USER-GUIDE.md',
|
|
'docs/ARCHITECTURE.md',
|
|
'docs/INVENTORY.md',
|
|
'docs/INVENTORY-MANIFEST.json',
|
|
],
|
|
'tests/plan-phase-stall-detection.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/plan-review-convergence.test.cjs': [
|
|
'docs/CONFIGURATION.md',
|
|
'docs/USER-GUIDE.md',
|
|
'docs/ARCHITECTURE.md',
|
|
],
|
|
'tests/planner-estimate-emission.test.cjs': ['docs/reference/plan-md.md', 'docs/CONFIGURATION.md'],
|
|
'tests/precondition-element.test.cjs': ['docs/reference/plan-md.md'],
|
|
'tests/product-name-purity.test.cjs': [
|
|
'docs/README.md',
|
|
'docs/zh-CN/README.md',
|
|
'docs/ko-KR/README.md',
|
|
'docs/ja-JP/README.md',
|
|
'docs/pt-BR/README.md',
|
|
],
|
|
'tests/progress-forensic.test.cjs': ['docs/COMMANDS.md'],
|
|
'tests/repo-layout.test.cjs': ['docs/contributing/bootstrap.md'],
|
|
// Reads REQ-LANG-04 and runs every form it offers an author through the
|
|
// matcher that enforces it, so a reword of the requirement alone is exactly
|
|
// the change this guard must run on (#2529). Both paths are named because
|
|
// #3840 made docs/FEATURES.md a generated projection: the requirement's
|
|
// source is the fragment, and an edit there that is not regenerated would
|
|
// otherwise reach this guard through neither path.
|
|
'tests/response-language-coverage.test.cjs': [
|
|
'docs/FEATURES.md',
|
|
'docs/features/response-language-config.md',
|
|
],
|
|
'tests/reversibility-tagging.test.cjs': ['docs/reference/plan-md.md'],
|
|
'tests/reviewer-docs-parity.test.cjs': [
|
|
'docs/COMMANDS.md',
|
|
'docs/ja-JP/COMMANDS.md',
|
|
'docs/ko-KR/COMMANDS.md',
|
|
'docs/pt-BR/COMMANDS.md',
|
|
'docs/zh-CN/COMMANDS.md',
|
|
'docs/FEATURES.md',
|
|
'docs/ja-JP/FEATURES.md',
|
|
'docs/ko-KR/FEATURES.md',
|
|
'docs/pt-BR/FEATURES.md',
|
|
'docs/zh-CN/FEATURES.md',
|
|
],
|
|
'tests/runtime-converters.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/secure-phase.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/security-dead-exports.regression.test.cjs': ['docs/FEATURES.md'],
|
|
'tests/security.test.cjs': ['docs/INVENTORY-MANIFEST.json'],
|
|
// Walks docs/ recursively (todos-done-rename-guard.test.cjs:19-22
|
|
// SCAN_DIRS) looking for stale references — a generic tree walk.
|
|
'tests/todos-done-rename-guard.test.cjs': ['*'],
|
|
'tests/tracer-bullet.test.cjs': [
|
|
'docs/COMMANDS.md',
|
|
'docs/reference/plan-md.md',
|
|
'docs/how-to/plan-a-phase.md',
|
|
'docs/AGENTS.md',
|
|
],
|
|
'tests/ui-interaction-capture.test.cjs': ['docs/CONFIGURATION.md'],
|
|
'tests/ui-spec-inventory-provenance.test.cjs': [
|
|
'docs/FEATURES.md',
|
|
'docs/how-to/design-a-ui-phase.md',
|
|
'docs/ja-JP/FEATURES.md',
|
|
'docs/ja-JP/how-to/design-a-ui-phase.md',
|
|
'docs/zh-CN/FEATURES.md',
|
|
'docs/zh-CN/how-to/design-a-ui-phase.md',
|
|
'docs/ko-KR/FEATURES.md',
|
|
'docs/ko-KR/how-to/design-a-ui-phase.md',
|
|
'docs/pt-BR/how-to/design-a-ui-phase.md',
|
|
],
|
|
'tests/verifier-behavior-unverified.test.cjs': ['docs/reference/planning-artifacts.md'],
|
|
'tests/verifier-coincidental-reliance.test.cjs': ['docs/AGENTS.md'],
|
|
'tests/verify.test.cjs': ['docs/reference/plan-md.md'],
|
|
'tests/workflow-fragments.test.cjs': ['docs/reference/workflow-fragments.md'],
|
|
};
|
|
|
|
/**
|
|
* Flat file-list view of DOCS_GUARD_TESTS, kept for consumers (the
|
|
* registration lint and its parity test) that only need "which test files
|
|
* are registered", not their per-file docs path patterns.
|
|
*/
|
|
const DOCS_GUARD_TEST_FILES = Object.keys(DOCS_GUARD_TESTS);
|
|
|
|
assertNoSuiteCollision(DOCS_GUARD_TEST_FILES);
|
|
|
|
module.exports = {
|
|
DOCS_GUARD_TESTS,
|
|
DOCS_GUARD_TEST_FILES,
|
|
RUN_TESTS_SUITES,
|
|
assertNoSuiteCollision,
|
|
normalizeForSuiteCheck,
|
|
};
|