* test(#3606): pin hook-kind coverage in the wired guard * fix(#3606): validate hook-kind coverage at call sites and dispatch generically * fix(#3606): address review - segment-granular narrowing, zero-coverage diagnosis, quick.md, fragment extraction * fix(#3606): drop stale shrink-ack, export HOOK_GROUP_KINDS, dedupe scanner regex * chore(#3606): regenerate install-tree fixtures for new wave-post fragment * chore(#3606): sync canonical launcher preamble into new fragment * fix(#3606): keep fragment preamble ahead of first gsd_run mention * fix(#3606): revert sync script's preamble move in explore.md * chore(#3606): regenerate derived manifests post-rebase * chore(#3606): allowlist peer test files - base was red on the count lane * chore(#3606): regenerate inventory for peer's verify-command-grounding doc * chore(#3606): grounding test maps to its own module by longest prefix * chore(#3606): backfill changeset pr number --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -4893,7 +4893,12 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
|
||||
// ─── Defect 2 — gen-time wired guard ────────────────────────────────────────
|
||||
|
||||
describe('Defect 2: validateHooksWired gen-time guard', () => {
|
||||
// Shared #3606 fixtures: every hook kind, and a Map<point, Set<kind>> builder
|
||||
// for validateHooksWired's wiredKinds argument.
|
||||
const ALL = ['contribution', 'step', 'gate'];
|
||||
const kindsMap = (spec) => new Map(Object.entries(spec).map(([pt, ks]) => [pt, new Set(ks)]));
|
||||
|
||||
describe('Defect 2: validateHooksWired gen-time wired guard', () => {
|
||||
/** Minimal capability fixture with one hook at a given point */
|
||||
function makeCapWithStep(point) {
|
||||
return {
|
||||
@@ -4930,7 +4935,7 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
|
||||
test('returns non-empty error array mentioning "not wired" when step point is not in wiredSet', () => {
|
||||
const cap = makeCapWithStep('discuss:pre');
|
||||
const wiredSet = new Set(['plan:pre', 'plan:post']); // discuss:pre absent
|
||||
const wiredSet = kindsMap({ 'plan:pre': ALL, 'plan:post': ALL }); // discuss:pre absent
|
||||
const errs = validateHooksWired(cap, wiredSet);
|
||||
assert.ok(Array.isArray(errs), 'must return an array');
|
||||
assert.ok(errs.length > 0, 'must return errors when point is unwired');
|
||||
@@ -4942,7 +4947,7 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
|
||||
test('returns non-empty error array when contribution point is not in wiredSet', () => {
|
||||
const cap = makeCapWithContribution('discuss:pre');
|
||||
const wiredSet = new Set(['plan:pre']); // discuss:pre absent
|
||||
const wiredSet = kindsMap({ 'plan:pre': ALL }); // discuss:pre absent
|
||||
const errs = validateHooksWired(cap, wiredSet);
|
||||
assert.ok(errs.length > 0, 'must return errors for unwired contribution point');
|
||||
assert.match(errs.join(' '), /not wired/i);
|
||||
@@ -4950,7 +4955,7 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
|
||||
test('returns non-empty error array when gate point is not in wiredSet', () => {
|
||||
const cap = makeCapWithGate('discuss:pre');
|
||||
const wiredSet = new Set(['plan:pre']); // discuss:pre absent
|
||||
const wiredSet = kindsMap({ 'plan:pre': ALL }); // discuss:pre absent
|
||||
const errs = validateHooksWired(cap, wiredSet);
|
||||
assert.ok(errs.length > 0, 'must return errors for unwired gate point');
|
||||
assert.match(errs.join(' '), /not wired/i);
|
||||
@@ -4958,35 +4963,37 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
|
||||
test('returns empty array when all declared points are in wiredSet', () => {
|
||||
const cap = makeCapWithStep('plan:pre');
|
||||
const wiredSet = new Set(['plan:pre', 'plan:post', 'execute:post']);
|
||||
const wiredSet = kindsMap({ 'plan:pre': ALL, 'plan:post': ALL, 'execute:post': ALL });
|
||||
const errs = validateHooksWired(cap, wiredSet);
|
||||
assert.deepEqual(errs, [], 'must return empty array when all points are wired');
|
||||
assert.deepEqual(errs, [], 'must return empty array when all points are wired and kind-covered');
|
||||
});
|
||||
|
||||
test('boundary: cap declaring discuss:pre is rejected against wiredSet lacking it', () => {
|
||||
const cap = makeCapWithStep('discuss:pre');
|
||||
const smallSet = new Set(['plan:pre', 'plan:post']);
|
||||
const smallSet = kindsMap({ 'plan:pre': ALL, 'plan:post': ALL });
|
||||
const errs = validateHooksWired(cap, smallSet);
|
||||
assert.ok(errs.length > 0, 'must reject discuss:pre against a set that lacks it');
|
||||
});
|
||||
|
||||
test('boundary: cap declaring discuss:pre is accepted against real getWiredLoopPoints(ROOT) post-fix', () => {
|
||||
test('boundary: cap declaring discuss:pre is accepted against real getWiredKinds(ROOT) post-fix', () => {
|
||||
const cap = makeCapWithStep('discuss:pre');
|
||||
const realWired = getWiredLoopPoints(ROOT);
|
||||
const { getWiredKinds } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const realWired = getWiredKinds(ROOT);
|
||||
const errs = validateHooksWired(cap, realWired);
|
||||
assert.deepEqual(
|
||||
errs, [],
|
||||
`discuss:pre must be wired after the fix. Errors: ${errs.join('; ')}`,
|
||||
`discuss:pre must be wired and kind-covered after the fix. Errors: ${errs.join('; ')}`,
|
||||
);
|
||||
});
|
||||
|
||||
test('boundary: cap declaring discuss:post is accepted against real getWiredLoopPoints(ROOT) post-fix', () => {
|
||||
test('boundary: cap declaring discuss:post is accepted against real getWiredKinds(ROOT) post-fix', () => {
|
||||
const cap = makeCapWithContribution('discuss:post');
|
||||
const realWired = getWiredLoopPoints(ROOT);
|
||||
const { getWiredKinds } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const realWired = getWiredKinds(ROOT);
|
||||
const errs = validateHooksWired(cap, realWired);
|
||||
assert.deepEqual(
|
||||
errs, [],
|
||||
`discuss:post must be wired after the fix. Errors: ${errs.join('; ')}`,
|
||||
`discuss:post must be wired and kind-covered after the fix. Errors: ${errs.join('; ')}`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -4999,7 +5006,7 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const wiredSet = new Set(['plan:pre']); // the invalid point is not here either
|
||||
const wiredSet = kindsMap({ 'plan:pre': ALL }); // the invalid point is not here either
|
||||
const errs = validateHooksWired(cap, wiredSet);
|
||||
// Should NOT flag it — invalid points are the schema validator's job
|
||||
const notWiredErrors = errs.filter((e) => /not wired/i.test(e));
|
||||
@@ -5010,6 +5017,228 @@ describe('#1196 — discuss loop wiring + wired-point guard', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Defect 3: hook-kind coverage (#3606) ────────────────────────────────────
|
||||
//
|
||||
// A point having a call site proves hooks are RENDERED, not DISPATCHED. A
|
||||
// consumer that iterates only `kind == "gate"` (or narrows `kind == "step"`
|
||||
// to one ref.skill) silently drops every other registered kind — mempalace's
|
||||
// step hooks were wired, active, and never run for five days across
|
||||
// plan:post / execute:wave:post / verify:post / execute:post consumers.
|
||||
// The guard must validate, per registered kind, that the call site's
|
||||
// dispatch text covers that kind.
|
||||
|
||||
describe('Defect 3: validateHooksWired hook-kind coverage (#3606)', () => {
|
||||
|
||||
test('a step hook at a point whose site covers only gate fails with a kind-coverage error', () => {
|
||||
const cap = {
|
||||
id: 'test-cap',
|
||||
role: 'feature',
|
||||
steps: [{ point: 'plan:post', ref: { skill: 'my-skill' }, produces: [], consumes: [], onError: 'skip' }],
|
||||
contributions: [],
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const wired = kindsMap({ 'plan:post': ['gate'] }); // hand-rolled gate-only consumer
|
||||
const errs = validateHooksWired(cap, wired);
|
||||
assert.ok(errs.length > 0, 'a step registered at a gate-only point must fail validation');
|
||||
const joined = errs.join(' ');
|
||||
assert.match(joined, /plan:post/, 'error must name the point');
|
||||
assert.match(joined, /test-cap/, 'error must name the capability id');
|
||||
assert.match(joined, /step/, 'error must name the uncovered kind');
|
||||
assert.doesNotMatch(joined, /not wired/i, 'the point IS wired — this is the coverage error, not the wiring error');
|
||||
});
|
||||
|
||||
test('a contribution hook at a point whose site covers only gate fails', () => {
|
||||
const cap = {
|
||||
id: 'test-cap',
|
||||
role: 'feature',
|
||||
steps: [],
|
||||
contributions: [{ point: 'execute:wave:post', into: 'orchestrator', fragment: { inline: 'hi' }, produces: [], consumes: [] }],
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const wired = kindsMap({ 'execute:wave:post': ['gate'] });
|
||||
const errs = validateHooksWired(cap, wired);
|
||||
assert.ok(errs.length > 0, 'a contribution registered at a gate-only point must fail validation');
|
||||
assert.match(errs.join(' '), /contribution/);
|
||||
});
|
||||
|
||||
test('a point covered for exactly the registered kinds passes (boundary: no over-reach)', () => {
|
||||
const cap = {
|
||||
id: 'test-cap',
|
||||
role: 'feature',
|
||||
steps: [{ point: 'ship:post', ref: { skill: 'my-skill' }, produces: [], consumes: [], onError: 'skip' }],
|
||||
contributions: [],
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const wired = kindsMap({ 'ship:post': ['step'] }); // ship.md's real coverage
|
||||
assert.deepEqual(validateHooksWired(cap, wired), [], 'step at a step-covered point must pass');
|
||||
});
|
||||
|
||||
test('unwired-point errors are unchanged when the arg is a kinds Map', () => {
|
||||
const cap = {
|
||||
id: 'test-cap',
|
||||
role: 'feature',
|
||||
steps: [{ point: 'discuss:pre', ref: { skill: 'x' }, produces: [], consumes: [], onError: 'skip' }],
|
||||
contributions: [],
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const wired = kindsMap({ 'plan:pre': ALL }); // discuss:pre absent entirely
|
||||
const errs = validateHooksWired(cap, wired);
|
||||
assert.ok(errs.length > 0, 'unwired point still fails');
|
||||
assert.match(errs.join(' '), /not wired/i, 'the existing unwired error text is preserved');
|
||||
});
|
||||
|
||||
test('boundary: invalid points are not kind-flagged (schema validator owns them)', () => {
|
||||
const cap = {
|
||||
id: 'test-cap',
|
||||
role: 'feature',
|
||||
steps: [{ point: 'not:a:real:point', ref: { skill: 'x' }, produces: [], consumes: [], onError: 'skip' }],
|
||||
contributions: [],
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const errs = validateHooksWired(cap, kindsMap({}));
|
||||
assert.deepEqual(errs, [], 'invalid points produce neither wiring nor coverage errors');
|
||||
});
|
||||
|
||||
test('the real tree passes the extended guard for every in-tree registered kind', () => {
|
||||
// Self-enforcement: the repo's own capabilities and host workflows must
|
||||
// satisfy the new check — this is the test that forces consumer fixes.
|
||||
const { getWiredKinds } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const wiredKinds = getWiredKinds(ROOT);
|
||||
const failures = [];
|
||||
for (const capPath of fs.readdirSync(path.join(ROOT, 'capabilities'))) {
|
||||
const manifest = path.join(ROOT, 'capabilities', capPath, 'capability.json');
|
||||
if (!fs.existsSync(manifest)) continue;
|
||||
let cap;
|
||||
try { cap = JSON.parse(fs.readFileSync(manifest, 'utf8')); } catch { continue; }
|
||||
for (const err of validateHooksWired(cap, wiredKinds)) failures.push(`${capPath}: ${err}`);
|
||||
}
|
||||
assert.deepEqual(
|
||||
failures, [],
|
||||
`in-tree capabilities must be fully kind-covered by host workflows:\n ${failures.join('\n ')}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('coveredKindsInRegion: dispatch-text kind coverage (#3606)', () => {
|
||||
test('deferral line without a kind discriminator covers every kind', () => {
|
||||
const region = 'Apply each entry in `activeHooks` per @gsd-core/references/loop-hook-dispatch.md\n';
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
assert.deepEqual([...coveredKindsInRegion(region)].sort(), ['contribution', 'gate', 'step']);
|
||||
});
|
||||
|
||||
test('deferral line naming one kind covers only that kind', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = 'Dispatch `kind == "step"` hooks per @gsd-core/references/loop-hook-dispatch.md.\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(region)], ['step']);
|
||||
});
|
||||
|
||||
test('a bare §-citation of the reference covers nothing (validation guidance, not dispatch)', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = '⚠ **Validate `check` before shell use** — `loop-hook-dispatch.md` § `gate`.\n**For each active entry where `kind == "gate"`**\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(region)], ['gate'], 'gate dispatched unconditionally, step/contribution NOT');
|
||||
});
|
||||
|
||||
test('a narrowed kind line (kind == step AND ref.skill ==) does not cover the kind', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = 'Resolve hooks where `kind == "step"` and `ref.skill == "secure-phase"`.\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(region)], [], 'a one-skill special case proves nothing about the kind generally');
|
||||
});
|
||||
|
||||
test('quote and operator variants are tolerated (=== and single quotes)', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = "for h in hooks: if h.kind === 'contribution' then inject\n";
|
||||
assert.deepEqual([...coveredKindsInRegion(region)], ['contribution']);
|
||||
});
|
||||
|
||||
test('CRLF input yields the same verdicts as LF', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const lf = 'per @gsd-core/references/loop-hook-dispatch.md\n`kind == "gate"` unconditional\n';
|
||||
const crlf = lf.replace(/\n/g, '\r\n');
|
||||
assert.deepEqual([...coveredKindsInRegion(crlf)].sort(), [...coveredKindsInRegion(lf)].sort());
|
||||
});
|
||||
|
||||
test('scanWiredKinds accumulates per-point unions across multiple call sites', () => {
|
||||
const { scanWiredKinds } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const text = [
|
||||
'X=$(gsd_run loop render-hooks verify:post --raw)',
|
||||
'**For each active entry where `kind == "gate"`**',
|
||||
'Y=$(gsd_run loop render-hooks verify:post --raw)',
|
||||
'Dispatch `kind == "step"` hooks per @gsd-core/references/loop-hook-dispatch.md.',
|
||||
'',
|
||||
].join('\n');
|
||||
const m = scanWiredKinds(text);
|
||||
assert.ok(m.has('verify:post'), 'point must be present');
|
||||
assert.deepEqual(
|
||||
[...m.get('verify:post')].sort(),
|
||||
['gate', 'step'],
|
||||
'two call sites at one point accumulate their coverage',
|
||||
);
|
||||
});
|
||||
|
||||
test('capId == and into == narrowing void contribution credit (#3606 adversarial finding)', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const capIdNarrowed = 'Resolve hooks where `kind == "contribution"` and `capId == "security"`.\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(capIdNarrowed)], [],
|
||||
'a one-capability hand-roll is not generic contribution coverage');
|
||||
const intoNarrowed = 'For each entry where `kind == "contribution"` and `into == "planner"`: inject.\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(intoNarrowed)], [],
|
||||
'planner-targeted-only injection leaves orchestrator-targeted contributions dispatched by no one');
|
||||
});
|
||||
|
||||
test('a negated kind mention describes an absence, not a dispatch', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = 'Branch 1 — no active `ship:post` step hooks (`activeHooks` has no entry with `kind == "step"`): Skip.\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(region)], [],
|
||||
'"has no entry with kind == step" must not count as step coverage');
|
||||
});
|
||||
|
||||
test('a deferral sentence keeps its credit when the NEXT sentence specializes (segment split)', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = 'Dispatch `kind == "step"` hooks per @gsd-core/references/loop-hook-dispatch.md. `ref.skill == "code-review"`:\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(region)], ['step'],
|
||||
'the generic deferral and the one-hook specialization are separate sentences');
|
||||
});
|
||||
|
||||
test('a deferral path with a period (loop-hook-dispatch.md) is not split into segments', () => {
|
||||
const { coveredKindsInRegion } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const region = 'Apply each entry per @~/.claude/gsd-core/references/loop-hook-dispatch.md\n';
|
||||
assert.deepEqual([...coveredKindsInRegion(region)].sort(), ['contribution', 'gate', 'step'],
|
||||
'the .md inside the deferral path is not a sentence boundary');
|
||||
});
|
||||
|
||||
test('a site whose consumers are all narrowed yields the zero-coverage error, not "not wired"', () => {
|
||||
const cap = {
|
||||
id: 'test-cap',
|
||||
role: 'feature',
|
||||
steps: [{ point: 'verify:post', ref: { skill: 'x' }, produces: [], consumes: [], onError: 'skip' }],
|
||||
contributions: [],
|
||||
gates: [],
|
||||
config: {},
|
||||
};
|
||||
const wired = new Map([['verify:post', new Set()]]); // sites exist, all narrowed
|
||||
const errs = validateHooksWired(cap, wired);
|
||||
assert.ok(errs.length > 0, 'all-narrowed consumers must fail');
|
||||
const joined = errs.join(' ');
|
||||
assert.match(joined, /covers NO hook kind/i, 'error must name the zero-coverage diagnosis');
|
||||
assert.doesNotMatch(joined, /not wired/i, 'the site EXISTS — misdiagnosing it as unwired points at the wrong remedy');
|
||||
});
|
||||
|
||||
test('HOOK_KINDS vocabulary parity: scanner kinds match the validator group->kind mapping', () => {
|
||||
const { HOOK_KINDS } = require('../scripts/gen-loop-host-contract.cjs');
|
||||
const { HOOK_GROUP_KINDS } = require('../gsd-core/bin/lib/capability-validator.cjs');
|
||||
assert.deepEqual(
|
||||
[...HOOK_KINDS].sort(),
|
||||
Object.values(HOOK_GROUP_KINDS).sort(),
|
||||
'the scanner vocabulary must stay in lock-step with validateHooksWired\u2019s exported group->kind mapping — a rename on either side must fail here',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Anti-pattern parity guards ──────────────────────────────────────────────
|
||||
|
||||
describe('Anti-pattern parity: host-file set has a single source of truth', () => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"version": 1,
|
||||
"paths": {
|
||||
"verify-work.md": {
|
||||
"reason": "#3357: the `03-VERIFICATION.md` staleness check now resolves the phase's own report via `gsd_run query verification.resolve-file \"$PHASE_DIR\" --raw` instead of `ls \"${PHASE_DIR}\"/*-VERIFICATION.md | head -1`, routing through the same shared resolver seam as transition.md so both call sites agree on which file is canonical. Growth is +13 bytes (38,983 -> 38,996), the delta between the old ls/head-1 pipeline and the gsd_run call. #3559: the generic gate-dispatch arm gained the in-context validation contract for manifest-supplied check values. gates[].check is not one of the four executable surfaces the install consent prompt discloses, so a capability consented to as declarative-only could still reach a shell through an unvalidated check.query interpolated into a command substitution. The reference (references/loop-hook-dispatch.md) stated this requirement for step -> ref.command and omitted it for gate; that omission is the root cause and is now closed at the reference plus all four dispatch sites. Growth is one validation paragraph per site. 38996 -> 39107 bytes (+111)."
|
||||
"reason": "#3357: the `03-VERIFICATION.md` staleness check now resolves the phase's own report via `gsd_run query verification.resolve-file \"$PHASE_DIR\" --raw` instead of `ls \"${PHASE_DIR}\"/*-VERIFICATION.md | head -1`, routing through the same shared resolver seam as transition.md so both call sites agree on which file is canonical. Growth is +13 bytes (38,983 -> 38,996), the delta between the old ls/head-1 pipeline and the gsd_run call. #3559: the generic gate-dispatch arm gained the in-context validation contract for manifest-supplied check values. gates[].check is not one of the four executable surfaces the install consent prompt discloses, so a capability consented to as declarative-only could still reach a shell through an unvalidated check.query interpolated into a command substitution. The reference (references/loop-hook-dispatch.md) stated this requirement for step -> ref.command and omitted it for gate; that omission is the root cause and is now closed at the reference plus all four dispatch sites. Growth is one validation paragraph per site. 38996 -> 39107 bytes (+111). \u2014 #3606 append: verify:post consumer gains generic step dispatch (deferral to loop-hook-dispatch.md) before the secure-phase specialization, so ui/security/mempalace/nyquist steps registered at verify:post actually run instead of being filtered out by the one-skill narrow."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
"execute-phase.md": "#3370: the step-3 executor-routing line now also cites #3370 \u2014 the checkpoint gate rule itself lives in the execute-phase/steps/per-plan-executor-routing.md fragment (loaded per plan in every isolation mode immediately before the dispatch prompt is composed), the same keep-the-host-lean pattern #1689/#3417 used, because the host sits under the frozen ADR-857 Phase 6 ceiling (\u226493400). Net growth is 6 bytes (93386 -> 93392): the routing citation only; the rule text, which forbids the orchestrator from composing dispatch text that refuses or overrides auto-approval for the default gate=\"blocking\" (only blocking-human always surfaces), is in the fragment. Supersedes the spent #3324 fragment (merged into next), which also named execute-phase.md and would otherwise double-ack the same path. \u2014 #3423 append (epic #1891 F8): grew 12 bytes with the <files_to_read> -> <required_reading> tag rename (4 tag tokens, +3 bytes each), then trimmed 8 bytes of redundant prose (dropped 'current' from the model-inheritance note; #3478's growth had left only 8 bytes of ADR-857 margin) to stay under the Phase 6 margin ceiling; net +4 bytes against the #3370 baseline. \u2014 #3210 append: the checkpoint_handling blocking-human carve-out names precondition-unmet checkpoints (+29-byte marker '(precondition-unmet, #3210)'), and the decision bullet's 'Except blocking-human' conditional \u2014 required by tests/package-legitimacy-gate.test.cjs \u2014 was restored (+29), funded by trimming ', regardless of type' (-20, the carve-out already overrides all branches) and '(standard flow below)' -> '(standard flow)' (-6); net +3 bytes (93395 -> 93398), still under the frozen ADR-857 Phase 6 ceiling (<=93400). \u2014 #3576 append: bare `references/<name>.md` cites repaired to the canonical `gsd-core/references/<name>.md` form (+9 bytes, 1 cite(s) \u00d7 9). Dead-pointer fix; no content change.",
|
||||
"execute-plan.md": "#3370: the Pattern A dispatch prompt spec gained the gate-semantics clause (gate=\"blocking\" (the default) is auto-approvable in auto-mode per the executor's own checkpoint protocol, gate=\"blocking-human\" always surfaces to a human; add no instruction overriding that protocol), closing the identically-shaped dispatch-time gap on the single-plan path named in the issue. Growth ~248 bytes (38913 -> 39161, still under the DEFAULT 40 KiB ceiling). Supersedes the spent #2652 fragment (merged into next), which also named execute-plan.md and would otherwise double-ack the same path."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"paths": {
|
||||
"gsd-phase-researcher.md": "#3409: guarded `cat \"$phase_dir\"/*-CONTEXT.md` against nullglob wiping the pattern to zero operands when no CONTEXT.md exists — a bare `cat` with no operands blocks reading stdin (hangs the agent) instead of the `2>/dev/null` guard ever firing, since a stalled read is not a failing exit. Now checks `${_CTX[0]}` is a real path before invoking cat. Growth is the array-guard idiom itself (+43 bytes).",
|
||||
"gsd-verifier.md": "#3409: same nullglob-hang fix as gsd-phase-researcher.md, applied to `cat \"$PHASE_DIR\"/*-VERIFICATION.md` in Step 0 — an absent VERIFICATION.md previously left a zero-operand `cat` blocking on stdin instead of falling through to first-verification mode. Growth is the array-guard idiom (+49 bytes). — #3206 append (merged into this fragment because two ack sources may never name the same path): +52 bytes, 49098 -> 49150 (2 under the LARGE cap). The growth is the literal fix for the term 5b used undefined: the compressed explicit-evidence definition inlined at 5b (+34 net on the rewritten line — the trailing honest-verifier cite there is dropped as superseded by the inline definition; honest-verifier.md stays cited at 5c) plus gsd-core/ path-prefix repairs on the two 404ing bare references/ cites at 5c (honest-verifier.md) and the MVP-mode section (verify-mvp-mode.md) (+9 each). Lazy extraction remains untakeable in this change: the large extractable blocks are content-pinned by tests that read the agent file directly (tests/verifier-behavior-unverified.test.cjs, tests/verification-overrides.test.cjs), so extraction is its own coordinated change.",
|
||||
"complete-milestone.md": "#3409: guarded `cat .planning/phases/*-*/*-SUMMARY.md` — with `shopt -s nullglob` active in this block's preamble (#2962), zero matching phase summaries collapses the glob to nothing and a bare `cat` blocks reading stdin rather than producing empty output, wedging the milestone-completion review. Growth is the array-existence-check idiom (+73 bytes, two glob segments makes this longer than the single-glob sites). — #2142 append (merged into this fragment because two ack sources may never name the same path): +1605 bytes, 40498 -> 42103. The `archive_milestone` step now documents the opt-in `--archive-quick` quick-task archival flag (default OFF, deliberately NOT symmetrical with phase archival's default-ON posture), folds the AskUserQuestion decision for it into the SAME `milestone.complete` invocation (avoiding a redundant second call), and states the known bucket-all provenance limit.",
|
||||
"discuss-phase-assumptions.md": "#3409: replaced the unreachable `AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null || echo \"false\")` — `||` never fires because the query exits 0 with empty stdout when the field is absent, not a failure, so AUTO_MODE silently ended up empty rather than \"false\" — with a two-line capture-then-default (`AUTO_MODE=\"${AUTO_MODE:-false}\"`) that actually reaches the fallback. Growth is the extra default-assignment line (+19 bytes).",
|
||||
"plan-phase.md": "#3409: three sites. `AUTO_CHAIN` and `PHASE_REQ_IDS` get the same unreachable-`||`-fallback fix as discuss-phase-assumptions.md (empty-but-successful `gsd_run query` output never triggered `|| echo`, now uses `${VAR:-default}`); `PRIOR_SUMMARIES` additionally swapped `gsd_run query phases.list --pick summaries_total` for `--type summaries --pick count` since the old pick key produced the same unreachable-fallback failure mode for the walking-skeleton check. Net growth across the three sites is +39 bytes. — #3576 append: bare `references/<name>.md` cites repaired to the canonical `gsd-core/references/<name>.md` form (+36 bytes, 4 cite(s) × 9). Dead-pointer fix; no content change. #3559: the generic gate-dispatch arm gained the in-context validation contract for manifest-supplied check values. gates[].check is not one of the four executable surfaces the install consent prompt discloses, so a capability consented to as declarative-only could still reach a shell through an unvalidated check.query interpolated into a command substitution. The reference (references/loop-hook-dispatch.md) stated this requirement for step -> ref.command and omitted it for gate; that omission is the root cause and is now closed at the reference plus all four dispatch sites. Growth is one validation paragraph per site. 90516 -> 90627 bytes (+111). — #2401 append (merged into this fragment because two ack sources may never name the same path): plan-phase.md now dispatches the deterministic `gsd_run check verify-command-paths` probe before spawning the plan-check pass and interpolates its result into the verification prompt as {VERIFY_PATHS} inside a new <verify_command_path_probe> block, plus a <proven_verify_commands> block carrying prior_verify_commands into planning context so the planner can reuse a proven path instead of re-deriving one. 90627 -> 92807 bytes (+2180). Deliberate runtime-loaded workflow text for the new feature, not converter drift.",
|
||||
"session-report.md": "#3409: guarded `ls -la .planning/reports/SESSION_REPORT*.md 2>/dev/null || echo \"No previous reports\"` — with nullglob active, zero prior reports collapses the pattern to nothing and `ls -la` with no operands lists the current directory (a successful exit, wrong output) instead of failing into the `|| echo` fallback, so the report-existence check silently printed a directory listing. Replaced with an array-existence check that only lists when a real report file is present. Growth is the guard idiom (+58 bytes).",
|
||||
"transition.md": "#3409: guarded `cat .planning/phases/XX-current/*-SUMMARY.md` — same nullglob-hang defect as complete-milestone.md's phase-summary read: zero summaries left a bare `cat` blocking on stdin instead of proceeding with no summary content during PROJECT.md evolution. Growth is the array-existence-check idiom (+73 bytes)."
|
||||
"gsd-phase-researcher.md": "#3409: guarded `cat \"$phase_dir\"/*-CONTEXT.md` against nullglob wiping the pattern to zero operands when no CONTEXT.md exists \u2014 a bare `cat` with no operands blocks reading stdin (hangs the agent) instead of the `2>/dev/null` guard ever firing, since a stalled read is not a failing exit. Now checks `${_CTX[0]}` is a real path before invoking cat. Growth is the array-guard idiom itself (+43 bytes).",
|
||||
"gsd-verifier.md": "#3409: same nullglob-hang fix as gsd-phase-researcher.md, applied to `cat \"$PHASE_DIR\"/*-VERIFICATION.md` in Step 0 \u2014 an absent VERIFICATION.md previously left a zero-operand `cat` blocking on stdin instead of falling through to first-verification mode. Growth is the array-guard idiom (+49 bytes). \u2014 #3206 append (merged into this fragment because two ack sources may never name the same path): +52 bytes, 49098 -> 49150 (2 under the LARGE cap). The growth is the literal fix for the term 5b used undefined: the compressed explicit-evidence definition inlined at 5b (+34 net on the rewritten line \u2014 the trailing honest-verifier cite there is dropped as superseded by the inline definition; honest-verifier.md stays cited at 5c) plus gsd-core/ path-prefix repairs on the two 404ing bare references/ cites at 5c (honest-verifier.md) and the MVP-mode section (verify-mvp-mode.md) (+9 each). Lazy extraction remains untakeable in this change: the large extractable blocks are content-pinned by tests that read the agent file directly (tests/verifier-behavior-unverified.test.cjs, tests/verification-overrides.test.cjs), so extraction is its own coordinated change.",
|
||||
"complete-milestone.md": "#3409: guarded `cat .planning/phases/*-*/*-SUMMARY.md` \u2014 with `shopt -s nullglob` active in this block's preamble (#2962), zero matching phase summaries collapses the glob to nothing and a bare `cat` blocks reading stdin rather than producing empty output, wedging the milestone-completion review. Growth is the array-existence-check idiom (+73 bytes, two glob segments makes this longer than the single-glob sites). \u2014 #2142 append (merged into this fragment because two ack sources may never name the same path): +1605 bytes, 40498 -> 42103. The `archive_milestone` step now documents the opt-in `--archive-quick` quick-task archival flag (default OFF, deliberately NOT symmetrical with phase archival's default-ON posture), folds the AskUserQuestion decision for it into the SAME `milestone.complete` invocation (avoiding a redundant second call), and states the known bucket-all provenance limit.",
|
||||
"discuss-phase-assumptions.md": "#3409: replaced the unreachable `AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null || echo \"false\")` \u2014 `||` never fires because the query exits 0 with empty stdout when the field is absent, not a failure, so AUTO_MODE silently ended up empty rather than \"false\" \u2014 with a two-line capture-then-default (`AUTO_MODE=\"${AUTO_MODE:-false}\"`) that actually reaches the fallback. Growth is the extra default-assignment line (+19 bytes).",
|
||||
"plan-phase.md": "#3409: three sites. `AUTO_CHAIN` and `PHASE_REQ_IDS` get the same unreachable-`||`-fallback fix as discuss-phase-assumptions.md (empty-but-successful `gsd_run query` output never triggered `|| echo`, now uses `${VAR:-default}`); `PRIOR_SUMMARIES` additionally swapped `gsd_run query phases.list --pick summaries_total` for `--type summaries --pick count` since the old pick key produced the same unreachable-fallback failure mode for the walking-skeleton check. Net growth across the three sites is +39 bytes. \u2014 #3576 append: bare `references/<name>.md` cites repaired to the canonical `gsd-core/references/<name>.md` form (+36 bytes, 4 cite(s) \u00d7 9). Dead-pointer fix; no content change. #3559: the generic gate-dispatch arm gained the in-context validation contract for manifest-supplied check values. gates[].check is not one of the four executable surfaces the install consent prompt discloses, so a capability consented to as declarative-only could still reach a shell through an unvalidated check.query interpolated into a command substitution. The reference (references/loop-hook-dispatch.md) stated this requirement for step -> ref.command and omitted it for gate; that omission is the root cause and is now closed at the reference plus all four dispatch sites. Growth is one validation paragraph per site. 90516 -> 90627 bytes (+111). \u2014 #2401 append (merged into this fragment because two ack sources may never name the same path): plan-phase.md now dispatches the deterministic `gsd_run check verify-command-paths` probe before spawning the plan-check pass and interpolates its result into the verification prompt as {VERIFY_PATHS} inside a new <verify_command_path_probe> block, plus a <proven_verify_commands> block carrying prior_verify_commands into planning context so the planner can reuse a proven path instead of re-deriving one. 90627 -> 92807 bytes (+2180). Deliberate runtime-loaded workflow text for the new feature, not converter drift. \u2014 #3606 append: plan:pre gains generic contribution dispatch (deferral covering every `into` target, not just planner); plan:post gains generic step + contribution dispatch and its skip condition no longer keys on the gap-analysis gate\u2019s absence (that skip silently dropped every other registered hook at the point).",
|
||||
"session-report.md": "#3409: guarded `ls -la .planning/reports/SESSION_REPORT*.md 2>/dev/null || echo \"No previous reports\"` \u2014 with nullglob active, zero prior reports collapses the pattern to nothing and `ls -la` with no operands lists the current directory (a successful exit, wrong output) instead of failing into the `|| echo` fallback, so the report-existence check silently printed a directory listing. Replaced with an array-existence check that only lists when a real report file is present. Growth is the guard idiom (+58 bytes).",
|
||||
"transition.md": "#3409: guarded `cat .planning/phases/XX-current/*-SUMMARY.md` \u2014 same nullglob-hang defect as complete-milestone.md's phase-summary read: zero summaries left a bare `cat` blocking on stdin instead of proceeding with no summary content during PROJECT.md evolution. Growth is the array-existence-check idiom (+73 bytes)."
|
||||
}
|
||||
}
|
||||
|
||||
8
tests/emitted-drift-acks/3606-hook-kind-coverage.json
Normal file
8
tests/emitted-drift-acks/3606-hook-kind-coverage.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": 1,
|
||||
"paths": {
|
||||
"quick.md": {
|
||||
"reason": "#3606: the execute:post consumer gains generic step dispatch (deferral to loop-hook-dispatch.md) before the code-review specialization, so refactor-trigger's ref.command step and any other registered execute:post steps actually run on /gsd:quick runs instead of being filtered out by the one-skill narrow. Deliberate growth, not converter drift."
|
||||
}
|
||||
}
|
||||
}
|
||||
1
tests/fixtures/install-tree/antigravity.json
vendored
1
tests/fixtures/install-tree/antigravity.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/augment.json
vendored
1
tests/fixtures/install-tree/augment.json
vendored
@@ -344,6 +344,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
@@ -344,6 +344,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/claude.json
vendored
1
tests/fixtures/install-tree/claude.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/cline.json
vendored
1
tests/fixtures/install-tree/cline.json
vendored
@@ -275,6 +275,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/codebuddy.json
vendored
1
tests/fixtures/install-tree/codebuddy.json
vendored
@@ -344,6 +344,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/codex.json
vendored
1
tests/fixtures/install-tree/codex.json
vendored
@@ -308,6 +308,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/copilot.json
vendored
1
tests/fixtures/install-tree/copilot.json
vendored
@@ -274,6 +274,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/cursor.json
vendored
1
tests/fixtures/install-tree/cursor.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/hermes.json
vendored
1
tests/fixtures/install-tree/hermes.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/kilo.json
vendored
1
tests/fixtures/install-tree/kilo.json
vendored
@@ -344,6 +344,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/kimi-code.json
vendored
1
tests/fixtures/install-tree/kimi-code.json
vendored
@@ -274,6 +274,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/kimi.json
vendored
1
tests/fixtures/install-tree/kimi.json
vendored
@@ -309,6 +309,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/opencode.json
vendored
1
tests/fixtures/install-tree/opencode.json
vendored
@@ -344,6 +344,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/pi.json
vendored
1
tests/fixtures/install-tree/pi.json
vendored
@@ -241,6 +241,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/qwen.json
vendored
1
tests/fixtures/install-tree/qwen.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/trae.json
vendored
1
tests/fixtures/install-tree/trae.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/windsurf.json
vendored
1
tests/fixtures/install-tree/windsurf.json
vendored
@@ -273,6 +273,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
1
tests/fixtures/install-tree/zcode.json
vendored
1
tests/fixtures/install-tree/zcode.json
vendored
@@ -344,6 +344,7 @@
|
||||
"gsd-core/workflows/execute-phase/steps/post-merge-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate-run.md",
|
||||
"gsd-core/workflows/execute-phase/steps/regression-gate.md",
|
||||
"gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
||||
"gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md",
|
||||
"gsd-core/workflows/execute-plan.md",
|
||||
"gsd-core/workflows/explore.md",
|
||||
|
||||
Reference in New Issue
Block a user