@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
|
@@ -131,7 +131,6 @@ export function verdictIfOpen(database, readOnly, input) {
|
|
|
131
131
|
if (input.verdict === "killed") {
|
|
132
132
|
throw new ProjectionGenerationStoreError("verdict 'killed' is reserved to runnerKilledIfRequested and settleKillIfRunnerDead");
|
|
133
133
|
}
|
|
134
|
-
const facts = validateVerdictFacts({ ...(input.facts ?? {}), state: input.verdict }, "verdict facts");
|
|
135
134
|
return writeTransition(database, readOnly, () => {
|
|
136
135
|
const history = readValidatedHistory(database);
|
|
137
136
|
const current = history.current;
|
|
@@ -150,6 +149,7 @@ export function verdictIfOpen(database, readOnly, input) {
|
|
|
150
149
|
if (input.verdict === "launch-failed" && current.adoption) {
|
|
151
150
|
return rejected("already-adopted", current);
|
|
152
151
|
}
|
|
152
|
+
const facts = validateVerdictFacts({ ...(input.facts ?? {}), state: input.verdict, ...(input.terminalAt ? { terminalAt: assertIsoTimestamp(input.terminalAt, "terminalAt") } : {}) }, "verdict facts");
|
|
153
153
|
return committed([appendRecord(database, "verdict", executionId, facts, history.records.length + 1)]);
|
|
154
154
|
});
|
|
155
155
|
}
|
|
@@ -160,6 +160,9 @@ export function supersedeStartupTimeout(database, readOnly, input) {
|
|
|
160
160
|
const startupTimeoutMs = assertPositiveSafeInteger(input.startupTimeoutMs, "startupTimeoutMs");
|
|
161
161
|
const diagnostic = cloneFacts(input.diagnostic, "startup-timeout diagnostic");
|
|
162
162
|
const successorFacts = validateLaunchFacts(input.successorFacts, "successor launch facts");
|
|
163
|
+
const terminalAt = input.terminalAt === undefined
|
|
164
|
+
? undefined
|
|
165
|
+
: assertIsoTimestamp(input.terminalAt, "terminalAt");
|
|
163
166
|
return writeTransition(database, readOnly, () => {
|
|
164
167
|
const history = readValidatedHistory(database);
|
|
165
168
|
const current = history.current;
|
|
@@ -180,7 +183,12 @@ export function supersedeStartupTimeout(database, readOnly, input) {
|
|
|
180
183
|
if (observedAtMs - launchedAtMs < startupTimeoutMs) {
|
|
181
184
|
return rejected("startup-timeout-not-elapsed", current);
|
|
182
185
|
}
|
|
183
|
-
const
|
|
186
|
+
const verdictFactsBase = {
|
|
187
|
+
...diagnostic,
|
|
188
|
+
state: "launch-failed",
|
|
189
|
+
...(terminalAt === undefined ? {} : { terminalAt }),
|
|
190
|
+
};
|
|
191
|
+
const verdictFacts = validateVerdictFacts(verdictFactsBase, "startup-timeout verdict facts");
|
|
184
192
|
const firstSeq = history.records.length + 1;
|
|
185
193
|
return committed([
|
|
186
194
|
appendRecord(database, "verdict", executionId, verdictFacts, firstSeq),
|
|
@@ -196,6 +204,9 @@ export function replaceDeadRunner(database, readOnly, input) {
|
|
|
196
204
|
throw new ProjectionGenerationStoreError("released runner-lock evidence must not be empty");
|
|
197
205
|
}
|
|
198
206
|
const successorFacts = validateLaunchFacts(input.successorFacts, "dead-runner successor launch facts");
|
|
207
|
+
const terminalAt = input.terminalAt === undefined
|
|
208
|
+
? undefined
|
|
209
|
+
: assertIsoTimestamp(input.terminalAt, "terminalAt");
|
|
199
210
|
return writeTransition(database, readOnly, () => {
|
|
200
211
|
const history = readValidatedHistory(database);
|
|
201
212
|
const current = history.current;
|
|
@@ -212,7 +223,12 @@ export function replaceDeadRunner(database, readOnly, input) {
|
|
|
212
223
|
if (history.records.some((record) => record.kind === "launch" && record.executionId === successorExecutionId)) {
|
|
213
224
|
return rejected("execution-id-already-used", current);
|
|
214
225
|
}
|
|
215
|
-
const
|
|
226
|
+
const verdictFactsBase = {
|
|
227
|
+
state: "lost-runner",
|
|
228
|
+
releasedLockEvidence,
|
|
229
|
+
...(terminalAt === undefined ? {} : { terminalAt }),
|
|
230
|
+
};
|
|
231
|
+
const verdictFacts = validateVerdictFacts(verdictFactsBase, "dead-runner verdict facts");
|
|
216
232
|
const firstSeq = history.records.length + 1;
|
|
217
233
|
return committed([
|
|
218
234
|
appendRecord(database, "verdict", executionId, verdictFacts, firstSeq),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface for the projection package.
|
|
3
|
+
* Only symbols required by current external consumers are re-exported.
|
|
4
|
+
* Package-internal modules must import each other directly, not through this file.
|
|
5
|
+
*/
|
|
6
|
+
export { heartPath } from "./heart.js";
|
|
7
|
+
export { AGENT_ACTIVITY_WINDOW_SIZE, foldAgentActivity, } from "./projection-activity.js";
|
|
8
|
+
export { assertProjectionAlias, isProjectionAlias, moveProjectionAlias, projectionAliasRoot, readProjectionAlias, } from "./projection-alias.js";
|
|
9
|
+
export { resolveProjectionCoordinate } from "./projection-coordinate.js";
|
|
10
|
+
export { appendGenerationEvent, executionEventsPath, isProjectionId, isPublishedProjection, isoFromNowMs, projectionDir, projectionRoot, readProjectionEvents, } from "./projection-core.js";
|
|
11
|
+
export { readProjectionIdentity } from "./projection-identity.js";
|
|
12
|
+
export { killProjectionGeneration } from "./projection-kill.js";
|
|
13
|
+
export { observeProjectionLife, observeProjectionLifeSnapshot, } from "./projection-life-observer.js";
|
|
14
|
+
export { mintProjection, mintRepositoryProjection, ProjectionMintCollisionError, } from "./projection-mint.js";
|
|
15
|
+
export { acquireProjectionRunnerLock, initializeProjectionRunnerLockDatabase, isProjectionRunnerLockPlatformSupported, observeProjectionRunnerLock, projectionRunnerLockPath, } from "./projection-runner-lock.js";
|
|
16
|
+
export { hasStrandableProjectionGeneration, prioritizeProjectionStatusRows, readProjectionStatusBoard, } from "./projection-status.js";
|
|
17
|
+
export { projectTerminalFailure, } from "./projection-terminal-failure.js";
|
|
18
|
+
export { snapshotCommissionProjectionIds, waitForProjection, waitForProjectionSet, } from "./projection-wait.js";
|
|
19
|
+
export { assertTellEffortSupported, assertProjectionTellable, tellProjection, } from "./projection-wake.js";
|
|
20
|
+
export { openProjectionGenerationStore, openProjectionGenerationStoreReadOnly, ProjectionGenerationStore, } from "./generation/store.js";
|
|
21
|
+
export { createProjectionExecutionId } from "./generation/projection-generation-identity.js";
|
|
22
|
+
export { PROJECTION_ADOPTION_TIMEOUT_MS, startProjectionGeneration, } from "./generation/projection-generation-launcher.js";
|
|
23
|
+
export { projectionGenerationRunnerArgv, spawnProjectionGenerationRunner, } from "./generation/projection-generation-process.js";
|
|
24
|
+
export { runProjectionGeneration, } from "./generation/projection-generation-runner.js";
|
|
25
|
+
export { executeProjectionGeneration } from "./generation/projection-generation-execution.js";
|
|
26
|
+
export { runProjectionGenerationRuntime } from "./generation/projection-generation-runtime.js";
|
|
27
|
+
export { claimFencedTells, claimTellToInflight, demoteSubmittedTellsForReplay, listTellIds, markTellConsumed, markTellSubmitted, readProjectionTellCounts, readTellOriginal, readTellSubmitted, writeInboxTell, } from "./tell/store.js";
|
|
@@ -9,6 +9,9 @@ function duration(first, last) {
|
|
|
9
9
|
return Math.max(0, last - first);
|
|
10
10
|
}
|
|
11
11
|
function warningIdentity(warning) {
|
|
12
|
+
if (warning.reason === "rate-limit") {
|
|
13
|
+
return JSON.stringify(warning);
|
|
14
|
+
}
|
|
12
15
|
if (warning.reason === "retry") {
|
|
13
16
|
return JSON.stringify({
|
|
14
17
|
reason: warning.reason,
|
|
@@ -238,3 +241,12 @@ export function foldAgentActivity(events) {
|
|
|
238
241
|
...(failure ? { failure } : {}),
|
|
239
242
|
};
|
|
240
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Public wait/status activity deliberately excludes provider-origin terminal
|
|
246
|
+
* prose. Diagnostic and fail-event text remains available to artifact/internal
|
|
247
|
+
* consumers through the full fold, but has no JSON or human projection path.
|
|
248
|
+
*/
|
|
249
|
+
export function foldPublicProjectionActivity(events) {
|
|
250
|
+
const { diagnostic: _diagnostic, failure: _failure, ...activity } = foldAgentActivity(events);
|
|
251
|
+
return activity;
|
|
252
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { isErrnoException } from "
|
|
4
|
-
import { syncDirectorySync } from "
|
|
5
|
-
import { ProjectionStateError, randomHex8 } from "
|
|
3
|
+
import { isErrnoException } from "../../errno.js";
|
|
4
|
+
import { syncDirectorySync } from "../../fs/durability.js";
|
|
5
|
+
import { ProjectionStateError, randomHex8 } from "../atomic-publish.js";
|
|
6
6
|
import { projectionCoordinateRoot } 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}$/;
|
|
@@ -16,12 +16,12 @@ export function assertProjectionAlias(value) {
|
|
|
16
16
|
}
|
|
17
17
|
return value;
|
|
18
18
|
}
|
|
19
|
-
export function projectionAliasRoot(cwd) {
|
|
20
|
-
return path.join(projectionCoordinateRoot(cwd), ".keiyaku", "projection-alias");
|
|
19
|
+
export async function projectionAliasRoot(cwd) {
|
|
20
|
+
return path.join(await projectionCoordinateRoot(cwd), ".keiyaku", "projection-alias");
|
|
21
21
|
}
|
|
22
|
-
export function projectionAliasPath(cwd, alias) {
|
|
22
|
+
export async function projectionAliasPath(cwd, alias) {
|
|
23
23
|
assertProjectionAlias(alias);
|
|
24
|
-
return path.join(projectionAliasRoot(cwd), alias);
|
|
24
|
+
return path.join(await projectionAliasRoot(cwd), alias);
|
|
25
25
|
}
|
|
26
26
|
function invalidAliasRef(filePath) {
|
|
27
27
|
return new ProjectionStateError(`invalid projection alias ref: ${filePath}`);
|
|
@@ -62,8 +62,8 @@ function readBoundedRegularAliasRef(filePath) {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
/** Undefined means no ref; malformed refs fail closed with their exact sidecar path. */
|
|
65
|
-
export function readProjectionAlias(cwd, alias) {
|
|
66
|
-
const filePath = projectionAliasPath(cwd, alias);
|
|
65
|
+
export async function readProjectionAlias(cwd, alias) {
|
|
66
|
+
const filePath = await projectionAliasPath(cwd, alias);
|
|
67
67
|
const content = readBoundedRegularAliasRef(filePath);
|
|
68
68
|
if (content === undefined)
|
|
69
69
|
return undefined;
|
|
@@ -75,14 +75,14 @@ export function readProjectionAlias(cwd, alias) {
|
|
|
75
75
|
return id;
|
|
76
76
|
}
|
|
77
77
|
/** Atomically replace one alias ref. Aliases intentionally have no multi-ref transaction. */
|
|
78
|
-
export function moveProjectionAlias(cwd, alias, id) {
|
|
78
|
+
export async function moveProjectionAlias(cwd, alias, id) {
|
|
79
79
|
assertProjectionAlias(alias);
|
|
80
80
|
if (!isProjectionId(id))
|
|
81
81
|
throw new ProjectionStateError(`invalid projection id: ${id}`);
|
|
82
|
-
const previous = readProjectionAlias(cwd, alias);
|
|
83
|
-
const root = projectionAliasRoot(cwd);
|
|
82
|
+
const previous = await readProjectionAlias(cwd, alias);
|
|
83
|
+
const root = await projectionAliasRoot(cwd);
|
|
84
84
|
fs.mkdirSync(root, { recursive: true });
|
|
85
|
-
const target = projectionAliasPath(cwd, alias);
|
|
85
|
+
const target = await projectionAliasPath(cwd, alias);
|
|
86
86
|
let temp;
|
|
87
87
|
try {
|
|
88
88
|
for (let attempt = 0; attempt < 16; attempt += 1) {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { ProjectionStateError } from "../atomic-publish.js";
|
|
3
|
+
import { createGit, isGitExecutableUnavailable, NOT_GIT_REPOSITORY_PATTERNS, } from "../../git/core.js";
|
|
4
|
+
import { normalizeFilesystemCoordinate } from "../../fs/path-coordinate.js";
|
|
5
|
+
import { gitCommonRootPath, resolveGitCommonRoot } from "../../git/path-coordinate.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve projection storage root and authority from one Git probe.
|
|
8
|
+
*
|
|
9
|
+
* A non-bare repository uses the parent of its absolute common Git directory,
|
|
10
|
+
* so every linked worktree shares one coordinate. Repo-free callers retain the
|
|
11
|
+
* existing cwd-local authority until its replacement is legislated.
|
|
12
|
+
*/
|
|
13
|
+
export async function resolveProjectionCoordinate(cwd) {
|
|
14
|
+
cwd = normalizeFilesystemCoordinate(cwd);
|
|
15
|
+
const git = createGit(cwd);
|
|
16
|
+
let response;
|
|
17
|
+
try {
|
|
18
|
+
response = await git.raw([
|
|
19
|
+
"rev-parse",
|
|
20
|
+
"--is-bare-repository",
|
|
21
|
+
"--path-format=absolute",
|
|
22
|
+
"--git-common-dir",
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (isGitExecutableUnavailable(error)) {
|
|
27
|
+
return { physicalRoot: cwd, authority: { kind: "user" } };
|
|
28
|
+
}
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
if (NOT_GIT_REPOSITORY_PATTERNS.some((pattern) => message.includes(pattern))) {
|
|
31
|
+
return { physicalRoot: cwd, authority: { kind: "user" } };
|
|
32
|
+
}
|
|
33
|
+
throw new ProjectionStateError(`cannot resolve projection repository coordinate: ${message}`);
|
|
34
|
+
}
|
|
35
|
+
const [bare, commonDir] = response.trim().split(/\r?\n/);
|
|
36
|
+
const stableRoot = commonDir === undefined ? undefined : gitCommonRootPath(commonDir);
|
|
37
|
+
if (bare !== "false" || !commonDir || !stableRoot || !path.isAbsolute(stableRoot)) {
|
|
38
|
+
return { physicalRoot: cwd, authority: { kind: "user" } };
|
|
39
|
+
}
|
|
40
|
+
let physicalRoot;
|
|
41
|
+
try {
|
|
42
|
+
physicalRoot = await resolveGitCommonRoot(commonDir);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new ProjectionStateError(`cannot resolve projection repository root ${stableRoot}`, { cause: error });
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
physicalRoot,
|
|
49
|
+
authority: { kind: "repository", stableRoot: physicalRoot },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Select the filesystem authority for repository projection state.
|
|
54
|
+
*
|
|
55
|
+
* A non-bare repository uses the parent of its absolute common Git directory,
|
|
56
|
+
* so every linked worktree shares one coordinate. Repo-free callers retain the
|
|
57
|
+
* existing cwd-local authority until its replacement is legislated.
|
|
58
|
+
*/
|
|
59
|
+
export async function projectionCoordinateRoot(cwd) {
|
|
60
|
+
return (await resolveProjectionCoordinate(cwd)).physicalRoot;
|
|
61
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
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 { projectionCoordinateRoot } from "./projection-coordinate.js";
|
|
5
|
-
import { ProjectionStateError, } from "
|
|
6
|
-
export { atomicPublishFile, ProjectionStateError, randomHex8 } from "
|
|
7
|
-
export { isTellCausallyConsumed, } from "./
|
|
8
|
-
export { claimAllInbox, claimFencedTells, claimTellToInflight, demoteSubmittedTellsForReplay, listTellIds, markTellConsumed, markTellSubmitted, readTellOriginal, readTellSubmitted, snapshotPendingTells, writeInboxTell, } from "./
|
|
5
|
+
import { ProjectionStateError, } from "../atomic-publish.js";
|
|
6
|
+
export { atomicPublishFile, ProjectionStateError, randomHex8 } from "../atomic-publish.js";
|
|
7
|
+
export { isTellCausallyConsumed, } from "./tell/model.js";
|
|
8
|
+
export { claimAllInbox, claimFencedTells, claimTellToInflight, demoteSubmittedTellsForReplay, listTellIds, markTellConsumed, markTellSubmitted, 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
|
-
export function projectionRoot(cwd) {
|
|
16
|
-
return path.join(projectionCoordinateRoot(cwd), ...PROJECTION_ROOT_SEGMENTS);
|
|
15
|
+
export async function projectionRoot(cwd) {
|
|
16
|
+
return path.join(await projectionCoordinateRoot(cwd), ...PROJECTION_ROOT_SEGMENTS);
|
|
17
17
|
}
|
|
18
|
-
export function projectionDir(cwd, id) {
|
|
18
|
+
export async function projectionDir(cwd, id) {
|
|
19
19
|
if (!isProjectionId(id))
|
|
20
20
|
throw new ProjectionStateError(`invalid projection id: ${id}`);
|
|
21
21
|
const [akuma, hex] = id.split("/");
|
|
22
|
-
return path.join(projectionRoot(cwd), akuma, hex);
|
|
22
|
+
return path.join(await projectionRoot(cwd), akuma, hex);
|
|
23
23
|
}
|
|
24
24
|
export function encodeProjectionJson(value) {
|
|
25
25
|
return `${JSON.stringify(value)}\n`;
|
package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js}
RENAMED
|
@@ -1,76 +1,27 @@
|
|
|
1
|
-
import { claimAllInbox,
|
|
2
|
-
import { openProjectionTellObserver, } from "./
|
|
3
|
-
function frameTellBodies(projectionDirectory, tellIds) {
|
|
4
|
-
const originals = tellIds.map((tellId) => readTellOriginal(projectionDirectory, "inflight", tellId));
|
|
5
|
-
const frames = originals
|
|
6
|
-
.map((original, index) => `--- tell ${tellIds[index]} ---\n${original.text}`)
|
|
7
|
-
.join("\n\n");
|
|
8
|
-
const effort = originals.reduce((value, original) => original.effort ?? value, undefined);
|
|
9
|
-
return { frames, ...(effort ? { effort } : {}) };
|
|
10
|
-
}
|
|
11
|
-
function operatorBodyForContinuation(prompt, tellFrames, sessionContinuationPromptPrefix) {
|
|
12
|
-
return sessionContinuationPromptPrefix === undefined
|
|
13
|
-
? `${prompt}\n\n${tellFrames}`
|
|
14
|
-
: `${sessionContinuationPromptPrefix}${tellFrames}`;
|
|
15
|
-
}
|
|
16
|
-
/** Tier-2 boundary snapshot. No tells leaves prompt byte-identical. */
|
|
17
|
-
export function snapshotReplayPrompt(projectionDirectory, prompt, tellFence, executionId, options = {}) {
|
|
18
|
-
const tellIds = claimFencedTells(projectionDirectory, tellFence, executionId);
|
|
19
|
-
if (tellIds.length === 0)
|
|
20
|
-
return { prompt, tellIds };
|
|
21
|
-
const { frames, effort } = frameTellBodies(projectionDirectory, tellIds);
|
|
22
|
-
const nextPrompt = operatorBodyForContinuation(prompt, frames, options.sessionContinuationPromptPrefix);
|
|
23
|
-
return { prompt: nextPrompt, tellIds, ...(effort ? { effort } : {}) };
|
|
24
|
-
}
|
|
25
|
-
/** Tier-2 has no steer acknowledgement: actual driver start is its ordinal-zero submission point. */
|
|
26
|
-
export function markReplayStarted(projectionDirectory, executionId, tellIds) {
|
|
27
|
-
for (const tellId of tellIds) {
|
|
28
|
-
if (listTellIds(projectionDirectory, "inflight").includes(tellId)) {
|
|
29
|
-
markTellSubmitted(projectionDirectory, tellId, { executionId, fence: { kind: "ordinal", ordinal: 0 } });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/** A successful replay terminal is checkpoint ordinal one; failures intentionally do not consume. */
|
|
34
|
-
export function markReplayCompleted(projectionDirectory, executionId) {
|
|
35
|
-
for (const tellId of listTellIds(projectionDirectory, "submitted")) {
|
|
36
|
-
const submitted = readTellSubmitted(projectionDirectory, tellId);
|
|
37
|
-
if (submitted.executionId === executionId && submitted.fence && isTellCausallyConsumed(submitted.fence, { kind: "ordinal", ordinal: 1 })) {
|
|
38
|
-
markTellConsumed(projectionDirectory, tellId);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Tier-2's only submission acknowledgement. A created driver is deliberately
|
|
44
|
-
* insufficient: observe the first provider event, or a successful completion
|
|
45
|
-
* from a provider that emitted no events.
|
|
46
|
-
*/
|
|
47
|
-
export function createReplayRunStartGate(projectionDirectory, executionId, tellIds) {
|
|
48
|
-
let started = false;
|
|
49
|
-
const start = () => {
|
|
50
|
-
if (started)
|
|
51
|
-
return;
|
|
52
|
-
markReplayStarted(projectionDirectory, executionId, tellIds);
|
|
53
|
-
started = true;
|
|
54
|
-
};
|
|
55
|
-
return { observeProviderEvent: start, observeSuccessfulCompletion: start };
|
|
56
|
-
}
|
|
1
|
+
import { claimAllInbox, listTellIds, markTellSubmitted, markTellConsumed, readTellSubmitted, readTellOriginal, isTellCausallyConsumed, appendGenerationEvent, } from "./projection-core.js";
|
|
2
|
+
import { openProjectionTellObserver, } from "./tell/database.js";
|
|
57
3
|
const LIVE_TELL_DELIVERY_THROTTLE_MS = 200;
|
|
58
|
-
function
|
|
4
|
+
export function renderProjectionTellFrame(tellId, text) {
|
|
5
|
+
return `--- tell ${tellId} ---\n${text}`;
|
|
6
|
+
}
|
|
7
|
+
function submitEligible(projectionDirectory, executionId, control, requireInbox, submitting, submissions, excludedTellIds, observer, pendingCompletionEvidence) {
|
|
59
8
|
if (requireInbox && !observer?.hasInbox())
|
|
60
9
|
return;
|
|
61
10
|
claimAllInbox(projectionDirectory);
|
|
62
11
|
for (const tellId of listTellIds(projectionDirectory, "inflight")) {
|
|
12
|
+
if (excludedTellIds.has(tellId))
|
|
13
|
+
continue;
|
|
63
14
|
if (submitting.has(tellId))
|
|
64
15
|
continue;
|
|
65
16
|
// Construct before pin: a sync read/build failure must not leave submitting stuck.
|
|
66
17
|
const original = readTellOriginal(projectionDirectory, "inflight", tellId);
|
|
67
18
|
const tell = {
|
|
68
19
|
id: tellId,
|
|
69
|
-
text:
|
|
20
|
+
text: renderProjectionTellFrame(tellId, original.text),
|
|
70
21
|
...(original.effort ? { effort: original.effort } : {}),
|
|
71
22
|
};
|
|
72
23
|
submitting.add(tellId);
|
|
73
|
-
|
|
24
|
+
const submission = Promise.resolve()
|
|
74
25
|
.then(() => control.enqueue(tell))
|
|
75
26
|
.then((ack) => {
|
|
76
27
|
if (!ack)
|
|
@@ -93,6 +44,8 @@ function submitEligible(projectionDirectory, executionId, control, requireInbox,
|
|
|
93
44
|
pendingCompletionEvidence.delete(tellId);
|
|
94
45
|
})
|
|
95
46
|
.finally(() => submitting.delete(tellId));
|
|
47
|
+
submissions.add(submission);
|
|
48
|
+
void submission.finally(() => submissions.delete(submission));
|
|
96
49
|
}
|
|
97
50
|
}
|
|
98
51
|
export function createLiveTellDeliveryController(projectionDirectory, executionId, dependencies = {}) {
|
|
@@ -101,8 +54,10 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
101
54
|
const clearTimer = dependencies.clearTimer ?? ((timer) => clearTimeout(timer));
|
|
102
55
|
const openObserver = dependencies.openObserver ?? openProjectionTellObserver;
|
|
103
56
|
const submitting = new Set();
|
|
57
|
+
const submissions = new Set();
|
|
104
58
|
// In-memory only: bridges completion-before-ack when a tell is still submitting.
|
|
105
59
|
const pendingCompletionEvidence = new Map();
|
|
60
|
+
const initial = new Set(dependencies.initialTellIds);
|
|
106
61
|
let observer;
|
|
107
62
|
let timer;
|
|
108
63
|
let nextOpportunityAt = 0;
|
|
@@ -147,7 +102,7 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
147
102
|
try {
|
|
148
103
|
observer ??= openObserver(projectionDirectory);
|
|
149
104
|
if (observer.hasDataVersionChanged()) {
|
|
150
|
-
submitEligible(projectionDirectory, executionId, control, true, submitting, observer, pendingCompletionEvidence);
|
|
105
|
+
submitEligible(projectionDirectory, executionId, control, true, submitting, submissions, initial, observer, pendingCompletionEvidence);
|
|
151
106
|
}
|
|
152
107
|
}
|
|
153
108
|
catch {
|
|
@@ -185,7 +140,14 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
185
140
|
return;
|
|
186
141
|
latestControl = control;
|
|
187
142
|
cancelOpportunity();
|
|
188
|
-
|
|
143
|
+
for (const tellId of initial) {
|
|
144
|
+
markTellSubmitted(projectionDirectory, tellId, {
|
|
145
|
+
executionId,
|
|
146
|
+
fence: checkpoint.fence,
|
|
147
|
+
});
|
|
148
|
+
initial.delete(tellId);
|
|
149
|
+
}
|
|
150
|
+
submitEligible(projectionDirectory, executionId, control, false, submitting, submissions, initial, observer, pendingCompletionEvidence);
|
|
189
151
|
if (!checkpoint.consumptionEvidence)
|
|
190
152
|
return;
|
|
191
153
|
for (const tellId of listTellIds(projectionDirectory, "submitted")) {
|
|
@@ -203,13 +165,14 @@ export function createLiveTellDeliveryController(projectionDirectory, executionI
|
|
|
203
165
|
pendingCompletionEvidence.set(tellId, [checkpoint.fence]);
|
|
204
166
|
}
|
|
205
167
|
},
|
|
206
|
-
close() {
|
|
207
|
-
if (closed)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
168
|
+
async close() {
|
|
169
|
+
if (!closed) {
|
|
170
|
+
closed = true;
|
|
171
|
+
cancelOpportunity();
|
|
172
|
+
discardObserver();
|
|
173
|
+
}
|
|
212
174
|
// Do not drop pendingCompletionEvidence: in-flight acks may still submit/consume.
|
|
175
|
+
await Promise.all([...submissions]);
|
|
213
176
|
},
|
|
214
177
|
};
|
|
215
178
|
}
|
|
@@ -228,11 +191,10 @@ export function buildSyncCheckpointCallback(projectionDirectory, executionId) {
|
|
|
228
191
|
*/
|
|
229
192
|
export function createProjectionExecutionObserver(input, dependencies = {}) {
|
|
230
193
|
const appendEvent = dependencies.appendGenerationEvent ?? appendGenerationEvent;
|
|
231
|
-
const tellController = createLiveTellDeliveryController(input.projectionDirectory, input.executionId);
|
|
232
|
-
let
|
|
194
|
+
const tellController = createLiveTellDeliveryController(input.projectionDirectory, input.executionId, { initialTellIds: input.initialTellIds });
|
|
195
|
+
let closePromise;
|
|
233
196
|
const observer = {
|
|
234
197
|
onEvent(event) {
|
|
235
|
-
input.replayStartGate?.observeProviderEvent();
|
|
236
198
|
appendEvent(input.projectionDirectory, input.executionId, event);
|
|
237
199
|
},
|
|
238
200
|
onCheckpoint(control, checkpoint) {
|
|
@@ -245,15 +207,12 @@ export function createProjectionExecutionObserver(input, dependencies = {}) {
|
|
|
245
207
|
return {
|
|
246
208
|
observer,
|
|
247
209
|
close() {
|
|
248
|
-
if (
|
|
249
|
-
return;
|
|
250
|
-
|
|
251
|
-
try {
|
|
252
|
-
tellController.close();
|
|
253
|
-
}
|
|
254
|
-
catch {
|
|
210
|
+
if (closePromise)
|
|
211
|
+
return closePromise;
|
|
212
|
+
closePromise = tellController.close().catch(() => {
|
|
255
213
|
// Controller cleanup cannot change provider completion.
|
|
256
|
-
}
|
|
214
|
+
});
|
|
215
|
+
return closePromise;
|
|
257
216
|
},
|
|
258
217
|
};
|
|
259
218
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { openProjectionGenerationStoreReadOnly, } from "./
|
|
1
|
+
import { openProjectionGenerationStoreReadOnly, } from "./generation/store.js";
|
|
2
2
|
/** Read the immutable projection identity from the heart database. */
|
|
3
3
|
export function readProjectionIdentity(projectionDirectory) {
|
|
4
4
|
const heart = openProjectionGenerationStoreReadOnly(projectionDirectory);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { openProjectionGenerationStore } from "./
|
|
1
|
+
import { openProjectionGenerationStore } from "./generation/store.js";
|
|
2
2
|
import { observeProjectionRunnerLock } from "./projection-runner-lock.js";
|
|
3
3
|
function settleReleasedLeash(store, projectionDirectory, executionId) {
|
|
4
4
|
const observation = observeProjectionRunnerLock(projectionDirectory);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { openProjectionGenerationStoreReadOnly, } from "./
|
|
1
|
+
import { isIncompatibleProjectionGenerationStoreError, openProjectionGenerationStoreReadOnly, } from "./generation/store.js";
|
|
2
2
|
import { deriveProjectionLife, selectCurrentGeneration, } from "./projection-life-protocol.js";
|
|
3
3
|
import { observeProjectionRunnerLock } from "./projection-runner-lock.js";
|
|
4
4
|
function errorDetail(error) {
|
|
@@ -25,7 +25,11 @@ export function observeProjectionLifeSnapshot(projectionDirectory, options) {
|
|
|
25
25
|
records = readRecords();
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
|
+
if (isIncompatibleProjectionGenerationStoreError(error)) {
|
|
29
|
+
return { compatibility: "incompatible", diagnostic: errorDetail(error) };
|
|
30
|
+
}
|
|
28
31
|
return {
|
|
32
|
+
compatibility: "current",
|
|
29
33
|
life: {
|
|
30
34
|
phase: "unknown",
|
|
31
35
|
diagnostic: `generation history could not be observed: ${errorDetail(error)}`,
|
|
@@ -35,6 +39,7 @@ export function observeProjectionLifeSnapshot(projectionDirectory, options) {
|
|
|
35
39
|
const current = selectCurrentGeneration(records);
|
|
36
40
|
if (!current || current.verdict || !current.adoption) {
|
|
37
41
|
return {
|
|
42
|
+
compatibility: "current",
|
|
38
43
|
life: deriveProjectionLife({
|
|
39
44
|
records,
|
|
40
45
|
nowMs: options.nowMs,
|
|
@@ -49,7 +54,11 @@ export function observeProjectionLifeSnapshot(projectionDirectory, options) {
|
|
|
49
54
|
after = readRecords();
|
|
50
55
|
}
|
|
51
56
|
catch (error) {
|
|
57
|
+
if (isIncompatibleProjectionGenerationStoreError(error)) {
|
|
58
|
+
return { compatibility: "incompatible", diagnostic: errorDetail(error) };
|
|
59
|
+
}
|
|
52
60
|
return {
|
|
61
|
+
compatibility: "current",
|
|
53
62
|
life: {
|
|
54
63
|
phase: "unknown",
|
|
55
64
|
executionId: current.launch.executionId,
|
|
@@ -62,6 +71,7 @@ export function observeProjectionLifeSnapshot(projectionDirectory, options) {
|
|
|
62
71
|
if (records.length !== after.length || beforeTail !== afterTail)
|
|
63
72
|
continue;
|
|
64
73
|
return {
|
|
74
|
+
compatibility: "current",
|
|
65
75
|
life: deriveProjectionLife({
|
|
66
76
|
records,
|
|
67
77
|
runnerLock: lock.state === "held"
|
|
@@ -76,6 +86,7 @@ export function observeProjectionLifeSnapshot(projectionDirectory, options) {
|
|
|
76
86
|
};
|
|
77
87
|
}
|
|
78
88
|
return {
|
|
89
|
+
compatibility: "current",
|
|
79
90
|
life: {
|
|
80
91
|
phase: "unknown",
|
|
81
92
|
diagnostic: "generation history changed during runner-lock observation",
|
|
@@ -83,5 +94,8 @@ export function observeProjectionLifeSnapshot(projectionDirectory, options) {
|
|
|
83
94
|
};
|
|
84
95
|
}
|
|
85
96
|
export function observeProjectionLife(projectionDirectory, options) {
|
|
86
|
-
|
|
97
|
+
const snapshot = observeProjectionLifeSnapshot(projectionDirectory, options);
|
|
98
|
+
return snapshot.compatibility === "current"
|
|
99
|
+
? snapshot.life
|
|
100
|
+
: { phase: "unknown", diagnostic: snapshot.diagnostic };
|
|
87
101
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { isErrnoException } from "
|
|
4
|
-
import { ProjectionStateError, randomHex8 } from "
|
|
3
|
+
import { isErrnoException } from "../../errno.js";
|
|
4
|
+
import { ProjectionStateError, randomHex8 } from "../atomic-publish.js";
|
|
5
5
|
import { isoFromNowMs, PROJECTION_ROOT_SEGMENTS, projectionDir, projectionRoot, } from "./projection-core.js";
|
|
6
|
-
import { parseExecutionAuthoritySelection, parseExecutionPact, parseExecutionPactFields, } from "
|
|
7
|
-
import { openProjectionGenerationStore } from "./
|
|
6
|
+
import { parseExecutionAuthoritySelection, parseExecutionPact, parseExecutionPactFields, } from "../execution-pact.js";
|
|
7
|
+
import { openProjectionGenerationStore } from "./generation/store.js";
|
|
8
8
|
import { initializeProjectionRunnerLockDatabase } from "./projection-runner-lock.js";
|
|
9
9
|
export class ProjectionMintCollisionError extends Error {
|
|
10
10
|
code = "PROJECTION_MINT_COLLISION";
|
|
@@ -38,7 +38,7 @@ function removeEmptyAkumaRoot(dir) {
|
|
|
38
38
|
* Validate mint inputs that can fail, then reserve one private staging directory.
|
|
39
39
|
* Dot-prefixed staging is never a published projection address.
|
|
40
40
|
*/
|
|
41
|
-
function reserveProjectionDirectory(input) {
|
|
41
|
+
async function reserveProjectionDirectory(input) {
|
|
42
42
|
const slug = assertMintSlug(input.slug);
|
|
43
43
|
if (!Number.isInteger(input.pid) || input.pid < 0) {
|
|
44
44
|
throw new ProjectionStateError("projection pid must be a non-negative integer");
|
|
@@ -50,7 +50,7 @@ function reserveProjectionDirectory(input) {
|
|
|
50
50
|
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
|
|
51
51
|
throw new ProjectionStateError("maxAttempts must be a positive integer");
|
|
52
52
|
}
|
|
53
|
-
const root = projectionRoot(input.cwd);
|
|
53
|
+
const root = await projectionRoot(input.cwd);
|
|
54
54
|
fs.mkdirSync(root, { recursive: true });
|
|
55
55
|
const akumaRoot = path.join(root, slug);
|
|
56
56
|
const createdAkumaRoot = !fs.existsSync(akumaRoot);
|
|
@@ -63,7 +63,7 @@ function reserveProjectionDirectory(input) {
|
|
|
63
63
|
throw new ProjectionStateError(`projection id random segment must be 8 hex chars, got ${hex}`);
|
|
64
64
|
}
|
|
65
65
|
const id = `${slug}/${hex}`;
|
|
66
|
-
const dir = projectionDir(input.cwd, id);
|
|
66
|
+
const dir = await projectionDir(input.cwd, id);
|
|
67
67
|
const stagingDir = path.join(akumaRoot, `.mint-${hex}`);
|
|
68
68
|
if (fs.existsSync(dir))
|
|
69
69
|
continue;
|
|
@@ -132,7 +132,7 @@ function publishReservedProjection(pact, reserved) {
|
|
|
132
132
|
* Mint a user-authority projection directory.
|
|
133
133
|
* Order (closed): validate → reserve staging → heart + leash → atomic rename.
|
|
134
134
|
*/
|
|
135
|
-
export function mintProjection(input) {
|
|
135
|
+
export async function mintProjection(input) {
|
|
136
136
|
const authority = parseExecutionAuthoritySelection(input.authority, "projection identity", "user");
|
|
137
137
|
const fields = parseExecutionPactFields(buildMintPactFields(input));
|
|
138
138
|
const pact = parseExecutionPact({
|
|
@@ -146,7 +146,7 @@ export function mintProjection(input) {
|
|
|
146
146
|
workspaceRoot: fields.workspaceRoot,
|
|
147
147
|
...(fields.effectivePolicy !== undefined ? { effectivePolicy: fields.effectivePolicy } : {}),
|
|
148
148
|
});
|
|
149
|
-
const reserved = reserveProjectionDirectory(input);
|
|
149
|
+
const reserved = await reserveProjectionDirectory(input);
|
|
150
150
|
return publishReservedProjection(pact, reserved);
|
|
151
151
|
}
|
|
152
152
|
/**
|
|
@@ -156,7 +156,7 @@ export function mintProjection(input) {
|
|
|
156
156
|
export async function mintRepositoryProjection(input) {
|
|
157
157
|
parseExecutionAuthoritySelection(input.authority, "projection identity", "repository");
|
|
158
158
|
const fields = parseExecutionPactFields(buildMintPactFields(input));
|
|
159
|
-
const reserved = reserveProjectionDirectory(input);
|
|
159
|
+
const reserved = await reserveProjectionDirectory(input);
|
|
160
160
|
const pact = parseExecutionPact({
|
|
161
161
|
version: fields.version,
|
|
162
162
|
pid: fields.pid,
|