@astrosheep/keiyaku 2.9.8 → 2.9.10
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 +50 -182
- package/build/.tsbuildinfo +1 -1
- package/build/agents/harness/control-types.js +18 -1
- package/build/agents/harness/index.js +2 -0
- package/build/agents/harness/outcome-error.js +81 -0
- package/build/agents/harness/projection.js +10 -7
- package/build/agents/harness/router.js +5 -1
- package/build/agents/providers/claude-agent-sdk/adapter.js +18 -4
- package/build/agents/providers/claude-agent-sdk/registration.js +11 -1
- package/build/agents/providers/claude-agent-sdk/session.js +19 -5
- package/build/agents/providers/codex-app-server/adapter.js +11 -6
- package/build/agents/providers/codex-app-server/events.js +67 -6
- package/build/agents/providers/codex-app-server/registration.js +11 -1
- package/build/agents/providers/opencode-sdk/adapter.js +8 -1
- package/build/agents/providers/opencode-sdk/events.js +24 -2
- package/build/agents/providers/opencode-sdk/registration.js +11 -1
- package/build/agents/providers/pi/checkpoint.js +9 -1
- package/build/agents/providers/pi/events.js +2 -0
- package/build/agents/providers/pi/registration.js +14 -1
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +3 -3
- package/build/cli/commands/akuma/catalog.js +2 -2
- package/build/cli/commands/akuma/{view → show}/handler.js +5 -5
- package/build/cli/commands/akuma/{view → show}/meta.js +3 -3
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +5 -4
- package/build/cli/commands/contract/arc/handler.js +5 -4
- package/build/cli/commands/contract/audit/handler.js +2 -2
- package/build/cli/commands/contract/bind/handler.js +12 -3
- package/build/cli/commands/contract/bind/meta.js +45 -15
- package/build/cli/commands/contract/forfeit/handler.js +9 -5
- package/build/cli/commands/contract/log/handler.js +2 -2
- package/build/cli/commands/contract/petition/handler.js +34 -7
- package/build/cli/commands/contract/renew/handler.js +7 -7
- package/build/cli/commands/contract/renew/meta.js +3 -3
- package/build/cli/commands/metadata.js +10 -6
- package/build/cli/commands/projection/call/meta.js +1 -1
- package/build/cli/commands/projection/catalog.js +2 -0
- package/build/cli/commands/projection/history/handler.js +21 -0
- package/build/cli/commands/projection/history/meta.js +9 -0
- package/build/cli/commands/projection/shared.js +3 -4
- package/build/cli/commands/projection/status/handler.js +3 -3
- package/build/cli/commands/projection/wait/handler.js +20 -11
- package/build/cli/commands/task/add/handler.js +14 -5
- package/build/cli/commands/task/add/meta.js +2 -2
- package/build/cli/commands/task/catalog.js +4 -0
- package/build/cli/commands/task/done/handler.js +1 -4
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/hold/handler.js +3 -0
- package/build/cli/commands/task/hold/meta.js +8 -0
- package/build/cli/commands/task/log/handler.js +1 -1
- package/build/cli/commands/task/log/meta.js +2 -2
- package/build/cli/commands/task/resume/handler.js +3 -0
- package/build/cli/commands/task/resume/meta.js +8 -0
- package/build/cli/commands/task/shared.js +39 -14
- package/build/cli/commands/task/show/handler.js +1 -1
- package/build/cli/commands/task/show/meta.js +1 -1
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +1 -4
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +11 -3
- package/build/cli/commands/task/update/meta.js +3 -3
- package/build/cli/completion.js +3 -2
- package/build/cli/flags.js +51 -14
- package/build/cli/help.js +4 -1
- package/build/cli/index.js +40 -25
- package/build/cli/parse-flags.js +40 -7
- package/build/cli/parse-metadata.js +5 -2
- package/build/cli/parse-selectors.js +2 -3
- package/build/cli/parse.js +40 -6
- package/build/cli/projection-address.js +12 -10
- package/build/cli/render/amendment-warning.js +8 -0
- package/build/cli/render/arc.js +6 -2
- package/build/cli/render/audit.js +400 -81
- package/build/cli/render/kanshi.js +242 -79
- package/build/cli/render/lifecycle.js +56 -0
- package/build/cli/render/misc.js +24 -28
- package/build/cli/render/petition.js +5 -0
- package/build/cli/render/projection-activity.js +65 -29
- package/build/cli/render/projection-history.js +64 -0
- package/build/cli/render/shared.js +23 -9
- package/build/cli/render/status.js +13 -35
- package/build/cli/render/task.js +51 -26
- package/build/cli/render/terminal-failure.js +3 -1
- package/build/cli/render/wait.js +45 -69
- package/build/cli/subagent-guard.js +1 -1
- package/build/cli/types.js +1 -1
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +24 -1
- package/build/config/settings/schema.js +3 -1
- package/build/core/address-carrier.js +89 -0
- package/build/core/addressing.js +255 -196
- package/build/core/amend.js +115 -38
- package/build/core/amendment-criteria.js +17 -0
- package/build/core/amendment-warning.js +10 -0
- package/build/core/arc.js +184 -83
- package/build/core/audit/candidate.js +110 -9
- package/build/core/audit/coordinates.js +120 -65
- package/build/core/audit/evidence.js +19 -23
- package/build/core/audit/facade.js +34 -11
- package/build/core/audit/report.js +5 -5
- package/build/core/bind-reconciliation.js +390 -0
- package/build/core/bind-workspace.js +12 -20
- package/build/core/bind.js +242 -273
- package/build/core/call/call.js +1 -0
- package/build/core/call/context.js +46 -71
- package/build/core/call/prompt.js +6 -3
- package/build/core/context.js +49 -35
- package/build/core/contract-carrier-runtime.js +408 -0
- package/build/core/contract-carrier.js +270 -0
- package/build/core/contract-view.js +33 -27
- package/build/core/contract.js +5 -1
- package/build/core/derived-replay.js +207 -0
- package/build/core/draft.js +125 -57
- package/build/core/forfeit.js +113 -56
- package/build/core/identifier-slug.js +63 -13
- package/build/core/ids.js +4 -4
- package/build/core/lifecycle-history.js +35 -0
- package/build/core/lifecycle-recovery.js +117 -0
- package/build/core/lifecycle-runner.js +377 -0
- package/build/core/log.js +37 -11
- package/build/core/outcome-base.js +181 -0
- package/build/core/process-group.js +139 -0
- package/build/core/projection/generation/database.js +82 -7
- package/build/core/projection/generation/model.js +9 -36
- package/build/core/projection/generation/projection-generation-continuation.js +10 -22
- package/build/core/projection/generation/projection-generation-execution.js +13 -6
- package/build/core/projection/index.js +5 -4
- package/build/core/projection/projection-activity.js +29 -8
- package/build/core/projection/projection-alias.js +23 -10
- package/build/core/projection/projection-core.js +21 -7
- package/build/core/projection/projection-execution-observer.js +91 -39
- package/build/core/projection/projection-history.js +474 -0
- package/build/core/projection/projection-runner-lock.js +12 -0
- package/build/core/projection/projection-status-observation.js +365 -0
- package/build/core/projection/projection-status.js +35 -337
- package/build/core/projection/projection-terminal-failure.js +13 -8
- package/build/core/projection/projection-wait.js +7 -2
- package/build/core/projection/tell/launch-store.js +244 -0
- package/build/core/projection/tell/model.js +3 -3
- package/build/core/projection/tell/store.js +70 -118
- package/build/core/registry.js +22 -87
- package/build/core/renew-build.js +424 -0
- package/build/core/renew-plan.js +239 -0
- package/build/core/renew-rewrite.js +77 -0
- package/build/core/renew.js +295 -520
- package/build/core/repository-ledger/accepted-fold-read.js +19 -0
- package/build/core/repository-ledger/accepted-tail.js +116 -0
- package/build/core/repository-ledger/admission.js +38 -0
- package/build/core/repository-ledger/authoritative-transaction.js +1 -0
- package/build/core/repository-ledger/claim-evidence.js +147 -0
- package/build/core/repository-ledger/codec.js +297 -0
- package/build/core/repository-ledger/current-state-store.js +853 -0
- package/build/core/repository-ledger/fold-repository.js +375 -0
- package/build/core/repository-ledger/fold.js +248 -0
- package/build/core/repository-ledger/git-object-store.js +243 -0
- package/build/core/repository-ledger/history-read.js +15 -0
- package/build/core/repository-ledger/incremental-read.js +153 -0
- package/build/core/repository-ledger/index.js +15 -0
- package/build/core/repository-ledger/inventory-plan.js +75 -0
- package/build/core/repository-ledger/inventory.js +310 -0
- package/build/core/repository-ledger/publication-admission.js +125 -0
- package/build/core/repository-ledger/publication.js +353 -0
- package/build/core/repository-ledger/read-model.js +469 -0
- package/build/core/repository-ledger/transaction-membership.js +78 -0
- package/build/core/repository-ledger/traversal.js +404 -0
- package/build/core/repository-ledger/write-transaction.js +339 -0
- package/build/core/seal.js +168 -161
- package/build/core/settlement/claim-delivery.js +42 -215
- package/build/core/settlement/claim.js +235 -153
- package/build/core/settlement/index.js +4 -4
- package/build/core/settlement/petition-claim-gates.js +52 -33
- package/build/core/settlement/petition-forfeit.js +12 -5
- package/build/core/settlement/petition-head-guard.js +8 -5
- package/build/core/settlement/petition-preview.js +68 -56
- package/build/core/settlement/petition-window.js +50 -0
- package/build/core/settlement/petition.js +252 -131
- package/build/core/settlement/queue-read-model.js +72 -95
- package/build/core/settlement/queue-seat-allocation.js +35 -126
- package/build/core/settlement/queue.js +1 -1
- package/build/core/settlement/settlement.js +172 -80
- package/build/core/settlement/verdict.js +112 -66
- package/build/core/settlement/verification-coordination.js +305 -0
- package/build/core/settlement/verification-supervisor.js +275 -0
- package/build/core/settlement/verification.js +398 -31
- package/build/core/status/board.js +125 -127
- package/build/core/status/lifecycle.js +7 -80
- package/build/core/structured-query.js +23 -0
- package/build/core/target-ref.js +1 -1
- package/build/core/task/board.js +59 -24
- package/build/core/task/commands.js +181 -33
- package/build/core/task/coordinate.js +56 -0
- package/build/core/task/document.js +25 -9
- package/build/core/task/index.js +7 -4
- package/build/core/task/query.js +17 -27
- package/build/core/task/settlement-git.js +164 -179
- package/build/core/task/settlement-policy.js +15 -11
- package/build/core/task/source-board.js +31 -13
- package/build/core/task/task-bind-preparation.js +193 -0
- package/build/core/task/task-contract.js +102 -193
- package/build/core/task/task-file-transaction.js +171 -0
- package/build/core/task/task-git-runtime.js +76 -14
- package/build/core/task/task-git-store.js +68 -169
- package/build/core/task/task-store-repository.js +13 -6
- package/build/core/task/task-worktree.js +6 -33
- package/build/core/task/task.js +1 -1
- package/build/core/task/tree.js +3 -3
- package/build/core/task/validation.js +4 -3
- package/build/core/transcripts.js +93 -1
- package/build/core/worktree-bootstrap.js +44 -36
- package/build/core/worktree-path.js +210 -77
- package/build/flow-error.js +7 -7
- package/build/generated/version.js +2 -2
- package/build/git/core.js +76 -13
- package/build/git/refs.js +168 -46
- package/build/git/streaming-batch.js +73 -13
- package/package.json +1 -1
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +3 -3
- package/skills/keiyaku-task/SKILL.md +4 -2
- package/skills/keiyaku-workflow/SKILL.md +88 -203
- package/build/core/entry.js +0 -305
- package/build/core/ledger-batch.js +0 -194
- package/build/core/ledger.js +0 -84
- package/build/core/projection/leash.js +0 -87
- package/build/core/ref-log.js +0 -119
- package/build/core/renew-session.js +0 -128
- package/build/core/status/ledger-batch.js +0 -1
- package/build/core/status/reconciliation.js +0 -137
|
@@ -5,17 +5,18 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { heartPath } from "./heart.js";
|
|
7
7
|
export { AGENT_ACTIVITY_WINDOW_SIZE, foldAgentActivity, } from "./projection-activity.js";
|
|
8
|
-
export { assertProjectionAlias, isProjectionAlias, moveProjectionAlias, projectionAliasRoot, readProjectionAlias, } from "./projection-alias.js";
|
|
8
|
+
export { assertProjectionAlias, isProjectionAlias, moveProjectionAlias, projectionAliasRoot, projectionAliasRootAtCoordinate, readProjectionAlias, readProjectionAliasAtRoot, } from "./projection-alias.js";
|
|
9
9
|
export { resolveProjectionCoordinate } from "./projection-coordinate.js";
|
|
10
|
-
export { appendGenerationEvent, executionEventsPath, isProjectionId, isPublishedProjection, isoFromNowMs, projectionDir, projectionRoot, readProjectionEvents, } from "./projection-core.js";
|
|
10
|
+
export { appendGenerationEvent, executionEventsPath, isProjectionId, isPublishedProjection, isoFromNowMs, projectionDir, projectionDirAtCoordinate, projectionRoot, readProjectionEvents, readGenerationEventsWithRetention, } from "./projection-core.js";
|
|
11
11
|
export { readProjectionIdentity } from "./projection-identity.js";
|
|
12
12
|
export { interruptProjectionGeneration, killProjectionGeneration } from "./projection-kill.js";
|
|
13
13
|
export { observeProjectionLife, observeProjectionLifeSnapshot, } from "./projection-life-observer.js";
|
|
14
14
|
export { mintProjection, mintRepositoryProjection, ProjectionMintCollisionError, } from "./projection-mint.js";
|
|
15
15
|
export { acquireProjectionRunnerLock, acquireProjectionRunnerSettlementLock, acquireProjectionRunnerTransferTarget, initializeProjectionRunnerLockDatabase, isProjectionRunnerLockPlatformSupported, observeProjectionRunnerLock, projectionRunnerLockPath, } from "./projection-runner-lock.js";
|
|
16
16
|
export { hasStrandableProjectionGeneration, prioritizeProjectionStatusRows, readAkumaNonterminalProjectionStatus, readExactProjectionStatus, readOperationalProjectionStatusBoard, } from "./projection-status.js";
|
|
17
|
+
export { PROJECTION_HISTORY_FILTER_COMPLETION, PROJECTION_HISTORY_FILTER_FIELDS, PROJECTION_HISTORY_FILTER_GRAMMAR, parseProjectionHistoryFilter, parseProjectionHistorySort, readProjectionHistoryAddress, readExactProjectionHistory, readProjectionHistory, resolveProjectionHistoryAddress, selectProjectionHistory, } from "./projection-history.js";
|
|
17
18
|
export { projectTerminalFailure, } from "./projection-terminal-failure.js";
|
|
18
|
-
export { snapshotCommissionProjectionIds, waitForProjection, waitForProjectionSet, } from "./projection-wait.js";
|
|
19
|
+
export { snapshotCommissionProjectionIds, snapshotCommissionProjectionIdsAtCoordinate, waitForProjection, waitForProjectionSet, } from "./projection-wait.js";
|
|
19
20
|
export { assertTellEffortSupported, assertProjectionTellable, tellProjection, } from "./projection-wake.js";
|
|
20
21
|
export { openProjectionGenerationStore, openProjectionGenerationStoreReadOnly, ProjectionGenerationStore, } from "./generation/store.js";
|
|
21
22
|
export { createProjectionExecutionId } from "./generation/projection-generation-identity.js";
|
|
@@ -24,4 +25,4 @@ export { projectionGenerationRunnerArgv, spawnProjectionGenerationRunner, } from
|
|
|
24
25
|
export { runProjectionGeneration, } from "./generation/projection-generation-runner.js";
|
|
25
26
|
export { executeProjectionGeneration, prepareProjectionGenerationExecution, } from "./generation/projection-generation-execution.js";
|
|
26
27
|
export { runProjectionGenerationRuntime } from "./generation/projection-generation-runtime.js";
|
|
27
|
-
export { claimFencedTells, claimTellToInflight,
|
|
28
|
+
export { bindTellLaunchReservation, claimAndReserveFencedTells, claimFencedTells, claimTellToInflight, listTellLaunchBatch, listTellLaunchAdmissions, isTellLaunchAdmissionMember, listTellIds, markTellSubmitted, recordTellReceipt, recordTellReceiptCapabilities, readTellReceiptCapabilities, readPendingTellWindow, readProjectionTellCounts, readTellOriginal, readTellSubmitted, writeInboxTell, } from "./tell/store.js";
|
|
@@ -40,7 +40,7 @@ function sortEvents(events) {
|
|
|
40
40
|
.map(({ event, order }) => ({ event, order }));
|
|
41
41
|
}
|
|
42
42
|
/** Fold the provider-neutral event ledger once into the bounded UI activity model. */
|
|
43
|
-
export function foldAgentActivity(events) {
|
|
43
|
+
export function foldAgentActivity(events, retentionOverride) {
|
|
44
44
|
const sorted = sortEvents(events);
|
|
45
45
|
const latestActivity = new Map();
|
|
46
46
|
const firstActivityCall = new Map();
|
|
@@ -56,13 +56,19 @@ export function foldAgentActivity(events) {
|
|
|
56
56
|
let latestPlan;
|
|
57
57
|
let diagnostic;
|
|
58
58
|
let failure;
|
|
59
|
+
let compacted = false;
|
|
59
60
|
for (const indexed of sorted) {
|
|
60
61
|
const event = indexed.event;
|
|
61
62
|
switch (event.type) {
|
|
62
63
|
case "message":
|
|
63
|
-
|
|
64
|
+
{
|
|
65
|
+
const key = JSON.stringify([event.turn, event.id]);
|
|
66
|
+
compacted ||= latestMessage.has(key);
|
|
67
|
+
latestMessage.set(key, indexed);
|
|
68
|
+
}
|
|
64
69
|
break;
|
|
65
70
|
case "activity": {
|
|
71
|
+
compacted ||= latestActivity.has(event.id);
|
|
66
72
|
latestActivity.set(event.id, indexed);
|
|
67
73
|
if (event.phase !== "updated" && !firstActivityCall.has(event.id))
|
|
68
74
|
firstActivityCall.set(event.id, event.call);
|
|
@@ -80,6 +86,7 @@ export function foldAgentActivity(events) {
|
|
|
80
86
|
break;
|
|
81
87
|
}
|
|
82
88
|
case "thought": {
|
|
89
|
+
compacted ||= latestThought.has(event.id);
|
|
83
90
|
latestThought.set(event.id, indexed);
|
|
84
91
|
thoughtEventCount.set(event.id, (thoughtEventCount.get(event.id) ?? 0) + 1);
|
|
85
92
|
const at = eventTime(event.at);
|
|
@@ -88,13 +95,14 @@ export function foldAgentActivity(events) {
|
|
|
88
95
|
break;
|
|
89
96
|
}
|
|
90
97
|
case "warning": {
|
|
91
|
-
const identity = warningIdentity(event.warning)
|
|
98
|
+
const identity = `${event.historyExecutionId ?? ""}:${warningIdentity(event.warning)}`;
|
|
92
99
|
const prior = warnings.get(identity);
|
|
100
|
+
compacted ||= prior !== undefined;
|
|
93
101
|
warnings.set(identity, { latest: indexed, count: (prior?.count ?? 0) + 1 });
|
|
94
102
|
break;
|
|
95
103
|
}
|
|
96
104
|
case "usage":
|
|
97
|
-
usageByTurn.set(event.turn, event);
|
|
105
|
+
usageByTurn.set(event.historyTurnKey ?? String(event.turn), event);
|
|
98
106
|
break;
|
|
99
107
|
case "plan":
|
|
100
108
|
latestPlan = indexed;
|
|
@@ -174,7 +182,7 @@ export function foldAgentActivity(events) {
|
|
|
174
182
|
continue;
|
|
175
183
|
}
|
|
176
184
|
if (event.type === "warning") {
|
|
177
|
-
const aggregate = warnings.get(warningIdentity(event.warning));
|
|
185
|
+
const aggregate = warnings.get(`${event.historyExecutionId ?? ""}:${warningIdentity(event.warning)}`);
|
|
178
186
|
if (aggregate?.latest !== indexed)
|
|
179
187
|
continue;
|
|
180
188
|
settled.push({
|
|
@@ -189,7 +197,7 @@ export function foldAgentActivity(events) {
|
|
|
189
197
|
continue;
|
|
190
198
|
}
|
|
191
199
|
if (event.type === "turn" && event.phase === "completed") {
|
|
192
|
-
const usage = usageByTurn.get(event.turn);
|
|
200
|
+
const usage = usageByTurn.get(event.historyTurnKey ?? String(event.turn));
|
|
193
201
|
turns.push({
|
|
194
202
|
kind: "turn",
|
|
195
203
|
order: indexed.order,
|
|
@@ -211,11 +219,15 @@ export function foldAgentActivity(events) {
|
|
|
211
219
|
settled.sort((left, right) => left.order - right.order);
|
|
212
220
|
pinned.sort((left, right) => left.order - right.order);
|
|
213
221
|
const window = settled.slice(-AGENT_ACTIVITY_WINDOW_SIZE);
|
|
222
|
+
const omittedSettledCount = Math.max(0, settled.length - window.length);
|
|
214
223
|
const visibleOrders = [...window, ...pinned].map((row) => row.order);
|
|
215
224
|
const relevantTurns = visibleOrders.length === 0
|
|
216
225
|
? turns.slice(-1)
|
|
217
226
|
: turns.filter((row) => row.order >= Math.min(...visibleOrders));
|
|
218
227
|
const timeline = [...window, ...relevantTurns, ...pinned].sort((left, right) => left.order - right.order);
|
|
228
|
+
const retainedTimeline = [...settled, ...turns, ...pinned].sort((left, right) => left.order - right.order);
|
|
229
|
+
const truncated = retainedTimeline.some((row) => (row.kind === "ran" || row.kind === "thought") && row.truncated);
|
|
230
|
+
const bounded = sorted.some(({ event }) => event.type === "truncation");
|
|
219
231
|
let plan;
|
|
220
232
|
if (latestPlan?.event.type === "plan") {
|
|
221
233
|
const event = latestPlan.event;
|
|
@@ -232,8 +244,17 @@ export function foldAgentActivity(events) {
|
|
|
232
244
|
}
|
|
233
245
|
return {
|
|
234
246
|
window,
|
|
247
|
+
omittedSettledCount,
|
|
235
248
|
pinned,
|
|
236
249
|
timeline,
|
|
250
|
+
retainedTimeline,
|
|
251
|
+
retention: {
|
|
252
|
+
state: retentionOverride ?? (bounded ? "bounded" : truncated ? "truncated" : compacted ? "compacted" : "complete"),
|
|
253
|
+
retainedCount: retainedTimeline.length,
|
|
254
|
+
range: retainedTimeline.length > 0
|
|
255
|
+
? { first: retainedTimeline[0].order, last: retainedTimeline.at(-1).order }
|
|
256
|
+
: null,
|
|
257
|
+
},
|
|
237
258
|
ledgerActivities,
|
|
238
259
|
ledgerTurns: turns,
|
|
239
260
|
...(plan ? { plan } : {}),
|
|
@@ -246,7 +267,7 @@ export function foldAgentActivity(events) {
|
|
|
246
267
|
* prose. Diagnostic and fail-event text remains available to artifact/internal
|
|
247
268
|
* consumers through the full fold, but has no JSON or human projection path.
|
|
248
269
|
*/
|
|
249
|
-
export function foldPublicProjectionActivity(events) {
|
|
250
|
-
const { diagnostic: _diagnostic, failure: _failure, ...activity } = foldAgentActivity(events);
|
|
270
|
+
export function foldPublicProjectionActivity(events, retentionOverride) {
|
|
271
|
+
const { diagnostic: _diagnostic, failure: _failure, ...activity } = foldAgentActivity(events, retentionOverride);
|
|
251
272
|
return activity;
|
|
252
273
|
}
|
|
@@ -3,7 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { isErrnoException } from "../../errno.js";
|
|
4
4
|
import { syncDirectorySync } from "../../fs/durability.js";
|
|
5
5
|
import { ProjectionStateError, randomHex8 } from "../atomic-publish.js";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveProjectionCoordinate } from "./projection-coordinate.js";
|
|
7
7
|
import { isProjectionId } from "./projection-core.js";
|
|
8
8
|
export const PROJECTION_ALIAS_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
9
9
|
const MAX_ALIAS_REF_BYTES = 1024;
|
|
@@ -16,12 +16,18 @@ export function assertProjectionAlias(value) {
|
|
|
16
16
|
}
|
|
17
17
|
return value;
|
|
18
18
|
}
|
|
19
|
+
export function projectionAliasRootAtCoordinate(coordinate) {
|
|
20
|
+
return path.join(coordinate.physicalRoot, ".keiyaku", "projection-alias");
|
|
21
|
+
}
|
|
19
22
|
export async function projectionAliasRoot(cwd) {
|
|
20
|
-
return
|
|
23
|
+
return projectionAliasRootAtCoordinate(await resolveProjectionCoordinate(cwd));
|
|
21
24
|
}
|
|
22
|
-
|
|
25
|
+
function projectionAliasPathAtRoot(root, alias) {
|
|
23
26
|
assertProjectionAlias(alias);
|
|
24
|
-
return path.join(
|
|
27
|
+
return path.join(root, alias);
|
|
28
|
+
}
|
|
29
|
+
export async function projectionAliasPath(cwd, alias) {
|
|
30
|
+
return projectionAliasPathAtRoot(await projectionAliasRoot(cwd), alias);
|
|
25
31
|
}
|
|
26
32
|
function invalidAliasRef(filePath) {
|
|
27
33
|
return new ProjectionStateError(`invalid projection alias ref: ${filePath}`);
|
|
@@ -62,8 +68,8 @@ function readBoundedRegularAliasRef(filePath) {
|
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
/** Undefined means no ref; malformed refs fail closed with their exact sidecar path. */
|
|
65
|
-
export async function
|
|
66
|
-
const filePath =
|
|
71
|
+
export async function readProjectionAliasAtRoot(root, alias) {
|
|
72
|
+
const filePath = projectionAliasPathAtRoot(root, alias);
|
|
67
73
|
const content = readBoundedRegularAliasRef(filePath);
|
|
68
74
|
if (content === undefined)
|
|
69
75
|
return undefined;
|
|
@@ -74,15 +80,18 @@ export async function readProjectionAlias(cwd, alias) {
|
|
|
74
80
|
throw invalidAliasRef(filePath);
|
|
75
81
|
return id;
|
|
76
82
|
}
|
|
83
|
+
/** Cwd-facing compatibility entry point; multi-alias callers should reuse a resolved root. */
|
|
84
|
+
export async function readProjectionAlias(cwd, alias) {
|
|
85
|
+
return readProjectionAliasAtRoot(await projectionAliasRoot(cwd), alias);
|
|
86
|
+
}
|
|
77
87
|
/** Atomically replace one alias ref. Aliases intentionally have no multi-ref transaction. */
|
|
78
|
-
|
|
88
|
+
async function moveProjectionAliasAtRoot(root, alias, id) {
|
|
79
89
|
assertProjectionAlias(alias);
|
|
80
90
|
if (!isProjectionId(id))
|
|
81
91
|
throw new ProjectionStateError(`invalid projection id: ${id}`);
|
|
82
|
-
const previous = await
|
|
83
|
-
const root = await projectionAliasRoot(cwd);
|
|
92
|
+
const previous = await readProjectionAliasAtRoot(root, alias);
|
|
84
93
|
fs.mkdirSync(root, { recursive: true });
|
|
85
|
-
const target =
|
|
94
|
+
const target = projectionAliasPathAtRoot(root, alias);
|
|
86
95
|
let temp;
|
|
87
96
|
try {
|
|
88
97
|
for (let attempt = 0; attempt < 16; attempt += 1) {
|
|
@@ -116,3 +125,7 @@ export async function moveProjectionAlias(cwd, alias, id) {
|
|
|
116
125
|
}
|
|
117
126
|
return previous;
|
|
118
127
|
}
|
|
128
|
+
/** Cwd-facing compatibility entry point; writers with a resolved root avoid rediscovery. */
|
|
129
|
+
export async function moveProjectionAlias(cwd, alias, id) {
|
|
130
|
+
return moveProjectionAliasAtRoot(await projectionAliasRoot(cwd), alias, id);
|
|
131
|
+
}
|
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { isErrnoException } from "../../errno.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveProjectionCoordinate } from "./projection-coordinate.js";
|
|
5
5
|
import { ProjectionStateError, } from "../atomic-publish.js";
|
|
6
6
|
export { atomicPublishFile, ProjectionStateError, randomHex8 } from "../atomic-publish.js";
|
|
7
7
|
export { isTellCausallyConsumed, } from "./tell/model.js";
|
|
8
|
-
export { claimAllInbox, claimFencedTells, claimTellToInflight, listTellIds,
|
|
8
|
+
export { bindTellLaunchReservation, claimAllInbox, claimAndReserveFencedTells, claimFencedTells, listTellLaunchBatch, listTellLaunchAdmissions, isTellLaunchAdmissionMember, claimTellToInflight, listTellIds, markTellSubmitted, recordTellReceiptCapabilities, recordTellReceipt, readTellReceiptCapabilities, readTellOriginal, readTellSubmitted, snapshotPendingTells, writeInboxTell, } from "./tell/store.js";
|
|
9
9
|
/** Relative segments for `.keiyaku/projection`. */
|
|
10
10
|
export const PROJECTION_ROOT_SEGMENTS = [".keiyaku", "projection"];
|
|
11
11
|
export const PROJECTION_ID_PATTERN = /^[a-zA-Z0-9]+(?:[.-][a-zA-Z0-9]+)*\/[0-9a-f]{8}$/;
|
|
12
12
|
export function isProjectionId(value) {
|
|
13
13
|
return PROJECTION_ID_PATTERN.test(value);
|
|
14
14
|
}
|
|
15
|
+
/** Derive one projection storage root from already-resolved repository authority. */
|
|
16
|
+
export function projectionRootAtCoordinate(coordinate) {
|
|
17
|
+
return path.join(coordinate.physicalRoot, ...PROJECTION_ROOT_SEGMENTS);
|
|
18
|
+
}
|
|
15
19
|
export async function projectionRoot(cwd) {
|
|
16
|
-
return
|
|
20
|
+
return projectionRootAtCoordinate(await resolveProjectionCoordinate(cwd));
|
|
17
21
|
}
|
|
18
|
-
|
|
22
|
+
/** Derive one projection directory from already-resolved repository authority. */
|
|
23
|
+
export function projectionDirAtCoordinate(coordinate, id) {
|
|
19
24
|
if (!isProjectionId(id))
|
|
20
25
|
throw new ProjectionStateError(`invalid projection id: ${id}`);
|
|
21
26
|
const [akuma, hex] = id.split("/");
|
|
22
|
-
return path.join(
|
|
27
|
+
return path.join(projectionRootAtCoordinate(coordinate), akuma, hex);
|
|
28
|
+
}
|
|
29
|
+
export async function projectionDir(cwd, id) {
|
|
30
|
+
if (!isProjectionId(id))
|
|
31
|
+
throw new ProjectionStateError(`invalid projection id: ${id}`);
|
|
32
|
+
return projectionDirAtCoordinate(await resolveProjectionCoordinate(cwd), id);
|
|
23
33
|
}
|
|
24
34
|
export function encodeProjectionJson(value) {
|
|
25
35
|
return `${JSON.stringify(value)}\n`;
|
|
@@ -59,13 +69,17 @@ export function appendGenerationEvent(projectionDirectory, executionId, event) {
|
|
|
59
69
|
* Earlier complete lines remain strict ledger records.
|
|
60
70
|
*/
|
|
61
71
|
export function readGenerationEvents(projectionDirectory, executionId) {
|
|
72
|
+
return readGenerationEventsWithRetention(projectionDirectory, executionId).events;
|
|
73
|
+
}
|
|
74
|
+
/** Distinguishes a deliberately empty ledger from an absent generation ledger. */
|
|
75
|
+
export function readGenerationEventsWithRetention(projectionDirectory, executionId) {
|
|
62
76
|
let content;
|
|
63
77
|
try {
|
|
64
78
|
content = fs.readFileSync(executionEventsPath(projectionDirectory, executionId), "utf8");
|
|
65
79
|
}
|
|
66
80
|
catch (error) {
|
|
67
81
|
if (isErrnoException(error) && error.code === "ENOENT")
|
|
68
|
-
return [];
|
|
82
|
+
return { events: [], retention: "unavailable" };
|
|
69
83
|
throw error;
|
|
70
84
|
}
|
|
71
85
|
const lines = content.split("\n");
|
|
@@ -83,7 +97,7 @@ export function readGenerationEvents(projectionDirectory, executionId) {
|
|
|
83
97
|
// A concurrent append can leave only this final record incomplete.
|
|
84
98
|
}
|
|
85
99
|
}
|
|
86
|
-
return events;
|
|
100
|
+
return { events, retention: "available" };
|
|
87
101
|
}
|
|
88
102
|
export function readProjectionEvents(projectionDirectory) {
|
|
89
103
|
let entries;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { claimAllInbox, listTellIds, markTellSubmitted,
|
|
1
|
+
import { claimAllInbox, isTellLaunchAdmissionMember, listTellLaunchAdmissions, listTellIds, markTellSubmitted, bindTellLaunchReservation, recordTellReceiptCapabilities, recordTellReceipt, readTellSubmitted, readTellOriginal, isTellCausallyConsumed, appendGenerationEvent, } from "./projection-core.js";
|
|
2
2
|
import { openProjectionTellObserver, } from "./tell/database.js";
|
|
3
3
|
const LIVE_TELL_DELIVERY_THROTTLE_MS = 200;
|
|
4
4
|
export function renderProjectionTellFrame(tellId, text) {
|
|
5
|
-
|
|
5
|
+
void tellId;
|
|
6
|
+
return text;
|
|
6
7
|
}
|
|
7
|
-
function submitEligible(projectionDirectory, executionId, control, requireInbox, submitting, submissions, excludedTellIds, observer,
|
|
8
|
+
function submitEligible(projectionDirectory, executionId, control, requireInbox, submitting, submissions, excludedTellIds, observer, pendingReceipts, pendingFenceReceipts) {
|
|
8
9
|
if (requireInbox && !observer?.hasInbox())
|
|
9
10
|
return;
|
|
10
11
|
claimAllInbox(projectionDirectory);
|
|
@@ -27,27 +28,53 @@ function submitEligible(projectionDirectory, executionId, control, requireInbox,
|
|
|
27
28
|
if (!ack)
|
|
28
29
|
throw new Error("provider enqueue resolved without TellSubmitAck");
|
|
29
30
|
markTellSubmitted(projectionDirectory, tellId, { executionId, fence: ack.fence });
|
|
30
|
-
|
|
31
|
-
if (!pending)
|
|
32
|
-
return;
|
|
33
|
-
for (const evidence of pending) {
|
|
34
|
-
if (isTellCausallyConsumed(ack.fence, evidence)) {
|
|
35
|
-
markTellConsumed(projectionDirectory, tellId);
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
pendingCompletionEvidence.delete(tellId);
|
|
31
|
+
reconcileAcknowledgedTell(projectionDirectory, executionId, tellId, ack.fence, pendingReceipts, pendingFenceReceipts);
|
|
40
32
|
})
|
|
41
33
|
.catch(() => {
|
|
42
34
|
// Leave in inflight for the next checkpoint or ingress opportunity.
|
|
43
35
|
// Reject means this crossing never accepted the tell; drop stale evidence.
|
|
44
|
-
|
|
36
|
+
pendingReceipts.delete(tellId);
|
|
45
37
|
})
|
|
46
38
|
.finally(() => submitting.delete(tellId));
|
|
47
39
|
submissions.add(submission);
|
|
48
40
|
void submission.finally(() => submissions.delete(submission));
|
|
49
41
|
}
|
|
50
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* An acknowledgement establishes the submission fence. Native exact and fence
|
|
45
|
+
* evidence may arrive on either side of that acknowledgement, so both buffers
|
|
46
|
+
* reduce through this one monotonic path. Exact visibility runs first only to
|
|
47
|
+
* supply the required heart predecessor for an already-buffered consumption.
|
|
48
|
+
*/
|
|
49
|
+
function reconcileAcknowledgedTell(projectionDirectory, executionId, tellId, submissionFence, pendingExactReceipts, pendingFenceReceipts) {
|
|
50
|
+
for (const receipt of pendingExactReceipts.get(tellId) ?? []) {
|
|
51
|
+
const launchInput = "launchInput" in receipt ? receipt.launchInput : undefined;
|
|
52
|
+
recordTellReceipt(projectionDirectory, {
|
|
53
|
+
tellId,
|
|
54
|
+
executionId,
|
|
55
|
+
stage: receipt.stage,
|
|
56
|
+
correlation: launchInput ? "inherited" : "exact",
|
|
57
|
+
...(launchInput ? { fence: launchInput.fence } : {}),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
pendingExactReceipts.delete(tellId);
|
|
61
|
+
const submitted = readTellSubmitted(projectionDirectory, tellId);
|
|
62
|
+
if (isTellLaunchAdmissionMember(projectionDirectory, executionId, tellId))
|
|
63
|
+
return;
|
|
64
|
+
for (const receipt of pendingFenceReceipts) {
|
|
65
|
+
if (receipt.correlation.kind !== "fence")
|
|
66
|
+
continue;
|
|
67
|
+
if (!isTellCausallyConsumed(submissionFence, receipt.correlation.fence))
|
|
68
|
+
continue;
|
|
69
|
+
recordTellReceipt(projectionDirectory, {
|
|
70
|
+
tellId,
|
|
71
|
+
executionId,
|
|
72
|
+
stage: receipt.stage,
|
|
73
|
+
correlation: submitted.replayedFrom?.length ? "inherited" : "fence",
|
|
74
|
+
fence: receipt.correlation.fence,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
51
78
|
export function createLiveTellDeliveryController(projectionDirectory, executionId, dependencies = {}) {
|
|
52
79
|
const now = dependencies.now ?? Date.now;
|
|
53
80
|
const setTimer = dependencies.setTimer ?? ((callback, delayMs) => setTimeout(callback, delayMs));
|
|
@@ -55,9 +82,12 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
55
82
|
const openObserver = dependencies.openObserver ?? openProjectionTellObserver;
|
|
56
83
|
const submitting = new Set();
|
|
57
84
|
const submissions = new Set();
|
|
58
|
-
// In-memory only: bridges
|
|
59
|
-
const
|
|
60
|
-
|
|
85
|
+
// In-memory only: bridges a native exact receipt that races its enqueue ack.
|
|
86
|
+
const pendingReceipts = new Map();
|
|
87
|
+
// Native completion can race the steer RPC acknowledgement. The receipt is
|
|
88
|
+
// retained until each acknowledged fence can be reconciled causally.
|
|
89
|
+
const pendingFenceReceipts = [];
|
|
90
|
+
const initial = new Set(dependencies.reservedLaunchTellIds ?? []);
|
|
61
91
|
let observer;
|
|
62
92
|
let timer;
|
|
63
93
|
let nextOpportunityAt = 0;
|
|
@@ -102,7 +132,7 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
102
132
|
try {
|
|
103
133
|
observer ??= openObserver(projectionDirectory);
|
|
104
134
|
if (observer.hasDataVersionChanged()) {
|
|
105
|
-
submitEligible(projectionDirectory, executionId, control, true, submitting, submissions, initial, observer,
|
|
135
|
+
submitEligible(projectionDirectory, executionId, control, true, submitting, submissions, initial, observer, pendingReceipts, pendingFenceReceipts);
|
|
106
136
|
}
|
|
107
137
|
}
|
|
108
138
|
catch {
|
|
@@ -140,29 +170,39 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
140
170
|
return;
|
|
141
171
|
latestControl = control;
|
|
142
172
|
cancelOpportunity();
|
|
143
|
-
|
|
144
|
-
|
|
173
|
+
submitEligible(projectionDirectory, executionId, control, false, submitting, submissions, initial, observer, pendingReceipts, pendingFenceReceipts);
|
|
174
|
+
},
|
|
175
|
+
receipt(receipt) {
|
|
176
|
+
if (closed)
|
|
177
|
+
return;
|
|
178
|
+
if (receipt.correlation.kind === "exact") {
|
|
179
|
+
const tellId = receipt.correlation.tellId;
|
|
180
|
+
const launchInput = "launchInput" in receipt ? receipt.launchInput : undefined;
|
|
181
|
+
if (submitting.has(tellId)) {
|
|
182
|
+
const pending = pendingReceipts.get(tellId) ?? [];
|
|
183
|
+
pending.push(receipt);
|
|
184
|
+
pendingReceipts.set(tellId, pending);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
recordTellReceipt(projectionDirectory, {
|
|
188
|
+
tellId,
|
|
145
189
|
executionId,
|
|
146
|
-
|
|
190
|
+
stage: receipt.stage,
|
|
191
|
+
correlation: launchInput ? "inherited" : "exact",
|
|
192
|
+
...(launchInput ? { fence: launchInput.fence } : {}),
|
|
147
193
|
});
|
|
148
|
-
initial.delete(tellId);
|
|
149
|
-
}
|
|
150
|
-
submitEligible(projectionDirectory, executionId, control, false, submitting, submissions, initial, observer, pendingCompletionEvidence);
|
|
151
|
-
if (!checkpoint.consumptionEvidence)
|
|
152
194
|
return;
|
|
153
|
-
for (const tellId of listTellIds(projectionDirectory, "submitted")) {
|
|
154
|
-
const submitted = readTellSubmitted(projectionDirectory, tellId);
|
|
155
|
-
if (submitted.executionId === executionId && submitted.fence && isTellCausallyConsumed(submitted.fence, checkpoint.fence)) {
|
|
156
|
-
markTellConsumed(projectionDirectory, tellId);
|
|
157
|
-
}
|
|
158
195
|
}
|
|
159
|
-
|
|
160
|
-
for (const
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
196
|
+
pendingFenceReceipts.push(receipt);
|
|
197
|
+
for (const state of ["submitted", "seen"]) {
|
|
198
|
+
for (const tellId of listTellIds(projectionDirectory, state)) {
|
|
199
|
+
const submitted = readTellSubmitted(projectionDirectory, tellId);
|
|
200
|
+
if (submitted.executionId !== executionId)
|
|
201
|
+
continue;
|
|
202
|
+
if (isTellLaunchAdmissionMember(projectionDirectory, executionId, tellId))
|
|
203
|
+
continue;
|
|
204
|
+
reconcileAcknowledgedTell(projectionDirectory, executionId, tellId, submitted.fence, pendingReceipts, pendingFenceReceipts);
|
|
205
|
+
}
|
|
166
206
|
}
|
|
167
207
|
},
|
|
168
208
|
async close() {
|
|
@@ -171,7 +211,7 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
171
211
|
cancelOpportunity();
|
|
172
212
|
discardObserver();
|
|
173
213
|
}
|
|
174
|
-
// Do not drop
|
|
214
|
+
// Do not drop pendingReceipts: in-flight acks may still persist a native receipt.
|
|
175
215
|
await Promise.all([...submissions]);
|
|
176
216
|
},
|
|
177
217
|
};
|
|
@@ -191,7 +231,7 @@ export function buildSyncCheckpointCallback(projectionDirectory, executionId) {
|
|
|
191
231
|
*/
|
|
192
232
|
export function createProjectionExecutionObserver(input, dependencies = {}) {
|
|
193
233
|
const appendEvent = dependencies.appendGenerationEvent ?? appendGenerationEvent;
|
|
194
|
-
const tellController = createLiveTellDeliveryController(input.projectionDirectory, input.executionId, {
|
|
234
|
+
const tellController = createLiveTellDeliveryController(input.projectionDirectory, input.executionId, { reservedLaunchTellIds: input.reservedLaunchTellIds });
|
|
195
235
|
let closePromise;
|
|
196
236
|
const observer = {
|
|
197
237
|
onEvent(event) {
|
|
@@ -200,6 +240,18 @@ export function createProjectionExecutionObserver(input, dependencies = {}) {
|
|
|
200
240
|
onCheckpoint(control, checkpoint) {
|
|
201
241
|
tellController.checkpoint(control, checkpoint);
|
|
202
242
|
},
|
|
243
|
+
async onTellReceiptCapabilities(capabilities) {
|
|
244
|
+
recordTellReceiptCapabilities(input.projectionDirectory, input.executionId, capabilities);
|
|
245
|
+
},
|
|
246
|
+
async onLaunchAdmission(admission) {
|
|
247
|
+
bindTellLaunchReservation(input.projectionDirectory, { executionId: input.executionId, ...admission });
|
|
248
|
+
},
|
|
249
|
+
listLaunchAdmissions() {
|
|
250
|
+
return listTellLaunchAdmissions(input.projectionDirectory, input.executionId);
|
|
251
|
+
},
|
|
252
|
+
onTellReceipt(receipt) {
|
|
253
|
+
tellController.receipt(receipt);
|
|
254
|
+
},
|
|
203
255
|
onDeliveryOpportunity(control) {
|
|
204
256
|
tellController.requestDelivery(control);
|
|
205
257
|
},
|