Merge branch 'next' into fix/3174-quick-verification-status-query
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"paths": {
|
||||
"next.md": "#3184 (epic #3180 Phase 2): Route 0 (resume_incomplete_phase) grows by one branch that reads the new `scope` field `roadmap analyze` emits. Before this, Route 0 treated a well-formed `{phases: []}` as a clean scan and fell through to routing as though the incomplete-phase invariant (#160) had been checked and passed — the silent disarm #3165 reports, where a milestone window truncated by a closed-milestone heading yields an empty phase list with exit 0 and no error. The added `elif [ \"$ROADMAP_SCOPE\" != \"complete\" ]` arm routes that case into the SAME warn-and-fall-through branch the existing `roadmap.analyze failed` arm already uses, so a non-answer is no longer indistinguishable from a genuinely empty scan. The growth is the new arm's three warning lines, its explanatory comment, the `ROADMAP_SCOPE` assignment, and one success-criteria bullet. Adding this to the workflow rather than only to the CLI is deliberate: a spec review of this phase found that emitting `scope` without a consumer left #3165's actual symptom reproducing, so the field would have been a diagnostic nobody reads."
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,17 @@ describe('#2658: end-to-end --trae install never emits the malformed path (accep
|
||||
test('local install: no emitted .md/.js/.cjs file contains the malformed strings; the rules file is concrete', () => {
|
||||
const { configDir, root } = runMinimalInstall({ runtime: 'trae', scope: 'local' });
|
||||
try {
|
||||
const files = walk(configDir).filter((f) => /\.(md|js|cjs)$/.test(f));
|
||||
const files = walk(configDir)
|
||||
.filter((f) => /\.(md|js|cjs)$/.test(f))
|
||||
// gsd-core/CHANGELOG.md is excluded by exact relative path (not a blanket
|
||||
// .md skip — the emitted agent/command/workflow markdown this gate exists
|
||||
// to guard stays fully scanned). CHANGELOG.md legitimately QUOTES the
|
||||
// malformed `.claude/.trae/rules` / `.trae/.trae/rules` strings while
|
||||
// documenting the #2658 fix itself (#3006) — that historical-value
|
||||
// citation is not a regression of the installer's actual output. Verified
|
||||
// empirically: excluding only this one file drops the hit count to zero
|
||||
// across all 620 other emitted files.
|
||||
.filter((f) => f.split(path.sep).join('/').indexOf('gsd-core/CHANGELOG.md') === -1);
|
||||
assert.ok(files.length > 0, 'expected at least one emitted .md/.js/.cjs file');
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(file, 'utf8');
|
||||
|
||||
1
tests/fixtures/install-tree/antigravity.json
vendored
1
tests/fixtures/install-tree/antigravity.json
vendored
@@ -415,6 +415,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/augment.json
vendored
1
tests/fixtures/install-tree/augment.json
vendored
@@ -485,6 +485,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-ns-context/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/docs-update/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md",
|
||||
|
||||
@@ -483,5 +483,6 @@
|
||||
"scripts/gen-capability-registry.cjs",
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs"
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs"
|
||||
]
|
||||
|
||||
1
tests/fixtures/install-tree/claude.json
vendored
1
tests/fixtures/install-tree/claude.json
vendored
@@ -413,6 +413,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/cline.json
vendored
1
tests/fixtures/install-tree/cline.json
vendored
@@ -385,6 +385,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-ns-context/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/docs-update/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/codebuddy.json
vendored
1
tests/fixtures/install-tree/codebuddy.json
vendored
@@ -485,6 +485,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
3
tests/fixtures/install-tree/codex.json
vendored
3
tests/fixtures/install-tree/codex.json
vendored
@@ -492,5 +492,6 @@
|
||||
"scripts/gen-capability-registry.cjs",
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs"
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs"
|
||||
]
|
||||
|
||||
1
tests/fixtures/install-tree/copilot.json
vendored
1
tests/fixtures/install-tree/copilot.json
vendored
@@ -384,6 +384,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/cursor.json
vendored
1
tests/fixtures/install-tree/cursor.json
vendored
@@ -391,6 +391,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/hermes.json
vendored
1
tests/fixtures/install-tree/hermes.json
vendored
@@ -414,6 +414,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd/DESCRIPTION.md",
|
||||
"skills/gsd/gsd-ns-context/SKILL.md",
|
||||
"skills/gsd/gsd-ns-context/skills/docs-update/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/kilo.json
vendored
1
tests/fixtures/install-tree/kilo.json
vendored
@@ -488,6 +488,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/kimi-code.json
vendored
1
tests/fixtures/install-tree/kimi-code.json
vendored
@@ -414,6 +414,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/kimi.json
vendored
1
tests/fixtures/install-tree/kimi.json
vendored
@@ -450,6 +450,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/opencode.json
vendored
1
tests/fixtures/install-tree/opencode.json
vendored
@@ -488,6 +488,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-add-tests/SKILL.md",
|
||||
"skills/gsd-ai-integration-phase/SKILL.md",
|
||||
"skills/gsd-audit-fix/SKILL.md",
|
||||
|
||||
3
tests/fixtures/install-tree/pi.json
vendored
3
tests/fixtures/install-tree/pi.json
vendored
@@ -381,5 +381,6 @@
|
||||
"scripts/gen-capability-registry.cjs",
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs"
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs"
|
||||
]
|
||||
|
||||
1
tests/fixtures/install-tree/qwen.json
vendored
1
tests/fixtures/install-tree/qwen.json
vendored
@@ -414,6 +414,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-ns-context/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/docs-update/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md",
|
||||
|
||||
1
tests/fixtures/install-tree/trae.json
vendored
1
tests/fixtures/install-tree/trae.json
vendored
@@ -382,6 +382,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-ns-context/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/docs-update/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md",
|
||||
|
||||
3
tests/fixtures/install-tree/windsurf.json
vendored
3
tests/fixtures/install-tree/windsurf.json
vendored
@@ -384,5 +384,6 @@
|
||||
"scripts/gen-capability-registry.cjs",
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs"
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs"
|
||||
]
|
||||
|
||||
1
tests/fixtures/install-tree/zcode.json
vendored
1
tests/fixtures/install-tree/zcode.json
vendored
@@ -453,6 +453,7 @@
|
||||
"scripts/gen-loop-host-contract.cjs",
|
||||
"scripts/lib/allowlist-ratchet.cjs",
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"skills/gsd-ns-context/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/docs-update/SKILL.md",
|
||||
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md",
|
||||
|
||||
@@ -49,6 +49,8 @@ const {
|
||||
configureKiloPermissions,
|
||||
selectRuntimesFromArgs,
|
||||
normalizeNodePath,
|
||||
GSD_CHANGESET_FILES,
|
||||
GSD_SCRIPTS_LIB_FILES,
|
||||
} = require('../bin/install.js');
|
||||
|
||||
const { getGlobalConfigDir } = require('../gsd-core/bin/lib/runtime-homes.cjs');
|
||||
@@ -11107,3 +11109,48 @@ describe('#3026: installer --help documents every accepted runtime flag', () =>
|
||||
`--help must document every accepted runtime flag; missing: ${missing.join(', ')}`);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── #3184: scripts/lib/ and scripts/changeset/ install/uninstall parity ────
|
||||
//
|
||||
// install() copies both source directories WHOLESALE (every file present —
|
||||
// see bin/install.js's "and any future lib helpers" comment), but uninstall()
|
||||
// removes files via an EXPLICIT hardcoded enumeration (GSD_SCRIPTS_LIB_FILES /
|
||||
// GSD_CHANGESET_FILES). Nothing keeps the two in sync: a file added to either
|
||||
// source directory ships to every install and then orphans on uninstall (it
|
||||
// survives removal, keeps the target dir non-empty, and blocks its rmdir).
|
||||
// This guard fails the moment the real directory outgrows the enumeration.
|
||||
|
||||
/**
|
||||
* Pure comparison: every file actually present in a source dir must be named
|
||||
* in the corresponding uninstall enumeration. Decoupled from fs so it can be
|
||||
* exercised directly with doctored input (see the probe in the PR report).
|
||||
*/
|
||||
function findUnenumeratedFiles(actualFiles, enumeratedFiles) {
|
||||
const enumerated = new Set(enumeratedFiles);
|
||||
return actualFiles.filter(f => !enumerated.has(f));
|
||||
}
|
||||
|
||||
describe('#3184: scripts/lib/ and scripts/changeset/ install/uninstall parity', () => {
|
||||
const REPO_ROOT = path.join(__dirname, '..');
|
||||
|
||||
function realFilesIn(relativeDir) {
|
||||
const dir = path.join(REPO_ROOT, relativeDir);
|
||||
return fs.readdirSync(dir).filter(entry => fs.statSync(path.join(dir, entry)).isFile());
|
||||
}
|
||||
|
||||
test('every file in scripts/lib/ is enumerated in GSD_SCRIPTS_LIB_FILES (bin/install.js)', () => {
|
||||
const unenumerated = findUnenumeratedFiles(realFilesIn(path.join('scripts', 'lib')), GSD_SCRIPTS_LIB_FILES);
|
||||
assert.deepEqual(unenumerated, [],
|
||||
`scripts/lib/${unenumerated.join(', scripts/lib/')} exist on disk but are missing from ` +
|
||||
`GSD_SCRIPTS_LIB_FILES in bin/install.js — add ${unenumerated.length === 1 ? 'it' : 'them'} to that ` +
|
||||
'array so uninstall() removes it (otherwise it ships to every install and orphans on uninstall).');
|
||||
});
|
||||
|
||||
test('every file in scripts/changeset/ is enumerated in GSD_CHANGESET_FILES (bin/install.js)', () => {
|
||||
const unenumerated = findUnenumeratedFiles(realFilesIn(path.join('scripts', 'changeset')), GSD_CHANGESET_FILES);
|
||||
assert.deepEqual(unenumerated, [],
|
||||
`scripts/changeset/${unenumerated.join(', scripts/changeset/')} exist on disk but are missing from ` +
|
||||
`GSD_CHANGESET_FILES in bin/install.js — add ${unenumerated.length === 1 ? 'it' : 'them'} to that ` +
|
||||
'array so uninstall() removes it (otherwise it ships to every install and orphans on uninstall).');
|
||||
});
|
||||
});
|
||||
|
||||
1285
tests/milestone-window-single-owner.test.cjs
Normal file
1285
tests/milestone-window-single-owner.test.cjs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user