@opengsd/gsd-core 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +131 -34
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-executor.md +7 -5
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-plan-checker.md +9 -0
- package/agents/gsd-planner.md +5 -8
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-verifier.md +14 -70
- package/bin/install.js +503 -341
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +607 -63
- package/gsd-core/bin/lib/active-workstream-store.cjs +25 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +38 -6
- package/gsd-core/bin/lib/api-coverage.cjs +120 -0
- package/gsd-core/bin/lib/audit.cjs +89 -1
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- package/gsd-core/bin/lib/capability-registry.cjs +96 -110
- package/gsd-core/bin/lib/capability-validator.cjs +12 -2
- package/gsd-core/bin/lib/check-command-router.cjs +43 -1
- package/gsd-core/bin/lib/command-aliases.cjs +72 -0
- package/gsd-core/bin/lib/commands.cjs +26 -25
- package/gsd-core/bin/lib/commonjs-marker.cjs +136 -0
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +12 -1
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +91 -12
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/frontmatter.cjs +84 -12
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +58 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +27 -4
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1021 -57
- package/gsd-core/bin/lib/install-engine.cjs +64 -10
- package/gsd-core/bin/lib/install-profiles.cjs +27 -1
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +87 -1
- package/gsd-core/bin/lib/io.cjs +28 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +6 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone.cjs +106 -51
- package/gsd-core/bin/lib/phase-id.cjs +63 -0
- package/gsd-core/bin/lib/phase-locator.cjs +138 -45
- package/gsd-core/bin/lib/phase.cjs +260 -25
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +232 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +4 -0
- package/gsd-core/bin/lib/project-root.cjs +48 -0
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +80 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +99 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +30 -6
- package/gsd-core/bin/lib/roadmap-command-router.cjs +42 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +100 -18
- package/gsd-core/bin/lib/roadmap.cjs +37 -7
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +195 -62
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +15 -3
- package/gsd-core/bin/lib/runtime-homes.cjs +154 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +105 -41
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +113 -27
- package/gsd-core/bin/lib/smart-entry.cjs +12 -0
- package/gsd-core/bin/lib/state-transition.cjs +73 -8
- package/gsd-core/bin/lib/state.cjs +151 -62
- package/gsd-core/bin/lib/surface.cjs +12 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +11 -1
- package/gsd-core/bin/lib/uat.cjs +320 -21
- package/gsd-core/bin/lib/unusable-input.cjs +9 -0
- package/gsd-core/bin/lib/verification.cjs +29 -12
- package/gsd-core/bin/lib/verify.cjs +29 -5
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +181 -18
- package/gsd-core/bin/lib/workstream-inventory.cjs +519 -27
- package/gsd-core/bin/lib/workstream.cjs +6 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +276 -118
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/specless-probe-fallback.md +7 -6
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +32 -69
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +83 -0
- package/gsd-core/workflows/code-review.md +42 -145
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +23 -81
- package/gsd-core/workflows/debug.md +9 -12
- package/gsd-core/workflows/diagnose-issues.md +22 -0
- package/gsd-core/workflows/discovery-phase.md +4 -4
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +5 -16
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +34 -2
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +19 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +65 -137
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/ingest-docs.md +2 -1
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +21 -38
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +13 -226
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +49 -193
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +11 -153
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +46 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +20 -390
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +15 -8
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +17 -14
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +49 -11
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +8 -21
- package/gsd-core/workflows/ui-phase.md +8 -7
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +18 -7
- package/gsd-core/workflows/verify-phase.md +4 -7
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +8 -58
- package/hooks/dist/gsd-agent-isolation-guard.js +428 -0
- package/hooks/dist/gsd-check-update-worker.js +14 -5
- package/hooks/dist/gsd-cursor-subagent-start.js +532 -26
- package/hooks/dist/gsd-read-injection-scanner.js +7 -0
- package/hooks/dist/gsd-statusline.js +72 -6
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/isolation-sentinel.js +268 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +428 -0
- package/hooks/gsd-check-update-worker.js +14 -5
- package/hooks/gsd-cursor-subagent-start.js +532 -26
- package/hooks/gsd-read-injection-scanner.js +7 -0
- package/hooks/gsd-statusline.js +72 -6
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/isolation-sentinel.js +268 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +14 -5
- package/pi/gsd.cjs +57 -12
- package/scripts/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +9 -2
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-context-index.cjs +448 -0
- package/scripts/gen-inventory-manifest.cjs +101 -1
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +39 -15
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lint-allow-test-rule-refs.allowlist.json +17 -31
- package/scripts/lint-compiled-artifact-sync.cjs +6 -1
- package/scripts/lint-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-test-file-count.allowlist.json +27 -1
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/prompt-injection-scan.sh +27 -6
- package/scripts/registry-schema.cjs +323 -94
- package/scripts/run-tests.cjs +3 -2
- package/scripts/validate-registry.cjs +10 -6
- package/skills/gsd-autonomous/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +2 -2
- package/vscode/package.json +1 -1
- package/scripts/gen-emitted-baseline.cjs +0 -145
|
@@ -63,6 +63,8 @@
|
|
|
63
63
|
"workflow.context_guard_mode",
|
|
64
64
|
"executor.stall_detect_interval_minutes",
|
|
65
65
|
"executor.stall_threshold_minutes",
|
|
66
|
+
"planner.stall_detect_interval_minutes",
|
|
67
|
+
"planner.stall_threshold_minutes",
|
|
66
68
|
"workflow.inline_plan_threshold",
|
|
67
69
|
"hooks.context_warnings",
|
|
68
70
|
"hooks.workflow_guard",
|
|
@@ -43,6 +43,13 @@ reads is inert — the consumption mechanism is what gives an artifact meaning.
|
|
|
43
43
|
- **Lifecycle**: Created at plan completion → Read by subsequent plans in same phase
|
|
44
44
|
- **Location**: `.planning/phases/XX-name/XX-YY-SUMMARY.md`
|
|
45
45
|
- **Consumed by**: Orchestrator (progress), planner (context for future plans), `milestone-summary`
|
|
46
|
+
- **`status:`** — `complete` (default) or **`halted`**. `halted` records a *designed stop*:
|
|
47
|
+
the plan ran and answered its question, but the answer means the work it was gating cannot
|
|
48
|
+
proceed (a spike that returns "no", for example). It is a success, not a failure — the plan
|
|
49
|
+
did its job. Marking a SUMMARY `halted` propagates transitively over `depends_on`: every
|
|
50
|
+
plan that depends on it, directly or through a chain, is reported as **blocked** rather than
|
|
51
|
+
offered to the executor as ordinary incomplete work, and is named with its cause. Any other
|
|
52
|
+
value — including no `status:` field at all — reads as complete. (#2830)
|
|
46
53
|
|
|
47
54
|
### HANDOFF.json / .continue-here.md
|
|
48
55
|
- **Shape**: Structured pause state (JSON machine-readable + Markdown human-readable)
|
|
@@ -72,11 +79,11 @@ reads is inert — the consumption mechanism is what gives an artifact meaning.
|
|
|
72
79
|
- **Location**: `.planning/spikes/SPIKE-NNN/`
|
|
73
80
|
- **Consumed by**: Planner when spike is referenced; `pause-work` for spike context handoff
|
|
74
81
|
|
|
75
|
-
### Spike README.md / MANIFEST.md (per-
|
|
76
|
-
- **Shape**: YAML frontmatter (spike, name, validates, verdict, related, tags) + run instructions + results
|
|
82
|
+
### Spike README.md (per-spike) / MANIFEST.md (per-project index, via /gsd:spike)
|
|
83
|
+
- **Shape**: README — YAML frontmatter (spike, idea, name, validates, verdict, related, tags) + run instructions + results. MANIFEST.md — one `### {idea-key}` section per idea under `## Ideas` (idea paragraph + its own scoped Requirements), plus one durable `## Spikes` table (with an Idea column) indexing every spike across every idea.
|
|
77
84
|
- **Lifecycle**: Created by `/gsd:spike` → Verified → Wrapped up by `/gsd-spike-wrap-up`
|
|
78
85
|
- **Location**: `.planning/spikes/NNN-name/README.md`, `.planning/spikes/MANIFEST.md`
|
|
79
|
-
- **Consumed by**: `/gsd-spike-wrap-up` for curation; `pause-work` for spike context handoff
|
|
86
|
+
- **Consumed by**: `/gsd-spike-wrap-up` for curation (Requirements pulled only from the idea key(s) it wraps); `pause-work` for spike context handoff
|
|
80
87
|
|
|
81
88
|
### Sketch README.md / MANIFEST.md / index.html (per-sketch)
|
|
82
89
|
- **Shape**: YAML frontmatter (sketch, name, question, winner, tags) + variants as tabbed HTML
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# UI Design Contract (Frontend Phases) — Autonomous Mode
|
|
2
|
+
|
|
3
|
+
Step 3a.5 of `/gsd:autonomous`: resolve whether the current phase needs a UI-SPEC.md generated before planning, and generate one via active `plan:pre` step hooks if so. Always non-blocking — proceeds to step 3b (Plan) regardless of outcome.
|
|
4
|
+
|
|
5
|
+
**Inputs:** `PHASE_NUM`, `PHASE_DIR` from execute_phase.
|
|
6
|
+
|
|
7
|
+
Resolve active `plan:pre` hooks:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
11
|
+
HOOKS_JSON=$(gsd_run loop render-hooks plan:pre --raw)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Read the `activeHooks` array directly from `HOOKS_JSON` (in-context — do NOT invoke a shell pipeline). **Compute the active UI step hooks** = entries from `activeHooks` where `kind == "step"` and `ref.skill` is set. **If there are NO active step hooks → skip silently to 3b.** (This covers `workflow.ui_phase=false` — including configurations where only a gate-only entry is present, e.g. `ui_phase=false` + `ui_safety_gate=true` produces `activeHooks=[{kind:"gate"}]`. Autonomous never runs the plan:pre gate — it is always pipeline mode — so a gate-only active set is equivalent to no active step and is silently skipped here. This matches OLD §3a.5 behaviour.)
|
|
15
|
+
|
|
16
|
+
(At least one active step hook ⇒ `workflow.ui_phase` is on.) Run the UI-SPEC gate:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
GATE=$(gsd_run check ui-plan-gate "${PHASE_NUM}" --raw)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Read `frontend` and `hasUiSpec` from `GATE` (in-context).
|
|
23
|
+
|
|
24
|
+
**If `frontend` is false:** Skip silently to 3b.
|
|
25
|
+
|
|
26
|
+
**If `hasUiSpec` is true (UI-SPEC already exists):** Skip silently to 3b.
|
|
27
|
+
|
|
28
|
+
**Otherwise (frontend phase + no UI-SPEC):** For each active step hook (the `kind == "step"` set from above, in array order):
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Skill(skill="gsd-${ref.skill}", args="${PHASE_NUM}")
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
(Prepend `gsd-` to `ref.skill` — so `ui-phase` → `gsd-ui-phase`. Bare `${PHASE_NUM}` args — autonomous style, same pattern as the verify:post dispatch.) Entries where `kind == "gate"` are silently ignored — autonomous is always pipeline mode, there is no blocking gate here.
|
|
35
|
+
|
|
36
|
+
After all step hooks return, re-read:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**If `UI_SPEC_FILE` is still empty:** Display warning `Phase ${PHASE_NUM}: UI-SPEC generation did not produce output — continuing without design contract.` and proceed to 3b. NON-BLOCKING.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Debugger technique catalog
|
|
2
|
+
|
|
3
|
+
Full technique bodies for `agents/gsd-debugger.md`, extracted per
|
|
4
|
+
`DEFECT.AGENT-FILE-SIZE-CAP-BREACH` (issue #2995, epic #1671 Phase 6.4). The agent
|
|
5
|
+
keeps each technique's name and routing entry; the step-by-step detail lives here.
|
|
6
|
+
|
|
7
|
+
## Binary Search / Divide and Conquer
|
|
8
|
+
|
|
9
|
+
**When:** Large codebase, long execution path, many possible failure points.
|
|
10
|
+
|
|
11
|
+
**How:** Cut problem space in half repeatedly until you isolate the issue.
|
|
12
|
+
|
|
13
|
+
1. Identify boundaries (where works, where fails)
|
|
14
|
+
2. Add logging/testing at midpoint
|
|
15
|
+
3. Determine which half contains the bug
|
|
16
|
+
4. Repeat until you find exact line
|
|
17
|
+
|
|
18
|
+
**Example:** API returns wrong data
|
|
19
|
+
- Test: Data leaves database correctly? YES
|
|
20
|
+
- Test: Data reaches frontend correctly? NO
|
|
21
|
+
- Test: Data leaves API route correctly? YES
|
|
22
|
+
- Test: Data survives serialization? NO
|
|
23
|
+
- **Found:** Bug in serialization layer (4 tests eliminated 90% of code)
|
|
24
|
+
|
|
25
|
+
## Rubber Duck Debugging
|
|
26
|
+
|
|
27
|
+
**When:** Stuck, confused, mental model doesn't match reality.
|
|
28
|
+
|
|
29
|
+
**How:** Explain the problem out loud in complete detail.
|
|
30
|
+
|
|
31
|
+
Write or say:
|
|
32
|
+
1. "The system should do X"
|
|
33
|
+
2. "Instead it does Y"
|
|
34
|
+
3. "I think this is because Z"
|
|
35
|
+
4. "The code path is: A -> B -> C -> D"
|
|
36
|
+
5. "I've verified that..." (list what you tested)
|
|
37
|
+
6. "I'm assuming that..." (list assumptions)
|
|
38
|
+
|
|
39
|
+
Often you'll spot the bug mid-explanation: "Wait, I never verified that B returns what I think it does."
|
|
40
|
+
|
|
41
|
+
## Delta Debugging
|
|
42
|
+
|
|
43
|
+
**When:** Large change set is suspected (many commits, a big refactor, or a complex feature that broke something). Also when "comment out everything" is too slow.
|
|
44
|
+
|
|
45
|
+
**How:** Binary search over the change space — not just the code, but the commits, configs, and inputs.
|
|
46
|
+
|
|
47
|
+
**Over commits (use git bisect):**
|
|
48
|
+
Already covered under Git Bisect. But delta debugging extends it: after finding the breaking commit, delta-debug the commit itself — identify which of its N changed files/lines actually causes the failure.
|
|
49
|
+
|
|
50
|
+
**Over code (systematic elimination):**
|
|
51
|
+
1. Identify the boundary: a known-good state (commit, config, input) vs the broken state
|
|
52
|
+
2. List all differences between good and bad states
|
|
53
|
+
3. Split the differences in half. Apply only half to the good state.
|
|
54
|
+
4. If broken: bug is in the applied half. If not: bug is in the other half.
|
|
55
|
+
5. Repeat until you have the minimal change set that causes the failure.
|
|
56
|
+
|
|
57
|
+
**Over inputs:**
|
|
58
|
+
1. Find a minimal input that triggers the bug (strip out unrelated data fields)
|
|
59
|
+
2. The minimal input reveals which code path is exercised
|
|
60
|
+
|
|
61
|
+
**When to use:**
|
|
62
|
+
- "This worked yesterday, something changed" → delta debug commits
|
|
63
|
+
- "Works with small data, fails with real data" → delta debug inputs
|
|
64
|
+
- "Works without this config change, fails with it" → delta debug config diff
|
|
65
|
+
|
|
66
|
+
**Example:** 40-file commit introduces bug
|
|
67
|
+
```
|
|
68
|
+
Split into two 20-file halves.
|
|
69
|
+
Apply first 20: still works → bug in second half.
|
|
70
|
+
Split second half into 10+10.
|
|
71
|
+
Apply first 10: broken → bug in first 10.
|
|
72
|
+
... 6 splits later: single file isolated.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Minimal Reproduction
|
|
76
|
+
|
|
77
|
+
**When:** Complex system, many moving parts, unclear which part fails.
|
|
78
|
+
|
|
79
|
+
**How:** Strip away everything until smallest possible code reproduces the bug.
|
|
80
|
+
|
|
81
|
+
1. Copy failing code to new file
|
|
82
|
+
2. Remove one piece (dependency, function, feature)
|
|
83
|
+
3. Test: Does it still reproduce? YES = keep removed. NO = put back.
|
|
84
|
+
4. Repeat until bare minimum
|
|
85
|
+
5. Bug is now obvious in stripped-down code
|
|
86
|
+
6. **Shrinking (input-space bugs)** — when the bug triggers on a class of inputs, wrap it in a property (fast-check for JS/TS, Hypothesis for Python) and let the shrinker auto-minimize the counterexample; store the **minimized** input as the regression seed. See `gsd-core/references/debugger-repro-hardening.md`.
|
|
87
|
+
|
|
88
|
+
**Example:**
|
|
89
|
+
```jsx
|
|
90
|
+
// Start: 500-line React component with 15 props, 8 hooks, 3 contexts
|
|
91
|
+
// End after stripping:
|
|
92
|
+
function MinimalRepro() {
|
|
93
|
+
const [count, setCount] = useState(0);
|
|
94
|
+
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
setCount(count + 1); // Bug: infinite loop, missing dependency array
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return <div>{count}</div>;
|
|
100
|
+
}
|
|
101
|
+
// The bug was hidden in complexity. Minimal reproduction made it obvious.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Working Backwards
|
|
105
|
+
|
|
106
|
+
**When:** You know correct output, don't know why you're not getting it.
|
|
107
|
+
|
|
108
|
+
**How:** Start from desired end state, trace backwards.
|
|
109
|
+
|
|
110
|
+
1. Define desired output precisely
|
|
111
|
+
2. What function produces this output?
|
|
112
|
+
3. Test that function with expected input - does it produce correct output?
|
|
113
|
+
- YES: Bug is earlier (wrong input)
|
|
114
|
+
- NO: Bug is here
|
|
115
|
+
4. Repeat backwards through call stack
|
|
116
|
+
5. Find divergence point (where expected vs actual first differ)
|
|
117
|
+
|
|
118
|
+
**Example:** UI shows "User not found" when user exists
|
|
119
|
+
```
|
|
120
|
+
Trace backwards:
|
|
121
|
+
1. UI displays: user.error → Is this the right value to display? YES
|
|
122
|
+
2. Component receives: user.error = "User not found" → Correct? NO, should be null
|
|
123
|
+
3. API returns: { error: "User not found" } → Why?
|
|
124
|
+
4. Database query: SELECT * FROM users WHERE id = 'undefined' → AH!
|
|
125
|
+
5. FOUND: User ID is 'undefined' (string) instead of a number
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Differential Debugging
|
|
129
|
+
|
|
130
|
+
**When:** Something used to work and now doesn't. Works in one environment but not another.
|
|
131
|
+
|
|
132
|
+
**Time-based (worked, now doesn't):**
|
|
133
|
+
- What changed in code since it worked?
|
|
134
|
+
- What changed in environment? (Node version, OS, dependencies)
|
|
135
|
+
- What changed in data?
|
|
136
|
+
- What changed in configuration?
|
|
137
|
+
|
|
138
|
+
**Environment-based (works in dev, fails in prod):**
|
|
139
|
+
- Configuration values
|
|
140
|
+
- Environment variables
|
|
141
|
+
- Network conditions (latency, reliability)
|
|
142
|
+
- Data volume
|
|
143
|
+
- Third-party service behavior
|
|
144
|
+
|
|
145
|
+
**Process:** List differences, test each in isolation, find the difference that causes failure.
|
|
146
|
+
|
|
147
|
+
**Example:** Works locally, fails in CI
|
|
148
|
+
```
|
|
149
|
+
Differences:
|
|
150
|
+
- Node version: Same ✓
|
|
151
|
+
- Environment variables: Same ✓
|
|
152
|
+
- Timezone: Different! ✗
|
|
153
|
+
|
|
154
|
+
Test: Set local timezone to UTC (like CI)
|
|
155
|
+
Result: Now fails locally too
|
|
156
|
+
FOUND: Date comparison logic assumes local timezone
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Observability First
|
|
160
|
+
|
|
161
|
+
**When:** Always. Before making any fix.
|
|
162
|
+
|
|
163
|
+
**Add visibility before changing behavior:**
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
// Strategic logging (useful):
|
|
167
|
+
console.log('[handleSubmit] Input:', { email, password: '***' });
|
|
168
|
+
console.log('[handleSubmit] Validation result:', validationResult);
|
|
169
|
+
console.log('[handleSubmit] API response:', response);
|
|
170
|
+
|
|
171
|
+
// Assertion checks:
|
|
172
|
+
console.assert(user !== null, 'User is null!');
|
|
173
|
+
console.assert(user.id !== undefined, 'User ID is undefined!');
|
|
174
|
+
|
|
175
|
+
// Timing measurements:
|
|
176
|
+
console.time('Database query');
|
|
177
|
+
const result = await db.query(sql);
|
|
178
|
+
console.timeEnd('Database query');
|
|
179
|
+
|
|
180
|
+
// Stack traces at key points:
|
|
181
|
+
console.log('[updateUser] Called from:', new Error().stack);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Workflow:** Add logging -> Run code -> Observe output -> Form hypothesis -> Then make changes.
|
|
185
|
+
|
|
186
|
+
## Comment Out Everything
|
|
187
|
+
|
|
188
|
+
**When:** Many possible interactions, unclear which code causes issue.
|
|
189
|
+
|
|
190
|
+
**How:**
|
|
191
|
+
1. Comment out everything in function/file
|
|
192
|
+
2. Verify bug is gone
|
|
193
|
+
3. Uncomment one piece at a time
|
|
194
|
+
4. After each uncomment, test
|
|
195
|
+
5. When bug returns, you found the culprit
|
|
196
|
+
|
|
197
|
+
**Example:** Some middleware breaks requests, but you have 8 middleware functions
|
|
198
|
+
```javascript
|
|
199
|
+
app.use(helmet()); // Uncomment, test → works
|
|
200
|
+
app.use(cors()); // Uncomment, test → works
|
|
201
|
+
app.use(compression()); // Uncomment, test → works
|
|
202
|
+
app.use(bodyParser.json({ limit: '50mb' })); // Uncomment, test → BREAKS
|
|
203
|
+
// FOUND: Body size limit too high causes memory issues
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Git Bisect
|
|
207
|
+
|
|
208
|
+
**When:** Feature worked in past, broke at unknown commit.
|
|
209
|
+
|
|
210
|
+
**How:** Binary search through git history.
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
git bisect start
|
|
214
|
+
git bisect bad # Current commit is broken
|
|
215
|
+
git bisect good abc123 # This commit worked
|
|
216
|
+
# Git checks out middle commit
|
|
217
|
+
git bisect bad # or good, based on testing
|
|
218
|
+
# Repeat until culprit found
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
100 commits between working and broken: ~7 tests to find exact breaking commit.
|
|
222
|
+
|
|
223
|
+
## Follow the Indirection
|
|
224
|
+
|
|
225
|
+
**When:** Code constructs paths, URLs, keys, or references from variables — and the constructed value might not point where you expect.
|
|
226
|
+
|
|
227
|
+
**The trap:** You read code that builds a path like `path.join(configDir, 'hooks')` and assume it's correct because it looks reasonable. But you never verified that the constructed path matches where another part of the system actually writes/reads.
|
|
228
|
+
|
|
229
|
+
**How:**
|
|
230
|
+
1. Find the code that **produces** the value (writer/installer/creator)
|
|
231
|
+
2. Find the code that **consumes** the value (reader/checker/validator)
|
|
232
|
+
3. Trace the actual resolved value in both — do they agree?
|
|
233
|
+
4. Check every variable in the path construction — where does each come from? What's its actual value at runtime?
|
|
234
|
+
|
|
235
|
+
**Common indirection bugs:**
|
|
236
|
+
- Path A writes to `dir/sub/hooks/` but Path B checks `dir/hooks/` (directory mismatch)
|
|
237
|
+
- Config value comes from cache/template that wasn't updated
|
|
238
|
+
- Variable is derived differently in two places (e.g., one adds a subdirectory, the other doesn't)
|
|
239
|
+
- Template placeholder (`{{VERSION}}`) not substituted in all code paths
|
|
240
|
+
|
|
241
|
+
**Example:** Stale hook warning persists after update
|
|
242
|
+
```
|
|
243
|
+
Check code says: hooksDir = path.join(configDir, 'hooks')
|
|
244
|
+
configDir = ~/.claude
|
|
245
|
+
→ checks ~/.claude/hooks/
|
|
246
|
+
|
|
247
|
+
Installer says: hooksDest = path.join(targetDir, 'hooks')
|
|
248
|
+
targetDir = ~/.claude/gsd-core
|
|
249
|
+
→ writes to ~/.claude/gsd-core/hooks/
|
|
250
|
+
|
|
251
|
+
MISMATCH: Checker looks in wrong directory → hooks "not found" → reported as stale
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**The discipline:** Never assume a constructed path is correct. Resolve it to its actual value and verify the other side agrees. When two systems share a resource (file, directory, key), trace the full path in both.
|
|
255
|
+
|
|
@@ -2,10 +2,12 @@ When you need library or framework documentation, check in this order:
|
|
|
2
2
|
|
|
3
3
|
1. If Context7 MCP tools (`mcp__context7__*`) are available in your environment, use them:
|
|
4
4
|
- Resolve library ID: `mcp__context7__resolve-library-id` with `libraryName`
|
|
5
|
-
- Fetch docs: `
|
|
5
|
+
- Fetch docs: `mcp__context7__query-docs` with `libraryId` (the ID from step 1) and `query`
|
|
6
6
|
|
|
7
|
-
2. If Context7 MCP is not available (
|
|
8
|
-
|
|
7
|
+
2. If Context7 MCP is not available (custom subagents cannot see project-scoped
|
|
8
|
+
`.mcp.json` servers — they only inherit user-scoped `~/.claude/mcp.json`, so a
|
|
9
|
+
context7 server configured at the project scope is invisible to spawned
|
|
10
|
+
agents), use the CLI fallback via Bash:
|
|
9
11
|
|
|
10
12
|
Step 1 — Resolve library ID:
|
|
11
13
|
```bash
|
|
@@ -119,16 +119,17 @@ if [ "$APPLICABLE" = "0" ]; then
|
|
|
119
119
|
fi
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
**Edge `--auto` resolution rules (reuse spec-phase 5.5 verbatim, D-06):** auto-`
|
|
123
|
-
defensible acceptance criterion can be written (→ a plain
|
|
124
|
-
auto-`
|
|
122
|
+
**Edge `--auto` resolution rules (reuse spec-phase 5.5 verbatim, D-06):** auto-`resolved`
|
|
123
|
+
(verification: explicit) where a defensible acceptance criterion can be written (→ a plain
|
|
124
|
+
`must_haves.truths` string); else auto-`resolved` (verification: backstop) → author it as a
|
|
125
|
+
**structured flat-scalar marker** `{ statement: <the check>,
|
|
125
126
|
verification: backstop }` in `must_haves.truths`, NOT a prose note (the verifier branches
|
|
126
127
|
deterministically on the `verification: backstop` field; a parenthetical is unparseable — the #1110
|
|
127
128
|
fragility; flat scalar `verification:` key, never a nested object, ADR-550 #1278). A `backstop` truth
|
|
128
129
|
the verifier cannot confirm with explicit evidence abstains → `human_needed` (reason
|
|
129
130
|
`insufficient_spec`), never a silent pass (#1154; `references/honest-verifier.md`). **Never
|
|
130
131
|
auto-dismiss** (a wrong dismissal is the exact silent failure this eliminates). An `unclassified` row
|
|
131
|
-
stays **`unresolved`** (#1110) — never auto
|
|
132
|
+
stays **`unresolved`** (#1110) — never auto-resolved with backstop — and is surfaced to the planner as a flagged
|
|
132
133
|
assumption. Pass `$COVERAGE` (+ the gate's `$SPECLESS_FALLBACK_DISABLED` note) into the gsd-planner
|
|
133
134
|
prompt (Step 8). When `EDGE_ABSENT=0`, `$COVERAGE` is empty and this does not run.
|
|
134
135
|
|
|
@@ -159,8 +160,8 @@ assumption — never a silent drop.
|
|
|
159
160
|
Author the fallback report into `must_haves` with the SAME lift the SPEC path uses — only the source
|
|
160
161
|
changes (the fallback report, not the SPEC):
|
|
161
162
|
|
|
162
|
-
- **Edges →** every
|
|
163
|
-
every
|
|
163
|
+
- **Edges →** every resolved (verification: explicit) edge's acceptance criterion → `must_haves.truths` as a plain string;
|
|
164
|
+
every resolved (verification: backstop) edge → `must_haves.truths` as a structured `{ statement, verification: backstop }`
|
|
164
165
|
marker (NOT prose; #1110/#1278), which abstains → `human_needed` at verify time when unconfirmed
|
|
165
166
|
(#1154); every `unresolved`/`unclassified` row → an explicit flagged assumption (never a silent drop).
|
|
166
167
|
- **Prohibitions →** every kept prohibition → the `must_haves.prohibitions:` sibling block (NOT
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Verifier wiring and data-flow patterns
|
|
2
|
+
|
|
3
|
+
Full pattern bodies for `agents/gsd-verifier.md`, extracted per
|
|
4
|
+
`DEFECT.AGENT-FILE-SIZE-CAP-BREACH` (issue #2995, epic #1671 Phase 6.4). The agent
|
|
5
|
+
keeps the step and its checklist; the per-pattern detail and shell recipes live here.
|
|
6
|
+
|
|
7
|
+
Artifacts that pass Levels 1-3 (exist, substantive, wired) can still be hollow if their data source produces empty or hardcoded values. Level 4 traces upstream from the artifact to verify real data flows through the wiring.
|
|
8
|
+
|
|
9
|
+
**When to run:** For each artifact that passes Level 3 (WIRED) and renders dynamic data (components, pages, dashboards — not utilities or configs).
|
|
10
|
+
|
|
11
|
+
**How:**
|
|
12
|
+
|
|
13
|
+
1. **Identify the data variable** — what state/prop does the artifact render?
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Find state variables that are rendered in JSX/TSX
|
|
17
|
+
grep -n -E "useState|useQuery|useSWR|useStore|props\." "$artifact" 2>/dev/null
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
2. **Trace the data source** — where does that variable get populated?
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Find the fetch/query that populates the state
|
|
24
|
+
grep -n -A 5 "set${STATE_VAR}\|${STATE_VAR}\s*=" "$artifact" 2>/dev/null | grep -E "fetch|axios|query|store|dispatch|props\."
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
3. **Verify the source produces real data** — does the API/store return actual data or static/empty values?
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Check the API route or data source for real DB queries vs static returns
|
|
31
|
+
grep -n -E "prisma\.|db\.|query\(|findMany|findOne|select|FROM" "$source_file" 2>/dev/null
|
|
32
|
+
# Flag: static returns with no query
|
|
33
|
+
grep -n -E "return.*json\(\s*\[\]|return.*json\(\s*\{\}" "$source_file" 2>/dev/null
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
4. **Check for disconnected props** — props passed to child components that are hardcoded empty at the call site
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Find where the component is used and check prop values
|
|
40
|
+
grep -r -A 3 "<${COMPONENT_NAME}" "${search_path:-src/}" --include="*.tsx" 2>/dev/null | grep -E "=\{(\[\]|\{\}|null|''|\"\")\}"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> These two status tables are intentionally mirrored in `agents/gsd-verifier.md`.
|
|
44
|
+
> The status vocabulary is load-bearing verifier output and must remain in the
|
|
45
|
+
> agent body (#2995); this copy is here so the procedure below reads standalone.
|
|
46
|
+
|
|
47
|
+
**Data-flow status:**
|
|
48
|
+
|
|
49
|
+
| Data Source | Produces Real Data | Status |
|
|
50
|
+
| ---------- | ------------------ | ------ |
|
|
51
|
+
| DB query found | Yes | ✓ FLOWING |
|
|
52
|
+
| Fetch exists, static fallback only | No | ⚠️ STATIC |
|
|
53
|
+
| No data source found | N/A | ✗ DISCONNECTED |
|
|
54
|
+
| Props hardcoded empty at call site | No | ✗ HOLLOW_PROP |
|
|
55
|
+
|
|
56
|
+
**Final Artifact Status (updated with Level 4):**
|
|
57
|
+
|
|
58
|
+
| Exists | Substantive | Wired | Data Flows | Status |
|
|
59
|
+
| ------ | ----------- | ----- | ---------- | ------ |
|
|
60
|
+
| ✓ | ✓ | ✓ | ✓ | ✓ VERIFIED |
|
|
61
|
+
| ✓ | ✓ | ✓ | ✗ | ⚠️ HOLLOW — wired but data disconnected |
|
|
62
|
+
| ✓ | ✓ | ✗ | - | ⚠️ ORPHANED |
|
|
63
|
+
| ✓ | ✗ | - | - | ✗ STUB |
|
|
64
|
+
| ✗ | - | - | - | ✗ MISSING |
|
|
65
|
+
|
|
66
|
+
### Pattern: Component → API
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
grep -E "fetch\(['\"].*$api_path|axios\.(get|post).*$api_path" "$component" 2>/dev/null
|
|
70
|
+
grep -A 5 "fetch\|axios" "$component" | grep -E "await|\.then|setData|setState" 2>/dev/null
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Status: WIRED (call + response handling) | PARTIAL (call, no response use) | NOT_WIRED (no call)
|
|
74
|
+
|
|
75
|
+
### Pattern: API → Database
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
grep -E "prisma\.$model|db\.$model|$model\.(find|create|update|delete)" "$route" 2>/dev/null
|
|
79
|
+
grep -E "return.*json.*\w+|res\.json\(\w+" "$route" 2>/dev/null
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Status: WIRED (query + result returned) | PARTIAL (query, static return) | NOT_WIRED (no query)
|
|
83
|
+
|
|
84
|
+
### Pattern: Form → Handler
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
grep -E "onSubmit=\{|handleSubmit" "$component" 2>/dev/null
|
|
88
|
+
grep -A 10 "onSubmit.*=" "$component" | grep -E "fetch|axios|mutate|dispatch" 2>/dev/null
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Status: WIRED (handler + API call) | STUB (only logs/preventDefault) | NOT_WIRED (no handler)
|
|
92
|
+
|
|
93
|
+
### Pattern: State → Render
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
grep -E "useState.*$state_var|\[$state_var," "$component" 2>/dev/null
|
|
97
|
+
grep -E "\{.*$state_var.*\}|\{$state_var\." "$component" 2>/dev/null
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Status: WIRED (state displayed) | NOT_WIRED (state exists, not rendered)
|
|
@@ -30,8 +30,8 @@ if [ "$HEAD_REF" = "DETACHED" ] || echo "$ACTUAL_BRANCH" | grep -Eq '^(main|mast
|
|
|
30
30
|
echo "FATAL: worktree HEAD on '$ACTUAL_BRANCH' (expected agent-* or worktree-agent-*); refusing to commit or self-recover via 'git update-ref' (#2924)." >&2
|
|
31
31
|
exit 42
|
|
32
32
|
fi
|
|
33
|
-
if ! echo "$ACTUAL_BRANCH" | grep -Eq '^(worktree-)?agent-[A-Za-z0-9._/-]+$'; then
|
|
34
|
-
echo "FATAL: worktree HEAD '$ACTUAL_BRANCH' is not in the agent-* / worktree-agent-* namespace; refusing to commit (#2924)." >&2
|
|
33
|
+
if ! echo "$ACTUAL_BRANCH" | grep -Eq '^((worktree-)?agent-|worktree-wf_)[A-Za-z0-9._/-]+$'; then
|
|
34
|
+
echo "FATAL: worktree HEAD '$ACTUAL_BRANCH' is not in the agent-* / worktree-agent-* / worktree-wf_* namespace; refusing to commit (#2924)." >&2
|
|
35
35
|
exit 42
|
|
36
36
|
fi
|
|
37
37
|
ACTUAL_BASE=$(git rev-parse HEAD)
|
|
@@ -28,6 +28,8 @@ completed: YYYY-MM-DD
|
|
|
28
28
|
status: complete
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
+
**Status (#2830):** `status: complete` is the default — the plan finished. Use `status: halted` instead when the plan reached a designed stop (a gate failure, a spike concluding without expanding into the full build, or any other intentional non-completion) and intentionally left tasks unfinished.
|
|
32
|
+
|
|
31
33
|
# Phase [X]: [Name] Summary (Complex)
|
|
32
34
|
|
|
33
35
|
**[Substantive one-liner describing outcome]**
|
|
@@ -25,6 +25,8 @@ completed: YYYY-MM-DD
|
|
|
25
25
|
status: complete
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
+
**Status (#2830):** `status: complete` is the default — the plan finished. Use `status: halted` instead when the plan reached a designed stop (a gate failure, a spike concluding without expanding into the full build, or any other intentional non-completion) and intentionally left tasks unfinished.
|
|
29
|
+
|
|
28
30
|
# Phase [X]: [Name] Summary (Minimal)
|
|
29
31
|
|
|
30
32
|
**[Substantive one-liner describing outcome]**
|
|
@@ -27,6 +27,8 @@ completed: YYYY-MM-DD
|
|
|
27
27
|
status: complete
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
**Status (#2830):** `status: complete` is the default — the plan finished. Use `status: halted` instead when the plan reached a designed stop (a gate failure, a spike concluding without expanding into the full build, or any other intentional non-completion) and intentionally left tasks unfinished.
|
|
31
|
+
|
|
30
32
|
# Phase [X]: [Name] Summary
|
|
31
33
|
|
|
32
34
|
**[Substantive one-liner describing outcome]**
|
|
@@ -171,6 +171,8 @@ None - no external service configuration required.
|
|
|
171
171
|
**Patterns:** Established conventions future phases should maintain.
|
|
172
172
|
|
|
173
173
|
**Population:** Frontmatter is populated during summary creation in execute-plan.md. See `<step name="create_summary">` for field-by-field guidance.
|
|
174
|
+
|
|
175
|
+
**Status (#2830):** `status: complete` is the default — the plan finished. Use `status: halted` instead when the plan reached a designed stop (a gate failure, a spike concluding without expanding into the full build, or any other intentional non-completion) and intentionally left tasks unfinished. `halted` is machine-read: any plan whose `depends_on` (directly or transitively) names a halted plan is reported as blocked, not offered to the executor, until the halt is resolved and re-summarized as `complete`.
|
|
174
176
|
</frontmatter_guidance>
|
|
175
177
|
|
|
176
178
|
<coverage_guidance>
|
|
@@ -124,6 +124,9 @@ For each phase's VERIFICATION.md, extract the expanded requirements table:
|
|
|
124
124
|
|
|
125
125
|
For each phase's SUMMARY.md, extract `requirements-completed` from YAML frontmatter:
|
|
126
126
|
```bash
|
|
127
|
+
# #2962: zsh aborts the block on an unmatched for-list glob (nomatch); bash passes it through. nullglob both.
|
|
128
|
+
shopt -s nullglob 2>/dev/null; setopt NULL_GLOB 2>/dev/null
|
|
129
|
+
|
|
127
130
|
for summary in .planning/phases/*-*/*-SUMMARY.md; do
|
|
128
131
|
[ -e "$summary" ] || continue
|
|
129
132
|
gsd_run query summary-extract "$summary" --fields requirements_completed --pick requirements_completed
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
If `PLAN_STRATEGY` is `converge`, display: `Planning: Plan-review convergence enabled`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Converge Dispatch (Background)
|
|
2
|
+
|
|
3
|
+
If `PLAN_STRATEGY=converge`, print: `◆ Spawning background plan-convergence loop for phase ${PHASE_NUM}... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)`
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Agent(
|
|
7
|
+
description="Plan convergence phase ${PHASE_NUM}: ${PHASE_NAME}",
|
|
8
|
+
run_in_background=true,
|
|
9
|
+
prompt="Run plan convergence for phase ${PHASE_NUM}: Skill(skill=\"gsd-plan-review-convergence\", args=\"${PHASE_NUM} ${CONVERGENCE_ARGS}\")"
|
|
10
|
+
)
|
|
11
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Converge Fail-Fast
|
|
2
|
+
|
|
3
|
+
When `PLAN_STRATEGY` is `converge`, fail fast unless the existing convergence feature gate is enabled:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
7
|
+
if [ "$PLAN_STRATEGY" = "converge" ]; then
|
|
8
|
+
CONVERGENCE_ENABLED=$(gsd_run query config-get workflow.plan_review_convergence 2>/dev/null || echo "false")
|
|
9
|
+
if [ "$CONVERGENCE_ENABLED" != "true" ]; then
|
|
10
|
+
printf '%s\n' \
|
|
11
|
+
'gsd-autonomous --converge is disabled (workflow.plan_review_convergence=false).' \
|
|
12
|
+
'' \
|
|
13
|
+
'Enable plan convergence with:' \
|
|
14
|
+
'' \
|
|
15
|
+
' gsd config-set workflow.plan_review_convergence true' \
|
|
16
|
+
'' \
|
|
17
|
+
'Then re-run the autonomous command with --converge.'
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
fi
|
|
21
|
+
```
|