gsd-pi 2.80.0-dev.2be7caf18 → 2.80.0-dev.3065f7bfa
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 +1 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/phases.js +178 -108
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +20 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +90 -15
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
- package/dist/resources/extensions/gsd/auto-start.js +197 -6
- 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-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +79 -24
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +42 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +238 -28
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
- package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- 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/ecosystem/gsd-extension-api.js +2 -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 +66 -32
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-runtime.js +11 -0
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
- 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 +15 -15
- 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 +15 -15
- 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/src/workflow-tools.test.ts +9 -2
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +2 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
- package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
- package/packages/pi-agent-core/dist/token-audit.js +221 -0
- package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
- package/packages/pi-agent-core/dist/types.d.ts +9 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-agent-core/src/agent.ts +8 -0
- package/packages/pi-agent-core/src/index.ts +2 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +14 -0
- package/packages/pi-agent-core/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-tool-refresh.test.js +18 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +41 -7
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -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 -6
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +3 -3
- 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 +32 -1
- 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/hooks-runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.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-tool-refresh.test.ts +25 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +45 -7
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +3 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +5 -5
- package/packages/pi-coding-agent/src/core/extensions/types.ts +35 -1
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/phases.ts +251 -172
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +25 -30
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +95 -14
- package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
- package/src/resources/extensions/gsd/auto-start.ts +230 -9
- 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-worktree.ts +123 -0
- package/src/resources/extensions/gsd/auto.ts +87 -19
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +10 -3
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +283 -28
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
- package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- 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/ecosystem/gsd-extension-api.ts +3 -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 +84 -39
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
- package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +417 -10
- 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/auto-wrapup-inflight-guard.test.ts +168 -6
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -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 +38 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-runtime.ts +11 -0
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
- /package/dist/web/standalone/.next/static/{3EDDd9ULaybSupPoA_vf- → O2WvnXROue6l7nAp_4dhC}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{3EDDd9ULaybSupPoA_vf- → O2WvnXROue6l7nAp_4dhC}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Tests for opt-in GSD tool surface reduction.
|
|
3
|
+
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import { buildMinimalAutoGsdToolSet, buildMinimalGsdToolSet, buildMinimalGsdWorkflowToolSet, buildRequestScopedGsdToolSet, MINIMAL_AUTO_BASE_TOOL_NAMES, MINIMAL_GSD_TOOL_NAMES, restoreGsdWorkflowTools, scopeGsdWorkflowToolsForDispatch } from "../bootstrap/register-hooks.ts";
|
|
8
|
+
|
|
9
|
+
test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surface", () => {
|
|
10
|
+
const result = buildMinimalGsdToolSet([
|
|
11
|
+
"bash",
|
|
12
|
+
"read",
|
|
13
|
+
"browser_open",
|
|
14
|
+
"gsd_plan_milestone",
|
|
15
|
+
"gsd_task_complete",
|
|
16
|
+
"gsd_exec",
|
|
17
|
+
"gsd_exec_search",
|
|
18
|
+
"gsd_resume",
|
|
19
|
+
"gsd_milestone_status",
|
|
20
|
+
"gsd_checkpoint_db",
|
|
21
|
+
"memory_query",
|
|
22
|
+
"capture_thought",
|
|
23
|
+
"gsd_graph",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
assert.ok(result.includes("bash"));
|
|
27
|
+
assert.ok(result.includes("read"));
|
|
28
|
+
assert.ok(result.includes("browser_open"));
|
|
29
|
+
for (const toolName of MINIMAL_GSD_TOOL_NAMES) {
|
|
30
|
+
assert.ok(result.includes(toolName), `expected ${toolName}`);
|
|
31
|
+
}
|
|
32
|
+
assert.ok(!result.includes("gsd_plan_milestone"));
|
|
33
|
+
assert.ok(!result.includes("gsd_task_complete"));
|
|
34
|
+
assert.ok(!result.includes("gsd_graph"));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("buildMinimalGsdToolSet deduplicates preserved and minimal tools", () => {
|
|
38
|
+
const result = buildMinimalGsdToolSet(["bash", "bash", "memory_query"]);
|
|
39
|
+
|
|
40
|
+
assert.deepEqual(result.filter((toolName) => toolName === "bash"), ["bash"]);
|
|
41
|
+
assert.deepEqual(result.filter((toolName) => toolName === "memory_query"), ["memory_query"]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("buildMinimalGsdToolSet does not reintroduce provider-filtered GSD tools", () => {
|
|
45
|
+
const result = buildMinimalGsdToolSet(["bash", "read", "memory_query"]);
|
|
46
|
+
|
|
47
|
+
assert.deepEqual(result, ["bash", "read", "memory_query"]);
|
|
48
|
+
assert.ok(!result.includes("gsd_exec"));
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("buildMinimalAutoGsdToolSet keeps unit-specific completion tools without aliases", () => {
|
|
52
|
+
const result = buildMinimalAutoGsdToolSet([
|
|
53
|
+
"ask_user_questions",
|
|
54
|
+
"bash",
|
|
55
|
+
"read",
|
|
56
|
+
"lsp",
|
|
57
|
+
"browser_click",
|
|
58
|
+
"gsd_task_complete",
|
|
59
|
+
"gsd_complete_task",
|
|
60
|
+
"gsd_exec",
|
|
61
|
+
"gsd_exec_search",
|
|
62
|
+
"gsd_resume",
|
|
63
|
+
"gsd_milestone_status",
|
|
64
|
+
"gsd_checkpoint_db",
|
|
65
|
+
"gsd_slice_complete",
|
|
66
|
+
"gsd_complete_slice",
|
|
67
|
+
"memory_query",
|
|
68
|
+
"capture_thought",
|
|
69
|
+
], "execute-task");
|
|
70
|
+
|
|
71
|
+
assert.ok(result.includes("ask_user_questions"));
|
|
72
|
+
assert.ok(result.includes("bash"));
|
|
73
|
+
assert.ok(result.includes("read"));
|
|
74
|
+
assert.ok(result.includes("gsd_task_complete"));
|
|
75
|
+
assert.ok(result.includes("memory_query"));
|
|
76
|
+
assert.ok(!result.includes("lsp"));
|
|
77
|
+
assert.ok(!result.includes("browser_click"));
|
|
78
|
+
assert.ok(!result.includes("gsd_complete_task"));
|
|
79
|
+
assert.ok(!result.includes("gsd_slice_complete"));
|
|
80
|
+
assert.ok(!result.includes("gsd_complete_slice"));
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("buildMinimalAutoGsdToolSet keeps only the auto base non-GSD tools", () => {
|
|
84
|
+
const result = buildMinimalAutoGsdToolSet([
|
|
85
|
+
"ask_user_questions",
|
|
86
|
+
"bash",
|
|
87
|
+
"bg_shell",
|
|
88
|
+
"browser_wait_for",
|
|
89
|
+
"edit",
|
|
90
|
+
"glob",
|
|
91
|
+
"grep",
|
|
92
|
+
"lsp",
|
|
93
|
+
"ls",
|
|
94
|
+
"mac_find",
|
|
95
|
+
"read",
|
|
96
|
+
"subagent",
|
|
97
|
+
"write",
|
|
98
|
+
"gsd_exec",
|
|
99
|
+
"gsd_exec_search",
|
|
100
|
+
"gsd_resume",
|
|
101
|
+
"gsd_milestone_status",
|
|
102
|
+
"gsd_checkpoint_db",
|
|
103
|
+
"memory_query",
|
|
104
|
+
"capture_thought",
|
|
105
|
+
], "execute-task");
|
|
106
|
+
|
|
107
|
+
for (const toolName of MINIMAL_AUTO_BASE_TOOL_NAMES) {
|
|
108
|
+
assert.ok(result.includes(toolName), `expected ${toolName}`);
|
|
109
|
+
}
|
|
110
|
+
assert.ok(!result.includes("browser_wait_for"));
|
|
111
|
+
assert.ok(!result.includes("lsp"));
|
|
112
|
+
assert.ok(!result.includes("mac_find"));
|
|
113
|
+
assert.ok(!result.includes("subagent"));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("buildMinimalAutoGsdToolSet includes closeout tool for complete-slice", () => {
|
|
117
|
+
const result = buildMinimalAutoGsdToolSet([
|
|
118
|
+
"bash",
|
|
119
|
+
"read",
|
|
120
|
+
"subagent",
|
|
121
|
+
"gsd_exec",
|
|
122
|
+
"gsd_exec_search",
|
|
123
|
+
"gsd_resume",
|
|
124
|
+
"gsd_milestone_status",
|
|
125
|
+
"gsd_checkpoint_db",
|
|
126
|
+
"gsd_task_complete",
|
|
127
|
+
"gsd_slice_complete",
|
|
128
|
+
"gsd_complete_slice",
|
|
129
|
+
"memory_query",
|
|
130
|
+
"capture_thought",
|
|
131
|
+
], "complete-slice");
|
|
132
|
+
|
|
133
|
+
assert.ok(result.includes("gsd_slice_complete"));
|
|
134
|
+
assert.ok(result.includes("subagent"));
|
|
135
|
+
assert.ok(result.includes("capture_thought"));
|
|
136
|
+
assert.ok(!result.includes("gsd_task_complete"));
|
|
137
|
+
assert.ok(!result.includes("gsd_complete_slice"));
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("buildMinimalAutoGsdToolSet covers execute-task-simple", () => {
|
|
141
|
+
const result = buildMinimalAutoGsdToolSet([
|
|
142
|
+
"bash",
|
|
143
|
+
"read",
|
|
144
|
+
"gsd_task_complete",
|
|
145
|
+
"gsd_decision_save",
|
|
146
|
+
"gsd_plan_task",
|
|
147
|
+
"memory_query",
|
|
148
|
+
"capture_thought",
|
|
149
|
+
], "execute-task-simple");
|
|
150
|
+
|
|
151
|
+
assert.ok(result.includes("gsd_task_complete"));
|
|
152
|
+
assert.ok(result.includes("gsd_decision_save"));
|
|
153
|
+
assert.ok(!result.includes("gsd_plan_task"));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("buildMinimalGsdWorkflowToolSet keeps workflow GSD tools but drops broad non-GSD tools", () => {
|
|
157
|
+
const result = buildMinimalGsdWorkflowToolSet([
|
|
158
|
+
"ask_user_questions",
|
|
159
|
+
"bash",
|
|
160
|
+
"bg_shell",
|
|
161
|
+
"browser_wait_for",
|
|
162
|
+
"edit",
|
|
163
|
+
"lsp",
|
|
164
|
+
"mac_find",
|
|
165
|
+
"read",
|
|
166
|
+
"subagent",
|
|
167
|
+
"write",
|
|
168
|
+
"gsd_plan_milestone",
|
|
169
|
+
"gsd_complete_milestone",
|
|
170
|
+
"gsd_task_complete",
|
|
171
|
+
"gsd_summary_save",
|
|
172
|
+
"memory_query",
|
|
173
|
+
"capture_thought",
|
|
174
|
+
"gsd_exec",
|
|
175
|
+
"gsd_exec_search",
|
|
176
|
+
"gsd_resume",
|
|
177
|
+
"gsd_milestone_status",
|
|
178
|
+
"gsd_checkpoint_db",
|
|
179
|
+
"gsd_graph",
|
|
180
|
+
]);
|
|
181
|
+
|
|
182
|
+
assert.ok(result.includes("ask_user_questions"));
|
|
183
|
+
assert.ok(result.includes("bash"));
|
|
184
|
+
assert.ok(result.includes("bg_shell"));
|
|
185
|
+
assert.ok(result.includes("read"));
|
|
186
|
+
assert.ok(result.includes("write"));
|
|
187
|
+
assert.ok(result.includes("gsd_plan_milestone"));
|
|
188
|
+
assert.ok(result.includes("gsd_complete_milestone"));
|
|
189
|
+
assert.ok(result.includes("gsd_task_complete"));
|
|
190
|
+
assert.ok(result.includes("gsd_summary_save"));
|
|
191
|
+
assert.ok(!result.includes("browser_wait_for"));
|
|
192
|
+
assert.ok(!result.includes("lsp"));
|
|
193
|
+
assert.ok(!result.includes("mac_find"));
|
|
194
|
+
assert.ok(!result.includes("subagent"));
|
|
195
|
+
assert.ok(!result.includes("gsd_graph"));
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("buildRequestScopedGsdToolSet scopes queued workflow custom-message requests", () => {
|
|
199
|
+
const result = buildRequestScopedGsdToolSet([
|
|
200
|
+
"ask_user_questions",
|
|
201
|
+
"bash",
|
|
202
|
+
"browser_wait_for",
|
|
203
|
+
"lsp",
|
|
204
|
+
"read",
|
|
205
|
+
"write",
|
|
206
|
+
"gsd_plan_milestone",
|
|
207
|
+
"gsd_complete_milestone",
|
|
208
|
+
"gsd_task_complete",
|
|
209
|
+
"gsd_graph",
|
|
210
|
+
"memory_query",
|
|
211
|
+
"capture_thought",
|
|
212
|
+
], [{ customType: "gsd-run" }, { customType: "gsd-memory" }]);
|
|
213
|
+
|
|
214
|
+
assert.ok(result);
|
|
215
|
+
assert.ok(result.includes("ask_user_questions"));
|
|
216
|
+
assert.ok(result.includes("bash"));
|
|
217
|
+
assert.ok(result.includes("read"));
|
|
218
|
+
assert.ok(result.includes("write"));
|
|
219
|
+
assert.ok(result.includes("gsd_plan_milestone"));
|
|
220
|
+
assert.ok(result.includes("gsd_complete_milestone"));
|
|
221
|
+
assert.ok(!result.includes("browser_wait_for"));
|
|
222
|
+
assert.ok(!result.includes("lsp"));
|
|
223
|
+
assert.ok(!result.includes("gsd_graph"));
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("buildRequestScopedGsdToolSet ignores stale workflow messages outside the current request tail", () => {
|
|
227
|
+
assert.equal(buildRequestScopedGsdToolSet(["bash", "gsd_plan_milestone"], []), undefined);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test("scopeGsdWorkflowToolsForDispatch applies and restores per-unit skill visibility", () => {
|
|
231
|
+
const calls: Array<{ kind: "tools" | "skills"; value: string[] | undefined }> = [];
|
|
232
|
+
let activeTools = [
|
|
233
|
+
"bash",
|
|
234
|
+
"read",
|
|
235
|
+
"lsp",
|
|
236
|
+
"gsd_plan_milestone",
|
|
237
|
+
"gsd_decision_save",
|
|
238
|
+
"memory_query",
|
|
239
|
+
"capture_thought",
|
|
240
|
+
];
|
|
241
|
+
let visibleSkills: string[] | undefined = ["previous-skill"];
|
|
242
|
+
|
|
243
|
+
const state = scopeGsdWorkflowToolsForDispatch({
|
|
244
|
+
getActiveTools: () => activeTools,
|
|
245
|
+
setActiveTools: (names) => {
|
|
246
|
+
activeTools = names;
|
|
247
|
+
calls.push({ kind: "tools", value: names });
|
|
248
|
+
},
|
|
249
|
+
getVisibleSkills: () => visibleSkills,
|
|
250
|
+
setVisibleSkills: (names) => {
|
|
251
|
+
visibleSkills = names;
|
|
252
|
+
calls.push({ kind: "skills", value: names });
|
|
253
|
+
},
|
|
254
|
+
}, "plan-milestone");
|
|
255
|
+
|
|
256
|
+
assert.ok(state);
|
|
257
|
+
assert.deepEqual(visibleSkills, [
|
|
258
|
+
"write-milestone-brief",
|
|
259
|
+
"decompose-into-slices",
|
|
260
|
+
"design-an-interface",
|
|
261
|
+
"grill-me",
|
|
262
|
+
"write-docs",
|
|
263
|
+
"api-design",
|
|
264
|
+
"tdd",
|
|
265
|
+
"verify-before-complete",
|
|
266
|
+
]);
|
|
267
|
+
assert.ok(!activeTools.includes("lsp"));
|
|
268
|
+
|
|
269
|
+
restoreGsdWorkflowTools({
|
|
270
|
+
setActiveTools: (names) => {
|
|
271
|
+
activeTools = names;
|
|
272
|
+
calls.push({ kind: "tools", value: names });
|
|
273
|
+
},
|
|
274
|
+
setVisibleSkills: (names) => {
|
|
275
|
+
visibleSkills = names;
|
|
276
|
+
calls.push({ kind: "skills", value: names });
|
|
277
|
+
},
|
|
278
|
+
}, state);
|
|
279
|
+
|
|
280
|
+
assert.deepEqual(activeTools, [
|
|
281
|
+
"bash",
|
|
282
|
+
"read",
|
|
283
|
+
"lsp",
|
|
284
|
+
"gsd_plan_milestone",
|
|
285
|
+
"gsd_decision_save",
|
|
286
|
+
"memory_query",
|
|
287
|
+
"capture_thought",
|
|
288
|
+
]);
|
|
289
|
+
assert.deepEqual(visibleSkills, ["previous-skill"]);
|
|
290
|
+
assert.equal(calls.filter((call) => call.kind === "skills").length, 2);
|
|
291
|
+
});
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
markFailed,
|
|
22
22
|
markStuck,
|
|
23
23
|
markCanceled,
|
|
24
|
+
markLatestActiveForWorkerCanceled,
|
|
24
25
|
getRecentForUnit,
|
|
25
26
|
getLatestForUnit,
|
|
26
27
|
} from "../db/unit-dispatches.ts";
|
|
@@ -196,6 +197,35 @@ test("markStuck and markCanceled set their respective statuses", (t) => {
|
|
|
196
197
|
assert.equal(getLatestForUnit("M001/S01/T01")!.status, "canceled");
|
|
197
198
|
});
|
|
198
199
|
|
|
200
|
+
test("markLatestActiveForWorkerCanceled cancels only the latest active dispatch for a worker", (t) => {
|
|
201
|
+
const base = makeBase();
|
|
202
|
+
t.after(() => cleanup(base));
|
|
203
|
+
const { workerId, leaseToken } = setup(base);
|
|
204
|
+
|
|
205
|
+
const first = recordDispatchClaim({
|
|
206
|
+
traceId: "tc-1", workerId, milestoneLeaseToken: leaseToken,
|
|
207
|
+
milestoneId: "M001", unitType: "plan-slice", unitId: "M001/S01",
|
|
208
|
+
});
|
|
209
|
+
assert.equal(first.ok, true);
|
|
210
|
+
if (!first.ok) return;
|
|
211
|
+
markCompleted(first.dispatchId);
|
|
212
|
+
|
|
213
|
+
const second = recordDispatchClaim({
|
|
214
|
+
traceId: "tc-2", workerId, milestoneLeaseToken: leaseToken,
|
|
215
|
+
milestoneId: "M001", unitType: "run-task", unitId: "M001/S01/T01",
|
|
216
|
+
});
|
|
217
|
+
assert.equal(second.ok, true);
|
|
218
|
+
if (!second.ok) return;
|
|
219
|
+
markRunning(second.dispatchId);
|
|
220
|
+
|
|
221
|
+
assert.equal(markLatestActiveForWorkerCanceled(workerId, "signal-exit"), true);
|
|
222
|
+
assert.equal(getLatestForUnit("M001/S01")!.status, "completed");
|
|
223
|
+
const latest = getLatestForUnit("M001/S01/T01")!;
|
|
224
|
+
assert.equal(latest.status, "canceled");
|
|
225
|
+
assert.equal(latest.exit_reason, "signal-exit");
|
|
226
|
+
assert.equal(markLatestActiveForWorkerCanceled(workerId, "signal-exit"), false);
|
|
227
|
+
});
|
|
228
|
+
|
|
199
229
|
test("terminal transitions do not overwrite an already terminal dispatch", (t) => {
|
|
200
230
|
const base = makeBase();
|
|
201
231
|
t.after(() => cleanup(base));
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
readUnitRuntimeRecord,
|
|
10
10
|
writeUnitRuntimeRecord,
|
|
11
11
|
} from "../unit-runtime.ts";
|
|
12
|
+
import { closeDatabase, insertMilestone, insertSlice, insertTask, openDatabase } from "../gsd-db.ts";
|
|
12
13
|
import { clearPathCache } from '../paths.ts';
|
|
13
14
|
import { test } from 'node:test';
|
|
14
15
|
import assert from 'node:assert/strict';
|
|
@@ -72,6 +73,35 @@ console.log("\n=== runtime record cleanup ===");
|
|
|
72
73
|
assert.deepStrictEqual(loaded, null, "record removed");
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
console.log("\n=== execute-task durability trusts closed DB task status ===");
|
|
77
|
+
{
|
|
78
|
+
const dbBase = mkdtempSync(join(tmpdir(), "gsd-unit-runtime-db-test-"));
|
|
79
|
+
mkdirSync(join(dbBase, ".gsd", "milestones", "M300", "slices", "S01", "tasks"), { recursive: true });
|
|
80
|
+
try {
|
|
81
|
+
openDatabase(join(dbBase, ".gsd", "gsd.db"));
|
|
82
|
+
insertMilestone({ id: "M300", title: "DB Milestone", status: "active" });
|
|
83
|
+
insertSlice({ id: "S01", milestoneId: "M300", title: "DB Slice", status: "in_progress" });
|
|
84
|
+
insertTask({ id: "T01", milestoneId: "M300", sliceId: "S01", title: "DB Task", status: "complete" });
|
|
85
|
+
writeFileSync(
|
|
86
|
+
join(dbBase, ".gsd", "milestones", "M300", "slices", "S01", "S01-PLAN.md"),
|
|
87
|
+
"# S01\n\n## Tasks\n\n- [ ] **T01: DB Task** `est:10m`\n",
|
|
88
|
+
"utf-8",
|
|
89
|
+
);
|
|
90
|
+
writeFileSync(join(dbBase, ".gsd", "STATE.md"), "## Next Action\nExecute T01 for S01: DB task\n", "utf-8");
|
|
91
|
+
|
|
92
|
+
const status = await inspectExecuteTaskDurability(dbBase, "M300/S01/T01");
|
|
93
|
+
assert.ok(status !== null, "db-complete: status exists");
|
|
94
|
+
assert.equal(status!.dbComplete, true, "db-complete: closed DB status is captured");
|
|
95
|
+
assert.equal(status!.summaryExists, false, "db-complete: summary can still be missing");
|
|
96
|
+
assert.equal(status!.taskChecked, false, "db-complete: checkbox can still be unchecked");
|
|
97
|
+
assert.equal(status!.nextActionAdvanced, false, "db-complete: next action can still point at task");
|
|
98
|
+
assert.equal(formatExecuteTaskRecoveryStatus(status!), "DB task status is closed");
|
|
99
|
+
} finally {
|
|
100
|
+
closeDatabase();
|
|
101
|
+
rmSync(dbBase, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
75
105
|
console.log("\n=== hook unit type sanitization (slash in unitType) ===");
|
|
76
106
|
{
|
|
77
107
|
// Hook units have unitType like "hook/code-review" with a slash
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// GSD-2
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Regression test for unstructured continue task-context injection.
|
|
2
3
|
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -55,12 +56,12 @@ describe("#3615 — structural: fallback exists with correct guards", () => {
|
|
|
55
56
|
);
|
|
56
57
|
});
|
|
57
58
|
|
|
58
|
-
test("fallback is intent-gated via
|
|
59
|
+
test("fallback is intent-gated via isLowEntropyResumePrompt", () => {
|
|
59
60
|
const afterFallback = fnBody.indexOf("// Fallback:");
|
|
60
61
|
const fallbackSection = fnBody.slice(afterFallback);
|
|
61
62
|
assert.ok(
|
|
62
|
-
fallbackSection.includes("
|
|
63
|
-
"fallback must check
|
|
63
|
+
fallbackSection.includes("isLowEntropyResumePrompt(prompt)"),
|
|
64
|
+
"fallback must check isLowEntropyResumePrompt before deriveState",
|
|
64
65
|
);
|
|
65
66
|
});
|
|
66
67
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Tests for capped GSD workflow protocol and doctor-heal payload helpers.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
buildDoctorHealIssuePayload,
|
|
9
|
+
buildDoctorHealSummary,
|
|
10
|
+
buildWorkflowDispatchContent,
|
|
11
|
+
buildWorkflowProtocolExcerpt,
|
|
12
|
+
} from "../workflow-protocol.ts";
|
|
13
|
+
|
|
14
|
+
test("workflow protocol helper emits capped excerpt plus source path", () => {
|
|
15
|
+
const workflow = `# Protocol\n${"FULL_WORKFLOW_BODY ".repeat(500)}`;
|
|
16
|
+
const excerpt = buildWorkflowProtocolExcerpt(workflow, "/tmp/GSD-WORKFLOW.md", { maxChars: 1200 });
|
|
17
|
+
|
|
18
|
+
assert.match(excerpt, /Source: `\/tmp\/GSD-WORKFLOW\.md`/);
|
|
19
|
+
assert.match(excerpt, /\[Workflow Protocol Truncated\]/);
|
|
20
|
+
assert.ok(excerpt.length < workflow.length);
|
|
21
|
+
assert.ok(excerpt.length < 1600);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("workflow dispatch uses excerpt instead of full workflow body", () => {
|
|
25
|
+
const workflow = `# Protocol\n${"FULL_WORKFLOW_BODY ".repeat(500)}`;
|
|
26
|
+
const content = buildWorkflowDispatchContent({
|
|
27
|
+
workflow,
|
|
28
|
+
workflowPath: "/tmp/GSD-WORKFLOW.md",
|
|
29
|
+
task: "Run the selected unit.",
|
|
30
|
+
maxProtocolChars: 1200,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
assert.match(content, /## GSD Workflow Protocol Excerpt/);
|
|
34
|
+
assert.match(content, /## Your Task/);
|
|
35
|
+
assert.match(content, /Run the selected unit/);
|
|
36
|
+
assert.ok(content.length < workflow.length);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("workflow protocol excerpt includes late verification and advance rules", () => {
|
|
40
|
+
const workflow = [
|
|
41
|
+
"# GSD Workflow",
|
|
42
|
+
"intro",
|
|
43
|
+
"## Quick Start",
|
|
44
|
+
"quick",
|
|
45
|
+
"## File Format Reference",
|
|
46
|
+
"format ".repeat(400),
|
|
47
|
+
"## The Phases",
|
|
48
|
+
"phase overview",
|
|
49
|
+
"### Phase 4: Execute",
|
|
50
|
+
"execute rules",
|
|
51
|
+
"### Phase 5: Verify",
|
|
52
|
+
"verification rules",
|
|
53
|
+
"### Phase 7: Advance",
|
|
54
|
+
"advance rules",
|
|
55
|
+
].join("\n");
|
|
56
|
+
|
|
57
|
+
const excerpt = buildWorkflowProtocolExcerpt(workflow, "/tmp/GSD-WORKFLOW.md", { maxChars: 1300 });
|
|
58
|
+
|
|
59
|
+
assert.match(excerpt, /Quick Start/);
|
|
60
|
+
assert.match(excerpt, /Phase 5: Verify/);
|
|
61
|
+
assert.match(excerpt, /Phase 7: Advance/);
|
|
62
|
+
assert.doesNotMatch(excerpt, /format format format format format/);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("doctor heal summary omits duplicated full report body", () => {
|
|
66
|
+
const report = [
|
|
67
|
+
"# GSD doctor heal prep.",
|
|
68
|
+
"Scope: M001",
|
|
69
|
+
"Status: warning",
|
|
70
|
+
"Warnings: 9",
|
|
71
|
+
"",
|
|
72
|
+
"VERY_LONG_FULL_REPORT_BODY ".repeat(300),
|
|
73
|
+
].join("\n");
|
|
74
|
+
|
|
75
|
+
const summary = buildDoctorHealSummary(report, { maxChars: 900 });
|
|
76
|
+
|
|
77
|
+
assert.match(summary, /GSD doctor heal prep/);
|
|
78
|
+
assert.match(summary, /Warnings: 9/);
|
|
79
|
+
assert.ok(summary.length <= 900);
|
|
80
|
+
assert.doesNotMatch(summary, /VERY_LONG_FULL_REPORT_BODY VERY_LONG_FULL_REPORT_BODY VERY_LONG_FULL_REPORT_BODY/);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("doctor heal issue payload keeps top actionable issues and caps detail", () => {
|
|
84
|
+
const issues = Array.from({ length: 20 }, (_, index) =>
|
|
85
|
+
`### Issue ${index + 1}\n${`detail ${index + 1} `.repeat(80)}`,
|
|
86
|
+
).join("\n");
|
|
87
|
+
|
|
88
|
+
const payload = buildDoctorHealIssuePayload(issues, {
|
|
89
|
+
maxIssues: 3,
|
|
90
|
+
maxIssueChars: 180,
|
|
91
|
+
maxChars: 900,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
assert.match(payload, /Issue 1/);
|
|
95
|
+
assert.match(payload, /Issue 3/);
|
|
96
|
+
assert.doesNotMatch(payload, /Issue 4/);
|
|
97
|
+
assert.match(payload, /17 additional actionable issue/);
|
|
98
|
+
assert.ok(payload.length <= 900);
|
|
99
|
+
});
|
|
@@ -165,6 +165,9 @@ test("executeMilestoneStatus returns milestone metadata and slice counts", async
|
|
|
165
165
|
assert.equal(parsed.sliceCount, 1);
|
|
166
166
|
assert.equal(parsed.slices[0].id, "S01");
|
|
167
167
|
assert.equal(parsed.slices[0].taskCounts.pending, 1);
|
|
168
|
+
assert.equal(result.details.status, "active");
|
|
169
|
+
assert.equal(result.details.title, "Milestone One");
|
|
170
|
+
assert.deepEqual(result.details.slices, parsed.slices);
|
|
168
171
|
} finally {
|
|
169
172
|
closeDatabase();
|
|
170
173
|
cleanup(base);
|
|
@@ -39,6 +39,7 @@ function makeDeps(
|
|
|
39
39
|
getAutoWorktreePath: () => null,
|
|
40
40
|
autoCommitCurrentBranch: () => {},
|
|
41
41
|
getCurrentBranch: () => "main",
|
|
42
|
+
checkoutBranch: () => {},
|
|
42
43
|
autoWorktreeBranch: (milestoneId: string) => `milestone/${milestoneId}`,
|
|
43
44
|
resolveMilestoneFile: (_basePath: string, milestoneId: string) =>
|
|
44
45
|
`/project/.gsd/milestones/${milestoneId}/${milestoneId}-ROADMAP.md`,
|
|
@@ -79,7 +79,7 @@ async function waitFor(condition: () => boolean, label: string): Promise<void> {
|
|
|
79
79
|
assert.fail(`Timed out waiting for ${label} after ${timeoutMs}ms`);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
test("runUnit
|
|
82
|
+
test("runUnit passes basePath as workspaceRoot without changing process cwd", async (t) => {
|
|
83
83
|
_resetPendingResolve();
|
|
84
84
|
|
|
85
85
|
const originalCwd = process.cwd();
|
|
@@ -93,13 +93,15 @@ test("runUnit changes cwd to basePath before creating a new session", async (t)
|
|
|
93
93
|
|
|
94
94
|
process.chdir(drifted);
|
|
95
95
|
|
|
96
|
+
let newSessionWorkspaceRoot: string | undefined;
|
|
96
97
|
let cwdAtNewSession: string | undefined;
|
|
97
98
|
const session = {
|
|
98
99
|
active: true,
|
|
99
100
|
basePath: base,
|
|
100
101
|
verbose: false,
|
|
101
102
|
cmdCtx: {
|
|
102
|
-
newSession: () => {
|
|
103
|
+
newSession: (options?: { workspaceRoot?: string }) => {
|
|
104
|
+
newSessionWorkspaceRoot = options?.workspaceRoot;
|
|
103
105
|
cwdAtNewSession = process.cwd();
|
|
104
106
|
return Promise.resolve({ cancelled: false });
|
|
105
107
|
},
|
|
@@ -119,10 +121,12 @@ test("runUnit changes cwd to basePath before creating a new session", async (t)
|
|
|
119
121
|
|
|
120
122
|
const result = await resultPromise;
|
|
121
123
|
assert.equal(result.status, "completed");
|
|
122
|
-
assert.equal(
|
|
124
|
+
assert.equal(newSessionWorkspaceRoot, base);
|
|
125
|
+
assert.equal(cwdAtNewSession, drifted);
|
|
126
|
+
assert.equal(process.cwd(), drifted);
|
|
123
127
|
});
|
|
124
128
|
|
|
125
|
-
test("runUnit
|
|
129
|
+
test("runUnit does not chdir or cancel when basePath is not a live directory", async (t) => {
|
|
126
130
|
_resetPendingResolve();
|
|
127
131
|
|
|
128
132
|
const originalCwd = process.cwd();
|
|
@@ -136,14 +140,14 @@ test("runUnit cancels before creating a session when basePath chdir fails", asyn
|
|
|
136
140
|
|
|
137
141
|
process.chdir(drifted);
|
|
138
142
|
|
|
139
|
-
let
|
|
143
|
+
let newSessionWorkspaceRoot: string | undefined;
|
|
140
144
|
const session = {
|
|
141
145
|
active: true,
|
|
142
146
|
basePath: base,
|
|
143
147
|
verbose: false,
|
|
144
148
|
cmdCtx: {
|
|
145
|
-
newSession: () => {
|
|
146
|
-
|
|
149
|
+
newSession: (options?: { workspaceRoot?: string }) => {
|
|
150
|
+
newSessionWorkspaceRoot = options?.workspaceRoot;
|
|
147
151
|
return Promise.resolve({ cancelled: false });
|
|
148
152
|
},
|
|
149
153
|
},
|
|
@@ -156,15 +160,14 @@ test("runUnit cancels before creating a session when basePath chdir fails", asyn
|
|
|
156
160
|
} as any;
|
|
157
161
|
const ctx = { ui: { notify: () => {} }, model: { id: "test-model" } } as any;
|
|
158
162
|
|
|
159
|
-
const
|
|
163
|
+
const resultPromise = runUnit(ctx, pi, session, "task", "T01", "prompt");
|
|
164
|
+
await waitFor(() => pi.calls.length === 1, "runUnit dispatch");
|
|
165
|
+
resolveAgentEnd({ messages: [{ role: "assistant" }] });
|
|
160
166
|
|
|
161
|
-
|
|
162
|
-
assert.equal(result.
|
|
163
|
-
assert.equal(
|
|
164
|
-
assert.
|
|
165
|
-
assert.ok(result.errorContext?.message.includes(base), "error should include the failed basePath");
|
|
166
|
-
assert.equal(newSessionCalled, false, "newSession must not run after chdir failure");
|
|
167
|
-
assert.equal(pi.calls.length, 0, "unit must not dispatch after chdir failure");
|
|
167
|
+
const result = await resultPromise;
|
|
168
|
+
assert.equal(result.status, "completed");
|
|
169
|
+
assert.equal(newSessionWorkspaceRoot, base);
|
|
170
|
+
assert.equal(process.cwd(), drifted);
|
|
168
171
|
});
|
|
169
172
|
|
|
170
173
|
test("direct dispatch redirects to the canonical milestone worktree before newSession", async (t) => {
|
|
@@ -185,12 +188,12 @@ test("direct dispatch redirects to the canonical milestone worktree before newSe
|
|
|
185
188
|
|
|
186
189
|
process.chdir(drifted);
|
|
187
190
|
|
|
188
|
-
let
|
|
191
|
+
let newSessionWorkspaceRoot: string | undefined;
|
|
189
192
|
let sentPrompt: string | undefined;
|
|
190
193
|
const ctx = {
|
|
191
194
|
ui: { notify: () => {} },
|
|
192
|
-
newSession: async () => {
|
|
193
|
-
|
|
195
|
+
newSession: async (options?: { workspaceRoot?: string }) => {
|
|
196
|
+
newSessionWorkspaceRoot = options?.workspaceRoot;
|
|
194
197
|
return { cancelled: false };
|
|
195
198
|
},
|
|
196
199
|
} as any;
|
|
@@ -202,7 +205,7 @@ test("direct dispatch redirects to the canonical milestone worktree before newSe
|
|
|
202
205
|
|
|
203
206
|
await dispatchDirectPhase(ctx, pi, "research-milestone", base);
|
|
204
207
|
|
|
205
|
-
assert.equal(
|
|
208
|
+
assert.equal(newSessionWorkspaceRoot, worktreeRoot);
|
|
206
209
|
assert.equal(process.cwd(), drifted);
|
|
207
210
|
assert.ok(sentPrompt?.includes(worktreeRoot), "prompt should name the canonical worktree root");
|
|
208
211
|
});
|