diff --git a/CHANGELOG.md b/CHANGELOG.md index dbce423c46..023e7b7068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,37 @@ > completion state and remaining P0 gates. No version bump or release claim is > made here while that status holds. +## [1.61.1.0] - 2026-07-22 + +## **Design docs now read like decision records.** +## **The transcript padding is gone.** + +v1.61.0.0 put design docs in your repo at `docs/designs/`. This release fixes what is inside them. The `/plan` Discovery specialist now writes bullets over paragraphs, one bullet per decision with its why. An approach you killed during the conversation gets one line, name plus rejection reason, instead of a resurrected "Approach B" section that re-argues the case. Template sections that are empty or that restate what you already settled are omitted. There is no page cap, just a rule that every word earns its place: extra length has to come from genuinely open questions, not template completeness. + +### The numbers that matter + +Source: `bun run scripts/gstack2/run-parity.ts`, the executable parity inventory, plus the field report that triggered this (a support-system design doc where most of the content was approaches the user had already ruled out in chat). + +| Metric | Before | After | +|---|---|---| +| Judgment overlays | 27 | 28 | +| Parity checks | 4,909 | 4,914 | +| Lines per ruled-out approach | a full section | 1 | + +No before/after length benchmark for generated docs exists yet; the rule ships with an executable regression fixture (`evals/parity/regressions/pr-2000.json`) instead of a measured corpus. + +### What this means for builders + +When office hours hands you a design doc, you can read it in one sitting and see what was decided and why. Nothing you rejected in the session comes back as prose. If a doc runs long, it is because real questions are still open. Run `/plan` as usual; nothing to configure. + +### Itemized changes + +#### Changed +- The `/plan` Discovery (office-hours) design doc is now a concise decision record (issue #2000): bullet points over paragraphs, ruled-out approaches collapsed to one line each with the rejection reason, settled or empty template sections omitted, no fixed page cap. + +#### For contributors +- New judgment overlay `GSTACK2_FIX_2000_DESIGN_DOC_CONCISION` (targets office-hours) with executable regression `pr-2000.json`; parity inventory is now 4,914 checks across 28 regression ports. + ## [1.61.0.0] - 2026-07-22 ## **/plan now sizes its machinery to your ask.** diff --git a/VERSION b/VERSION index 82b3fa4c6d..ad37b0f1be 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.61.0.0 +1.61.1.0 diff --git a/docs/gstack-2/JUDGMENT-PARITY.md b/docs/gstack-2/JUDGMENT-PARITY.md index 20e06d0997..8d2c311cee 100644 --- a/docs/gstack-2/JUDGMENT-PARITY.md +++ b/docs/gstack-2/JUDGMENT-PARITY.md @@ -2,7 +2,7 @@ Parity is executable, not a prose claim. Run `bun run scripts/gstack2/run-parity.ts` or the dedicated Bun tests. -The pinned release inventory passes **4,909 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 27 regression ports, and **78 assets**. +The pinned release inventory passes **4,914 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 28 regression ports, and **78 assets**. The suite verifies: @@ -11,7 +11,7 @@ The suite verifies: - immutable full 1.x render hashes plus canonical specialist-render equality, with the excluded onboarding wrapper and lazy section references asserted explicitly; - preservation of nine behavioral contract dimensions per module; - 25 structured non-keyword routing fixtures with active/skipped modules, depth, mutation, and web context; -- 25 upstream judgment-port regression fixtures and anchors; +- 28 upstream judgment-port regression fixtures and anchors; - all linked asset copies against their pinned Git blobs; - frontmatter and `agents/openai.yaml` schema for each public skill. diff --git a/docs/gstack-2/JUDGMENT-PROVENANCE.json b/docs/gstack-2/JUDGMENT-PROVENANCE.json index 78349a8d18..92b72f96d7 100644 --- a/docs/gstack-2/JUDGMENT-PROVENANCE.json +++ b/docs/gstack-2/JUDGMENT-PROVENANCE.json @@ -17,7 +17,7 @@ "packaged_section_copies": 17, "internal_execution_adapters": 1, "scenarios": 25, - "bug_fix_ports": 25, + "bug_fix_ports": 28, "assets": 78, "dependency_copies": 4, "runtime_helpers": 41 @@ -92,7 +92,8 @@ 1049, 1116, 886, - 703 + 703, + 2000 ], "original_source_file": "office-hours/SKILL.md.tmpl", "original_line_range": "1-526", @@ -7459,6 +7460,15 @@ "review" ], "anchor": "GSTACK2_FIX_452_CLAUDEMD_REVIEW_SECTION" + }, + { + "pr": 2000, + "url": "https://github.com/garrytan/gstack/issues/2000", + "title": "Design docs record decisions concisely", + "targets": [ + "office-hours" + ], + "anchor": "GSTACK2_FIX_2000_DESIGN_DOC_CONCISION" } ] } diff --git a/docs/gstack-2/SKILL-MIGRATION.md b/docs/gstack-2/SKILL-MIGRATION.md index 70b470412c..277c020df0 100644 --- a/docs/gstack-2/SKILL-MIGRATION.md +++ b/docs/gstack-2/SKILL-MIGRATION.md @@ -11,7 +11,7 @@ The fixed public modes are: Design = `Explore | Generate | Critique | Implement` | Legacy invocation | Replacement | Visibility | Mandatory | Judgment overlays | |---|---|---|---|---| | `/gstack` | `$plan --mode Discovery --module gstack` | internal (internal) | no | #679 | -| `/office-hours` | `$plan --mode Discovery --module office-hours` | internal (primary) | yes | #679, #2030, #1049, #1116, #886, #703 | +| `/office-hours` | `$plan --mode Discovery --module office-hours` | internal (primary) | yes | #679, #2030, #1049, #1116, #886, #703, #2000 | | `/plan-ceo-review` | `$plan --mode Product --module plan-ceo-review` | internal (primary) | yes | #679, #2030, #886, #703 | | `/plan-eng-review` | `$plan --mode Engineering --module plan-eng-review` | internal (primary) | yes | #679, #1071, #2030, #592, #886, #703 | | `/plan-devex-review` | `$plan --mode DX --module plan-devex-review` | internal (primary) | yes | #679, #2030, #886, #703 | @@ -75,5 +75,5 @@ The fixed public modes are: Design = `Explore | Generate | Critique | Implement` ## Mechanical versus judgment changes - `JUDGMENT_PRESERVING_CARVE`: pinned specialist workflow with the retired shared onboarding wrapper excluded, retired invocations resolved to six public routes, host/runtime paths normalized, and large carved phases loaded lazily from package-local pinned references. -- `BUG_FIX`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 27 upstream PRs and issues and its regression fixture. +- `BUG_FIX`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 28 upstream PRs and issues and its regression fixture. - Asset relocation is byte-for-byte from the pinned Git blob and is indexed per tree. diff --git a/evals/parity/contracts/office-hours.json b/evals/parity/contracts/office-hours.json index 89e2f0e132..04e1310052 100644 --- a/evals/parity/contracts/office-hours.json +++ b/evals/parity/contracts/office-hours.json @@ -17,7 +17,8 @@ 1049, 1116, 886, - 703 + 703, + 2000 ], "contract": { "question_order": "Preserve the source workflow order; gather prerequisites before consequential questions.", diff --git a/evals/parity/manifest.json b/evals/parity/manifest.json index 78349a8d18..92b72f96d7 100644 --- a/evals/parity/manifest.json +++ b/evals/parity/manifest.json @@ -17,7 +17,7 @@ "packaged_section_copies": 17, "internal_execution_adapters": 1, "scenarios": 25, - "bug_fix_ports": 25, + "bug_fix_ports": 28, "assets": 78, "dependency_copies": 4, "runtime_helpers": 41 @@ -92,7 +92,8 @@ 1049, 1116, 886, - 703 + 703, + 2000 ], "original_source_file": "office-hours/SKILL.md.tmpl", "original_line_range": "1-526", @@ -7459,6 +7460,15 @@ "review" ], "anchor": "GSTACK2_FIX_452_CLAUDEMD_REVIEW_SECTION" + }, + { + "pr": 2000, + "url": "https://github.com/garrytan/gstack/issues/2000", + "title": "Design docs record decisions concisely", + "targets": [ + "office-hours" + ], + "anchor": "GSTACK2_FIX_2000_DESIGN_DOC_CONCISION" } ] } diff --git a/evals/parity/regressions/pr-2000.json b/evals/parity/regressions/pr-2000.json new file mode 100644 index 0000000000..63ea834b06 --- /dev/null +++ b/evals/parity/regressions/pr-2000.json @@ -0,0 +1,20 @@ +{ + "pr": 2000, + "url": "https://github.com/garrytan/gstack/issues/2000", + "title": "Design docs record decisions concisely", + "targets": [ + "office-hours" + ], + "anchor": "GSTACK2_FIX_2000_DESIGN_DOC_CONCISION", + "body": "### Design-doc concision\n\nThe design doc is a decision record, not a transcript of the session. There is no fixed page limit, but every word must earn its place: prefer bullet points over paragraphs, one bullet per decision with its why. An approach the user ruled out during the session gets at most one line — name plus rejection reason — never its own section, comparison matrix, or re-argued case. Omit template sections that are empty or that restate what the conversation already settled. Cut preamble, hedging, and restated context; extra length must be earned by genuinely open questions, not by template completeness. (Placement is governed by the repo-local design-artifact rule from issue #703.)", + "regression": { + "input": { + "ruled_out_approaches": 3 + }, + "expected": { + "ruled_out_lines_each": 1, + "bullets_over_paragraphs": true, + "settled_sections_omitted": true + } + } +} diff --git a/evals/parity/transcripts/deterministic/office-hours.json b/evals/parity/transcripts/deterministic/office-hours.json index 54fa1e7516..319721f6a1 100644 --- a/evals/parity/transcripts/deterministic/office-hours.json +++ b/evals/parity/transcripts/deterministic/office-hours.json @@ -123,6 +123,13 @@ "reproduced_defect": "Write design docs repo-local and read them from the repo first", "regression_fixture": "evals/parity/regressions/pr-703.json", "explanation": "### Repo-local design artifacts\n\nWhen the session produces a design or plan document and the working directory is inside a repository, write it to `docs/designs/.md` in that repository (create `docs/designs/` if needed) and name that path every time the document is presented or approval is requested. A hashed home-directory path is never the thing the user is asked to open. Keep writing the cross-session copy under `\"${GSTACK_HOME:-$HOME/.gstack}\"/projects//` with the existing filename convention — downstream skills, prior-design lookup, and cross-team discovery depend on that store — but the repo-local file is the canonical one the user owns and edits. Outside a repository, the `$GSTACK_HOME` path remains the only copy; print it in full when asking for approval. When reviewing, prefer a repo-local design doc (`docs/designs/`, `docs/plans/`, or an explicitly provided path) over the `$GSTACK_HOME` store whenever both exist." + }, + { + "classification": "INTENTIONAL_IMPROVEMENT", + "issue_or_pr": "https://github.com/garrytan/gstack/issues/2000", + "reproduced_defect": "Design docs record decisions concisely", + "regression_fixture": "evals/parity/regressions/pr-2000.json", + "explanation": "### Design-doc concision\n\nThe design doc is a decision record, not a transcript of the session. There is no fixed page limit, but every word must earn its place: prefer bullet points over paragraphs, one bullet per decision with its why. An approach the user ruled out during the session gets at most one line — name plus rejection reason — never its own section, comparison matrix, or re-argued case. Omit template sections that are empty or that restate what the conversation already settled. Cut preamble, hedging, and restated context; extra length must be earned by genuinely open questions, not by template completeness. (Placement is governed by the repo-local design-artifact rule from issue #703.)" } ] } diff --git a/scripts/gstack2/bug-fix-overlays.ts b/scripts/gstack2/bug-fix-overlays.ts index d178738989..cbe81cb118 100644 --- a/scripts/gstack2/bug-fix-overlays.ts +++ b/scripts/gstack2/bug-fix-overlays.ts @@ -391,6 +391,24 @@ Before scope-drift detection, read a \`## Review\` section from the project CLAU expected: { apply_repo_rules: true, silent_skip_if_absent: true }, }, }, + { + pr: 2000, + url: 'https://github.com/garrytan/gstack/issues/2000', + title: 'Design docs record decisions concisely', + targets: ['office-hours'], + anchor: 'GSTACK2_FIX_2000_DESIGN_DOC_CONCISION', + body: `### Design-doc concision + +The design doc is a decision record, not a transcript of the session. There is no fixed page limit, but every word must earn its place: prefer bullet points over paragraphs, one bullet per decision with its why. An approach the user ruled out during the session gets at most one line — name plus rejection reason — never its own section, comparison matrix, or re-argued case. Omit template sections that are empty or that restate what the conversation already settled. Cut preamble, hedging, and restated context; extra length must be earned by genuinely open questions, not by template completeness. (Placement is governed by the repo-local design-artifact rule from issue #703.)`, + regression: { + input: { ruled_out_approaches: 3 }, + expected: { + ruled_out_lines_each: 1, + bullets_over_paragraphs: true, + settled_sections_omitted: true, + }, + }, + }, ]; export function overlaysForSource(source: string): BugFixOverlay[] { @@ -566,6 +584,14 @@ export function evaluateBugFixRegression(pr: number, rawInput: unknown): Record< } case 452: return { apply_repo_rules: input.claude_md_has_review_section === true, silent_skip_if_absent: true }; + case 2000: { + const ruledOut = Number(input.ruled_out_approaches ?? 0); + return { + ruled_out_lines_each: ruledOut > 0 ? 1 : 0, + bullets_over_paragraphs: true, + settled_sections_omitted: true, + }; + } case 703: { const inRepo = input.in_repository === true; return { diff --git a/scripts/gstack2/generate-skill-tree.ts b/scripts/gstack2/generate-skill-tree.ts index 760c55283e..e0fe75e6ef 100644 --- a/scripts/gstack2/generate-skill-tree.ts +++ b/scripts/gstack2/generate-skill-tree.ts @@ -82,7 +82,7 @@ function assertInventory(): void { } if (legacySections().length !== 16) throw new Error(`Expected 16 section templates, found ${legacySections().length}`); if (SCENARIOS.length !== 25) throw new Error(`Expected 25 parity scenarios, found ${SCENARIOS.length}`); - if (BUG_FIX_OVERLAYS.length !== 27) throw new Error(`Expected 27 upstream judgment overlays, found ${BUG_FIX_OVERLAYS.length}`); + if (BUG_FIX_OVERLAYS.length !== 28) throw new Error(`Expected 28 upstream judgment overlays, found ${BUG_FIX_OVERLAYS.length}`); } function toc(body: string): string { @@ -758,7 +758,7 @@ ${rows} ## Mechanical versus judgment changes - \`JUDGMENT_PRESERVING_CARVE\`: pinned specialist workflow with the retired shared onboarding wrapper excluded, retired invocations resolved to six public routes, host/runtime paths normalized, and large carved phases loaded lazily from package-local pinned references. -- \`BUG_FIX\`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 27 upstream PRs and issues and its regression fixture. +- \`BUG_FIX\`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 28 upstream PRs and issues and its regression fixture. - Asset relocation is byte-for-byte from the pinned Git blob and is indexed per tree. `; } @@ -779,7 +779,7 @@ function parityDoc(assetCount: number): string { Parity is executable, not a prose claim. Run \`bun run scripts/gstack2/run-parity.ts\` or the dedicated Bun tests. -The pinned release inventory passes **${EXPECTED_PARITY_CHECKS.toLocaleString('en-US')} checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 27 regression ports, and **${assetCount} assets**. +The pinned release inventory passes **${EXPECTED_PARITY_CHECKS.toLocaleString('en-US')} checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 28 regression ports, and **${assetCount} assets**. The suite verifies: @@ -788,7 +788,7 @@ The suite verifies: - immutable full 1.x render hashes plus canonical specialist-render equality, with the excluded onboarding wrapper and lazy section references asserted explicitly; - preservation of nine behavioral contract dimensions per module; - 25 structured non-keyword routing fixtures with active/skipped modules, depth, mutation, and web context; -- 25 upstream judgment-port regression fixtures and anchors; +- 28 upstream judgment-port regression fixtures and anchors; - all linked asset copies against their pinned Git blobs; - frontmatter and \`agents/openai.yaml\` schema for each public skill. @@ -938,7 +938,7 @@ function main(): void { schema_version: 1, base_sha: GSTACK2_BASE_SHA, public_skills: [...TREE_NAMES], - counts: { public_skills: 6, mandatory_inputs: 31, templates: 55, section_templates: 16, packaged_section_copies: sectionCopies.length, internal_execution_adapters: 1, scenarios: 25, bug_fix_ports: 25, assets: assets.length, dependency_copies: dependencyCopies.length, runtime_helpers: runtimeHelpers.length }, + counts: { public_skills: 6, mandatory_inputs: 31, templates: 55, section_templates: 16, packaged_section_copies: sectionCopies.length, internal_execution_adapters: 1, scenarios: 25, bug_fix_ports: 28, assets: assets.length, dependency_copies: dependencyCopies.length, runtime_helpers: runtimeHelpers.length }, sources: sourceRecords, sections: sectionRecords, section_copies: sectionCopies, diff --git a/scripts/gstack2/run-parity.ts b/scripts/gstack2/run-parity.ts index e2eebba959..0dcab6f9a4 100644 --- a/scripts/gstack2/run-parity.ts +++ b/scripts/gstack2/run-parity.ts @@ -21,8 +21,9 @@ const ALLOWED_DISPOSITIONS = new Set(['VERBATIM_PORT', 'MECHANICAL_PORT', 'JUDGM // proportional-planning overlay for issue #886 (25 -> 26, six plan-tree // targets) added 15 more (2 per targeted module + 3 regression checks). The // repo-local design-doc overlay for issue #703 (26 -> 27, five plan-tree -// targets) added 13 more. -export const EXPECTED_PARITY_CHECKS = 4909; +// targets) added 13 more. The design-doc concision overlay for issue #2000 +// (27 -> 28, office-hours only) added 5 more. +export const EXPECTED_PARITY_CHECKS = 4914; function sha256(value: string | Uint8Array): string { return createHash('sha256').update(value).digest('hex'); @@ -257,8 +258,8 @@ export function runParity(): ParityResult { check(JSON.stringify(json(path.join(ROOT, 'evals', 'parity', 'scenarios', `${scenario.id}.json`))) === JSON.stringify(scenario), `${scenario.id} generated fixture drift`); } - check(BUG_FIX_OVERLAYS.length === 27, `Expected 27 regression definitions; got ${BUG_FIX_OVERLAYS.length}`); - check(files(path.join(ROOT, 'evals', 'parity', 'regressions'), '.json').length === 27, 'Generated regression fixture count is not 27'); + check(BUG_FIX_OVERLAYS.length === 28, `Expected 28 regression definitions; got ${BUG_FIX_OVERLAYS.length}`); + check(files(path.join(ROOT, 'evals', 'parity', 'regressions'), '.json').length === 28, 'Generated regression fixture count is not 28'); for (const overlay of BUG_FIX_OVERLAYS) { const fixture = json(path.join(ROOT, 'evals', 'parity', 'regressions', `pr-${overlay.pr}.json`)); check(JSON.stringify(fixture) === JSON.stringify(overlay), `PR #${overlay.pr} regression fixture drift`); diff --git a/skills/plan/references/legacy/office-hours.md b/skills/plan/references/legacy/office-hours.md index 1ce41a132e..ff387d18ec 100644 --- a/skills/plan/references/legacy/office-hours.md +++ b/skills/plan/references/legacy/office-hours.md @@ -797,3 +797,13 @@ For office-hours specifically: at session or hobby scale, batch the Phase 2B que When the session produces a design or plan document and the working directory is inside a repository, write it to `docs/designs/.md` in that repository (create `docs/designs/` if needed) and name that path every time the document is presented or approval is requested. A hashed home-directory path is never the thing the user is asked to open. Keep writing the cross-session copy under `"${GSTACK_HOME:-$HOME/.gstack}"/projects//` with the existing filename convention — downstream skills, prior-design lookup, and cross-team discovery depend on that store — but the repo-local file is the canonical one the user owns and edits. Outside a repository, the `$GSTACK_HOME` path remains the only copy; print it in full when asking for approval. When reviewing, prefer a repo-local design doc (`docs/designs/`, `docs/plans/`, or an explicitly provided path) over the `$GSTACK_HOME` store whenever both exist. + + +## Upstream judgment port: issue #2000 + +[Design docs record decisions concisely](https://github.com/garrytan/gstack/issues/2000) + +### Design-doc concision + +The design doc is a decision record, not a transcript of the session. There is no fixed page limit, but every word must earn its place: prefer bullet points over paragraphs, one bullet per decision with its why. An approach the user ruled out during the session gets at most one line — name plus rejection reason — never its own section, comparison matrix, or re-argued case. Omit template sections that are empty or that restate what the conversation already settled. Cut preamble, hedging, and restated context; extra length must be earned by genuinely open questions, not by template completeness. (Placement is governed by the repo-local design-artifact rule from issue #703.) + diff --git a/test/gstack2-skills.test.ts b/test/gstack2-skills.test.ts index f9d3610e90..ba40c41b08 100644 --- a/test/gstack2-skills.test.ts +++ b/test/gstack2-skills.test.ts @@ -27,7 +27,7 @@ describe('GStack 2 skill parity', () => { const result = runParity(); expect(result.sources).toBe(55); expect(result.sections).toBe(16); - expect(result.regressions).toBe(27); + expect(result.regressions).toBe(28); }, 30_000); test('keeps image generation host-native, optional, and provider-free', () => {