@openprose/reactor-cradle 0.1.0-rc.1
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/LICENSE +21 -0
- package/README.md +270 -0
- package/dist/assert/index.d.ts +35 -0
- package/dist/assert/index.d.ts.map +1 -0
- package/dist/assert/index.js +398 -0
- package/dist/baselines/cost-thesis/index.d.ts +103 -0
- package/dist/baselines/cost-thesis/index.d.ts.map +1 -0
- package/dist/baselines/cost-thesis/index.js +337 -0
- package/dist/baselines/naive-loop/index.d.ts +46 -0
- package/dist/baselines/naive-loop/index.d.ts.map +1 -0
- package/dist/baselines/naive-loop/index.js +188 -0
- package/dist/baselines/no-memo/index.d.ts +84 -0
- package/dist/baselines/no-memo/index.d.ts.map +1 -0
- package/dist/baselines/no-memo/index.js +226 -0
- package/dist/doubles/clock.d.ts +9 -0
- package/dist/doubles/clock.d.ts.map +1 -0
- package/dist/doubles/clock.js +42 -0
- package/dist/doubles/storage.d.ts +24 -0
- package/dist/doubles/storage.d.ts.map +1 -0
- package/dist/doubles/storage.js +191 -0
- package/dist/eval/index.d.ts +204 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +596 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/policy-author/index.d.ts +103 -0
- package/dist/policy-author/index.d.ts.map +1 -0
- package/dist/policy-author/index.js +358 -0
- package/dist/policy-drift/index.d.ts +64 -0
- package/dist/policy-drift/index.d.ts.map +1 -0
- package/dist/policy-drift/index.js +495 -0
- package/dist/policy-replay/index.d.ts +106 -0
- package/dist/policy-replay/index.d.ts.map +1 -0
- package/dist/policy-replay/index.js +361 -0
- package/dist/provider-parity/index.d.ts +91 -0
- package/dist/provider-parity/index.d.ts.map +1 -0
- package/dist/provider-parity/index.js +439 -0
- package/dist/recompile/index.d.ts +161 -0
- package/dist/recompile/index.d.ts.map +1 -0
- package/dist/recompile/index.js +690 -0
- package/dist/release-candidate/index.d.ts +139 -0
- package/dist/release-candidate/index.d.ts.map +1 -0
- package/dist/release-candidate/index.js +553 -0
- package/dist/release-parity/index.d.ts +80 -0
- package/dist/release-parity/index.d.ts.map +1 -0
- package/dist/release-parity/index.js +1035 -0
- package/dist/replay/model-gateway.d.ts +25 -0
- package/dist/replay/model-gateway.d.ts.map +1 -0
- package/dist/replay/model-gateway.js +166 -0
- package/dist/replay/parity.d.ts +110 -0
- package/dist/replay/parity.d.ts.map +1 -0
- package/dist/replay/parity.js +232 -0
- package/dist/rollback/index.d.ts +106 -0
- package/dist/rollback/index.d.ts.map +1 -0
- package/dist/rollback/index.js +694 -0
- package/dist/scenario/parser.d.ts +11 -0
- package/dist/scenario/parser.d.ts.map +1 -0
- package/dist/scenario/parser.js +490 -0
- package/dist/scenario/runner.d.ts +12 -0
- package/dist/scenario/runner.d.ts.map +1 -0
- package/dist/scenario/runner.js +345 -0
- package/dist/scenario/synthetic-world-adapter.d.ts +4 -0
- package/dist/scenario/synthetic-world-adapter.d.ts.map +1 -0
- package/dist/scenario/synthetic-world-adapter.js +82 -0
- package/dist/scenario/time.d.ts +4 -0
- package/dist/scenario/time.d.ts.map +1 -0
- package/dist/scenario/time.js +45 -0
- package/dist/scenario/types.d.ts +149 -0
- package/dist/scenario/types.d.ts.map +1 -0
- package/dist/scenario/types.js +5 -0
- package/dist/spikes/index.d.ts +10 -0
- package/dist/spikes/index.d.ts.map +1 -0
- package/dist/spikes/index.js +29 -0
- package/dist/spikes/k1-ensemble-spread.d.ts +88 -0
- package/dist/spikes/k1-ensemble-spread.d.ts.map +1 -0
- package/dist/spikes/k1-ensemble-spread.js +396 -0
- package/dist/spikes/k2-policy-author.d.ts +25 -0
- package/dist/spikes/k2-policy-author.d.ts.map +1 -0
- package/dist/spikes/k2-policy-author.js +503 -0
- package/dist/spikes/live-refresh.d.ts +150 -0
- package/dist/spikes/live-refresh.d.ts.map +1 -0
- package/dist/spikes/live-refresh.js +511 -0
- package/dist/world/index.d.ts +2 -0
- package/dist/world/index.d.ts.map +1 -0
- package/dist/world/index.js +17 -0
- package/dist/world/synthetic-world.d.ts +104 -0
- package/dist/world/synthetic-world.d.ts.map +1 -0
- package/dist/world/synthetic-world.js +449 -0
- package/package.json +139 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactorModelGatewayAdapterV0, ReactorModelGatewayRequestV0, ReactorModelGatewayResponseV0 } from "@openprose/reactor/sdk";
|
|
2
|
+
import type { ContentHashV0 } from "@openprose/reactor/receipt";
|
|
3
|
+
export declare const MODEL_GATEWAY_CASSETTE_SCHEMA_V0: "openprose.reactor.model-gateway-cassette";
|
|
4
|
+
export declare const MODEL_GATEWAY_CASSETTE_VERSION_V0: 0;
|
|
5
|
+
export interface RecordedModelGatewayExchangeV0 {
|
|
6
|
+
readonly request: ReactorModelGatewayRequestV0;
|
|
7
|
+
readonly request_canonical: string;
|
|
8
|
+
readonly request_hash: ContentHashV0;
|
|
9
|
+
readonly response: ReactorModelGatewayResponseV0;
|
|
10
|
+
readonly response_canonical: string;
|
|
11
|
+
readonly response_hash: ContentHashV0;
|
|
12
|
+
}
|
|
13
|
+
export interface ModelGatewayCassetteV0 {
|
|
14
|
+
readonly schema: typeof MODEL_GATEWAY_CASSETTE_SCHEMA_V0;
|
|
15
|
+
readonly v: typeof MODEL_GATEWAY_CASSETTE_VERSION_V0;
|
|
16
|
+
readonly exchanges: readonly RecordedModelGatewayExchangeV0[];
|
|
17
|
+
}
|
|
18
|
+
export type ModelGatewayHandlerV0 = (request: ReactorModelGatewayRequestV0) => ReactorModelGatewayResponseV0;
|
|
19
|
+
export interface RecordingModelGatewayV0 {
|
|
20
|
+
readonly adapter: ReactorModelGatewayAdapterV0;
|
|
21
|
+
readonly cassette: ModelGatewayCassetteV0;
|
|
22
|
+
}
|
|
23
|
+
export declare function createRecordingModelGatewayV0(handler: ModelGatewayHandlerV0): RecordingModelGatewayV0;
|
|
24
|
+
export declare function createReplayModelGatewayV0(cassette: ModelGatewayCassetteV0): ReactorModelGatewayAdapterV0;
|
|
25
|
+
//# sourceMappingURL=model-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-gateway.d.ts","sourceRoot":"","sources":["../../src/replay/model-gateway.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,EAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,eAAO,MAAM,gCAAgC,EAC3C,0CAAmD,CAAC;AACtD,eAAO,MAAM,iCAAiC,EAAG,CAAU,CAAC;AAE5D,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,6BAA6B,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,OAAO,gCAAgC,CAAC;IACzD,QAAQ,CAAC,CAAC,EAAE,OAAO,iCAAiC,CAAC;IACrD,QAAQ,CAAC,SAAS,EAAE,SAAS,8BAA8B,EAAE,CAAC;CAC/D;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,4BAA4B,KAClC,6BAA6B,CAAC;AAEnC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;CAC3C;AAQD,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,qBAAqB,GAC7B,uBAAuB,CAqCzB;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,sBAAsB,GAC/B,4BAA4B,CA4B9B"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MODEL_GATEWAY_CASSETTE_VERSION_V0 = exports.MODEL_GATEWAY_CASSETTE_SCHEMA_V0 = void 0;
|
|
4
|
+
exports.createRecordingModelGatewayV0 = createRecordingModelGatewayV0;
|
|
5
|
+
exports.createReplayModelGatewayV0 = createReplayModelGatewayV0;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
exports.MODEL_GATEWAY_CASSETTE_SCHEMA_V0 = "openprose.reactor.model-gateway-cassette";
|
|
8
|
+
exports.MODEL_GATEWAY_CASSETTE_VERSION_V0 = 0;
|
|
9
|
+
function createRecordingModelGatewayV0(handler) {
|
|
10
|
+
const exchanges = [];
|
|
11
|
+
const adapter = {
|
|
12
|
+
invoke(request) {
|
|
13
|
+
const requestSnapshot = createCanonicalSnapshot(request, "model gateway request");
|
|
14
|
+
const response = handler(cloneFromCanonical(requestSnapshot));
|
|
15
|
+
const responseSnapshot = createCanonicalSnapshot(response, "model gateway response");
|
|
16
|
+
exchanges.push({
|
|
17
|
+
request: requestSnapshot.value,
|
|
18
|
+
request_canonical: requestSnapshot.canonical,
|
|
19
|
+
request_hash: requestSnapshot.hash,
|
|
20
|
+
response: responseSnapshot.value,
|
|
21
|
+
response_canonical: responseSnapshot.canonical,
|
|
22
|
+
response_hash: responseSnapshot.hash,
|
|
23
|
+
});
|
|
24
|
+
return cloneFromCanonical(responseSnapshot);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
adapter,
|
|
29
|
+
get cassette() {
|
|
30
|
+
return cloneCassette({
|
|
31
|
+
schema: exports.MODEL_GATEWAY_CASSETTE_SCHEMA_V0,
|
|
32
|
+
v: exports.MODEL_GATEWAY_CASSETTE_VERSION_V0,
|
|
33
|
+
exchanges,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function createReplayModelGatewayV0(cassette) {
|
|
39
|
+
const replayCassette = cloneCassette(cassette);
|
|
40
|
+
let cursor = 0;
|
|
41
|
+
return {
|
|
42
|
+
invoke(request) {
|
|
43
|
+
const expected = replayCassette.exchanges[cursor];
|
|
44
|
+
if (expected === undefined) {
|
|
45
|
+
throw new Error(`model gateway replay exhausted at exchange ${cursor}; cassette has ${replayCassette.exchanges.length} exchanges`);
|
|
46
|
+
}
|
|
47
|
+
const actual = createCanonicalSnapshot(request, "model gateway request");
|
|
48
|
+
if (actual.canonical !== expected.request_canonical) {
|
|
49
|
+
throw new Error(`unexpected model gateway request at exchange ${cursor}: expected ${expected.request_hash}, received ${actual.hash}`);
|
|
50
|
+
}
|
|
51
|
+
cursor += 1;
|
|
52
|
+
return cloneFromCanonical({
|
|
53
|
+
value: expected.response,
|
|
54
|
+
canonical: expected.response_canonical,
|
|
55
|
+
hash: expected.response_hash,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function cloneCassette(cassette) {
|
|
61
|
+
if (cassette.schema !== exports.MODEL_GATEWAY_CASSETTE_SCHEMA_V0) {
|
|
62
|
+
throw new Error("model gateway cassette schema must be openprose.reactor.model-gateway-cassette");
|
|
63
|
+
}
|
|
64
|
+
if (cassette.v !== exports.MODEL_GATEWAY_CASSETTE_VERSION_V0) {
|
|
65
|
+
throw new Error("model gateway cassette version must be 0");
|
|
66
|
+
}
|
|
67
|
+
if (!Array.isArray(cassette.exchanges)) {
|
|
68
|
+
throw new Error("model gateway cassette exchanges must be an array");
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
schema: exports.MODEL_GATEWAY_CASSETTE_SCHEMA_V0,
|
|
72
|
+
v: exports.MODEL_GATEWAY_CASSETTE_VERSION_V0,
|
|
73
|
+
exchanges: cassette.exchanges.map((exchange, index) => cloneExchange(exchange, index)),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function cloneExchange(exchange, index) {
|
|
77
|
+
const request = createCanonicalSnapshot(exchange.request, `model gateway cassette exchange ${index} request`);
|
|
78
|
+
const response = createCanonicalSnapshot(exchange.response, `model gateway cassette exchange ${index} response`);
|
|
79
|
+
assertStoredCanonical(exchange.request_canonical, request.canonical, `model gateway cassette exchange ${index} request_canonical`);
|
|
80
|
+
assertStoredHash(exchange.request_hash, request.hash, `model gateway cassette exchange ${index} request_hash`);
|
|
81
|
+
assertStoredCanonical(exchange.response_canonical, response.canonical, `model gateway cassette exchange ${index} response_canonical`);
|
|
82
|
+
assertStoredHash(exchange.response_hash, response.hash, `model gateway cassette exchange ${index} response_hash`);
|
|
83
|
+
return {
|
|
84
|
+
request: request.value,
|
|
85
|
+
request_canonical: request.canonical,
|
|
86
|
+
request_hash: request.hash,
|
|
87
|
+
response: response.value,
|
|
88
|
+
response_canonical: response.canonical,
|
|
89
|
+
response_hash: response.hash,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function createCanonicalSnapshot(value, label) {
|
|
93
|
+
try {
|
|
94
|
+
const canonical = renderCanonical(value);
|
|
95
|
+
return {
|
|
96
|
+
value: JSON.parse(canonical),
|
|
97
|
+
canonical,
|
|
98
|
+
hash: hashCanonical(canonical),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
const message = error instanceof Error ? error.message : "canonicalization failed";
|
|
103
|
+
throw new Error(`${label} must be canonical JSON: ${message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function cloneFromCanonical(snapshot) {
|
|
107
|
+
return JSON.parse(snapshot.canonical);
|
|
108
|
+
}
|
|
109
|
+
function assertStoredCanonical(stored, actual, label) {
|
|
110
|
+
if (stored !== actual) {
|
|
111
|
+
throw new Error(`${label} does not match canonical payload`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function assertStoredHash(stored, actual, label) {
|
|
115
|
+
if (stored !== actual) {
|
|
116
|
+
throw new Error(`${label} does not match canonical payload hash`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function hashCanonical(canonical) {
|
|
120
|
+
return `sha256:${(0, node_crypto_1.createHash)("sha256").update(canonical).digest("hex")}`;
|
|
121
|
+
}
|
|
122
|
+
function renderCanonical(value) {
|
|
123
|
+
if (value === null) {
|
|
124
|
+
return "null";
|
|
125
|
+
}
|
|
126
|
+
switch (typeof value) {
|
|
127
|
+
case "boolean":
|
|
128
|
+
return value ? "true" : "false";
|
|
129
|
+
case "number":
|
|
130
|
+
if (!Number.isFinite(value)) {
|
|
131
|
+
throw new TypeError("Cannot canonicalize non-finite numbers");
|
|
132
|
+
}
|
|
133
|
+
return JSON.stringify(value);
|
|
134
|
+
case "string":
|
|
135
|
+
return JSON.stringify(value);
|
|
136
|
+
case "object":
|
|
137
|
+
if (Array.isArray(value)) {
|
|
138
|
+
return `[${value.map((item) => renderCanonical(item)).join(",")}]`;
|
|
139
|
+
}
|
|
140
|
+
if (!isPlainRecord(value)) {
|
|
141
|
+
throw new TypeError("Cannot canonicalize non-plain objects");
|
|
142
|
+
}
|
|
143
|
+
return renderCanonicalObject(value);
|
|
144
|
+
case "undefined":
|
|
145
|
+
case "bigint":
|
|
146
|
+
case "function":
|
|
147
|
+
case "symbol":
|
|
148
|
+
throw new TypeError(`Cannot canonicalize ${typeof value}`);
|
|
149
|
+
}
|
|
150
|
+
throw new TypeError("Cannot canonicalize unknown value");
|
|
151
|
+
}
|
|
152
|
+
function renderCanonicalObject(value) {
|
|
153
|
+
const fields = [];
|
|
154
|
+
for (const key of Object.keys(value).sort()) {
|
|
155
|
+
const item = value[key];
|
|
156
|
+
if (item === undefined) {
|
|
157
|
+
throw new TypeError(`Cannot canonicalize undefined field ${key}`);
|
|
158
|
+
}
|
|
159
|
+
fields.push(`${JSON.stringify(key)}:${renderCanonical(item)}`);
|
|
160
|
+
}
|
|
161
|
+
return `{${fields.join(",")}}`;
|
|
162
|
+
}
|
|
163
|
+
function isPlainRecord(value) {
|
|
164
|
+
const prototype = Object.getPrototypeOf(value);
|
|
165
|
+
return prototype === Object.prototype || prototype === null;
|
|
166
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { ContentHashV0 } from "@openprose/reactor/receipt";
|
|
2
|
+
export declare const REPLAY_COMPARABLE_OUTPUT_SCHEMA_V0: "openprose.reactor-cradle.replay-comparable-output";
|
|
3
|
+
export declare const REPLAY_COMPARABLE_OUTPUT_VERSION_V0: 0;
|
|
4
|
+
export declare const REPLAY_PARITY_MATRIX_SCHEMA_V0: "openprose.reactor-cradle.replay-parity-matrix";
|
|
5
|
+
export declare const REPLAY_PARITY_MATRIX_VERSION_V0: 0;
|
|
6
|
+
export type ReplayComparableJsonValueV0 = null | boolean | number | string | readonly ReplayComparableJsonValueV0[] | {
|
|
7
|
+
readonly [key: string]: ReplayComparableJsonValueV0;
|
|
8
|
+
};
|
|
9
|
+
export interface ReplayComparableScenarioOutputInputV0 {
|
|
10
|
+
readonly scenario_id: string;
|
|
11
|
+
readonly world_profile: string;
|
|
12
|
+
readonly cassette_path: string;
|
|
13
|
+
readonly initial_instant: string;
|
|
14
|
+
readonly final_instant: string;
|
|
15
|
+
readonly trace: unknown;
|
|
16
|
+
readonly receipt_log: unknown;
|
|
17
|
+
readonly expected_relationships?: unknown;
|
|
18
|
+
readonly decisions?: unknown;
|
|
19
|
+
readonly registry?: unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface ReplayComparableScenarioOutputV0 {
|
|
22
|
+
readonly schema: typeof REPLAY_COMPARABLE_OUTPUT_SCHEMA_V0;
|
|
23
|
+
readonly v: typeof REPLAY_COMPARABLE_OUTPUT_VERSION_V0;
|
|
24
|
+
readonly scenario_id: string;
|
|
25
|
+
readonly world_profile: string;
|
|
26
|
+
readonly cassette_path: string;
|
|
27
|
+
readonly initial_instant: string;
|
|
28
|
+
readonly final_instant: string;
|
|
29
|
+
readonly trace: ReplayComparableJsonValueV0;
|
|
30
|
+
readonly receipt_log: ReplayComparableJsonValueV0;
|
|
31
|
+
readonly expected_relationships: ReplayComparableJsonValueV0;
|
|
32
|
+
readonly decisions?: ReplayComparableJsonValueV0;
|
|
33
|
+
readonly registry?: ReplayComparableJsonValueV0;
|
|
34
|
+
}
|
|
35
|
+
export interface ReplayComparableSnapshotV0 {
|
|
36
|
+
readonly output: ReplayComparableScenarioOutputV0;
|
|
37
|
+
readonly bytes: string;
|
|
38
|
+
readonly content_hash: ContentHashV0;
|
|
39
|
+
readonly byte_length: number;
|
|
40
|
+
}
|
|
41
|
+
export type ReplayByteIdenticalCheckV0 = ReplayByteIdenticalPassV0 | ReplayByteIdenticalFailV0;
|
|
42
|
+
export interface ReplayByteIdenticalPassV0 {
|
|
43
|
+
readonly ok: true;
|
|
44
|
+
readonly relationship: "replay-byte-identical";
|
|
45
|
+
readonly expected_hash: ContentHashV0;
|
|
46
|
+
readonly actual_hash: ContentHashV0;
|
|
47
|
+
readonly byte_length: number;
|
|
48
|
+
readonly evidence_path: "$";
|
|
49
|
+
}
|
|
50
|
+
export interface ReplayByteIdenticalFailV0 {
|
|
51
|
+
readonly ok: false;
|
|
52
|
+
readonly relationship: "replay-byte-identical";
|
|
53
|
+
readonly expected_hash: ContentHashV0;
|
|
54
|
+
readonly actual_hash: ContentHashV0;
|
|
55
|
+
readonly expected_bytes: string;
|
|
56
|
+
readonly actual_bytes: string;
|
|
57
|
+
readonly evidence_path: "$";
|
|
58
|
+
readonly reason: string;
|
|
59
|
+
}
|
|
60
|
+
export type ReplayParityAdapterNameV0 = "deterministic-in-memory" | "filesystem" | "postgres";
|
|
61
|
+
export type ReplayParityStorageAdapterV0 = "memory" | "fs" | "pg";
|
|
62
|
+
export type ReplayParityAdapterStatusV0 = "ready" | "future";
|
|
63
|
+
export interface ReplayParityAdapterRowV0 {
|
|
64
|
+
readonly name: ReplayParityAdapterNameV0;
|
|
65
|
+
readonly storage_adapter: ReplayParityStorageAdapterV0;
|
|
66
|
+
readonly status: ReplayParityAdapterStatusV0;
|
|
67
|
+
readonly reason: string;
|
|
68
|
+
}
|
|
69
|
+
export declare const REPLAY_PARITY_MATRIX_ROWS_V0: readonly ReplayParityAdapterRowV0[];
|
|
70
|
+
export interface ReplayParityMatrixInputV0 {
|
|
71
|
+
readonly baseline: ReplayComparableScenarioOutputInputV0;
|
|
72
|
+
readonly rows?: readonly ReplayParityAdapterRowV0[];
|
|
73
|
+
readonly runAdapter: (row: ReplayParityAdapterRowV0) => ReplayComparableScenarioOutputInputV0;
|
|
74
|
+
}
|
|
75
|
+
export interface ReplayParityMatrixResultV0 {
|
|
76
|
+
readonly schema: typeof REPLAY_PARITY_MATRIX_SCHEMA_V0;
|
|
77
|
+
readonly v: typeof REPLAY_PARITY_MATRIX_VERSION_V0;
|
|
78
|
+
readonly relationship: "cross-adapter-parity";
|
|
79
|
+
readonly ok: boolean;
|
|
80
|
+
readonly ready_rows_run: number;
|
|
81
|
+
readonly future_rows: number;
|
|
82
|
+
readonly rows: readonly ReplayParityRowResultV0[];
|
|
83
|
+
}
|
|
84
|
+
export type ReplayParityRowResultV0 = ReplayParityReadyPassV0 | ReplayParityReadyFailV0 | ReplayParityFutureRowV0;
|
|
85
|
+
export interface ReplayParityReadyPassV0 {
|
|
86
|
+
readonly adapter_name: ReplayParityAdapterNameV0;
|
|
87
|
+
readonly storage_adapter: ReplayParityStorageAdapterV0;
|
|
88
|
+
readonly status: "passed";
|
|
89
|
+
readonly check: ReplayByteIdenticalPassV0;
|
|
90
|
+
}
|
|
91
|
+
export interface ReplayParityReadyFailV0 {
|
|
92
|
+
readonly adapter_name: ReplayParityAdapterNameV0;
|
|
93
|
+
readonly storage_adapter: ReplayParityStorageAdapterV0;
|
|
94
|
+
readonly status: "failed";
|
|
95
|
+
readonly reason: string;
|
|
96
|
+
readonly check?: ReplayByteIdenticalFailV0;
|
|
97
|
+
}
|
|
98
|
+
export interface ReplayParityFutureRowV0 {
|
|
99
|
+
readonly adapter_name: ReplayParityAdapterNameV0;
|
|
100
|
+
readonly storage_adapter: ReplayParityStorageAdapterV0;
|
|
101
|
+
readonly status: "future";
|
|
102
|
+
readonly reason: string;
|
|
103
|
+
}
|
|
104
|
+
export declare function createReplayComparableOutputV0(input: ReplayComparableScenarioOutputInputV0): ReplayComparableScenarioOutputV0;
|
|
105
|
+
export declare function snapshotReplayComparableOutputV0(input: ReplayComparableScenarioOutputInputV0): ReplayComparableSnapshotV0;
|
|
106
|
+
export declare function compareReplayByteIdenticalV0(expected: ReplayComparableScenarioOutputInputV0, actual: ReplayComparableScenarioOutputInputV0): ReplayByteIdenticalCheckV0;
|
|
107
|
+
export declare function assertReplayByteIdenticalV0(expected: ReplayComparableScenarioOutputInputV0, actual: ReplayComparableScenarioOutputInputV0): ReplayByteIdenticalPassV0;
|
|
108
|
+
export declare function runReplayParityMatrixV0(input: ReplayParityMatrixInputV0): ReplayParityMatrixResultV0;
|
|
109
|
+
export declare function assertReplayParityMatrixV0(input: ReplayParityMatrixInputV0): ReplayParityMatrixResultV0;
|
|
110
|
+
//# sourceMappingURL=parity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parity.d.ts","sourceRoot":"","sources":["../../src/replay/parity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REPLAY_PARITY_MATRIX_ROWS_V0 = exports.REPLAY_PARITY_MATRIX_VERSION_V0 = exports.REPLAY_PARITY_MATRIX_SCHEMA_V0 = exports.REPLAY_COMPARABLE_OUTPUT_VERSION_V0 = exports.REPLAY_COMPARABLE_OUTPUT_SCHEMA_V0 = void 0;
|
|
4
|
+
exports.createReplayComparableOutputV0 = createReplayComparableOutputV0;
|
|
5
|
+
exports.snapshotReplayComparableOutputV0 = snapshotReplayComparableOutputV0;
|
|
6
|
+
exports.compareReplayByteIdenticalV0 = compareReplayByteIdenticalV0;
|
|
7
|
+
exports.assertReplayByteIdenticalV0 = assertReplayByteIdenticalV0;
|
|
8
|
+
exports.runReplayParityMatrixV0 = runReplayParityMatrixV0;
|
|
9
|
+
exports.assertReplayParityMatrixV0 = assertReplayParityMatrixV0;
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
11
|
+
exports.REPLAY_COMPARABLE_OUTPUT_SCHEMA_V0 = "openprose.reactor-cradle.replay-comparable-output";
|
|
12
|
+
exports.REPLAY_COMPARABLE_OUTPUT_VERSION_V0 = 0;
|
|
13
|
+
exports.REPLAY_PARITY_MATRIX_SCHEMA_V0 = "openprose.reactor-cradle.replay-parity-matrix";
|
|
14
|
+
exports.REPLAY_PARITY_MATRIX_VERSION_V0 = 0;
|
|
15
|
+
exports.REPLAY_PARITY_MATRIX_ROWS_V0 = Object.freeze([
|
|
16
|
+
Object.freeze({
|
|
17
|
+
name: "deterministic-in-memory",
|
|
18
|
+
storage_adapter: "memory",
|
|
19
|
+
status: "ready",
|
|
20
|
+
reason: "C3 deterministic row backed by in-memory doubles",
|
|
21
|
+
}),
|
|
22
|
+
Object.freeze({
|
|
23
|
+
name: "filesystem",
|
|
24
|
+
storage_adapter: "fs",
|
|
25
|
+
status: "ready",
|
|
26
|
+
reason: "durable filesystem adapter row backed by deterministic JSON files",
|
|
27
|
+
}),
|
|
28
|
+
Object.freeze({
|
|
29
|
+
name: "postgres",
|
|
30
|
+
storage_adapter: "pg",
|
|
31
|
+
status: "future",
|
|
32
|
+
reason: "future Postgres adapter parity row; not implemented in C3",
|
|
33
|
+
}),
|
|
34
|
+
]);
|
|
35
|
+
function createReplayComparableOutputV0(input) {
|
|
36
|
+
assertNonEmptyString(input.scenario_id, "scenario_id");
|
|
37
|
+
assertNonEmptyString(input.world_profile, "world_profile");
|
|
38
|
+
assertNonEmptyString(input.cassette_path, "cassette_path");
|
|
39
|
+
assertNonEmptyString(input.initial_instant, "initial_instant");
|
|
40
|
+
assertNonEmptyString(input.final_instant, "final_instant");
|
|
41
|
+
const base = {
|
|
42
|
+
schema: exports.REPLAY_COMPARABLE_OUTPUT_SCHEMA_V0,
|
|
43
|
+
v: exports.REPLAY_COMPARABLE_OUTPUT_VERSION_V0,
|
|
44
|
+
scenario_id: input.scenario_id,
|
|
45
|
+
world_profile: input.world_profile,
|
|
46
|
+
cassette_path: input.cassette_path,
|
|
47
|
+
initial_instant: input.initial_instant,
|
|
48
|
+
final_instant: input.final_instant,
|
|
49
|
+
trace: toComparableJsonValue(input.trace, "trace"),
|
|
50
|
+
receipt_log: toComparableJsonValue(input.receipt_log, "receipt_log"),
|
|
51
|
+
expected_relationships: toComparableJsonValue(input.expected_relationships ?? [], "expected_relationships"),
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
...base,
|
|
55
|
+
...(input.decisions === undefined
|
|
56
|
+
? {}
|
|
57
|
+
: { decisions: toComparableJsonValue(input.decisions, "decisions") }),
|
|
58
|
+
...(input.registry === undefined
|
|
59
|
+
? {}
|
|
60
|
+
: { registry: toComparableJsonValue(input.registry, "registry") }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function snapshotReplayComparableOutputV0(input) {
|
|
64
|
+
const output = createReplayComparableOutputV0(input);
|
|
65
|
+
const bytes = renderCanonical(output);
|
|
66
|
+
return {
|
|
67
|
+
output,
|
|
68
|
+
bytes,
|
|
69
|
+
content_hash: hashCanonical(bytes),
|
|
70
|
+
byte_length: Buffer.byteLength(bytes, "utf8"),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function compareReplayByteIdenticalV0(expected, actual) {
|
|
74
|
+
const expectedSnapshot = snapshotReplayComparableOutputV0(expected);
|
|
75
|
+
const actualSnapshot = snapshotReplayComparableOutputV0(actual);
|
|
76
|
+
if (expectedSnapshot.bytes === actualSnapshot.bytes) {
|
|
77
|
+
return {
|
|
78
|
+
ok: true,
|
|
79
|
+
relationship: "replay-byte-identical",
|
|
80
|
+
expected_hash: expectedSnapshot.content_hash,
|
|
81
|
+
actual_hash: actualSnapshot.content_hash,
|
|
82
|
+
byte_length: expectedSnapshot.byte_length,
|
|
83
|
+
evidence_path: "$",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
relationship: "replay-byte-identical",
|
|
89
|
+
expected_hash: expectedSnapshot.content_hash,
|
|
90
|
+
actual_hash: actualSnapshot.content_hash,
|
|
91
|
+
expected_bytes: expectedSnapshot.bytes,
|
|
92
|
+
actual_bytes: actualSnapshot.bytes,
|
|
93
|
+
evidence_path: "$",
|
|
94
|
+
reason: "comparable scenario output bytes differ",
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function assertReplayByteIdenticalV0(expected, actual) {
|
|
98
|
+
const check = compareReplayByteIdenticalV0(expected, actual);
|
|
99
|
+
if (!check.ok) {
|
|
100
|
+
throw new Error(`replay-byte-identical failed: expected ${check.expected_hash}, received ${check.actual_hash}`);
|
|
101
|
+
}
|
|
102
|
+
return check;
|
|
103
|
+
}
|
|
104
|
+
function runReplayParityMatrixV0(input) {
|
|
105
|
+
const rows = input.rows ?? exports.REPLAY_PARITY_MATRIX_ROWS_V0;
|
|
106
|
+
const results = rows.map((row) => runParityRow(row, input));
|
|
107
|
+
const readyRowsRun = results.filter((result) => result.status === "passed" || result.status === "failed").length;
|
|
108
|
+
const futureRows = results.filter((result) => result.status === "future").length;
|
|
109
|
+
const failedRows = results.filter((result) => result.status === "failed");
|
|
110
|
+
return {
|
|
111
|
+
schema: exports.REPLAY_PARITY_MATRIX_SCHEMA_V0,
|
|
112
|
+
v: exports.REPLAY_PARITY_MATRIX_VERSION_V0,
|
|
113
|
+
relationship: "cross-adapter-parity",
|
|
114
|
+
ok: readyRowsRun > 0 && failedRows.length === 0,
|
|
115
|
+
ready_rows_run: readyRowsRun,
|
|
116
|
+
future_rows: futureRows,
|
|
117
|
+
rows: Object.freeze(results),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function assertReplayParityMatrixV0(input) {
|
|
121
|
+
const result = runReplayParityMatrixV0(input);
|
|
122
|
+
if (!result.ok) {
|
|
123
|
+
throw new Error("cross-adapter-parity failed");
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
function runParityRow(row, input) {
|
|
128
|
+
if (row.status === "future") {
|
|
129
|
+
return {
|
|
130
|
+
adapter_name: row.name,
|
|
131
|
+
storage_adapter: row.storage_adapter,
|
|
132
|
+
status: "future",
|
|
133
|
+
reason: row.reason,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const check = compareReplayByteIdenticalV0(input.baseline, input.runAdapter(row));
|
|
138
|
+
if (check.ok) {
|
|
139
|
+
return {
|
|
140
|
+
adapter_name: row.name,
|
|
141
|
+
storage_adapter: row.storage_adapter,
|
|
142
|
+
status: "passed",
|
|
143
|
+
check,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
adapter_name: row.name,
|
|
148
|
+
storage_adapter: row.storage_adapter,
|
|
149
|
+
status: "failed",
|
|
150
|
+
reason: check.reason,
|
|
151
|
+
check,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
return {
|
|
156
|
+
adapter_name: row.name,
|
|
157
|
+
storage_adapter: row.storage_adapter,
|
|
158
|
+
status: "failed",
|
|
159
|
+
reason: error instanceof Error ? error.message : "adapter row failed",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function toComparableJsonValue(value, label) {
|
|
164
|
+
return createCanonicalSnapshot(value, label).value;
|
|
165
|
+
}
|
|
166
|
+
function createCanonicalSnapshot(value, label) {
|
|
167
|
+
try {
|
|
168
|
+
const canonical = renderCanonical(value);
|
|
169
|
+
return {
|
|
170
|
+
value: JSON.parse(canonical),
|
|
171
|
+
canonical,
|
|
172
|
+
hash: hashCanonical(canonical),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
const message = error instanceof Error ? error.message : "canonicalization failed";
|
|
177
|
+
throw new Error(`${label} must be comparable canonical JSON: ${message}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function hashCanonical(canonical) {
|
|
181
|
+
return `sha256:${(0, node_crypto_1.createHash)("sha256").update(canonical).digest("hex")}`;
|
|
182
|
+
}
|
|
183
|
+
function renderCanonical(value) {
|
|
184
|
+
if (value === null) {
|
|
185
|
+
return "null";
|
|
186
|
+
}
|
|
187
|
+
switch (typeof value) {
|
|
188
|
+
case "boolean":
|
|
189
|
+
return value ? "true" : "false";
|
|
190
|
+
case "number":
|
|
191
|
+
if (!Number.isFinite(value)) {
|
|
192
|
+
throw new TypeError("Cannot canonicalize non-finite numbers");
|
|
193
|
+
}
|
|
194
|
+
return JSON.stringify(value);
|
|
195
|
+
case "string":
|
|
196
|
+
return JSON.stringify(value);
|
|
197
|
+
case "object":
|
|
198
|
+
if (Array.isArray(value)) {
|
|
199
|
+
return `[${value.map((item) => renderCanonical(item)).join(",")}]`;
|
|
200
|
+
}
|
|
201
|
+
if (!isPlainRecord(value)) {
|
|
202
|
+
throw new TypeError("Cannot canonicalize non-plain objects");
|
|
203
|
+
}
|
|
204
|
+
return renderCanonicalObject(value);
|
|
205
|
+
case "undefined":
|
|
206
|
+
case "bigint":
|
|
207
|
+
case "function":
|
|
208
|
+
case "symbol":
|
|
209
|
+
throw new TypeError(`Cannot canonicalize ${typeof value}`);
|
|
210
|
+
}
|
|
211
|
+
throw new TypeError("Cannot canonicalize unknown value");
|
|
212
|
+
}
|
|
213
|
+
function renderCanonicalObject(value) {
|
|
214
|
+
const fields = [];
|
|
215
|
+
for (const key of Object.keys(value).sort()) {
|
|
216
|
+
const item = value[key];
|
|
217
|
+
if (item === undefined) {
|
|
218
|
+
throw new TypeError(`Cannot canonicalize undefined field ${key}`);
|
|
219
|
+
}
|
|
220
|
+
fields.push(`${JSON.stringify(key)}:${renderCanonical(item)}`);
|
|
221
|
+
}
|
|
222
|
+
return `{${fields.join(",")}}`;
|
|
223
|
+
}
|
|
224
|
+
function assertNonEmptyString(value, label) {
|
|
225
|
+
if (value.length === 0) {
|
|
226
|
+
throw new Error(`${label} must be non-empty`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function isPlainRecord(value) {
|
|
230
|
+
const prototype = Object.getPrototypeOf(value);
|
|
231
|
+
return prototype === Object.prototype || prototype === null;
|
|
232
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { CompiledEvidencePlan, DeepRoamDiscovery, DeepRoamReconciliation, ShallowEvidencePlanResult } from "@openprose/reactor/evidence-plan";
|
|
2
|
+
import type { AuthoredPolicyArtifactV0 } from "@openprose/reactor/policy";
|
|
3
|
+
import type { ContentHashV0, ReceiptV0 } from "@openprose/reactor/receipt";
|
|
4
|
+
import { type NormalizedPolicyRecompileDecisionV0, type PlanPolicyRecompileV0 } from "../recompile";
|
|
5
|
+
export declare const POLICY_ROLLBACK_D2_SCENARIO_SCHEMA_V0: "openprose.reactor-cradle.rollback-d2-scenario";
|
|
6
|
+
export declare const POLICY_ROLLBACK_D2_SCENARIO_VERSION_V0: 0;
|
|
7
|
+
export declare const PLAN_INCOMPLETE_D2_SCENARIO_SCHEMA_V0: "openprose.reactor-cradle.plan-incomplete-d2-scenario";
|
|
8
|
+
export declare const PLAN_INCOMPLETE_D2_SCENARIO_VERSION_V0: 0;
|
|
9
|
+
export declare const ROLLBACK_D2_RESPONSIBILITY_ID: "incident-channel-current-briefing";
|
|
10
|
+
export declare const PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID: "crm-owner-map";
|
|
11
|
+
export declare const PLAN_INCOMPLETE_D2_BACKSTOP_FACT: "kernel.deep_shallow_contradiction_count_7d";
|
|
12
|
+
export type PolicyRollbackDecisionOutcomeV0 = "rollback" | "keep-current" | "no-last-known-good";
|
|
13
|
+
export type PlanPolicyRollbackV0 = (input: PolicyRollbackPlanInputV0) => Promise<unknown> | unknown;
|
|
14
|
+
export interface RecordedPolicyTripSummaryV0 {
|
|
15
|
+
readonly policy_revision: string;
|
|
16
|
+
readonly judged_activations_before_trip: number;
|
|
17
|
+
readonly activated_at: string;
|
|
18
|
+
readonly first_trip_at: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RecordedPolicyRollbackD2ScenarioV0 {
|
|
21
|
+
readonly schema: typeof POLICY_ROLLBACK_D2_SCENARIO_SCHEMA_V0;
|
|
22
|
+
readonly v: typeof POLICY_ROLLBACK_D2_SCENARIO_VERSION_V0;
|
|
23
|
+
readonly responsibility_id: string;
|
|
24
|
+
readonly contract_revision: ContentHashV0;
|
|
25
|
+
readonly as_of: string;
|
|
26
|
+
readonly fresh_policy: RecordedPolicyTripSummaryV0;
|
|
27
|
+
readonly last_known_good_policy: RecordedPolicyTripSummaryV0;
|
|
28
|
+
}
|
|
29
|
+
export interface PolicyRollbackPlanInputV0 {
|
|
30
|
+
readonly responsibility_id: string;
|
|
31
|
+
readonly contract_revision: ContentHashV0;
|
|
32
|
+
readonly as_of: string;
|
|
33
|
+
readonly fresh_policy_revision: string;
|
|
34
|
+
readonly fresh_policy_judged_activations_before_trip: number;
|
|
35
|
+
readonly last_known_good_revision?: string;
|
|
36
|
+
readonly last_known_good_judged_activations_before_trip?: number;
|
|
37
|
+
readonly policy_trip_history: readonly RecordedPolicyTripSummaryV0[];
|
|
38
|
+
}
|
|
39
|
+
export interface NormalizedPolicyRollbackDecisionV0 {
|
|
40
|
+
readonly outcome: PolicyRollbackDecisionOutcomeV0;
|
|
41
|
+
readonly fresh_policy_revision: string;
|
|
42
|
+
readonly fresh_policy_judged_activations_before_trip: number;
|
|
43
|
+
readonly last_known_good_revision?: string;
|
|
44
|
+
readonly last_known_good_judged_activations_before_trip?: number;
|
|
45
|
+
readonly target_policy_revision?: string;
|
|
46
|
+
readonly raw: unknown;
|
|
47
|
+
}
|
|
48
|
+
export interface RecordedPolicyRollbackD2ProofV0 {
|
|
49
|
+
readonly scenario: RecordedPolicyRollbackD2ScenarioV0;
|
|
50
|
+
readonly decision: NormalizedPolicyRollbackDecisionV0;
|
|
51
|
+
readonly gateway_invocations: {
|
|
52
|
+
readonly agent_launch_count: 0;
|
|
53
|
+
readonly model_gateway_invocation_count: 0;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface RunRecordedPolicyRollbackD2ProofInputV0 {
|
|
57
|
+
readonly planPolicyRollbackV0: PlanPolicyRollbackV0;
|
|
58
|
+
readonly scenario?: RecordedPolicyRollbackD2ScenarioV0;
|
|
59
|
+
}
|
|
60
|
+
export interface RecordedPlanIncompleteD2ScenarioV0 {
|
|
61
|
+
readonly schema: typeof PLAN_INCOMPLETE_D2_SCENARIO_SCHEMA_V0;
|
|
62
|
+
readonly v: typeof PLAN_INCOMPLETE_D2_SCENARIO_VERSION_V0;
|
|
63
|
+
readonly responsibility_id: string;
|
|
64
|
+
readonly contract_revision: ContentHashV0;
|
|
65
|
+
readonly as_of: string;
|
|
66
|
+
readonly last_recompile_at: string;
|
|
67
|
+
readonly last_policy_revalidated_at: string;
|
|
68
|
+
readonly last_unforced_deep_at: string;
|
|
69
|
+
readonly incomplete_plan: CompiledEvidencePlan;
|
|
70
|
+
readonly planned_receipt: ReceiptV0;
|
|
71
|
+
readonly plan_age_receipt: ReceiptV0;
|
|
72
|
+
readonly missing_dependency_receipt: ReceiptV0;
|
|
73
|
+
readonly plan_incomplete_receipt: ReceiptV0;
|
|
74
|
+
readonly deep_roam_discovery: DeepRoamDiscovery;
|
|
75
|
+
readonly policy_artifact: AuthoredPolicyArtifactV0;
|
|
76
|
+
readonly policy_artifact_bytes: string;
|
|
77
|
+
readonly policy_artifact_content_hash: ContentHashV0;
|
|
78
|
+
readonly receipt_history_after_discovery: readonly ReceiptV0[];
|
|
79
|
+
}
|
|
80
|
+
export interface RecordedPlanIncompleteD2ProofV0 {
|
|
81
|
+
readonly scenario: RecordedPlanIncompleteD2ScenarioV0;
|
|
82
|
+
readonly shallow: Extract<ShallowEvidencePlanResult, {
|
|
83
|
+
outcome: "ready";
|
|
84
|
+
}>;
|
|
85
|
+
readonly deep_roam: Extract<DeepRoamReconciliation, {
|
|
86
|
+
outcome: "force-recompile";
|
|
87
|
+
}>;
|
|
88
|
+
readonly recompile_request: NormalizedPolicyRecompileDecisionV0;
|
|
89
|
+
readonly gateway_invocations: {
|
|
90
|
+
readonly agent_launch_count: 0;
|
|
91
|
+
readonly model_gateway_invocation_count: 0;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export interface RunRecordedPlanIncompleteD2ProofInputV0 {
|
|
95
|
+
readonly planPolicyRecompileV0: PlanPolicyRecompileV0;
|
|
96
|
+
readonly scenario?: RecordedPlanIncompleteD2ScenarioV0;
|
|
97
|
+
}
|
|
98
|
+
export declare function makeRecordedPolicyRollbackD2ScenarioV0(): RecordedPolicyRollbackD2ScenarioV0;
|
|
99
|
+
export declare function assertRecordedPolicyRollbackD2ScenarioV0(scenario: RecordedPolicyRollbackD2ScenarioV0): void;
|
|
100
|
+
export declare function runRecordedPolicyRollbackD2ProofV0(input: RunRecordedPolicyRollbackD2ProofInputV0): Promise<RecordedPolicyRollbackD2ProofV0>;
|
|
101
|
+
export declare function createRecordedPolicyRollbackPlannerDoubleV0(): PlanPolicyRollbackV0;
|
|
102
|
+
export declare function normalizePolicyRollbackDecisionV0(result: unknown): NormalizedPolicyRollbackDecisionV0;
|
|
103
|
+
export declare function makeRecordedPlanIncompleteD2ScenarioV0(): RecordedPlanIncompleteD2ScenarioV0;
|
|
104
|
+
export declare function assertRecordedPlanIncompleteD2ScenarioV0(scenario: RecordedPlanIncompleteD2ScenarioV0): void;
|
|
105
|
+
export declare function runRecordedPlanIncompleteD2ProofV0(input: RunRecordedPlanIncompleteD2ProofInputV0): Promise<RecordedPlanIncompleteD2ProofV0>;
|
|
106
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rollback/index.ts"],"names":[],"mappings":"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"}
|