harnery 0.43.0 → 0.45.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.js +1 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +41 -48
- 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/files.d.ts +2 -2
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +7 -4
- 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 +26 -17
- 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 +15 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +453 -153
- package/dist/commands/turn-rollback.d.ts +5 -0
- package/dist/commands/turn-rollback.d.ts.map +1 -0
- package/dist/commands/turn-rollback.js +76 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +68 -30
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +18 -0
- 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 +8 -12
- 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 +7 -30
- 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/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 -1
- package/dist/core/agents/state/proc-start.d.ts.map +1 -1
- package/dist/core/agents/state/proc-start.js +46 -1
- package/dist/core/agents/state/process-handle.d.ts +26 -0
- package/dist/core/agents/state/process-handle.d.ts.map +1 -0
- package/dist/core/agents/state/process-handle.js +121 -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/artifacts/delivery-card.d.ts.map +1 -1
- package/dist/core/artifacts/delivery-card.js +2 -1
- 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/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 +33 -5
- 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 +7 -13
- package/dist/core/resources/service.d.ts.map +1 -1
- package/dist/core/resources/service.js +34 -91
- 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/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +2 -9
- package/dist/core/servers/index.d.ts +34 -22
- package/dist/core/servers/index.d.ts.map +1 -1
- package/dist/core/servers/index.js +297 -144
- package/dist/core/servers/tunnels.d.ts +7 -7
- package/dist/core/servers/tunnels.d.ts.map +1 -1
- package/dist/core/servers/tunnels.js +47 -10
- 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 +7 -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/turn-rollback/content.d.ts +53 -0
- package/dist/core/turn-rollback/content.d.ts.map +1 -0
- package/dist/core/turn-rollback/content.js +396 -0
- package/dist/core/turn-rollback/index.d.ts +72 -0
- package/dist/core/turn-rollback/index.d.ts.map +1 -0
- package/dist/core/turn-rollback/index.js +443 -0
- 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 +5 -3
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +3 -2
- 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/recovery-audit.d.ts +30 -0
- package/dist/core/workflow/recovery-audit.d.ts.map +1 -0
- package/dist/core/workflow/recovery-audit.js +116 -0
- package/dist/core/workflow/run-state.d.ts +20 -1
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +141 -32
- 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 +328 -8
- 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 +40 -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 +2 -0
- package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/recovery.js +42 -10
- 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/state.d.ts +13 -6
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +58 -12
- 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 +12 -1
- package/src/commander.ts +10 -0
- package/src/commands/agents.ts +54 -63
- package/src/commands/browse.ts +50 -14
- package/src/commands/diagnostics.ts +10 -0
- package/src/commands/doctor.ts +26 -7
- package/src/commands/files.ts +13 -5
- 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 +27 -26
- package/src/commands/supervisor.ts +7 -2
- package/src/commands/toc.ts +14 -6
- package/src/commands/tunnel.ts +533 -166
- package/src/commands/turn-rollback.ts +111 -0
- package/src/commands/workflow.ts +89 -30
- package/src/core/agents/coord-client.ts +20 -0
- 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 +10 -12
- package/src/core/agents/render/session-context.ts +9 -32
- 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/pidmap.ts +13 -0
- package/src/core/agents/state/proc-start.ts +62 -2
- package/src/core/agents/state/process-handle.ts +165 -0
- package/src/core/agents/state/stale-sweep.ts +247 -82
- package/src/core/agents/state/unchanged-file.ts +456 -0
- package/src/core/artifacts/delivery-card.ts +7 -1
- 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/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 +33 -5
- 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 +57 -95
- package/src/core/resources/status.ts +57 -8
- package/src/core/semantic/service.ts +2 -8
- package/src/core/servers/index.ts +376 -141
- package/src/core/servers/tunnels.ts +57 -13
- 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 +87 -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/turn-rollback/content.ts +499 -0
- package/src/core/turn-rollback/index.ts +580 -0
- 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 +12 -2
- package/src/core/workflow/live-session-v3.ts +146 -5
- package/src/core/workflow/proof.ts +134 -26
- package/src/core/workflow/recovery-audit.ts +181 -0
- package/src/core/workflow/run-state.ts +165 -34
- 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 +388 -7
- package/src/core/workflow/workspaces/ownership.ts +232 -0
- package/src/core/workflow/workspaces/reclaim.ts +62 -0
- package/src/core/workflow/workspaces/recovery.ts +45 -10
- 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/state.ts +70 -15
- package/src/lib/zip/index.ts +483 -0
|
@@ -3,12 +3,19 @@ import { hostname } from "node:os";
|
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { gunzipSync } from "node:zlib";
|
|
5
5
|
import { coordEnv } from "../../lib/env.ts";
|
|
6
|
+
import {
|
|
7
|
+
type ProcessGenerationVerdict,
|
|
8
|
+
verifyProcessGeneration,
|
|
9
|
+
} from "../agents/state/proc-start.ts";
|
|
10
|
+
import { currentHarneryRuntimeBuild } from "../events/v3/runtime-build.ts";
|
|
6
11
|
import { createStorageCatalog } from "../storage/catalog.ts";
|
|
7
12
|
import type { HarneryLogRecordV1 } from "../storage/jsonl.ts";
|
|
8
13
|
import { parseLogRecord } from "../storage/jsonl.ts";
|
|
9
14
|
import { familyLogDirectory, readSegmentManifest } from "../storage/segments.ts";
|
|
10
15
|
import type {
|
|
16
|
+
GovernorServiceBuild,
|
|
11
17
|
GovernorServiceConfig,
|
|
18
|
+
GovernorServiceProcessDependencies,
|
|
12
19
|
GovernorServiceRuntime,
|
|
13
20
|
GovernorServiceStatus,
|
|
14
21
|
GovernorServiceStatusRecord,
|
|
@@ -17,7 +24,106 @@ import type {
|
|
|
17
24
|
const MAX_FILE_BYTES = 512 * 1024;
|
|
18
25
|
const MAX_LOG_RECORDS = 10_000;
|
|
19
26
|
const MAX_GOALS = 100;
|
|
20
|
-
|
|
27
|
+
|
|
28
|
+
export function currentGovernorServiceBuild(): GovernorServiceBuild {
|
|
29
|
+
let version = "unknown";
|
|
30
|
+
let revision = "unknown";
|
|
31
|
+
try {
|
|
32
|
+
const manifest = JSON.parse(
|
|
33
|
+
readFileSync(new URL("../../../package.json", import.meta.url), "utf8"),
|
|
34
|
+
) as {
|
|
35
|
+
version?: unknown;
|
|
36
|
+
};
|
|
37
|
+
if (typeof manifest.version === "string" && manifest.version.length <= 100) {
|
|
38
|
+
version = manifest.version;
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
// Missing package metadata cannot establish that the running build is current.
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
revision = currentHarneryRuntimeBuild();
|
|
45
|
+
} catch {
|
|
46
|
+
// Status still reports the unavailable build instead of guessing a match.
|
|
47
|
+
}
|
|
48
|
+
return { version, revision };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function governorServiceBuildStatus(
|
|
52
|
+
record: GovernorServiceStatusRecord | undefined,
|
|
53
|
+
): Pick<
|
|
54
|
+
GovernorServiceStatus,
|
|
55
|
+
"running_build" | "installed_build" | "restart_needed" | "build_status"
|
|
56
|
+
> {
|
|
57
|
+
const installed_build = currentGovernorServiceBuild();
|
|
58
|
+
const candidate = record?.running_build;
|
|
59
|
+
const running_build =
|
|
60
|
+
candidate &&
|
|
61
|
+
typeof candidate.version === "string" &&
|
|
62
|
+
candidate.version.length > 0 &&
|
|
63
|
+
candidate.version.length <= 100 &&
|
|
64
|
+
typeof candidate.revision === "string" &&
|
|
65
|
+
candidate.revision.length > 0 &&
|
|
66
|
+
candidate.revision.length <= 100 &&
|
|
67
|
+
candidate.version !== "unknown" &&
|
|
68
|
+
candidate.revision !== "unknown"
|
|
69
|
+
? candidate
|
|
70
|
+
: null;
|
|
71
|
+
const restart_needed =
|
|
72
|
+
running_build === null ||
|
|
73
|
+
installed_build.version === "unknown" ||
|
|
74
|
+
installed_build.revision === "unknown" ||
|
|
75
|
+
running_build.version !== installed_build.version ||
|
|
76
|
+
running_build.revision !== installed_build.revision;
|
|
77
|
+
return {
|
|
78
|
+
running_build,
|
|
79
|
+
installed_build,
|
|
80
|
+
restart_needed,
|
|
81
|
+
build_status:
|
|
82
|
+
running_build === null
|
|
83
|
+
? "running build unknown; restart needed"
|
|
84
|
+
: restart_needed
|
|
85
|
+
? "restart needed"
|
|
86
|
+
: "current",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** An unknown token or process probe cannot establish a running or stopped owner. */
|
|
91
|
+
export function observeGovernorServiceProcess(
|
|
92
|
+
record: Pick<GovernorServiceStatusRecord, "pid" | "host" | "state" | "start_token"> | undefined,
|
|
93
|
+
dependencies: GovernorServiceProcessDependencies = {},
|
|
94
|
+
): { generation: ProcessGenerationVerdict; liveness: GovernorServiceStatus["liveness"] } {
|
|
95
|
+
if (!record) return { generation: "unknown", liveness: "stopped" };
|
|
96
|
+
const generation =
|
|
97
|
+
record.host === hostname()
|
|
98
|
+
? verifyProcessGeneration(record.pid, record.start_token, dependencies.readToken)
|
|
99
|
+
: "unknown";
|
|
100
|
+
if (record.host !== hostname()) return { generation, liveness: "unknown" };
|
|
101
|
+
try {
|
|
102
|
+
const present = (dependencies.probePid ?? probePid)(record.pid);
|
|
103
|
+
if (!present) return { generation, liveness: "stopped" };
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return {
|
|
106
|
+
generation,
|
|
107
|
+
liveness: (error as NodeJS.ErrnoException).code === "ESRCH" ? "stopped" : "unknown",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
generation,
|
|
112
|
+
liveness:
|
|
113
|
+
generation === "same"
|
|
114
|
+
? record.state === "stopped"
|
|
115
|
+
? "stopped"
|
|
116
|
+
: "running"
|
|
117
|
+
: generation === "different"
|
|
118
|
+
? "stopped"
|
|
119
|
+
: "unknown",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function probePid(pid: number): boolean {
|
|
124
|
+
process.kill(pid, 0);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
21
127
|
|
|
22
128
|
export function readGovernorServiceConfig(coordRootRaw: string): GovernorServiceConfig {
|
|
23
129
|
const coordRoot = resolve(coordRootRaw);
|
|
@@ -67,7 +173,10 @@ export function readGovernorServiceRuntime(
|
|
|
67
173
|
return runtime;
|
|
68
174
|
}
|
|
69
175
|
|
|
70
|
-
export function readGovernorServiceStatus(
|
|
176
|
+
export function readGovernorServiceStatus(
|
|
177
|
+
coordRootRaw: string,
|
|
178
|
+
dependencies: GovernorServiceProcessDependencies = {},
|
|
179
|
+
): GovernorServiceStatus {
|
|
71
180
|
const coordRoot = resolve(coordRootRaw);
|
|
72
181
|
const record = readStatusRecord(coordRoot);
|
|
73
182
|
let config: GovernorServiceConfig | undefined;
|
|
@@ -82,9 +191,19 @@ export function readGovernorServiceStatus(coordRootRaw: string): GovernorService
|
|
|
82
191
|
} catch {
|
|
83
192
|
// Runtime is recoverable and must not make the dashboard unreadable.
|
|
84
193
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
194
|
+
const observation = observeGovernorServiceProcess(record, dependencies);
|
|
195
|
+
if (!record && existsSync(join(serviceDir(coordRoot), "status.json"))) {
|
|
196
|
+
observation.liveness = "unknown";
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
running: observation.liveness === "running" && record?.state !== "stopped",
|
|
200
|
+
stale: observation.liveness === "stopped" && record !== undefined && record.state !== "stopped",
|
|
201
|
+
...observation,
|
|
202
|
+
...governorServiceBuildStatus(record),
|
|
203
|
+
record,
|
|
204
|
+
config,
|
|
205
|
+
runtime,
|
|
206
|
+
};
|
|
88
207
|
}
|
|
89
208
|
|
|
90
209
|
export function governorServiceLogPath(coordRoot: string): string {
|
|
@@ -418,26 +537,15 @@ function readStatusRecord(coordRoot: string): GovernorServiceStatusRecord | unde
|
|
|
418
537
|
) {
|
|
419
538
|
return undefined;
|
|
420
539
|
}
|
|
421
|
-
return
|
|
540
|
+
return {
|
|
541
|
+
...value,
|
|
542
|
+
start_token: typeof value.start_token === "string" ? value.start_token : undefined,
|
|
543
|
+
};
|
|
422
544
|
} catch {
|
|
423
545
|
return undefined;
|
|
424
546
|
}
|
|
425
547
|
}
|
|
426
548
|
|
|
427
|
-
function statusOwnerIsLive(record: GovernorServiceStatusRecord): boolean {
|
|
428
|
-
if (record.state === "stopped") return false;
|
|
429
|
-
if (record.host === hostname()) {
|
|
430
|
-
try {
|
|
431
|
-
process.kill(record.pid, 0);
|
|
432
|
-
return true;
|
|
433
|
-
} catch (error) {
|
|
434
|
-
return (error as NodeJS.ErrnoException).code === "EPERM";
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
const age = Date.now() - Date.parse(record.heartbeat_at);
|
|
438
|
-
return Number.isFinite(age) && age < FOREIGN_STATUS_STALE_MS;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
549
|
function readBoundedJson<T>(path: string, label: string): T {
|
|
442
550
|
if (!existsSync(path)) throw new Error(`${label} does not exist`);
|
|
443
551
|
const size = statSync(path).size;
|
|
@@ -16,12 +16,24 @@ import {
|
|
|
16
16
|
import { hostname } from "node:os";
|
|
17
17
|
import { dirname, join, resolve } from "node:path";
|
|
18
18
|
import { coordEnv } from "../../lib/env.ts";
|
|
19
|
+
import {
|
|
20
|
+
type ProcessGenerationSignalDependencies,
|
|
21
|
+
type ProcessGenerationVerdict,
|
|
22
|
+
processStartToken,
|
|
23
|
+
signalIfSameGeneration,
|
|
24
|
+
} from "../agents/state/proc-start.ts";
|
|
25
|
+
import { resolveBinName } from "../config.ts";
|
|
19
26
|
import { type NormalizedPolicy, normalizePolicy, type PolicyIsolation } from "../policy/index.ts";
|
|
20
27
|
import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.ts";
|
|
21
28
|
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
22
29
|
import { RotatingTextSink } from "../storage/process-log.ts";
|
|
23
30
|
import type { RunWorkItemInput } from "../work/index.ts";
|
|
24
31
|
import { type GovernorRunReport, type GovernorStopReason, runGovernor } from "./runner.ts";
|
|
32
|
+
import {
|
|
33
|
+
currentGovernorServiceBuild,
|
|
34
|
+
governorServiceBuildStatus,
|
|
35
|
+
observeGovernorServiceProcess,
|
|
36
|
+
} from "./service-read.ts";
|
|
25
37
|
import { type GovernorRecord, readGovernor } from "./state.ts";
|
|
26
38
|
|
|
27
39
|
export const GOVERNOR_SERVICE_CONFIG_SCHEMA_VERSION = 1 as const;
|
|
@@ -31,7 +43,6 @@ export const GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION = 1 as const;
|
|
|
31
43
|
const MAX_FILE_BYTES = 512 * 1024;
|
|
32
44
|
const MAX_GOALS = 100;
|
|
33
45
|
const MAX_ERROR = 2_000;
|
|
34
|
-
const FOREIGN_STATUS_STALE_MS = 30_000;
|
|
35
46
|
|
|
36
47
|
export interface GovernorServiceEngineConfig {
|
|
37
48
|
default_adapter?: string;
|
|
@@ -85,9 +96,20 @@ export interface GovernorServiceRuntime {
|
|
|
85
96
|
|
|
86
97
|
export type GovernorServiceProcessState = "starting" | "running" | "stopping" | "stopped";
|
|
87
98
|
|
|
99
|
+
export interface GovernorServiceBuild {
|
|
100
|
+
version: string;
|
|
101
|
+
revision: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface GovernorServiceProcessDependencies extends ProcessGenerationSignalDependencies {
|
|
105
|
+
probePid?: (pid: number) => boolean;
|
|
106
|
+
}
|
|
107
|
+
|
|
88
108
|
export interface GovernorServiceStatusRecord {
|
|
89
109
|
schema_version: typeof GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION;
|
|
90
110
|
pid: number;
|
|
111
|
+
start_token?: string;
|
|
112
|
+
running_build?: GovernorServiceBuild;
|
|
91
113
|
host: string;
|
|
92
114
|
nonce: string;
|
|
93
115
|
state: GovernorServiceProcessState;
|
|
@@ -105,6 +127,14 @@ export interface GovernorServiceStatusRecord {
|
|
|
105
127
|
export interface GovernorServiceStatus {
|
|
106
128
|
running: boolean;
|
|
107
129
|
stale: boolean;
|
|
130
|
+
generation: ProcessGenerationVerdict;
|
|
131
|
+
liveness: "running" | "stopped" | "unknown";
|
|
132
|
+
running_build: GovernorServiceBuild | null;
|
|
133
|
+
installed_build: GovernorServiceBuild;
|
|
134
|
+
restart_needed: boolean;
|
|
135
|
+
build_status: string;
|
|
136
|
+
signal_sent?: boolean;
|
|
137
|
+
signal_verdict?: ProcessGenerationVerdict;
|
|
108
138
|
record?: GovernorServiceStatusRecord;
|
|
109
139
|
config?: GovernorServiceConfig;
|
|
110
140
|
runtime?: GovernorServiceRuntime;
|
|
@@ -145,6 +175,8 @@ export interface RunGovernorServiceDaemonInput {
|
|
|
145
175
|
|
|
146
176
|
interface ServiceLease {
|
|
147
177
|
pid: number;
|
|
178
|
+
start_token?: string;
|
|
179
|
+
running_build?: GovernorServiceBuild;
|
|
148
180
|
host: string;
|
|
149
181
|
nonce: string;
|
|
150
182
|
created_at: string;
|
|
@@ -155,8 +187,12 @@ export function configureGovernorService(
|
|
|
155
187
|
): GovernorServiceConfig {
|
|
156
188
|
const coordRoot = resolve(input.coordRoot);
|
|
157
189
|
const active = readStatusRecord(coordRoot);
|
|
158
|
-
if (active &&
|
|
159
|
-
throw
|
|
190
|
+
if (!active && existsSync(serviceStatusPath(coordRoot))) {
|
|
191
|
+
throw serviceStartRefusal(coordRoot, undefined, "unknown");
|
|
192
|
+
}
|
|
193
|
+
if (active) {
|
|
194
|
+
const liveness = statusOwnerIsLive(active);
|
|
195
|
+
if (liveness !== "stopped") throw serviceStartRefusal(coordRoot, active.pid, liveness);
|
|
160
196
|
}
|
|
161
197
|
const goalIds = unique(input.goalIds.map((value) => value.trim()).filter(Boolean));
|
|
162
198
|
if (goalIds.length < 1 || goalIds.length > MAX_GOALS) {
|
|
@@ -235,7 +271,10 @@ export function readGovernorServiceRuntime(
|
|
|
235
271
|
return runtime;
|
|
236
272
|
}
|
|
237
273
|
|
|
238
|
-
export function readGovernorServiceStatus(
|
|
274
|
+
export function readGovernorServiceStatus(
|
|
275
|
+
coordRootRaw: string,
|
|
276
|
+
dependencies: GovernorServiceProcessDependencies = {},
|
|
277
|
+
): GovernorServiceStatus {
|
|
239
278
|
const coordRoot = resolve(coordRootRaw);
|
|
240
279
|
const record = readStatusRecord(coordRoot);
|
|
241
280
|
let config: GovernorServiceConfig | undefined;
|
|
@@ -250,17 +289,25 @@ export function readGovernorServiceStatus(coordRootRaw: string): GovernorService
|
|
|
250
289
|
} catch {
|
|
251
290
|
// Status remains readable when recoverable runtime state is corrupt.
|
|
252
291
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
return {
|
|
292
|
+
const observation = observeGovernorServiceProcess(record, dependencies);
|
|
293
|
+
if (!record && existsSync(serviceStatusPath(coordRoot))) observation.liveness = "unknown";
|
|
294
|
+
return {
|
|
295
|
+
running: observation.liveness === "running" && record?.state !== "stopped",
|
|
296
|
+
stale: observation.liveness === "stopped" && record !== undefined && record.state !== "stopped",
|
|
297
|
+
...observation,
|
|
298
|
+
...governorServiceBuildStatus(record),
|
|
299
|
+
record,
|
|
300
|
+
config,
|
|
301
|
+
runtime,
|
|
302
|
+
};
|
|
256
303
|
}
|
|
257
304
|
|
|
258
305
|
export async function spawnGovernorService(coordRootRaw: string): Promise<GovernorServiceStatus> {
|
|
259
306
|
const coordRoot = resolve(coordRootRaw);
|
|
260
307
|
readGovernorServiceConfig(coordRoot);
|
|
261
308
|
const current = readGovernorServiceStatus(coordRoot);
|
|
262
|
-
if (current.
|
|
263
|
-
throw
|
|
309
|
+
if (current.liveness !== "stopped") {
|
|
310
|
+
throw serviceStartRefusal(coordRoot, current.record?.pid, current.liveness);
|
|
264
311
|
}
|
|
265
312
|
mkdirSync(serviceDir(coordRoot), { recursive: true, mode: stateDirMode() });
|
|
266
313
|
const sharedLogs = coordEnv("SHARED_LOGS") !== "0";
|
|
@@ -298,22 +345,33 @@ export async function spawnGovernorService(coordRootRaw: string): Promise<Govern
|
|
|
298
345
|
throw new Error(`governor service failed to start; inspect ${governorServiceLogPath(coordRoot)}`);
|
|
299
346
|
}
|
|
300
347
|
|
|
301
|
-
export function requestGovernorServiceStop(
|
|
348
|
+
export function requestGovernorServiceStop(
|
|
349
|
+
coordRootRaw: string,
|
|
350
|
+
dependencies: GovernorServiceProcessDependencies = {},
|
|
351
|
+
): GovernorServiceStatus {
|
|
302
352
|
const coordRoot = resolve(coordRootRaw);
|
|
303
|
-
const status = readGovernorServiceStatus(coordRoot);
|
|
304
|
-
if (
|
|
353
|
+
const status = readGovernorServiceStatus(coordRoot, dependencies);
|
|
354
|
+
if ((status.record?.state === "stopped" || !status.record) && status.liveness === "stopped") {
|
|
355
|
+
return { ...status, signal_sent: false, signal_verdict: status.generation };
|
|
356
|
+
}
|
|
305
357
|
writePrivateJsonAtomic(serviceStopPath(coordRoot), {
|
|
306
358
|
requested_at: new Date().toISOString(),
|
|
307
359
|
requested_by_pid: process.pid,
|
|
308
360
|
});
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
361
|
+
const signal =
|
|
362
|
+
status.record?.host === hostname() && status.record.state !== "stopped"
|
|
363
|
+
? signalIfSameGeneration(
|
|
364
|
+
status.record.pid,
|
|
365
|
+
status.record.start_token,
|
|
366
|
+
"SIGTERM",
|
|
367
|
+
dependencies,
|
|
368
|
+
)
|
|
369
|
+
: { sent: false, verdict: status.generation };
|
|
370
|
+
return {
|
|
371
|
+
...readGovernorServiceStatus(coordRoot, dependencies),
|
|
372
|
+
signal_sent: signal.sent,
|
|
373
|
+
signal_verdict: signal.verdict,
|
|
374
|
+
};
|
|
317
375
|
}
|
|
318
376
|
|
|
319
377
|
export async function runGovernorServiceSweep(
|
|
@@ -461,12 +519,22 @@ export async function runGovernorServiceDaemon(
|
|
|
461
519
|
): Promise<GovernorServiceStatusRecord> {
|
|
462
520
|
const coordRoot = resolve(input.coordRoot);
|
|
463
521
|
const config = readGovernorServiceConfig(coordRoot);
|
|
522
|
+
const existing = readStatusRecord(coordRoot);
|
|
523
|
+
if (!existing && existsSync(serviceStatusPath(coordRoot))) {
|
|
524
|
+
throw serviceStartRefusal(coordRoot, undefined, "unknown");
|
|
525
|
+
}
|
|
526
|
+
if (existing) {
|
|
527
|
+
const liveness = statusOwnerIsLive(existing);
|
|
528
|
+
if (liveness !== "stopped") throw serviceStartRefusal(coordRoot, existing.pid, liveness);
|
|
529
|
+
}
|
|
464
530
|
const release = acquireServiceLease(coordRoot);
|
|
465
531
|
rmSync(serviceStopPath(coordRoot), { force: true });
|
|
466
532
|
const now = new Date().toISOString();
|
|
467
533
|
const status: GovernorServiceStatusRecord = {
|
|
468
534
|
schema_version: GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION,
|
|
469
535
|
pid: process.pid,
|
|
536
|
+
start_token: processStartToken(process.pid) ?? undefined,
|
|
537
|
+
running_build: currentGovernorServiceBuild(),
|
|
470
538
|
host: hostname(),
|
|
471
539
|
nonce: randomUUID(),
|
|
472
540
|
state: "starting",
|
|
@@ -493,6 +561,8 @@ export async function runGovernorServiceDaemon(
|
|
|
493
561
|
appendGovernorServiceDiagnostic(coordRoot, {
|
|
494
562
|
event: "service.started",
|
|
495
563
|
pid: process.pid,
|
|
564
|
+
start_token: status.start_token,
|
|
565
|
+
running_build: status.running_build,
|
|
496
566
|
goals: config.goal_ids,
|
|
497
567
|
config_created_at: config.created_at,
|
|
498
568
|
});
|
|
@@ -716,6 +786,8 @@ function acquireServiceLease(coordRoot: string): () => void {
|
|
|
716
786
|
mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
|
|
717
787
|
const owner: ServiceLease = {
|
|
718
788
|
pid: process.pid,
|
|
789
|
+
start_token: processStartToken(process.pid) ?? undefined,
|
|
790
|
+
running_build: currentGovernorServiceBuild(),
|
|
719
791
|
host: hostname(),
|
|
720
792
|
nonce: randomUUID(),
|
|
721
793
|
created_at: new Date().toISOString(),
|
|
@@ -736,8 +808,9 @@ function acquireServiceLease(coordRoot: string): () => void {
|
|
|
736
808
|
};
|
|
737
809
|
if (!acquire()) {
|
|
738
810
|
const existing = readLease(path);
|
|
739
|
-
|
|
740
|
-
|
|
811
|
+
const liveness = existing ? leaseOwnerIsLive(existing) : "unknown";
|
|
812
|
+
if (liveness !== "stopped") {
|
|
813
|
+
throw serviceStartRefusal(coordRoot, existing?.pid, liveness);
|
|
741
814
|
}
|
|
742
815
|
unlinkSync(path);
|
|
743
816
|
if (!acquire()) throw new Error("governor service lease raced with another process");
|
|
@@ -760,19 +833,18 @@ function readLease(path: string): ServiceLease | null {
|
|
|
760
833
|
typeof value.host === "string" &&
|
|
761
834
|
typeof value.nonce === "string" &&
|
|
762
835
|
typeof value.created_at === "string"
|
|
763
|
-
? (
|
|
836
|
+
? ({
|
|
837
|
+
...value,
|
|
838
|
+
start_token: typeof value.start_token === "string" ? value.start_token : undefined,
|
|
839
|
+
} as ServiceLease)
|
|
764
840
|
: null;
|
|
765
841
|
} catch {
|
|
766
842
|
return null;
|
|
767
843
|
}
|
|
768
844
|
}
|
|
769
845
|
|
|
770
|
-
function leaseOwnerIsLive(lease: ServiceLease):
|
|
771
|
-
|
|
772
|
-
const age = Date.now() - Date.parse(lease.created_at);
|
|
773
|
-
return Number.isFinite(age) && age < FOREIGN_STATUS_STALE_MS;
|
|
774
|
-
}
|
|
775
|
-
return pidAlive(lease.pid);
|
|
846
|
+
function leaseOwnerIsLive(lease: ServiceLease): GovernorServiceStatus["liveness"] {
|
|
847
|
+
return observeGovernorServiceProcess({ ...lease, state: "running" }).liveness;
|
|
776
848
|
}
|
|
777
849
|
|
|
778
850
|
function readStatusRecord(coordRoot: string): GovernorServiceStatusRecord | undefined {
|
|
@@ -793,26 +865,31 @@ function readStatusRecord(coordRoot: string): GovernorServiceStatusRecord | unde
|
|
|
793
865
|
) {
|
|
794
866
|
return undefined;
|
|
795
867
|
}
|
|
796
|
-
return
|
|
868
|
+
return {
|
|
869
|
+
...value,
|
|
870
|
+
start_token: typeof value.start_token === "string" ? value.start_token : undefined,
|
|
871
|
+
};
|
|
797
872
|
} catch {
|
|
798
873
|
return undefined;
|
|
799
874
|
}
|
|
800
875
|
}
|
|
801
876
|
|
|
802
|
-
function statusOwnerIsLive(record: GovernorServiceStatusRecord):
|
|
803
|
-
|
|
804
|
-
if (record.host === hostname()) return pidAlive(record.pid);
|
|
805
|
-
const age = Date.now() - Date.parse(record.heartbeat_at);
|
|
806
|
-
return Number.isFinite(age) && age < FOREIGN_STATUS_STALE_MS;
|
|
877
|
+
function statusOwnerIsLive(record: GovernorServiceStatusRecord): GovernorServiceStatus["liveness"] {
|
|
878
|
+
return observeGovernorServiceProcess(record).liveness;
|
|
807
879
|
}
|
|
808
880
|
|
|
809
|
-
function
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
881
|
+
function serviceStartRefusal(
|
|
882
|
+
coordRoot: string,
|
|
883
|
+
pid: number | undefined,
|
|
884
|
+
liveness: GovernorServiceStatus["liveness"],
|
|
885
|
+
): Error {
|
|
886
|
+
const reason =
|
|
887
|
+
liveness === "unknown"
|
|
888
|
+
? `governor service process generation is unknown${pid ? ` for pid ${pid}` : ""}`
|
|
889
|
+
: `governor service process is still running under pid ${pid}`;
|
|
890
|
+
return new Error(
|
|
891
|
+
`${reason}; run \`${resolveBinName(coordRoot)} governor service stop\` to write a durable stop request before starting or reconfiguring it`,
|
|
892
|
+
);
|
|
816
893
|
}
|
|
817
894
|
|
|
818
895
|
export function appendGovernorServiceDiagnostic(
|
package/src/core/hooks/cli.ts
CHANGED
|
@@ -2298,12 +2298,16 @@ async function emitUserPromptSubmitSystemMessage(
|
|
|
2298
2298
|
if (coordEnv("WORKFLOW_CHILD") === "1") return false;
|
|
2299
2299
|
const behavior = adapterBehavior(adapter);
|
|
2300
2300
|
const { renderPromptContext } = await import("../agents/render/prompt-context.ts");
|
|
2301
|
+
let peerMessageIds: readonly string[] = [];
|
|
2301
2302
|
let additionalContext = renderPromptContext({
|
|
2302
2303
|
coordRoot,
|
|
2303
2304
|
instanceId,
|
|
2304
2305
|
sessionId,
|
|
2305
2306
|
sessionNameNudge: true,
|
|
2306
2307
|
...behavior.promptContextNudges,
|
|
2308
|
+
onInboxPrepared: (ids) => {
|
|
2309
|
+
peerMessageIds = ids;
|
|
2310
|
+
},
|
|
2307
2311
|
}).trim();
|
|
2308
2312
|
const fileLinkContext = behavior.fileLinkContext?.(coordRoot, workspaceCwd) ?? "";
|
|
2309
2313
|
if (fileLinkContext) {
|
|
@@ -2318,7 +2322,12 @@ async function emitUserPromptSubmitSystemMessage(
|
|
|
2318
2322
|
if (!additionalContext) return false;
|
|
2319
2323
|
|
|
2320
2324
|
const { emitContext } = await import("./adapter/output.ts");
|
|
2321
|
-
|
|
2325
|
+
const emitted = emitContext(adapter, "UserPromptSubmit", additionalContext);
|
|
2326
|
+
if (emitted) {
|
|
2327
|
+
const { acknowledgeEmittedPeerInbox } = await import("../inbox/peer-messages.ts");
|
|
2328
|
+
await acknowledgeEmittedPeerInbox(coordRoot, instanceId, peerMessageIds);
|
|
2329
|
+
}
|
|
2330
|
+
return emitted;
|
|
2322
2331
|
}
|
|
2323
2332
|
|
|
2324
2333
|
async function emitSubagentStartContext(
|
|
@@ -2342,19 +2351,26 @@ async function emitSubagentStartContext(
|
|
|
2342
2351
|
// is around. Reuse prompt-context (which dedups against the per-owner hash);
|
|
2343
2352
|
// first call will always emit.
|
|
2344
2353
|
let combined = message;
|
|
2354
|
+
let peerMessageIds: readonly string[] = [];
|
|
2345
2355
|
const { renderPromptContext } = await import("../agents/render/prompt-context.ts");
|
|
2346
2356
|
const context = renderPromptContext({
|
|
2347
2357
|
coordRoot,
|
|
2348
2358
|
instanceId,
|
|
2349
2359
|
sessionId,
|
|
2350
2360
|
agentName: subagentName,
|
|
2361
|
+
onInboxPrepared: (ids) => {
|
|
2362
|
+
peerMessageIds = ids;
|
|
2363
|
+
},
|
|
2351
2364
|
}).trim();
|
|
2352
2365
|
if (context) combined = `${message}\n\n${context}`;
|
|
2353
2366
|
|
|
2354
2367
|
// Use SubagentStart event-name in CC's hookSpecificOutput shape; cursor's
|
|
2355
2368
|
// flat `additional_context` works the same way.
|
|
2356
2369
|
const { emitContext } = await import("./adapter/output.ts");
|
|
2357
|
-
emitContext(adapter, "SubagentStart", combined)
|
|
2370
|
+
if (emitContext(adapter, "SubagentStart", combined)) {
|
|
2371
|
+
const { acknowledgeEmittedPeerInbox } = await import("../inbox/peer-messages.ts");
|
|
2372
|
+
await acknowledgeEmittedPeerInbox(coordRoot, instanceId, peerMessageIds);
|
|
2373
|
+
}
|
|
2358
2374
|
}
|
|
2359
2375
|
|
|
2360
2376
|
function adapterPlatform(adapter: Adapter): string {
|
|
@@ -2373,6 +2389,7 @@ async function emitSessionStartSystemMessage(
|
|
|
2373
2389
|
const behavior = adapterBehavior(adapter);
|
|
2374
2390
|
const workflowChild = coordEnv("WORKFLOW_CHILD") === "1";
|
|
2375
2391
|
let additionalContext = "";
|
|
2392
|
+
let peerMessageIds: readonly string[] = [];
|
|
2376
2393
|
// Opportunistic reconciliation makes normal session starts a failsafe for
|
|
2377
2394
|
// archive, idle, cascade, and host lifecycle observations. It also runs the
|
|
2378
2395
|
// stale cache sweep through the shared ADR 0077 composition.
|
|
@@ -2392,6 +2409,9 @@ async function emitSessionStartSystemMessage(
|
|
|
2392
2409
|
sessionId,
|
|
2393
2410
|
agentName: agentName || undefined,
|
|
2394
2411
|
platformLabel: behavior.sessionStartPlatformLabel,
|
|
2412
|
+
onInboxPrepared: (ids) => {
|
|
2413
|
+
peerMessageIds = ids;
|
|
2414
|
+
},
|
|
2395
2415
|
}).trim();
|
|
2396
2416
|
}
|
|
2397
2417
|
|
|
@@ -2420,7 +2440,12 @@ async function emitSessionStartSystemMessage(
|
|
|
2420
2440
|
}
|
|
2421
2441
|
}
|
|
2422
2442
|
const { emitContext } = await import("./adapter/output.ts");
|
|
2423
|
-
|
|
2443
|
+
const emitted = emitContext(adapter, "SessionStart", additionalContext);
|
|
2444
|
+
if (emitted) {
|
|
2445
|
+
const { acknowledgeEmittedPeerInbox } = await import("../inbox/peer-messages.ts");
|
|
2446
|
+
await acknowledgeEmittedPeerInbox(coordRoot, instanceId, peerMessageIds);
|
|
2447
|
+
}
|
|
2448
|
+
return emitted;
|
|
2424
2449
|
}
|
|
2425
2450
|
|
|
2426
2451
|
function completeRecoveryInjection(
|
|
@@ -2429,8 +2454,11 @@ function completeRecoveryInjection(
|
|
|
2429
2454
|
sessionId: string,
|
|
2430
2455
|
recovery: PreparedContextRecovery,
|
|
2431
2456
|
): void {
|
|
2432
|
-
completeContextRecovery(coordRoot, {
|
|
2433
|
-
|
|
2457
|
+
completeContextRecovery(coordRoot, {
|
|
2458
|
+
sessionId,
|
|
2459
|
+
instanceId,
|
|
2460
|
+
checkpoint: recovery.checkpoint,
|
|
2461
|
+
});
|
|
2434
2462
|
}
|
|
2435
2463
|
|
|
2436
2464
|
main()
|
|
@@ -19,7 +19,8 @@ export interface HarneryInboxMessageRecordV1 {
|
|
|
19
19
|
schema: typeof HARNERY_INBOX_RECORD_SCHEMA;
|
|
20
20
|
kind: "message";
|
|
21
21
|
message_id: string;
|
|
22
|
-
|
|
22
|
+
/** A required null identifies an operator; strings identify real agent instances. */
|
|
23
|
+
sender_instance_id: string | null;
|
|
23
24
|
sender_display_name: string;
|
|
24
25
|
recipient_instance_id: string;
|
|
25
26
|
recipient_display_name: string;
|