@astrosheep/keiyaku 2.9.3 → 2.9.5
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/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +14 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +26 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +68 -5
- package/build/agents/harness/projection.js +179 -124
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +82 -53
- package/build/agents/providers/codex-app-server/events.js +90 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/events.js +4 -3
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +10 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +1 -1
- package/build/cli/commands/akuma/list/meta-ls.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma/view/meta.js +1 -1
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/amend/meta.js +4 -4
- package/build/cli/commands/contract/arc/handler.js +8 -2
- package/build/cli/commands/contract/arc/meta.js +4 -4
- package/build/cli/commands/contract/audit/handler.js +16 -0
- package/build/cli/commands/contract/audit/meta.js +16 -0
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +44 -8
- package/build/cli/commands/contract/catalog.js +2 -0
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/forfeit/meta.js +1 -1
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/log/meta.js +1 -1
- package/build/cli/commands/contract/petition/handler.js +5 -8
- package/build/cli/commands/contract/petition/meta.js +6 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +6 -5
- package/build/cli/commands/metadata.js +59 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/call/meta.js +4 -1
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/kill/meta.js +1 -1
- package/build/cli/commands/projection/revive/meta.js +4 -1
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/status/meta.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/tell/meta.js +4 -1
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +8 -3
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/install/meta.js +1 -1
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/skills/skills/meta.js +1 -1
- package/build/cli/commands/system/completion/meta.js +1 -1
- package/build/cli/commands/system/dump-env/meta.js +1 -1
- package/build/cli/commands/system/guide/meta.js +1 -1
- package/build/cli/commands/task/add/handler.js +7 -15
- package/build/cli/commands/task/add/meta.js +4 -1
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/doctor/meta.js +1 -1
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/ls/handler.js +12 -8
- package/build/cli/commands/task/ls/meta.js +3 -3
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/task/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +6 -11
- package/build/cli/commands/task/update/meta.js +4 -1
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +37 -6
- package/build/cli/help.js +7 -14
- package/build/cli/index.js +112 -154
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/output-stream-error-policy.js +19 -5
- package/build/cli/parse-flags.js +33 -7
- package/build/cli/parse-metadata.js +3 -9
- package/build/cli/parse-selectors.js +2 -1
- package/build/cli/parse.js +35 -5
- package/build/cli/projection-address.js +12 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/audit.js +121 -0
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +58 -13
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +15 -6
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +56 -23
- package/build/cli/render/success-response.js +78 -0
- package/build/cli/render/task.js +66 -57
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +63 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +68 -38
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +3 -0
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +61 -18
- package/build/core/arc.js +33 -73
- package/build/core/audit.js +650 -0
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +22 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +22 -6
- package/build/core/draft.js +139 -19
- package/build/core/entry.js +3 -4
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/lex.js +2 -1
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +41 -52
- package/build/core/projection/generation/model.js +63 -2
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
- package/build/core/projection/generation/store.js +3 -3
- package/build/core/projection/generation/transitions.js +19 -3
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
- package/build/core/projection/projection-terminal-failure.js +106 -0
- package/build/core/projection/projection-wait.js +275 -0
- package/build/core/projection/projection-wake.js +227 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +448 -102
- package/build/core/scope.js +272 -68
- package/build/core/seal.js +165 -40
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
- package/build/core/{petition.js → settlement/petition.js} +21 -12
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +288 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/settlement/verification.js +59 -0
- package/build/core/status/board.js +62 -41
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +6 -2
- package/build/core/task/board.js +41 -4
- package/build/core/task/commands.js +45 -28
- package/build/core/task/document.js +5 -0
- package/build/core/task/index.js +12 -0
- package/build/core/task/model.js +8 -1
- package/build/core/task/query.js +172 -0
- package/build/core/task/settlement-git.js +265 -74
- package/build/core/task/settlement-policy.js +67 -29
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-contract.js +444 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +7 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +83 -39
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/diff/parsers.js +23 -13
- package/build/git/diff/structured.js +127 -0
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +9 -9
- package/build/keiyaku.js +2 -36
- package/build/telemetry/logger.js +4 -2
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +5 -4
- package/skills/keiyaku-akuma/SKILL.md +25 -11
- package/skills/keiyaku-task/SKILL.md +17 -8
- package/skills/keiyaku-workflow/SKILL.md +58 -9
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { isErrnoException } from "
|
|
3
|
+
import { isErrnoException } from "../../errno.js";
|
|
4
4
|
import { executionEventsPath, isProjectionId, projectionRoot, } from "./projection-core.js";
|
|
5
5
|
import { readProjectionAlias } from "./projection-alias.js";
|
|
6
|
-
import { ProjectionStateError } from "
|
|
7
|
-
import {
|
|
6
|
+
import { ProjectionStateError } from "../atomic-publish.js";
|
|
7
|
+
import { foldPublicProjectionActivity, } from "./projection-activity.js";
|
|
8
8
|
import { readProjectionIdentity } from "./projection-identity.js";
|
|
9
|
-
import { readProjectionTellCounts } from "./
|
|
10
|
-
import {
|
|
11
|
-
import { PROJECTION_ADOPTION_TIMEOUT_MS } from "./projection-generation-launcher.js";
|
|
9
|
+
import { readProjectionTellCounts } from "./tell/store.js";
|
|
10
|
+
import { ProjectionGenerationStoreError, } from "./generation/store.js";
|
|
11
|
+
import { PROJECTION_ADOPTION_TIMEOUT_MS } from "./generation/projection-generation-launcher.js";
|
|
12
12
|
import { observeProjectionLifeSnapshot } from "./projection-life-observer.js";
|
|
13
|
-
import { selectCurrentGeneration } from "./projection-life-protocol.js";
|
|
14
|
-
import { invalidActivityEventDiagnostic, selectValidStoredAgentEvents } from "
|
|
13
|
+
import { selectCurrentGeneration, } from "./projection-life-protocol.js";
|
|
14
|
+
import { invalidActivityEventDiagnostic, selectValidStoredAgentEvents } from "../stored-agent-event.js";
|
|
15
|
+
import { worktreeContainsCoordinate } from "../worktree-path.js";
|
|
16
|
+
import { projectTerminalFailure, } from "./projection-terminal-failure.js";
|
|
17
|
+
import { extractTerminalTimestamp } from "./generation/model.js";
|
|
15
18
|
const MAX_STATUS_FILE_BYTES = 256 * 1024;
|
|
16
|
-
export const DEFAULT_PROJECTION_STATUS_ROW_BUDGET = 20;
|
|
17
19
|
const STATUS_GROUP = {
|
|
18
20
|
"startup-timeout": 0,
|
|
19
21
|
lost: 0,
|
|
@@ -25,13 +27,15 @@ const STATUS_GROUP = {
|
|
|
25
27
|
done: 3,
|
|
26
28
|
killed: 4,
|
|
27
29
|
dismissed: 4,
|
|
30
|
+
incompatible: 5,
|
|
28
31
|
};
|
|
29
32
|
function isOmissibleProjectionStatusState(state) {
|
|
30
33
|
return state === "failed"
|
|
31
34
|
|| state === "dead"
|
|
32
35
|
|| state === "done"
|
|
33
36
|
|| state === "killed"
|
|
34
|
-
|| state === "dismissed"
|
|
37
|
+
|| state === "dismissed"
|
|
38
|
+
|| state === "incompatible";
|
|
35
39
|
}
|
|
36
40
|
function rowSortTime(row) {
|
|
37
41
|
if (row.activityAtMs !== undefined && Number.isFinite(row.activityAtMs)) {
|
|
@@ -63,23 +67,16 @@ export function prioritizeProjectionStatusRows(rows, showAll) {
|
|
|
63
67
|
const ordered = [...rows].sort(compareProjectionStatusRows);
|
|
64
68
|
if (showAll)
|
|
65
69
|
return { rows: ordered };
|
|
66
|
-
const
|
|
67
|
-
let terminalBudget = Math.max(0, DEFAULT_PROJECTION_STATUS_ROW_BUDGET - protectedCount);
|
|
68
|
-
const visible = [];
|
|
70
|
+
const visible = ordered.filter((row) => !isOmissibleProjectionStatusState(row.state));
|
|
69
71
|
const byState = {
|
|
70
72
|
failed: 0,
|
|
71
73
|
dead: 0,
|
|
72
74
|
done: 0,
|
|
73
75
|
killed: 0,
|
|
74
76
|
dismissed: 0,
|
|
77
|
+
incompatible: 0,
|
|
75
78
|
};
|
|
76
79
|
for (const row of ordered) {
|
|
77
|
-
if (STATUS_GROUP[row.state] < 2 || terminalBudget > 0) {
|
|
78
|
-
visible.push(row);
|
|
79
|
-
if (STATUS_GROUP[row.state] >= 2)
|
|
80
|
-
terminalBudget -= 1;
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
80
|
if (isOmissibleProjectionStatusState(row.state))
|
|
84
81
|
byState[row.state] += 1;
|
|
85
82
|
}
|
|
@@ -97,10 +94,9 @@ class ProjectionStatusFileError extends Error {
|
|
|
97
94
|
}
|
|
98
95
|
}
|
|
99
96
|
function oversizedProjectionFileDiagnostic(filePath) {
|
|
100
|
-
const label = path.basename(filePath);
|
|
101
97
|
return {
|
|
102
98
|
kind: "oversized-projection-file",
|
|
103
|
-
|
|
99
|
+
fileName: path.basename(filePath),
|
|
104
100
|
};
|
|
105
101
|
}
|
|
106
102
|
function recordProjectionStatusFileError(error, diagnostics) {
|
|
@@ -247,84 +243,130 @@ function readStoredEvents(projectionDir, executionId, diagnostics) {
|
|
|
247
243
|
}
|
|
248
244
|
return values;
|
|
249
245
|
}
|
|
250
|
-
function
|
|
246
|
+
function latestValidEvent(events) {
|
|
251
247
|
let latest;
|
|
252
248
|
for (const event of events) {
|
|
253
249
|
const atMs = Date.parse(event.at);
|
|
254
250
|
if (!Number.isFinite(atMs))
|
|
255
251
|
continue;
|
|
256
|
-
if (latest === undefined || atMs > latest)
|
|
257
|
-
latest = atMs;
|
|
252
|
+
if (latest === undefined || atMs > latest.atMs)
|
|
253
|
+
latest = { at: event.at, atMs };
|
|
258
254
|
}
|
|
259
255
|
return latest;
|
|
260
256
|
}
|
|
261
|
-
function readActivityFacts(projectionDir, executionId, nowMs, diagnostics,
|
|
262
|
-
|
|
263
|
-
|
|
257
|
+
function readActivityFacts(projectionDir, executionId, nowMs, diagnostics, fallbackAt) {
|
|
258
|
+
const fallbackAtMs = fallbackAt === undefined ? undefined : Date.parse(fallbackAt);
|
|
259
|
+
const validFallback = fallbackAt !== undefined && Number.isFinite(fallbackAtMs)
|
|
260
|
+
? { at: fallbackAt, atMs: fallbackAtMs }
|
|
261
|
+
: undefined;
|
|
262
|
+
if (!executionId) {
|
|
263
|
+
return validFallback
|
|
264
|
+
? { activityAt: validFallback.at, activityAtMs: validFallback.atMs, activityAgeMs: Math.max(0, nowMs - validFallback.atMs) }
|
|
265
|
+
: {};
|
|
266
|
+
}
|
|
264
267
|
const stored = readStoredEvents(projectionDir, executionId, diagnostics);
|
|
265
268
|
const { events, malformed } = selectValidStoredAgentEvents(stored);
|
|
266
269
|
const invalidActivity = invalidActivityEventDiagnostic(malformed);
|
|
267
270
|
if (invalidActivity)
|
|
268
271
|
diagnostics.push(invalidActivity);
|
|
269
|
-
const
|
|
272
|
+
const latest = latestValidEvent(events) ?? validFallback;
|
|
270
273
|
return {
|
|
271
|
-
...(events.length > 0 ? { activity:
|
|
272
|
-
...(
|
|
274
|
+
...(events.length > 0 ? { activity: foldPublicProjectionActivity(events) } : {}),
|
|
275
|
+
...(latest !== undefined
|
|
273
276
|
? {
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
activityAt: latest.at,
|
|
278
|
+
activityAtMs: latest.atMs,
|
|
279
|
+
activityAgeMs: Math.max(0, nowMs - latest.atMs),
|
|
276
280
|
}
|
|
277
281
|
: {}),
|
|
278
282
|
};
|
|
279
283
|
}
|
|
284
|
+
function terminalTimestamp(current) {
|
|
285
|
+
return extractTerminalTimestamp(current?.verdict?.facts);
|
|
286
|
+
}
|
|
280
287
|
function readProjectionRow(projectionDir, id, alias, nowMs) {
|
|
281
288
|
const diagnostics = [];
|
|
289
|
+
const snapshot = observeProjectionLifeSnapshot(projectionDir, {
|
|
290
|
+
nowMs,
|
|
291
|
+
startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
|
|
292
|
+
});
|
|
293
|
+
if (snapshot.compatibility === "incompatible") {
|
|
294
|
+
return {
|
|
295
|
+
id,
|
|
296
|
+
...(alias ? { alias } : {}),
|
|
297
|
+
state: "incompatible",
|
|
298
|
+
observation: snapshot,
|
|
299
|
+
tellCounts: emptyTellCounts(),
|
|
300
|
+
diagnostics,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
282
303
|
const identityFacts = readIdentityFacts(projectionDir, diagnostics);
|
|
283
304
|
const tellCounts = identityFacts.identity
|
|
284
305
|
? readHeartTellCounts(projectionDir, diagnostics)
|
|
285
306
|
: emptyTellCounts();
|
|
286
307
|
if (!identityFacts.identity) {
|
|
308
|
+
const diagnostic = diagnostics.map((entry) => entry.detail).find((detail) => detail !== undefined)
|
|
309
|
+
?? "projection identity could not be observed";
|
|
287
310
|
return {
|
|
288
311
|
id,
|
|
312
|
+
...(alias ? { alias } : {}),
|
|
289
313
|
state: "unknown",
|
|
314
|
+
observation: {
|
|
315
|
+
compatibility: "current",
|
|
316
|
+
lifecycle: { phase: "unknown", diagnostic },
|
|
317
|
+
},
|
|
290
318
|
tellCounts,
|
|
291
319
|
diagnostics,
|
|
292
320
|
};
|
|
293
321
|
}
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
});
|
|
298
|
-
const life = observation.life;
|
|
299
|
-
const current = observation.records
|
|
300
|
-
? selectCurrentGeneration(observation.records)
|
|
322
|
+
const life = snapshot.life;
|
|
323
|
+
const current = snapshot.records
|
|
324
|
+
? selectCurrentGeneration(snapshot.records)
|
|
301
325
|
: null;
|
|
302
326
|
const adoptedAt = current?.adoption?.facts.adoptedAt;
|
|
303
327
|
const adoptedAtMs = typeof adoptedAt === "string"
|
|
304
328
|
? Date.parse(adoptedAt)
|
|
305
329
|
: Number.NaN;
|
|
306
|
-
const activityFacts = readActivityFacts(projectionDir, life.executionId, nowMs, diagnostics, Number.isFinite(adoptedAtMs) ?
|
|
330
|
+
const activityFacts = readActivityFacts(projectionDir, life.executionId, nowMs, diagnostics, typeof adoptedAt === "string" && Number.isFinite(adoptedAtMs) ? adoptedAt : identityFacts.mintedAt);
|
|
331
|
+
const mintedAtMs = Date.parse(identityFacts.mintedAt ?? "");
|
|
332
|
+
const terminalAt = terminalTimestamp(current);
|
|
333
|
+
const durationAnchorMs = current?.verdict
|
|
334
|
+
? (terminalAt === undefined ? Number.NaN : Date.parse(terminalAt))
|
|
335
|
+
: nowMs;
|
|
336
|
+
const durationMs = Number.isFinite(mintedAtMs) && Number.isFinite(durationAnchorMs)
|
|
337
|
+
? Math.max(0, durationAnchorMs - mintedAtMs)
|
|
338
|
+
: undefined;
|
|
339
|
+
const displayAgeMs = activityFacts.activityAgeMs
|
|
340
|
+
?? (Number.isFinite(mintedAtMs) ? Math.max(0, nowMs - mintedAtMs) : undefined);
|
|
307
341
|
if (life.phase === "unknown" && life.diagnostic) {
|
|
308
342
|
diagnostics.push({ kind: "unknown-lifecycle", detail: life.diagnostic });
|
|
309
343
|
}
|
|
310
344
|
const phase = life.phase;
|
|
311
345
|
const state = phase === "active" || phase === "quiescent" ? "out" : phase;
|
|
346
|
+
const terminalFailure = current?.verdict
|
|
347
|
+
? projectTerminalFailure(current.verdict.facts.state, current.verdict.facts)
|
|
348
|
+
: undefined;
|
|
312
349
|
return {
|
|
313
350
|
id,
|
|
314
351
|
...(alias ? { alias } : {}),
|
|
315
352
|
state,
|
|
353
|
+
observation: { compatibility: "current", lifecycle: life },
|
|
316
354
|
akuma: identityFacts.akuma,
|
|
317
355
|
provider: identityFacts.provider,
|
|
318
356
|
pid: identityFacts.pid,
|
|
319
357
|
mintedAt: identityFacts.mintedAt,
|
|
358
|
+
...(terminalAt ? { terminalAt } : {}),
|
|
359
|
+
...(durationMs !== undefined ? { durationMs } : {}),
|
|
320
360
|
...(identityFacts.workspaceRoot ? { workspaceRoot: identityFacts.workspaceRoot } : {}),
|
|
321
361
|
...activityFacts,
|
|
362
|
+
...(displayAgeMs !== undefined ? { activityAgeMs: displayAgeMs } : {}),
|
|
363
|
+
...(terminalFailure ? { terminalFailure } : {}),
|
|
322
364
|
tellCounts,
|
|
323
365
|
diagnostics,
|
|
324
366
|
};
|
|
325
367
|
}
|
|
326
|
-
export function readProjectionStatusBoard(cwd, nowMs, options = {}) {
|
|
327
|
-
const root = projectionRoot(cwd);
|
|
368
|
+
export async function readProjectionStatusBoard(cwd, nowMs, options = {}) {
|
|
369
|
+
const root = await projectionRoot(cwd);
|
|
328
370
|
try {
|
|
329
371
|
if (!fs.lstatSync(root).isDirectory())
|
|
330
372
|
return null;
|
|
@@ -349,7 +391,7 @@ export function readProjectionStatusBoard(cwd, nowMs, options = {}) {
|
|
|
349
391
|
for (const alias of fs.readdirSync(aliasRoot).sort()) {
|
|
350
392
|
if (alias.startsWith("."))
|
|
351
393
|
continue;
|
|
352
|
-
const id = readProjectionAlias(cwd, alias);
|
|
394
|
+
const id = await readProjectionAlias(cwd, alias);
|
|
353
395
|
if (id)
|
|
354
396
|
aliases.set(id, alias);
|
|
355
397
|
}
|
|
@@ -382,10 +424,86 @@ export function readProjectionStatusBoard(cwd, nowMs, options = {}) {
|
|
|
382
424
|
catch {
|
|
383
425
|
continue;
|
|
384
426
|
}
|
|
385
|
-
if (isProjectionGenerationSchemaV1Residue(dir))
|
|
386
|
-
continue;
|
|
387
427
|
rows.push(readProjectionRow(dir, id, aliases.get(id), nowMs));
|
|
388
428
|
}
|
|
389
429
|
}
|
|
390
430
|
return rows.length > 0 ? prioritizeProjectionStatusRows(rows, options.showAll === true) : null;
|
|
391
431
|
}
|
|
432
|
+
/**
|
|
433
|
+
* Renew-only lifecycle guard. Immutable identity is checked before lifecycle,
|
|
434
|
+
* so an unrelated or unattributable projection cannot block a commission.
|
|
435
|
+
*/
|
|
436
|
+
export async function hasStrandableProjectionGeneration(input) {
|
|
437
|
+
const root = await projectionRoot(input.cwd);
|
|
438
|
+
let akumas;
|
|
439
|
+
try {
|
|
440
|
+
if (!fs.lstatSync(root).isDirectory())
|
|
441
|
+
return false;
|
|
442
|
+
akumas = fs.readdirSync(root);
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
if (isErrnoException(error) && error.code === "ENOENT")
|
|
446
|
+
return false;
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
for (const akuma of akumas.sort()) {
|
|
450
|
+
if (akuma.startsWith("."))
|
|
451
|
+
continue;
|
|
452
|
+
const akumaDir = path.join(root, akuma);
|
|
453
|
+
try {
|
|
454
|
+
if (!fs.lstatSync(akumaDir).isDirectory())
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
let hexes;
|
|
461
|
+
try {
|
|
462
|
+
hexes = fs.readdirSync(akumaDir);
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
for (const hex of hexes.sort()) {
|
|
468
|
+
const projectionId = `${akuma}/${hex}`;
|
|
469
|
+
const projectionDir = path.join(akumaDir, hex);
|
|
470
|
+
if (!isProjectionId(projectionId))
|
|
471
|
+
continue;
|
|
472
|
+
try {
|
|
473
|
+
if (!fs.lstatSync(projectionDir).isDirectory())
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
let identity;
|
|
480
|
+
try {
|
|
481
|
+
identity = readProjectionIdentity(projectionDir);
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
// Corrupt identity has no trustworthy commission/worktree join and
|
|
485
|
+
// therefore cannot become a repository-wide renew interlock.
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (identity.binding.kind !== "commission"
|
|
489
|
+
|| identity.binding.commissionId !== input.commissionId
|
|
490
|
+
|| !worktreeContainsCoordinate(input.deliveryWorktree, identity.workspaceRoot)) {
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
const observation = observeProjectionLifeSnapshot(projectionDir, {
|
|
494
|
+
nowMs: input.nowMs,
|
|
495
|
+
startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
|
|
496
|
+
});
|
|
497
|
+
if (observation.compatibility !== "current")
|
|
498
|
+
continue;
|
|
499
|
+
const phase = observation.life.phase;
|
|
500
|
+
if (phase === "active"
|
|
501
|
+
|| phase === "minting"
|
|
502
|
+
|| phase === "startup-timeout"
|
|
503
|
+
|| phase === "unknown") {
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { constants as osConstants } from "node:os";
|
|
2
|
+
import { RESPONSE_ARTIFACT_ID_RE } from "../response-artifact-id.js";
|
|
3
|
+
import { OUTCOME_ERROR_VERSION } from "../../agents/types.js";
|
|
4
|
+
const HARNESS_FAILURE_CODES = new Set([
|
|
5
|
+
"SUBAGENT_TIMEOUT",
|
|
6
|
+
"SUBAGENT_TRANSPORT_ERROR",
|
|
7
|
+
"SUBAGENT_POLICY_BUDGET",
|
|
8
|
+
"SUBAGENT_NON_ZERO_EXIT",
|
|
9
|
+
"SUBAGENT_SPAWN_ERROR",
|
|
10
|
+
"SUBAGENT_EXEC_ERROR",
|
|
11
|
+
"SUBAGENT_PROVIDER_UNAVAILABLE",
|
|
12
|
+
]);
|
|
13
|
+
const SYSTEM_SIGNALS = new Set(Object.keys(osConstants.signals));
|
|
14
|
+
function objectValue(value) {
|
|
15
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
16
|
+
? value
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
19
|
+
function failureCode(value) {
|
|
20
|
+
return typeof value === "string" && HARNESS_FAILURE_CODES.has(value)
|
|
21
|
+
? value
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
function nonNegativeNumber(value) {
|
|
25
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0
|
|
26
|
+
? value
|
|
27
|
+
: undefined;
|
|
28
|
+
}
|
|
29
|
+
function exitCode(value) {
|
|
30
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? value : undefined;
|
|
31
|
+
}
|
|
32
|
+
function signal(value) {
|
|
33
|
+
return typeof value === "string" && SYSTEM_SIGNALS.has(value)
|
|
34
|
+
? value
|
|
35
|
+
: undefined;
|
|
36
|
+
}
|
|
37
|
+
function artifactId(source) {
|
|
38
|
+
for (const value of [source.artifactId, source.sourceArtifactId]) {
|
|
39
|
+
if (typeof value === "string" && RESPONSE_ARTIFACT_ID_RE.test(value))
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
function providerFailureCause(value) {
|
|
45
|
+
const source = objectValue(value);
|
|
46
|
+
return source?.kind === "rate_limit_exhausted"
|
|
47
|
+
? { kind: "rate_limit_exhausted" }
|
|
48
|
+
: undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Convert artifact-rich verdict facts into the strict public allowlist. Raw
|
|
52
|
+
* messages, output, diagnostics, sessions, provider payloads, and unknown
|
|
53
|
+
* strings have no path through this function.
|
|
54
|
+
*/
|
|
55
|
+
export function projectTerminalFailure(state, facts) {
|
|
56
|
+
if (state !== "failed" && state !== "lost-runner" && state !== "launch-failed")
|
|
57
|
+
return undefined;
|
|
58
|
+
const source = objectValue(facts);
|
|
59
|
+
if (!source)
|
|
60
|
+
return undefined;
|
|
61
|
+
const error = objectValue(source.error);
|
|
62
|
+
const publicArtifactId = artifactId(source);
|
|
63
|
+
// Runner verdict authority wins classification even when harness evidence is
|
|
64
|
+
// also attached to the verdict.
|
|
65
|
+
if (state === "launch-failed" || state === "lost-runner") {
|
|
66
|
+
const phase = state === "lost-runner"
|
|
67
|
+
? "adoption"
|
|
68
|
+
: source.stage === "spawn" ? "launch" : "adoption";
|
|
69
|
+
const code = phase === "launch"
|
|
70
|
+
? "SUBAGENT_SPAWN_ERROR"
|
|
71
|
+
: "SUBAGENT_EXEC_ERROR";
|
|
72
|
+
const timeoutMs = nonNegativeNumber(error?.timeoutMs ?? source.timeoutMs);
|
|
73
|
+
const publicExitCode = exitCode(error?.exitCode ?? source.exitCode);
|
|
74
|
+
const publicSignal = signal(error?.signal ?? source.signal);
|
|
75
|
+
return {
|
|
76
|
+
class: "runner",
|
|
77
|
+
code,
|
|
78
|
+
phase,
|
|
79
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
80
|
+
...(publicExitCode !== undefined ? { exitCode: publicExitCode } : {}),
|
|
81
|
+
...(publicSignal ? { signal: publicSignal } : {}),
|
|
82
|
+
...(publicArtifactId ? { artifactId: publicArtifactId } : {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (error?.version !== OUTCOME_ERROR_VERSION)
|
|
86
|
+
return undefined;
|
|
87
|
+
const publicSignal = signal(error?.signal ?? source.signal);
|
|
88
|
+
const publicExitCode = exitCode(error?.exitCode ?? source.exitCode);
|
|
89
|
+
const code = failureCode(error?.code ?? source.code)
|
|
90
|
+
?? (publicSignal ? "SUBAGENT_EXEC_ERROR" : undefined)
|
|
91
|
+
?? (publicExitCode !== undefined ? "SUBAGENT_NON_ZERO_EXIT" : undefined);
|
|
92
|
+
if (!code || code === "SUBAGENT_SPAWN_ERROR")
|
|
93
|
+
return undefined;
|
|
94
|
+
const timeoutMs = nonNegativeNumber(error?.timeoutMs ?? source.timeoutMs);
|
|
95
|
+
const publicCause = providerFailureCause(error?.publicCause);
|
|
96
|
+
return {
|
|
97
|
+
class: "harness",
|
|
98
|
+
code,
|
|
99
|
+
phase: source.phase === "adoption" ? "adoption" : "runtime",
|
|
100
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
101
|
+
...(publicExitCode !== undefined ? { exitCode: publicExitCode } : {}),
|
|
102
|
+
...(publicSignal ? { signal: publicSignal } : {}),
|
|
103
|
+
...(publicArtifactId ? { artifactId: publicArtifactId } : {}),
|
|
104
|
+
...(publicCause ? { publicCause } : {}),
|
|
105
|
+
};
|
|
106
|
+
}
|