enhance(#4405): split the rest of the eager-window workflows worth splitting (#4536)

This commit is contained in:
Tom Boucher
2026-09-08 00:17:22 -04:00
committed by GitHub
parent 18c899def5
commit e03921c7d8
38 changed files with 1328 additions and 907 deletions

View File

@@ -517,7 +517,7 @@ All workflow toggles follow the **absent = enabled** pattern. If a key is missin
| `workflow.text_mode` | boolean | `false` | Replaces AskUserQuestion TUI menus with plain-text numbered lists. Required for Claude Code remote sessions (`/rc` mode) where TUI menus don't render. Can also be set per-session with `--text` flag on discuss-phase. Added in v1.28 |
| `workflow.use_worktrees` | boolean | `true` | When `false`, disables git worktree isolation for parallel execution. Users who prefer sequential execution or whose environment does not support worktrees can disable this. Added in v1.31. **Branch-divergence note:** when your branch has diverged from `origin/HEAD`, GSD auto-degrades to sequential and prints a warning. See [`worktree.baseRef`](#worktree-settings) to restore parallel execution on a diverged branch. **Per-runtime note:** whether this key can be honored depends on the runtime's declared `dispatch.isolation` capability, not on its name (#2584). Runtimes whose own harness isolates each executor (**Claude Code**, **Cursor**) run parallel worktrees natively; runtimes exposing a headless exec with an explicit working directory (**Codex**, **OpenCode**, **Kimi**, **Kimi Code**) get worktrees GSD itself creates and merges — where a dispatch site can only drive the harness model, those hosts degrade to sequential with a warning rather than aborting. Every other runtime declares no isolation primitive, and forcing `use_worktrees: true` there still fails closed before any executor dispatch. `/gsd-health` reports such a value as warning `W025` (#2486). **Default on a non-Claude install:** if a worktree-capable non-Claude host is not isolating as described above, check whether the install stamped this key's default to `false` and set an explicit `use_worktrees: true`. See [Executor isolation per runtime](#executor-isolation-per-runtime). |
| `workflow.agent_hint_routing` | boolean | `true` | Per-plan specialist executor routing (#1689). When `true`, a plan whose `agent_hint:` frontmatter names a subagent that resolves on the active runtime is dispatched to that specialist instead of `gsd-executor`. Default `true` — a no-op for plans without `agent_hint:`, so existing dispatch is unchanged. Set `false` to disable. See [PLAN.md `agent_hint`](reference/plan-md.md#per-plan-executor-routing). |
| `workflow.compact_content` | boolean | `false` | Compact content mode (#4139, [ADR-4139](adr/4139-compact-content-seam.md)). Per-project boolean selecting the terser form of GSD's own shipped prompt content (workflows, templates, agent-skill payloads). `/gsd-plan-phase` is the pilot workflow that actually branches on it today (#4402) — with the key off, its spine reads a deferred elaboration file back in before continuing (byte-identical instruction set to before); with it on, that read is skipped. The rest of the corpus does not branch on it yet — full coverage is later sub-issues (#4405+). The eager-window token reduction each split actually achieves is measured, not asserted: `npm run benchmark:compact-content` reports per-split and aggregate on/off token counts (a proxy-tokenizer delta — Anthropic publishes no tokenizer for Claude 3+, so the comparison is exact under a pinned tokenizer even though the absolute counts are not Claude's real ones) against a committed baseline (`tests/fixtures/compact-content-benchmark-baseline.json`, #4404). Reporting-only — it never fails CI. |
| `workflow.compact_content` | boolean | `false` | Compact content mode (#4139, [ADR-4139](adr/4139-compact-content-seam.md)). Per-project boolean selecting the terser form of GSD's own shipped prompt content (workflows, templates, agent-skill payloads). Six workflows branch on it today — `plan-phase` (#4402, the pilot), `execute-phase`, `docs-update`, `new-project`, `verify-work`, and `complete-milestone` (#4405) — each split into a spine plus a deferred `<workflow>/detail/*.md` elaboration: with the key off, the spine reads its own elaboration back in before continuing (byte-identical instruction set to before); with it on, that read is skipped. The remaining eagerly-`@`-included workflows were reviewed and recorded as not worth splitting (see `docs/PARTITION-RULES.md` § "Deciding whether a file is worth splitting") — either their size comes from safety-critical orchestration logic rather than deferrable narrative (`review.md`), or they're small enough that a split's fixed structural overhead would exceed the savings. The eager-window token reduction each split actually achieves is measured, not asserted: `npm run benchmark:compact-content` reports per-split and aggregate on/off token counts (a proxy-tokenizer delta — Anthropic publishes no tokenizer for Claude 3+, so the comparison is exact under a pinned tokenizer even though the absolute counts are not Claude's real ones) against a committed baseline (`tests/fixtures/compact-content-benchmark-baseline.json`, #4404). Reporting-only — it never fails CI. |
| `workflow.worktree_skip_hooks` | boolean | `false` | When `true`, executor agents in worktree mode pass `--no-verify` (skipping pre-commit hooks) and post-wave hook validation runs against the merged result instead. Opt-in escape hatch for projects whose hooks cannot run in agent worktrees. Default `false` runs hooks on every commit (#2924). |
| `workflow.code_review` | boolean | `true` | Enable `/gsd-code-review` and `/gsd-code-review --fix` commands. When `false`, the commands exit with a configuration gate message. Added in v1.34 |
| `workflow.code_review_point` | string | `execute:post` | Loop point at which the code-review capability's step registers: `execute:post` reviews once, after every wave in a phase has landed (default — unchanged behavior); `execute:wave:post` reviews once per completed wave instead, scoped to what changed since the phase's prior review (the whole phase's diff on the first wave, each subsequent wave's own diff thereafter). Manual `/gsd-code-review <phase>` invocation is unaffected by this key — it is gated by `workflow.code_review` alone and runs regardless of which point is configured. `/gsd-autonomous` and `/gsd-quick` have no wave granularity of their own, so setting this to `execute:wave:post` means code review does not run automatically inside those two flows (consistent with how every other `execute:wave:post`-only capability already behaves for them). Added in #3661 |

View File

@@ -672,7 +672,12 @@
"verify-work/steps/mvp-uat-framing.md"
],
"workflow_detail": [
"plan-phase/detail/elaboration.md"
"complete-milestone/detail/elaboration.md",
"docs-update/detail/elaboration.md",
"execute-phase/detail/elaboration.md",
"new-project/detail/elaboration.md",
"plan-phase/detail/elaboration.md",
"verify-work/detail/elaboration.md"
],
"workflow_templates": [
"discuss-phase/templates/context.md",

View File

@@ -280,7 +280,7 @@ none is separately invocable — the parent workflow reaches them.
|---|---|---|---|
| `<workflow>/steps/*.md` | Gated section bodies extracted by the fragment model (ADR-1671, epic #1671 Phases 6.1–6.3). The parent carries a `section_manifest`-gated stub; `gsd-core/workflows/section-manifest.json` names which step a given invocation reads. | `workflow_steps` | See `docs/INVENTORY-MANIFEST.json` for the authoritative per-file list |
| `<workflow>/modes/*.md` | Progressive-disclosure mode files (#717). The parent dispatches to exactly one; `discuss-phase/modes/` is the canonical example. | `workflow_modes` | `discuss-phase`, `help` |
| `<workflow>/detail/*.md` | Elaboration content deferred from a workflow spine, read at runtime only when `workflow.compact_content` is `false` (ADR-4139; epic #4139 Phase 2 #4402 established the first example, Phase 3 #4403 added the CI guard). | `workflow_detail` | `plan-phase` |
| `<workflow>/detail/*.md` | Elaboration content deferred from a workflow spine, read at runtime only when `workflow.compact_content` is `false` (ADR-4139; epic #4139 Phase 2 #4402 established the first example, Phase 3 #4403 added the CI guard, Phase 5 #4405 split the rest of the eager-window corpus worth splitting). | `workflow_detail` | `plan-phase`, `execute-phase`, `docs-update`, `new-project`, `verify-work`, `complete-milestone` |
| `<workflow>/templates/*.md` | Fill-in template bodies the parent workflow renders at runtime; also referenced as a `FRAGMENT_DIRS` entry in `scripts/lint-response-language-coverage.cjs`. | `workflow_templates` | `discuss-phase` |
All four families are keyed by `<workflow>/<subdir>/<file>.md` rather than a bare filename, because

View File

@@ -104,3 +104,29 @@ Checks 1 and 4–5 read `merge-base..HEAD`, never `base..HEAD` (two-dot) — the
ADR-3942 made for its own trailer range, for the same reason: a two-dot range would let the
set of commits being checked and the set of files being diffed disagree about what "this PR"
means.
## Deciding whether a file is worth splitting
Not every eagerly-`@`-included workflow benefits from a spine/detail partition. Epic #4139
Phase 5 ([#4405](https://github.com/open-gsd/gsd-core/issues/4405)) established the working
criteria, applied to every file in the eager-window corpus:
- **Split it** when the file has one or more clearly-delineated steps or sub-sections that are
genuinely optional or rare in normal execution — gated by an explicit flag, an off-by-default
config key, an uncommon runtime condition, or a fallback path most runs never take. The five
files split in Phase 5 (`execute-phase.md`, `docs-update.md`, `new-project.md`,
`verify-work.md`, `complete-milestone.md`) all had this shape.
- **Record it as not worth splitting** when either: (a) the file's size comes predominantly
from safety-critical, always-relevant orchestration logic and documented bug-history
comments rather than deferrable narrative elaboration — extracting from it would butcher
core happy-path logic or bury a regression-preventing "why" comment (`review.md`'s
disposition in Phase 5, despite being named among the epic's heaviest files); or (b) the
file is small enough that the fixed structural cost of a split — a new `detail/` directory,
the five checks' ongoing enforcement surface, `docs/INVENTORY.md`/manifest bookkeeping, and
reviewer attention — is not justified by the achievable savings. The smallest file split in
Phase 5 (`complete-milestone.md`, 41,278 bytes) still only yielded roughly 10.4 KB of actual
reduction; a file well under that size buys proportionally less for the same fixed cost.
A "not worth splitting" disposition is not permanent — re-evaluate a file if it grows
substantially, or a later change gives it a genuinely optional or rare execution branch it
didn't have before.