fix(#3894): quick path honors workflow.research_before_questions; key resolves from global defaults (#4047)

* test(#3894): research_before_questions must resolve globally and order quick.md (failing first)

* fix(#3894): quick path honors workflow.research_before_questions; key resolves from global defaults

Two layers, one key. The quick workflow ran its discussion phase
before its research phase unconditionally — neither quick.md nor its
steps ever read workflow.research_before_questions, though the key is
documented, schema-registered, /gsd-settings-writable, and honored by
/gsd-discuss-phase and /gsd-new-project. A gray-area answer given
without research is then written to <quick_id>-CONTEXT.md as a locked
decision downstream agents are told not to revisit — an evidence-free
choice made unfalsifiable (the reporter's #3714 misresolution).

- quick.md Step 4 now carries the same research-before-questions check
  the two honoring paths make: when enabled, research-phase executes
  before discussion-phase; false/unset keeps the written order. Both
  sections stay section-manifest gated.
- src/config-loader.cts forwarded workflow.post_planning_gaps from
  ~/.gsd/defaults.json but silently dropped this key — same file, same
  nesting, one resolved and one didn't. Now forwarded with the same
  flat + nested-alias fallback shape, added to the resolution-keys
  lockstep canary and the #3532 shadowed-warning set (nested alias
  reporting generalized over both keys).

Emitted-Drift-Ack-Growth: quick.md — #3894: +Step 4 ordering rule (the research-before-questions check the discuss-phase and new-project paths already make); a real behavioral gate, not incidental bloat.

* fix(#3894): review fold-ins — gate the CONTEXT.md reference, colon slash-forms

- quick/steps/research-phase.md directed the researcher subagent to read
  <quick_id>-CONTEXT.md under DISCUSS_MODE with no existence hedge — but
  under the new ordering (research BEFORE discussion) the file cannot
  exist yet when the researcher is dispatched. The reference now says
  read-only-if-present with the #3894 reason; the alignment purpose
  still applies on the default ordering.
- quick.md's new rule used the hyphen slash forms (/gsd-discuss-phase,
  /gsd-new-project); source artifacts under gsd-core/workflows must
  author the colon form the install-time converters key on — the same
  file already uses /gsd:new-project and /gsd:quick elsewhere.

* docs(#3894): planning-config row names the flat CONFIG_DEFAULTS alias

config-field-docs requires every CONFIG_DEFAULTS key to appear in the
doc; the row documented the canonical namespaced form only. Adds the
same alias sentence post_planning_gaps's row carries, plus the #3894
quick-path note.

* chore(#3894): changeset fragment (pr number backfilled after PR creation)

* chore(#3894): backfill changeset PR number (4047)

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-29 13:51:42 -04:00
committed by GitHub
parent 192eb1dfbd
commit 400db94e02
7 changed files with 131 additions and 9 deletions

View File

@@ -324,3 +324,36 @@ describe('quick workflow: banner variants for flag combinations', () => {
);
});
});
// ─── #3894: quick.md honors workflow.research_before_questions ───────────────
describe('#3894 quick.md research-before-questions ordering', () => {
const QUICK = fs.readFileSync(path.join(WORKFLOWS_DIR, 'quick.md'), 'utf-8');
test('quick.md reads workflow.research_before_questions', () => {
assert.ok(
QUICK.includes('research_before_questions'),
'#3894: the quick path must read the documented key — before this fix neither quick.md nor its steps referenced it'
);
});
test('when enabled, research-phase is ordered BEFORE discussion-phase', () => {
const orderingIdx = QUICK.indexOf('research_before_questions');
assert.ok(orderingIdx !== -1, 'key referenced');
const ruleWindow = QUICK.slice(orderingIdx, orderingIdx + 900);
assert.ok(
/research[- ]phase[^]{0,200}(before|prior to|first)[^]{0,120}discussion/i.test(ruleWindow)
|| /when[^]{0,60}(true|enabled)[^]{0,300}research/i.test(ruleWindow),
'the ordering rule must state research runs before discussion when the key is true'
);
assert.ok(
ruleWindow.includes('false') || ruleWindow.includes('unset') || ruleWindow.toLowerCase().includes('unchanged'),
'and must keep the written order when false/unset'
);
});
test('both step sections remain section-manifest gated (no structural regression)', () => {
assert.ok(/gsd:section id="discussion-phase"/.test(QUICK), 'discussion-phase section marker intact');
assert.ok(/gsd:section id="research-phase"/.test(QUICK), 'research-phase section marker intact');
});
});