gsd-pi 2.80.0-dev.c5c38454b → 2.80.0-dev.cf9433f56
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 +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +66 -45
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +13 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +124 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto.js +77 -5
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +21 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +21 -0
- package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
- package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
- package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
- package/dist/resources/extensions/gsd/detection.js +106 -0
- package/dist/resources/extensions/gsd/git-service.js +36 -4
- package/dist/resources/extensions/gsd/gsd-db.js +46 -13
- package/dist/resources/extensions/gsd/guided-flow.js +80 -14
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +7 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
- package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
- package/dist/resources/extensions/gsd/worktree-resolver.js +33 -17
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +3 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -17
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
- package/packages/mcp-server/src/workflow-tools.ts +30 -16
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -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 +25 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +15 -5
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +53 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.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 +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +38 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +3 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +4 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +24 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +3 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +18 -8
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +20 -8
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +50 -8
- package/src/resources/extensions/gsd/auto/phases.ts +77 -48
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +18 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
- package/src/resources/extensions/gsd/auto-prompts.ts +133 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto.ts +92 -4
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -1
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
- package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
- package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
- package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
- package/src/resources/extensions/gsd/detection.ts +128 -0
- package/src/resources/extensions/gsd/git-service.ts +46 -8
- package/src/resources/extensions/gsd/gsd-db.ts +50 -13
- package/src/resources/extensions/gsd/guided-flow.ts +96 -14
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +7 -0
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +72 -1
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +63 -1
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
- package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
- package/src/resources/extensions/gsd/worktree-resolver.ts +36 -15
- /package/dist/web/standalone/.next/static/{TCSim36ZpcPu2WgeoC45g → -5nHJWzSdG-WkPMul_khA}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{TCSim36ZpcPu2WgeoC45g → -5nHJWzSdG-WkPMul_khA}/_ssgManifest.js +0 -0
|
@@ -328,6 +328,8 @@ function shouldValidateInputAsPath(raw) {
|
|
|
328
328
|
const trimmed = raw.trim();
|
|
329
329
|
if (!trimmed)
|
|
330
330
|
return false;
|
|
331
|
+
if (isRuntimeOnlyInput(trimmed))
|
|
332
|
+
return false;
|
|
331
333
|
const candidate = extractPathFromAnnotation(trimmed);
|
|
332
334
|
if (!candidate)
|
|
333
335
|
return false;
|
|
@@ -349,6 +351,9 @@ function shouldValidateInputAsPath(raw) {
|
|
|
349
351
|
/[\\/]/.test(candidate) ||
|
|
350
352
|
/[*?[\]{}]/.test(candidate));
|
|
351
353
|
}
|
|
354
|
+
function isRuntimeOnlyInput(raw) {
|
|
355
|
+
return /\(\s*runtime\s*\)/i.test(raw);
|
|
356
|
+
}
|
|
352
357
|
function containsGlobPattern(candidate) {
|
|
353
358
|
return ["*", "?", "[", "]", "{", "}"].some((char) => candidate.includes(char));
|
|
354
359
|
}
|
|
@@ -461,6 +466,8 @@ export function checkTaskOrdering(tasks, basePath) {
|
|
|
461
466
|
const task = tasks[i];
|
|
462
467
|
const filesToCheck = [...task.inputs];
|
|
463
468
|
for (const file of filesToCheck) {
|
|
469
|
+
if (isRuntimeOnlyInput(file))
|
|
470
|
+
continue;
|
|
464
471
|
if (!shouldValidateInputAsPath(file))
|
|
465
472
|
continue;
|
|
466
473
|
const normalizedFile = normalizeFilePath(file);
|
|
@@ -111,15 +111,41 @@ function warmCache() {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
let warmCacheScheduled = false;
|
|
114
|
+
let warmCacheRan = false;
|
|
115
|
+
let warmCacheTimer;
|
|
116
|
+
/**
|
|
117
|
+
* Synchronously snapshot the prompt/template tree into the cache.
|
|
118
|
+
*
|
|
119
|
+
* Safe to call immediately after `initResources()` because that function uses
|
|
120
|
+
* synchronous fs APIs — there is no race window that requires deferring the
|
|
121
|
+
* cache warm via setTimeout. Idempotent: subsequent calls are no-ops.
|
|
122
|
+
*
|
|
123
|
+
* Cancels the fallback `scheduleWarmCache` timer if it is still pending.
|
|
124
|
+
*/
|
|
125
|
+
export function primeCache() {
|
|
126
|
+
if (warmCacheRan)
|
|
127
|
+
return;
|
|
128
|
+
if (warmCacheTimer) {
|
|
129
|
+
clearTimeout(warmCacheTimer);
|
|
130
|
+
warmCacheTimer = undefined;
|
|
131
|
+
}
|
|
132
|
+
warmCacheScheduled = true;
|
|
133
|
+
warmCacheRan = true;
|
|
134
|
+
warmCache();
|
|
135
|
+
}
|
|
114
136
|
function scheduleWarmCache() {
|
|
115
137
|
if (warmCacheScheduled)
|
|
116
138
|
return;
|
|
117
139
|
warmCacheScheduled = true;
|
|
118
140
|
const run = () => {
|
|
141
|
+
warmCacheTimer = undefined;
|
|
142
|
+
if (warmCacheRan)
|
|
143
|
+
return;
|
|
144
|
+
warmCacheRan = true;
|
|
119
145
|
warmCache();
|
|
120
146
|
};
|
|
121
|
-
|
|
122
|
-
|
|
147
|
+
warmCacheTimer = setTimeout(run, 1000);
|
|
148
|
+
warmCacheTimer.unref?.();
|
|
123
149
|
}
|
|
124
150
|
// Snapshot the full prompt/template tree after import so extension startup only
|
|
125
151
|
// pays for prompts that are actually needed immediately.
|
|
@@ -16,28 +16,28 @@ Start with what the excerpts give you. Read full files when the section heads si
|
|
|
16
16
|
|
|
17
17
|
**On-demand Read ordering:** Complete all slice SUMMARY Reads you need for cross-slice synthesis, the Decision Re-evaluation table, and LEARNINGS **before** calling `gsd_complete_milestone` (step 12). Once that tool runs, the milestone is marked complete in the DB, so it must be the final persistent milestone-closeout write.
|
|
18
18
|
|
|
19
|
-
###
|
|
19
|
+
### Closeout Review Mode
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
The inlined context includes a validation status block.
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- Significant tests added or changed -> **tester** coverage check against success criteria.
|
|
23
|
+
- If it says a passing validation artifact is present, treat that artifact as authoritative for success criteria, requirement coverage, verification classes, and cross-slice integration. Do not delegate fresh reviewer/security/tester audits unless the validation artifact is internally inconsistent with the inlined summaries.
|
|
24
|
+
- If validation is missing, stale, non-pass, or internally inconsistent, use `subagent` for review work needing fresh context before drafting LEARNINGS: cross-slice integrations or new public APIs -> **reviewer**; auth, network, parsing, file IO, shell exec, or crypto -> **security**; significant tests added or changed -> **tester**.
|
|
26
25
|
|
|
27
|
-
Subagents report only; they do not write user source. Fold findings into Decision Re-evaluation and LEARNINGS before completion.
|
|
26
|
+
Subagents report only; they do not write user source. Fold any findings into Decision Re-evaluation and LEARNINGS before completion.
|
|
28
27
|
|
|
29
28
|
{{inlinedContext}}
|
|
30
29
|
|
|
31
30
|
## Steps
|
|
32
31
|
|
|
33
|
-
1.
|
|
34
|
-
2.
|
|
35
|
-
3.
|
|
36
|
-
4. Verify
|
|
37
|
-
5. Verify **
|
|
38
|
-
6. If
|
|
39
|
-
7.
|
|
40
|
-
8.
|
|
32
|
+
1. **Duplicate completion guard:** Call `gsd_milestone_status` for `{{milestoneId}}` before any durable writes. If the returned milestone **status is `complete`**, this is a stale or duplicate closeout turn: do NOT mutate requirements, do NOT refresh the project document, do NOT write LEARNINGS, and do NOT persist milestone completion again. Say: "Milestone {{milestoneId}} is already complete." and stop.
|
|
33
|
+
2. Use the **Milestone Summary** output template from the inlined context above
|
|
34
|
+
3. {{skillActivation}}
|
|
35
|
+
4. **Verify code changes exist.** Compare milestone work against the integration branch (`main`, `master`, or recorded branch), using merge-base as older revision and `HEAD` as newer. If the diff lists non-`.gsd/` files, pass. If `HEAD` equals the integration branch/merge-base, treat it as a self-diff retry: inspect milestone-scoped commit evidence (`GSD-Unit: {{milestoneId}}` or production `GSD-Task: Sxx/Tyy` trailers touching `.gsd/milestones/{{milestoneId}}/`) and verify those commits touched non-`.gsd/` files. Record **verification failure** only when neither source shows implementation files.
|
|
36
|
+
5. Verify every **success criterion** from `{{roadmapPath}}`. If passing validation is present, summarize the validation evidence instead of re-auditing it; otherwise verify with evidence from summaries, tests, or observable behavior. Record unmet criteria as **verification failure**.
|
|
37
|
+
6. Verify **definition of done**: all slices `[x]`, summaries exist, and integrations work. If passing validation is present, trust its integration/verification verdict unless inconsistent with current artifacts. Record unmet items as **verification failure**.
|
|
38
|
+
7. If the roadmap includes a **Horizontal Checklist**, verify each item and note unchecked items in the summary.
|
|
39
|
+
8. Fill the **Decision Re-evaluation** table: compare each key `.gsd/DECISIONS.md` decision from this milestone with what shipped, and flag decisions to revisit.
|
|
40
|
+
9. Validate **requirement status transitions**. For each changed requirement, confirm evidence supports the new status. Requirements may move between Active, Validated, Deferred, Blocked, or Out of Scope only with proof.
|
|
41
41
|
|
|
42
42
|
**DB access safety:** Do NOT query `.gsd/gsd.db` directly via `sqlite3` or `node -e require('better-sqlite3')`; the engine owns the WAL connection. Use `gsd_milestone_status`, inlined context, or `gsd_*` tools; never direct SQL.
|
|
43
43
|
|
|
@@ -54,13 +54,13 @@ Subagents report only; they do not write user source. Fold findings into Decisio
|
|
|
54
54
|
|
|
55
55
|
**Success path** (all verifications passed):
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
10. For each requirement whose status changed in step 9, call `gsd_requirement_update` with the requirement ID and updated `status` and `validation` fields — the tool regenerates `.gsd/REQUIREMENTS.md` automatically. Do this BEFORE completing the milestone so requirement updates are persisted.
|
|
58
|
+
11. Update `.gsd/PROJECT.md`: use the `write` tool with `path: ".gsd/PROJECT.md"` and `content` containing the full updated document reflecting milestone completion and current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh.
|
|
59
|
+
12. Extract structured learnings from this milestone and persist them to the GSD memory store. Follow the procedure block immediately below — it writes `{{milestoneId}}-LEARNINGS.md` as the audit trail and persists Patterns, Lessons, and Decisions via `capture_thought` (categories: pattern, gotcha/convention, architecture). The memory store is the single source of truth for cross-session durable knowledge (ADR-013).
|
|
60
60
|
|
|
61
61
|
{{extractLearningsSteps}}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
13. **Persist completion through `gsd_complete_milestone`.** Call it with the parameters below. This must be the final persistent write in the unit. The tool updates the milestone status in the DB, renders `{{milestoneSummaryPath}}`, and validates all slices are complete.
|
|
64
64
|
|
|
65
65
|
**Required parameters:**
|
|
66
66
|
- `milestoneId` (string) — Milestone ID (e.g. M001)
|
|
@@ -79,7 +79,7 @@ Subagents report only; they do not write user source. Fold findings into Decisio
|
|
|
79
79
|
- `followUps` (string) — Follow-up items for future milestones
|
|
80
80
|
- `deviations` (string) — Deviations from the original plan
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
14. Do not commit manually — the system auto-commits your changes after this unit completes.
|
|
83
83
|
- Say: "Milestone {{milestoneId}} complete."
|
|
84
84
|
|
|
85
85
|
**Important:** Do NOT skip code-change, success-criteria, or definition-of-done verification (steps 3-5). The summary must reflect verified outcomes. Verification failures block completion; there is no override. If a verification tool fails, errors, or returns unexpected output, treat it as failure.
|
|
@@ -16,7 +16,7 @@ Dispatch ALL slices simultaneously using the `subagent` tool in **parallel mode*
|
|
|
16
16
|
|
|
17
17
|
1. Call `subagent` with `tasks: [...]` containing one entry per slice below
|
|
18
18
|
2. Wait for ALL subagents to complete
|
|
19
|
-
3. Verify each slice's RESEARCH file was written (check
|
|
19
|
+
3. Verify each slice's RESEARCH file was written (check `.gsd/milestones/{{mid}}/slices/<slice-id>/`)
|
|
20
20
|
4. If a subagent failed to write its RESEARCH file, retry it **once** individually
|
|
21
21
|
5. If it fails a second time, write a partial RESEARCH file for that slice with a `## BLOCKER` section explaining the failure — do NOT retry again
|
|
22
22
|
6. Report which slices completed research and which (if any) needed a blocker note
|
|
@@ -48,7 +48,7 @@ Narrate decomposition reasoning in complete sentences: grouping, risk order, ver
|
|
|
48
48
|
Then:
|
|
49
49
|
1. Use the **Roadmap** output template from the inlined context above
|
|
50
50
|
2. {{skillActivation}}
|
|
51
|
-
3. Create only as many demoable vertical slices as the work genuinely needs.
|
|
51
|
+
3. Create only as many demoable vertical slices as the work genuinely needs. Use 1-10 slices, sized to the work; tiny/single-file/static work should usually be one slice.
|
|
52
52
|
4. Order by risk, high-risk first.
|
|
53
53
|
5. Call `gsd_plan_milestone` to persist milestone fields, slice rows, and **Horizontal Checklist** through the DB-backed path. Fill checklist concerns considered during planning: requirements, decisions, shutdown, revenue, auth, shared resources, reconnection. Omit for trivial milestones. Do **not** write `{{outputPath}}`, `ROADMAP.md`, or other planning artifacts manually; the tool owns rendering and persistence.
|
|
54
54
|
6. If planning produced structural decisions (slice ordering, technology choices, scope exclusions), call `gsd_decision_save` for each; the tool assigns IDs and regenerates `.gsd/DECISIONS.md`.
|
|
@@ -78,6 +78,8 @@ Apply these when decomposing and ordering slices:
|
|
|
78
78
|
- Ship features, not proofs; use clearly marked realistic stubs only when necessary.
|
|
79
79
|
- **Dependency format is comma-separated, never range syntax.** Write `depends:[S01,S02,S03]`, not `depends:[S01-S03]`.
|
|
80
80
|
- Roadmap ambition must match the milestone; right-size decomposition.
|
|
81
|
+
- Missing ecosystem markers are not a reason to over-plan. If Project Classification says `untyped-existing`, treat the listed content files as the project surface and use generic file-level workflow guidance.
|
|
82
|
+
- For `untyped-existing` projects with 1-2 content files, prefer exactly one slice unless the request clearly spans multiple independent user-visible capabilities. For 3-5 content files, prefer 1-2 slices.
|
|
81
83
|
|
|
82
84
|
## Progressive Planning (ADR-011)
|
|
83
85
|
|
|
@@ -39,7 +39,7 @@ If slice research is inlined, trust it. Explore enough code to confirm paths, bo
|
|
|
39
39
|
5. Define slice verification before tasks. Non-trivial slices need real tests or executable assertions; boundary contracts need contract-exercising checks. Tests must not read .gitignore/gitignored paths such as `.gsd/`, `.planning/`, or `.audits/`.
|
|
40
40
|
6. Include Threat Surface (Q3), Requirement Impact (Q4), proof level, observability, integration closure, Failure Modes (Q5), Load Profile (Q6), and Negative Tests (Q7) only where applicable.
|
|
41
41
|
7. Right-size tasks. Simple slices can be one task; split only when context, ownership, or verification boundaries justify it.
|
|
42
|
-
8. Each task needs a concrete title, Why / Files / Do / Verify / Done when, plus task-plan description, steps, must-haves, verification, inputs, and expected output. Inputs and Expected Output must include concrete backtick-wrapped paths; each task needs at least one output path.
|
|
42
|
+
8. Each task needs a concrete title, Why / Files / Do / Verify / Done when, plus task-plan description, steps, must-haves, verification, inputs, and expected output. Inputs and Expected Output must include concrete backtick-wrapped paths; each task needs at least one output path. Use paths relative to `{{workingDirectory}}`; do not put absolute paths to the original checkout or any directory outside `{{workingDirectory}}` in `files`, `inputs`, `expectedOutput`, or verification commands.
|
|
43
43
|
9. Persist with `gsd_plan_slice` using goal, successCriteria, optional proofLevel/integrationClosure/observabilityImpact, and tasks. `gsd_plan_slice` handles task persistence transactionally and renders `{{outputPath}}` plus task plans; do not call `gsd_plan_task`. The DB-backed tool is the canonical write path. Do **not** rely on direct `PLAN.md` writes as the source of truth.
|
|
44
44
|
10. Self-audit before finishing: goal/demo closure, requirement coverage, locked decisions, concrete paths, dependency order, wiring, scope size, proof truthfulness, feature completeness, and quality gates. Quality gates: non-trivial slices/tasks include specific Q3-Q7 coverage where applicable.
|
|
45
45
|
11. If planning creates structural decisions, append them to `.gsd/DECISIONS.md`.
|
|
@@ -17,11 +17,7 @@ You are executing a GSD quick task — a lightweight, focused unit of work outsi
|
|
|
17
17
|
5. Verify your work:
|
|
18
18
|
- Run tests if applicable.
|
|
19
19
|
- Verify both happy path and failure modes for non-trivial changes.
|
|
20
|
-
6.
|
|
21
|
-
- Use conventional commit messages (feat:, fix:, refactor:, etc.)
|
|
22
|
-
- Stage only relevant files — never commit secrets or runtime files.
|
|
23
|
-
- Commit logical units separately if the task involves distinct changes.
|
|
24
|
-
- Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.
|
|
20
|
+
6. {{commitInstruction}}
|
|
25
21
|
7. Write a brief summary to `{{summaryPath}}`:
|
|
26
22
|
- Quick tasks operate outside the milestone/slice/task DB structure, so `gsd_summary_save` (which requires a `milestone_id`) cannot be used here. Write the file directly.
|
|
27
23
|
|
|
@@ -27,13 +27,13 @@ Roadmap, slice summaries, assessments, requirements, decisions, and project cont
|
|
|
27
27
|
Call `subagent` with `tasks: [...]` containing ALL THREE reviewers simultaneously:
|
|
28
28
|
|
|
29
29
|
**Reviewer A - Requirements Coverage**
|
|
30
|
-
Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.gsd/
|
|
30
|
+
Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.gsd/REQUIREMENTS.md` or use the inlined requirements context. For each requirement, check slice SUMMARY files under `.gsd/milestones/{{milestoneId}}/slices/` and mark COVERED, PARTIAL, or MISSING. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
|
|
31
31
|
|
|
32
32
|
**Reviewer B - Cross-Slice Integration**
|
|
33
33
|
Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Read `{{roadmapPath}}` and find the boundary map (produces/consumes contracts). For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
|
|
34
34
|
|
|
35
35
|
**Reviewer C - Assessment & Acceptance Criteria**
|
|
36
|
-
Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/{{milestoneId}}/CONTEXT.md` for criteria. Check slice
|
|
36
|
+
Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md` for criteria. Check slice SUMMARY/UAT files under `.gsd/milestones/{{milestoneId}}/slices/`. Verify each criterion maps to passing evidence. Then review inlined milestone verification classes. For each non-empty planned class, output table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered, NEEDS-ATTENTION if gaps exist."
|
|
37
37
|
|
|
38
38
|
### Step 2 - Synthesize Findings
|
|
39
39
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* Quick tasks live in `.gsd/quick/` and are tracked in STATE.md's
|
|
9
9
|
* "Quick Tasks Completed" table.
|
|
10
10
|
*/
|
|
11
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
12
|
-
import { join } from "node:path";
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
13
13
|
import { loadPrompt } from "./prompt-loader.js";
|
|
14
14
|
import { gsdRoot } from "./paths.js";
|
|
15
15
|
import { GitServiceImpl, runGit } from "./git-service.js";
|
|
@@ -64,6 +64,37 @@ function ensureQuickDir(basePath, taskNum, slug) {
|
|
|
64
64
|
mkdirSync(taskDir, { recursive: true });
|
|
65
65
|
return taskDir;
|
|
66
66
|
}
|
|
67
|
+
function isPathInside(parent, child) {
|
|
68
|
+
const rel = relative(parent, child);
|
|
69
|
+
return rel === "" || (!!rel && !rel.startsWith("..") && !isAbsolute(rel));
|
|
70
|
+
}
|
|
71
|
+
function isExternalGsdRoot(basePath, root) {
|
|
72
|
+
try {
|
|
73
|
+
return !isPathInside(realpathSync(basePath), realpathSync(root));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return !isPathInside(basePath, root);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function buildQuickCommitInstruction(basePath, root) {
|
|
80
|
+
const externalState = isExternalGsdRoot(basePath, root);
|
|
81
|
+
if (externalState) {
|
|
82
|
+
return [
|
|
83
|
+
"Commit repo changes atomically, but do not stage or commit `.gsd/quick/...`:",
|
|
84
|
+
" - `.gsd/` resolves outside this git repository, so Git cannot stage quick-task summary files from the project repo.",
|
|
85
|
+
" - Write the quick summary file directly at the requested path; that file is persisted by GSD external state.",
|
|
86
|
+
" - Stage and commit only implementation/test/docs files that live inside the repository.",
|
|
87
|
+
" - If the task only writes quick-task research/summary files and no repository files changed, do not run `git commit`; report that there was nothing in the project repo to commit.",
|
|
88
|
+
].join("\n");
|
|
89
|
+
}
|
|
90
|
+
return [
|
|
91
|
+
"Commit your changes atomically:",
|
|
92
|
+
" - Use conventional commit messages (feat:, fix:, refactor:, etc.)",
|
|
93
|
+
" - Stage only relevant files — never commit secrets or runtime files.",
|
|
94
|
+
" - Commit logical units separately if the task involves distinct changes.",
|
|
95
|
+
" - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.",
|
|
96
|
+
].join("\n");
|
|
97
|
+
}
|
|
67
98
|
function quickReturnStatePath(basePath) {
|
|
68
99
|
return join(gsdRoot(basePath), "runtime", "quick-return.json");
|
|
69
100
|
}
|
|
@@ -198,6 +229,7 @@ export async function handleQuick(args, ctx, pi) {
|
|
|
198
229
|
taskDir: taskDirRel,
|
|
199
230
|
branch: actualBranch,
|
|
200
231
|
summaryPath,
|
|
232
|
+
commitInstruction: buildQuickCommitInstruction(basePath, root),
|
|
201
233
|
date,
|
|
202
234
|
taskNum: String(taskNum),
|
|
203
235
|
slug,
|
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, } from "node:fs";
|
|
15
15
|
import { join, dirname } from "node:path";
|
|
16
16
|
import { randomBytes } from "node:crypto";
|
|
17
|
+
const EXECUTION_TOOL_NAMES = new Set([
|
|
18
|
+
"bash",
|
|
19
|
+
"Bash",
|
|
20
|
+
"gsd_exec",
|
|
21
|
+
"gsd_exec_search",
|
|
22
|
+
"mcp__gsd-workflow__gsd_exec",
|
|
23
|
+
"mcp__gsd-workflow__gsd_exec_search",
|
|
24
|
+
]);
|
|
17
25
|
// ─── Module State ───────────────────────────────────────────────────────────
|
|
18
26
|
let unitEvidence = [];
|
|
19
27
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
@@ -129,11 +137,11 @@ export function clearEvidenceFromDisk(basePath, milestoneId, sliceId, taskId) {
|
|
|
129
137
|
* Exit codes and output are filled in by recordToolResult after execution.
|
|
130
138
|
*/
|
|
131
139
|
export function recordToolCall(toolCallId, toolName, input) {
|
|
132
|
-
if (toolName
|
|
140
|
+
if (EXECUTION_TOOL_NAMES.has(toolName)) {
|
|
133
141
|
unitEvidence.push({
|
|
134
142
|
kind: "bash",
|
|
135
143
|
toolCallId,
|
|
136
|
-
command: String(input.command ?? ""),
|
|
144
|
+
command: String(input.command ?? input.cmd ?? input.query ?? ""),
|
|
137
145
|
exitCode: -1,
|
|
138
146
|
outputSnippet: "",
|
|
139
147
|
timestamp: Date.now(),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Shared Context Mode tool result helpers.
|
|
3
|
+
export function contextModeDisabledResult(operation) {
|
|
4
|
+
return {
|
|
5
|
+
content: [
|
|
6
|
+
{
|
|
7
|
+
type: "text",
|
|
8
|
+
text: `${operation} is disabled by \`context_mode.enabled: false\` in preferences. ` +
|
|
9
|
+
"Remove that override or set it to true to re-enable Context Mode tools.",
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
details: { operation, error: "context_mode_disabled" },
|
|
13
|
+
isError: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
// Scans .gsd/exec/*.meta.json and returns a ranked summary so agents can
|
|
4
4
|
// re-discover past runs without re-executing. Read-only; no DB writes.
|
|
5
5
|
import { searchExecHistory } from "../exec-history.js";
|
|
6
|
+
import { isContextModeEnabled } from "../preferences-types.js";
|
|
7
|
+
import { contextModeDisabledResult } from "./context-mode-tool-result.js";
|
|
6
8
|
export function executeExecSearch(params, opts) {
|
|
9
|
+
if (!isContextModeEnabled(opts.preferences)) {
|
|
10
|
+
return contextModeDisabledResult("gsd_exec_search");
|
|
11
|
+
}
|
|
7
12
|
const searchOpts = {
|
|
8
13
|
query: typeof params.query === "string" ? params.query : undefined,
|
|
9
14
|
runtime: params.runtime,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// for MCP return.
|
|
6
6
|
import { EXEC_DEFAULTS, runExecSandbox, } from "../exec-sandbox.js";
|
|
7
7
|
import { isContextModeEnabled } from "../preferences-types.js";
|
|
8
|
+
import { contextModeDisabledResult } from "./context-mode-tool-result.js";
|
|
8
9
|
export function buildExecOptions(baseDir, cfg, extras) {
|
|
9
10
|
const allowlist = Array.isArray(cfg?.exec_env_allowlist) ? cfg.exec_env_allowlist : EXEC_DEFAULTS.envAllowlist;
|
|
10
11
|
const stdoutCap = clampNumber(cfg?.exec_stdout_cap_bytes, EXEC_DEFAULTS.stdoutCapBytes, 4_096, 16_777_216);
|
|
@@ -33,19 +34,6 @@ function clampNumber(value, fallback, min, max) {
|
|
|
33
34
|
function isEnabled(prefs) {
|
|
34
35
|
return isContextModeEnabled(prefs);
|
|
35
36
|
}
|
|
36
|
-
function disabledResult() {
|
|
37
|
-
return {
|
|
38
|
-
content: [
|
|
39
|
-
{
|
|
40
|
-
type: "text",
|
|
41
|
-
text: "gsd_exec is disabled by `context_mode.enabled: false` in preferences. Remove that " +
|
|
42
|
-
"override (or set it to true) to re-enable sandboxed tool-output execution.",
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
details: { operation: "gsd_exec", error: "context_mode_disabled" },
|
|
46
|
-
isError: true,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
37
|
function paramError(message) {
|
|
50
38
|
return {
|
|
51
39
|
content: [{ type: "text", text: `Error: ${message}` }],
|
|
@@ -55,7 +43,7 @@ function paramError(message) {
|
|
|
55
43
|
}
|
|
56
44
|
export async function executeGsdExec(params, deps) {
|
|
57
45
|
if (!isEnabled(deps.preferences))
|
|
58
|
-
return
|
|
46
|
+
return contextModeDisabledResult("gsd_exec");
|
|
59
47
|
const runtime = params.runtime;
|
|
60
48
|
if (runtime !== "bash" && runtime !== "node" && runtime !== "python") {
|
|
61
49
|
return paramError(`invalid runtime "${String(runtime)}" — must be bash | node | python`);
|
|
@@ -67,7 +55,7 @@ export async function executeGsdExec(params, deps) {
|
|
|
67
55
|
if (Buffer.byteLength(script, "utf8") > 200_000) {
|
|
68
56
|
return paramError("script exceeds the 200 KB length limit");
|
|
69
57
|
}
|
|
70
|
-
const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { now: deps.now, generateId: deps.generateId });
|
|
58
|
+
const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { env: deps.env, now: deps.now, generateId: deps.generateId });
|
|
71
59
|
const run = deps.run ?? runExecSandbox;
|
|
72
60
|
try {
|
|
73
61
|
const result = await run({
|
|
@@ -8,6 +8,7 @@ import { renderAllProjections } from "../workflow-projections.js";
|
|
|
8
8
|
import { writeManifest } from "../workflow-manifest.js";
|
|
9
9
|
import { appendEvent } from "../workflow-events.js";
|
|
10
10
|
import { logWarning } from "../workflow-logger.js";
|
|
11
|
+
import { validatePlanningPathScope } from "../planning-path-scope.js";
|
|
11
12
|
function validateTasks(value) {
|
|
12
13
|
if (!Array.isArray(value) || value.length === 0) {
|
|
13
14
|
throw new Error("tasks must be a non-empty array");
|
|
@@ -91,6 +92,14 @@ export async function handlePlanSlice(rawParams, basePath) {
|
|
|
91
92
|
catch (err) {
|
|
92
93
|
return { error: `validation failed: ${err.message}` };
|
|
93
94
|
}
|
|
95
|
+
const pathScopeError = validatePlanningPathScope(basePath, params.tasks.flatMap((task, index) => [
|
|
96
|
+
{ field: `tasks[${index}].files`, values: task.files },
|
|
97
|
+
{ field: `tasks[${index}].inputs`, values: task.inputs },
|
|
98
|
+
{ field: `tasks[${index}].expectedOutput`, values: task.expectedOutput },
|
|
99
|
+
]));
|
|
100
|
+
if (pathScopeError) {
|
|
101
|
+
return { error: `validation failed: ${pathScopeError}` };
|
|
102
|
+
}
|
|
94
103
|
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
95
104
|
// Guards must be inside the transaction so the state they check cannot
|
|
96
105
|
// change between the read and the write (#2723).
|
|
@@ -8,6 +8,7 @@ import { renderAllProjections } from "../workflow-projections.js";
|
|
|
8
8
|
import { writeManifest } from "../workflow-manifest.js";
|
|
9
9
|
import { appendEvent } from "../workflow-events.js";
|
|
10
10
|
import { logWarning } from "../workflow-logger.js";
|
|
11
|
+
import { validatePlanningPathScope } from "../planning-path-scope.js";
|
|
11
12
|
function validateParams(params) {
|
|
12
13
|
if (!isNonEmptyString(params?.milestoneId))
|
|
13
14
|
throw new Error("milestoneId is required");
|
|
@@ -41,6 +42,14 @@ export async function handlePlanTask(rawParams, basePath) {
|
|
|
41
42
|
catch (err) {
|
|
42
43
|
return { error: `validation failed: ${err.message}` };
|
|
43
44
|
}
|
|
45
|
+
const pathScopeError = validatePlanningPathScope(basePath, [
|
|
46
|
+
{ field: "files", values: params.files },
|
|
47
|
+
{ field: "inputs", values: params.inputs },
|
|
48
|
+
{ field: "expectedOutput", values: params.expectedOutput },
|
|
49
|
+
]);
|
|
50
|
+
if (pathScopeError) {
|
|
51
|
+
return { error: `validation failed: ${pathScopeError}` };
|
|
52
|
+
}
|
|
44
53
|
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
45
54
|
// Guards must be inside the transaction so the state they check cannot
|
|
46
55
|
// change between the read and the write (#2723).
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
// agents can re-orient after compaction or session resume without
|
|
3
3
|
// re-deriving project memory state.
|
|
4
4
|
import { readCompactionSnapshot } from "../compaction-snapshot.js";
|
|
5
|
+
import { isContextModeEnabled } from "../preferences-types.js";
|
|
6
|
+
import { contextModeDisabledResult } from "./context-mode-tool-result.js";
|
|
5
7
|
export function executeResume(_params, opts) {
|
|
8
|
+
if (!isContextModeEnabled(opts.preferences)) {
|
|
9
|
+
return contextModeDisabledResult("gsd_resume");
|
|
10
|
+
}
|
|
6
11
|
const snapshot = readCompactionSnapshot(opts.baseDir);
|
|
7
12
|
if (snapshot == null) {
|
|
8
13
|
return {
|
|
@@ -680,7 +680,7 @@ export async function executeMilestoneStatus(params, basePath = process.cwd()) {
|
|
|
680
680
|
};
|
|
681
681
|
return {
|
|
682
682
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
683
|
-
details: { operation: "milestone_status",
|
|
683
|
+
details: { operation: "milestone_status", ...result },
|
|
684
684
|
};
|
|
685
685
|
});
|
|
686
686
|
}
|
|
@@ -80,7 +80,15 @@ const CONTEXT_MODE_LANE_LABELS = {
|
|
|
80
80
|
orchestration: "orchestration",
|
|
81
81
|
docs: "documentation",
|
|
82
82
|
};
|
|
83
|
-
const
|
|
83
|
+
const CONTEXT_MODE_GUIDANCE_BY_LANE = {
|
|
84
|
+
interview: "Use `gsd_resume` to restore prior discussion, `gsd_exec` for noisy discovery, and `gsd_exec_search` before repeating scans.",
|
|
85
|
+
research: "Use `gsd_exec` for noisy research scans, `gsd_exec_search` before reruns, and `gsd_resume` to restore prior findings.",
|
|
86
|
+
planning: "Use `gsd_resume` for planning continuity, `gsd_exec` for noisy checks, and `gsd_exec_search` before rerunning diagnostics.",
|
|
87
|
+
execution: "Use `gsd_exec` for builds, tests, and diagnostics, `gsd_exec_search` before reruns, and `gsd_resume` after compaction or resume.",
|
|
88
|
+
verification: "Use `gsd_exec` for verification commands, `gsd_exec_search` to reuse prior evidence, and `gsd_resume` after compaction or resume.",
|
|
89
|
+
orchestration: "Use `gsd_resume` before resuming orchestration, `gsd_exec_search` to reuse prior runs, and `gsd_exec` for noisy coordination checks.",
|
|
90
|
+
docs: "Use `gsd_resume` for prior context, `gsd_exec_search` for saved evidence, and `gsd_exec` for noisy doc validation commands.",
|
|
91
|
+
};
|
|
84
92
|
/**
|
|
85
93
|
* Render the Context Mode instruction lane for a unit type. Unknown unit
|
|
86
94
|
* types, disabled config, and explicit `contextMode: "none"` all omit the
|
|
@@ -93,14 +101,15 @@ export function composeContextModeInstructions(unitType, opts) {
|
|
|
93
101
|
if (!manifest || manifest.contextMode === "none")
|
|
94
102
|
return "";
|
|
95
103
|
const lane = CONTEXT_MODE_LANE_LABELS[manifest.contextMode];
|
|
104
|
+
const guidance = CONTEXT_MODE_GUIDANCE_BY_LANE[manifest.contextMode];
|
|
96
105
|
if (opts.renderMode === "nested") {
|
|
97
|
-
return `Context Mode (${lane} lane): ${
|
|
106
|
+
return `Context Mode (${lane} lane): ${guidance}`;
|
|
98
107
|
}
|
|
99
108
|
return [
|
|
100
109
|
"## Context Mode",
|
|
101
110
|
"",
|
|
102
111
|
`Lane: **${lane} lane**.`,
|
|
103
|
-
|
|
112
|
+
guidance,
|
|
104
113
|
].join("\n");
|
|
105
114
|
}
|
|
106
115
|
const SECTION_SEPARATOR = "\n\n---\n\n";
|
|
@@ -4,6 +4,8 @@ import { atomicWriteSync } from "./atomic-write.js";
|
|
|
4
4
|
import { gsdRoot, relSliceFile, relTaskFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
|
|
5
5
|
import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
|
|
6
6
|
import { parseUnitId } from "./unit-id.js";
|
|
7
|
+
import { getTask, isDbAvailable, refreshOpenDatabaseFromDisk } from "./gsd-db.js";
|
|
8
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
7
9
|
// Per-record advisory lock — prevents read-modify-write races between
|
|
8
10
|
// concurrent writers updating disjoint fields of the same runtime record.
|
|
9
11
|
// Within a single Node process this is moot (writeUnitRuntimeRecord is sync),
|
|
@@ -67,6 +69,17 @@ function withRecordLock(recordPath, fn) {
|
|
|
67
69
|
catch { /* best-effort */ }
|
|
68
70
|
}
|
|
69
71
|
}
|
|
72
|
+
export const IN_FLIGHT_RUNTIME_PHASES = new Set([
|
|
73
|
+
"dispatched",
|
|
74
|
+
"wrapup-warning-sent",
|
|
75
|
+
"timeout",
|
|
76
|
+
"finalize-timeout",
|
|
77
|
+
"crashed",
|
|
78
|
+
"paused",
|
|
79
|
+
]);
|
|
80
|
+
export function isInFlightRuntimePhase(phase) {
|
|
81
|
+
return IN_FLIGHT_RUNTIME_PHASES.has(phase);
|
|
82
|
+
}
|
|
70
83
|
function runtimeDir(basePath) {
|
|
71
84
|
return join(gsdRoot(basePath), "runtime", "units");
|
|
72
85
|
}
|
|
@@ -154,6 +167,12 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
|
|
|
154
167
|
const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
155
168
|
const taskChecked = !!planContent && new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m").test(planContent);
|
|
156
169
|
const nextActionAdvanced = !new RegExp(`Execute ${tid}\\b`).test(stateContent);
|
|
170
|
+
let dbComplete = false;
|
|
171
|
+
if (isDbAvailable()) {
|
|
172
|
+
refreshOpenDatabaseFromDisk();
|
|
173
|
+
const task = getTask(mid, sid, tid);
|
|
174
|
+
dbComplete = !!task && isClosedStatus(task.status);
|
|
175
|
+
}
|
|
157
176
|
// Must-have coverage: load task plan and count mentions in summary
|
|
158
177
|
let mustHaveCount = 0;
|
|
159
178
|
let mustHavesMentionedInSummary = 0;
|
|
@@ -177,11 +196,14 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
|
|
|
177
196
|
summaryExists,
|
|
178
197
|
taskChecked,
|
|
179
198
|
nextActionAdvanced,
|
|
199
|
+
dbComplete,
|
|
180
200
|
mustHaveCount,
|
|
181
201
|
mustHavesMentionedInSummary,
|
|
182
202
|
};
|
|
183
203
|
}
|
|
184
204
|
export function formatExecuteTaskRecoveryStatus(status) {
|
|
205
|
+
if (status.dbComplete)
|
|
206
|
+
return "DB task status is closed";
|
|
185
207
|
const missing = [];
|
|
186
208
|
if (!status.summaryExists)
|
|
187
209
|
missing.push(`summary missing (${status.summaryPath})`);
|
|
@@ -22,6 +22,16 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
22
22
|
import { nativeBranchDelete, nativeBranchExists, nativeBranchForceReset, nativeCommit, nativeDetectMainBranch, nativeDiffContent, nativeDiffNameStatus, nativeDiffNumstat, nativeGetCurrentBranch, nativeIsAncestor, nativeLogOneline, nativeMergeSquash, nativeWorktreeAdd, nativeWorktreeList, nativeWorktreePrune, nativeWorktreeRemove, } from "./native-git-bridge.js";
|
|
23
23
|
import { emitCanonicalRootRedirect } from "./worktree-telemetry.js";
|
|
24
24
|
import { isGsdWorktreePath, normalizeWorktreePathForCompare, resolveWorktreeProjectRoot, } from "./worktree-root.js";
|
|
25
|
+
function deleteBranchIfPresent(basePath, branch, warningPrefix) {
|
|
26
|
+
try {
|
|
27
|
+
if (!nativeBranchExists(basePath, branch))
|
|
28
|
+
return;
|
|
29
|
+
nativeBranchDelete(basePath, branch, true);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
logWarning("worktree", `${warningPrefix}: ${e.message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
25
35
|
// ─── Path Helpers ──────────────────────────────────────────────────────────
|
|
26
36
|
function normalizePathForComparison(path) {
|
|
27
37
|
const normalized = path
|
|
@@ -311,7 +321,7 @@ export function listWorktrees(basePath) {
|
|
|
311
321
|
// of their object database, causing permanent silent data loss.
|
|
312
322
|
/** Directories to skip when scanning for nested .git dirs. */
|
|
313
323
|
const NESTED_GIT_SKIP_DIRS = new Set([
|
|
314
|
-
".git", ".gsd", "node_modules", ".next", ".nuxt", "dist", "build",
|
|
324
|
+
".git", ".gsd", ".bg-shell", "node_modules", ".next", ".nuxt", "dist", "build",
|
|
315
325
|
"__pycache__", ".tox", ".venv", "venv", "target", "vendor",
|
|
316
326
|
]);
|
|
317
327
|
/**
|
|
@@ -364,7 +374,9 @@ export function findNestedGitDirs(rootPath) {
|
|
|
364
374
|
}
|
|
365
375
|
}
|
|
366
376
|
catch (e) {
|
|
367
|
-
|
|
377
|
+
if (e.code !== "ENOENT") {
|
|
378
|
+
logWarning("worktree", `existsSync/.git check failed for ${fullPath}: ${e.message}`);
|
|
379
|
+
}
|
|
368
380
|
}
|
|
369
381
|
walk(fullPath, depth + 1);
|
|
370
382
|
}
|
|
@@ -430,12 +442,7 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
430
442
|
if (!existsSync(wtPath)) {
|
|
431
443
|
nativeWorktreePrune(basePath);
|
|
432
444
|
if (deleteBranch) {
|
|
433
|
-
|
|
434
|
-
nativeBranchDelete(basePath, branch, true);
|
|
435
|
-
}
|
|
436
|
-
catch (e) {
|
|
437
|
-
logWarning("worktree", `nativeBranchDelete failed: ${e.message}`);
|
|
438
|
-
}
|
|
445
|
+
deleteBranchIfPresent(basePath, branch, "nativeBranchDelete failed");
|
|
439
446
|
}
|
|
440
447
|
return;
|
|
441
448
|
}
|
|
@@ -549,12 +556,7 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
549
556
|
// Prune stale entries so git knows the worktree is gone
|
|
550
557
|
nativeWorktreePrune(basePath);
|
|
551
558
|
if (deleteBranch) {
|
|
552
|
-
|
|
553
|
-
nativeBranchDelete(basePath, branch, true);
|
|
554
|
-
}
|
|
555
|
-
catch (e) {
|
|
556
|
-
logWarning("worktree", `final branch delete failed: ${e.message}`);
|
|
557
|
-
}
|
|
559
|
+
deleteBranchIfPresent(basePath, branch, "final branch delete failed");
|
|
558
560
|
}
|
|
559
561
|
}
|
|
560
562
|
/**
|