gsd-pi 2.77.0-dev.c9c8932c6 → 2.77.0-dev.eaa4973bc
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/cli-web-branch.d.ts +1 -0
- package/dist/cli-web-branch.js +3 -0
- package/dist/cli.js +24 -2
- package/dist/provider-migrations.d.ts +18 -0
- package/dist/provider-migrations.js +14 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +14 -10
- package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
- package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
- package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +24 -0
- package/dist/resources/extensions/gsd/auto-loop.js +1 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +31 -0
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +58 -8
- package/dist/resources/extensions/gsd/auto.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
- package/dist/resources/extensions/gsd/file-lock.js +49 -9
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
- package/dist/resources/extensions/gsd/journal.js +17 -2
- package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
- package/dist/resources/extensions/gsd/reports.js +5 -4
- package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
- package/dist/resources/extensions/gsd/uok/audit.js +18 -2
- package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
- package/dist/resources/extensions/mcp-client/auth.js +10 -1
- package/dist/resources/extensions/mcp-client/index.js +118 -9
- package/dist/resources/skills/create-skill/SKILL.md +2 -2
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- 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 +13 -13
- 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/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +13 -13
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- 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.e9f5195e91f9cad2.js +11 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-1832629448831fdc.js → webpack-2e68521d7c82f7c2.js} +1 -1
- package/package.json +3 -3
- package/packages/mcp-server/README.md +3 -3
- package/packages/mcp-server/dist/env-writer.d.ts +1 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
- package/packages/mcp-server/dist/env-writer.js +74 -6
- package/packages/mcp-server/dist/env-writer.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +25 -2
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/src/env-writer.test.ts +79 -1
- package/packages/mcp-server/src/env-writer.ts +76 -6
- package/packages/mcp-server/src/server.ts +29 -2
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +21 -16
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +24 -17
- package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +19 -0
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +20 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +25 -0
- package/packages/pi-tui/src/stdin-buffer.ts +26 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +14 -10
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +22 -16
- package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
- package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +16 -2
- package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +20 -0
- package/src/resources/extensions/gsd/auto-loop.ts +1 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +30 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +60 -5
- package/src/resources/extensions/gsd/auto.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
- package/src/resources/extensions/gsd/file-lock.ts +84 -11
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
- package/src/resources/extensions/gsd/journal.ts +27 -2
- package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
- package/src/resources/extensions/gsd/reports.ts +5 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +39 -25
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
- package/src/resources/extensions/gsd/uok/audit.ts +20 -2
- package/src/resources/extensions/gsd/workflow-logger.ts +22 -3
- package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
- package/src/resources/extensions/mcp-client/auth.ts +12 -1
- package/src/resources/extensions/mcp-client/index.ts +129 -10
- package/src/resources/skills/create-skill/SKILL.md +2 -2
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2826.d445fb428ef41fa1.js +0 -9
- /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → 5wbu35_C2_MQ3Jj1lEVDx}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → 5wbu35_C2_MQ3Jj1lEVDx}/_ssgManifest.js +0 -0
|
@@ -38,6 +38,7 @@ import { writeManifest } from "../workflow-manifest.js";
|
|
|
38
38
|
import { appendEvent } from "../workflow-events.js";
|
|
39
39
|
import { logWarning, logError } from "../workflow-logger.js";
|
|
40
40
|
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
41
|
+
import { isStaleWrite } from "../auto/turn-epoch.js";
|
|
41
42
|
import { buildEscalationArtifact, writeEscalationArtifact } from "../escalation.js";
|
|
42
43
|
|
|
43
44
|
export interface CompleteTaskResult {
|
|
@@ -45,6 +46,14 @@ export interface CompleteTaskResult {
|
|
|
45
46
|
sliceId: string;
|
|
46
47
|
milestoneId: string;
|
|
47
48
|
summaryPath: string;
|
|
49
|
+
/**
|
|
50
|
+
* True when this call re-completed an already-closed task from a turn that
|
|
51
|
+
* had been superseded by timeout recovery or cancellation. The underlying
|
|
52
|
+
* state was not mutated; the response is a no-op shaped like a success so
|
|
53
|
+
* the orphaned LLM tool call resolves cleanly.
|
|
54
|
+
*/
|
|
55
|
+
duplicate?: boolean;
|
|
56
|
+
stale?: boolean;
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
import type { TaskRow } from "../gsd-db.js";
|
|
@@ -211,6 +220,18 @@ export async function handleCompleteTask(
|
|
|
211
220
|
|
|
212
221
|
const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
|
|
213
222
|
if (existingTask && isClosedStatus(existingTask.status)) {
|
|
223
|
+
// Stale-turn path: a timed-out turn that was superseded by recovery
|
|
224
|
+
// can still reach this code when its LLM call eventually returns and
|
|
225
|
+
// invokes gsd_complete_task. Returning an error would produce noisy
|
|
226
|
+
// "already complete — use reopen first" logs in the orphaned turn.
|
|
227
|
+
// Instead, signal the duplicate via a non-mutating success shape that
|
|
228
|
+
// callers can detect via `duplicate: true` / `stale: true`.
|
|
229
|
+
if (isStaleWrite("complete-task")) {
|
|
230
|
+
// Sentinel handled below — outside the transaction — so we don't
|
|
231
|
+
// render SUMMARY.md or flip plan checkboxes for a stale duplicate.
|
|
232
|
+
guardError = "__stale_duplicate__";
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
214
235
|
guardError = `task ${params.taskId} is already complete — use gsd_task_reopen first if you need to redo it`;
|
|
215
236
|
return;
|
|
216
237
|
}
|
|
@@ -248,6 +269,34 @@ export async function handleCompleteTask(
|
|
|
248
269
|
}
|
|
249
270
|
});
|
|
250
271
|
|
|
272
|
+
if (guardError === "__stale_duplicate__") {
|
|
273
|
+
// Orphaned-turn duplicate: the task is already complete from the
|
|
274
|
+
// superseded turn's earlier (real) call. Return a non-mutating success
|
|
275
|
+
// so the stale LLM tool call unwinds cleanly. summaryPath is synthesized
|
|
276
|
+
// from the existing on-disk layout; no file is written.
|
|
277
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
|
|
278
|
+
const staleSummaryPath = tasksDir
|
|
279
|
+
? join(tasksDir, `${params.taskId}-SUMMARY.md`)
|
|
280
|
+
: join(
|
|
281
|
+
basePath,
|
|
282
|
+
".gsd",
|
|
283
|
+
"milestones",
|
|
284
|
+
params.milestoneId,
|
|
285
|
+
"slices",
|
|
286
|
+
params.sliceId,
|
|
287
|
+
"tasks",
|
|
288
|
+
`${params.taskId}-SUMMARY.md`,
|
|
289
|
+
);
|
|
290
|
+
return {
|
|
291
|
+
taskId: params.taskId,
|
|
292
|
+
sliceId: params.sliceId,
|
|
293
|
+
milestoneId: params.milestoneId,
|
|
294
|
+
summaryPath: staleSummaryPath,
|
|
295
|
+
duplicate: true,
|
|
296
|
+
stale: true,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
251
300
|
if (guardError) {
|
|
252
301
|
return { error: guardError };
|
|
253
302
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { appendFileSync, mkdirSync } from "node:fs";
|
|
1
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
|
|
5
|
+
import { isStaleWrite } from "../auto/turn-epoch.js";
|
|
6
|
+
import { withFileLockSync } from "../file-lock.js";
|
|
5
7
|
import { gsdRoot } from "../paths.js";
|
|
6
8
|
import { isDbAvailable, insertAuditEvent } from "../gsd-db.js";
|
|
7
9
|
import type { AuditEventEnvelope } from "./contracts.js";
|
|
@@ -35,9 +37,25 @@ export function buildAuditEnvelope(args: {
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export function emitUokAuditEvent(basePath: string, event: AuditEventEnvelope): void {
|
|
40
|
+
// Drop writes from a turn superseded by timeout recovery / cancellation.
|
|
41
|
+
if (isStaleWrite("uok-audit")) return;
|
|
38
42
|
try {
|
|
39
43
|
ensureAuditDir(basePath);
|
|
40
|
-
|
|
44
|
+
const path = auditLogPath(basePath);
|
|
45
|
+
// proper-lockfile requires the target file to exist before locking.
|
|
46
|
+
// Touch it via open(O_APPEND|O_CREAT) so the first writer wins the race
|
|
47
|
+
// atomically at the kernel level.
|
|
48
|
+
if (!existsSync(path)) closeSync(openSync(path, "a"));
|
|
49
|
+
// onLocked: "skip" — audit writes are best-effort; under heavy contention
|
|
50
|
+
// POSIX O_APPEND atomicity still protects small line writes, so skipping
|
|
51
|
+
// the lock rather than stalling orchestration is the correct tradeoff.
|
|
52
|
+
withFileLockSync(
|
|
53
|
+
path,
|
|
54
|
+
() => {
|
|
55
|
+
appendFileSync(path, `${JSON.stringify(event)}\n`, "utf-8");
|
|
56
|
+
},
|
|
57
|
+
{ onLocked: "skip" },
|
|
58
|
+
);
|
|
41
59
|
} catch {
|
|
42
60
|
// Best-effort: audit writes must never break orchestration.
|
|
43
61
|
}
|
|
@@ -16,9 +16,17 @@
|
|
|
16
16
|
// the start of each unit to prevent log bleed between units running in the same
|
|
17
17
|
// Node process.
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
appendFileSync,
|
|
21
|
+
closeSync,
|
|
22
|
+
existsSync,
|
|
23
|
+
mkdirSync,
|
|
24
|
+
openSync,
|
|
25
|
+
readFileSync,
|
|
26
|
+
} from "node:fs";
|
|
20
27
|
import { join } from "node:path";
|
|
21
28
|
|
|
29
|
+
import { withFileLockSync } from "./file-lock.js";
|
|
22
30
|
import { appendNotification } from "./notification-store.js";
|
|
23
31
|
import { buildAuditEnvelope, emitUokAuditEvent } from "./uok/audit.js";
|
|
24
32
|
import { isUnifiedAuditEnabled } from "./uok/audit-toggle.js";
|
|
@@ -59,7 +67,8 @@ export type LogComponent =
|
|
|
59
67
|
| "memory-ingest" // Memory layer ingestion pipeline
|
|
60
68
|
| "memory-backfill" // ADR-013: decisions->memories backfill
|
|
61
69
|
| "context-mode" // Context-mode exec sandbox and compaction snapshot
|
|
62
|
-
| "preflight"
|
|
70
|
+
| "preflight" // Clean-root preflight gate at milestone completion
|
|
71
|
+
| "postUnit"; // Post-unit processing (abandon detection, overrides)
|
|
63
72
|
|
|
64
73
|
export interface LogEntry {
|
|
65
74
|
ts: string;
|
|
@@ -313,8 +322,18 @@ function _push(
|
|
|
313
322
|
try {
|
|
314
323
|
const auditDir = join(_auditBasePath, ".gsd");
|
|
315
324
|
mkdirSync(auditDir, { recursive: true });
|
|
325
|
+
const auditPath = join(auditDir, "audit-log.jsonl");
|
|
316
326
|
const sanitized = _sanitizeForAudit(entry);
|
|
317
|
-
|
|
327
|
+
// Ensure file exists so proper-lockfile can acquire a lock against it.
|
|
328
|
+
if (!existsSync(auditPath)) closeSync(openSync(auditPath, "a"));
|
|
329
|
+
// onLocked: "skip" — never block error logging on lock contention.
|
|
330
|
+
withFileLockSync(
|
|
331
|
+
auditPath,
|
|
332
|
+
() => {
|
|
333
|
+
appendFileSync(auditPath, JSON.stringify(sanitized) + "\n", "utf-8");
|
|
334
|
+
},
|
|
335
|
+
{ onLocked: "skip" },
|
|
336
|
+
);
|
|
318
337
|
} catch (auditErr) {
|
|
319
338
|
// Best-effort — never let audit write failures bubble up
|
|
320
339
|
_writeStderr(`[gsd:audit] failed to persist log entry: ${(auditErr as Error).message}\n`);
|
|
@@ -37,7 +37,18 @@ export type McpHttpAuthConfig = McpHttpAuthHeaders & McpHttpOAuthConfig;
|
|
|
37
37
|
function resolveEnvValue(value: string): string {
|
|
38
38
|
return value.replace(
|
|
39
39
|
/\$\{([^}]+)\}/g,
|
|
40
|
-
(_match, varName) =>
|
|
40
|
+
(_match, varName) => {
|
|
41
|
+
const resolved = process.env[varName];
|
|
42
|
+
if (resolved === undefined || resolved === "") {
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.warn(
|
|
45
|
+
`[mcp-client auth] Environment variable "${varName}" referenced in MCP server config is unset. ` +
|
|
46
|
+
`Requests will go out with a malformed header and the remote server will likely reject them with 401.`,
|
|
47
|
+
);
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
return resolved;
|
|
51
|
+
},
|
|
41
52
|
);
|
|
42
53
|
}
|
|
43
54
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* mcp_call — Call a tool on an MCP server (lazy connect)
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
14
|
+
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
15
15
|
import {
|
|
16
16
|
truncateHead,
|
|
17
17
|
DEFAULT_MAX_BYTES,
|
|
@@ -33,6 +33,7 @@ import type { McpHttpAuthConfig } from "./auth.js";
|
|
|
33
33
|
interface McpServerConfig {
|
|
34
34
|
name: string;
|
|
35
35
|
transport: "stdio" | "http" | "unknown";
|
|
36
|
+
sourcePath: string;
|
|
36
37
|
command?: string;
|
|
37
38
|
args?: string[];
|
|
38
39
|
env?: Record<string, string>;
|
|
@@ -58,8 +59,40 @@ interface ManagedConnection {
|
|
|
58
59
|
// ─── Connection Manager ───────────────────────────────────────────────────────
|
|
59
60
|
|
|
60
61
|
const connections = new Map<string, ManagedConnection>();
|
|
62
|
+
const pendingConnections = new Map<string, Promise<Client>>();
|
|
61
63
|
let configCache: McpServerConfig[] | null = null;
|
|
62
64
|
const toolCache = new Map<string, McpToolSchema[]>();
|
|
65
|
+
const trustedStdioServers = new Set<string>();
|
|
66
|
+
|
|
67
|
+
const CHILD_ENV_ALLOWLIST = new Set([
|
|
68
|
+
"PATH",
|
|
69
|
+
"Path",
|
|
70
|
+
"HOME",
|
|
71
|
+
"USER",
|
|
72
|
+
"USERNAME",
|
|
73
|
+
"USERPROFILE",
|
|
74
|
+
"SHELL",
|
|
75
|
+
"TMPDIR",
|
|
76
|
+
"TEMP",
|
|
77
|
+
"TMP",
|
|
78
|
+
"SystemRoot",
|
|
79
|
+
"WINDIR",
|
|
80
|
+
"APPDATA",
|
|
81
|
+
"LOCALAPPDATA",
|
|
82
|
+
"XDG_CONFIG_HOME",
|
|
83
|
+
"XDG_CACHE_HOME",
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
function stdioTrustKey(config: McpServerConfig): string {
|
|
87
|
+
return JSON.stringify({
|
|
88
|
+
name: config.name,
|
|
89
|
+
sourcePath: config.sourcePath,
|
|
90
|
+
command: config.command,
|
|
91
|
+
args: config.args ?? [],
|
|
92
|
+
cwd: config.cwd,
|
|
93
|
+
env: config.env ?? {},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
63
96
|
|
|
64
97
|
function readConfigs(): McpServerConfig[] {
|
|
65
98
|
if (configCache) return configCache;
|
|
@@ -99,6 +132,7 @@ function readConfigs(): McpServerConfig[] {
|
|
|
99
132
|
servers.push({
|
|
100
133
|
name,
|
|
101
134
|
transport,
|
|
135
|
+
sourcePath: configPath,
|
|
102
136
|
...(hasCommand && {
|
|
103
137
|
command: config.command as string,
|
|
104
138
|
args: Array.isArray(config.args) ? (config.args as string[]) : undefined,
|
|
@@ -121,6 +155,54 @@ function readConfigs(): McpServerConfig[] {
|
|
|
121
155
|
return servers;
|
|
122
156
|
}
|
|
123
157
|
|
|
158
|
+
export function _buildMcpChildEnvForTest(configEnv: Record<string, string> | undefined): Record<string, string> {
|
|
159
|
+
const childEnv: Record<string, string> = {};
|
|
160
|
+
for (const key of CHILD_ENV_ALLOWLIST) {
|
|
161
|
+
const value = process.env[key];
|
|
162
|
+
if (typeof value === "string") childEnv[key] = value;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
...childEnv,
|
|
166
|
+
...(configEnv ? resolveEnv(configEnv) : {}),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function _buildMcpTrustConfirmOptionsForTest(signal?: AbortSignal): { timeout: number; signal?: AbortSignal } {
|
|
171
|
+
return signal ? { timeout: 120_000, signal } : { timeout: 120_000 };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function assertTrustedStdioServer(
|
|
175
|
+
config: McpServerConfig,
|
|
176
|
+
ctx?: ExtensionContext,
|
|
177
|
+
signal?: AbortSignal,
|
|
178
|
+
): Promise<string | undefined> {
|
|
179
|
+
if (config.transport !== "stdio") return undefined;
|
|
180
|
+
const trustKey = stdioTrustKey(config);
|
|
181
|
+
if (trustedStdioServers.has(trustKey)) return undefined;
|
|
182
|
+
|
|
183
|
+
if (!ctx?.hasUI) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`MCP server "${config.name}" is a project-local stdio command from ${config.sourcePath}. ` +
|
|
186
|
+
"Run this from an interactive GSD session and approve the server before use.",
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const commandLine = [config.command, ...(config.args ?? [])].filter(Boolean).join(" ");
|
|
191
|
+
const envKeys = Object.keys(config.env ?? {});
|
|
192
|
+
const envSummary = envKeys.length > 0
|
|
193
|
+
? `\n\nConfigured environment keys: ${envKeys.join(", ")}`
|
|
194
|
+
: "\n\nNo explicit environment keys configured.";
|
|
195
|
+
const approved = await ctx.ui.confirm(
|
|
196
|
+
`Trust MCP server "${config.name}"?`,
|
|
197
|
+
`Project config ${config.sourcePath} wants to start:\n\n${commandLine}${envSummary}\n\nOnly approve MCP servers you trust.`,
|
|
198
|
+
_buildMcpTrustConfirmOptionsForTest(signal),
|
|
199
|
+
);
|
|
200
|
+
if (!approved) {
|
|
201
|
+
throw new Error(`MCP server "${config.name}" was not approved by the user.`);
|
|
202
|
+
}
|
|
203
|
+
return trustKey;
|
|
204
|
+
}
|
|
205
|
+
|
|
124
206
|
function getServerConfig(name: string): McpServerConfig | undefined {
|
|
125
207
|
const trimmed = name.trim();
|
|
126
208
|
return readConfigs().find((s) =>
|
|
@@ -145,7 +227,7 @@ function resolveEnv(env: Record<string, string>): Record<string, string> {
|
|
|
145
227
|
return resolved;
|
|
146
228
|
}
|
|
147
229
|
|
|
148
|
-
async function getOrConnect(name: string, signal?: AbortSignal): Promise<Client> {
|
|
230
|
+
async function getOrConnect(name: string, signal?: AbortSignal, ctx?: ExtensionContext): Promise<Client> {
|
|
149
231
|
const config = getServerConfig(name);
|
|
150
232
|
if (!config) throw new Error(`Unknown MCP server: "${name}". Use mcp_servers to list available servers.`);
|
|
151
233
|
|
|
@@ -154,14 +236,29 @@ async function getOrConnect(name: string, signal?: AbortSignal): Promise<Client>
|
|
|
154
236
|
const existing = connections.get(config.name);
|
|
155
237
|
if (existing) return existing.client;
|
|
156
238
|
|
|
239
|
+
const pending = pendingConnections.get(config.name);
|
|
240
|
+
if (pending) return pending;
|
|
241
|
+
|
|
242
|
+
const connectionPromise = connectServer(config, signal, ctx);
|
|
243
|
+
pendingConnections.set(config.name, connectionPromise);
|
|
244
|
+
try {
|
|
245
|
+
return await connectionPromise;
|
|
246
|
+
} finally {
|
|
247
|
+
pendingConnections.delete(config.name);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async function connectServer(config: McpServerConfig, signal?: AbortSignal, ctx?: ExtensionContext): Promise<Client> {
|
|
157
252
|
const client = new Client({ name: "gsd", version: "1.0.0" });
|
|
158
253
|
let transport: StdioClientTransport | StreamableHTTPClientTransport;
|
|
254
|
+
let approvedTrustKey: string | undefined;
|
|
159
255
|
|
|
160
256
|
if (config.transport === "stdio" && config.command) {
|
|
257
|
+
approvedTrustKey = await assertTrustedStdioServer(config, ctx, signal);
|
|
161
258
|
transport = new StdioClientTransport({
|
|
162
259
|
command: config.command,
|
|
163
260
|
args: config.args,
|
|
164
|
-
env:
|
|
261
|
+
env: _buildMcpChildEnvForTest(config.env),
|
|
165
262
|
cwd: config.cwd,
|
|
166
263
|
stderr: "pipe",
|
|
167
264
|
});
|
|
@@ -179,9 +276,24 @@ async function getOrConnect(name: string, signal?: AbortSignal): Promise<Client>
|
|
|
179
276
|
throw new Error(`Server "${config.name}" has unsupported transport: ${config.transport}`);
|
|
180
277
|
}
|
|
181
278
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
279
|
+
try {
|
|
280
|
+
await client.connect(transport, { signal, timeout: 30000 });
|
|
281
|
+
if (approvedTrustKey) trustedStdioServers.add(approvedTrustKey);
|
|
282
|
+
connections.set(config.name, { client, transport });
|
|
283
|
+
return client;
|
|
284
|
+
} catch (err) {
|
|
285
|
+
try {
|
|
286
|
+
await transport.close();
|
|
287
|
+
} catch {
|
|
288
|
+
// Best-effort cleanup after a failed or aborted connection attempt.
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
await client.close();
|
|
292
|
+
} catch {
|
|
293
|
+
// Best-effort cleanup after a failed or aborted connection attempt.
|
|
294
|
+
}
|
|
295
|
+
throw err;
|
|
296
|
+
}
|
|
185
297
|
}
|
|
186
298
|
|
|
187
299
|
async function closeAll(): Promise<void> {
|
|
@@ -191,9 +303,16 @@ async function closeAll(): Promise<void> {
|
|
|
191
303
|
} catch {
|
|
192
304
|
// Best-effort cleanup
|
|
193
305
|
}
|
|
306
|
+
try {
|
|
307
|
+
await conn.transport.close();
|
|
308
|
+
} catch {
|
|
309
|
+
// Best-effort cleanup
|
|
310
|
+
}
|
|
194
311
|
connections.delete(name);
|
|
195
312
|
});
|
|
196
313
|
await Promise.allSettled(closing);
|
|
314
|
+
pendingConnections.clear();
|
|
315
|
+
trustedStdioServers.clear();
|
|
197
316
|
toolCache.clear();
|
|
198
317
|
}
|
|
199
318
|
|
|
@@ -331,7 +450,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
331
450
|
}),
|
|
332
451
|
}),
|
|
333
452
|
|
|
334
|
-
async execute(_id, params, signal) {
|
|
453
|
+
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
335
454
|
try {
|
|
336
455
|
// Return cached tools if available
|
|
337
456
|
const cached = toolCache.get(params.server);
|
|
@@ -348,7 +467,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
348
467
|
};
|
|
349
468
|
}
|
|
350
469
|
|
|
351
|
-
const client = await getOrConnect(params.server, signal);
|
|
470
|
+
const client = await getOrConnect(params.server, signal, ctx);
|
|
352
471
|
const result = await client.listTools(undefined, { signal, timeout: 30000 });
|
|
353
472
|
const tools: McpToolSchema[] = (result.tools ?? []).map((t) => ({
|
|
354
473
|
name: t.name,
|
|
@@ -423,9 +542,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
423
542
|
),
|
|
424
543
|
}),
|
|
425
544
|
|
|
426
|
-
async execute(_id, params, signal) {
|
|
545
|
+
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
427
546
|
try {
|
|
428
|
-
const client = await getOrConnect(params.server, signal);
|
|
547
|
+
const client = await getOrConnect(params.server, signal, ctx);
|
|
429
548
|
const result = await client.callTool(
|
|
430
549
|
{ name: params.tool, arguments: params.args ?? {} },
|
|
431
550
|
undefined,
|
|
@@ -88,8 +88,8 @@ Then proceed directly to the workflow.
|
|
|
88
88
|
## Skill Structure Quick Reference
|
|
89
89
|
|
|
90
90
|
**Skill directories:**
|
|
91
|
-
- Global: `~/.
|
|
92
|
-
- Project-local: `.
|
|
91
|
+
- Global: `~/.agents/skills/{skill-name}/`
|
|
92
|
+
- Project-local: `.agents/skills/{skill-name}/`
|
|
93
93
|
|
|
94
94
|
**Simple skill (single file):**
|
|
95
95
|
```yaml
|
|
@@ -5,13 +5,13 @@ GSD-specific skill ecosystem details: directory conventions, discovery mechanics
|
|
|
5
5
|
<skill_directories>
|
|
6
6
|
GSD supports two skill directories, checked in order:
|
|
7
7
|
|
|
8
|
-
**User-scope (global):** `~/.
|
|
8
|
+
**User-scope (global):** `~/.agents/skills/`
|
|
9
9
|
- Available in every GSD session regardless of working directory
|
|
10
|
-
- Installed
|
|
10
|
+
- Installed via [skills.sh](https://skills.sh) or manually
|
|
11
11
|
|
|
12
|
-
**Project-scope (local):** `.
|
|
12
|
+
**Project-scope (local):** `.agents/skills/`
|
|
13
13
|
- Available only when GSD runs inside the project directory
|
|
14
|
-
-
|
|
14
|
+
- Committable to version control so team members share the same skill set
|
|
15
15
|
- Ideal for project-specific workflows, deploy scripts, or conventions
|
|
16
16
|
|
|
17
17
|
Skills in both directories follow the same SKILL.md format and router pattern conventions.
|
|
@@ -16,22 +16,22 @@
|
|
|
16
16
|
Enumerate skills from both directories:
|
|
17
17
|
```bash
|
|
18
18
|
echo "=== Global skills ==="
|
|
19
|
-
ls ~/.
|
|
19
|
+
ls ~/.agents/skills/ 2>/dev/null || echo "(none)"
|
|
20
20
|
|
|
21
21
|
echo "=== Project-local skills ==="
|
|
22
|
-
ls .
|
|
22
|
+
ls .agents/skills/ 2>/dev/null || echo "(none)"
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Present as:
|
|
26
26
|
```
|
|
27
27
|
Available skills:
|
|
28
28
|
|
|
29
|
-
Global (~/.
|
|
29
|
+
Global (~/.agents/skills/):
|
|
30
30
|
1. create-skill
|
|
31
31
|
2. manage-stripe
|
|
32
32
|
...
|
|
33
33
|
|
|
34
|
-
Project-local (.
|
|
34
|
+
Project-local (.agents/skills/):
|
|
35
35
|
3. project-deploy
|
|
36
36
|
...
|
|
37
37
|
```
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
**Ask the user:**
|
|
16
16
|
"Should this skill be global or project-local?"
|
|
17
17
|
|
|
18
|
-
1. **Global** (`~/.
|
|
19
|
-
2. **Project-local** (`.
|
|
18
|
+
1. **Global** (`~/.agents/skills/`) — Available in all GSD sessions
|
|
19
|
+
2. **Project-local** (`.agents/skills/`) — Available only in this project
|
|
20
20
|
|
|
21
21
|
## Step 2: Adaptive Requirements Gathering
|
|
22
22
|
|
|
@@ -99,11 +99,11 @@ See references/recommended-structure.md for templates.
|
|
|
99
99
|
## Step 5: Create Directory
|
|
100
100
|
|
|
101
101
|
Use the scope selected in Step 1 to determine the base path:
|
|
102
|
-
- **Global:** `~/.
|
|
103
|
-
- **Project-local:** `.
|
|
102
|
+
- **Global:** `~/.agents/skills/{skill-name}`
|
|
103
|
+
- **Project-local:** `.agents/skills/{skill-name}`
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
|
-
BASE_PATH="{selected-base}/
|
|
106
|
+
BASE_PATH="{selected-base}/skills/{skill-name}"
|
|
107
107
|
mkdir -p $BASE_PATH
|
|
108
108
|
# If complex:
|
|
109
109
|
mkdir -p $BASE_PATH/workflows
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";exports.id=7461,exports.ids=[7461],exports.modules={7461:(a,b,c)=>{c.d(b,{isOnboardingComplete:()=>k,readOnboardingRecord:()=>j});var d=c(3024),e=c(8161),f=c(6760);c(7598),c(1421),process.env.GSD_ENABLE_NATIVE_GSD_PARSER,Symbol("native-unavailable"),c(9134),Object.values({Q3:{id:"Q3",scope:"slice",ownerTurn:"gate-evaluate",question:"How can this be exploited?",guidance:"Identify abuse scenarios: parameter tampering, replay attacks, privilege escalation.\nMap data exposure risks: PII, tokens, secrets accessible through this slice.\nDefine input trust boundaries: untrusted user input reaching DB, API, or filesystem.\nIf none apply, return verdict 'omitted' with rationale explaining why.",promptSection:"Abuse Surface"},Q4:{id:"Q4",scope:"slice",ownerTurn:"gate-evaluate",question:"What existing promises does this break?",guidance:"List which existing requirements (R001, R003, etc.) are touched by this slice.\nIdentify what must be re-tested after shipping.\nFlag decisions that should be revisited given the new scope.\nIf no existing requirements are affected, return verdict 'omitted'.",promptSection:"Broken Promises"},Q5:{id:"Q5",scope:"task",ownerTurn:"execute-task",question:"What breaks when dependencies fail?",guidance:"Enumerate the task's external dependencies (APIs, filesystem, network, subprocesses).\nDescribe the failure path for each: timeout, malformed response, connection loss.\nVerify the implementation handles each failure or explicitly bubbles the error.\nReturn verdict 'omitted' only if the task has no external dependencies.",promptSection:"Failure Modes"},Q6:{id:"Q6",scope:"task",ownerTurn:"execute-task",question:"What is the 10x load breakpoint?",guidance:"Identify the resource that saturates first at 10x the expected load.\nDescribe the protection applied (pool sizing, rate limiting, pagination, caching).\nReturn verdict 'omitted' if the task has no runtime load dimension.",promptSection:"Load Profile"},Q7:{id:"Q7",scope:"task",ownerTurn:"execute-task",question:"What negative tests protect this task?",guidance:"List malformed inputs, error paths, and boundary conditions the tests cover.\nPoint to the specific test files or cases that assert each negative scenario.\nReturn verdict 'omitted' only if the task has no meaningful negative surface.",promptSection:"Negative Tests"},Q8:{id:"Q8",scope:"slice",ownerTurn:"complete-slice",question:"How will ops know this slice is healthy or broken?",guidance:"Describe the health signal (metric, log line, dashboard) that proves the slice works.\nDescribe the failure signal that triggers an alert or paging.\nDocument the recovery procedure and any monitoring gaps.\nReturn verdict 'omitted' only for slices with no runtime behavior at all.",promptSection:"Operational Readiness"},MV01:{id:"MV01",scope:"milestone",ownerTurn:"validate-milestone",question:"Is every success criterion in the milestone roadmap satisfied?",guidance:"Walk the success-criteria checklist from the milestone roadmap.\nFor each criterion, point to the slice / assessment / verification evidence that proves it.\nReturn verdict 'flag' if any criterion is unmet or unverifiable.",promptSection:"Success Criteria Checklist"},MV02:{id:"MV02",scope:"milestone",ownerTurn:"validate-milestone",question:"Does every slice have a SUMMARY.md and a passing assessment?",guidance:"Confirm every slice listed in the roadmap has a SUMMARY.md.\nConfirm each slice has an ASSESSMENT verdict of 'pass' (or justified 'omitted').\nFlag missing artifacts and slices with outstanding follow-ups or known limitations.",promptSection:"Slice Delivery Audit"},MV03:{id:"MV03",scope:"milestone",ownerTurn:"validate-milestone",question:"Do the slices integrate end-to-end?",guidance:"Trace at least one cross-slice flow proving the pieces compose.\nFlag gaps where two slices were built in isolation with no integration evidence.",promptSection:"Cross-Slice Integration"},MV04:{id:"MV04",scope:"milestone",ownerTurn:"validate-milestone",question:"Are all touched requirements covered and still coherent?",guidance:"For each requirement advanced, validated, surfaced, or invalidated across the milestone's slices, confirm the milestone-level evidence matches.\nFlag requirements that slices claim to advance but no artifact proves.",promptSection:"Requirement Coverage"}});let g=process.env.GSD_CODING_AGENT_DIR||(0,f.join)(process.env.GSD_HOME||(0,f.join)((0,e.homedir)(),".gsd"),"agent"),h=(0,f.join)(g,"onboarding.json"),i={version:1,flowVersion:1,completedAt:null,completedSteps:[],skippedSteps:[],lastResumePoint:null};function j(){if(!(0,d.existsSync)(h))return{...i};try{let a=JSON.parse((0,d.readFileSync)(h,"utf-8"));return{version:"number"==typeof a.version?a.version:1,flowVersion:"number"==typeof a.flowVersion?a.flowVersion:0,completedAt:"string"==typeof a.completedAt?a.completedAt:null,completedSteps:Array.isArray(a.completedSteps)?a.completedSteps.filter(a=>"string"==typeof a):[],skippedSteps:Array.isArray(a.skippedSteps)?a.skippedSteps.filter(a=>"string"==typeof a):[],lastResumePoint:"string"==typeof a.lastResumePoint?a.lastResumePoint:null}}catch{return{...i}}}function k(){let a=j();return null!==a.completedAt&&1===a.flowVersion}},9134:(a,b,c)=>{c.d(b,{DZ:()=>e,rs:()=>d});let d="GSD_GIT_ERROR";class e extends Error{constructor(a,b,c){super(b,c),this.name="GSDError",this.code=a}}}};
|