harnery 0.42.0 → 0.44.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/README.md +3 -3
- package/dist/commander.d.ts +16 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +18 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +95 -52
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +38 -11
- package/dist/commands/diagnostics.d.ts.map +1 -1
- package/dist/commands/diagnostics.js +10 -0
- package/dist/commands/doctor.d.ts +12 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +22 -7
- package/dist/commands/governor.js +22 -10
- package/dist/commands/inbox.d.ts +1 -1
- package/dist/commands/inbox.d.ts.map +1 -1
- package/dist/commands/inbox.js +55 -2
- package/dist/commands/rm.d.ts.map +1 -1
- package/dist/commands/rm.js +28 -4
- package/dist/commands/servers.d.ts.map +1 -1
- package/dist/commands/servers.js +16 -1
- package/dist/commands/supervisor.d.ts.map +1 -1
- package/dist/commands/supervisor.js +7 -2
- package/dist/commands/toc.d.ts +14 -0
- package/dist/commands/toc.d.ts.map +1 -1
- package/dist/commands/toc.js +7 -4
- package/dist/commands/tunnel.d.ts +65 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +290 -101
- package/dist/commands/web-fetch.d.ts +3 -2
- package/dist/commands/web-fetch.d.ts.map +1 -1
- package/dist/commands/web-fetch.js +25 -19
- package/dist/commands/web.d.ts +7 -1
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +9 -3
- package/dist/commands/workflow.js +24 -30
- package/dist/core/agents/live-authority-v3.d.ts +1 -0
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +11 -0
- package/dist/core/agents/live-lifecycle-v3.d.ts +4 -2
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
- package/dist/core/agents/live-lifecycle-v3.js +28 -7
- package/dist/core/agents/mailbox.d.ts +9 -8
- package/dist/core/agents/mailbox.d.ts.map +1 -1
- package/dist/core/agents/mailbox.js +24 -17
- package/dist/core/agents/render/prompt-context.d.ts +2 -0
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +19 -17
- package/dist/core/agents/render/session-context.d.ts +2 -8
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +64 -43
- package/dist/core/agents/rules/stop-hook.js +3 -3
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +25 -14
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-writer.js +5 -0
- package/dist/core/agents/state/names.d.ts +43 -3
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +87 -3
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +5 -0
- package/dist/core/agents/state/proc-start.d.ts +19 -0
- package/dist/core/agents/state/proc-start.d.ts.map +1 -1
- package/dist/core/agents/state/proc-start.js +41 -0
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +180 -70
- package/dist/core/agents/state/unchanged-file.d.ts +44 -0
- package/dist/core/agents/state/unchanged-file.d.ts.map +1 -0
- package/dist/core/agents/state/unchanged-file.js +390 -0
- package/dist/core/context/index.d.ts +22 -10
- package/dist/core/context/index.d.ts.map +1 -1
- package/dist/core/context/index.js +381 -119
- package/dist/core/context/observation.d.ts +26 -0
- package/dist/core/context/observation.d.ts.map +1 -0
- package/dist/core/context/observation.js +11 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +25 -14
- package/dist/core/diagnostics/path-identity.d.ts +3 -0
- package/dist/core/diagnostics/path-identity.d.ts.map +1 -0
- package/dist/core/diagnostics/path-identity.js +12 -0
- package/dist/core/diagnostics/sanitize.d.ts.map +1 -1
- package/dist/core/diagnostics/sanitize.js +4 -3
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +29 -0
- package/dist/core/events/v3/generation-custody.d.ts +5 -0
- package/dist/core/events/v3/generation-custody.d.ts.map +1 -0
- package/dist/core/events/v3/generation-custody.js +50 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +1 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +7 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +77 -64
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-reader.js +42 -16
- package/dist/core/governor/planning.d.ts.map +1 -1
- package/dist/core/governor/planning.js +14 -1
- package/dist/core/governor/service-read.d.ts +10 -2
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +105 -22
- package/dist/core/governor/service.d.ts +20 -2
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +72 -47
- package/dist/core/hooks/cli.js +120 -23
- package/dist/core/hooks/fork-lineage.d.ts +40 -0
- package/dist/core/hooks/fork-lineage.d.ts.map +1 -0
- package/dist/core/hooks/fork-lineage.js +62 -0
- package/dist/core/hooks/resolve/transcript.d.ts +16 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +84 -0
- package/dist/core/hooks/shell-rm.d.ts +2 -0
- package/dist/core/hooks/shell-rm.d.ts.map +1 -0
- package/dist/core/hooks/shell-rm.js +105 -0
- package/dist/core/hooks/shell-tokens.d.ts +12 -0
- package/dist/core/hooks/shell-tokens.d.ts.map +1 -0
- package/dist/core/hooks/shell-tokens.js +97 -0
- package/dist/core/hooks/shell-waiter.d.ts.map +1 -1
- package/dist/core/hooks/shell-waiter.js +3 -93
- package/dist/core/inbox/contract.d.ts +2 -1
- package/dist/core/inbox/contract.d.ts.map +1 -1
- package/dist/core/inbox/index.d.ts +2 -0
- package/dist/core/inbox/index.d.ts.map +1 -1
- package/dist/core/inbox/index.js +2 -0
- package/dist/core/inbox/peer-messages.d.ts +37 -0
- package/dist/core/inbox/peer-messages.d.ts.map +1 -0
- package/dist/core/inbox/peer-messages.js +72 -0
- package/dist/core/inbox/service.d.ts +8 -1
- package/dist/core/inbox/service.d.ts.map +1 -1
- package/dist/core/inbox/service.js +67 -21
- package/dist/core/inbox/targets.d.ts +22 -0
- package/dist/core/inbox/targets.d.ts.map +1 -0
- package/dist/core/inbox/targets.js +108 -0
- package/dist/core/inbox/watcher.js +7 -3
- package/dist/core/journal/index.d.ts.map +1 -1
- package/dist/core/journal/index.js +17 -2
- package/dist/core/resources/contract.d.ts +3 -0
- package/dist/core/resources/contract.d.ts.map +1 -1
- package/dist/core/resources/service-status.d.ts +14 -1
- package/dist/core/resources/service-status.d.ts.map +1 -1
- package/dist/core/resources/service-status.js +23 -13
- package/dist/core/resources/service.d.ts +9 -1
- package/dist/core/resources/service.d.ts.map +1 -1
- package/dist/core/resources/service.js +47 -27
- package/dist/core/resources/status.d.ts +2 -5
- package/dist/core/resources/status.d.ts.map +1 -1
- package/dist/core/resources/status.js +36 -7
- package/dist/core/semantic/contract.d.ts +5 -5
- package/dist/core/servers/index.d.ts +24 -13
- package/dist/core/servers/index.d.ts.map +1 -1
- package/dist/core/servers/index.js +132 -92
- package/dist/core/servers/tunnels.d.ts +3 -5
- package/dist/core/servers/tunnels.d.ts.map +1 -1
- package/dist/core/servers/tunnels.js +3 -9
- package/dist/core/storage/process-log.d.ts +12 -0
- package/dist/core/storage/process-log.d.ts.map +1 -1
- package/dist/core/storage/process-log.js +10 -2
- package/dist/core/supervisor/contract.d.ts +12 -0
- package/dist/core/supervisor/contract.d.ts.map +1 -1
- package/dist/core/supervisor/explanations.d.ts.map +1 -1
- package/dist/core/supervisor/explanations.js +2 -1
- package/dist/core/supervisor/findings.d.ts.map +1 -1
- package/dist/core/supervisor/findings.js +54 -9
- package/dist/core/supervisor/service.d.ts +9 -1
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +59 -29
- package/dist/core/supervisor/services.d.ts.map +1 -1
- package/dist/core/supervisor/services.js +22 -1
- package/dist/core/supervisor/status.d.ts +17 -2
- package/dist/core/supervisor/status.d.ts.map +1 -1
- package/dist/core/supervisor/status.js +70 -12
- package/dist/core/supervisor/timeline.d.ts.map +1 -1
- package/dist/core/supervisor/timeline.js +2 -1
- package/dist/core/work/state.js +7 -7
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +105 -32
- package/dist/core/workflow/failure-evidence.d.ts +16 -0
- package/dist/core/workflow/failure-evidence.d.ts.map +1 -0
- package/dist/core/workflow/failure-evidence.js +114 -0
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +1 -1
- package/dist/core/workflow/live-session-v3.d.ts +6 -0
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +126 -5
- package/dist/core/workflow/proof.d.ts +5 -5
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +115 -20
- package/dist/core/workflow/run-state.d.ts +3 -1
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +31 -27
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +19 -0
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +13 -0
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +19 -0
- package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
- package/dist/core/workflow/spawn-opencode.js +14 -0
- package/dist/core/workflow/types.d.ts +64 -17
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/index.d.ts +0 -1
- package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/index.js +0 -1
- package/dist/core/workflow/workspaces/leases.d.ts +3 -1
- package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/leases.js +30 -16
- package/dist/core/workflow/workspaces/local-git.d.ts +6 -2
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +270 -6
- package/dist/core/workflow/workspaces/ownership.d.ts +11 -0
- package/dist/core/workflow/workspaces/ownership.d.ts.map +1 -0
- package/dist/core/workflow/workspaces/ownership.js +194 -0
- package/dist/core/workflow/workspaces/reclaim.d.ts +35 -0
- package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/reclaim.js +14 -0
- package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/recovery.js +21 -13
- package/dist/core/workflow/workspaces/state.d.ts +1 -0
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +21 -1
- package/dist/lib/browser/windows-chrome.d.ts +100 -12
- package/dist/lib/browser/windows-chrome.d.ts.map +1 -1
- package/dist/lib/browser/windows-chrome.js +262 -73
- package/dist/lib/docs-links.d.ts.map +1 -1
- package/dist/lib/docs-links.js +45 -2
- package/dist/lib/guarded-remove.d.ts +7 -0
- package/dist/lib/guarded-remove.d.ts.map +1 -1
- package/dist/lib/guarded-remove.js +106 -12
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +4 -0
- package/dist/lib/tunnel/allowlist.d.ts +44 -0
- package/dist/lib/tunnel/allowlist.d.ts.map +1 -0
- package/dist/lib/tunnel/allowlist.js +204 -0
- package/dist/lib/tunnel/current-address.d.ts +41 -0
- package/dist/lib/tunnel/current-address.d.ts.map +1 -0
- package/dist/lib/tunnel/current-address.js +123 -0
- package/dist/lib/tunnel/gate.js +13 -6
- package/dist/lib/tunnel/processes.d.ts +39 -0
- package/dist/lib/tunnel/processes.d.ts.map +1 -0
- package/dist/lib/tunnel/processes.js +121 -0
- package/dist/lib/tunnel/state.d.ts +28 -3
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +98 -27
- package/dist/lib/zip/index.d.ts +41 -0
- package/dist/lib/zip/index.d.ts.map +1 -0
- package/dist/lib/zip/index.js +398 -0
- package/package.json +8 -1
- package/src/commander.ts +32 -0
- package/src/commands/agents.ts +151 -74
- package/src/commands/browse.ts +50 -14
- package/src/commands/diagnostics.ts +10 -0
- package/src/commands/doctor.ts +26 -7
- package/src/commands/governor.ts +23 -10
- package/src/commands/inbox.ts +52 -2
- package/src/commands/rm.ts +43 -4
- package/src/commands/servers.ts +16 -4
- package/src/commands/supervisor.ts +7 -2
- package/src/commands/toc.ts +14 -6
- package/src/commands/tunnel.ts +394 -116
- package/src/commands/web-fetch.ts +30 -19
- package/src/commands/web.ts +9 -3
- package/src/commands/workflow.ts +30 -30
- package/src/core/agents/live-authority-v3.ts +17 -0
- package/src/core/agents/live-lifecycle-v3.ts +52 -14
- package/src/core/agents/mailbox.ts +26 -17
- package/src/core/agents/render/prompt-context.ts +35 -20
- package/src/core/agents/render/session-context.ts +92 -48
- package/src/core/agents/rules/stop-hook.ts +3 -3
- package/src/core/agents/state/heartbeat-writer.ts +29 -12
- package/src/core/agents/state/live-coordination-writer.ts +29 -0
- package/src/core/agents/state/names.ts +117 -6
- package/src/core/agents/state/pidmap.ts +13 -0
- package/src/core/agents/state/proc-start.ts +57 -0
- package/src/core/agents/state/stale-sweep.ts +247 -82
- package/src/core/agents/state/unchanged-file.ts +456 -0
- package/src/core/context/index.ts +446 -136
- package/src/core/context/observation.ts +29 -0
- package/src/core/diagnostics/bundle.ts +23 -18
- package/src/core/diagnostics/path-identity.ts +15 -0
- package/src/core/diagnostics/sanitize.ts +4 -3
- package/src/core/events/v3/authority-outbox.ts +56 -0
- package/src/core/events/v3/generation-custody.ts +59 -0
- package/src/core/events/v3/producers/coordination-recorder.ts +15 -0
- package/src/core/events/v3/producers/recorder.ts +94 -68
- package/src/core/events/v3/support-storage/pack-reader.ts +45 -19
- package/src/core/governor/planning.ts +20 -8
- package/src/core/governor/service-read.ts +128 -20
- package/src/core/governor/service.ts +119 -42
- package/src/core/hooks/cli.ts +139 -22
- package/src/core/hooks/fork-lineage.ts +82 -0
- package/src/core/hooks/resolve/transcript.ts +88 -0
- package/src/core/hooks/shell-rm.ts +103 -0
- package/src/core/hooks/shell-tokens.ts +96 -0
- package/src/core/hooks/shell-waiter.ts +4 -91
- package/src/core/inbox/contract.ts +2 -1
- package/src/core/inbox/index.ts +2 -0
- package/src/core/inbox/peer-messages.ts +94 -0
- package/src/core/inbox/service.ts +88 -22
- package/src/core/inbox/targets.ts +148 -0
- package/src/core/inbox/watcher.ts +8 -9
- package/src/core/journal/index.ts +19 -2
- package/src/core/resources/contract.ts +4 -0
- package/src/core/resources/service-status.ts +35 -12
- package/src/core/resources/service.ts +71 -24
- package/src/core/resources/status.ts +57 -8
- package/src/core/servers/index.ts +177 -91
- package/src/core/servers/tunnels.ts +3 -11
- package/src/core/storage/process-log.ts +17 -2
- package/src/core/supervisor/contract.ts +13 -0
- package/src/core/supervisor/explanations.ts +4 -1
- package/src/core/supervisor/findings.ts +68 -10
- package/src/core/supervisor/service.ts +88 -26
- package/src/core/supervisor/services.ts +26 -8
- package/src/core/supervisor/status.ts +89 -12
- package/src/core/supervisor/timeline.ts +2 -1
- package/src/core/work/state.ts +7 -7
- package/src/core/workflow/engine.ts +131 -49
- package/src/core/workflow/failure-evidence.ts +141 -0
- package/src/core/workflow/index.ts +0 -1
- package/src/core/workflow/live-session-v3.ts +146 -5
- package/src/core/workflow/proof.ts +134 -26
- package/src/core/workflow/run-state.ts +31 -29
- package/src/core/workflow/spawn-claude.ts +18 -0
- package/src/core/workflow/spawn-codex.ts +13 -0
- package/src/core/workflow/spawn-cursor.ts +18 -0
- package/src/core/workflow/spawn-opencode.ts +14 -0
- package/src/core/workflow/types.ts +51 -17
- package/src/core/workflow/workspaces/index.ts +0 -1
- package/src/core/workflow/workspaces/leases.ts +48 -17
- package/src/core/workflow/workspaces/local-git.ts +315 -5
- package/src/core/workflow/workspaces/ownership.ts +232 -0
- package/src/core/workflow/workspaces/reclaim.ts +58 -0
- package/src/core/workflow/workspaces/recovery.ts +25 -13
- package/src/core/workflow/workspaces/state.ts +20 -0
- package/src/lib/browser/windows-chrome.ts +346 -86
- package/src/lib/docs-links.ts +49 -2
- package/src/lib/guarded-remove.ts +132 -14
- package/src/lib/identities/assume.ts +4 -0
- package/src/lib/tunnel/allowlist.ts +208 -0
- package/src/lib/tunnel/current-address.ts +158 -0
- package/src/lib/tunnel/gate.ts +16 -8
- package/src/lib/tunnel/processes.ts +149 -0
- package/src/lib/tunnel/state.ts +123 -27
- package/src/lib/zip/index.ts +483 -0
|
@@ -1,13 +1,21 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { existsSync, linkSync, readdirSync, readFileSync, renameSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { basename, dirname } from "node:path";
|
|
1
4
|
import { adapterFromPlatform } from "../adapter.js";
|
|
2
|
-
import { recordLiveTaskChangeV3 } from "../agents/live-authority-v3.js";
|
|
5
|
+
import { recordLiveLifecycleChangeV3, recordLiveTaskChangeV3, } from "../agents/live-authority-v3.js";
|
|
3
6
|
import { endSessionExplicitV3 } from "../agents/session-finalizer-v3.js";
|
|
4
|
-
import {
|
|
7
|
+
import { heartbeatPath } from "../agents/state/heartbeat-reader.js";
|
|
8
|
+
import { readHeartbeat, setIdentityCache, } from "../agents/state/heartbeat-writer.js";
|
|
5
9
|
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
|
|
6
10
|
import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.js";
|
|
7
11
|
import { assignName } from "../agents/state/names.js";
|
|
8
12
|
import { coordFreshnessSeconds } from "../config.js";
|
|
9
13
|
import { ensureEventLedgerV3 } from "../events/v3/bootstrap.js";
|
|
10
|
-
import {
|
|
14
|
+
import { readCoordinationViewV3, requireAuthoritySafeCoordinationViewV3, } from "../events/v3/coordination-view.js";
|
|
15
|
+
import { withGenerationCustodyV3 } from "../events/v3/generation-custody.js";
|
|
16
|
+
import { liveInstanceIdV3, recordLiveHookSignalV3, resolveLiveEventLedgerRouteV3, } from "../events/v3/live-routing.js";
|
|
17
|
+
import { readHookProducerStateV3 } from "../events/v3/producers/recorder.js";
|
|
18
|
+
import { fsyncParentDirectory } from "./durable-record.js";
|
|
11
19
|
import { stableScopeId } from "./scope-id.js";
|
|
12
20
|
/** Start a headless workflow child through the same canonical V3 producer as native hooks. */
|
|
13
21
|
export function startWorkflowChildSessionV3(input) {
|
|
@@ -54,13 +62,38 @@ export function startWorkflowChildSessionV3(input) {
|
|
|
54
62
|
const projected = readLiveCoordinationRow(input.coordRoot, input.instanceId);
|
|
55
63
|
if (!projected)
|
|
56
64
|
throw new Error("workflow_child_v3_projection_missing");
|
|
65
|
+
const own = readHookProducerStateV3(input.coordRoot, adapter, sessionId);
|
|
66
|
+
if (!own || own.terminal || own.generation_id !== projected.v3_generation_id) {
|
|
67
|
+
throw new Error("workflow_child_v3_start_generation_changed");
|
|
68
|
+
}
|
|
57
69
|
return projected;
|
|
58
70
|
}
|
|
59
71
|
/** Record the authoritative terminal before removing the disposable coordination cache. */
|
|
60
72
|
export function endWorkflowChildSessionV3(input) {
|
|
73
|
+
withGenerationCustodyV3(input.coordRoot, [liveInstanceIdV3(input.instanceId)], () => endExpectedChild(input));
|
|
74
|
+
}
|
|
75
|
+
function endExpectedChild(input) {
|
|
61
76
|
requireV3Route(input.coordRoot);
|
|
77
|
+
const view = requireAuthoritySafeCoordinationViewV3(readCoordinationViewV3(input.coordRoot));
|
|
78
|
+
const instanceId = liveInstanceIdV3(input.instanceId);
|
|
79
|
+
const current = view.instances[instanceId];
|
|
80
|
+
const terminal = view.terminal_generations[input.expectedGenerationId];
|
|
81
|
+
if (terminal?.instance_id === instanceId)
|
|
82
|
+
recoverHeldCaches(input);
|
|
83
|
+
if (current && current.generation_id !== input.expectedGenerationId) {
|
|
84
|
+
throw new Error("workflow_child_v3_generation_changed");
|
|
85
|
+
}
|
|
86
|
+
if (!current) {
|
|
87
|
+
if (!terminal || terminal.instance_id !== instanceId)
|
|
88
|
+
throw new Error("workflow_child_v3_generation_missing");
|
|
89
|
+
if (terminal.terminal?.outcome !== (input.cleanExit ? "succeeded" : "failed")) {
|
|
90
|
+
throw new Error("workflow_child_v3_terminal_outcome_changed");
|
|
91
|
+
}
|
|
92
|
+
clearExpectedCache(input);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
62
95
|
const row = readLiveCoordinationRow(input.coordRoot, input.instanceId);
|
|
63
|
-
if (!row?.v3_instance_id ||
|
|
96
|
+
if (!row?.v3_instance_id || row.v3_generation_id !== input.expectedGenerationId) {
|
|
64
97
|
throw new Error("workflow_child_v3_generation_missing");
|
|
65
98
|
}
|
|
66
99
|
const result = endSessionExplicitV3({
|
|
@@ -73,7 +106,95 @@ export function endWorkflowChildSessionV3(input) {
|
|
|
73
106
|
if (result.state !== "recorded" && result.state !== "already_ended") {
|
|
74
107
|
throw new Error(`workflow_child_v3_end_failed:${result.state}${"reason" in result ? `:${result.reason}` : ""}`);
|
|
75
108
|
}
|
|
76
|
-
|
|
109
|
+
clearExpectedCache(input);
|
|
110
|
+
}
|
|
111
|
+
/** Persist unresolved terminal custody only for the generation this dispatch owns. */
|
|
112
|
+
export function recordWorkflowChildTerminalFailureV3(input) {
|
|
113
|
+
withGenerationCustodyV3(input.coordRoot, [liveInstanceIdV3(input.instanceId)], () => {
|
|
114
|
+
const row = readLiveCoordinationRow(input.coordRoot, input.instanceId);
|
|
115
|
+
if (!row || row.v3_generation_id !== input.expectedGenerationId)
|
|
116
|
+
return;
|
|
117
|
+
recordLiveLifecycleChangeV3({
|
|
118
|
+
coordRoot: input.coordRoot,
|
|
119
|
+
owner: input.instanceId,
|
|
120
|
+
nativeSessionId: input.sessionId ?? input.instanceId,
|
|
121
|
+
adapter: workflowAdapter(input.adapter),
|
|
122
|
+
expectedGenerationId: input.expectedGenerationId,
|
|
123
|
+
state: "blocked",
|
|
124
|
+
reason: input.reason,
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function heldPrefix(input) {
|
|
129
|
+
if (!/^gen_[a-zA-Z0-9._-]{1,128}$/.test(input.expectedGenerationId))
|
|
130
|
+
throw new Error("workflow_child_v3_generation_invalid");
|
|
131
|
+
return `${basename(heartbeatPath(input.coordRoot, input.instanceId))}.terminal-${input.expectedGenerationId}-`;
|
|
132
|
+
}
|
|
133
|
+
function recoverHeldCaches(input) {
|
|
134
|
+
const path = heartbeatPath(input.coordRoot, input.instanceId);
|
|
135
|
+
if (!existsSync(dirname(path)))
|
|
136
|
+
return;
|
|
137
|
+
const prefix = heldPrefix(input);
|
|
138
|
+
for (const name of readdirSync(dirname(path)).filter((value) => value.startsWith(prefix))) {
|
|
139
|
+
finishHeldCache(`${dirname(path)}/${name}`, path, input.expectedGenerationId);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function clearExpectedCache(input) {
|
|
143
|
+
recoverHeldCaches(input);
|
|
144
|
+
if (readHeartbeat(input.coordRoot, input.instanceId)?.v3_generation_id !==
|
|
145
|
+
input.expectedGenerationId)
|
|
146
|
+
return;
|
|
147
|
+
const path = heartbeatPath(input.coordRoot, input.instanceId);
|
|
148
|
+
const held = `${dirname(path)}/${heldPrefix(input)}${randomUUID()}`;
|
|
149
|
+
try {
|
|
150
|
+
// A unique held name pins the actual bytes atomically. Checking before
|
|
151
|
+
// unlink alone could consume a replacement published at this boundary.
|
|
152
|
+
renameSync(path, held);
|
|
153
|
+
fsyncParentDirectory(path);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (error.code === "ENOENT")
|
|
157
|
+
return;
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
finishHeldCache(held, path, input.expectedGenerationId);
|
|
161
|
+
}
|
|
162
|
+
function finishHeldCache(held, path, expectedGenerationId) {
|
|
163
|
+
let removed = false;
|
|
164
|
+
let cleanupFailed = false;
|
|
165
|
+
let cleanupError;
|
|
166
|
+
try {
|
|
167
|
+
const cache = JSON.parse(readFileSync(held, "utf8"));
|
|
168
|
+
if (cache.v3_generation_id === expectedGenerationId) {
|
|
169
|
+
unlinkSync(held);
|
|
170
|
+
fsyncParentDirectory(held);
|
|
171
|
+
removed = true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
cleanupFailed = true;
|
|
176
|
+
cleanupError = error;
|
|
177
|
+
}
|
|
178
|
+
if (!removed) {
|
|
179
|
+
try {
|
|
180
|
+
// Never overwrite a later publication. Keep the held evidence when
|
|
181
|
+
// another cache already owns the live name.
|
|
182
|
+
linkSync(held, path);
|
|
183
|
+
fsyncParentDirectory(path);
|
|
184
|
+
unlinkSync(held);
|
|
185
|
+
fsyncParentDirectory(held);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
if (error.code !== "EEXIST") {
|
|
189
|
+
if (cleanupFailed) {
|
|
190
|
+
throw new AggregateError([cleanupError, error], `workflow_child_v3_cache_cleanup_and_restore_failed: ${String(cleanupError)}; restoration: ${String(error)}`);
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (cleanupFailed)
|
|
197
|
+
throw cleanupError;
|
|
77
198
|
}
|
|
78
199
|
function requireV3Route(coordRoot) {
|
|
79
200
|
let route = resolveLiveEventLedgerRouteV3(coordRoot);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type RepoSnapshot } from "../context/observation.js";
|
|
2
2
|
import type { NormalizedPolicy, PolicyDecision, PolicyIsolation, PolicyNetworkAccess } from "../policy/index.js";
|
|
3
3
|
import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, AdapterAttestationCitation, AdapterEvidenceCapability, ResultDigest, SpawnFailureClass, WorkflowAgentProof, WorkflowAttemptContext, WorkflowDiagnosticAdmissionProof, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof, WorkflowSandboxProjectionEvidence, WorkflowWorkContext } from "./types.js";
|
|
4
4
|
import type { WorkspaceAttestation, WorkspaceBinding, WorkspaceCompatibilityExecutionEvidence } from "./workspaces/index.js";
|
|
@@ -72,12 +72,12 @@ export declare function digestResult(value: unknown, kind?: "text" | "json"): Re
|
|
|
72
72
|
* attempt was informative about the work — charge it. This also keeps a
|
|
73
73
|
* resumed run whose earlier segment did real work from being written off by
|
|
74
74
|
* a later environment failure.
|
|
75
|
-
* 3.
|
|
76
|
-
*
|
|
77
|
-
* hard stop.
|
|
75
|
+
* 3. Every participant must have failed with positive no-effect evidence,
|
|
76
|
+
* observed absent output and no refusal. A class alone is insufficient.
|
|
77
|
+
* Among those eligible failures, environment is the hard stop.
|
|
78
78
|
* 4. Anything else is undefined ⇒ a charged work failure, exactly as today.
|
|
79
79
|
*/
|
|
80
|
-
export declare function deriveRunFailureClass(status: "succeeded" | "failed", agents: readonly Pick<WorkflowAgentProof, "status" | "class">[]): SpawnFailureClass | undefined;
|
|
80
|
+
export declare function deriveRunFailureClass(status: "succeeded" | "failed", agents: readonly Pick<WorkflowAgentProof, "status" | "class" | "failure_evidence">[]): SpawnFailureClass | undefined;
|
|
81
81
|
export declare function buildWorkflowProof(input: BuildWorkflowProofInput): WorkflowProof;
|
|
82
82
|
export declare function writeWorkflowProof(path: string, proof: WorkflowProof): void;
|
|
83
83
|
export declare function readWorkflowProof(coordRoot: string, runId: string): WorkflowProof;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/proof.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/proof.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { isAbsolute, join } from "node:path";
|
|
4
|
+
import { observationsComparable } from "../context/observation.js";
|
|
4
5
|
import { DIAGNOSTIC_ADVICE_SCHEMA_VERSION } from "../diagnostics/contract.js";
|
|
5
6
|
import { policyDigest } from "../policy/index.js";
|
|
6
7
|
import { isCanonicalWorkflowAttemptContext } from "./attempt-context.js";
|
|
7
8
|
import { stableDigest, writeImmutableJson } from "./durable-record.js";
|
|
9
|
+
import { failureEvidenceAllowsUncharged, isSpawnFailureEvidence } from "./failure-evidence.js";
|
|
8
10
|
import { readWorkflowRunManifest } from "./run-state.js";
|
|
9
11
|
import { EVIDENCE_KINDS, WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION, WORKFLOW_PROOF_SCHEMA_VERSION, } from "./types.js";
|
|
10
12
|
import { isCanonicalWorkflowWorkContext } from "./work-context.js";
|
|
@@ -125,15 +127,18 @@ export function digestResult(value, kind) {
|
|
|
125
127
|
* attempt was informative about the work — charge it. This also keeps a
|
|
126
128
|
* resumed run whose earlier segment did real work from being written off by
|
|
127
129
|
* a later environment failure.
|
|
128
|
-
* 3.
|
|
129
|
-
*
|
|
130
|
-
* hard stop.
|
|
130
|
+
* 3. Every participant must have failed with positive no-effect evidence,
|
|
131
|
+
* observed absent output and no refusal. A class alone is insufficient.
|
|
132
|
+
* Among those eligible failures, environment is the hard stop.
|
|
131
133
|
* 4. Anything else is undefined ⇒ a charged work failure, exactly as today.
|
|
132
134
|
*/
|
|
133
135
|
export function deriveRunFailureClass(status, agents) {
|
|
134
136
|
if (status !== "failed")
|
|
135
137
|
return undefined;
|
|
136
|
-
if (agents.
|
|
138
|
+
if (agents.length === 0 ||
|
|
139
|
+
agents.some((agent) => agent.status !== "failed" ||
|
|
140
|
+
(agent.class !== "environment" && agent.class !== "upstream") ||
|
|
141
|
+
!failureEvidenceAllowsUncharged(agent.failure_evidence))) {
|
|
137
142
|
return undefined;
|
|
138
143
|
}
|
|
139
144
|
const failed = agents.filter((agent) => agent.status === "failed");
|
|
@@ -262,6 +267,10 @@ export function readWorkflowProof(coordRoot, runId) {
|
|
|
262
267
|
proof.run.class !== "environment" &&
|
|
263
268
|
proof.run.class !== "upstream" &&
|
|
264
269
|
proof.run.class !== "decision") ||
|
|
270
|
+
!Array.isArray(proof.agents) ||
|
|
271
|
+
proof.agents.some((agent) => !agent ||
|
|
272
|
+
typeof agent !== "object" ||
|
|
273
|
+
(agent.failure_evidence !== undefined && !isSpawnFailureEvidence(agent.failure_evidence))) ||
|
|
265
274
|
(proof.run.work_context !== undefined &&
|
|
266
275
|
(!proof.run.work_item_id ||
|
|
267
276
|
proof.run.work_context.id !== proof.run.work_item_id ||
|
|
@@ -275,6 +284,20 @@ export function readWorkflowProof(coordRoot, runId) {
|
|
|
275
284
|
!isWorkspaceExecutionEvidence(proof.execution, runId, proof.run.status))) {
|
|
276
285
|
throw new Error(`workflow proof at ${path} has an unsupported or mismatched schema`);
|
|
277
286
|
}
|
|
287
|
+
if (repoComparisonProblem(proof.repository.before, proof.repository.after) !== undefined ||
|
|
288
|
+
proof.repository.before.dirty_paths_truncated ||
|
|
289
|
+
proof.repository.after.dirty_paths_truncated ||
|
|
290
|
+
!proof.repository.before.branch?.trim() ||
|
|
291
|
+
!proof.repository.after.branch?.trim() ||
|
|
292
|
+
!proof.repository.before.head?.trim() ||
|
|
293
|
+
!proof.repository.after.head?.trim()) {
|
|
294
|
+
proof.repository = buildRepoEvidence(proof.repository.before, proof.repository.after);
|
|
295
|
+
proof.unknowns = proof.unknowns.filter((item) => item.code !== "repository_drift_incomplete");
|
|
296
|
+
proof.unknowns.push({
|
|
297
|
+
code: "repository_drift_incomplete",
|
|
298
|
+
message: proof.repository.drift.note,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
278
301
|
const manifestPath = join(coordRoot, ".harnery", "workflows", runId, "run.json");
|
|
279
302
|
if (proof.execution === undefined && !existsSync(manifestPath))
|
|
280
303
|
return proof;
|
|
@@ -369,11 +392,27 @@ export function renderWorkflowProof(proof) {
|
|
|
369
392
|
`${observation.advice.assessment.recommended_action}; action none`
|
|
370
393
|
: "admission: shadow not needed; no real child dispatch");
|
|
371
394
|
}
|
|
372
|
-
const
|
|
395
|
+
const comparable = repoComparisonProblem(proof.repository.before, proof.repository.after) === undefined;
|
|
396
|
+
const repo = comparable &&
|
|
397
|
+
!proof.repository.before.dirty_paths_truncated &&
|
|
398
|
+
!proof.repository.after.dirty_paths_truncated &&
|
|
399
|
+
proof.repository.before.branch?.trim() &&
|
|
400
|
+
proof.repository.after.branch?.trim() &&
|
|
401
|
+
proof.repository.before.head?.trim() &&
|
|
402
|
+
proof.repository.after.head?.trim()
|
|
403
|
+
? proof.repository
|
|
404
|
+
: buildRepoEvidence(proof.repository.before, proof.repository.after);
|
|
373
405
|
const drift = repo.drift;
|
|
374
|
-
|
|
375
|
-
`
|
|
376
|
-
|
|
406
|
+
if (!comparable) {
|
|
407
|
+
lines.push(`repository: drift unknown. ${drift.note}`);
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
const paths = drift.dirty_paths_added === null || drift.dirty_paths_cleared === null
|
|
411
|
+
? "dirty-path drift unknown"
|
|
412
|
+
: `${drift.dirty_paths_added.length} dirty added, ${drift.dirty_paths_cleared.length} cleared`;
|
|
413
|
+
lines.push(`repository: branch ${repo.before.branch ?? "unknown"} -> ${repo.after.branch ?? "unknown"}; ` +
|
|
414
|
+
`HEAD ${short(repo.before.head)} -> ${short(repo.after.head)}; ${paths}`);
|
|
415
|
+
}
|
|
377
416
|
if (proof.unknowns.length > 0) {
|
|
378
417
|
lines.push(`unknowns: ${proof.unknowns.length}`);
|
|
379
418
|
for (const unknown of proof.unknowns)
|
|
@@ -385,37 +424,93 @@ export function renderWorkflowProof(proof) {
|
|
|
385
424
|
function buildRepoEvidence(beforeRaw, afterRaw) {
|
|
386
425
|
const before = normalizeRepoSnapshot(beforeRaw);
|
|
387
426
|
const after = normalizeRepoSnapshot(afterRaw);
|
|
427
|
+
const problem = repoComparisonProblem(before, after);
|
|
428
|
+
if (problem !== undefined) {
|
|
429
|
+
return {
|
|
430
|
+
source: "engine",
|
|
431
|
+
before,
|
|
432
|
+
after,
|
|
433
|
+
drift: {
|
|
434
|
+
branch_changed: null,
|
|
435
|
+
head_changed: null,
|
|
436
|
+
dirty_paths_added: null,
|
|
437
|
+
dirty_paths_cleared: null,
|
|
438
|
+
dirty_paths_retained: null,
|
|
439
|
+
incomplete: true,
|
|
440
|
+
note: `Repository drift could not be verified: ${problem}. Re-check before editing.`,
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
const pathsComparable = !before.dirty_paths_truncated && !after.dirty_paths_truncated;
|
|
445
|
+
const branchKnown = Boolean(before.branch && after.branch);
|
|
446
|
+
const headKnown = Boolean(before.head && after.head);
|
|
388
447
|
const beforeDirty = new Set(before.dirty_paths);
|
|
389
448
|
const afterDirty = new Set(after.dirty_paths);
|
|
390
449
|
const retained = after.dirty_paths.filter((path) => beforeDirty.has(path));
|
|
391
|
-
const
|
|
450
|
+
const notes = [
|
|
451
|
+
...(!pathsComparable
|
|
452
|
+
? ["Dirty-path drift is unknown because a snapshot list was truncated."]
|
|
453
|
+
: []),
|
|
454
|
+
...(!branchKnown ? ["Branch drift is unknown because a snapshot has no branch."] : []),
|
|
455
|
+
...(!headKnown ? ["HEAD drift is unknown because a snapshot has no HEAD."] : []),
|
|
456
|
+
...(pathsComparable && retained.length > 0
|
|
457
|
+
? ["Snapshots cannot prove whether retained dirty paths changed during the run."]
|
|
458
|
+
: []),
|
|
459
|
+
];
|
|
460
|
+
const incomplete = notes.length > 0;
|
|
392
461
|
return {
|
|
393
462
|
source: "engine",
|
|
394
463
|
before,
|
|
395
464
|
after,
|
|
396
465
|
drift: {
|
|
397
|
-
branch_changed: before.branch !== after.branch,
|
|
398
|
-
head_changed: before.head !== after.head,
|
|
399
|
-
dirty_paths_added:
|
|
400
|
-
|
|
401
|
-
|
|
466
|
+
branch_changed: branchKnown ? before.branch !== after.branch : null,
|
|
467
|
+
head_changed: headKnown ? before.head !== after.head : null,
|
|
468
|
+
dirty_paths_added: pathsComparable
|
|
469
|
+
? after.dirty_paths.filter((path) => !beforeDirty.has(path))
|
|
470
|
+
: null,
|
|
471
|
+
dirty_paths_cleared: pathsComparable
|
|
472
|
+
? before.dirty_paths.filter((path) => !afterDirty.has(path))
|
|
473
|
+
: null,
|
|
474
|
+
dirty_paths_retained: pathsComparable ? retained : null,
|
|
402
475
|
incomplete,
|
|
403
|
-
note: incomplete
|
|
404
|
-
? "Snapshots cannot prove whether retained dirty paths changed during the run, and truncated lists may omit paths."
|
|
405
|
-
: undefined,
|
|
476
|
+
note: incomplete ? notes.join(" ") : undefined,
|
|
406
477
|
},
|
|
407
478
|
};
|
|
408
479
|
}
|
|
409
480
|
function normalizeRepoSnapshot(snapshot) {
|
|
410
481
|
return {
|
|
411
482
|
cwd: snapshot.cwd,
|
|
483
|
+
observation: snapshot.observation ?? "unavailable",
|
|
484
|
+
observation_detail: snapshot.observation
|
|
485
|
+
? clippedOptional(snapshot.observation_detail, 500)
|
|
486
|
+
: "No repository observation was recorded.",
|
|
412
487
|
root: snapshot.root,
|
|
413
|
-
branch: snapshot.branch,
|
|
414
|
-
head: snapshot.head,
|
|
488
|
+
branch: snapshot.branch?.trim() || undefined,
|
|
489
|
+
head: snapshot.head?.trim() || undefined,
|
|
415
490
|
dirty_paths: snapshot.dirty_paths,
|
|
416
491
|
dirty_paths_truncated: snapshot.dirty_paths_truncated,
|
|
417
492
|
};
|
|
418
493
|
}
|
|
494
|
+
function snapshotFailure(label, snapshot) {
|
|
495
|
+
return `${label} snapshot is ${snapshot.observation}${snapshot.observation_detail ? ` (${snapshot.observation_detail})` : ""}`;
|
|
496
|
+
}
|
|
497
|
+
function repoComparisonProblem(before, after) {
|
|
498
|
+
if (!observationsComparable(before, after)) {
|
|
499
|
+
return [
|
|
500
|
+
...(before.observation !== "ok" ? [snapshotFailure("before", before)] : []),
|
|
501
|
+
...(after.observation !== "ok" ? [snapshotFailure("after", after)] : []),
|
|
502
|
+
].join("; ");
|
|
503
|
+
}
|
|
504
|
+
const unknownRoots = [
|
|
505
|
+
...(!before.root || !isAbsolute(before.root) ? ["before"] : []),
|
|
506
|
+
...(!after.root || !isAbsolute(after.root) ? ["after"] : []),
|
|
507
|
+
];
|
|
508
|
+
if (unknownRoots.length > 0)
|
|
509
|
+
return `${unknownRoots.join(" and ")} snapshot repository root is unknown`;
|
|
510
|
+
if (before.root !== after.root)
|
|
511
|
+
return "snapshots name different repository roots";
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
419
514
|
function buildAdapterCoverage(agents, claims, attestations) {
|
|
420
515
|
return [...new Set(agents.map((agent) => agent.adapter))].map((adapter) => {
|
|
421
516
|
const adapterAgents = agents.filter((agent) => agent.adapter === adapter);
|
|
@@ -47,6 +47,8 @@ export declare function assertWorkflowRunResumable(coordRoot: string, runId: str
|
|
|
47
47
|
};
|
|
48
48
|
export declare function assertWorkflowScriptUnchanged(manifest: WorkflowRunManifest): void;
|
|
49
49
|
export declare function workflowRunManifestPath(coordRoot: string, runId: string): string;
|
|
50
|
-
/** Acquire an exclusive
|
|
50
|
+
/** Acquire an exclusive lease shared by resume and reclaim. Existing locks
|
|
51
|
+
* always refuse: a stale observation cannot authorize unlinking a new owner.
|
|
52
|
+
* Crash recovery requires an audited ownership check outside this operation. */
|
|
51
53
|
export declare function acquireWorkflowResumeLease(coordRoot: string, runId: string): () => void;
|
|
52
54
|
//# sourceMappingURL=run-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-state.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/run-state.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAEzB,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EACV,sBAAsB,EACtB,iCAAiC,EACjC,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAEV,gBAAgB,EAChB,uCAAuC,EACxC,MAAM,uBAAuB,CAAC;AAO/B,eAAO,MAAM,oCAAoC,EAAG,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"run-state.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/run-state.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAEzB,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EACV,sBAAsB,EACtB,iCAAiC,EACjC,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAEV,gBAAgB,EAChB,uCAAuC,EACxC,MAAM,uBAAuB,CAAC;AAO/B,eAAO,MAAM,oCAAoC,EAAG,CAAU,CAAC;AAI/D,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,OAAO,oCAAoC,CAAC;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,iBAAiB,EAAE,YAAY,CAAC;IAChC,SAAS,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,oBAAoB,CAAC,EAAE,iCAAiC,CAAC;QACzD,iBAAiB,EAAE,OAAO,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC;QAC/B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,SAAS,EAAE,eAAe,CAAC;QAC3B,cAAc,EAAE,mBAAmB,CAAC;QACpC,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;QACxD,iBAAiB,CAAC,EAAE,gBAAgB,CAAC;QACrC,kBAAkB,CAAC,EAAE,uCAAuC,CAAC;KAC9D,CAAC;CACH;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,6BAA6B,GAAG,MAAM,CAgBrF;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAgD7F;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ;IAAE,QAAQ,EAAE,mBAAmB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA4BvD;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CASjF;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED;;gFAEgF;AAChF,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,CA2CvF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { hostname } from "node:os";
|
|
4
4
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
@@ -13,7 +13,6 @@ import { isCanonicalWorkflowWorkContext } from "./work-context.js";
|
|
|
13
13
|
import { assertWorkspaceManifestAuthority, isWorkspaceBinding, isWorkspaceCompatibilityExecutionEvidence, } from "./workspaces/validate.js";
|
|
14
14
|
export const WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION = 2;
|
|
15
15
|
const MANIFEST_LIMIT_BYTES = 256 * 1024;
|
|
16
|
-
const FOREIGN_LEASE_STALE_MS = 24 * 60 * 60 * 1_000;
|
|
17
16
|
export function workflowScriptDigest(scriptPath) {
|
|
18
17
|
return createHash("sha256").update(readFileSync(scriptPath)).digest("hex");
|
|
19
18
|
}
|
|
@@ -70,6 +69,13 @@ export function readWorkflowRunManifest(coordRoot, runId) {
|
|
|
70
69
|
!validExecution(manifest.execution)) {
|
|
71
70
|
throw new Error(`workflow run manifest at ${path} has an unsupported or mismatched schema`);
|
|
72
71
|
}
|
|
72
|
+
if (manifest.repository_before.observation === undefined) {
|
|
73
|
+
manifest.repository_before = {
|
|
74
|
+
...manifest.repository_before,
|
|
75
|
+
observation: "unavailable",
|
|
76
|
+
observation_detail: "No repository observation was recorded.",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
73
79
|
assertWorkspaceManifestAuthority(manifest, readManifestWorkspaceRequest(coordRoot, runId));
|
|
74
80
|
return manifest;
|
|
75
81
|
}
|
|
@@ -121,17 +127,25 @@ export function workflowRunManifestPath(coordRoot, runId) {
|
|
|
121
127
|
assertWorkflowRunId(runId);
|
|
122
128
|
return join(coordRoot, ".harnery", "workflows", runId, "run.json");
|
|
123
129
|
}
|
|
124
|
-
/** Acquire an exclusive
|
|
130
|
+
/** Acquire an exclusive lease shared by resume and reclaim. Existing locks
|
|
131
|
+
* always refuse: a stale observation cannot authorize unlinking a new owner.
|
|
132
|
+
* Crash recovery requires an audited ownership check outside this operation. */
|
|
125
133
|
export function acquireWorkflowResumeLease(coordRoot, runId) {
|
|
126
134
|
assertWorkflowRunId(runId);
|
|
127
135
|
const path = join(coordRoot, ".harnery", "workflows", runId, "resume.lock");
|
|
128
|
-
const owner = {
|
|
136
|
+
const owner = {
|
|
137
|
+
owner_id: randomUUID(),
|
|
138
|
+
pid: process.pid,
|
|
139
|
+
host: hostname(),
|
|
140
|
+
created_at: new Date().toISOString(),
|
|
141
|
+
};
|
|
142
|
+
const ownerBytes = `${JSON.stringify(owner)}\n`;
|
|
129
143
|
mkdirSync(dirname(path), { recursive: true });
|
|
130
144
|
const acquire = () => {
|
|
131
145
|
try {
|
|
132
146
|
const fd = openSync(path, "wx", stateFileMode());
|
|
133
147
|
try {
|
|
134
|
-
writeFileSync(fd,
|
|
148
|
+
writeFileSync(fd, ownerBytes, "utf8");
|
|
135
149
|
}
|
|
136
150
|
finally {
|
|
137
151
|
closeSync(fd);
|
|
@@ -147,21 +161,18 @@ export function acquireWorkflowResumeLease(coordRoot, runId) {
|
|
|
147
161
|
};
|
|
148
162
|
if (!acquire()) {
|
|
149
163
|
const existing = readResumeLease(path);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if (!acquire())
|
|
155
|
-
throw new Error(`workflow run ${runId} resume lease raced with another process`);
|
|
164
|
+
const holder = existing
|
|
165
|
+
? ` by pid ${existing.pid} on ${existing.host}; its liveness has not been verified`
|
|
166
|
+
: "; its owner could not be verified";
|
|
167
|
+
throw new Error(`workflow run ${runId} resume lease is already held${holder}`);
|
|
156
168
|
}
|
|
157
169
|
return () => {
|
|
158
170
|
try {
|
|
159
|
-
|
|
160
|
-
if (existing?.pid === owner.pid && existing.host === owner.host)
|
|
171
|
+
if (readFileSync(path, "utf8") === ownerBytes)
|
|
161
172
|
unlinkSync(path);
|
|
162
173
|
}
|
|
163
174
|
catch {
|
|
164
|
-
//
|
|
175
|
+
// Leave an unreadable or replaced lock untouched.
|
|
165
176
|
}
|
|
166
177
|
};
|
|
167
178
|
}
|
|
@@ -180,19 +191,6 @@ function readResumeLease(path) {
|
|
|
180
191
|
return null;
|
|
181
192
|
}
|
|
182
193
|
}
|
|
183
|
-
function resumeLeaseIsLive(lease) {
|
|
184
|
-
if (lease.host !== hostname()) {
|
|
185
|
-
const age = Date.now() - Date.parse(lease.created_at);
|
|
186
|
-
return Number.isFinite(age) && age < FOREIGN_LEASE_STALE_MS;
|
|
187
|
-
}
|
|
188
|
-
try {
|
|
189
|
-
process.kill(lease.pid, 0);
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
return error.code === "EPERM";
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
194
|
function validExecution(value) {
|
|
197
195
|
if (!value || typeof value !== "object")
|
|
198
196
|
return false;
|
|
@@ -259,6 +257,12 @@ function validFrozenPolicy(policy, cwd) {
|
|
|
259
257
|
function validRepoSnapshot(value) {
|
|
260
258
|
return (Boolean(value) &&
|
|
261
259
|
typeof value === "object" &&
|
|
260
|
+
(value.observation === undefined ||
|
|
261
|
+
value.observation === "ok" ||
|
|
262
|
+
value.observation === "partial" ||
|
|
263
|
+
value.observation === "unavailable") &&
|
|
264
|
+
(value.observation_detail === undefined ||
|
|
265
|
+
(typeof value.observation_detail === "string" && value.observation_detail.length <= 500)) &&
|
|
262
266
|
isAbsolute(value.cwd) &&
|
|
263
267
|
(value.root === undefined || isAbsolute(value.root)) &&
|
|
264
268
|
(value.branch === undefined || typeof value.branch === "string") &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMhF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAYrE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA0B1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAexE;AA+ED,eAAO,MAAM,iBAAiB,EAAE,OAiB/B,CAAC"}
|
|
@@ -21,6 +21,7 @@ import { exec } from "../../lib/exec.js";
|
|
|
21
21
|
import { builtinAdapterProfile, validateAdapterEffort } from "../adapters/profiles.js";
|
|
22
22
|
import { notFoundError } from "./adapters.js";
|
|
23
23
|
import { buildChildEnv } from "./child-env.js";
|
|
24
|
+
import { observeSpawnFailure } from "./failure-evidence.js";
|
|
24
25
|
import { resolveFullAccessArgv, resolveSandboxProjection } from "./sandbox-projection.js";
|
|
25
26
|
import { isUpstreamFailureText, vendorFailureText } from "./spawn-failure.js";
|
|
26
27
|
export function buildClaudeInvocation(req) {
|
|
@@ -50,6 +51,24 @@ export function buildClaudeInvocation(req) {
|
|
|
50
51
|
return { argv };
|
|
51
52
|
}
|
|
52
53
|
export function normalizeClaudeResult(raw) {
|
|
54
|
+
const result = normalizeClaudeTransportResult(raw);
|
|
55
|
+
if (result.ok)
|
|
56
|
+
return result;
|
|
57
|
+
let text = raw.stdout.trim();
|
|
58
|
+
let source = "stdout";
|
|
59
|
+
try {
|
|
60
|
+
const envelope = JSON.parse(raw.stdout);
|
|
61
|
+
if (typeof envelope.result === "string" && envelope.result.length > 0) {
|
|
62
|
+
text = envelope.result;
|
|
63
|
+
source = "vendor_envelope";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Retain unstructured output without treating it as native authority.
|
|
68
|
+
}
|
|
69
|
+
return { ...result, text, failureEvidence: observeSpawnFailure(raw, text, source) };
|
|
70
|
+
}
|
|
71
|
+
function normalizeClaudeTransportResult(raw) {
|
|
53
72
|
if (raw.timedOut) {
|
|
54
73
|
return {
|
|
55
74
|
ok: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-codex.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-codex.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMhF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB,CA6C9F;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAUvE;AA4CD,eAAO,MAAM,YAAY,EAAE,OA8B1B,CAAC"}
|
|
@@ -24,6 +24,7 @@ import { exec } from "../../lib/exec.js";
|
|
|
24
24
|
import { builtinAdapterProfile, validateAdapterEffort } from "../adapters/profiles.js";
|
|
25
25
|
import { notFoundError } from "./adapters.js";
|
|
26
26
|
import { buildChildEnv } from "./child-env.js";
|
|
27
|
+
import { observeSpawnFailure } from "./failure-evidence.js";
|
|
27
28
|
import { resolveFullAccessArgv, resolveSandboxProjection } from "./sandbox-projection.js";
|
|
28
29
|
import { isUpstreamFailureText, vendorFailureText } from "./spawn-failure.js";
|
|
29
30
|
export function buildCodexInvocation(req, resultFile) {
|
|
@@ -71,6 +72,18 @@ export function buildCodexInvocation(req, resultFile) {
|
|
|
71
72
|
return { argv, resultFile };
|
|
72
73
|
}
|
|
73
74
|
export function normalizeCodexResult(raw) {
|
|
75
|
+
const result = normalizeCodexTransportResult(raw);
|
|
76
|
+
if (result.ok)
|
|
77
|
+
return result;
|
|
78
|
+
const finalText = raw.resultFileText?.trim();
|
|
79
|
+
const text = finalText || raw.stdout.trim();
|
|
80
|
+
return {
|
|
81
|
+
...result,
|
|
82
|
+
text,
|
|
83
|
+
failureEvidence: observeSpawnFailure(raw, text, finalText ? "final_message" : "stdout"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function normalizeCodexTransportResult(raw) {
|
|
74
87
|
if (raw.timedOut) {
|
|
75
88
|
return {
|
|
76
89
|
ok: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-cursor.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-cursor.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMhF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASrE,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAWA;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAsB1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAexE;AAyDD,eAAO,MAAM,aAAa,EAAE,OAkB3B,CAAC"}
|