@sema-agent/core 7.6.2 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -6
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/brain/anthropic.js +8 -2
- package/dist/brain/open-responses.js +5 -3
- package/dist/brain/openai.js +31 -8
- package/dist/brain/reasoning.d.ts +32 -0
- package/dist/brain/reasoning.js +18 -0
- package/dist/core/auto-mode-defaults.d.ts +16 -0
- package/dist/core/auto-mode-defaults.js +1 -0
- package/dist/core/auto-mode.d.ts +19 -0
- package/dist/core/auto-mode.js +74 -56
- package/dist/core/checkpoint-execution-record.d.ts +110 -0
- package/dist/core/checkpoint-execution-record.js +49 -0
- package/dist/core/checkpoint-store.d.ts +88 -10
- package/dist/core/checkpoint-store.js +35 -2
- package/dist/core/engine-notice.d.ts +11 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/runner/clock-and-limits.d.ts +117 -0
- package/dist/core/runner/clock-and-limits.js +118 -0
- package/dist/core/runner/contracts.d.ts +10 -0
- package/dist/core/runner/decide-continuation.d.ts +98 -0
- package/dist/core/runner/decide-continuation.js +133 -0
- package/dist/core/runner/execution-record.d.ts +26 -0
- package/dist/core/runner/execution-record.js +19 -0
- package/dist/core/runner/git-leg-delivery.d.ts +28 -0
- package/dist/core/runner/git-leg-delivery.js +94 -0
- package/dist/core/runner/initial-run-state.d.ts +14 -0
- package/dist/core/runner/initial-run-state.js +11 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +17 -0
- package/dist/core/runner/prepare-run-refs.d.ts +0 -12
- package/dist/core/runner/prepare-run-refs.js +0 -5
- package/dist/core/runner/runtask.d.ts +0 -68
- package/dist/core/runner/runtask.js +28 -450
- package/dist/core/runner/steer-admission.d.ts +17 -0
- package/dist/core/runner/steer-admission.js +17 -0
- package/dist/core/runner/tool-end-body.d.ts +71 -0
- package/dist/core/runner/tool-end-body.js +74 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +4 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +85 -0
- package/dist/core/trace.d.ts +24 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/stores/file/checkpoint-store.d.ts +7 -0
- package/dist/stores/file/checkpoint-store.js +20 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +37 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const humanInputOrdinals = new WeakMap();
|
|
2
|
+
export function nextHumanInputSeq(key) {
|
|
3
|
+
let box = humanInputOrdinals.get(key);
|
|
4
|
+
if (box === undefined) {
|
|
5
|
+
box = { n: 0 };
|
|
6
|
+
humanInputOrdinals.set(key, box);
|
|
7
|
+
}
|
|
8
|
+
return ++box.n;
|
|
9
|
+
}
|
|
10
|
+
export function sameAcceptedSteerInput(a, b) {
|
|
11
|
+
return (a.payload === b.payload &&
|
|
12
|
+
a.trusted === b.trusted &&
|
|
13
|
+
a.priority === b.priority &&
|
|
14
|
+
a.actor?.id === b.actor?.id &&
|
|
15
|
+
a.actor?.hostAsserted === b.actor?.hostAsserted &&
|
|
16
|
+
a.actor?.issuer === b.actor?.issuer);
|
|
17
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the run loop derives from a tool call's END, in every leg that closes one: the `tool_end` frame
|
|
3
|
+
* body (the ONE projection the live loop, the resumed batch and the reconcile-recovered orphan all go
|
|
4
|
+
* through), the `toolResult` transcript message the resume engine closes pending calls with, the thin
|
|
5
|
+
* `response` digest the post-tool-batch observer is handed, and the canonical write-tool → reminder-window
|
|
6
|
+
* family the attachment reducer keys on when a write tool ends.
|
|
7
|
+
*
|
|
8
|
+
* Projections over values the caller already holds, with ONE clock read: `toolResultMsg` stamps the message
|
|
9
|
+
* it mints with `Date.now()` (as it did inside the driver — the transcript's timestamp is minted where the
|
|
10
|
+
* message is). Nothing here reads host state through a callback, awaits, or keeps state between calls.
|
|
11
|
+
* Layer-1 machinery, not a driven lane; the prefix rule it follows is written once, on initial-run-state.ts.
|
|
12
|
+
*/
|
|
13
|
+
import { type AgentMessage } from "../../internal/harness.js";
|
|
14
|
+
import type { GateOutcome } from "../gate-outcome.js";
|
|
15
|
+
import { type McpDelivered } from "../mcp-failure.js";
|
|
16
|
+
import type { RecoveredOrphan } from "../session-reconcile.js";
|
|
17
|
+
import type { WriteFamily } from "./turn-attachments.js";
|
|
18
|
+
/** design/134 §3.1b — derive the thin `response` digest from a harness tool result: model-facing text
|
|
19
|
+
* content only (never `details` — the H4 thin-projection discipline), capped with a truncation note. */
|
|
20
|
+
export declare function batchResponseDigest(result: unknown): string | undefined;
|
|
21
|
+
/** The `tool_end` body fields projected from a harness tool result — output/truncated/totalChars via
|
|
22
|
+
* {@link toolOutputFrom} and the CC card via {@link structuredFrom}. Single construction point for BOTH
|
|
23
|
+
* the live loop's frames and the resumed batch's frames (`resolvePendingCall` + the deferred-sibling
|
|
24
|
+
* close): the resumed frames used to carry only `isError`, so a client rendering tool output from frames
|
|
25
|
+
* showed an empty body for every durable-approved call. Same projection = same source as the transcript.
|
|
26
|
+
* Also the one place the gate outcome reaches a frame — see the parameter. */
|
|
27
|
+
export declare function toolEndBodyFrom(result: unknown, isError: boolean,
|
|
28
|
+
/** The gate's record of the pass that admitted or refused this call, supplied by the CALLER of this
|
|
29
|
+
* projection — the live loop reads it off the gate's per-call sideband, the resumed leg off the decide's
|
|
30
|
+
* minted record. Deliberately a parameter and never derived from `result`: a tool's own `details`
|
|
31
|
+
* (which post-tool hooks may also replace) is writable by layers that adjudicate nothing, so reading
|
|
32
|
+
* provenance out of it would let a failing tool claim a person approved it. Omitted ⇒ the call never
|
|
33
|
+
* went through the gate (see the `tool_end.gate` doc, the one home). */
|
|
34
|
+
gate?: GateOutcome,
|
|
35
|
+
/** WHICH call this run's committed durable park is holding ({@link import("./park-commit.js").gatedCallIdOf}), for the frames the
|
|
36
|
+
* abort short-circuits. Same never-derived-from-`result` posture as the outcome above, and for the
|
|
37
|
+
* sharpest version of that reason: this one is an assertion about a DIFFERENT call, so a tool able to
|
|
38
|
+
* author it could point an approval UI at a call nobody is waiting on. Omitted ⇒ no park is holding a
|
|
39
|
+
* call (nothing parked, or the park that did holds none), and the frame then carries no id at all. */
|
|
40
|
+
gatedCallIdOfRun?: string): {
|
|
41
|
+
output?: unknown;
|
|
42
|
+
truncated?: boolean;
|
|
43
|
+
totalChars?: number;
|
|
44
|
+
structured?: unknown;
|
|
45
|
+
errorCode?: string;
|
|
46
|
+
delivered?: McpDelivered;
|
|
47
|
+
gatedCallId?: string;
|
|
48
|
+
gate?: GateOutcome;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* scan-1/A1 — the BODY of the synthetic `tool_end` that closes a reconcile-recovered orphan. ONE
|
|
52
|
+
* construction point for BOTH minting legs (the live-abort loop at the end of a run, and the wake/crash
|
|
53
|
+
* leg's replay at run open), so the two can never disagree about the shape of the same event.
|
|
54
|
+
*
|
|
55
|
+
* Both frames used to carry `isError:true` and NOTHING else: a consumer rendering tool output from the
|
|
56
|
+
* event stream showed an EMPTY body for every interrupted call, even though the persisted transcript
|
|
57
|
+
* (which the model reads) carried the full `[INTERRUPTED]` explanation — the two faces of one call
|
|
58
|
+
* disagreed. The projection goes through the same {@link toolEndBodyFrom} every live tool result uses, so
|
|
59
|
+
* `output` = the persisted model-facing text and `errorCode` = the persisted `details.errorKind`
|
|
60
|
+
* (`interrupted_never_started` / `interrupted_outcome_unknown`) — a consumer discriminates on the code
|
|
61
|
+
* instead of prose-matching. No `structured`: the reconcile mints no CC card (no `details.type`), which
|
|
62
|
+
* `structuredFrom`'s allowlist already enforces.
|
|
63
|
+
*/
|
|
64
|
+
export declare function reconciledToolEndBody(orphan: Pick<RecoveredOrphan, "text" | "errorKind">): ReturnType<typeof toolEndBodyFrom>;
|
|
65
|
+
/** task #51 F2/F3 — the CANONICAL write-tool → reminder-window mapping (CC qFm :480253-480254
|
|
66
|
+
* `a.name === bD || a.name === hF` = TaskCreate/TaskUpdate; BFm :480217-480219 = TodoWrite). Live
|
|
67
|
+
* deployment-alias resolution happens at the call sites (run-local `writeFamilyOf` over the mounted
|
|
68
|
+
* roster); retired-name normalization is gone (RB-476-A, 5.0.0). */
|
|
69
|
+
export declare function writeFamilyOfCanonical(name: string): WriteFamily | undefined;
|
|
70
|
+
/** A `toolResult` transcript message (text content). Used by the resume engine to close pending calls. */
|
|
71
|
+
export declare function toolResultMsg(toolCallId: string, toolName: string, text: string, isError: boolean): AgentMessage;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {} from "../../internal/harness.js";
|
|
2
|
+
import { MCP_DELIVERY_VERDICTS } from "../mcp-failure.js";
|
|
3
|
+
import { TOOL_SEARCH_NAME } from "./tool-disclosure.js";
|
|
4
|
+
import { structuredFrom, toolOutputFrom } from "./tool-output-projection.js";
|
|
5
|
+
const BATCH_RESPONSE_MAX_CHARS = 500;
|
|
6
|
+
export function batchResponseDigest(result) {
|
|
7
|
+
const content = result !== null && typeof result === "object" ? result.content : result;
|
|
8
|
+
if (content === undefined || content === null)
|
|
9
|
+
return undefined;
|
|
10
|
+
let text;
|
|
11
|
+
if (typeof content === "string") {
|
|
12
|
+
text = content;
|
|
13
|
+
}
|
|
14
|
+
else if (Array.isArray(content)) {
|
|
15
|
+
text = content
|
|
16
|
+
.map((c) => (c !== null && typeof c === "object" && typeof c.text === "string" ? c.text : ""))
|
|
17
|
+
.filter((t) => t.length > 0)
|
|
18
|
+
.join("\n");
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
try {
|
|
22
|
+
text = JSON.stringify(content) ?? "";
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (text.length === 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
return text.length > BATCH_RESPONSE_MAX_CHARS
|
|
31
|
+
? `${text.slice(0, BATCH_RESPONSE_MAX_CHARS)}…[+${text.length - BATCH_RESPONSE_MAX_CHARS} chars truncated]`
|
|
32
|
+
: text;
|
|
33
|
+
}
|
|
34
|
+
export function toolEndBodyFrom(result, isError, gate, gatedCallIdOfRun) {
|
|
35
|
+
const o = toolOutputFrom(result);
|
|
36
|
+
const st = structuredFrom(result);
|
|
37
|
+
const det = isError ? result?.details : undefined;
|
|
38
|
+
const codeRaw = det?.code;
|
|
39
|
+
const kindRaw = det?.errorKind;
|
|
40
|
+
const code = typeof codeRaw === "string" ? codeRaw : typeof kindRaw === "string" ? kindRaw : undefined;
|
|
41
|
+
const deliveredRaw = det?.delivered;
|
|
42
|
+
const delivered = typeof deliveredRaw === "string" && MCP_DELIVERY_VERDICTS.includes(deliveredRaw) ? deliveredRaw : undefined;
|
|
43
|
+
const gatedCallId = code === "gate.parked" ? gatedCallIdOfRun : undefined;
|
|
44
|
+
return {
|
|
45
|
+
...(o !== undefined ? { output: o.output, ...(o.truncated ? { truncated: true } : {}), ...(o.totalChars !== undefined ? { totalChars: o.totalChars } : {}) } : {}),
|
|
46
|
+
...(st !== undefined ? { structured: st } : {}),
|
|
47
|
+
...(typeof code === "string" ? { errorCode: code } : {}),
|
|
48
|
+
...(delivered !== undefined ? { delivered } : {}),
|
|
49
|
+
...(gatedCallId !== undefined ? { gatedCallId } : {}),
|
|
50
|
+
...(gate !== undefined ? { gate } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function reconciledToolEndBody(orphan) {
|
|
54
|
+
return toolEndBodyFrom({ content: orphan.text, details: { code: orphan.errorKind } }, true);
|
|
55
|
+
}
|
|
56
|
+
export function writeFamilyOfCanonical(name) {
|
|
57
|
+
if (name === "TaskCreate" || name === "TaskUpdate")
|
|
58
|
+
return "task";
|
|
59
|
+
if (name === "TodoWrite")
|
|
60
|
+
return "todo";
|
|
61
|
+
if (name === TOOL_SEARCH_NAME)
|
|
62
|
+
return "tool_search";
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
export function toolResultMsg(toolCallId, toolName, text, isError) {
|
|
66
|
+
return {
|
|
67
|
+
role: "toolResult",
|
|
68
|
+
toolCallId,
|
|
69
|
+
toolName,
|
|
70
|
+
content: [{ type: "text", text }],
|
|
71
|
+
isError,
|
|
72
|
+
timestamp: Date.now(),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Checkpoint, type CheckpointStore, type ResumeOutcome } from "../checkpoint-store.js";
|
|
2
|
+
import type { GateOutcome } from "../gate-outcome.js";
|
|
2
3
|
import { type CheckpointFields } from "../pause-registry.js";
|
|
3
4
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
4
5
|
/**
|
|
@@ -23,6 +24,9 @@ export declare function createCheckpointFixture(over?: Partial<CheckpointFields>
|
|
|
23
24
|
export declare const ALLOW: Extract<ResumeOutcome, {
|
|
24
25
|
gate: "policy_ask";
|
|
25
26
|
}>;
|
|
27
|
+
export declare const EXECUTED_ALLOW: GateOutcome;
|
|
28
|
+
export declare const EXECUTED_ALLOW_REORDERED: GateOutcome;
|
|
29
|
+
export declare const VETOED_BY_POLICY: GateOutcome;
|
|
26
30
|
/**
|
|
27
31
|
* The full cross-backend contract for {@link CheckpointStore} — the SAME assertions for every
|
|
28
32
|
* backend. Entries are a 1:1 port of the vitest originals (assertion semantics unchanged).
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { strict as assert } from "node:assert";
|
|
2
|
+
import { executionVerdict } from "../checkpoint-execution-record.js";
|
|
2
3
|
import { MAX_PENDING_STEER_ENTRIES, mintCheckpointToken, readPendingSteerQueue, } from "../checkpoint-store.js";
|
|
3
4
|
import { checkpointFrom } from "../pause-registry.js";
|
|
4
5
|
import { beginContract } from "./contract-harness.js";
|
|
@@ -36,6 +37,10 @@ export const ALLOW = {
|
|
|
36
37
|
boundInputHash: "h0",
|
|
37
38
|
hostDecision: { decidedBy: "person" },
|
|
38
39
|
};
|
|
40
|
+
const SETTLED = { kind: "human_allowed", who: { party: "person" }, when: 1_700_000_000_500 };
|
|
41
|
+
export const EXECUTED_ALLOW = Object.freeze({ disposition: Object.freeze({ kind: "allowed" }), settlement: Object.freeze({ ...SETTLED, who: Object.freeze({ ...SETTLED.who }) }), origin: "policy" });
|
|
42
|
+
export const EXECUTED_ALLOW_REORDERED = Object.freeze({ origin: "policy", settlement: Object.freeze({ when: 1_700_000_000_500, who: Object.freeze({ party: "person" }), kind: "human_allowed" }), disposition: Object.freeze({ kind: "allowed" }) });
|
|
43
|
+
export const VETOED_BY_POLICY = Object.freeze({ disposition: Object.freeze({ kind: "denied", deniedBy: "policy" }), settlement: Object.freeze({ ...SETTLED, who: Object.freeze({ ...SETTLED.who }) }), origin: "policy" });
|
|
39
44
|
export async function checkpointStoreContract(make, runAssertion) {
|
|
40
45
|
const { run, settle } = beginContract(runAssertion);
|
|
41
46
|
run("kit prerequisites: reopen/setPendingSteer/listByScope are implemented (REQUIRED by this kit)", async () => {
|
|
@@ -43,6 +48,86 @@ export async function checkpointStoreContract(make, runAssertion) {
|
|
|
43
48
|
const missing = ["reopen", "setPendingSteer", "listByScope"].filter((m) => typeof probe[m] !== "function");
|
|
44
49
|
assert.equal(missing.length, 0, `backend does not implement ${missing.join(", ")} — required for the CheckpointStore contract kit`);
|
|
45
50
|
});
|
|
51
|
+
run("execution declaration: the backend declares execution.outcome === true (a REQUIRED member of the contract)", async () => {
|
|
52
|
+
const probe = make();
|
|
53
|
+
assert.equal(probe.execution?.outcome, true, "backend does not declare `execution = { outcome: true }` — the run refuses the store at its first read");
|
|
54
|
+
assert.equal(typeof probe.recordExecutionOutcome, "function", "backend does not implement recordExecutionOutcome — required by the CheckpointStore contract");
|
|
55
|
+
});
|
|
56
|
+
run("recordExecutionOutcome on a resolved row → `recorded`; the record and its stamp ride the row, the decision winner is untouched, executionVerdict reads executed", async () => {
|
|
57
|
+
const store = make();
|
|
58
|
+
const cp = createCheckpointFixture();
|
|
59
|
+
await store.put(cp.token, cp);
|
|
60
|
+
assert.equal(executionVerdict((await store.get(cp.token))).kind, "unknown");
|
|
61
|
+
await store.resolve(cp.token, cp.scope, ALLOW);
|
|
62
|
+
const before = (await store.get(cp.token));
|
|
63
|
+
assert.equal(executionVerdict(before).kind, "unknown", "a resolved row with no record reads UNKNOWN — never allowed by default");
|
|
64
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, VETOED_BY_POLICY), "recorded");
|
|
65
|
+
const after = (await store.get(cp.token));
|
|
66
|
+
assert.deepEqual(after.executionOutcome, VETOED_BY_POLICY);
|
|
67
|
+
assert.equal(typeof after.executionAtMs, "number");
|
|
68
|
+
assert.equal(Number.isFinite(after.executionAtMs), true);
|
|
69
|
+
assert.deepEqual(executionVerdict(after), { kind: "executed", gate: VETOED_BY_POLICY });
|
|
70
|
+
assert.deepEqual(after.resolvedOutcome, before.resolvedOutcome);
|
|
71
|
+
assert.equal(after.status, "resolved");
|
|
72
|
+
assert.equal(after.rev, before.rev);
|
|
73
|
+
});
|
|
74
|
+
run("recordExecutionOutcome is idempotent on the SAME record (structural, key-order-blind) → `already_recorded`; a DIFFERENT record throws checkpoint.execution_outcome_conflict and the row is byte-identical", async () => {
|
|
75
|
+
const store = make();
|
|
76
|
+
const cp = createCheckpointFixture();
|
|
77
|
+
await store.put(cp.token, cp);
|
|
78
|
+
await store.resolve(cp.token, cp.scope, ALLOW);
|
|
79
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, EXECUTED_ALLOW), "recorded");
|
|
80
|
+
const filed = (await store.get(cp.token));
|
|
81
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, EXECUTED_ALLOW), "already_recorded");
|
|
82
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, EXECUTED_ALLOW_REORDERED), "already_recorded", "equality is over the record's JSON — key order and freezing are not part of the value");
|
|
83
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, structuredClone(EXECUTED_ALLOW)), "already_recorded", "an unfrozen structural twin is the same record");
|
|
84
|
+
await assert.rejects(store.recordExecutionOutcome(cp.token, cp.scope, VETOED_BY_POLICY), (e) => e.code === "checkpoint.execution_outcome_conflict");
|
|
85
|
+
const still = (await store.get(cp.token));
|
|
86
|
+
assert.deepEqual(still.executionOutcome, filed.executionOutcome);
|
|
87
|
+
assert.equal(still.executionAtMs, filed.executionAtMs, "a conflict writes nothing — not even a fresh stamp");
|
|
88
|
+
});
|
|
89
|
+
run("recordExecutionOutcome answers `not_resolved` for a pending and for an expired row, `absent` for a missing row and for a wrong-scope row; none of them write", async () => {
|
|
90
|
+
const store = make();
|
|
91
|
+
const pending = createCheckpointFixture();
|
|
92
|
+
await store.put(pending.token, pending);
|
|
93
|
+
assert.equal(await store.recordExecutionOutcome(pending.token, pending.scope, EXECUTED_ALLOW), "not_resolved");
|
|
94
|
+
assert.equal((await store.get(pending.token)).executionOutcome, undefined);
|
|
95
|
+
assert.equal(await store.recordExecutionOutcome(pending.token, "tenant-b", EXECUTED_ALLOW), "absent", "a wrong-scope row reads exactly like a missing one (the isolation rule)");
|
|
96
|
+
assert.equal(await store.recordExecutionOutcome(mintCheckpointToken(), pending.scope, EXECUTED_ALLOW), "absent");
|
|
97
|
+
const expired = createCheckpointFixture();
|
|
98
|
+
await store.put(expired.token, expired);
|
|
99
|
+
assert.equal(await store.expire(expired.token, expired.scope), true);
|
|
100
|
+
assert.equal(await store.recordExecutionOutcome(expired.token, expired.scope, EXECUTED_ALLOW), "not_resolved");
|
|
101
|
+
assert.equal((await store.get(expired.token)).executionOutcome, undefined);
|
|
102
|
+
});
|
|
103
|
+
run("reopen is refused on a row that carries an execution record (a settled action is not re-openable); the same row reopens before the record lands", async () => {
|
|
104
|
+
const store = make();
|
|
105
|
+
const cp = createCheckpointFixture();
|
|
106
|
+
await store.put(cp.token, cp);
|
|
107
|
+
await store.resolve(cp.token, cp.scope, ALLOW);
|
|
108
|
+
assert.equal(await store.reopen(cp.token, cp.scope, "env_failed"), true);
|
|
109
|
+
assert.equal(await store.resolve(cp.token, cp.scope, ALLOW, { rev: 2 }), true);
|
|
110
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, EXECUTED_ALLOW), "recorded");
|
|
111
|
+
assert.equal(await store.reopen(cp.token, cp.scope, "env_failed"), false);
|
|
112
|
+
assert.equal(await store.reopen(cp.token, cp.scope, "tool_unavailable"), false, "no reason reopens a recorded row");
|
|
113
|
+
const got = (await store.get(cp.token));
|
|
114
|
+
assert.equal(got.status, "resolved");
|
|
115
|
+
assert.equal(got.rev, 3, "a refused reopen bumps nothing");
|
|
116
|
+
assert.equal(got.reopenReason, undefined);
|
|
117
|
+
assert.deepEqual(got.executionOutcome, EXECUTED_ALLOW);
|
|
118
|
+
});
|
|
119
|
+
run("a row filed WITH an execution record (a restored resolved row) keeps it authoritative: get() returns it, reopen is refused, a different record conflicts, the same one is already_recorded", async () => {
|
|
120
|
+
const store = make();
|
|
121
|
+
const cp = createCheckpointFixture({ status: "resolved", rev: 1, executionOutcome: EXECUTED_ALLOW, executionAtMs: 1_700_000_001_000 });
|
|
122
|
+
await store.put(cp.token, cp);
|
|
123
|
+
const back = (await store.get(cp.token));
|
|
124
|
+
assert.deepEqual(back.executionOutcome, EXECUTED_ALLOW);
|
|
125
|
+
assert.equal(back.executionAtMs, 1_700_000_001_000);
|
|
126
|
+
assert.equal(await store.reopen(cp.token, cp.scope, "env_failed"), false, "a restored recorded row is as settled as a live one");
|
|
127
|
+
await assert.rejects(store.recordExecutionOutcome(cp.token, cp.scope, VETOED_BY_POLICY), (e) => e.code === "checkpoint.execution_outcome_conflict");
|
|
128
|
+
assert.equal(await store.recordExecutionOutcome(cp.token, cp.scope, EXECUTED_ALLOW), "already_recorded");
|
|
129
|
+
assert.equal((await store.get(cp.token)).status, "resolved");
|
|
130
|
+
});
|
|
46
131
|
run("put create-once → already_exists", async () => {
|
|
47
132
|
const store = make();
|
|
48
133
|
const cp = createCheckpointFixture();
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -511,6 +511,30 @@ export type TraceEvent = {
|
|
|
511
511
|
/** The boundary classification the admission asserted. */
|
|
512
512
|
boundary: "sandbox_internal";
|
|
513
513
|
ts: number;
|
|
514
|
+
} | {
|
|
515
|
+
/**
|
|
516
|
+
* The auto-mode classifier decided (or declined to decide) one pending ask — one frame per
|
|
517
|
+
* `decide` call, including the breaker-open short-circuit, so a consumer can read the gate's
|
|
518
|
+
* wall-clock cost per tool call and the failure cause behind an ask that reached a person. A
|
|
519
|
+
* TRACE frame rather than a task event: it fires once per gated call, it is an operator's read
|
|
520
|
+
* (why did that ask take four seconds / why did it fall back), and the session-level breaker
|
|
521
|
+
* read face a shell renders is a separate, additive wire face. `ms` is the wall time from the
|
|
522
|
+
* decide call to its verdict (timeout included: a timed-out round reads the deadline).
|
|
523
|
+
*/
|
|
524
|
+
kind: "auto_mode.classified";
|
|
525
|
+
version: 1;
|
|
526
|
+
taskId: string;
|
|
527
|
+
/** The gated call the classifier judged. */
|
|
528
|
+
toolCallId: string;
|
|
529
|
+
/** The classifier model (the resolved `classifier` role, or the main model it fell back to). */
|
|
530
|
+
model: string;
|
|
531
|
+
/** Wall-clock milliseconds the gate waited on this decision (integer, ≥ 0). */
|
|
532
|
+
ms: number;
|
|
533
|
+
/** The verdict kind the gate acted on (`allow` / `block` / `unavailable` / `parse_error`). */
|
|
534
|
+
verdict: "allow" | "block" | "unavailable" | "parse_error";
|
|
535
|
+
/** Present iff `verdict === "unavailable"`: `error` / `timeout` / `breaker_open`. */
|
|
536
|
+
cause?: "error" | "timeout" | "breaker_open";
|
|
537
|
+
ts: number;
|
|
514
538
|
} | {
|
|
515
539
|
/** C1 — the failover brain served this call from a FALLBACK entry (`createFailoverBrain`): the
|
|
516
540
|
* primary (and possibly earlier hops) failed cleanly upfront. Without this, same-model gateway
|
package/dist/index.d.ts
CHANGED
|
@@ -98,7 +98,8 @@ export { READ_FACE_DEFAULT_DENY_ENTRIES, READ_FACE_BUILTIN_DENY_TABLE, READ_DENY
|
|
|
98
98
|
export { deploymentReadFaceClampNotice, resolveReadFace, type ReadFace, type ReadFaceInputs } from "./tools/fs/index.js";
|
|
99
99
|
export { WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, compileWriteProtection, type WriteProtectedEntry, type WriteProtectedRow, type WriteProtectedKind, type WriteProtectedHit, type WriteProtectionMatcher, } from "./core/write-protect.js";
|
|
100
100
|
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, buildToolResultRef, toolResultContentSegment, MAX_MINTED_TOOL_RESULT_REF_CHARS, type ToolResultProvenance, assertToolResultProvenanceMatch, normalizeToolResultProvenance, toolResultProvenanceOf, ToolResultRefConflictError, TOOL_RESULT_REF_CONFLICT_CODE, type ToolResultStore, type ToolResultSlice, type ToolResultDeletionReport, } from "./core/tool-result-store.js";
|
|
101
|
-
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointId, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, type ActorAssertion, type PendingSteerEntry, type PendingSteerInput, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type ProbeCause, type ProbeCauseOperands, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type TerminalClaimIntent, type TerminalClaimOutcome, type SafetyAxis, type RealApprovalGateBit, type ResourceLedger, type ResourceLimitReason, type PlatformLimitReason, type CheckpointRow, realApprovalOrgFact, resolveCheckpointStore, } from "./core/checkpoint-store.js";
|
|
101
|
+
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointId, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, type ActorAssertion, type PendingSteerEntry, type PendingSteerInput, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type ProbeCause, type ProbeCauseOperands, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type TerminalClaimIntent, type TerminalClaimOutcome, type SafetyAxis, type RealApprovalGateBit, type ResourceLedger, type ResourceLimitReason, type PlatformLimitReason, type CheckpointRow, realApprovalOrgFact, resolveCheckpointStore, checkpointStoreExecutionUndeclared, } from "./core/checkpoint-store.js";
|
|
102
|
+
export { EXECUTION_OUTCOME_RECORD_WORDS, EXECUTION_RECORD_LEAVES_ROW_UNRECORDED, isExecutionOutcomeRecordWord, type ExecutionOutcomeRecordWord, type ExecutionRecordTableCoversEveryWord, type ExecutionRecordRowFacts, type ExecutionVerdict, ExecutionOutcomeConflictError, checkpointExecutionRecorded, executionRecordDisposition, sameExecutionRecord, executionVerdict, } from "./core/checkpoint-execution-record.js";
|
|
102
103
|
export { PAUSE_REGISTRY, type GateKind, type PendingKind, type ResumeGate, isGateKind, resumeGateMatches, type CheckpointPause, type CheckpointFields, pauseOf, checkpointFrom } from "./core/pause-registry.js";
|
|
103
104
|
export { InMemoryUsageWindowStore, GLOBAL_USAGE_KEY, EMPTY_USAGE_WINDOW_RECORD, chargeUsageRecord, readUsageRecord, usageRetryAfterMs, resolveUsageWindows, type UsageWindow, type UsageWindowStore, type UsageWindowReading, type UsageWindowRecord, type UsageSlot, type UsageBucketRow, } from "./core/usage-window-store.js";
|
|
104
105
|
export { FileUsageWindowStore } from "./stores/file/usage-window-store.js";
|
|
@@ -152,8 +153,8 @@ export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, create
|
|
|
152
153
|
export { type AskOrigin, ASK_ORIGINS, isAskOrigin, classifierMayAnswer, ORIGIN_IMPLIES_REAL_APPROVAL } from "./core/ask-origin.js";
|
|
153
154
|
export { SETTLEMENT_KINDS, type SettlementKind, isSettlementKind, type Settlement, SETTLEMENT_IS_REFUSAL, DENIED_BY_VALUES, type DeniedBy, isDeniedBy, DENIED_BY_MAY_VETO, type GateDisposition, type GateOutcome, screenGateOutcome } from "./core/gate-outcome.js";
|
|
154
155
|
export { type AskCarry } from "./core/hooks.js";
|
|
155
|
-
export { parseAutoModeResponse, createAutoModeDecider, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassifyFn, type AutoModeClassifyInput, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, type AutoModeDenialTracker, type AutoModeDenialLimitOptions, type DenialLimitCounts, type DenialLimitFallbackFace, type UnarmedDenialLimitFallback, type DenialLimitFallback, type DenialLimitVerdict, } from "./core/auto-mode.js";
|
|
156
|
-
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS } from "./core/auto-mode-defaults.js";
|
|
156
|
+
export { parseAutoModeResponse, createAutoModeDecider, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassified, type AutoModeClassifyFn, type AutoModeClassifyInput, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, type AutoModeDenialTracker, type AutoModeDenialLimitOptions, type DenialLimitCounts, type DenialLimitFallbackFace, type UnarmedDenialLimitFallback, type DenialLimitFallback, type DenialLimitVerdict, } from "./core/auto-mode.js";
|
|
157
|
+
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS, AUTO_MODE_CLASSIFIER_MAX_TOKENS } from "./core/auto-mode-defaults.js";
|
|
157
158
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, type AutoModeRules, type BuildAutoModePromptOptions, type AutoModeWindowOptions, } from "./core/auto-mode-prompt.js";
|
|
158
159
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
159
160
|
export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, type AutoModeArmingRecipe, type AutoModeArmingFace, type AutoModeArmingFold, type AutoModeRebuildRefusal, } from "./core/auto-mode-arming.js";
|
|
@@ -209,7 +210,7 @@ export { CenterPromptSource, FilePromptArtifactStore, FilePromptSourceStateStore
|
|
|
209
210
|
export { stripEngineMetadata } from "./internal/llm.js";
|
|
210
211
|
export { EVENT_PROMPT_REGISTRY, eventDefaultOn, type CompiledEventPrompt, type CompiledMessageInjection, type EventDedupe, type EventDefaultPolicy } from "./prompt-assembly/event-registry.js";
|
|
211
212
|
export type { CompiledSection, ComposedPrompt, PackSectionDeclaration, PromptCacheClass, PromptCarrier, PromptMutability, PromptOwner, PromptPack, PromptRenderCadence, PromptRuntimeFacts, PromptSlot, PromptTrust, SectionRenderInputs, } from "./prompt-assembly/types.js";
|
|
212
|
-
export { type ReasoningIntensity, type ReasoningResolution, type ResolvedReasoning, type ReasoningFormat, DEFAULT_EFFORT_LEVELS, REASONING_BUDGET_SHARE, isThinkingLevel, rankOf, resolveEffort, resolveBinary, reasoningBudgetShare, resolveReasoning, resolveReasoningProfile, type ReasoningTier, type ReasoningProfileFlags, } from "./brain/reasoning.js";
|
|
213
|
+
export { type ReasoningIntensity, type ReasoningResolution, type ResolvedReasoning, type ReasoningFormat, DEFAULT_EFFORT_LEVELS, REASONING_BUDGET_SHARE, isThinkingLevel, rankOf, resolveEffort, resolveBinary, reasoningBudgetShare, resolveReasoning, thinkingOffExpressible, declaredOffSpelling, type OffCapabilityModel, resolveReasoningProfile, type ReasoningTier, type ReasoningProfileFlags, } from "./brain/reasoning.js";
|
|
213
214
|
export { DESIGN_REVIEW_PROMPTS, CODE_REVIEW_PROMPT, SCENARIO_REGISTRY, runScenario, type ScenarioId, type CodeReviewMode, type ScenarioProfile, type RunScenarioOptions, type RunScenarioResult, } from "./scenarios/scenario-registry.js";
|
|
214
215
|
export { teacherMode, TEACHER_PROFILE, type TeacherModePair, type TeacherProfile, } from "./scenarios/teacher-quickstart.js";
|
|
215
216
|
export { loadOrchestrationEnv, DEFAULT_REASONING_INTENSITY, type OrchestrationMode, type OrchestrationEnv, } from "./scenarios/env.js";
|
package/dist/index.js
CHANGED
|
@@ -77,7 +77,8 @@ export { READ_FACE_DEFAULT_DENY_ENTRIES, READ_FACE_BUILTIN_DENY_TABLE, READ_DENY
|
|
|
77
77
|
export { deploymentReadFaceClampNotice, resolveReadFace } from "./tools/fs/index.js";
|
|
78
78
|
export { WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, compileWriteProtection, } from "./core/write-protect.js";
|
|
79
79
|
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, buildToolResultRef, toolResultContentSegment, MAX_MINTED_TOOL_RESULT_REF_CHARS, assertToolResultProvenanceMatch, normalizeToolResultProvenance, toolResultProvenanceOf, ToolResultRefConflictError, TOOL_RESULT_REF_CONFLICT_CODE, } from "./core/tool-result-store.js";
|
|
80
|
-
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointId, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, realApprovalOrgFact, resolveCheckpointStore, } from "./core/checkpoint-store.js";
|
|
80
|
+
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointId, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, realApprovalOrgFact, resolveCheckpointStore, checkpointStoreExecutionUndeclared, } from "./core/checkpoint-store.js";
|
|
81
|
+
export { EXECUTION_OUTCOME_RECORD_WORDS, EXECUTION_RECORD_LEAVES_ROW_UNRECORDED, isExecutionOutcomeRecordWord, ExecutionOutcomeConflictError, checkpointExecutionRecorded, executionRecordDisposition, sameExecutionRecord, executionVerdict, } from "./core/checkpoint-execution-record.js";
|
|
81
82
|
export { PAUSE_REGISTRY, isGateKind, resumeGateMatches, pauseOf, checkpointFrom } from "./core/pause-registry.js";
|
|
82
83
|
export { InMemoryUsageWindowStore, GLOBAL_USAGE_KEY, EMPTY_USAGE_WINDOW_RECORD, chargeUsageRecord, readUsageRecord, usageRetryAfterMs, resolveUsageWindows, } from "./core/usage-window-store.js";
|
|
83
84
|
export { FileUsageWindowStore } from "./stores/file/usage-window-store.js";
|
|
@@ -127,7 +128,7 @@ export { ASK_ORIGINS, isAskOrigin, classifierMayAnswer, ORIGIN_IMPLIES_REAL_APPR
|
|
|
127
128
|
export { SETTLEMENT_KINDS, isSettlementKind, SETTLEMENT_IS_REFUSAL, DENIED_BY_VALUES, isDeniedBy, DENIED_BY_MAY_VETO, screenGateOutcome } from "./core/gate-outcome.js";
|
|
128
129
|
export {} from "./core/hooks.js";
|
|
129
130
|
export { parseAutoModeResponse, createAutoModeDecider, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, } from "./core/auto-mode.js";
|
|
130
|
-
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS } from "./core/auto-mode-defaults.js";
|
|
131
|
+
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS, AUTO_MODE_CLASSIFIER_MAX_TOKENS } from "./core/auto-mode-defaults.js";
|
|
131
132
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, } from "./core/auto-mode-prompt.js";
|
|
132
133
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
133
134
|
export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
|
|
@@ -167,7 +168,7 @@ export { buildTurnPromptSnapshot, loweringRecordFor, LOWERING_VERSION, PREFIX_IN
|
|
|
167
168
|
export { CenterPromptSource, FilePromptArtifactStore, FilePromptSourceStateStore, MemoryPromptArtifactStore, MemoryPromptSourceStateStore, } from "./prompt-assembly/artifact-store.js";
|
|
168
169
|
export { stripEngineMetadata } from "./internal/llm.js";
|
|
169
170
|
export { EVENT_PROMPT_REGISTRY, eventDefaultOn } from "./prompt-assembly/event-registry.js";
|
|
170
|
-
export { DEFAULT_EFFORT_LEVELS, REASONING_BUDGET_SHARE, isThinkingLevel, rankOf, resolveEffort, resolveBinary, reasoningBudgetShare, resolveReasoning, resolveReasoningProfile, } from "./brain/reasoning.js";
|
|
171
|
+
export { DEFAULT_EFFORT_LEVELS, REASONING_BUDGET_SHARE, isThinkingLevel, rankOf, resolveEffort, resolveBinary, reasoningBudgetShare, resolveReasoning, thinkingOffExpressible, declaredOffSpelling, resolveReasoningProfile, } from "./brain/reasoning.js";
|
|
171
172
|
export { DESIGN_REVIEW_PROMPTS, CODE_REVIEW_PROMPT, SCENARIO_REGISTRY, runScenario, } from "./scenarios/scenario-registry.js";
|
|
172
173
|
export { teacherMode, TEACHER_PROFILE, } from "./scenarios/teacher-quickstart.js";
|
|
173
174
|
export { loadOrchestrationEnv, DEFAULT_REASONING_INTENSITY, } from "./scenarios/env.js";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { type ExecutionOutcomeRecordWord } from "../../core/checkpoint-execution-record.js";
|
|
1
2
|
import { type Checkpoint, type PendingSteerInput, type CheckpointFaultMode, type CheckpointStore, type CheckpointSummary, type CheckpointToken, type ReopenReason, type ResolveExpectation, type ResumeOutcome } from "../../core/checkpoint-store.js";
|
|
3
|
+
import type { GateOutcome } from "../../core/gate-outcome.js";
|
|
2
4
|
export interface FileCheckpointStoreOptions {
|
|
3
5
|
/** When false, an `appendLine` for a state transition is NOT fsync'd. The checkpoint COMMIT POINT always
|
|
4
6
|
* fsyncs regardless (its crash-safety depends on it); this governs the `put` and `setPendingSteer`
|
|
@@ -25,6 +27,10 @@ export declare class FileCheckpointStore implements CheckpointStore {
|
|
|
25
27
|
readonly redecision: {
|
|
26
28
|
readonly reopen: true;
|
|
27
29
|
};
|
|
30
|
+
/** The execution-outcome record verb below is the contract's CAS (journaled), and `reopen` honours the record. */
|
|
31
|
+
readonly execution: {
|
|
32
|
+
readonly outcome: true;
|
|
33
|
+
};
|
|
28
34
|
private readonly fsyncEnabled;
|
|
29
35
|
private readonly compactEvery;
|
|
30
36
|
/** RB-134: the directory's ONE authority (map + token mutex + append log), joined not rebuilt. */
|
|
@@ -50,6 +56,7 @@ export declare class FileCheckpointStore implements CheckpointStore {
|
|
|
50
56
|
put(token: CheckpointToken, cp: Checkpoint): Promise<void>;
|
|
51
57
|
get(token: CheckpointToken): Promise<Checkpoint | null>;
|
|
52
58
|
resolve(token: CheckpointToken, scope: string, outcome: ResumeOutcome, expect?: ResolveExpectation): Promise<boolean>;
|
|
59
|
+
recordExecutionOutcome(token: CheckpointToken, scope: string, gate: GateOutcome): Promise<ExecutionOutcomeRecordWord>;
|
|
53
60
|
reopen(token: CheckpointToken, scope: string, reason: ReopenReason): Promise<boolean>;
|
|
54
61
|
setPendingSteer(token: CheckpointToken, scope: string, steer: PendingSteerInput): Promise<boolean>;
|
|
55
62
|
expire(token: CheckpointToken, scope: string): Promise<boolean>;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { assertAdoptionBootGate } from "./adoption/marker.js";
|
|
3
|
+
import { checkpointExecutionRecorded, executionRecordDisposition, ExecutionOutcomeConflictError, } from "../../core/checkpoint-execution-record.js";
|
|
3
4
|
import { appendPendingSteer, CheckpointError, checkpointOccMatches, checkpointRowMatches, summarizeCheckpoint, validatePendingSteer, winnerFromOutcome, } from "../../core/checkpoint-store.js";
|
|
4
5
|
import { SharedLedgerTable } from "./shared-ledger.js";
|
|
5
6
|
const CHECKPOINT_LEDGER_EVENT_REGISTRY = {
|
|
6
7
|
put: true,
|
|
7
8
|
resolve: true,
|
|
8
9
|
reopen: true,
|
|
10
|
+
execution: true,
|
|
9
11
|
expire: true,
|
|
10
12
|
steer: true,
|
|
11
13
|
steer_append: true,
|
|
@@ -36,6 +38,10 @@ function applyCheckpointEvent(cps, ev) {
|
|
|
36
38
|
cp.rev = ev.rev;
|
|
37
39
|
cp.reopenReason = ev.reason;
|
|
38
40
|
break;
|
|
41
|
+
case "execution":
|
|
42
|
+
cp.executionOutcome = ev.gate;
|
|
43
|
+
cp.executionAtMs = ev.atMs;
|
|
44
|
+
break;
|
|
39
45
|
case "expire":
|
|
40
46
|
cp.status = "expired";
|
|
41
47
|
break;
|
|
@@ -64,6 +70,7 @@ export class FileCheckpointStore {
|
|
|
64
70
|
durability = "durable";
|
|
65
71
|
fidelity = "json";
|
|
66
72
|
redecision = { reopen: true };
|
|
73
|
+
execution = { outcome: true };
|
|
67
74
|
fsyncEnabled;
|
|
68
75
|
compactEvery;
|
|
69
76
|
ledger;
|
|
@@ -126,10 +133,22 @@ export class FileCheckpointStore {
|
|
|
126
133
|
return true;
|
|
127
134
|
});
|
|
128
135
|
}
|
|
136
|
+
async recordExecutionOutcome(token, scope, gate) {
|
|
137
|
+
return this.withLock(token, () => {
|
|
138
|
+
const cp = this.cps.get(token);
|
|
139
|
+
const disposition = executionRecordDisposition(cp, scope, gate);
|
|
140
|
+
if (disposition === "conflict")
|
|
141
|
+
throw new ExecutionOutcomeConflictError(cp.executionOutcome, gate);
|
|
142
|
+
if (disposition !== "commit")
|
|
143
|
+
return disposition;
|
|
144
|
+
this.commit({ t: "execution", token, gate: structuredClone(gate), atMs: Date.now() }, true);
|
|
145
|
+
return "recorded";
|
|
146
|
+
});
|
|
147
|
+
}
|
|
129
148
|
async reopen(token, scope, reason) {
|
|
130
149
|
return this.withLock(token, () => {
|
|
131
150
|
const cp = this.cps.get(token);
|
|
132
|
-
if (!checkpointRowMatches(cp, scope, "resolved")) {
|
|
151
|
+
if (!checkpointRowMatches(cp, scope, "resolved") || checkpointExecutionRecorded(cp)) {
|
|
133
152
|
return false;
|
|
134
153
|
}
|
|
135
154
|
const rev = (cp.rev ?? 0) + 1;
|