gsd-pi 2.79.0-dev.ece5fd8ba → 2.80.0
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/loader.js +0 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/contracts.js +1 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +146 -0
- package/dist/resources/extensions/gsd/auto/phases.js +55 -6
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +45 -52
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -0
- package/dist/resources/extensions/gsd/auto.js +159 -2
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -1
- package/dist/resources/extensions/gsd/gsd-db.js +34 -1
- package/dist/resources/extensions/gsd/post-execution-checks.js +25 -6
- package/dist/resources/extensions/shared/interview-ui.js +15 -4
- 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/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +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_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 +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- 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/63.js +3 -3
- 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.js +2 -2
- 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/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-ff639266d978f2a0.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/package.json +2 -2
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto/contracts.ts +87 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -3
- package/src/resources/extensions/gsd/auto/orchestrator.ts +161 -0
- package/src/resources/extensions/gsd/auto/phases.ts +82 -8
- package/src/resources/extensions/gsd/auto/session.ts +11 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +42 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +7 -0
- package/src/resources/extensions/gsd/auto.ts +167 -1
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +14 -1
- package/src/resources/extensions/gsd/gsd-db.ts +35 -1
- package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +31 -6
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +353 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/paused-session-via-db.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +46 -0
- package/src/resources/extensions/shared/interview-ui.ts +18 -5
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +41 -0
- package/dist/web/standalone/.next/static/chunks/app/page-fab3ebb85b006001.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → V-3Ehy4B24f9FCGiLPWIM}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → V-3Ehy4B24f9FCGiLPWIM}/_ssgManifest.js +0 -0
|
@@ -31,7 +31,7 @@ import { selectAndApplyModel, resolveModelId, clearToolBaseline } from "./auto-m
|
|
|
31
31
|
import { resetRoutingHistory, recordOutcome } from "./routing-history.js";
|
|
32
32
|
import { resetHookState, runPreDispatchHooks, restoreHookState, clearPersistedHookState, } from "./post-unit-hooks.js";
|
|
33
33
|
import { runGSDDoctor, rebuildState } from "./doctor.js";
|
|
34
|
-
import { preDispatchHealthGate, resetProactiveHealing, setLevelChangeCallback, } from "./doctor-proactive.js";
|
|
34
|
+
import { preDispatchHealthGate, recordHealthSnapshot, resetProactiveHealing, setLevelChangeCallback, } from "./doctor-proactive.js";
|
|
35
35
|
import { clearSkillSnapshot } from "./skill-discovery.js";
|
|
36
36
|
import { captureAvailableSkills, resetSkillTelemetry, } from "./skill-telemetry.js";
|
|
37
37
|
import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
|
|
@@ -43,7 +43,7 @@ import { isAbsolute, join } from "node:path";
|
|
|
43
43
|
import { pathToFileURL } from "node:url";
|
|
44
44
|
import { readFileSync, existsSync, mkdirSync } from "node:fs";
|
|
45
45
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
46
|
-
import { autoCommitCurrentBranch, captureIntegrationBranch, detectWorktreeName, getCurrentBranch, getMainBranch, setActiveMilestoneId, } from "./worktree.js";
|
|
46
|
+
import { autoCommitCurrentBranch, captureIntegrationBranch, detectWorktreeName, getCurrentBranch, getMainBranch, setActiveMilestoneId, resolveProjectRoot, } from "./worktree.js";
|
|
47
47
|
import { GitServiceImpl } from "./git-service.js";
|
|
48
48
|
import { getPriorSliceCompletionBlocker } from "./dispatch-guard.js";
|
|
49
49
|
import { createAutoWorktree, enterAutoWorktree, enterBranchModeForMilestone, teardownAutoWorktree, isInAutoWorktree, getAutoWorktreePath, mergeMilestoneToMain, autoWorktreeBranch, syncWorktreeStateBack, syncProjectRootToWorktree, checkResourcesStale, escapeStaleWorktree, } from "./auto-worktree.js";
|
|
@@ -82,6 +82,7 @@ import { resolveAgentEnd, resolveAgentEndCancelled, _resetPendingResolve, isSess
|
|
|
82
82
|
import { runAutoLoopWithUok } from "./uok/kernel.js";
|
|
83
83
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
84
84
|
import { validateDirectory } from "./validate-directory.js";
|
|
85
|
+
import { createAutoOrchestrator } from "./auto/orchestrator.js";
|
|
85
86
|
import { WorktreeResolver, } from "./worktree-resolver.js";
|
|
86
87
|
import { reorderForCaching } from "./prompt-ordering.js";
|
|
87
88
|
export { STUB_RECOVERY_THRESHOLD, NEW_SESSION_TIMEOUT_MS, } from "./auto/session.js";
|
|
@@ -904,6 +905,12 @@ export async function stopAuto(ctx, pi, reason) {
|
|
|
904
905
|
// changes the user made between sessions (#4959 / CodeRabbit).
|
|
905
906
|
if (pi)
|
|
906
907
|
clearToolBaseline(pi);
|
|
908
|
+
try {
|
|
909
|
+
await s.orchestration?.stop(reason ?? "stop");
|
|
910
|
+
}
|
|
911
|
+
catch (err) {
|
|
912
|
+
debugLog("stop-orchestration-stop", { error: err instanceof Error ? err.message : String(err) });
|
|
913
|
+
}
|
|
907
914
|
// Reset all session state in one call
|
|
908
915
|
s.reset();
|
|
909
916
|
}
|
|
@@ -953,6 +960,7 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
|
|
|
953
960
|
activeRunDir: s.activeRunDir,
|
|
954
961
|
autoStartTime: s.autoStartTime,
|
|
955
962
|
milestoneLock: s.sessionMilestoneLock ?? undefined,
|
|
963
|
+
pauseReason: _errorContext?.message,
|
|
956
964
|
};
|
|
957
965
|
setRuntimeKv("global", "", PAUSED_SESSION_KV_KEY, pausedMeta);
|
|
958
966
|
}
|
|
@@ -992,6 +1000,12 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
|
|
|
992
1000
|
// Unblock pending unitPromise so autoLoop exits cleanly (#1799)
|
|
993
1001
|
resolveAgentEnd({ messages: [] });
|
|
994
1002
|
_resetPendingResolve();
|
|
1003
|
+
try {
|
|
1004
|
+
await s.orchestration?.stop("pause");
|
|
1005
|
+
}
|
|
1006
|
+
catch (err) {
|
|
1007
|
+
debugLog("pause-orchestration-stop", { error: err instanceof Error ? err.message : String(err) });
|
|
1008
|
+
}
|
|
995
1009
|
s.active = false;
|
|
996
1010
|
s.paused = true;
|
|
997
1011
|
deactivateGSD();
|
|
@@ -1041,6 +1055,132 @@ function buildResolverDeps() {
|
|
|
1041
1055
|
function buildResolver() {
|
|
1042
1056
|
return new WorktreeResolver(s, buildResolverDeps());
|
|
1043
1057
|
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Thin entry glue for the new Auto Orchestration module.
|
|
1060
|
+
*
|
|
1061
|
+
* This intentionally wires only dispatch + error notification today, with
|
|
1062
|
+
* no behavior changes to the existing auto loop. It provides a concrete seam
|
|
1063
|
+
* the next refactor steps can adopt incrementally.
|
|
1064
|
+
*/
|
|
1065
|
+
export function createWiredAutoOrchestrationModule(ctx, _pi, dispatchBasePath, runtimeBasePath = resolveProjectRoot(dispatchBasePath)) {
|
|
1066
|
+
const flowId = `auto-orchestrator-${Date.now()}`;
|
|
1067
|
+
let seq = 0;
|
|
1068
|
+
const deps = {
|
|
1069
|
+
dispatch: {
|
|
1070
|
+
async decideNextUnit() {
|
|
1071
|
+
const state = await deriveState(dispatchBasePath);
|
|
1072
|
+
const active = state.activeMilestone;
|
|
1073
|
+
if (!active)
|
|
1074
|
+
return null;
|
|
1075
|
+
const prefs = loadEffectiveGSDPreferences(dispatchBasePath)?.preferences;
|
|
1076
|
+
const action = await resolveDispatch({
|
|
1077
|
+
basePath: dispatchBasePath,
|
|
1078
|
+
mid: active.id,
|
|
1079
|
+
midTitle: active.title,
|
|
1080
|
+
state,
|
|
1081
|
+
prefs,
|
|
1082
|
+
});
|
|
1083
|
+
if (action.action !== "dispatch")
|
|
1084
|
+
return null;
|
|
1085
|
+
return {
|
|
1086
|
+
unitType: action.unitType,
|
|
1087
|
+
unitId: action.unitId,
|
|
1088
|
+
reason: action.matchedRule ?? "dispatch",
|
|
1089
|
+
preconditions: [],
|
|
1090
|
+
};
|
|
1091
|
+
},
|
|
1092
|
+
},
|
|
1093
|
+
recovery: {
|
|
1094
|
+
async classifyAndRecover(input) {
|
|
1095
|
+
const reason = input.error instanceof Error ? input.error.message : String(input.error ?? "unknown auto error");
|
|
1096
|
+
return { action: "escalate", reason };
|
|
1097
|
+
},
|
|
1098
|
+
},
|
|
1099
|
+
worktree: {
|
|
1100
|
+
async prepareForUnit() { },
|
|
1101
|
+
async syncAfterUnit() { },
|
|
1102
|
+
async cleanupOnStop() { },
|
|
1103
|
+
},
|
|
1104
|
+
health: {
|
|
1105
|
+
async preAdvanceGate() {
|
|
1106
|
+
const gate = await preDispatchHealthGate(dispatchBasePath);
|
|
1107
|
+
return {
|
|
1108
|
+
allow: gate.proceed,
|
|
1109
|
+
reason: gate.reason,
|
|
1110
|
+
};
|
|
1111
|
+
},
|
|
1112
|
+
async postAdvanceRecord(result) {
|
|
1113
|
+
if (result.kind === "error") {
|
|
1114
|
+
recordHealthSnapshot(1, 0, 0, [{
|
|
1115
|
+
code: "orchestration-error",
|
|
1116
|
+
message: result.reason ?? "orchestration error",
|
|
1117
|
+
severity: "error",
|
|
1118
|
+
unitId: "orchestration",
|
|
1119
|
+
}], [], "orchestration");
|
|
1120
|
+
}
|
|
1121
|
+
else if (result.kind === "blocked") {
|
|
1122
|
+
recordHealthSnapshot(0, 1, 0, [{
|
|
1123
|
+
code: "orchestration-blocked",
|
|
1124
|
+
message: result.reason ?? "orchestration blocked",
|
|
1125
|
+
severity: "warning",
|
|
1126
|
+
unitId: "orchestration",
|
|
1127
|
+
}], [], "orchestration");
|
|
1128
|
+
}
|
|
1129
|
+
},
|
|
1130
|
+
},
|
|
1131
|
+
runtime: {
|
|
1132
|
+
async ensureLockOwnership() {
|
|
1133
|
+
const status = getSessionLockStatus(runtimeBasePath);
|
|
1134
|
+
if (!status.valid || status.failureReason === "pid-mismatch") {
|
|
1135
|
+
throw new Error("session lock held by another process");
|
|
1136
|
+
}
|
|
1137
|
+
},
|
|
1138
|
+
async journalTransition(event) {
|
|
1139
|
+
const eventType = event.name === "start"
|
|
1140
|
+
? "iteration-start"
|
|
1141
|
+
: event.name === "resume"
|
|
1142
|
+
? "iteration-start"
|
|
1143
|
+
: event.name === "advance"
|
|
1144
|
+
? "dispatch-match"
|
|
1145
|
+
: event.name === "advance-blocked"
|
|
1146
|
+
? "guard-block"
|
|
1147
|
+
: event.name === "advance-stopped"
|
|
1148
|
+
? "dispatch-stop"
|
|
1149
|
+
: event.name === "advance-error"
|
|
1150
|
+
? "iteration-end"
|
|
1151
|
+
: event.name === "advance-paused" || event.name === "advance-retry"
|
|
1152
|
+
? "guard-block"
|
|
1153
|
+
: event.name === "stop"
|
|
1154
|
+
? "terminal"
|
|
1155
|
+
: "iteration-end";
|
|
1156
|
+
_emitJournalEvent(runtimeBasePath, {
|
|
1157
|
+
ts: new Date().toISOString(),
|
|
1158
|
+
flowId,
|
|
1159
|
+
seq: ++seq,
|
|
1160
|
+
eventType,
|
|
1161
|
+
data: {
|
|
1162
|
+
source: "auto-orchestrator",
|
|
1163
|
+
name: event.name,
|
|
1164
|
+
reason: event.reason,
|
|
1165
|
+
unitType: event.unitType,
|
|
1166
|
+
unitId: event.unitId,
|
|
1167
|
+
},
|
|
1168
|
+
});
|
|
1169
|
+
},
|
|
1170
|
+
},
|
|
1171
|
+
notifications: {
|
|
1172
|
+
async notifyLifecycle(event) {
|
|
1173
|
+
if (event.name === "error") {
|
|
1174
|
+
ctx.ui.notify(event.detail ?? "auto orchestration error", "error");
|
|
1175
|
+
}
|
|
1176
|
+
},
|
|
1177
|
+
},
|
|
1178
|
+
};
|
|
1179
|
+
return createAutoOrchestrator(deps);
|
|
1180
|
+
}
|
|
1181
|
+
function ensureOrchestrationModule(ctx, pi, basePath) {
|
|
1182
|
+
s.orchestration = createWiredAutoOrchestrationModule(ctx, pi, basePath, lockBase());
|
|
1183
|
+
}
|
|
1044
1184
|
/**
|
|
1045
1185
|
* Build the LoopDeps object from auto.ts private scope.
|
|
1046
1186
|
* This bundles all private functions that autoLoop needs without exporting them.
|
|
@@ -1398,6 +1538,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1398
1538
|
// s.basePath may have been updated to a worktree path by enterMilestone.
|
|
1399
1539
|
rebuildScope(s.basePath, s.currentMilestoneId);
|
|
1400
1540
|
}
|
|
1541
|
+
ensureOrchestrationModule(ctx, pi, s.basePath || base);
|
|
1401
1542
|
registerSigtermHandler(lockBase());
|
|
1402
1543
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
1403
1544
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
@@ -1457,6 +1598,12 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1457
1598
|
clearPausedSession("paused-session DB cleanup failed (resume activation)");
|
|
1458
1599
|
}
|
|
1459
1600
|
pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", level: "progress" });
|
|
1601
|
+
try {
|
|
1602
|
+
await s.orchestration?.resume();
|
|
1603
|
+
}
|
|
1604
|
+
catch (err) {
|
|
1605
|
+
debugLog("resume-orchestration-resume", { error: err instanceof Error ? err.message : String(err) });
|
|
1606
|
+
}
|
|
1460
1607
|
startAutoCommandPolling(s.basePath);
|
|
1461
1608
|
await runAutoLoopWithUok({
|
|
1462
1609
|
ctx,
|
|
@@ -1482,6 +1629,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1482
1629
|
// Build scope after bootstrap has populated s.basePath / s.originalBasePath /
|
|
1483
1630
|
// s.currentMilestoneId (including worktree setup inside bootstrapAutoSession).
|
|
1484
1631
|
rebuildScope(s.basePath, s.currentMilestoneId);
|
|
1632
|
+
ensureOrchestrationModule(ctx, pi, s.basePath || base);
|
|
1485
1633
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1486
1634
|
registerAutoWorkerForSession(s);
|
|
1487
1635
|
try {
|
|
@@ -1492,6 +1640,12 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1492
1640
|
logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1493
1641
|
}
|
|
1494
1642
|
pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: requestedStepMode ? "Step-mode started." : "Auto-mode started.", level: "progress" });
|
|
1643
|
+
try {
|
|
1644
|
+
await s.orchestration?.start({ basePath: s.basePath, trigger: "auto-loop" });
|
|
1645
|
+
}
|
|
1646
|
+
catch (err) {
|
|
1647
|
+
debugLog("start-orchestration-start", { error: err instanceof Error ? err.message : String(err) });
|
|
1648
|
+
}
|
|
1495
1649
|
startAutoCommandPolling(s.basePath);
|
|
1496
1650
|
// Dispatch the first unit
|
|
1497
1651
|
await runAutoLoopWithUok({
|
|
@@ -1576,6 +1730,9 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
|
|
|
1576
1730
|
s.pendingQuickTasks = [];
|
|
1577
1731
|
}
|
|
1578
1732
|
s.basePath = targetBasePath;
|
|
1733
|
+
if (!s.orchestration) {
|
|
1734
|
+
ensureOrchestrationModule(ctx, pi, s.basePath);
|
|
1735
|
+
}
|
|
1579
1736
|
const hookUnitType = `hook/${hookName}`;
|
|
1580
1737
|
const hookStartedAt = Date.now();
|
|
1581
1738
|
s.currentUnit = {
|
|
@@ -39,6 +39,14 @@ function resolveAgentEndBasePath() {
|
|
|
39
39
|
return undefined;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
export function _buildAbortedPauseContext(lastMsg) {
|
|
43
|
+
const hasErrorMessage = Object.prototype.hasOwnProperty.call(lastMsg, "errorMessage") && !!lastMsg.errorMessage;
|
|
44
|
+
return {
|
|
45
|
+
message: hasErrorMessage ? String(lastMsg.errorMessage) : "Operation aborted",
|
|
46
|
+
category: "aborted",
|
|
47
|
+
isTransient: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
42
50
|
async function pauseTransientWithBackoff(cls, pi, ctx, errorDetail, isRateLimit) {
|
|
43
51
|
retryState.consecutiveTransientCount += 1;
|
|
44
52
|
const baseRetryAfterMs = "retryAfterMs" in cls ? cls.retryAfterMs : 15_000;
|
|
@@ -134,7 +142,7 @@ export async function handleAgentEnd(pi, event, ctx) {
|
|
|
134
142
|
}
|
|
135
143
|
return;
|
|
136
144
|
}
|
|
137
|
-
await pauseAuto(ctx, pi);
|
|
145
|
+
await pauseAuto(ctx, pi, _buildAbortedPauseContext(lastMsg));
|
|
138
146
|
return;
|
|
139
147
|
}
|
|
140
148
|
if (lastMsg && "stopReason" in lastMsg && lastMsg.stopReason === "error") {
|
|
@@ -669,6 +669,10 @@ function columnExists(db, table, column) {
|
|
|
669
669
|
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
670
670
|
return rows.some((row) => row["name"] === column);
|
|
671
671
|
}
|
|
672
|
+
function formatFtsUnavailableError(err) {
|
|
673
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
674
|
+
return message.replace(/\bmoduel\s*:\s*/gi, "module: ");
|
|
675
|
+
}
|
|
672
676
|
/**
|
|
673
677
|
* Create the FTS5 virtual table for memories plus the triggers that keep it
|
|
674
678
|
* in sync with the base table. FTS5 may be unavailable on stripped-down
|
|
@@ -704,7 +708,7 @@ export function tryCreateMemoriesFts(db) {
|
|
|
704
708
|
return true;
|
|
705
709
|
}
|
|
706
710
|
catch (err) {
|
|
707
|
-
logWarning("db", `FTS5 unavailable — memory queries will use LIKE fallback: ${err
|
|
711
|
+
logWarning("db", `FTS5 unavailable — memory queries will use LIKE fallback: ${formatFtsUnavailableError(err)}`);
|
|
708
712
|
return false;
|
|
709
713
|
}
|
|
710
714
|
}
|
|
@@ -1653,6 +1657,35 @@ export function closeDatabase() {
|
|
|
1653
1657
|
_lastDbError = null;
|
|
1654
1658
|
_lastDbPhase = null;
|
|
1655
1659
|
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Re-open the active database connection from disk.
|
|
1662
|
+
*
|
|
1663
|
+
* Auto-mode can observe artifacts written by a workflow server running in a
|
|
1664
|
+
* different process before its long-lived singleton has re-synchronized. The
|
|
1665
|
+
* recovery path uses this to force the next state derivation to read from the
|
|
1666
|
+
* current on-disk database instead of continuing with a possibly stale handle.
|
|
1667
|
+
*/
|
|
1668
|
+
export function refreshOpenDatabaseFromDisk() {
|
|
1669
|
+
if (!currentDb || !currentPath)
|
|
1670
|
+
return false;
|
|
1671
|
+
if (currentPath === ":memory:")
|
|
1672
|
+
return false;
|
|
1673
|
+
const dbPath = currentPath;
|
|
1674
|
+
const identityKey = _currentIdentityKey;
|
|
1675
|
+
try {
|
|
1676
|
+
closeDatabase();
|
|
1677
|
+
const opened = openDatabase(dbPath);
|
|
1678
|
+
if (opened && identityKey && currentDb) {
|
|
1679
|
+
_dbCache.set(identityKey, { dbPath, db: currentDb });
|
|
1680
|
+
_currentIdentityKey = identityKey;
|
|
1681
|
+
}
|
|
1682
|
+
return opened;
|
|
1683
|
+
}
|
|
1684
|
+
catch (e) {
|
|
1685
|
+
logWarning("db", `database refresh failed: ${e.message}`);
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1656
1689
|
/** Run a full VACUUM — call sparingly (e.g. after milestone completion). */
|
|
1657
1690
|
export function vacuumDatabase() {
|
|
1658
1691
|
if (!currentDb)
|
|
@@ -96,12 +96,25 @@ export function resolveImportPath(importPath, sourceFile, basePath) {
|
|
|
96
96
|
if (existsSync(directPath)) {
|
|
97
97
|
return { exists: true, resolvedPath: directPath };
|
|
98
98
|
}
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
// Known concrete extensions that should NOT fall through to code-shadow
|
|
100
|
+
// probing when missing. This preserves the "missing.css must stay missing"
|
|
101
|
+
// guarantee while still allowing dotted module stems like ./route.server
|
|
102
|
+
// to resolve as ./route.server.ts.
|
|
103
|
+
const nonFallbackExtensions = new Set([
|
|
104
|
+
".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
|
|
105
|
+
".json", ".css", ".scss", ".sass", ".less", ".styl",
|
|
106
|
+
".svg", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".ico", ".bmp",
|
|
107
|
+
".woff", ".woff2", ".ttf", ".otf", ".eot",
|
|
108
|
+
]);
|
|
109
|
+
const runtimeFallbackExtensions = new Set([".js", ".jsx", ".mjs", ".cjs"]);
|
|
110
|
+
const dottedStemFallbackExtensions = new Set([".server", ".client", ".webhook"]);
|
|
111
|
+
if (explicitExt !== "" &&
|
|
112
|
+
!runtimeFallbackExtensions.has(explicitExt) &&
|
|
113
|
+
!nonFallbackExtensions.has(explicitExt) &&
|
|
114
|
+
!dottedStemFallbackExtensions.has(explicitExt)) {
|
|
115
|
+
return { exists: false, resolvedPath: null };
|
|
116
|
+
}
|
|
117
|
+
if (nonFallbackExtensions.has(explicitExt) && !runtimeFallbackExtensions.has(explicitExt)) {
|
|
105
118
|
return { exists: false, resolvedPath: null };
|
|
106
119
|
}
|
|
107
120
|
}
|
|
@@ -163,6 +176,12 @@ export function checkImportResolution(taskRow, _priorTasks, basePath) {
|
|
|
163
176
|
}
|
|
164
177
|
const imports = extractRelativeImports(source);
|
|
165
178
|
for (const { importPath, lineNum } of imports) {
|
|
179
|
+
// React Router generated +types modules may not exist on disk during
|
|
180
|
+
// post-exec checks (generated during framework build). Don't block task
|
|
181
|
+
// completion on these imports.
|
|
182
|
+
if (/^\.{1,2}\/\+types\//.test(importPath)) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
166
185
|
const resolution = resolveImportPath(importPath, file, basePath);
|
|
167
186
|
if (!resolution.exists) {
|
|
168
187
|
results.push({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GSD2 — Shared interview round UI widget
|
|
1
2
|
/**
|
|
2
3
|
* Shared interview round UI widget.
|
|
3
4
|
*
|
|
@@ -128,14 +129,24 @@ export async function showInterviewRound(questions, opts, ctx) {
|
|
|
128
129
|
let showingExitConfirm = false;
|
|
129
130
|
let exitCursor = 0; // 0 = keep going (default), 1 = end interview
|
|
130
131
|
let cachedLines;
|
|
132
|
+
let completed = false;
|
|
133
|
+
let removeAbortListener;
|
|
134
|
+
function finish(result) {
|
|
135
|
+
if (completed)
|
|
136
|
+
return;
|
|
137
|
+
completed = true;
|
|
138
|
+
removeAbortListener?.();
|
|
139
|
+
done(result);
|
|
140
|
+
}
|
|
131
141
|
// External cancellation (e.g. remote channel won the race)
|
|
132
142
|
if (opts.signal) {
|
|
133
|
-
const onAbort = () =>
|
|
143
|
+
const onAbort = () => finish({ endInterview: false, answers: {} });
|
|
134
144
|
if (opts.signal.aborted) {
|
|
135
145
|
onAbort();
|
|
136
146
|
}
|
|
137
147
|
else {
|
|
138
148
|
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
149
|
+
removeAbortListener = () => opts.signal?.removeEventListener("abort", onAbort);
|
|
139
150
|
}
|
|
140
151
|
}
|
|
141
152
|
// Editor is created once; editorTheme comes from the design system
|
|
@@ -212,7 +223,7 @@ export async function showInterviewRound(questions, opts, ctx) {
|
|
|
212
223
|
}
|
|
213
224
|
function submit() {
|
|
214
225
|
saveEditorToState();
|
|
215
|
-
|
|
226
|
+
finish(buildResult());
|
|
216
227
|
}
|
|
217
228
|
function goNextOrSubmit() {
|
|
218
229
|
if (!isMultiSelect(currentIdx)) {
|
|
@@ -267,7 +278,7 @@ export async function showInterviewRound(questions, opts, ctx) {
|
|
|
267
278
|
return;
|
|
268
279
|
}
|
|
269
280
|
if (data === "2") {
|
|
270
|
-
|
|
281
|
+
finish({ endInterview: false, answers: {} });
|
|
271
282
|
return;
|
|
272
283
|
}
|
|
273
284
|
if (matchesKey(data, Key.enter) || matchesKey(data, Key.space)) {
|
|
@@ -276,7 +287,7 @@ export async function showInterviewRound(questions, opts, ctx) {
|
|
|
276
287
|
refresh();
|
|
277
288
|
}
|
|
278
289
|
else {
|
|
279
|
-
|
|
290
|
+
finish({ endInterview: false, answers: {} });
|
|
280
291
|
}
|
|
281
292
|
return;
|
|
282
293
|
}
|