gsd-pi 2.67.0-dev.1cd1e0f → 2.67.0-dev.2367d7e
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 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +155 -70
- package/dist/resources/extensions/gsd/auto/phases.js +17 -0
- package/dist/resources/extensions/gsd/auto/session.js +10 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +12 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto-start.js +16 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +62 -15
- package/dist/resources/extensions/gsd/auto.js +121 -59
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -435
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -4
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +7 -64
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -25
- package/dist/resources/extensions/gsd/commands/index.js +8 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +43 -7
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -4
- package/dist/resources/extensions/gsd/doctor-proactive.js +3 -3
- package/dist/resources/extensions/gsd/doctor.js +8 -4
- package/dist/resources/extensions/gsd/gsd-db.js +11 -0
- package/dist/resources/extensions/gsd/guided-flow.js +56 -31
- package/dist/resources/extensions/gsd/init-wizard.js +37 -0
- package/dist/resources/extensions/gsd/interrupted-session.js +146 -0
- package/dist/resources/extensions/gsd/mcp-project-config.js +83 -0
- package/dist/resources/extensions/gsd/state.js +7 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +508 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +18 -3
- package/dist/resources/extensions/gsd/workflow-mcp.js +261 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +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/page_client-reference-manifest.js +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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- 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/2826.821e01b07d92e948.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-0c485498795110d6.js → page-f1e30ab6bb269149.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-b49b09f97429b5d0.js → webpack-6e4d7e9a4f57bed4.js} +1 -1
- package/package.json +4 -2
- package/packages/mcp-server/README.md +38 -0
- package/packages/mcp-server/dist/cli.d.ts +9 -0
- package/packages/mcp-server/dist/cli.d.ts.map +1 -0
- package/packages/mcp-server/dist/cli.js +58 -0
- package/packages/mcp-server/dist/cli.js.map +1 -0
- package/packages/mcp-server/dist/index.d.ts +20 -0
- package/packages/mcp-server/dist/index.d.ts.map +1 -0
- package/packages/mcp-server/dist/index.js +14 -0
- package/packages/mcp-server/dist/index.js.map +1 -0
- package/packages/mcp-server/dist/readers/captures.d.ts +25 -0
- package/packages/mcp-server/dist/readers/captures.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/captures.js +67 -0
- package/packages/mcp-server/dist/readers/captures.js.map +1 -0
- package/packages/mcp-server/dist/readers/doctor-lite.d.ts +20 -0
- package/packages/mcp-server/dist/readers/doctor-lite.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/doctor-lite.js +173 -0
- package/packages/mcp-server/dist/readers/doctor-lite.js.map +1 -0
- package/packages/mcp-server/dist/readers/index.d.ts +14 -0
- package/packages/mcp-server/dist/readers/index.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/index.js +10 -0
- package/packages/mcp-server/dist/readers/index.js.map +1 -0
- package/packages/mcp-server/dist/readers/knowledge.d.ts +18 -0
- package/packages/mcp-server/dist/readers/knowledge.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/knowledge.js +82 -0
- package/packages/mcp-server/dist/readers/knowledge.js.map +1 -0
- package/packages/mcp-server/dist/readers/metrics.d.ts +32 -0
- package/packages/mcp-server/dist/readers/metrics.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/metrics.js +74 -0
- package/packages/mcp-server/dist/readers/metrics.js.map +1 -0
- package/packages/mcp-server/dist/readers/paths.d.ts +42 -0
- package/packages/mcp-server/dist/readers/paths.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/paths.js +199 -0
- package/packages/mcp-server/dist/readers/paths.js.map +1 -0
- package/packages/mcp-server/dist/readers/roadmap.d.ts +26 -0
- package/packages/mcp-server/dist/readers/roadmap.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/roadmap.js +194 -0
- package/packages/mcp-server/dist/readers/roadmap.js.map +1 -0
- package/packages/mcp-server/dist/readers/state.d.ts +43 -0
- package/packages/mcp-server/dist/readers/state.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/state.js +184 -0
- package/packages/mcp-server/dist/readers/state.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +28 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -0
- package/packages/mcp-server/dist/server.js +319 -0
- package/packages/mcp-server/dist/server.js.map +1 -0
- package/packages/mcp-server/dist/session-manager.d.ts +54 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -0
- package/packages/mcp-server/dist/session-manager.js +284 -0
- package/packages/mcp-server/dist/session-manager.js.map +1 -0
- package/packages/mcp-server/dist/types.d.ts +61 -0
- package/packages/mcp-server/dist/types.d.ts.map +1 -0
- package/packages/mcp-server/dist/types.js +11 -0
- package/packages/mcp-server/dist/types.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts +9 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.js +532 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -0
- package/packages/mcp-server/src/server.ts +6 -2
- package/packages/mcp-server/src/workflow-tools.test.ts +976 -0
- package/packages/mcp-server/src/workflow-tools.ts +997 -0
- package/packages/mcp-server/tsconfig.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +14 -6
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +53 -0
- package/packages/pi-agent-core/src/agent-loop.ts +20 -6
- package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts +43 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.js +208 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.js +227 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +28 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -0
- 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 +17 -12
- 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 +19 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
- 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 +15 -12
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/contextual-tips.test.ts +259 -0
- package/packages/pi-coding-agent/src/core/contextual-tips.ts +232 -0
- package/packages/pi-coding-agent/src/core/index.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +54 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +18 -12
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +21 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +19 -15
- package/packages/rpc-client/dist/index.d.ts +10 -0
- package/packages/rpc-client/dist/index.d.ts.map +1 -0
- package/packages/rpc-client/dist/index.js +9 -0
- package/packages/rpc-client/dist/index.js.map +1 -0
- package/packages/rpc-client/dist/jsonl.d.ts +17 -0
- package/packages/rpc-client/dist/jsonl.d.ts.map +1 -0
- package/packages/rpc-client/dist/jsonl.js +54 -0
- package/packages/rpc-client/dist/jsonl.js.map +1 -0
- package/packages/rpc-client/dist/rpc-client.d.ts +259 -0
- package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -0
- package/packages/rpc-client/dist/rpc-client.js +541 -0
- package/packages/rpc-client/dist/rpc-client.js.map +1 -0
- package/packages/rpc-client/dist/rpc-client.test.d.ts +2 -0
- package/packages/rpc-client/dist/rpc-client.test.d.ts.map +1 -0
- package/packages/rpc-client/dist/rpc-client.test.js +477 -0
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -0
- package/packages/rpc-client/dist/rpc-types.d.ts +566 -0
- package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -0
- package/packages/rpc-client/dist/rpc-types.js +12 -0
- package/packages/rpc-client/dist/rpc-types.js.map +1 -0
- package/scripts/ensure-workspace-builds.cjs +2 -0
- package/scripts/link-workspace-packages.cjs +21 -14
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +193 -93
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +173 -79
- package/src/resources/extensions/gsd/auto/phases.ts +25 -0
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +20 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto-start.ts +23 -55
- package/src/resources/extensions/gsd/auto-worktree.ts +59 -15
- package/src/resources/extensions/gsd/auto.ts +133 -64
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +22 -435
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -5
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +7 -72
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -2
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +122 -6
- package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +53 -26
- package/src/resources/extensions/gsd/commands/index.ts +7 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +53 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +4 -4
- package/src/resources/extensions/gsd/doctor-proactive.ts +3 -3
- package/src/resources/extensions/gsd/doctor.ts +9 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -0
- package/src/resources/extensions/gsd/guided-flow.ts +66 -36
- package/src/resources/extensions/gsd/init-wizard.ts +40 -0
- package/src/resources/extensions/gsd/interrupted-session.ts +224 -0
- package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
- package/src/resources/extensions/gsd/state.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +668 -2
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +380 -2
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/integration/doctor-fixlevel.test.ts +52 -1
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +2 -9
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +0 -33
- package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +169 -0
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +500 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +625 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +629 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +19 -3
- package/src/resources/extensions/gsd/workflow-mcp.ts +320 -0
- package/dist/web/standalone/.next/static/chunks/6502.b804e48b7919f55e.js +0 -9
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts +0 -13
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js +0 -27
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js.map +0 -1
- package/packages/pi-coding-agent/src/modes/interactive/provider-auth-setup.ts +0 -40
- /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → WMDT_0C0XDkBKtsAI_AX4}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → WMDT_0C0XDkBKtsAI_AX4}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
|
|
2
|
+
import { sanitizeCompleteMilestoneParams } from "../bootstrap/sanitize-complete-milestone.js";
|
|
3
|
+
import { loadWriteGateSnapshot, shouldBlockContextArtifactSaveInSnapshot } from "../bootstrap/write-gate.js";
|
|
4
|
+
import { getMilestone, getSliceStatusSummary, getSliceTaskCounts, _getAdapter, saveGateResult, } from "../gsd-db.js";
|
|
5
|
+
import { saveArtifactToDb } from "../db-writer.js";
|
|
6
|
+
import { handleCompleteMilestone } from "./complete-milestone.js";
|
|
7
|
+
import { handleCompleteTask } from "./complete-task.js";
|
|
8
|
+
import { handleCompleteSlice } from "./complete-slice.js";
|
|
9
|
+
import { handlePlanMilestone } from "./plan-milestone.js";
|
|
10
|
+
import { handlePlanSlice } from "./plan-slice.js";
|
|
11
|
+
import { handleReplanSlice } from "./replan-slice.js";
|
|
12
|
+
import { handleReassessRoadmap } from "./reassess-roadmap.js";
|
|
13
|
+
import { handleValidateMilestone } from "./validate-milestone.js";
|
|
14
|
+
import { logError, logWarning } from "../workflow-logger.js";
|
|
15
|
+
import { invalidateStateCache } from "../state.js";
|
|
16
|
+
export const SUPPORTED_SUMMARY_ARTIFACT_TYPES = ["SUMMARY", "RESEARCH", "CONTEXT", "ASSESSMENT", "CONTEXT-DRAFT"];
|
|
17
|
+
export function isSupportedSummaryArtifactType(artifactType) {
|
|
18
|
+
return SUPPORTED_SUMMARY_ARTIFACT_TYPES.includes(artifactType);
|
|
19
|
+
}
|
|
20
|
+
export async function executeSummarySave(params, basePath = process.cwd()) {
|
|
21
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
22
|
+
if (!dbAvailable) {
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot save artifact." }],
|
|
25
|
+
details: { operation: "save_summary", error: "db_unavailable" },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (!isSupportedSummaryArtifactType(params.artifact_type)) {
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: "text", text: `Error: Invalid artifact_type "${params.artifact_type}". Must be one of: ${SUPPORTED_SUMMARY_ARTIFACT_TYPES.join(", ")}` }],
|
|
31
|
+
details: { operation: "save_summary", error: "invalid_artifact_type" },
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const contextGuard = shouldBlockContextArtifactSaveInSnapshot(loadWriteGateSnapshot(basePath), params.artifact_type, params.milestone_id ?? null, params.slice_id ?? null);
|
|
35
|
+
if (contextGuard.block) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: `Error saving artifact: ${contextGuard.reason ?? "context write blocked"}` }],
|
|
38
|
+
details: { operation: "save_summary", error: "context_write_blocked" },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
let relativePath;
|
|
43
|
+
if (params.task_id && params.slice_id) {
|
|
44
|
+
relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/tasks/${params.task_id}-${params.artifact_type}.md`;
|
|
45
|
+
}
|
|
46
|
+
else if (params.slice_id) {
|
|
47
|
+
relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/${params.slice_id}-${params.artifact_type}.md`;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
relativePath = `milestones/${params.milestone_id}/${params.milestone_id}-${params.artifact_type}.md`;
|
|
51
|
+
}
|
|
52
|
+
await saveArtifactToDb({
|
|
53
|
+
path: relativePath,
|
|
54
|
+
artifact_type: params.artifact_type,
|
|
55
|
+
content: params.content,
|
|
56
|
+
milestone_id: params.milestone_id,
|
|
57
|
+
slice_id: params.slice_id,
|
|
58
|
+
task_id: params.task_id,
|
|
59
|
+
}, basePath);
|
|
60
|
+
return {
|
|
61
|
+
content: [{ type: "text", text: `Saved ${params.artifact_type} artifact to ${relativePath}` }],
|
|
62
|
+
details: { operation: "save_summary", path: relativePath, artifact_type: params.artifact_type },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
67
|
+
logError("tool", `gsd_summary_save tool failed: ${msg}`, { tool: "gsd_summary_save", error: String(err) });
|
|
68
|
+
return {
|
|
69
|
+
content: [{ type: "text", text: `Error saving artifact: ${msg}` }],
|
|
70
|
+
details: { operation: "save_summary", error: msg },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export async function executeTaskComplete(params, basePath = process.cwd()) {
|
|
75
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
76
|
+
if (!dbAvailable) {
|
|
77
|
+
return {
|
|
78
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot complete task." }],
|
|
79
|
+
details: { operation: "complete_task", error: "db_unavailable" },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const coerced = { ...params };
|
|
84
|
+
coerced.verificationEvidence = (params.verificationEvidence ?? []).map((v) => typeof v === "string" ? { command: v, exitCode: -1, verdict: "unknown (coerced from string)", durationMs: 0 } : v);
|
|
85
|
+
const result = await handleCompleteTask(coerced, basePath);
|
|
86
|
+
if ("error" in result) {
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: "text", text: `Error completing task: ${result.error}` }],
|
|
89
|
+
details: { operation: "complete_task", error: result.error },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
content: [{ type: "text", text: `Completed task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
|
|
94
|
+
details: {
|
|
95
|
+
operation: "complete_task",
|
|
96
|
+
taskId: result.taskId,
|
|
97
|
+
sliceId: result.sliceId,
|
|
98
|
+
milestoneId: result.milestoneId,
|
|
99
|
+
summaryPath: result.summaryPath,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
105
|
+
logError("tool", `complete_task tool failed: ${msg}`, { tool: "gsd_task_complete", error: String(err) });
|
|
106
|
+
return {
|
|
107
|
+
content: [{ type: "text", text: `Error completing task: ${msg}` }],
|
|
108
|
+
details: { operation: "complete_task", error: msg },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export async function executeSliceComplete(params, basePath = process.cwd()) {
|
|
113
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
114
|
+
if (!dbAvailable) {
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot complete slice." }],
|
|
117
|
+
details: { operation: "complete_slice", error: "db_unavailable" },
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
const splitPair = (s) => {
|
|
122
|
+
const m = s.match(/^(.+?)\s*(?:—|-)\s+(.+)$/);
|
|
123
|
+
return m ? [m[1].trim(), m[2].trim()] : [s.trim(), ""];
|
|
124
|
+
};
|
|
125
|
+
const wrapArray = (v) => v == null ? [] : Array.isArray(v) ? v : [v];
|
|
126
|
+
const coerced = { ...params };
|
|
127
|
+
coerced.provides = wrapArray(params.provides);
|
|
128
|
+
coerced.keyFiles = wrapArray(params.keyFiles);
|
|
129
|
+
coerced.keyDecisions = wrapArray(params.keyDecisions);
|
|
130
|
+
coerced.patternsEstablished = wrapArray(params.patternsEstablished);
|
|
131
|
+
coerced.observabilitySurfaces = wrapArray(params.observabilitySurfaces);
|
|
132
|
+
coerced.requirementsSurfaced = wrapArray(params.requirementsSurfaced);
|
|
133
|
+
coerced.drillDownPaths = wrapArray(params.drillDownPaths);
|
|
134
|
+
coerced.affects = wrapArray(params.affects);
|
|
135
|
+
coerced.filesModified = wrapArray(params.filesModified).map((f) => {
|
|
136
|
+
if (typeof f !== "string")
|
|
137
|
+
return f;
|
|
138
|
+
const [path, description] = splitPair(f);
|
|
139
|
+
return { path, description };
|
|
140
|
+
});
|
|
141
|
+
coerced.requires = wrapArray(params.requires).map((r) => {
|
|
142
|
+
if (typeof r !== "string")
|
|
143
|
+
return r;
|
|
144
|
+
const [slice, provides] = splitPair(r);
|
|
145
|
+
return { slice, provides };
|
|
146
|
+
});
|
|
147
|
+
coerced.requirementsAdvanced = wrapArray(params.requirementsAdvanced).map((r) => {
|
|
148
|
+
if (typeof r !== "string")
|
|
149
|
+
return r;
|
|
150
|
+
const [id, how] = splitPair(r);
|
|
151
|
+
return { id, how };
|
|
152
|
+
});
|
|
153
|
+
coerced.requirementsValidated = wrapArray(params.requirementsValidated).map((r) => {
|
|
154
|
+
if (typeof r !== "string")
|
|
155
|
+
return r;
|
|
156
|
+
const [id, proof] = splitPair(r);
|
|
157
|
+
return { id, proof };
|
|
158
|
+
});
|
|
159
|
+
coerced.requirementsInvalidated = wrapArray(params.requirementsInvalidated).map((r) => {
|
|
160
|
+
if (typeof r !== "string")
|
|
161
|
+
return r;
|
|
162
|
+
const [id, what] = splitPair(r);
|
|
163
|
+
return { id, what };
|
|
164
|
+
});
|
|
165
|
+
const result = await handleCompleteSlice(coerced, basePath);
|
|
166
|
+
if ("error" in result) {
|
|
167
|
+
return {
|
|
168
|
+
content: [{ type: "text", text: `Error completing slice: ${result.error}` }],
|
|
169
|
+
details: { operation: "complete_slice", error: result.error },
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
content: [{ type: "text", text: `Completed slice ${result.sliceId} (${result.milestoneId})` }],
|
|
174
|
+
details: {
|
|
175
|
+
operation: "complete_slice",
|
|
176
|
+
sliceId: result.sliceId,
|
|
177
|
+
milestoneId: result.milestoneId,
|
|
178
|
+
summaryPath: result.summaryPath,
|
|
179
|
+
uatPath: result.uatPath,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
185
|
+
logError("tool", `complete_slice tool failed: ${msg}`, { tool: "gsd_slice_complete", error: String(err) });
|
|
186
|
+
return {
|
|
187
|
+
content: [{ type: "text", text: `Error completing slice: ${msg}` }],
|
|
188
|
+
details: { operation: "complete_slice", error: msg },
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export async function executeCompleteMilestone(params, basePath = process.cwd()) {
|
|
193
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
194
|
+
if (!dbAvailable) {
|
|
195
|
+
return {
|
|
196
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot complete milestone." }],
|
|
197
|
+
details: { operation: "complete_milestone", error: "db_unavailable" },
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const sanitized = sanitizeCompleteMilestoneParams(params);
|
|
202
|
+
const result = await handleCompleteMilestone(sanitized, basePath);
|
|
203
|
+
if ("error" in result) {
|
|
204
|
+
return {
|
|
205
|
+
content: [{ type: "text", text: `Error completing milestone: ${result.error}` }],
|
|
206
|
+
details: { operation: "complete_milestone", error: result.error },
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
content: [{ type: "text", text: `Completed milestone ${result.milestoneId}. Summary written to ${result.summaryPath}` }],
|
|
211
|
+
details: {
|
|
212
|
+
operation: "complete_milestone",
|
|
213
|
+
milestoneId: result.milestoneId,
|
|
214
|
+
summaryPath: result.summaryPath,
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
220
|
+
logError("tool", `complete_milestone tool failed: ${msg}`, { tool: "gsd_complete_milestone", error: String(err) });
|
|
221
|
+
return {
|
|
222
|
+
content: [{ type: "text", text: `Error completing milestone: ${msg}` }],
|
|
223
|
+
details: { operation: "complete_milestone", error: msg },
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
export async function executeValidateMilestone(params, basePath = process.cwd()) {
|
|
228
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
229
|
+
if (!dbAvailable) {
|
|
230
|
+
return {
|
|
231
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot validate milestone." }],
|
|
232
|
+
details: { operation: "validate_milestone", error: "db_unavailable" },
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const result = await handleValidateMilestone(params, basePath);
|
|
237
|
+
if ("error" in result) {
|
|
238
|
+
return {
|
|
239
|
+
content: [{ type: "text", text: `Error validating milestone: ${result.error}` }],
|
|
240
|
+
details: { operation: "validate_milestone", error: result.error },
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
content: [{ type: "text", text: `Validated milestone ${result.milestoneId} — verdict: ${result.verdict}. Written to ${result.validationPath}` }],
|
|
245
|
+
details: {
|
|
246
|
+
operation: "validate_milestone",
|
|
247
|
+
milestoneId: result.milestoneId,
|
|
248
|
+
verdict: result.verdict,
|
|
249
|
+
validationPath: result.validationPath,
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
255
|
+
logError("tool", `validate_milestone tool failed: ${msg}`, { tool: "gsd_validate_milestone", error: String(err) });
|
|
256
|
+
return {
|
|
257
|
+
content: [{ type: "text", text: `Error validating milestone: ${msg}` }],
|
|
258
|
+
details: { operation: "validate_milestone", error: msg },
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
export async function executeReassessRoadmap(params, basePath = process.cwd()) {
|
|
263
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
264
|
+
if (!dbAvailable) {
|
|
265
|
+
return {
|
|
266
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot reassess roadmap." }],
|
|
267
|
+
details: { operation: "reassess_roadmap", error: "db_unavailable" },
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const result = await handleReassessRoadmap(params, basePath);
|
|
272
|
+
if ("error" in result) {
|
|
273
|
+
return {
|
|
274
|
+
content: [{ type: "text", text: `Error reassessing roadmap: ${result.error}` }],
|
|
275
|
+
details: { operation: "reassess_roadmap", error: result.error },
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
content: [{ type: "text", text: `Reassessed roadmap for milestone ${result.milestoneId} after ${result.completedSliceId}` }],
|
|
280
|
+
details: {
|
|
281
|
+
operation: "reassess_roadmap",
|
|
282
|
+
milestoneId: result.milestoneId,
|
|
283
|
+
completedSliceId: result.completedSliceId,
|
|
284
|
+
assessmentPath: result.assessmentPath,
|
|
285
|
+
roadmapPath: result.roadmapPath,
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
291
|
+
logError("tool", `reassess_roadmap tool failed: ${msg}`, { tool: "gsd_reassess_roadmap", error: String(err) });
|
|
292
|
+
return {
|
|
293
|
+
content: [{ type: "text", text: `Error reassessing roadmap: ${msg}` }],
|
|
294
|
+
details: { operation: "reassess_roadmap", error: msg },
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
export async function executeSaveGateResult(params, basePath = process.cwd()) {
|
|
299
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
300
|
+
if (!dbAvailable) {
|
|
301
|
+
return {
|
|
302
|
+
content: [{ type: "text", text: "Error: GSD database is not available." }],
|
|
303
|
+
details: { operation: "save_gate_result", error: "db_unavailable" },
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const validGates = ["Q3", "Q4", "Q5", "Q6", "Q7", "Q8"];
|
|
307
|
+
if (!validGates.includes(params.gateId)) {
|
|
308
|
+
return {
|
|
309
|
+
content: [{ type: "text", text: `Error: Invalid gateId "${params.gateId}". Must be one of: ${validGates.join(", ")}` }],
|
|
310
|
+
details: { operation: "save_gate_result", error: "invalid_gate_id" },
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const validVerdicts = ["pass", "flag", "omitted"];
|
|
314
|
+
if (!validVerdicts.includes(params.verdict)) {
|
|
315
|
+
return {
|
|
316
|
+
content: [{ type: "text", text: `Error: Invalid verdict "${params.verdict}". Must be one of: ${validVerdicts.join(", ")}` }],
|
|
317
|
+
details: { operation: "save_gate_result", error: "invalid_verdict" },
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
saveGateResult({
|
|
322
|
+
milestoneId: params.milestoneId,
|
|
323
|
+
sliceId: params.sliceId,
|
|
324
|
+
gateId: params.gateId,
|
|
325
|
+
taskId: params.taskId ?? "",
|
|
326
|
+
verdict: params.verdict,
|
|
327
|
+
rationale: params.rationale,
|
|
328
|
+
findings: params.findings ?? "",
|
|
329
|
+
});
|
|
330
|
+
invalidateStateCache();
|
|
331
|
+
return {
|
|
332
|
+
content: [{ type: "text", text: `Gate ${params.gateId} result saved: verdict=${params.verdict}` }],
|
|
333
|
+
details: { operation: "save_gate_result", gateId: params.gateId, verdict: params.verdict },
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
338
|
+
logError("tool", `gsd_save_gate_result failed: ${msg}`, { tool: "gsd_save_gate_result", error: String(err) });
|
|
339
|
+
return {
|
|
340
|
+
content: [{ type: "text", text: `Error saving gate result: ${msg}` }],
|
|
341
|
+
details: { operation: "save_gate_result", error: msg },
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
export async function executePlanMilestone(params, basePath = process.cwd()) {
|
|
346
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
347
|
+
if (!dbAvailable) {
|
|
348
|
+
return {
|
|
349
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot plan milestone." }],
|
|
350
|
+
details: { operation: "plan_milestone", error: "db_unavailable" },
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
const result = await handlePlanMilestone(params, basePath);
|
|
355
|
+
if ("error" in result) {
|
|
356
|
+
return {
|
|
357
|
+
content: [{ type: "text", text: `Error planning milestone: ${result.error}` }],
|
|
358
|
+
details: { operation: "plan_milestone", error: result.error },
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
content: [{ type: "text", text: `Planned milestone ${result.milestoneId}` }],
|
|
363
|
+
details: {
|
|
364
|
+
operation: "plan_milestone",
|
|
365
|
+
milestoneId: result.milestoneId,
|
|
366
|
+
roadmapPath: result.roadmapPath,
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
catch (err) {
|
|
371
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
372
|
+
logError("tool", `plan_milestone tool failed: ${msg}`, { tool: "gsd_plan_milestone", error: String(err) });
|
|
373
|
+
return {
|
|
374
|
+
content: [{ type: "text", text: `Error planning milestone: ${msg}` }],
|
|
375
|
+
details: { operation: "plan_milestone", error: msg },
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
export async function executePlanSlice(params, basePath = process.cwd()) {
|
|
380
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
381
|
+
if (!dbAvailable) {
|
|
382
|
+
return {
|
|
383
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot plan slice." }],
|
|
384
|
+
details: { operation: "plan_slice", error: "db_unavailable" },
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
const result = await handlePlanSlice(params, basePath);
|
|
389
|
+
if ("error" in result) {
|
|
390
|
+
return {
|
|
391
|
+
content: [{ type: "text", text: `Error planning slice: ${result.error}` }],
|
|
392
|
+
details: { operation: "plan_slice", error: result.error },
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
content: [{ type: "text", text: `Planned slice ${result.sliceId} (${result.milestoneId})` }],
|
|
397
|
+
details: {
|
|
398
|
+
operation: "plan_slice",
|
|
399
|
+
milestoneId: result.milestoneId,
|
|
400
|
+
sliceId: result.sliceId,
|
|
401
|
+
planPath: result.planPath,
|
|
402
|
+
taskPlanPaths: result.taskPlanPaths,
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
catch (err) {
|
|
407
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
408
|
+
logError("tool", `plan_slice tool failed: ${msg}`, { tool: "gsd_plan_slice", error: String(err) });
|
|
409
|
+
return {
|
|
410
|
+
content: [{ type: "text", text: `Error planning slice: ${msg}` }],
|
|
411
|
+
details: { operation: "plan_slice", error: msg },
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
export async function executeReplanSlice(params, basePath = process.cwd()) {
|
|
416
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
417
|
+
if (!dbAvailable) {
|
|
418
|
+
return {
|
|
419
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot replan slice." }],
|
|
420
|
+
details: { operation: "replan_slice", error: "db_unavailable" },
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
const result = await handleReplanSlice(params, basePath);
|
|
425
|
+
if ("error" in result) {
|
|
426
|
+
return {
|
|
427
|
+
content: [{ type: "text", text: `Error replanning slice: ${result.error}` }],
|
|
428
|
+
details: { operation: "replan_slice", error: result.error },
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
return {
|
|
432
|
+
content: [{ type: "text", text: `Replanned slice ${result.sliceId} (${result.milestoneId})` }],
|
|
433
|
+
details: {
|
|
434
|
+
operation: "replan_slice",
|
|
435
|
+
milestoneId: result.milestoneId,
|
|
436
|
+
sliceId: result.sliceId,
|
|
437
|
+
replanPath: result.replanPath,
|
|
438
|
+
planPath: result.planPath,
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
catch (err) {
|
|
443
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
444
|
+
logError("tool", `replan_slice tool failed: ${msg}`, { tool: "gsd_replan_slice", error: String(err) });
|
|
445
|
+
return {
|
|
446
|
+
content: [{ type: "text", text: `Error replanning slice: ${msg}` }],
|
|
447
|
+
details: { operation: "replan_slice", error: msg },
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
export async function executeMilestoneStatus(params, basePath = process.cwd()) {
|
|
452
|
+
try {
|
|
453
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
454
|
+
if (!dbAvailable) {
|
|
455
|
+
return {
|
|
456
|
+
content: [{ type: "text", text: "Error: GSD database is not available." }],
|
|
457
|
+
details: { operation: "milestone_status", error: "db_unavailable" },
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
const adapter = _getAdapter();
|
|
461
|
+
adapter.exec("BEGIN");
|
|
462
|
+
try {
|
|
463
|
+
const milestone = getMilestone(params.milestoneId);
|
|
464
|
+
if (!milestone) {
|
|
465
|
+
adapter.exec("COMMIT");
|
|
466
|
+
return {
|
|
467
|
+
content: [{ type: "text", text: `Milestone ${params.milestoneId} not found in database.` }],
|
|
468
|
+
details: { operation: "milestone_status", milestoneId: params.milestoneId, found: false },
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const sliceStatuses = getSliceStatusSummary(params.milestoneId);
|
|
472
|
+
const slices = sliceStatuses.map((s) => ({
|
|
473
|
+
id: s.id,
|
|
474
|
+
status: s.status,
|
|
475
|
+
taskCounts: getSliceTaskCounts(params.milestoneId, s.id),
|
|
476
|
+
}));
|
|
477
|
+
adapter.exec("COMMIT");
|
|
478
|
+
const result = {
|
|
479
|
+
milestoneId: milestone.id,
|
|
480
|
+
title: milestone.title,
|
|
481
|
+
status: milestone.status,
|
|
482
|
+
createdAt: milestone.created_at,
|
|
483
|
+
completedAt: milestone.completed_at,
|
|
484
|
+
sliceCount: slices.length,
|
|
485
|
+
slices,
|
|
486
|
+
};
|
|
487
|
+
return {
|
|
488
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
489
|
+
details: { operation: "milestone_status", milestoneId: milestone.id, sliceCount: slices.length },
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
catch (txErr) {
|
|
493
|
+
try {
|
|
494
|
+
adapter.exec("ROLLBACK");
|
|
495
|
+
}
|
|
496
|
+
catch { /* swallow */ }
|
|
497
|
+
throw txErr;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
catch (err) {
|
|
501
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
502
|
+
logWarning("tool", `gsd_milestone_status tool failed: ${msg}`);
|
|
503
|
+
return {
|
|
504
|
+
content: [{ type: "text", text: `Error querying milestone status: ${msg}` }],
|
|
505
|
+
details: { operation: "milestone_status", error: msg },
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
}
|
|
@@ -22,6 +22,7 @@ import { appendNotification } from "./notification-store.js";
|
|
|
22
22
|
const MAX_BUFFER = 100;
|
|
23
23
|
let _buffer = [];
|
|
24
24
|
let _auditBasePath = null;
|
|
25
|
+
let _stderrEnabled = true;
|
|
25
26
|
/**
|
|
26
27
|
* Set the base path for persistent audit log writes.
|
|
27
28
|
* Should be called once at engine init with the project root.
|
|
@@ -30,6 +31,15 @@ let _auditBasePath = null;
|
|
|
30
31
|
export function setLogBasePath(basePath) {
|
|
31
32
|
_auditBasePath = basePath;
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Enable or disable immediate stderr writes for workflow logs.
|
|
36
|
+
* Returns the previous setting so callers can restore it.
|
|
37
|
+
*/
|
|
38
|
+
export function setStderrLoggingEnabled(enabled) {
|
|
39
|
+
const previous = _stderrEnabled;
|
|
40
|
+
_stderrEnabled = enabled;
|
|
41
|
+
return previous;
|
|
42
|
+
}
|
|
33
43
|
// ─── Public API ─────────────────────────────────────────────────────────
|
|
34
44
|
/**
|
|
35
45
|
* Record a warning. Also writes to stderr for terminal visibility.
|
|
@@ -179,13 +189,13 @@ function _push(severity, component, message, context) {
|
|
|
179
189
|
// Always forward to stderr so terminal watchers see it (see module header for policy)
|
|
180
190
|
const prefix = severity === "error" ? "ERROR" : "WARN";
|
|
181
191
|
const ctxStr = context ? ` ${JSON.stringify(context)}` : "";
|
|
182
|
-
|
|
192
|
+
_writeStderr(`[gsd:${component}] ${prefix}: ${message}${ctxStr}\n`);
|
|
183
193
|
// Persist to notification store (both warnings and errors)
|
|
184
194
|
try {
|
|
185
195
|
appendNotification(`[${component}] ${message}`, severity === "error" ? "error" : "warning", "workflow-logger");
|
|
186
196
|
}
|
|
187
197
|
catch (notifErr) {
|
|
188
|
-
|
|
198
|
+
_writeStderr(`[gsd:workflow-logger] notification-store append failed: ${notifErr.message}\n`);
|
|
189
199
|
}
|
|
190
200
|
// Buffer for auto-loop to drain
|
|
191
201
|
_buffer.push(entry);
|
|
@@ -204,10 +214,15 @@ function _push(severity, component, message, context) {
|
|
|
204
214
|
}
|
|
205
215
|
catch (auditErr) {
|
|
206
216
|
// Best-effort — never let audit write failures bubble up
|
|
207
|
-
|
|
217
|
+
_writeStderr(`[gsd:audit] failed to persist log entry: ${auditErr.message}\n`);
|
|
208
218
|
}
|
|
209
219
|
}
|
|
210
220
|
}
|
|
221
|
+
function _writeStderr(message) {
|
|
222
|
+
if (!_stderrEnabled)
|
|
223
|
+
return;
|
|
224
|
+
process.stderr.write(message);
|
|
225
|
+
}
|
|
211
226
|
/**
|
|
212
227
|
* Sanitize a log entry before persisting to the audit JSONL file.
|
|
213
228
|
* Strips potentially sensitive context (raw paths, cwd, full error text)
|