gsd-pi 2.28.0-dev.e19bf89 → 2.29.0-dev.23d50d0
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/README.md +24 -17
- package/dist/cli.js +15 -9
- package/dist/headless.js +4 -0
- package/dist/resource-loader.js +80 -8
- package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +217 -65
- package/dist/resources/extensions/gsd/auto-dispatch.ts +2 -2
- package/dist/resources/extensions/gsd/auto-post-unit.ts +53 -6
- package/dist/resources/extensions/gsd/auto-prompts.ts +27 -14
- package/dist/resources/extensions/gsd/auto-recovery.ts +33 -23
- package/dist/resources/extensions/gsd/auto-start.ts +25 -10
- package/dist/resources/extensions/gsd/auto-verification.ts +41 -7
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
- package/dist/resources/extensions/gsd/auto-worktree.ts +9 -0
- package/dist/resources/extensions/gsd/auto.ts +67 -22
- package/dist/resources/extensions/gsd/commands-handlers.ts +3 -11
- package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/dist/resources/extensions/gsd/commands.ts +75 -29
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-types.ts +13 -0
- package/dist/resources/extensions/gsd/doctor.ts +2 -6
- package/dist/resources/extensions/gsd/export.ts +28 -2
- package/dist/resources/extensions/gsd/gsd-db.ts +19 -0
- package/dist/resources/extensions/gsd/index.ts +2 -1
- package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
- package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/dist/resources/extensions/gsd/metrics.ts +17 -31
- package/dist/resources/extensions/gsd/paths.ts +17 -8
- package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
- package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/dist/resources/extensions/gsd/queue-order.ts +10 -11
- package/dist/resources/extensions/gsd/routing-history.ts +13 -17
- package/dist/resources/extensions/gsd/session-lock.ts +284 -0
- package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
- package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
- package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
- package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
- package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
- package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
- package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/dist/resources/extensions/gsd/types.ts +3 -0
- package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
- package/dist/resources/extensions/gsd/verification-evidence.ts +2 -0
- package/dist/resources/extensions/gsd/verification-gate.ts +13 -2
- package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/dist/resources/extensions/mcp-client/index.ts +459 -0
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
- package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
- package/dist/resources/extensions/remote-questions/notify.ts +1 -2
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
- package/dist/resources/extensions/remote-questions/types.ts +3 -0
- package/dist/resources/extensions/shared/mod.ts +3 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/dist/resources/skills/create-skill/SKILL.md +184 -0
- package/dist/resources/skills/create-skill/references/api-security.md +226 -0
- package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
- package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/package.json +6 -3
- package/packages/native/dist/native.d.ts +2 -0
- package/packages/native/dist/native.js +19 -5
- package/packages/native/src/native.ts +23 -9
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -1
- package/packages/pi-tui/dist/autocomplete.d.ts +3 -0
- package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/packages/pi-tui/dist/autocomplete.js +14 -0
- package/packages/pi-tui/dist/autocomplete.js.map +1 -1
- package/packages/pi-tui/src/autocomplete.ts +19 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +217 -65
- package/src/resources/extensions/gsd/auto-dispatch.ts +2 -2
- package/src/resources/extensions/gsd/auto-post-unit.ts +53 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +27 -14
- package/src/resources/extensions/gsd/auto-recovery.ts +33 -23
- package/src/resources/extensions/gsd/auto-start.ts +25 -10
- package/src/resources/extensions/gsd/auto-verification.ts +41 -7
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +9 -0
- package/src/resources/extensions/gsd/auto.ts +67 -22
- package/src/resources/extensions/gsd/commands-handlers.ts +3 -11
- package/src/resources/extensions/gsd/commands-logs.ts +536 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/src/resources/extensions/gsd/commands.ts +75 -29
- package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/src/resources/extensions/gsd/doctor-types.ts +13 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -6
- package/src/resources/extensions/gsd/export.ts +28 -2
- package/src/resources/extensions/gsd/gsd-db.ts +19 -0
- package/src/resources/extensions/gsd/index.ts +2 -1
- package/src/resources/extensions/gsd/json-persistence.ts +67 -0
- package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/src/resources/extensions/gsd/metrics.ts +17 -31
- package/src/resources/extensions/gsd/paths.ts +17 -8
- package/src/resources/extensions/gsd/preferences-models.ts +7 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/queue-order.ts +10 -11
- package/src/resources/extensions/gsd/routing-history.ts +13 -17
- package/src/resources/extensions/gsd/session-lock.ts +284 -0
- package/src/resources/extensions/gsd/session-status-io.ts +23 -41
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/src/resources/extensions/gsd/types.ts +3 -0
- package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
- package/src/resources/extensions/gsd/verification-evidence.ts +2 -0
- package/src/resources/extensions/gsd/verification-gate.ts +13 -2
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/src/resources/extensions/mcp-client/index.ts +459 -0
- package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
- package/src/resources/extensions/remote-questions/http-client.ts +76 -0
- package/src/resources/extensions/remote-questions/notify.ts +1 -2
- package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
- package/src/resources/extensions/remote-questions/types.ts +3 -0
- package/src/resources/extensions/shared/mod.ts +3 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/src/resources/skills/create-skill/SKILL.md +184 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/dist/resources/extensions/gsd/preferences-hooks.ts +0 -10
- package/dist/resources/extensions/mcporter/index.ts +0 -525
- package/dist/resources/extensions/shared/progress-widget.ts +0 -282
- package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
- package/src/resources/extensions/gsd/preferences-hooks.ts +0 -10
- package/src/resources/extensions/mcporter/index.ts +0 -525
- package/src/resources/extensions/shared/progress-widget.ts +0 -282
- package/src/resources/extensions/shared/thinking-widget.ts +0 -107
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanical Completion — deterministic post-verification artifact generation.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions that aggregate task-level outputs into slice/milestone summaries,
|
|
5
|
+
* UAT stubs, roadmap checkbox updates, and validation reports. Zero orchestration
|
|
6
|
+
* dependencies — operates on filesystem paths and parsed structures only.
|
|
7
|
+
*
|
|
8
|
+
* ADR-003: replaces LLM-driven complete-slice and validate-milestone units with
|
|
9
|
+
* mechanical aggregation when the data is sufficient.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { atomicWriteSync } from "./atomic-write.js";
|
|
15
|
+
import { loadFile, parseSummary } from "./files.js";
|
|
16
|
+
import { extractMarkdownSection } from "./auto-prompts.js";
|
|
17
|
+
import {
|
|
18
|
+
resolveTaskFiles,
|
|
19
|
+
resolveTaskJsonFiles,
|
|
20
|
+
resolveTasksDir,
|
|
21
|
+
resolveSliceFile,
|
|
22
|
+
resolveSlicePath,
|
|
23
|
+
resolveMilestoneFile,
|
|
24
|
+
resolveMilestonePath,
|
|
25
|
+
resolveGsdRootFile,
|
|
26
|
+
} from "./paths.js";
|
|
27
|
+
import type { Summary, SummaryFrontmatter } from "./types.js";
|
|
28
|
+
import type { EvidenceJSON } from "./verification-evidence.js";
|
|
29
|
+
|
|
30
|
+
// ─── Slice Completion ────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Mechanically complete a slice by aggregating task summaries into:
|
|
34
|
+
* - S##-SUMMARY.md (aggregated frontmatter + task one-liners)
|
|
35
|
+
* - S##-UAT.md (extracted from plan Verification section)
|
|
36
|
+
* - Roadmap checkbox [x] update
|
|
37
|
+
*
|
|
38
|
+
* Returns true if completion succeeded, false if data is insufficient
|
|
39
|
+
* (serves as quality gate — caller falls back to LLM completion).
|
|
40
|
+
*/
|
|
41
|
+
export async function mechanicalSliceCompletion(
|
|
42
|
+
base: string, mid: string, sid: string,
|
|
43
|
+
): Promise<boolean> {
|
|
44
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
45
|
+
if (!tDir) return false;
|
|
46
|
+
|
|
47
|
+
// Read all task summaries
|
|
48
|
+
const summaryFiles = resolveTaskFiles(tDir, "SUMMARY");
|
|
49
|
+
if (summaryFiles.length === 0) return false;
|
|
50
|
+
|
|
51
|
+
const taskSummaries: Array<{ taskId: string; summary: Summary }> = [];
|
|
52
|
+
for (const file of summaryFiles) {
|
|
53
|
+
const content = readFileSync(join(tDir, file), "utf-8");
|
|
54
|
+
if (!content.trim()) continue;
|
|
55
|
+
const summary = parseSummary(content);
|
|
56
|
+
const taskId = file.match(/^(T\d+)/)?.[1] ?? file;
|
|
57
|
+
taskSummaries.push({ taskId, summary });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (taskSummaries.length === 0) return false;
|
|
61
|
+
|
|
62
|
+
// Quality gate: multi-task slices need substantive summaries
|
|
63
|
+
if (taskSummaries.length > 1) {
|
|
64
|
+
const totalContent = taskSummaries
|
|
65
|
+
.map(ts => ts.summary.whatHappened || ts.summary.oneLiner || "")
|
|
66
|
+
.join("");
|
|
67
|
+
if (totalContent.length < 200) return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Aggregate frontmatter
|
|
71
|
+
const aggregated = aggregateFrontmatter(taskSummaries.map(ts => ts.summary.frontmatter));
|
|
72
|
+
|
|
73
|
+
// Build SUMMARY.md
|
|
74
|
+
const summaryLines: string[] = [
|
|
75
|
+
"---",
|
|
76
|
+
`id: ${sid}`,
|
|
77
|
+
`parent: ${mid}`,
|
|
78
|
+
`milestone: ${mid}`,
|
|
79
|
+
];
|
|
80
|
+
if (aggregated.provides.length > 0)
|
|
81
|
+
summaryLines.push(`provides:\n${aggregated.provides.map(p => ` - ${p}`).join("\n")}`);
|
|
82
|
+
if (aggregated.key_files.length > 0)
|
|
83
|
+
summaryLines.push(`key_files:\n${aggregated.key_files.map(f => ` - ${f}`).join("\n")}`);
|
|
84
|
+
if (aggregated.key_decisions.length > 0)
|
|
85
|
+
summaryLines.push(`key_decisions:\n${aggregated.key_decisions.map(d => ` - ${d}`).join("\n")}`);
|
|
86
|
+
if (aggregated.patterns_established.length > 0)
|
|
87
|
+
summaryLines.push(`patterns_established:\n${aggregated.patterns_established.map(p => ` - ${p}`).join("\n")}`);
|
|
88
|
+
if (aggregated.affects.length > 0)
|
|
89
|
+
summaryLines.push(`affects:\n${aggregated.affects.map(a => ` - ${a}`).join("\n")}`);
|
|
90
|
+
if (aggregated.observability_surfaces.length > 0)
|
|
91
|
+
summaryLines.push(`observability_surfaces:\n${aggregated.observability_surfaces.map(o => ` - ${o}`).join("\n")}`);
|
|
92
|
+
const allPassed = taskSummaries.every(ts => ts.summary.frontmatter.verification_result === "passed");
|
|
93
|
+
summaryLines.push(`verification_result: ${allPassed ? "passed" : "mixed"}`);
|
|
94
|
+
summaryLines.push(`completed_at: ${new Date().toISOString()}`);
|
|
95
|
+
summaryLines.push("---");
|
|
96
|
+
summaryLines.push("");
|
|
97
|
+
summaryLines.push(`# ${sid}: Slice Summary`);
|
|
98
|
+
summaryLines.push("");
|
|
99
|
+
|
|
100
|
+
// Task one-liners
|
|
101
|
+
for (const { taskId, summary } of taskSummaries) {
|
|
102
|
+
const line = summary.oneLiner || summary.title || taskId;
|
|
103
|
+
summaryLines.push(`- **${taskId}**: ${line}`);
|
|
104
|
+
}
|
|
105
|
+
summaryLines.push("");
|
|
106
|
+
|
|
107
|
+
const sDir = resolveSlicePath(base, mid, sid);
|
|
108
|
+
if (!sDir) return false;
|
|
109
|
+
|
|
110
|
+
const summaryPath = join(sDir, `${sid}-SUMMARY.md`);
|
|
111
|
+
atomicWriteSync(summaryPath, summaryLines.join("\n"));
|
|
112
|
+
process.stderr.write(`gsd-mechanical: wrote ${summaryPath}\n`);
|
|
113
|
+
|
|
114
|
+
// Build UAT.md from plan's Verification section
|
|
115
|
+
const planPath = resolveSliceFile(base, mid, sid, "PLAN");
|
|
116
|
+
if (planPath) {
|
|
117
|
+
const planContent = readFileSync(planPath, "utf-8");
|
|
118
|
+
const verification = extractMarkdownSection(planContent, "Verification");
|
|
119
|
+
if (verification) {
|
|
120
|
+
const uatContent = [
|
|
121
|
+
"---",
|
|
122
|
+
`id: ${sid}`,
|
|
123
|
+
`parent: ${mid}`,
|
|
124
|
+
"type: artifact-driven",
|
|
125
|
+
"---",
|
|
126
|
+
"",
|
|
127
|
+
`# ${sid}: UAT`,
|
|
128
|
+
"",
|
|
129
|
+
verification,
|
|
130
|
+
"",
|
|
131
|
+
].join("\n");
|
|
132
|
+
const uatPath = join(sDir, `${sid}-UAT.md`);
|
|
133
|
+
atomicWriteSync(uatPath, uatContent);
|
|
134
|
+
process.stderr.write(`gsd-mechanical: wrote ${uatPath}\n`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Mark slice [x] in ROADMAP
|
|
139
|
+
await markSliceInRoadmap(base, mid, sid);
|
|
140
|
+
|
|
141
|
+
// Append new decisions if any
|
|
142
|
+
await appendNewDecisions(base, taskSummaries.map(ts => ts.summary));
|
|
143
|
+
|
|
144
|
+
// Update requirements if all passed
|
|
145
|
+
if (allPassed) {
|
|
146
|
+
await mechanicalRequirementsUpdate(base, mid, sid, taskSummaries.map(ts => ts.summary));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ─── Requirements Update ─────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Conservative requirements update: mark requirements Validated only if
|
|
156
|
+
* all tasks' verification passed.
|
|
157
|
+
*/
|
|
158
|
+
export async function mechanicalRequirementsUpdate(
|
|
159
|
+
_base: string, _mid: string, _sid: string, _taskSummaries: Summary[],
|
|
160
|
+
): Promise<void> {
|
|
161
|
+
// Conservative: requirements validation requires human or LLM judgment
|
|
162
|
+
// about whether the requirement is truly met. Mechanical completion only
|
|
163
|
+
// marks the slice done — requirement status updates are left to the
|
|
164
|
+
// existing validation pipeline.
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ─── Decision Aggregation ────────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Collect key_decisions from task summaries, deduplicate against existing
|
|
171
|
+
* DECISIONS.md, and append new ones.
|
|
172
|
+
*/
|
|
173
|
+
export async function appendNewDecisions(
|
|
174
|
+
base: string, taskSummaries: Summary[],
|
|
175
|
+
): Promise<void> {
|
|
176
|
+
const allDecisions = taskSummaries.flatMap(s => s.frontmatter.key_decisions);
|
|
177
|
+
if (allDecisions.length === 0) return;
|
|
178
|
+
|
|
179
|
+
const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
|
|
180
|
+
const existing = existsSync(decisionsPath)
|
|
181
|
+
? readFileSync(decisionsPath, "utf-8")
|
|
182
|
+
: "";
|
|
183
|
+
|
|
184
|
+
// Deduplicate — skip decisions whose text already appears in the file
|
|
185
|
+
const newDecisions = allDecisions.filter(d =>
|
|
186
|
+
d.trim() && !existing.includes(d.trim()),
|
|
187
|
+
);
|
|
188
|
+
if (newDecisions.length === 0) return;
|
|
189
|
+
|
|
190
|
+
const entries = newDecisions
|
|
191
|
+
.map(d => `- ${d} _(auto-aggregated from task summaries)_`)
|
|
192
|
+
.join("\n");
|
|
193
|
+
|
|
194
|
+
const updated = existing.trimEnd() + "\n\n### Auto-aggregated Decisions\n\n" + entries + "\n";
|
|
195
|
+
atomicWriteSync(decisionsPath, updated);
|
|
196
|
+
process.stderr.write(`gsd-mechanical: appended ${newDecisions.length} decision(s) to DECISIONS.md\n`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ─── Milestone Verification ──────────────────────────────────────────────────
|
|
200
|
+
|
|
201
|
+
export interface MilestoneVerificationResult {
|
|
202
|
+
verdict: "passed" | "failed" | "mixed";
|
|
203
|
+
checks: EvidenceJSON[];
|
|
204
|
+
uatResults: string[];
|
|
205
|
+
markdown: string;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Aggregate T##-VERIFY.json files and S##-UAT-RESULT.md files across all
|
|
210
|
+
* slices in a milestone to produce VALIDATION.md.
|
|
211
|
+
*/
|
|
212
|
+
export async function aggregateMilestoneVerification(
|
|
213
|
+
base: string, mid: string,
|
|
214
|
+
): Promise<MilestoneVerificationResult> {
|
|
215
|
+
const mDir = resolveMilestonePath(base, mid);
|
|
216
|
+
if (!mDir) return { verdict: "failed", checks: [], uatResults: [], markdown: "" };
|
|
217
|
+
|
|
218
|
+
const allChecks: EvidenceJSON[] = [];
|
|
219
|
+
const allUatResults: string[] = [];
|
|
220
|
+
|
|
221
|
+
// Scan all slices
|
|
222
|
+
const slicesDir = join(mDir, "slices");
|
|
223
|
+
if (!existsSync(slicesDir)) return { verdict: "failed", checks: [], uatResults: [], markdown: "" };
|
|
224
|
+
|
|
225
|
+
const sliceDirs = readdirSyncSafe(slicesDir).filter(name => /^S\d+/i.test(name)).sort();
|
|
226
|
+
|
|
227
|
+
for (const sliceName of sliceDirs) {
|
|
228
|
+
const sid = sliceName.match(/^(S\d+)/i)?.[1] ?? sliceName;
|
|
229
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
230
|
+
if (tDir) {
|
|
231
|
+
const verifyFiles = resolveTaskJsonFiles(tDir, "VERIFY");
|
|
232
|
+
for (const vf of verifyFiles) {
|
|
233
|
+
try {
|
|
234
|
+
const content = readFileSync(join(tDir, vf), "utf-8");
|
|
235
|
+
const evidence = JSON.parse(content) as EvidenceJSON;
|
|
236
|
+
allChecks.push(evidence);
|
|
237
|
+
} catch {
|
|
238
|
+
// Skip malformed JSON
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Check for UAT result
|
|
244
|
+
const uatResultPath = resolveSliceFile(base, mid, sid, "UAT-RESULT");
|
|
245
|
+
if (uatResultPath) {
|
|
246
|
+
try {
|
|
247
|
+
const uatContent = readFileSync(uatResultPath, "utf-8");
|
|
248
|
+
allUatResults.push(`### ${sid}\n\n${uatContent}`);
|
|
249
|
+
} catch {
|
|
250
|
+
// Non-fatal
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Determine verdict
|
|
256
|
+
const allPassed = allChecks.length > 0 && allChecks.every(c => c.passed);
|
|
257
|
+
const anyFailed = allChecks.some(c => !c.passed);
|
|
258
|
+
const verdict: "passed" | "failed" | "mixed" = allPassed
|
|
259
|
+
? "passed"
|
|
260
|
+
: anyFailed
|
|
261
|
+
? (allChecks.some(c => c.passed) ? "mixed" : "failed")
|
|
262
|
+
: "passed"; // No checks = vacuously passed
|
|
263
|
+
|
|
264
|
+
// Build VALIDATION.md
|
|
265
|
+
const mdLines: string[] = [
|
|
266
|
+
"---",
|
|
267
|
+
`milestone: ${mid}`,
|
|
268
|
+
`verdict: ${verdict}`,
|
|
269
|
+
"remediation_round: 0",
|
|
270
|
+
`validated_at: ${new Date().toISOString()}`,
|
|
271
|
+
"---",
|
|
272
|
+
"",
|
|
273
|
+
`# ${mid}: Milestone Validation`,
|
|
274
|
+
"",
|
|
275
|
+
`**Verdict:** ${verdict}`,
|
|
276
|
+
"",
|
|
277
|
+
"## Verification Results",
|
|
278
|
+
"",
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
if (allChecks.length === 0) {
|
|
282
|
+
mdLines.push("_No verification evidence found._");
|
|
283
|
+
} else {
|
|
284
|
+
mdLines.push("| Task | Passed | Checks | Failed |");
|
|
285
|
+
mdLines.push("|------|--------|--------|--------|");
|
|
286
|
+
for (const check of allChecks) {
|
|
287
|
+
const failedCount = check.checks.filter(c => c.verdict === "fail").length;
|
|
288
|
+
mdLines.push(
|
|
289
|
+
`| ${check.taskId} | ${check.passed ? "yes" : "no"} | ${check.checks.length} | ${failedCount} |`,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (allUatResults.length > 0) {
|
|
295
|
+
mdLines.push("");
|
|
296
|
+
mdLines.push("## UAT Results");
|
|
297
|
+
mdLines.push("");
|
|
298
|
+
mdLines.push(...allUatResults);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
mdLines.push("");
|
|
302
|
+
|
|
303
|
+
const markdown = mdLines.join("\n");
|
|
304
|
+
|
|
305
|
+
// Write VALIDATION.md
|
|
306
|
+
const validationPath = join(mDir, `${mid}-VALIDATION.md`);
|
|
307
|
+
atomicWriteSync(validationPath, markdown);
|
|
308
|
+
process.stderr.write(`gsd-mechanical: wrote ${validationPath}\n`);
|
|
309
|
+
|
|
310
|
+
return { verdict, checks: allChecks, uatResults: allUatResults, markdown };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// ─── Milestone Summary ──────────────────────────────────────────────────────
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Read all S##-SUMMARY.md files and produce M##-SUMMARY.md.
|
|
317
|
+
*/
|
|
318
|
+
export async function generateMilestoneSummary(
|
|
319
|
+
base: string, mid: string,
|
|
320
|
+
): Promise<string> {
|
|
321
|
+
const mDir = resolveMilestonePath(base, mid);
|
|
322
|
+
if (!mDir) return "";
|
|
323
|
+
|
|
324
|
+
const slicesDir = join(mDir, "slices");
|
|
325
|
+
if (!existsSync(slicesDir)) return "";
|
|
326
|
+
|
|
327
|
+
const sliceDirs = readdirSyncSafe(slicesDir).filter(name => /^S\d+/i.test(name)).sort();
|
|
328
|
+
|
|
329
|
+
const aggregatedProvides: string[] = [];
|
|
330
|
+
const aggregatedKeyFiles: string[] = [];
|
|
331
|
+
const aggregatedKeyDecisions: string[] = [];
|
|
332
|
+
const aggregatedPatterns: string[] = [];
|
|
333
|
+
const sliceOneLinerList: string[] = [];
|
|
334
|
+
|
|
335
|
+
for (const sliceName of sliceDirs) {
|
|
336
|
+
const sid = sliceName.match(/^(S\d+)/i)?.[1] ?? sliceName;
|
|
337
|
+
const summaryPath = resolveSliceFile(base, mid, sid, "SUMMARY");
|
|
338
|
+
if (!summaryPath) continue;
|
|
339
|
+
|
|
340
|
+
try {
|
|
341
|
+
const content = readFileSync(summaryPath, "utf-8");
|
|
342
|
+
const summary = parseSummary(content);
|
|
343
|
+
aggregatedProvides.push(...summary.frontmatter.provides);
|
|
344
|
+
aggregatedKeyFiles.push(...summary.frontmatter.key_files);
|
|
345
|
+
aggregatedKeyDecisions.push(...summary.frontmatter.key_decisions);
|
|
346
|
+
aggregatedPatterns.push(...summary.frontmatter.patterns_established);
|
|
347
|
+
sliceOneLinerList.push(`- **${sid}**: ${summary.oneLiner || summary.title || sid}`);
|
|
348
|
+
} catch {
|
|
349
|
+
sliceOneLinerList.push(`- **${sid}**: _(summary unavailable)_`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const mdLines: string[] = [
|
|
354
|
+
"---",
|
|
355
|
+
`id: ${mid}`,
|
|
356
|
+
];
|
|
357
|
+
if (dedup(aggregatedProvides).length > 0)
|
|
358
|
+
mdLines.push(`provides:\n${dedup(aggregatedProvides).map(p => ` - ${p}`).join("\n")}`);
|
|
359
|
+
if (dedup(aggregatedKeyFiles).length > 0)
|
|
360
|
+
mdLines.push(`key_files:\n${dedup(aggregatedKeyFiles).map(f => ` - ${f}`).join("\n")}`);
|
|
361
|
+
if (dedup(aggregatedKeyDecisions).length > 0)
|
|
362
|
+
mdLines.push(`key_decisions:\n${dedup(aggregatedKeyDecisions).map(d => ` - ${d}`).join("\n")}`);
|
|
363
|
+
if (dedup(aggregatedPatterns).length > 0)
|
|
364
|
+
mdLines.push(`patterns_established:\n${dedup(aggregatedPatterns).map(p => ` - ${p}`).join("\n")}`);
|
|
365
|
+
mdLines.push(`completed_at: ${new Date().toISOString()}`);
|
|
366
|
+
mdLines.push("---");
|
|
367
|
+
mdLines.push("");
|
|
368
|
+
mdLines.push(`# ${mid}: Milestone Summary`);
|
|
369
|
+
mdLines.push("");
|
|
370
|
+
mdLines.push("## Slices");
|
|
371
|
+
mdLines.push("");
|
|
372
|
+
mdLines.push(...sliceOneLinerList);
|
|
373
|
+
mdLines.push("");
|
|
374
|
+
|
|
375
|
+
const content = mdLines.join("\n");
|
|
376
|
+
|
|
377
|
+
// Write M##-SUMMARY.md
|
|
378
|
+
const summaryPath = join(mDir, `${mid}-SUMMARY.md`);
|
|
379
|
+
atomicWriteSync(summaryPath, content);
|
|
380
|
+
process.stderr.write(`gsd-mechanical: wrote ${summaryPath}\n`);
|
|
381
|
+
|
|
382
|
+
return content;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
386
|
+
|
|
387
|
+
function aggregateFrontmatter(fms: SummaryFrontmatter[]): {
|
|
388
|
+
provides: string[];
|
|
389
|
+
key_files: string[];
|
|
390
|
+
key_decisions: string[];
|
|
391
|
+
patterns_established: string[];
|
|
392
|
+
affects: string[];
|
|
393
|
+
observability_surfaces: string[];
|
|
394
|
+
} {
|
|
395
|
+
return {
|
|
396
|
+
provides: dedup(fms.flatMap(f => f.provides)),
|
|
397
|
+
key_files: dedup(fms.flatMap(f => f.key_files)),
|
|
398
|
+
key_decisions: dedup(fms.flatMap(f => f.key_decisions)),
|
|
399
|
+
patterns_established: dedup(fms.flatMap(f => f.patterns_established)),
|
|
400
|
+
affects: dedup(fms.flatMap(f => f.affects)),
|
|
401
|
+
observability_surfaces: dedup(fms.flatMap(f => f.observability_surfaces)),
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function dedup(arr: string[]): string[] {
|
|
406
|
+
return [...new Set(arr.filter(s => s.trim()))];
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async function markSliceInRoadmap(base: string, mid: string, sid: string): Promise<void> {
|
|
410
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
411
|
+
if (!roadmapPath) return;
|
|
412
|
+
const content = await loadFile(roadmapPath);
|
|
413
|
+
if (!content) return;
|
|
414
|
+
const updated = content.replace(
|
|
415
|
+
new RegExp(`^(\\s*-\\s+)\\[ \\]\\s+\\*\\*${sid}:`, "m"),
|
|
416
|
+
`$1[x] **${sid}:`,
|
|
417
|
+
);
|
|
418
|
+
if (updated !== content) {
|
|
419
|
+
atomicWriteSync(roadmapPath, updated);
|
|
420
|
+
process.stderr.write(`gsd-mechanical: marked ${sid} done in ROADMAP\n`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function readdirSyncSafe(dir: string): string[] {
|
|
425
|
+
try {
|
|
426
|
+
return readdirSync(dir);
|
|
427
|
+
} catch {
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
}
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
* 4. On crash recovery or fresh start, the ledger is loaded from disk
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
17
16
|
import { join } from "node:path";
|
|
18
17
|
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
19
18
|
import { gsdRoot } from "./paths.js";
|
|
20
19
|
import { getAndClearSkills } from "./skill-telemetry.js";
|
|
20
|
+
import { loadJsonFile, loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
|
|
21
21
|
|
|
22
22
|
// Re-export from shared — canonical implementation lives in format-utils.
|
|
23
23
|
export { formatTokenCount } from "../shared/mod.js";
|
|
@@ -502,45 +502,31 @@ function metricsPath(base: string): string {
|
|
|
502
502
|
return join(gsdRoot(base), "metrics.json");
|
|
503
503
|
}
|
|
504
504
|
|
|
505
|
+
function isMetricsLedger(data: unknown): data is MetricsLedger {
|
|
506
|
+
return (
|
|
507
|
+
typeof data === "object" &&
|
|
508
|
+
data !== null &&
|
|
509
|
+
(data as MetricsLedger).version === 1 &&
|
|
510
|
+
Array.isArray((data as MetricsLedger).units)
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function defaultLedger(): MetricsLedger {
|
|
515
|
+
return { version: 1, projectStartedAt: Date.now(), units: [] };
|
|
516
|
+
}
|
|
517
|
+
|
|
505
518
|
/**
|
|
506
519
|
* Load ledger from disk without initializing in-memory state.
|
|
507
520
|
* Used by history/export commands outside of auto-mode.
|
|
508
521
|
*/
|
|
509
522
|
export function loadLedgerFromDisk(base: string): MetricsLedger | null {
|
|
510
|
-
|
|
511
|
-
const raw = readFileSync(metricsPath(base), "utf-8");
|
|
512
|
-
const parsed = JSON.parse(raw);
|
|
513
|
-
if (parsed.version === 1 && Array.isArray(parsed.units)) {
|
|
514
|
-
return parsed as MetricsLedger;
|
|
515
|
-
}
|
|
516
|
-
} catch {
|
|
517
|
-
// File doesn't exist or is corrupt
|
|
518
|
-
}
|
|
519
|
-
return null;
|
|
523
|
+
return loadJsonFileOrNull(metricsPath(base), isMetricsLedger);
|
|
520
524
|
}
|
|
521
525
|
|
|
522
526
|
function loadLedger(base: string): MetricsLedger {
|
|
523
|
-
|
|
524
|
-
const raw = readFileSync(metricsPath(base), "utf-8");
|
|
525
|
-
const parsed = JSON.parse(raw);
|
|
526
|
-
if (parsed.version === 1 && Array.isArray(parsed.units)) {
|
|
527
|
-
return parsed as MetricsLedger;
|
|
528
|
-
}
|
|
529
|
-
} catch {
|
|
530
|
-
// File doesn't exist or is corrupt — start fresh
|
|
531
|
-
}
|
|
532
|
-
return {
|
|
533
|
-
version: 1,
|
|
534
|
-
projectStartedAt: Date.now(),
|
|
535
|
-
units: [],
|
|
536
|
-
};
|
|
527
|
+
return loadJsonFile(metricsPath(base), isMetricsLedger, defaultLedger);
|
|
537
528
|
}
|
|
538
529
|
|
|
539
530
|
function saveLedger(base: string, data: MetricsLedger): void {
|
|
540
|
-
|
|
541
|
-
mkdirSync(gsdRoot(base), { recursive: true });
|
|
542
|
-
writeFileSync(metricsPath(base), JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
543
|
-
} catch {
|
|
544
|
-
// Don't let metrics failures break auto-mode
|
|
545
|
-
}
|
|
531
|
+
saveJsonFile(metricsPath(base), data);
|
|
546
532
|
}
|
|
@@ -137,14 +137,6 @@ export function clearPathCache(): void {
|
|
|
137
137
|
|
|
138
138
|
// ─── Name Builders ─────────────────────────────────────────────────────────
|
|
139
139
|
|
|
140
|
-
/**
|
|
141
|
-
* Build a directory name from an ID.
|
|
142
|
-
* ("M001") → "M001"
|
|
143
|
-
*/
|
|
144
|
-
export function buildDirName(id: string): string {
|
|
145
|
-
return id;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
140
|
/**
|
|
149
141
|
* Build a milestone-level file name.
|
|
150
142
|
* ("M001", "CONTEXT") → "M001-CONTEXT.md"
|
|
@@ -244,6 +236,23 @@ export function resolveTaskFiles(tasksDir: string, suffix: string): string[] {
|
|
|
244
236
|
}
|
|
245
237
|
}
|
|
246
238
|
|
|
239
|
+
/**
|
|
240
|
+
* Find all task JSON files matching a pattern in a tasks directory.
|
|
241
|
+
* Returns sorted file names matching T##-SUFFIX.json or legacy T##-*-SUFFIX.json
|
|
242
|
+
*/
|
|
243
|
+
export function resolveTaskJsonFiles(tasksDir: string, suffix: string): string[] {
|
|
244
|
+
if (!existsSync(tasksDir)) return [];
|
|
245
|
+
try {
|
|
246
|
+
const currentPattern = new RegExp(`^T\\d+-${suffix}\\.json$`, "i");
|
|
247
|
+
const legacyPattern = new RegExp(`^T\\d+-.*-${suffix}\\.json$`, "i");
|
|
248
|
+
return cachedReaddir(tasksDir)
|
|
249
|
+
.filter(f => currentPattern.test(f) || legacyPattern.test(f))
|
|
250
|
+
.sort();
|
|
251
|
+
} catch {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
247
256
|
// ─── Full Path Builders ────────────────────────────────────────────────────
|
|
248
257
|
|
|
249
258
|
export const GSD_ROOT_FILES = {
|
|
@@ -254,13 +254,19 @@ export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPrefer
|
|
|
254
254
|
subagent: "claude-sonnet-4-5-20250514",
|
|
255
255
|
},
|
|
256
256
|
phases: {
|
|
257
|
+
skip_research: true,
|
|
258
|
+
skip_reassess: true,
|
|
257
259
|
skip_slice_research: true,
|
|
258
260
|
},
|
|
259
261
|
};
|
|
260
262
|
case "quality":
|
|
261
263
|
return {
|
|
262
264
|
models: {},
|
|
263
|
-
phases: {
|
|
265
|
+
phases: {
|
|
266
|
+
skip_research: true,
|
|
267
|
+
skip_slice_research: true,
|
|
268
|
+
skip_reassess: true,
|
|
269
|
+
},
|
|
264
270
|
};
|
|
265
271
|
}
|
|
266
272
|
}
|
|
@@ -172,9 +172,10 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
172
172
|
if (p.skip_reassess !== undefined) validatedPhases.skip_reassess = !!p.skip_reassess;
|
|
173
173
|
if (p.skip_slice_research !== undefined) validatedPhases.skip_slice_research = !!p.skip_slice_research;
|
|
174
174
|
if (p.skip_milestone_validation !== undefined) validatedPhases.skip_milestone_validation = !!p.skip_milestone_validation;
|
|
175
|
+
if (p.reassess_after_slice !== undefined) validatedPhases.reassess_after_slice = !!p.reassess_after_slice;
|
|
175
176
|
if ((p as any).require_slice_discussion !== undefined) (validatedPhases as any).require_slice_discussion = !!(p as any).require_slice_discussion;
|
|
176
177
|
// Warn on unknown phase keys
|
|
177
|
-
const knownPhaseKeys = new Set(["skip_research", "skip_reassess", "skip_slice_research", "skip_milestone_validation", "require_slice_discussion"]);
|
|
178
|
+
const knownPhaseKeys = new Set(["skip_research", "skip_reassess", "skip_slice_research", "skip_milestone_validation", "reassess_after_slice", "require_slice_discussion"]);
|
|
178
179
|
for (const key of Object.keys(p)) {
|
|
179
180
|
if (!knownPhaseKeys.has(key)) {
|
|
180
181
|
warnings.push(`unknown phases key "${key}" — ignored`);
|
|
@@ -16,13 +16,15 @@ Summarize your understanding of the specification concretely:
|
|
|
16
16
|
- Scope estimate (how many milestones × slices)
|
|
17
17
|
- Any ambiguities or gaps you notice
|
|
18
18
|
|
|
19
|
-
### Step 2: Investigate
|
|
19
|
+
### Step 2: Investigate (brief)
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Quickly scout the codebase to understand what already exists — spend no more than 5-6 tool calls here:
|
|
22
22
|
- `ls` the project root and key directories
|
|
23
23
|
- Search for relevant existing code, patterns, dependencies
|
|
24
24
|
- Check library docs if needed (`resolve_library` / `get_library_docs`)
|
|
25
25
|
|
|
26
|
+
Then move on to writing artifacts. Do not explore exhaustively — the research phase will do deeper investigation later.
|
|
27
|
+
|
|
26
28
|
### Step 3: Make Decisions
|
|
27
29
|
|
|
28
30
|
For any ambiguities or gaps in the specification:
|
|
@@ -91,7 +91,7 @@ Before moving to the wrap-up gate, verify you have covered:
|
|
|
91
91
|
- options: "Yes, you got it (Recommended)", "Not quite — let me clarify"
|
|
92
92
|
- **The question ID must contain `depth_verification`** (e.g. `depth_verification_confirm`) — this enables the write-gate downstream.
|
|
93
93
|
|
|
94
|
-
**If `{{structuredQuestionsAvailable}}` is `false`:** ask in plain text: "Did I capture that correctly?
|
|
94
|
+
**If `{{structuredQuestionsAvailable}}` is `false`:** ask in plain text: "Did I capture that correctly? If not, tell me what I missed." Wait for confirmation before proceeding.
|
|
95
95
|
|
|
96
96
|
If they clarify, absorb the correction and re-verify.
|
|
97
97
|
|
|
@@ -12,9 +12,33 @@ All relevant context has been preloaded below — start working immediately with
|
|
|
12
12
|
|
|
13
13
|
## Your Role in the Pipeline
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
You are the first deep look at this milestone. You have full tool access — explore the codebase, look up docs, investigate technology choices. Your job is to understand the landscape and then strategically decompose the work into demoable slices.
|
|
16
16
|
|
|
17
|
-
After you finish, each slice goes through its own
|
|
17
|
+
After you finish, each slice goes through its own plan → execute cycle. Slice planners decompose into tasks. Executors build each task. Your roadmap sets the strategic frame for all of them.
|
|
18
|
+
|
|
19
|
+
### Explore First, Then Decompose
|
|
20
|
+
|
|
21
|
+
Before decomposing, build your understanding:
|
|
22
|
+
|
|
23
|
+
1. **Codebase exploration.** For small/familiar codebases, use `rg`, `find`, and targeted reads. For large or unfamiliar codebases, use `scout` to build a broad map efficiently before diving in.
|
|
24
|
+
2. **Library docs.** Use `resolve_library` / `get_library_docs` for unfamiliar libraries — skip this for libraries already used in the codebase.
|
|
25
|
+
3. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
|
|
26
|
+
4. **Requirements analysis.** If `.gsd/REQUIREMENTS.md` exists, research against it. Identify which Active requirements are table stakes, likely omissions, overbuilt risks, or domain-standard behaviors.
|
|
27
|
+
|
|
28
|
+
### Strategic Questions to Answer
|
|
29
|
+
|
|
30
|
+
- What should be proven first?
|
|
31
|
+
- What existing patterns should be reused?
|
|
32
|
+
- What boundary contracts matter?
|
|
33
|
+
- What constraints does the existing codebase impose?
|
|
34
|
+
- Are there known failure modes that should shape slice ordering?
|
|
35
|
+
- If requirements exist: what table stakes, expected behaviors, continuity expectations, launchability expectations, or failure-visibility expectations are missing, optional, or clearly out of scope?
|
|
36
|
+
|
|
37
|
+
### Source Files
|
|
38
|
+
|
|
39
|
+
{{sourceFilePaths}}
|
|
40
|
+
|
|
41
|
+
If milestone research exists (inlined above), trust those findings and skip redundant exploration. If findings are significant and no research file exists yet, write `{{researchOutputPath}}`.
|
|
18
42
|
|
|
19
43
|
Narrate your decomposition reasoning — why you're grouping work this way, what risks are driving the order, what verification strategy you're choosing and why. Use complete sentences rather than planner shorthand or fragmentary notes.
|
|
20
44
|
|
|
@@ -18,7 +18,21 @@ Pay particular attention to **Forward Intelligence** sections — they contain h
|
|
|
18
18
|
|
|
19
19
|
## Your Role in the Pipeline
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
You have full tool access. Before decomposing, explore the relevant code to ground your plan in reality.
|
|
22
|
+
|
|
23
|
+
### Verify Roadmap Assumptions
|
|
24
|
+
|
|
25
|
+
Check prior slice summaries (inlined above as dependency summaries, if present). If prior slices discovered constraints, changed approaches, or flagged fragility, adjust your plan accordingly. The roadmap description may be stale — verify it against the current codebase state.
|
|
26
|
+
|
|
27
|
+
### Explore Slice Scope
|
|
28
|
+
|
|
29
|
+
Read the code files relevant to this slice. Confirm the roadmap's description of what exists, what needs to change, and what boundaries apply. Use `rg`, `find`, and targeted reads.
|
|
30
|
+
|
|
31
|
+
### Source Files
|
|
32
|
+
|
|
33
|
+
{{sourceFilePaths}}
|
|
34
|
+
|
|
35
|
+
If slice research exists (inlined above), trust those findings and skip redundant exploration.
|
|
22
36
|
|
|
23
37
|
After you finish, **executor agents** implement each task in isolated fresh context windows. They see only their task plan, the slice plan excerpt (goal/demo/verification), and compressed summaries of prior tasks. They do not see the research doc, the roadmap, or REQUIREMENTS.md. Everything an executor needs must be in the task plan itself — file paths, specific steps, expected inputs and outputs.
|
|
24
38
|
|