gsd-pi 2.33.1-dev.ee47f1b → 2.34.0-dev.bbb5216
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/bundled-resource-path.d.ts +8 -0
- package/dist/bundled-resource-path.js +14 -0
- package/dist/headless-query.js +6 -6
- package/dist/resources/extensions/gsd/auto/session.js +27 -32
- package/dist/resources/extensions/gsd/auto-dashboard.js +29 -109
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +6 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +52 -81
- package/dist/resources/extensions/gsd/auto-loop.js +956 -0
- package/dist/resources/extensions/gsd/auto-observability.js +4 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +75 -185
- package/dist/resources/extensions/gsd/auto-prompts.js +133 -101
- package/dist/resources/extensions/gsd/auto-recovery.js +59 -97
- package/dist/resources/extensions/gsd/auto-start.js +330 -309
- package/dist/resources/extensions/gsd/auto-supervisor.js +5 -11
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -7
- package/dist/resources/extensions/gsd/auto-timers.js +3 -4
- package/dist/resources/extensions/gsd/auto-verification.js +35 -73
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +167 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +291 -126
- package/dist/resources/extensions/gsd/auto.js +283 -1013
- package/dist/resources/extensions/gsd/captures.js +10 -4
- package/dist/resources/extensions/gsd/dispatch-guard.js +7 -8
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +25 -18
- package/dist/resources/extensions/gsd/doctor-checks.js +3 -4
- package/dist/resources/extensions/gsd/git-service.js +1 -1
- package/dist/resources/extensions/gsd/gsd-db.js +296 -151
- package/dist/resources/extensions/gsd/index.js +92 -228
- package/dist/resources/extensions/gsd/post-unit-hooks.js +13 -13
- package/dist/resources/extensions/gsd/progress-score.js +61 -156
- package/dist/resources/extensions/gsd/quick.js +98 -122
- package/dist/resources/extensions/gsd/session-lock.js +13 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
- package/dist/resources/extensions/gsd/undo.js +43 -48
- package/dist/resources/extensions/gsd/unit-runtime.js +16 -15
- package/dist/resources/extensions/gsd/verification-evidence.js +0 -1
- package/dist/resources/extensions/gsd/verification-gate.js +6 -35
- package/dist/resources/extensions/gsd/worktree-command.js +30 -24
- package/dist/resources/extensions/gsd/worktree-manager.js +2 -3
- package/dist/resources/extensions/gsd/worktree-resolver.js +344 -0
- package/dist/resources/extensions/gsd/worktree.js +7 -44
- package/dist/tool-bootstrap.js +59 -11
- package/dist/worktree-cli.js +7 -7
- package/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +3630 -5483
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +735 -2588
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/src/models.generated.ts +1039 -2892
- package/packages/pi-coding-agent/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto/session.ts +47 -30
- package/src/resources/extensions/gsd/auto-dashboard.ts +28 -131
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +6 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +135 -91
- package/src/resources/extensions/gsd/auto-loop.ts +1665 -0
- package/src/resources/extensions/gsd/auto-observability.ts +4 -2
- package/src/resources/extensions/gsd/auto-post-unit.ts +85 -228
- package/src/resources/extensions/gsd/auto-prompts.ts +138 -109
- package/src/resources/extensions/gsd/auto-recovery.ts +124 -118
- package/src/resources/extensions/gsd/auto-start.ts +440 -354
- package/src/resources/extensions/gsd/auto-supervisor.ts +5 -12
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +8 -8
- package/src/resources/extensions/gsd/auto-timers.ts +3 -4
- package/src/resources/extensions/gsd/auto-verification.ts +76 -90
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +204 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +389 -141
- package/src/resources/extensions/gsd/auto.ts +515 -1199
- package/src/resources/extensions/gsd/captures.ts +10 -4
- package/src/resources/extensions/gsd/dispatch-guard.ts +13 -9
- package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -18
- package/src/resources/extensions/gsd/doctor-checks.ts +3 -4
- package/src/resources/extensions/gsd/git-service.ts +8 -1
- package/src/resources/extensions/gsd/gitignore.ts +4 -2
- package/src/resources/extensions/gsd/gsd-db.ts +375 -180
- package/src/resources/extensions/gsd/index.ts +104 -263
- package/src/resources/extensions/gsd/post-unit-hooks.ts +13 -13
- package/src/resources/extensions/gsd/progress-score.ts +65 -200
- package/src/resources/extensions/gsd/quick.ts +121 -125
- package/src/resources/extensions/gsd/session-lock.ts +11 -0
- package/src/resources/extensions/gsd/templates/preferences.md +1 -0
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +32 -59
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +75 -27
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1458 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +8 -162
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -108
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +1 -3
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -55
- package/src/resources/extensions/gsd/tests/headless-query.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +8 -11
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +4 -6
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/undo.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +24 -26
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +7 -201
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +705 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +57 -106
- package/src/resources/extensions/gsd/tests/worktree.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +43 -132
- package/src/resources/extensions/gsd/types.ts +90 -81
- package/src/resources/extensions/gsd/undo.ts +42 -46
- package/src/resources/extensions/gsd/unit-runtime.ts +14 -18
- package/src/resources/extensions/gsd/verification-evidence.ts +1 -3
- package/src/resources/extensions/gsd/verification-gate.ts +6 -39
- package/src/resources/extensions/gsd/worktree-command.ts +36 -24
- package/src/resources/extensions/gsd/worktree-manager.ts +2 -3
- package/src/resources/extensions/gsd/worktree-resolver.ts +485 -0
- package/src/resources/extensions/gsd/worktree.ts +7 -44
- package/dist/resources/extensions/gsd/auto-constants.js +0 -5
- package/dist/resources/extensions/gsd/auto-idempotency.js +0 -106
- package/dist/resources/extensions/gsd/auto-stuck-detection.js +0 -165
- package/dist/resources/extensions/gsd/mechanical-completion.js +0 -351
- package/src/resources/extensions/gsd/auto-constants.ts +0 -6
- package/src/resources/extensions/gsd/auto-idempotency.ts +0 -151
- package/src/resources/extensions/gsd/auto-stuck-detection.ts +0 -221
- package/src/resources/extensions/gsd/mechanical-completion.ts +0 -430
- package/src/resources/extensions/gsd/tests/auto-dispatch-loop.test.ts +0 -691
- package/src/resources/extensions/gsd/tests/auto-reentrancy-guard.test.ts +0 -127
- package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +0 -123
- package/src/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +0 -126
- package/src/resources/extensions/gsd/tests/loop-regression.test.ts +0 -874
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +0 -356
- package/src/resources/extensions/gsd/tests/progress-score.test.ts +0 -206
- package/src/resources/extensions/gsd/tests/session-lock.test.ts +0 -434
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
formatValidationIssues,
|
|
13
13
|
} from "./observability-validator.js";
|
|
14
14
|
import type { ValidationIssue } from "./observability-validator.js";
|
|
15
|
-
import { parseUnitId } from "./unit-id.js";
|
|
16
15
|
|
|
17
16
|
export async function collectObservabilityWarnings(
|
|
18
17
|
ctx: ExtensionContext,
|
|
@@ -23,7 +22,10 @@ export async function collectObservabilityWarnings(
|
|
|
23
22
|
// Hook units have custom artifacts — skip standard observability checks
|
|
24
23
|
if (unitType.startsWith("hook/")) return [];
|
|
25
24
|
|
|
26
|
-
const
|
|
25
|
+
const parts = unitId.split("/");
|
|
26
|
+
const mid = parts[0];
|
|
27
|
+
const sid = parts[1];
|
|
28
|
+
const tid = parts[2];
|
|
27
29
|
|
|
28
30
|
if (!mid || !sid) return [];
|
|
29
31
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Extracted from handleAgentEnd() in auto.ts.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type { ExtensionContext,
|
|
14
|
+
import type { ExtensionContext, ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
15
15
|
import { deriveState } from "./state.js";
|
|
16
16
|
import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
|
|
17
17
|
import { loadPrompt } from "./prompt-loader.js";
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
resolveSliceFile,
|
|
20
20
|
resolveTaskFile,
|
|
21
21
|
resolveMilestoneFile,
|
|
22
|
-
gsdRoot,
|
|
23
22
|
} from "./paths.js";
|
|
24
23
|
import { invalidateAllCaches } from "./cache.js";
|
|
25
24
|
import { closeoutUnit, type CloseoutOptions } from "./auto-unit-closeout.js";
|
|
@@ -29,30 +28,23 @@ import {
|
|
|
29
28
|
} from "./worktree.js";
|
|
30
29
|
import {
|
|
31
30
|
verifyExpectedArtifact,
|
|
32
|
-
persistCompletedKey,
|
|
33
|
-
removePersistedKey,
|
|
34
31
|
} from "./auto-recovery.js";
|
|
35
32
|
import { writeUnitRuntimeRecord, clearUnitRuntimeRecord } from "./unit-runtime.js";
|
|
36
|
-
import { resolveAutoSupervisorConfig, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
37
33
|
import { runGSDDoctor, rebuildState, summarizeDoctorIssues } from "./doctor.js";
|
|
38
|
-
import { COMPLETION_TRANSITION_CODES } from "./doctor-types.js";
|
|
39
34
|
import { recordHealthSnapshot, checkHealEscalation } from "./doctor-proactive.js";
|
|
35
|
+
import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
|
|
40
36
|
import { resetRewriteCircuitBreaker } from "./auto-dispatch.js";
|
|
41
37
|
import { isDbAvailable } from "./gsd-db.js";
|
|
42
38
|
import { consumeSignal } from "./session-status-io.js";
|
|
43
39
|
import {
|
|
44
40
|
checkPostUnitHooks,
|
|
45
|
-
getActiveHook,
|
|
46
|
-
resetHookState,
|
|
47
41
|
isRetryPending,
|
|
48
42
|
consumeRetryTrigger,
|
|
49
43
|
persistHookState,
|
|
50
44
|
} from "./post-unit-hooks.js";
|
|
51
|
-
import { hasPendingCaptures, loadPendingCaptures
|
|
52
|
-
import { writeLock } from "./crash-recovery.js";
|
|
45
|
+
import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
|
|
53
46
|
import { debugLog } from "./debug-logger.js";
|
|
54
47
|
import type { AutoSession } from "./auto/session.js";
|
|
55
|
-
import type { WidgetStateAccessors, AutoDashboardData } from "./auto-dashboard.js";
|
|
56
48
|
import {
|
|
57
49
|
updateProgressWidget as _updateProgressWidget,
|
|
58
50
|
updateSliceProgressCache,
|
|
@@ -60,32 +52,9 @@ import {
|
|
|
60
52
|
hideFooter,
|
|
61
53
|
} from "./auto-dashboard.js";
|
|
62
54
|
import { join } from "node:path";
|
|
63
|
-
import { STATE_REBUILD_MIN_INTERVAL_MS } from "./auto-constants.js";
|
|
64
|
-
import { parseUnitId } from "./unit-id.js";
|
|
65
55
|
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
* and persist the initial runtime record. Returns `startedAt` for callers
|
|
69
|
-
* that need the timestamp.
|
|
70
|
-
*/
|
|
71
|
-
function dispatchUnit(
|
|
72
|
-
s: AutoSession,
|
|
73
|
-
basePath: string,
|
|
74
|
-
unitType: string,
|
|
75
|
-
unitId: string,
|
|
76
|
-
): number {
|
|
77
|
-
const startedAt = Date.now();
|
|
78
|
-
s.currentUnit = { type: unitType, id: unitId, startedAt };
|
|
79
|
-
writeUnitRuntimeRecord(basePath, unitType, unitId, startedAt, {
|
|
80
|
-
phase: "dispatched",
|
|
81
|
-
wrapupWarningSent: false,
|
|
82
|
-
timeoutAt: null,
|
|
83
|
-
lastProgressAt: startedAt,
|
|
84
|
-
progressCount: 0,
|
|
85
|
-
lastProgressKind: "dispatch",
|
|
86
|
-
});
|
|
87
|
-
return startedAt;
|
|
88
|
-
}
|
|
56
|
+
/** Throttle STATE.md rebuilds — at most once per 30 seconds */
|
|
57
|
+
const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
|
|
89
58
|
|
|
90
59
|
export interface PostUnitContext {
|
|
91
60
|
s: AutoSession;
|
|
@@ -135,7 +104,8 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
135
104
|
let taskContext: TaskCommitContext | undefined;
|
|
136
105
|
|
|
137
106
|
if (s.currentUnit.type === "execute-task") {
|
|
138
|
-
const
|
|
107
|
+
const parts = s.currentUnit.id.split("/");
|
|
108
|
+
const [mid, sid, tid] = parts;
|
|
139
109
|
if (mid && sid && tid) {
|
|
140
110
|
const summaryPath = resolveTaskFile(s.basePath, mid, sid, tid, "SUMMARY");
|
|
141
111
|
if (summaryPath) {
|
|
@@ -167,8 +137,8 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
167
137
|
|
|
168
138
|
// Doctor: fix mechanical bookkeeping
|
|
169
139
|
try {
|
|
170
|
-
const
|
|
171
|
-
const doctorScope =
|
|
140
|
+
const scopeParts = s.currentUnit.id.split("/").slice(0, 2);
|
|
141
|
+
const doctorScope = scopeParts.join("/");
|
|
172
142
|
const sliceTerminalUnits = new Set(["complete-slice", "run-uat"]);
|
|
173
143
|
const effectiveFixLevel = sliceTerminalUnits.has(s.currentUnit.type) ? "all" as const : "task" as const;
|
|
174
144
|
const report = await runGSDDoctor(s.basePath, { fix: true, scope: doctorScope, fixLevel: effectiveFixLevel });
|
|
@@ -176,17 +146,13 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
176
146
|
ctx.ui.notify(`Post-hook: applied ${report.fixesApplied.length} fix(es).`, "info");
|
|
177
147
|
}
|
|
178
148
|
|
|
179
|
-
// Proactive health tracking
|
|
180
|
-
|
|
181
|
-
const issuesForHealth = effectiveFixLevel === "task"
|
|
182
|
-
? report.issues.filter(i => !COMPLETION_TRANSITION_CODES.has(i.code))
|
|
183
|
-
: report.issues;
|
|
184
|
-
const summary = summarizeDoctorIssues(issuesForHealth);
|
|
149
|
+
// Proactive health tracking
|
|
150
|
+
const summary = summarizeDoctorIssues(report.issues);
|
|
185
151
|
recordHealthSnapshot(summary.errors, summary.warnings, report.fixesApplied.length);
|
|
186
152
|
|
|
187
153
|
// Check if we should escalate to LLM-assisted heal
|
|
188
154
|
if (summary.errors > 0) {
|
|
189
|
-
const unresolvedErrors =
|
|
155
|
+
const unresolvedErrors = report.issues
|
|
190
156
|
.filter(i => i.severity === "error" && !i.fixable)
|
|
191
157
|
.map(i => ({ code: i.code, message: i.message, unitId: i.unitId }));
|
|
192
158
|
const escalation = checkHealEscalation(summary.errors, unresolvedErrors);
|
|
@@ -223,17 +189,23 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
223
189
|
}
|
|
224
190
|
}
|
|
225
191
|
|
|
226
|
-
// Prune dead bg-shell processes
|
|
227
|
-
// Without killing live processes between units, dev servers spawned during
|
|
228
|
-
// one task keep ports bound, causing conflicts in subsequent tasks (#1209).
|
|
192
|
+
// Prune dead bg-shell processes
|
|
229
193
|
try {
|
|
230
|
-
const { pruneDeadProcesses
|
|
194
|
+
const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
|
|
231
195
|
pruneDeadProcesses();
|
|
232
|
-
killSessionProcesses();
|
|
233
196
|
} catch {
|
|
234
197
|
// Non-fatal
|
|
235
198
|
}
|
|
236
199
|
|
|
200
|
+
// Sync worktree state back to project root
|
|
201
|
+
if (s.originalBasePath && s.originalBasePath !== s.basePath) {
|
|
202
|
+
try {
|
|
203
|
+
syncStateToProjectRoot(s.basePath, s.originalBasePath, s.currentMilestoneId);
|
|
204
|
+
} catch {
|
|
205
|
+
// Non-fatal
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
237
209
|
// Rewrite-docs completion
|
|
238
210
|
if (s.currentUnit.type === "rewrite-docs") {
|
|
239
211
|
try {
|
|
@@ -286,17 +258,12 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
286
258
|
}
|
|
287
259
|
}
|
|
288
260
|
|
|
289
|
-
// Artifact verification
|
|
261
|
+
// Artifact verification
|
|
290
262
|
let triggerArtifactVerified = false;
|
|
291
263
|
if (!s.currentUnit.type.startsWith("hook/")) {
|
|
292
264
|
try {
|
|
293
265
|
triggerArtifactVerified = verifyExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
294
266
|
if (triggerArtifactVerified) {
|
|
295
|
-
const completionKey = `${s.currentUnit.type}/${s.currentUnit.id}`;
|
|
296
|
-
if (!s.completedKeySet.has(completionKey)) {
|
|
297
|
-
persistCompletedKey(s.basePath, completionKey);
|
|
298
|
-
s.completedKeySet.add(completionKey);
|
|
299
|
-
}
|
|
300
267
|
invalidateAllCaches();
|
|
301
268
|
}
|
|
302
269
|
} catch {
|
|
@@ -324,13 +291,15 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
324
291
|
* Post-verification processing: DB dual-write, post-unit hooks, triage
|
|
325
292
|
* capture dispatch, quick-task dispatch.
|
|
326
293
|
*
|
|
294
|
+
* Sidecar work (hooks, triage, quick-tasks) is enqueued on `s.sidecarQueue`
|
|
295
|
+
* for the main loop to drain via `runUnit()`.
|
|
296
|
+
*
|
|
327
297
|
* Returns:
|
|
328
|
-
* - "
|
|
329
|
-
* - "continue" — proceed to normal dispatchNextUnit
|
|
298
|
+
* - "continue" — proceed to sidecar drain / normal dispatch
|
|
330
299
|
* - "step-wizard" — step mode, show wizard instead
|
|
331
300
|
* - "stopped" — stopAuto was called
|
|
332
301
|
*/
|
|
333
|
-
export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
302
|
+
export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"continue" | "step-wizard" | "stopped"> {
|
|
334
303
|
const { s, ctx, pi, buildSnapshotOpts, lockBase, stopAuto, pauseAuto, updateProgressWidget } = pctx;
|
|
335
304
|
|
|
336
305
|
// ── DB dual-write ──
|
|
@@ -343,45 +312,6 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
343
312
|
}
|
|
344
313
|
}
|
|
345
314
|
|
|
346
|
-
// ── Mechanical completion (ADR-003) ──
|
|
347
|
-
// After task execution, attempt mechanical slice and milestone completion
|
|
348
|
-
// instead of dispatching LLM sessions for complete-slice / validate-milestone.
|
|
349
|
-
if (s.currentUnit?.type === "execute-task" && !s.stepMode) {
|
|
350
|
-
try {
|
|
351
|
-
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
|
|
352
|
-
if (mid && sid) {
|
|
353
|
-
const state = await deriveState(s.basePath);
|
|
354
|
-
if (state.phase === "summarizing" && state.activeSlice?.id === sid) {
|
|
355
|
-
const { mechanicalSliceCompletion } = await import("./mechanical-completion.js");
|
|
356
|
-
const ok = await mechanicalSliceCompletion(s.basePath, mid, sid);
|
|
357
|
-
if (ok) {
|
|
358
|
-
invalidateAllCaches();
|
|
359
|
-
autoCommitCurrentBranch(s.basePath, "mechanical-completion", `${mid}/${sid}`);
|
|
360
|
-
ctx.ui.notify(`Mechanical completion: ${sid} summary + roadmap updated.`, "info");
|
|
361
|
-
|
|
362
|
-
// Re-derive state — check if milestone is now ready for validation
|
|
363
|
-
invalidateAllCaches();
|
|
364
|
-
const postSliceState = await deriveState(s.basePath);
|
|
365
|
-
if (postSliceState.phase === "validating-milestone" || postSliceState.phase === "completing-milestone") {
|
|
366
|
-
const { aggregateMilestoneVerification, generateMilestoneSummary } = await import("./mechanical-completion.js");
|
|
367
|
-
const validation = await aggregateMilestoneVerification(s.basePath, mid);
|
|
368
|
-
if (validation.verdict !== "failed") {
|
|
369
|
-
await generateMilestoneSummary(s.basePath, mid);
|
|
370
|
-
invalidateAllCaches();
|
|
371
|
-
autoCommitCurrentBranch(s.basePath, "mechanical-milestone-completion", mid);
|
|
372
|
-
ctx.ui.notify(`Mechanical completion: ${mid} validation + summary written.`, "info");
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
// If !ok, summarizing phase persists → dispatch rule fires as LLM fallback
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
} catch (err) {
|
|
380
|
-
process.stderr.write(`gsd-mechanical: completion failed: ${(err as Error).message}\n`);
|
|
381
|
-
// Non-fatal — fall through to normal dispatch
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
315
|
// ── Post-unit hooks ──
|
|
386
316
|
if (s.currentUnit && !s.stepMode) {
|
|
387
317
|
const hookUnit = checkPostUnitHooks(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
@@ -389,79 +319,36 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
389
319
|
if (s.currentUnit) {
|
|
390
320
|
await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
391
321
|
}
|
|
392
|
-
dispatchUnit(s, s.basePath, hookUnit.unitType, hookUnit.unitId);
|
|
393
|
-
|
|
394
|
-
const state = await deriveState(s.basePath);
|
|
395
|
-
updateProgressWidget(ctx, hookUnit.unitType, hookUnit.unitId, state);
|
|
396
|
-
const hookState = getActiveHook();
|
|
397
|
-
ctx.ui.notify(
|
|
398
|
-
`Running post-unit hook: ${hookUnit.hookName} (cycle ${hookState?.cycle ?? 1})`,
|
|
399
|
-
"info",
|
|
400
|
-
);
|
|
401
|
-
|
|
402
|
-
// Switch model if the hook specifies one
|
|
403
|
-
if (hookUnit.model) {
|
|
404
|
-
const availableModels = ctx.modelRegistry.getAvailable();
|
|
405
|
-
const match = availableModels.find(m =>
|
|
406
|
-
m.id === hookUnit.model || `${m.provider}/${m.id}` === hookUnit.model,
|
|
407
|
-
);
|
|
408
|
-
if (match) {
|
|
409
|
-
try {
|
|
410
|
-
await pi.setModel(match);
|
|
411
|
-
} catch { /* non-fatal */ }
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const result = await s.cmdCtx!.newSession();
|
|
416
|
-
if (result.cancelled) {
|
|
417
|
-
resetHookState();
|
|
418
|
-
await stopAuto(ctx, pi, "Hook session cancelled");
|
|
419
|
-
return "stopped";
|
|
420
|
-
}
|
|
421
|
-
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
422
|
-
writeLock(lockBase(), hookUnit.unitType, hookUnit.unitId, s.completedUnits.length, sessionFile);
|
|
423
322
|
persistHookState(s.basePath);
|
|
424
323
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
await pauseAuto(ctx, pi);
|
|
443
|
-
}, hookHardTimeoutMs);
|
|
444
|
-
|
|
445
|
-
if (!s.active) return "stopped";
|
|
446
|
-
pi.sendMessage(
|
|
447
|
-
{ customType: "gsd-auto", content: hookUnit.prompt, display: s.verbose },
|
|
448
|
-
{ triggerTurn: true },
|
|
449
|
-
);
|
|
450
|
-
return "dispatched";
|
|
324
|
+
s.sidecarQueue.push({
|
|
325
|
+
kind: "hook",
|
|
326
|
+
unitType: hookUnit.unitType,
|
|
327
|
+
unitId: hookUnit.unitId,
|
|
328
|
+
prompt: hookUnit.prompt,
|
|
329
|
+
model: hookUnit.model,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
debugLog("postUnitPostVerification", {
|
|
333
|
+
phase: "sidecar-enqueue",
|
|
334
|
+
kind: "hook",
|
|
335
|
+
unitType: hookUnit.unitType,
|
|
336
|
+
unitId: hookUnit.unitId,
|
|
337
|
+
hookName: hookUnit.hookName,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
return "continue";
|
|
451
341
|
}
|
|
452
342
|
|
|
453
343
|
// Check if a hook requested a retry of the trigger unit
|
|
454
344
|
if (isRetryPending()) {
|
|
455
345
|
const trigger = consumeRetryTrigger();
|
|
456
346
|
if (trigger) {
|
|
457
|
-
const triggerKey = `${trigger.unitType}/${trigger.unitId}`;
|
|
458
|
-
s.completedKeySet.delete(triggerKey);
|
|
459
|
-
removePersistedKey(s.basePath, triggerKey);
|
|
460
347
|
ctx.ui.notify(
|
|
461
348
|
`Hook requested retry of ${trigger.unitType} ${trigger.unitId}.`,
|
|
462
349
|
"info",
|
|
463
350
|
);
|
|
464
|
-
// Fall through to normal dispatch
|
|
351
|
+
// Fall through to normal dispatch — deriveState will re-derive the unit
|
|
465
352
|
}
|
|
466
353
|
}
|
|
467
354
|
}
|
|
@@ -500,46 +387,31 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
500
387
|
roadmapContext: roadmapContext || "(no active roadmap)",
|
|
501
388
|
});
|
|
502
389
|
|
|
503
|
-
ctx.ui.notify(
|
|
504
|
-
`Triaging ${pending.length} pending capture${pending.length === 1 ? "" : "s"}...`,
|
|
505
|
-
"info",
|
|
506
|
-
);
|
|
507
|
-
|
|
508
390
|
if (s.currentUnit) {
|
|
509
391
|
await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt);
|
|
510
392
|
}
|
|
511
393
|
|
|
512
|
-
const triageUnitType = "triage-captures";
|
|
513
394
|
const triageUnitId = `${mid}/${sid}/triage`;
|
|
514
|
-
|
|
515
|
-
|
|
395
|
+
s.sidecarQueue.push({
|
|
396
|
+
kind: "triage",
|
|
397
|
+
unitType: "triage-captures",
|
|
398
|
+
unitId: triageUnitId,
|
|
399
|
+
prompt,
|
|
400
|
+
});
|
|
516
401
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
s.unitTimeoutHandle = setTimeout(async () => {
|
|
528
|
-
s.unitTimeoutHandle = null;
|
|
529
|
-
if (!s.active) return;
|
|
530
|
-
ctx.ui.notify(
|
|
531
|
-
`Triage unit exceeded timeout. Pausing auto-mode.`,
|
|
532
|
-
"warning",
|
|
533
|
-
);
|
|
534
|
-
await pauseAuto(ctx, pi);
|
|
535
|
-
}, triageTimeoutMs);
|
|
536
|
-
|
|
537
|
-
if (!s.active) return "stopped";
|
|
538
|
-
pi.sendMessage(
|
|
539
|
-
{ customType: "gsd-auto", content: prompt, display: s.verbose },
|
|
540
|
-
{ triggerTurn: true },
|
|
402
|
+
debugLog("postUnitPostVerification", {
|
|
403
|
+
phase: "sidecar-enqueue",
|
|
404
|
+
kind: "triage",
|
|
405
|
+
unitId: triageUnitId,
|
|
406
|
+
pendingCount: pending.length,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
ctx.ui.notify(
|
|
410
|
+
`Triaging ${pending.length} pending capture${pending.length === 1 ? "" : "s"}...`,
|
|
411
|
+
"info",
|
|
541
412
|
);
|
|
542
|
-
|
|
413
|
+
|
|
414
|
+
return "continue";
|
|
543
415
|
}
|
|
544
416
|
}
|
|
545
417
|
}
|
|
@@ -561,49 +433,34 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
561
433
|
const { markCaptureExecuted } = await import("./captures.js");
|
|
562
434
|
const prompt = buildQuickTaskPrompt(capture);
|
|
563
435
|
|
|
564
|
-
ctx.ui.notify(
|
|
565
|
-
`Executing quick-task: ${capture.id} — "${capture.text}"`,
|
|
566
|
-
"info",
|
|
567
|
-
);
|
|
568
|
-
|
|
569
436
|
if (s.currentUnit) {
|
|
570
437
|
await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt);
|
|
571
438
|
}
|
|
572
439
|
|
|
573
|
-
const qtUnitType = "quick-task";
|
|
574
|
-
const qtUnitId = `${s.currentMilestoneId}/${capture.id}`;
|
|
575
|
-
dispatchUnit(s, s.basePath, qtUnitType, qtUnitId);
|
|
576
|
-
const state = await deriveState(s.basePath);
|
|
577
|
-
updateProgressWidget(ctx, qtUnitType, qtUnitId, state);
|
|
578
|
-
|
|
579
|
-
const result = await s.cmdCtx!.newSession();
|
|
580
|
-
if (result.cancelled) {
|
|
581
|
-
await stopAuto(ctx, pi);
|
|
582
|
-
return "stopped";
|
|
583
|
-
}
|
|
584
|
-
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
585
|
-
writeLock(lockBase(), qtUnitType, qtUnitId, s.completedUnits.length, sessionFile);
|
|
586
|
-
|
|
587
440
|
markCaptureExecuted(s.basePath, capture.id);
|
|
588
441
|
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
442
|
+
const qtUnitId = `${s.currentMilestoneId}/${capture.id}`;
|
|
443
|
+
s.sidecarQueue.push({
|
|
444
|
+
kind: "quick-task",
|
|
445
|
+
unitType: "quick-task",
|
|
446
|
+
unitId: qtUnitId,
|
|
447
|
+
prompt,
|
|
448
|
+
captureId: capture.id,
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
debugLog("postUnitPostVerification", {
|
|
452
|
+
phase: "sidecar-enqueue",
|
|
453
|
+
kind: "quick-task",
|
|
454
|
+
unitId: qtUnitId,
|
|
455
|
+
captureId: capture.id,
|
|
456
|
+
});
|
|
600
457
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
{ triggerTurn: true },
|
|
458
|
+
ctx.ui.notify(
|
|
459
|
+
`Executing quick-task: ${capture.id} — "${capture.text}"`,
|
|
460
|
+
"info",
|
|
605
461
|
);
|
|
606
|
-
|
|
462
|
+
|
|
463
|
+
return "continue";
|
|
607
464
|
} catch {
|
|
608
465
|
// Non-fatal — proceed to normal dispatch
|
|
609
466
|
}
|