@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.eed73bea
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/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
- package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
- package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -14
- package/dist/resources/extensions/gsd/auto-prompts.js +43 -12
- package/dist/resources/extensions/gsd/auto-recovery.js +13 -6
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -3
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +75 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/commands-context.js +19 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
- package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
- package/dist/resources/extensions/gsd/db/queries.js +60 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
- package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
- package/dist/resources/extensions/gsd/forensics.js +2 -32
- package/dist/resources/extensions/gsd/git-service.js +4 -4
- package/dist/resources/extensions/gsd/guided-flow-queue.js +59 -5
- package/dist/resources/extensions/gsd/health-widget.js +55 -29
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -2
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
- package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
- package/dist/resources/extensions/gsd/quick.js +45 -2
- package/dist/resources/extensions/gsd/session-forensics.js +11 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +52 -3
- package/dist/resources/extensions/gsd/tools/complete-slice.js +34 -3
- package/dist/resources/extensions/gsd/tools/complete-task.js +78 -16
- package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
- package/dist/resources/extensions/gsd/unit-registry.js +25 -3
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
- package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
- 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 +14 -14
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- 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/api/visualizer/route.js +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 +14 -14
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-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/dist/web/standalone/.next/static/chunks/{796.e0bdc932325d7e03.js → 796.3976108148518f7d.js} +3 -3
- package/dist/web/standalone/.next/static/chunks/{webpack-f46ea08200a0227e.js → webpack-7c1d97e39be2da11.js} +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +1 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +2 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +21 -9
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +1 -1
- package/packages/mcp-server/dist/server.d.ts +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +3 -3
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +34 -20
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
- package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -17
- package/src/resources/extensions/gsd/auto-prompts.ts +54 -12
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -6
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +9 -3
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +82 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/commands-context.ts +18 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
- package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
- package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
- package/src/resources/extensions/gsd/db/queries.ts +79 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/forensics.ts +2 -33
- package/src/resources/extensions/gsd/git-service.ts +5 -5
- package/src/resources/extensions/gsd/guided-flow-queue.ts +82 -4
- package/src/resources/extensions/gsd/health-widget.ts +69 -32
- package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
- package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
- package/src/resources/extensions/gsd/quick.ts +43 -2
- package/src/resources/extensions/gsd/session-forensics.ts +11 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +76 -8
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
- package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
- package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
- package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
- package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +30 -3
- package/src/resources/extensions/gsd/tools/complete-task.ts +86 -16
- package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
- package/src/resources/extensions/gsd/unit-registry.ts +25 -3
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
- package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → SzEuqWX37DR9MEpEuQjP1}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → SzEuqWX37DR9MEpEuQjP1}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/mcp-server",
|
|
3
|
-
"version": "1.3.0-dev.
|
|
3
|
+
"version": "1.3.0-dev.eed73bea",
|
|
4
4
|
"description": "MCP server exposing GSD orchestration tools for compatible clients",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"gsd": {
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"test": "pnpm run build:test && node --test dist/mcp-server.test.js dist/remote-questions.test.js dist/moonshot-tool-schema.test.js dist/pid-registry.test.js dist/probe-mode.test.js dist/stdio-watchdog.test.js dist/cli-runner.test.js dist/readers/graph.test.js dist/readers/paths.test.js dist/readers/readers.test.js"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@gsd/pi-ai": "^1.3.0-dev.
|
|
54
|
-
"@opengsd/contracts": "^1.3.0-dev.
|
|
55
|
-
"@opengsd/rpc-client": "^1.3.0-dev.
|
|
53
|
+
"@gsd/pi-ai": "^1.3.0-dev.eed73bea",
|
|
54
|
+
"@opengsd/contracts": "^1.3.0-dev.eed73bea",
|
|
55
|
+
"@opengsd/rpc-client": "^1.3.0-dev.eed73bea",
|
|
56
56
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
57
57
|
"zod": "^4.0.0"
|
|
58
58
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-coding-agent",
|
|
3
|
-
"version": "1.3.0-dev.
|
|
3
|
+
"version": "1.3.0-dev.eed73bea",
|
|
4
4
|
"description": "Coding agent CLI (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"copy-assets": "node scripts/copy-assets.cjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@opengsd/contracts": "^1.3.0-dev.
|
|
36
|
+
"@opengsd/contracts": "^1.3.0-dev.eed73bea",
|
|
37
37
|
"@mariozechner/jiti": "^2.6.2",
|
|
38
38
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
39
39
|
"chalk": "5.6.2",
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"typebox": "1.1.38",
|
|
54
54
|
"undici": "7.28.0",
|
|
55
55
|
"yaml": "2.9.0",
|
|
56
|
-
"@gsd/agent-core": "^1.3.0-dev.
|
|
57
|
-
"@gsd/native": "^1.3.0-dev.
|
|
58
|
-
"@gsd/pi-agent-core": "^1.3.0-dev.
|
|
59
|
-
"@gsd/pi-ai": "^1.3.0-dev.
|
|
60
|
-
"@gsd/pi-tui": "^1.3.0-dev.
|
|
56
|
+
"@gsd/agent-core": "^1.3.0-dev.eed73bea",
|
|
57
|
+
"@gsd/native": "^1.3.0-dev.eed73bea",
|
|
58
|
+
"@gsd/pi-agent-core": "^1.3.0-dev.eed73bea",
|
|
59
|
+
"@gsd/pi-ai": "^1.3.0-dev.eed73bea",
|
|
60
|
+
"@gsd/pi-tui": "^1.3.0-dev.eed73bea",
|
|
61
61
|
"@sinclair/typebox": "^0.34.41"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-tui",
|
|
3
|
-
"version": "1.3.0-dev.
|
|
3
|
+
"version": "1.3.0-dev.eed73bea",
|
|
4
4
|
"description": "Terminal UI library (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build": "node ../../scripts/clean-package-dist.cjs && tsc -p tsconfig.json --incremental false"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@gsd/native": "^1.3.0-dev.
|
|
24
|
+
"@gsd/native": "^1.3.0-dev.eed73bea",
|
|
25
25
|
"get-east-asian-width": "1.6.0",
|
|
26
26
|
"marked": "15.0.12",
|
|
27
27
|
"@sinclair/typebox": "^0.34.41"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/rpc-client",
|
|
3
|
-
"version": "1.3.0-dev.
|
|
3
|
+
"version": "1.3.0-dev.eed73bea",
|
|
4
4
|
"description": "Standalone RPC client SDK for GSD — zero internal dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"gsd": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test": "node --test dist/rpc-client.test.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@opengsd/contracts": "^1.3.0-dev.
|
|
37
|
+
"@opengsd/contracts": "^1.3.0-dev.eed73bea"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=22.0.0"
|
package/pkg/package.json
CHANGED
|
@@ -101,6 +101,7 @@ export type {
|
|
|
101
101
|
interface PromptToolContextOptions {
|
|
102
102
|
workflowMcpServerName?: string | null;
|
|
103
103
|
browserMcpServerName?: string | null;
|
|
104
|
+
questionToolAvailable?: boolean;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
/** `SimpleStreamOptions` extended with an optional extension UI context for elicitation dialogs. */
|
|
@@ -480,8 +481,10 @@ export function buildPromptFromContext(context: Context, toolContext: PromptTool
|
|
|
480
481
|
? "- GSD workflow tools (gsd_exec, gsd_slice_complete, gsd_task_complete, gsd_plan_slice, gsd_save_gate_result, etc.) " +
|
|
481
482
|
`are MCP tools — call them as mcp__${toolContext.workflowMcpServerName}__<tool_name> ` +
|
|
482
483
|
`(e.g. mcp__${toolContext.workflowMcpServerName}__gsd_exec, mcp__${toolContext.workflowMcpServerName}__gsd_save_gate_result)\n` +
|
|
483
|
-
|
|
484
|
-
|
|
484
|
+
(toolContext.questionToolAvailable !== false
|
|
485
|
+
? `- Structured user input: call mcp__${toolContext.workflowMcpServerName}__ask_user_questions. ` +
|
|
486
|
+
"Do not call bare ask_user_questions. Do not call native AskUserQuestion.\n"
|
|
487
|
+
: "")
|
|
485
488
|
: "- GSD workflow MCP tools are unavailable in this Claude Code run.\n";
|
|
486
489
|
const toolSearchLine = toolContext.workflowMcpServerName
|
|
487
490
|
? "- ToolSearch is available only for Claude Code deferred workflow MCP hydration. " +
|
|
@@ -1753,6 +1756,16 @@ function workflowMcpServerNameFromAllowedTools(allowedTools: unknown): string |
|
|
|
1753
1756
|
return undefined;
|
|
1754
1757
|
}
|
|
1755
1758
|
|
|
1759
|
+
function workflowQuestionToolAvailableFromAllowedTools(
|
|
1760
|
+
allowedTools: unknown,
|
|
1761
|
+
workflowMcpServerName: string | undefined,
|
|
1762
|
+
gsdPhase: string | undefined,
|
|
1763
|
+
): boolean | undefined {
|
|
1764
|
+
if (!workflowMcpServerName || !gsdPhase) return undefined;
|
|
1765
|
+
return Array.isArray(allowedTools)
|
|
1766
|
+
&& allowedTools.includes(`mcp__${workflowMcpServerName}__ask_user_questions`);
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1756
1769
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
1757
1770
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
1758
1771
|
}
|
|
@@ -2257,6 +2270,11 @@ async function pumpSdkMessages(
|
|
|
2257
2270
|
const prompt = buildPromptFromContext(context, {
|
|
2258
2271
|
workflowMcpServerName,
|
|
2259
2272
|
browserMcpServerName: browserMcpServerNameFromAllowedTools(sdkOpts.allowedTools),
|
|
2273
|
+
questionToolAvailable: workflowQuestionToolAvailableFromAllowedTools(
|
|
2274
|
+
sdkOpts.allowedTools,
|
|
2275
|
+
workflowMcpServerName,
|
|
2276
|
+
gsdPhase,
|
|
2277
|
+
),
|
|
2260
2278
|
});
|
|
2261
2279
|
const queryPrompt = buildSdkQueryPrompt(context, prompt);
|
|
2262
2280
|
|
|
@@ -2001,6 +2001,86 @@ describe("stream-adapter — session persistence (#2859)", () => {
|
|
|
2001
2001
|
});
|
|
2002
2002
|
|
|
2003
2003
|
describe("stream-adapter — workflow MCP readiness", () => {
|
|
2004
|
+
test("strict slice phase prompt omits workflow MCP question guidance when allowedTools omit it", async () => {
|
|
2005
|
+
const cwd = realpathSync(mkdtempSync(join(tmpdir(), "claude-sdk-strict-question-prompt-")));
|
|
2006
|
+
const restore = setWorkflowMcpEnv({
|
|
2007
|
+
GSD_WORKFLOW_MCP_COMMAND: process.execPath,
|
|
2008
|
+
GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
|
|
2009
|
+
GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["-e", ""]),
|
|
2010
|
+
GSD_WORKFLOW_MCP_CWD: cwd,
|
|
2011
|
+
});
|
|
2012
|
+
const phases = [
|
|
2013
|
+
{ type: "research-slice", label: "Research Slice", expectedTool: "mcp__gsd-workflow__gsd_summary_save" },
|
|
2014
|
+
{ type: "plan-slice", label: "Plan Slice", expectedTool: "mcp__gsd-workflow__gsd_plan_slice" },
|
|
2015
|
+
{ type: "refine-slice", label: "Refine Slice", expectedTool: "mcp__gsd-workflow__gsd_plan_slice" },
|
|
2016
|
+
] as const;
|
|
2017
|
+
clearGuidedUnitContext();
|
|
2018
|
+
_setAutoActiveForTest(true);
|
|
2019
|
+
try {
|
|
2020
|
+
for (const phase of phases) {
|
|
2021
|
+
let capturedPrompt: unknown;
|
|
2022
|
+
let capturedAllowedTools: string[] | undefined;
|
|
2023
|
+
autoSession.currentUnit = { type: phase.type, id: "M001/S001", startedAt: 0, workspaceRoot: cwd } as never;
|
|
2024
|
+
const stream = streamViaClaudeCode(
|
|
2025
|
+
{ id: "claude-sonnet-4-6" } as any,
|
|
2026
|
+
{
|
|
2027
|
+
systemPrompt: `UNIT: ${phase.label}`,
|
|
2028
|
+
messages: [{ role: "user", content: "Complete the strict slice phase." } as Message],
|
|
2029
|
+
},
|
|
2030
|
+
{
|
|
2031
|
+
cwd,
|
|
2032
|
+
_skipWorkflowMcpPreflightForTest: true,
|
|
2033
|
+
async *_sdkQueryForTest(args: {
|
|
2034
|
+
prompt: string | AsyncIterable<unknown>;
|
|
2035
|
+
options?: Record<string, unknown>;
|
|
2036
|
+
}) {
|
|
2037
|
+
capturedPrompt = args.prompt;
|
|
2038
|
+
capturedAllowedTools = args.options?.allowedTools as string[] | undefined;
|
|
2039
|
+
yield {
|
|
2040
|
+
type: "result",
|
|
2041
|
+
subtype: "success",
|
|
2042
|
+
uuid: `result-${phase.type}`,
|
|
2043
|
+
session_id: `session-${phase.type}`,
|
|
2044
|
+
duration_ms: 1,
|
|
2045
|
+
duration_api_ms: 1,
|
|
2046
|
+
is_error: false,
|
|
2047
|
+
num_turns: 1,
|
|
2048
|
+
result: "completed",
|
|
2049
|
+
stop_reason: "end_turn",
|
|
2050
|
+
total_cost_usd: 0,
|
|
2051
|
+
usage: {
|
|
2052
|
+
input_tokens: 0,
|
|
2053
|
+
output_tokens: 0,
|
|
2054
|
+
cache_read_input_tokens: 0,
|
|
2055
|
+
cache_creation_input_tokens: 0,
|
|
2056
|
+
},
|
|
2057
|
+
};
|
|
2058
|
+
},
|
|
2059
|
+
} as any,
|
|
2060
|
+
);
|
|
2061
|
+
|
|
2062
|
+
await stream.result();
|
|
2063
|
+
|
|
2064
|
+
assert.equal(typeof capturedPrompt, "string", phase.type);
|
|
2065
|
+
const prompt = capturedPrompt as string;
|
|
2066
|
+
assert.ok(capturedAllowedTools?.includes(phase.expectedTool), phase.type);
|
|
2067
|
+
assert.ok(!capturedAllowedTools?.includes("mcp__gsd-workflow__ask_user_questions"), phase.type);
|
|
2068
|
+
assert.ok(!prompt.includes("mcp__gsd-workflow__ask_user_questions"), phase.type);
|
|
2069
|
+
assert.ok(!prompt.includes("Do not call bare ask_user_questions"), phase.type);
|
|
2070
|
+
assert.ok(
|
|
2071
|
+
prompt.includes("ToolSearch is available only for Claude Code deferred workflow MCP hydration"),
|
|
2072
|
+
phase.type,
|
|
2073
|
+
);
|
|
2074
|
+
}
|
|
2075
|
+
} finally {
|
|
2076
|
+
autoSession.currentUnit = null;
|
|
2077
|
+
_setAutoActiveForTest(false);
|
|
2078
|
+
restore();
|
|
2079
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
2080
|
+
clearMcpConfigCache();
|
|
2081
|
+
}
|
|
2082
|
+
});
|
|
2083
|
+
|
|
2004
2084
|
test("resolves the workflow MCP preflight config from SDK mcpServers", () => {
|
|
2005
2085
|
const workflowConfig = { command: "node", args: ["workflow-server.js"] };
|
|
2006
2086
|
const browserConfig = { command: "gsd-browser" };
|
|
@@ -20,7 +20,13 @@ const ZERO_USAGE = {
|
|
|
20
20
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
type GoogleCliProviderId = "google-gemini-cli" | "google-antigravity";
|
|
23
|
+
export type GoogleCliProviderId = "google-gemini-cli" | "google-antigravity";
|
|
24
|
+
|
|
25
|
+
export interface GoogleCliRunPlan {
|
|
26
|
+
command: string;
|
|
27
|
+
args: string[];
|
|
28
|
+
stdin?: string;
|
|
29
|
+
}
|
|
24
30
|
|
|
25
31
|
interface CliRunResult {
|
|
26
32
|
stdout: string;
|
|
@@ -29,6 +35,71 @@ interface CliRunResult {
|
|
|
29
35
|
signal: NodeJS.Signals | null;
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
const WINDOWS_CHILD_ENV_KEYS = new Set([
|
|
39
|
+
"ALLUSERSPROFILE",
|
|
40
|
+
"APPDATA",
|
|
41
|
+
"COMSPEC",
|
|
42
|
+
"COMMONPROGRAMFILES",
|
|
43
|
+
"COMMONPROGRAMFILES(X86)",
|
|
44
|
+
"FORCE_COLOR",
|
|
45
|
+
"HOME",
|
|
46
|
+
"HOMEDRIVE",
|
|
47
|
+
"HOMEPATH",
|
|
48
|
+
"LANG",
|
|
49
|
+
"LC_ALL",
|
|
50
|
+
"LOCALAPPDATA",
|
|
51
|
+
"NODE_EXTRA_CA_CERTS",
|
|
52
|
+
"NO_COLOR",
|
|
53
|
+
"NO_PROXY",
|
|
54
|
+
"PATHEXT",
|
|
55
|
+
"PATH",
|
|
56
|
+
"PROGRAMDATA",
|
|
57
|
+
"PROGRAMFILES",
|
|
58
|
+
"PROGRAMFILES(X86)",
|
|
59
|
+
"SSL_CERT_FILE",
|
|
60
|
+
"SYSTEMROOT",
|
|
61
|
+
"TEMP",
|
|
62
|
+
"TERM",
|
|
63
|
+
"TMP",
|
|
64
|
+
"TMPDIR",
|
|
65
|
+
"USER",
|
|
66
|
+
"USERNAME",
|
|
67
|
+
"USERPROFILE",
|
|
68
|
+
"WINDIR",
|
|
69
|
+
"XDG_CACHE_HOME",
|
|
70
|
+
"XDG_CONFIG_HOME",
|
|
71
|
+
"HTTP_PROXY",
|
|
72
|
+
"HTTPS_PROXY",
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
const WINDOWS_CHILD_ENV_PREFIXES = [
|
|
76
|
+
"AGY_",
|
|
77
|
+
"ANTIGRAVITY_",
|
|
78
|
+
"CLOUDSDK_",
|
|
79
|
+
"GEMINI_",
|
|
80
|
+
"GOOGLE_",
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
export function buildGoogleCliChildEnv(
|
|
84
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
85
|
+
platform: NodeJS.Platform = process.platform,
|
|
86
|
+
): NodeJS.ProcessEnv {
|
|
87
|
+
if (platform !== "win32") return env;
|
|
88
|
+
|
|
89
|
+
const childEnv: NodeJS.ProcessEnv = {};
|
|
90
|
+
for (const [key, value] of Object.entries(env)) {
|
|
91
|
+
if (typeof value !== "string") continue;
|
|
92
|
+
const upperKey = key.toUpperCase();
|
|
93
|
+
if (
|
|
94
|
+
WINDOWS_CHILD_ENV_KEYS.has(upperKey) ||
|
|
95
|
+
WINDOWS_CHILD_ENV_PREFIXES.some((prefix) => upperKey.startsWith(prefix))
|
|
96
|
+
) {
|
|
97
|
+
childEnv[key] = value;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return childEnv;
|
|
101
|
+
}
|
|
102
|
+
|
|
32
103
|
function textBlocks(content: (TextContent | { type: string })[]): string {
|
|
33
104
|
return content
|
|
34
105
|
.map((block) => block.type === "text" ? (block as TextContent).text : `[${block.type} omitted]`)
|
|
@@ -120,15 +191,15 @@ function commandForProvider(provider: GoogleCliProviderId): string {
|
|
|
120
191
|
return provider === "google-gemini-cli" ? "gemini" : "agy";
|
|
121
192
|
}
|
|
122
193
|
|
|
123
|
-
function argsForProvider(provider: GoogleCliProviderId,
|
|
194
|
+
function argsForProvider(provider: GoogleCliProviderId, modelId: string, prompt?: string): string[] {
|
|
124
195
|
if (provider === "google-gemini-cli") {
|
|
125
|
-
const args = ["-p", prompt, "--output-format", "json"];
|
|
126
|
-
if (
|
|
196
|
+
const args = prompt === undefined ? ["--output-format", "json"] : ["-p", prompt, "--output-format", "json"];
|
|
197
|
+
if (modelId !== "default") args.unshift("-m", modelId);
|
|
127
198
|
return args;
|
|
128
199
|
}
|
|
129
200
|
|
|
130
|
-
const args = ["-p", prompt];
|
|
131
|
-
if (
|
|
201
|
+
const args = prompt === undefined ? [] : ["-p", prompt];
|
|
202
|
+
if (modelId !== "default") args.unshift("-m", modelId);
|
|
132
203
|
return args;
|
|
133
204
|
}
|
|
134
205
|
|
|
@@ -136,20 +207,33 @@ export function buildGoogleCliSpawnInvocation(
|
|
|
136
207
|
command: string,
|
|
137
208
|
args: string[],
|
|
138
209
|
platform: NodeJS.Platform = process.platform,
|
|
139
|
-
):
|
|
210
|
+
): Omit<GoogleCliRunPlan, "stdin"> {
|
|
140
211
|
if (platform === "win32") {
|
|
141
212
|
return { command: "cmd", args: ["/c", command, ...args] };
|
|
142
213
|
}
|
|
143
214
|
return { command, args };
|
|
144
215
|
}
|
|
145
216
|
|
|
146
|
-
function
|
|
217
|
+
export function buildGoogleCliRunPlan(
|
|
218
|
+
provider: GoogleCliProviderId,
|
|
219
|
+
modelId: string,
|
|
220
|
+
prompt: string,
|
|
221
|
+
platform: NodeJS.Platform = process.platform,
|
|
222
|
+
): GoogleCliRunPlan {
|
|
223
|
+
const pipePrompt = platform === "win32";
|
|
224
|
+
const args = argsForProvider(provider, modelId, pipePrompt ? undefined : prompt);
|
|
225
|
+
return {
|
|
226
|
+
...buildGoogleCliSpawnInvocation(commandForProvider(provider), args, platform),
|
|
227
|
+
...(pipePrompt ? { stdin: prompt } : {}),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function runCli(plan: GoogleCliRunPlan, options?: SimpleStreamOptions): Promise<CliRunResult> {
|
|
147
232
|
return new Promise((resolve, reject) => {
|
|
148
|
-
const
|
|
149
|
-
const child = spawn(invocation.command, invocation.args, {
|
|
233
|
+
const child = spawn(plan.command, plan.args, {
|
|
150
234
|
cwd: options?.cwd || process.cwd(),
|
|
151
|
-
env:
|
|
152
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
235
|
+
env: buildGoogleCliChildEnv(),
|
|
236
|
+
stdio: [plan.stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"],
|
|
153
237
|
});
|
|
154
238
|
|
|
155
239
|
let stdout = "";
|
|
@@ -174,12 +258,17 @@ function runCli(command: string, args: string[], options?: SimpleStreamOptions):
|
|
|
174
258
|
}
|
|
175
259
|
options?.signal?.addEventListener("abort", onAbort);
|
|
176
260
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
261
|
+
if (plan.stdin !== undefined) {
|
|
262
|
+
child.stdin?.on("error", () => {});
|
|
263
|
+
child.stdin?.end(plan.stdin);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
child.stdout!.setEncoding("utf8");
|
|
267
|
+
child.stderr!.setEncoding("utf8");
|
|
268
|
+
child.stdout!.on("data", (chunk) => {
|
|
180
269
|
stdout += chunk;
|
|
181
270
|
});
|
|
182
|
-
child.stderr
|
|
271
|
+
child.stderr!.on("data", (chunk) => {
|
|
183
272
|
stderr += chunk;
|
|
184
273
|
});
|
|
185
274
|
|
|
@@ -243,9 +332,7 @@ export function streamViaGoogleCli(
|
|
|
243
332
|
queueMicrotask(async () => {
|
|
244
333
|
try {
|
|
245
334
|
const prompt = buildGoogleCliPrompt(context);
|
|
246
|
-
const
|
|
247
|
-
const args = argsForProvider(provider, model, prompt);
|
|
248
|
-
const result = await runCli(command, args, options);
|
|
335
|
+
const result = await runCli(buildGoogleCliRunPlan(provider, model.id, prompt), options);
|
|
249
336
|
|
|
250
337
|
if (result.code !== 0) {
|
|
251
338
|
const detail = (result.stderr || result.stdout || `CLI exited with code ${result.code}`).trim();
|
|
@@ -76,6 +76,8 @@ import { join } from "node:path";
|
|
|
76
76
|
import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
|
|
77
77
|
import { hasHeldMilestoneLease, reclaimMissingMilestoneLease } from "./milestone-lease-reclaim.js";
|
|
78
78
|
|
|
79
|
+
type UokFlags = ReturnType<typeof resolveUokFlags>;
|
|
80
|
+
|
|
79
81
|
function now(): number {
|
|
80
82
|
return Date.now();
|
|
81
83
|
}
|
|
@@ -517,15 +519,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
517
519
|
|
|
518
520
|
// ── UokGateAdapter (folded) ──────────────────────────────────────────────
|
|
519
521
|
|
|
520
|
-
private
|
|
521
|
-
gateId: string;
|
|
522
|
-
gateType: "policy" | "execution";
|
|
523
|
-
outcome: "pass" | "fail" | "manual-attention";
|
|
524
|
-
failureClass: "none" | "policy" | "manual-attention";
|
|
525
|
-
rationale: string;
|
|
526
|
-
findings?: string;
|
|
527
|
-
milestoneId?: string;
|
|
528
|
-
}): Promise<void> {
|
|
522
|
+
private resolveUokGateContext(): { activeBasePath: string; uokFlags: UokFlags } {
|
|
529
523
|
const activeBasePath = this.getLiveDispatchBasePath();
|
|
530
524
|
const prefs = loadEffectiveGSDPreferencesWithRegistry(
|
|
531
525
|
this.ctx.modelRegistry,
|
|
@@ -535,8 +529,22 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
535
529
|
? `${this.s.autoModeStartModel.provider}/${this.s.autoModeStartModel.id}`
|
|
536
530
|
: undefined,
|
|
537
531
|
)?.preferences;
|
|
538
|
-
|
|
539
|
-
|
|
532
|
+
return { activeBasePath, uokFlags: resolveUokFlags(prefs) };
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
private async emitUokGate(input: {
|
|
536
|
+
gateId: string;
|
|
537
|
+
gateType: "policy" | "execution";
|
|
538
|
+
outcome: "pass" | "fail" | "manual-attention";
|
|
539
|
+
failureClass: "none" | "policy" | "manual-attention";
|
|
540
|
+
rationale: string;
|
|
541
|
+
findings?: string;
|
|
542
|
+
milestoneId?: string;
|
|
543
|
+
activeBasePath: string;
|
|
544
|
+
uokFlags: UokFlags;
|
|
545
|
+
}): Promise<void> {
|
|
546
|
+
if (!input.uokFlags.gates) return;
|
|
547
|
+
const activeBasePath = input.activeBasePath;
|
|
540
548
|
const milestoneId = input.milestoneId ?? this.s.currentMilestoneId ?? undefined;
|
|
541
549
|
try {
|
|
542
550
|
const { UokGateRunner } = await import("../uok/gate-runner.js");
|
|
@@ -943,10 +951,12 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
943
951
|
const stopAdvanceTimer = debugTime("orchestrator-advance");
|
|
944
952
|
try {
|
|
945
953
|
this.ensureLockOwnership();
|
|
954
|
+
const uokGateContext = this.resolveUokGateContext();
|
|
946
955
|
|
|
947
956
|
const staleMsg = this.checkResourcesStale();
|
|
948
957
|
if (staleMsg) {
|
|
949
958
|
await this.emitUokGate({
|
|
959
|
+
...uokGateContext,
|
|
950
960
|
gateId: "resource-version-guard",
|
|
951
961
|
gateType: "policy",
|
|
952
962
|
outcome: "fail",
|
|
@@ -960,6 +970,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
960
970
|
return blocked;
|
|
961
971
|
}
|
|
962
972
|
await this.emitUokGate({
|
|
973
|
+
...uokGateContext,
|
|
963
974
|
gateId: "resource-version-guard",
|
|
964
975
|
gateType: "policy",
|
|
965
976
|
outcome: "pass",
|
|
@@ -970,6 +981,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
970
981
|
const gate = await this.preAdvanceGate();
|
|
971
982
|
if (gate.kind === "fail") {
|
|
972
983
|
await this.emitUokGate({
|
|
984
|
+
...uokGateContext,
|
|
973
985
|
gateId: "pre-dispatch-health-gate",
|
|
974
986
|
gateType: "execution",
|
|
975
987
|
outcome: "manual-attention",
|
|
@@ -988,6 +1000,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
988
1000
|
}
|
|
989
1001
|
if (gate.kind === "threw") {
|
|
990
1002
|
await this.emitUokGate({
|
|
1003
|
+
...uokGateContext,
|
|
991
1004
|
gateId: "pre-dispatch-health-gate",
|
|
992
1005
|
gateType: "execution",
|
|
993
1006
|
outcome: "manual-attention",
|
|
@@ -998,6 +1011,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
998
1011
|
// intentional fall-through: matches runPreDispatch behaviour
|
|
999
1012
|
} else {
|
|
1000
1013
|
await this.emitUokGate({
|
|
1014
|
+
...uokGateContext,
|
|
1001
1015
|
gateId: "pre-dispatch-health-gate",
|
|
1002
1016
|
gateType: "execution",
|
|
1003
1017
|
outcome: "pass",
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
setSliceSketchFlag,
|
|
31
31
|
transaction,
|
|
32
32
|
getAssessment,
|
|
33
|
+
getSliceRunUatAssessment,
|
|
33
34
|
} from "./gsd-db.js";
|
|
34
35
|
import { isClosedStatus } from "./status-guards.js";
|
|
35
36
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
@@ -322,6 +323,19 @@ export async function readUatGateVerdict(
|
|
|
322
323
|
}
|
|
323
324
|
}
|
|
324
325
|
|
|
326
|
+
// ADR-017 DB fallback: when the ASSESSMENT markdown is missing or orphaned
|
|
327
|
+
// from its canonical path (e.g. after a milestone artifact-layout migration
|
|
328
|
+
// moves slice artifacts from `phases/…` to `milestones/…`), consult the
|
|
329
|
+
// authoritative assessments table by (mid, slice) identity instead of path.
|
|
330
|
+
// `gsd_uat_result_save` always writes this row, so it is the source of truth.
|
|
331
|
+
const runUatAssessment = getSliceRunUatAssessment(mid, sliceId);
|
|
332
|
+
if (runUatAssessment?.status) {
|
|
333
|
+
return {
|
|
334
|
+
verdict: runUatAssessment.status,
|
|
335
|
+
uatType: uatType ?? extractUatType(runUatAssessment.fullContent),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
325
339
|
return null;
|
|
326
340
|
}
|
|
327
341
|
|
|
@@ -1142,16 +1156,13 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1142
1156
|
const dbSlices = getMilestoneSliceSummaries(mid);
|
|
1143
1157
|
if (dbSlices.length === 0) return null;
|
|
1144
1158
|
|
|
1145
|
-
// Find slices that need research (no RESEARCH file, dependencies done)
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
resolveMilestoneFile(basePath, mid, "RESEARCH");
|
|
1159
|
+
// Find slices that need research (no RESEARCH file, dependencies done).
|
|
1160
|
+
// Milestone research informs slice research; it does not satisfy the
|
|
1161
|
+
// per-slice RESEARCH artifact contract.
|
|
1149
1162
|
const researchReadySlices: Array<{ id: string; title: string }> = [];
|
|
1150
1163
|
|
|
1151
1164
|
for (const slice of dbSlices) {
|
|
1152
1165
|
if (slice.done) continue;
|
|
1153
|
-
// Skip S01 when milestone research exists
|
|
1154
|
-
if (milestoneResearchFile && slice.id === "S01") continue;
|
|
1155
1166
|
// Skip if already has research
|
|
1156
1167
|
if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath)) continue;
|
|
1157
1168
|
// Skip if dependencies aren't done (check for SUMMARY files)
|
|
@@ -1190,7 +1201,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1190
1201
|
},
|
|
1191
1202
|
},
|
|
1192
1203
|
{
|
|
1193
|
-
name: "planning (no research
|
|
1204
|
+
name: "planning (no research) → research-slice",
|
|
1194
1205
|
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
1195
1206
|
if (state.phase !== "planning") return null;
|
|
1196
1207
|
// Phase skip: skip research when preference or profile says so
|
|
@@ -1205,16 +1216,6 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1205
1216
|
resolveExistingExpectedArtifact("research-slice", `${mid}/${sid}`, basePath) ??
|
|
1206
1217
|
resolveSliceFile(basePath, mid, sid, "RESEARCH");
|
|
1207
1218
|
if (researchFile) return null; // has research, fall through
|
|
1208
|
-
// Skip slice research for S01 when milestone research already exists —
|
|
1209
|
-
// the milestone research already covers the same ground for the first slice.
|
|
1210
|
-
const milestoneResearchFile =
|
|
1211
|
-
resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
|
|
1212
|
-
resolveMilestoneFile(
|
|
1213
|
-
basePath,
|
|
1214
|
-
mid,
|
|
1215
|
-
"RESEARCH",
|
|
1216
|
-
);
|
|
1217
|
-
if (milestoneResearchFile && sid === "S01") return null; // fall through to plan-slice
|
|
1218
1219
|
return {
|
|
1219
1220
|
action: "dispatch",
|
|
1220
1221
|
unitType: "research-slice",
|