gsd-pi 2.82.0-dev.725028083 → 2.82.0-dev.9d5798940
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 +3 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +3 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +113 -6
- package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +232 -126
- package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
- package/dist/resources/extensions/gsd/auto-start.js +7 -3
- package/dist/resources/extensions/gsd/auto-verification.js +28 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +96 -0
- package/dist/resources/extensions/gsd/auto.js +128 -52
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +4 -1
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +16 -7
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +37 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +2 -2
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +8 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +49 -9
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
- package/dist/resources/extensions/visual-brief/prompts.js +140 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
- 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.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +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 +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- 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 +4 -5
- 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 +2 -5
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -7
- 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 +4 -7
- 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 +4 -5
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +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 +15 -15
- package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
- 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/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +3 -3
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/mcp-server/README.md +13 -4
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +22 -0
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/src/resources/GSD-WORKFLOW.md +3 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
- package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
- package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
- package/src/resources/extensions/gsd/auto-post-unit.ts +265 -138
- package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
- package/src/resources/extensions/gsd/auto-start.ts +7 -3
- package/src/resources/extensions/gsd/auto-verification.ts +36 -34
- package/src/resources/extensions/gsd/auto-worktree.ts +104 -0
- package/src/resources/extensions/gsd/auto.ts +136 -51
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +16 -6
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +40 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +3 -3
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +8 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +57 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +47 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +54 -9
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
- package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
- package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → BdZQhe8yKl6bdKLiXVEzh}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → BdZQhe8yKl6bdKLiXVEzh}/_ssgManifest.js +0 -0
|
@@ -19,6 +19,7 @@ import { deleteMilestone, getMilestone, isDbAvailable, updateMilestoneStatus } f
|
|
|
19
19
|
import { removeWorktree } from "./worktree-manager.js";
|
|
20
20
|
import { logWarning } from "./workflow-logger.js";
|
|
21
21
|
import { isAutoActive } from "./auto.js";
|
|
22
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
22
23
|
/**
|
|
23
24
|
* Writer-side assert for mutations that race with auto-mode's squash merge (#4704).
|
|
24
25
|
* Auto-mode is confirmed not to call parkMilestone/discardMilestone/unparkMilestone
|
|
@@ -34,7 +35,7 @@ function assertNotAutoActive(action) {
|
|
|
34
35
|
/**
|
|
35
36
|
* Park a milestone — creates a PARKED.md marker file with reason and timestamp.
|
|
36
37
|
* Parked milestones are skipped during active-milestone discovery but stay on disk.
|
|
37
|
-
* Returns true if successfully parked, false if milestone not found
|
|
38
|
+
* Returns true if successfully parked, false if milestone not found, already parked, or complete.
|
|
38
39
|
*/
|
|
39
40
|
export function parkMilestone(basePath, milestoneId, reason) {
|
|
40
41
|
assertNotAutoActive("park milestone");
|
|
@@ -42,9 +43,15 @@ export function parkMilestone(basePath, milestoneId, reason) {
|
|
|
42
43
|
if (!mDir || !existsSync(mDir))
|
|
43
44
|
return false;
|
|
44
45
|
// Guard: do not park a completed milestone — it would corrupt depends_on satisfaction
|
|
45
|
-
const
|
|
46
|
-
|
|
46
|
+
const dbAvailable = isDbAvailable();
|
|
47
|
+
const milestone = dbAvailable ? getMilestone(milestoneId) : null;
|
|
48
|
+
if (milestone && isClosedStatus(milestone.status))
|
|
47
49
|
return false;
|
|
50
|
+
if (!dbAvailable) {
|
|
51
|
+
const summaryFile = resolveMilestoneFile(basePath, milestoneId, "SUMMARY");
|
|
52
|
+
if (summaryFile)
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
48
55
|
const parkedPath = join(mDir, buildMilestoneFileName(milestoneId, "PARKED"));
|
|
49
56
|
if (existsSync(parkedPath))
|
|
50
57
|
return false; // already parked
|
|
@@ -61,7 +68,7 @@ export function parkMilestone(basePath, milestoneId, reason) {
|
|
|
61
68
|
].join("\n");
|
|
62
69
|
writeFileSync(parkedPath, content, "utf-8");
|
|
63
70
|
// Sync DB status so deriveStateFromDb also skips this milestone (#2694)
|
|
64
|
-
if (
|
|
71
|
+
if (dbAvailable) {
|
|
65
72
|
try {
|
|
66
73
|
updateMilestoneStatus(milestoneId, "parked");
|
|
67
74
|
}
|
|
@@ -303,15 +303,20 @@ export function nativeDiffNameStatus(basePath, fromRef, toRef, pathspec, useMerg
|
|
|
303
303
|
}
|
|
304
304
|
/**
|
|
305
305
|
* Get numstat diff between two refs.
|
|
306
|
+
* useMergeBase: if true, uses three-dot semantics.
|
|
306
307
|
* Native: libgit2 patch line stats.
|
|
307
308
|
* Fallback: `git diff --numstat`.
|
|
308
309
|
*/
|
|
309
|
-
export function nativeDiffNumstat(basePath, fromRef, toRef) {
|
|
310
|
+
export function nativeDiffNumstat(basePath, fromRef, toRef, useMergeBase) {
|
|
310
311
|
const native = loadNative();
|
|
311
|
-
if (native) {
|
|
312
|
+
if (native && !useMergeBase) {
|
|
312
313
|
return native.gitDiffNumstat(basePath, fromRef, toRef);
|
|
313
314
|
}
|
|
314
|
-
const
|
|
315
|
+
const refspec = useMergeBase ? `${fromRef}...${toRef}` : undefined;
|
|
316
|
+
const args = refspec
|
|
317
|
+
? ["diff", "--numstat", refspec]
|
|
318
|
+
: ["diff", "--numstat", fromRef, toRef];
|
|
319
|
+
const result = gitExec(basePath, args, true);
|
|
315
320
|
if (!result)
|
|
316
321
|
return [];
|
|
317
322
|
return result.split("\n").filter(Boolean).map(line => {
|
|
@@ -10,6 +10,7 @@ import { isAbsolute, join, resolve } from "node:path";
|
|
|
10
10
|
import { getErrorMessage } from "../../error-utils.js";
|
|
11
11
|
import { nativeAddPaths, nativeCheckoutTheirs, nativeCommit, nativeConflictFiles, nativeMergeAbort, nativeRebaseAbort, nativeResetHard, } from "../../native-git-bridge.js";
|
|
12
12
|
import { logError, logWarning } from "../../workflow-logger.js";
|
|
13
|
+
import { isGsdWorktreePath } from "../../worktree-root.js";
|
|
13
14
|
const SILENT_NOTIFY = () => { };
|
|
14
15
|
function resolveGitDir(basePath) {
|
|
15
16
|
try {
|
|
@@ -23,7 +24,11 @@ function resolveGitDir(basePath) {
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
catch (err) {
|
|
26
|
-
|
|
27
|
+
const message = getErrorMessage(err);
|
|
28
|
+
logWarning("recovery", `gitdir resolution failed: ${message}`);
|
|
29
|
+
if (isGsdWorktreePath(basePath)) {
|
|
30
|
+
throw new Error(`Worktree integrity failure: ${basePath} is not a valid git worktree (git rev-parse failed: ${message.split("\n")[0]}). Repair or recreate the worktree before retrying.`);
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
33
|
return join(basePath, ".git");
|
|
29
34
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clearParseCache } from "../files.js";
|
|
2
2
|
import { isClosedStatus, isDeferredStatus } from "../status-guards.js";
|
|
3
3
|
import { isNonEmptyString } from "../validation.js";
|
|
4
|
-
import { transaction, getMilestone, getSlice, insertTask, upsertSlicePlanning, upsertTaskPlanning, insertGateRow, updateSliceStatus, } from "../gsd-db.js";
|
|
4
|
+
import { transaction, getMilestone, getSlice, insertTask, upsertSlicePlanning, upsertTaskPlanning, insertGateRow, updateSliceStatus, setSliceSketchFlag, } from "../gsd-db.js";
|
|
5
5
|
import { invalidateStateCache } from "../state.js";
|
|
6
6
|
import { renderPlanFromDb } from "../markdown-renderer.js";
|
|
7
7
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
@@ -127,6 +127,7 @@ export async function handlePlanSlice(rawParams, basePath) {
|
|
|
127
127
|
if (isDeferredStatus(parentSlice.status)) {
|
|
128
128
|
updateSliceStatus(params.milestoneId, params.sliceId, "pending");
|
|
129
129
|
}
|
|
130
|
+
setSliceSketchFlag(params.milestoneId, params.sliceId, false);
|
|
130
131
|
upsertSlicePlanning(params.milestoneId, params.sliceId, {
|
|
131
132
|
goal: params.goal,
|
|
132
133
|
successCriteria: params.successCriteria,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Adapts shared GSD workflow handlers for MCP executor calls.
|
|
1
3
|
import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
|
|
2
4
|
import { sanitizeCompleteMilestoneParams } from "../bootstrap/sanitize-complete-milestone.js";
|
|
3
5
|
import { loadWriteGateSnapshot, shouldBlockContextArtifactSaveInSnapshot, shouldBlockRootArtifactSaveInSnapshot } from "../bootstrap/write-gate.js";
|
|
@@ -12,6 +14,9 @@ import { handleCompleteSlice } from "./complete-slice.js";
|
|
|
12
14
|
import { handlePlanMilestone } from "./plan-milestone.js";
|
|
13
15
|
import { handlePlanSlice } from "./plan-slice.js";
|
|
14
16
|
import { handleReplanSlice } from "./replan-slice.js";
|
|
17
|
+
import { handleReopenMilestone } from "./reopen-milestone.js";
|
|
18
|
+
import { handleReopenSlice } from "./reopen-slice.js";
|
|
19
|
+
import { handleReopenTask } from "./reopen-task.js";
|
|
15
20
|
import { handleReassessRoadmap } from "./reassess-roadmap.js";
|
|
16
21
|
import { handleValidateMilestone } from "./validate-milestone.js";
|
|
17
22
|
import { logError, logWarning } from "../workflow-logger.js";
|
|
@@ -274,6 +279,120 @@ export async function executeTaskComplete(params, basePath = process.cwd()) {
|
|
|
274
279
|
};
|
|
275
280
|
}
|
|
276
281
|
}
|
|
282
|
+
export async function executeTaskReopen(params, basePath = process.cwd()) {
|
|
283
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
284
|
+
if (!dbAvailable) {
|
|
285
|
+
return {
|
|
286
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot reopen task." }],
|
|
287
|
+
details: { operation: "reopen_task", error: "db_unavailable" },
|
|
288
|
+
isError: true,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const result = await handleReopenTask(params, basePath);
|
|
293
|
+
if ("error" in result) {
|
|
294
|
+
return {
|
|
295
|
+
content: [{ type: "text", text: `Error reopening task: ${result.error}` }],
|
|
296
|
+
details: { operation: "reopen_task", error: result.error },
|
|
297
|
+
isError: true,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
content: [{ type: "text", text: `Reopened task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
|
|
302
|
+
details: {
|
|
303
|
+
operation: "reopen_task",
|
|
304
|
+
taskId: result.taskId,
|
|
305
|
+
sliceId: result.sliceId,
|
|
306
|
+
milestoneId: result.milestoneId,
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
312
|
+
logError("tool", `reopen_task tool failed: ${msg}`, { tool: "gsd_task_reopen", error: String(err) });
|
|
313
|
+
return {
|
|
314
|
+
content: [{ type: "text", text: `Error reopening task: ${msg}` }],
|
|
315
|
+
details: { operation: "reopen_task", error: msg },
|
|
316
|
+
isError: true,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
export async function executeSliceReopen(params, basePath = process.cwd()) {
|
|
321
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
322
|
+
if (!dbAvailable) {
|
|
323
|
+
return {
|
|
324
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot reopen slice." }],
|
|
325
|
+
details: { operation: "reopen_slice", error: "db_unavailable" },
|
|
326
|
+
isError: true,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
const result = await handleReopenSlice(params, basePath);
|
|
331
|
+
if ("error" in result) {
|
|
332
|
+
return {
|
|
333
|
+
content: [{ type: "text", text: `Error reopening slice: ${result.error}` }],
|
|
334
|
+
details: { operation: "reopen_slice", error: result.error },
|
|
335
|
+
isError: true,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
content: [{ type: "text", text: `Reopened slice ${result.sliceId} (${result.milestoneId})` }],
|
|
340
|
+
details: {
|
|
341
|
+
operation: "reopen_slice",
|
|
342
|
+
sliceId: result.sliceId,
|
|
343
|
+
milestoneId: result.milestoneId,
|
|
344
|
+
tasksReset: result.tasksReset,
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
350
|
+
logError("tool", `reopen_slice tool failed: ${msg}`, { tool: "gsd_slice_reopen", error: String(err) });
|
|
351
|
+
return {
|
|
352
|
+
content: [{ type: "text", text: `Error reopening slice: ${msg}` }],
|
|
353
|
+
details: { operation: "reopen_slice", error: msg },
|
|
354
|
+
isError: true,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
export async function executeMilestoneReopen(params, basePath = process.cwd()) {
|
|
359
|
+
const dbAvailable = await ensureDbOpen(basePath);
|
|
360
|
+
if (!dbAvailable) {
|
|
361
|
+
return {
|
|
362
|
+
content: [{ type: "text", text: "Error: GSD database is not available. Cannot reopen milestone." }],
|
|
363
|
+
details: { operation: "reopen_milestone", error: "db_unavailable" },
|
|
364
|
+
isError: true,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
try {
|
|
368
|
+
const result = await handleReopenMilestone(params, basePath);
|
|
369
|
+
if ("error" in result) {
|
|
370
|
+
return {
|
|
371
|
+
content: [{ type: "text", text: `Error reopening milestone: ${result.error}` }],
|
|
372
|
+
details: { operation: "reopen_milestone", error: result.error },
|
|
373
|
+
isError: true,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
content: [{ type: "text", text: `Reopened milestone ${result.milestoneId}` }],
|
|
378
|
+
details: {
|
|
379
|
+
operation: "reopen_milestone",
|
|
380
|
+
milestoneId: result.milestoneId,
|
|
381
|
+
slicesReset: result.slicesReset,
|
|
382
|
+
tasksReset: result.tasksReset,
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
388
|
+
logError("tool", `reopen_milestone tool failed: ${msg}`, { tool: "gsd_milestone_reopen", error: String(err) });
|
|
389
|
+
return {
|
|
390
|
+
content: [{ type: "text", text: `Error reopening milestone: ${msg}` }],
|
|
391
|
+
details: { operation: "reopen_milestone", error: msg },
|
|
392
|
+
isError: true,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
277
396
|
export async function executeSliceComplete(params, basePath = process.cwd()) {
|
|
278
397
|
const dbAvailable = await ensureDbOpen(basePath);
|
|
279
398
|
if (!dbAvailable) {
|
|
@@ -73,6 +73,7 @@ const COMMON_BUDGET_SMALL = 250_000; // ~65K tokens
|
|
|
73
73
|
// allowed-path set for the docs policy lives in one reviewable place.
|
|
74
74
|
const TOOLS_ALL = { mode: "all" };
|
|
75
75
|
const TOOLS_PLANNING = { mode: "planning" };
|
|
76
|
+
const TOOLS_VERIFICATION = { mode: "verification" };
|
|
76
77
|
// Like TOOLS_PLANNING but permits dispatch to read-only recon/planning
|
|
77
78
|
// specialists. Runtime-enforced by write-gate.ts before the subagent tool runs.
|
|
78
79
|
const TOOLS_PLANNING_DISPATCH_RECON = {
|
|
@@ -187,8 +188,8 @@ export const UNIT_MANIFESTS = {
|
|
|
187
188
|
contextMode: "verification",
|
|
188
189
|
// planning-dispatch: validation is a verification-fan-out unit. It reads
|
|
189
190
|
// the milestone surface and dispatches reviewer/security/tester subagents
|
|
190
|
-
// to report findings without touching user source.
|
|
191
|
-
//
|
|
191
|
+
// to report findings without touching user source. Write isolation to
|
|
192
|
+
// .gsd/ is preserved.
|
|
192
193
|
tools: TOOLS_PLANNING_DISPATCH_REVIEW,
|
|
193
194
|
artifacts: {
|
|
194
195
|
inline: ["roadmap", "slice-summary", "slice-uat", "requirements", "decisions", "templates"],
|
|
@@ -204,11 +205,9 @@ export const UNIT_MANIFESTS = {
|
|
|
204
205
|
codebaseMap: false,
|
|
205
206
|
preferences: "active-only",
|
|
206
207
|
contextMode: "verification",
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
// preserved.
|
|
211
|
-
tools: TOOLS_PLANNING_DISPATCH_REVIEW,
|
|
208
|
+
// Milestone closeout must run unrestricted shell verification commands
|
|
209
|
+
// against the final diff before recording completion.
|
|
210
|
+
tools: TOOLS_ALL,
|
|
212
211
|
artifacts: {
|
|
213
212
|
// #4780 landed slice-summary as excerpt for this unit; phase 2 of
|
|
214
213
|
// the architecture will read this manifest as the source of truth
|
|
@@ -227,7 +226,9 @@ export const UNIT_MANIFESTS = {
|
|
|
227
226
|
codebaseMap: true,
|
|
228
227
|
preferences: "active-only",
|
|
229
228
|
contextMode: "research",
|
|
230
|
-
|
|
229
|
+
// Multi-slice research dispatches use the research-slice unit contract to
|
|
230
|
+
// fan out scout subagents that write .gsd research artifacts.
|
|
231
|
+
tools: TOOLS_PLANNING_DISPATCH_RECON,
|
|
231
232
|
artifacts: {
|
|
232
233
|
inline: ["roadmap", "milestone-research", "dependency-summaries", "templates"],
|
|
233
234
|
excerpt: [],
|
|
@@ -365,7 +366,7 @@ export const UNIT_MANIFESTS = {
|
|
|
365
366
|
codebaseMap: false,
|
|
366
367
|
preferences: "active-only",
|
|
367
368
|
contextMode: "verification",
|
|
368
|
-
tools:
|
|
369
|
+
tools: TOOLS_VERIFICATION,
|
|
369
370
|
artifacts: {
|
|
370
371
|
// Phase 3 migration (#4782): manifest matches today's actual
|
|
371
372
|
// buildRunUatPrompt inlining. Prior phase-1 entry listed
|
|
@@ -384,7 +385,9 @@ export const UNIT_MANIFESTS = {
|
|
|
384
385
|
codebaseMap: false,
|
|
385
386
|
preferences: "active-only",
|
|
386
387
|
contextMode: "verification",
|
|
387
|
-
|
|
388
|
+
// Gate evaluation fans out tester-style subagents, which read the slice
|
|
389
|
+
// plan and report via the DB-backed gate-result tool.
|
|
390
|
+
tools: TOOLS_PLANNING_DISPATCH_REVIEW,
|
|
388
391
|
artifacts: {
|
|
389
392
|
inline: ["slice-plan", "prior-task-summaries"],
|
|
390
393
|
excerpt: [],
|
|
@@ -509,3 +512,22 @@ export const UNIT_MANIFESTS = {
|
|
|
509
512
|
export function resolveManifest(unitType) {
|
|
510
513
|
return UNIT_MANIFESTS[unitType] ?? null;
|
|
511
514
|
}
|
|
515
|
+
export function compileSubagentPermissionContract(policy) {
|
|
516
|
+
if (!policy) {
|
|
517
|
+
return { allowed: false, allowedSubagents: [], toolsMode: "unknown" };
|
|
518
|
+
}
|
|
519
|
+
if (policy.mode === "all") {
|
|
520
|
+
return { allowed: true, allowedSubagents: ["*"], toolsMode: policy.mode };
|
|
521
|
+
}
|
|
522
|
+
if (policy.mode === "planning-dispatch") {
|
|
523
|
+
return {
|
|
524
|
+
allowed: true,
|
|
525
|
+
allowedSubagents: [...policy.allowedSubagents],
|
|
526
|
+
toolsMode: policy.mode,
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return { allowed: false, allowedSubagents: [], toolsMode: policy.mode };
|
|
530
|
+
}
|
|
531
|
+
export function resolveSubagentPermissionContract(unitType) {
|
|
532
|
+
return compileSubagentPermissionContract(resolveManifest(unitType)?.tools);
|
|
533
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Host-owned verification verdict policy for auto-mode units.
|
|
3
|
+
export function decideVerificationVerdict(unitType, result) {
|
|
4
|
+
if (unitType === "execute-task" && result.discoverySource === "none" && result.checks.length === 0) {
|
|
5
|
+
return {
|
|
6
|
+
passed: false,
|
|
7
|
+
reason: "no-host-checks",
|
|
8
|
+
retryable: false,
|
|
9
|
+
failureContext: "No runnable host-owned verification command was discovered. Add project verification_commands or a runnable task-plan Verify command before completing this execute-task.",
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (!result.passed) {
|
|
13
|
+
return {
|
|
14
|
+
passed: false,
|
|
15
|
+
reason: "checks-failed",
|
|
16
|
+
retryable: true,
|
|
17
|
+
failureContext: "",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
passed: true,
|
|
22
|
+
reason: "passed",
|
|
23
|
+
retryable: false,
|
|
24
|
+
failureContext: "",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -48,6 +48,11 @@ import { nativeCheckoutBranch } from "./native-git-bridge.js";
|
|
|
48
48
|
// is the only Module that calls them, and they live alongside the Module's
|
|
49
49
|
// other primitives in `auto-worktree.ts`.
|
|
50
50
|
import { autoWorktreeBranch, createAutoWorktree, enterAutoWorktree, enterBranchModeForMilestone, getAutoWorktreePath, isInAutoWorktree, teardownAutoWorktree, } from "./auto-worktree.js";
|
|
51
|
+
const recentWorktreeMergeFailures = new Map();
|
|
52
|
+
const MERGE_FAILURE_DEDUPE_MS = 60_000;
|
|
53
|
+
export function resetRecentWorktreeMergeFailuresForTest() {
|
|
54
|
+
recentWorktreeMergeFailures.clear();
|
|
55
|
+
}
|
|
51
56
|
/**
|
|
52
57
|
* Internal sentinel — thrown by `_mergeBranchMode` when it has already
|
|
53
58
|
* emitted a user-visible error. The outer `mergeAndExit` catches the type
|
|
@@ -477,6 +482,28 @@ function rebuildGitService(s, deps) {
|
|
|
477
482
|
// GitService cast.
|
|
478
483
|
s.gitService = deps.gitServiceFactory(s.basePath);
|
|
479
484
|
}
|
|
485
|
+
function emitWorktreeMergeFailedOnce(basePath, milestoneId, err) {
|
|
486
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
487
|
+
const errorCategory = err instanceof Error ? err.name : "Error";
|
|
488
|
+
const now = Date.now();
|
|
489
|
+
const key = `${basePath}\0${milestoneId}\0${errorCategory}`;
|
|
490
|
+
const previous = recentWorktreeMergeFailures.get(key);
|
|
491
|
+
if (previous && now - previous < MERGE_FAILURE_DEDUPE_MS)
|
|
492
|
+
return;
|
|
493
|
+
for (const [candidate, ts] of recentWorktreeMergeFailures) {
|
|
494
|
+
if (now - ts >= MERGE_FAILURE_DEDUPE_MS) {
|
|
495
|
+
recentWorktreeMergeFailures.delete(candidate);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
emitJournalEvent(basePath, {
|
|
499
|
+
ts: new Date().toISOString(),
|
|
500
|
+
flowId: randomUUID(),
|
|
501
|
+
seq: 0,
|
|
502
|
+
eventType: "worktree-merge-failed",
|
|
503
|
+
data: { milestoneId, error: msg },
|
|
504
|
+
});
|
|
505
|
+
recentWorktreeMergeFailures.set(key, now);
|
|
506
|
+
}
|
|
480
507
|
// ─── Session-less merge entry (ADR-016 phase 2 / A1) ─────────────────────
|
|
481
508
|
/**
|
|
482
509
|
* Worktree-mode merge body. Session-less — operates on a `MergeContext`.
|
|
@@ -590,13 +617,7 @@ function _mergeWorktreeModeImpl(deps, mctx) {
|
|
|
590
617
|
error: msg,
|
|
591
618
|
fallback: "chdir-to-project-root",
|
|
592
619
|
});
|
|
593
|
-
|
|
594
|
-
ts: new Date().toISOString(),
|
|
595
|
-
flowId: randomUUID(),
|
|
596
|
-
seq: 0,
|
|
597
|
-
eventType: "worktree-merge-failed",
|
|
598
|
-
data: { milestoneId, error: msg },
|
|
599
|
-
});
|
|
620
|
+
emitWorktreeMergeFailedOnce(originalBasePath || worktreeBasePath, milestoneId, err);
|
|
600
621
|
// Surface a clear, actionable error. Worktree and milestone branch
|
|
601
622
|
// are intentionally preserved — nothing has been deleted. User can
|
|
602
623
|
// retry /gsd dispatch complete-milestone or merge manually once the
|
|
@@ -1198,17 +1219,36 @@ export class WorktreeLifecycle {
|
|
|
1198
1219
|
}
|
|
1199
1220
|
}
|
|
1200
1221
|
/**
|
|
1201
|
-
* Restore `s.basePath` to `s.originalBasePath
|
|
1202
|
-
* No-op when `originalBasePath` is empty (fresh
|
|
1222
|
+
* Restore `s.basePath` to `s.originalBasePath`, chdir process cwd, and
|
|
1223
|
+
* rebuild `s.gitService`. No-op when `originalBasePath` is empty (fresh
|
|
1224
|
+
* sessions).
|
|
1203
1225
|
*
|
|
1204
1226
|
* Used by error/cleanup paths that need the session to behave as if the
|
|
1205
1227
|
* worktree was never entered. Does NOT teardown the worktree directory —
|
|
1206
1228
|
* callers that need teardown go through `exitMilestone({ merge: false })`.
|
|
1229
|
+
*
|
|
1230
|
+
* ADR-016 phase 3 (#5693): chdir lives inside the verb so callers do not
|
|
1231
|
+
* pair `restoreToProjectRoot()` with a redundant `process.chdir`. The
|
|
1232
|
+
* chdir runs BEFORE the throwable work (`rebuildGitService`, cache
|
|
1233
|
+
* invalidation) so that cleanup-path cwd is restored even if the
|
|
1234
|
+
* downstream rebuild throws. The chdir itself is best-effort; failure is
|
|
1235
|
+
* logged via debugLog and swallowed.
|
|
1207
1236
|
*/
|
|
1208
1237
|
restoreToProjectRoot() {
|
|
1209
1238
|
if (!this.s.originalBasePath)
|
|
1210
1239
|
return;
|
|
1211
1240
|
this.s.basePath = this.s.originalBasePath;
|
|
1241
|
+
try {
|
|
1242
|
+
process.chdir(this.s.basePath);
|
|
1243
|
+
}
|
|
1244
|
+
catch (err) {
|
|
1245
|
+
debugLog("WorktreeLifecycle", {
|
|
1246
|
+
action: "restoreToProjectRoot",
|
|
1247
|
+
result: "chdir-failed",
|
|
1248
|
+
basePath: this.s.basePath,
|
|
1249
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1212
1252
|
rebuildGitService(this.s, this.deps);
|
|
1213
1253
|
invalidateAllCaches();
|
|
1214
1254
|
}
|