@skill-harness/adapters 0.12.0 → 0.14.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/dist/archive-access.d.ts +58 -0
- package/dist/archive-access.js +61 -0
- package/dist/archive-checkpoint.d.ts +47 -0
- package/dist/archive-checkpoint.js +116 -0
- package/dist/archive-facts.d.ts +19 -0
- package/dist/archive-facts.js +20 -0
- package/dist/archive-observer.d.ts +21 -0
- package/dist/archive-observer.js +79 -0
- package/dist/archive-policy.d.ts +107 -0
- package/dist/archive-policy.js +135 -0
- package/dist/archive-read-capability.d.ts +49 -0
- package/dist/archive-read-capability.js +45 -0
- package/dist/archive-retention-policy.d.ts +52 -0
- package/dist/archive-retention-policy.js +49 -0
- package/dist/archived-work.d.ts +44 -0
- package/dist/archived-work.js +64 -0
- package/dist/blind-intervention.d.ts +29 -0
- package/dist/blind-intervention.js +211 -0
- package/dist/codex-diagnostic-model.d.ts +14 -0
- package/dist/codex-diagnostic-model.js +39 -0
- package/dist/codex-host-observer.d.ts +111 -0
- package/dist/codex-host-observer.js +309 -0
- package/dist/codex-https.d.ts +7 -0
- package/dist/codex-https.js +221 -0
- package/dist/codex-model-profile.d.ts +38 -0
- package/dist/codex-model-profile.js +54 -0
- package/dist/codex-producer-ipc.d.ts +55 -0
- package/dist/codex-producer-ipc.js +67 -0
- package/dist/codex-sdk-transport.d.ts +50 -0
- package/dist/codex-sdk-transport.js +294 -0
- package/dist/codex-subscription.d.ts +114 -0
- package/dist/codex-subscription.js +268 -0
- package/dist/evidence-archive.d.ts +57 -0
- package/dist/evidence-archive.js +221 -0
- package/dist/execution-projection-schema.d.ts +10 -0
- package/dist/execution-projection-schema.js +30 -0
- package/dist/execution-retention-archive.d.ts +69 -0
- package/dist/execution-retention-archive.js +154 -0
- package/dist/generated/retention-v2-contract.d.ts +72 -0
- package/dist/generated/retention-v2-contract.js +105 -0
- package/dist/generated/retention-v2-json.d.ts +24 -0
- package/dist/generated/retention-v2-json.js +268 -0
- package/dist/generated/retention-v2-native-json.d.ts +2 -0
- package/dist/generated/retention-v2-native-json.js +33 -0
- package/dist/generated/retention-v2-native.d.ts +58 -0
- package/dist/generated/retention-v2-native.js +155 -0
- package/dist/generated/retention-v2-pin.d.ts +2 -0
- package/dist/generated/retention-v2-pin.js +4 -0
- package/dist/generated/retention-v2-types.d.ts +49 -0
- package/dist/generated/retention-v2-types.js +2 -0
- package/dist/generated/retention-v2-work-types.d.ts +260 -0
- package/dist/generated/retention-v2-work-types.js +13 -0
- package/dist/generated/work-v4/execution-id.d.ts +5 -0
- package/dist/generated/work-v4/execution-id.js +14 -0
- package/dist/generated/work-v4/json.d.ts +24 -0
- package/dist/generated/work-v4/json.js +268 -0
- package/dist/generated/work-v4/occurrences.d.ts +226 -0
- package/dist/generated/work-v4/occurrences.js +116 -0
- package/dist/generated/work-v4/pin.d.ts +1 -0
- package/dist/generated/work-v4/pin.js +3 -0
- package/dist/generated/work-v4/projection.d.ts +294 -0
- package/dist/generated/work-v4/projection.js +238 -0
- package/dist/generated/work-v4/reader.d.ts +24 -0
- package/dist/generated/work-v4/reader.js +109 -0
- package/dist/generated/work-v4/snapshot.d.ts +28 -0
- package/dist/generated/work-v4/snapshot.js +268 -0
- package/dist/generated/work-v4/types.d.ts +260 -0
- package/dist/generated/work-v4/types.js +13 -0
- package/dist/generated/work-v4/validation.d.ts +13 -0
- package/dist/generated/work-v4/validation.js +227 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +22 -0
- package/dist/installed-review-session.d.ts +28 -0
- package/dist/installed-review-session.js +166 -0
- package/dist/intervention-run.d.ts +403 -0
- package/dist/intervention-run.js +169 -0
- package/dist/learning-case.d.ts +12 -0
- package/dist/learning-case.js +15 -0
- package/dist/learning-journal.d.ts +18 -0
- package/dist/learning-journal.js +256 -0
- package/dist/principal-payload-port.d.ts +25 -0
- package/dist/principal-payload-port.js +40 -0
- package/dist/producer-product.d.ts +70 -0
- package/dist/producer-product.js +186 -0
- package/dist/producer-review.d.ts +53 -0
- package/dist/producer-review.js +207 -0
- package/dist/reviewed-archive-export.d.ts +42 -0
- package/dist/reviewed-archive-export.js +78 -0
- package/dist/trust-lifecycle.d.ts +128 -0
- package/dist/trust-lifecycle.js +200 -0
- package/dist/weekly-investigation.d.ts +237 -0
- package/dist/weekly-investigation.js +330 -0
- package/dist/work-candidates.d.ts +29 -0
- package/dist/work-candidates.js +78 -0
- package/dist/work-case-archive.d.ts +25 -0
- package/dist/work-case-archive.js +63 -0
- package/dist/work-case-review.d.ts +45 -0
- package/dist/work-case-review.js +220 -0
- package/dist/work-signal-cases.d.ts +15 -0
- package/dist/work-signal-cases.js +54 -0
- package/dist/work-signal-observation.d.ts +23 -0
- package/dist/work-signal-observation.js +89 -0
- package/package.json +3 -2
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { constants, closeSync, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readSync, writeSync } from "node:fs";
|
|
2
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { assessIntervention, createBlindComparison, interventionCanonicalJson } from "@skill-harness/core";
|
|
5
|
+
import { readArchiveSource, retainArchiveSource } from "./evidence-archive.js";
|
|
6
|
+
const SHA = /^[a-f0-9]{64}$/;
|
|
7
|
+
const missing = (e) => e?.code === "ENOENT";
|
|
8
|
+
const encode = interventionCanonicalJson;
|
|
9
|
+
const copy = (value) => JSON.parse(encode(value));
|
|
10
|
+
function keys(value, names) {
|
|
11
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join() !== names.sort().join())
|
|
12
|
+
throw new Error("invalid blind record fields");
|
|
13
|
+
}
|
|
14
|
+
function authorValid(author) {
|
|
15
|
+
if (typeof author !== "string" || !author.length || author.length > 512 || /[\u0000-\u001f\u007f]/.test(author))
|
|
16
|
+
throw new Error("explicit blind author required");
|
|
17
|
+
}
|
|
18
|
+
function claimsValid(claims, manifest) {
|
|
19
|
+
keys(claims, ["manifestId", "proposer", "judge", "subjects", "evidenceDigests"]);
|
|
20
|
+
for (const role of [claims.proposer, claims.judge])
|
|
21
|
+
keys(role, ["requested", "canonical"]);
|
|
22
|
+
keys(claims.subjects, manifest.arms.map(a => a.id));
|
|
23
|
+
keys(claims.evidenceDigests, manifest.arms.map(a => a.id));
|
|
24
|
+
for (const role of Object.values(claims.subjects))
|
|
25
|
+
keys(role, ["requested", "canonical"]);
|
|
26
|
+
}
|
|
27
|
+
/** Explicit private retention. Host role declarations are NOT authentication. No provider is called. */
|
|
28
|
+
export function retainBlindIntervention(root, manifest, evidence, qualification, author) {
|
|
29
|
+
authorValid(author);
|
|
30
|
+
const descriptors = Object.getOwnPropertyDescriptors(qualification);
|
|
31
|
+
if (Reflect.ownKeys(descriptors).some(k => typeof k !== "string" || !descriptors[k].enumerable || !Object.hasOwn(descriptors[k], "value")))
|
|
32
|
+
throw new Error("plain qualification required");
|
|
33
|
+
keys(qualification, ["manifestId", "proposer", "judge", "subjects", "evidenceDigests", "artifacts"]);
|
|
34
|
+
const { artifacts: artifactDescriptor, ...rest } = descriptors;
|
|
35
|
+
const claims = copy(Object.fromEntries(Object.entries(rest).map(([k, d]) => [k, d.value])));
|
|
36
|
+
const stableManifest = copy(manifest), stableEvidence = copy(evidence);
|
|
37
|
+
claimsValid(claims, stableManifest);
|
|
38
|
+
if (!(artifactDescriptor.value instanceof Map))
|
|
39
|
+
throw new Error("retained artifact map required");
|
|
40
|
+
const artifacts = new Map();
|
|
41
|
+
let total = 0;
|
|
42
|
+
for (const [hash, bytes] of Map.prototype.entries.call(artifactDescriptor.value)) {
|
|
43
|
+
if (typeof hash !== "string" || !SHA.test(hash) || !(bytes instanceof Uint8Array) || bytes.byteLength > 8 * 1024 * 1024 || artifacts.size >= 4096 || (total += bytes.byteLength) > 64 * 1024 * 1024)
|
|
44
|
+
throw new Error("bounded blind artifacts required");
|
|
45
|
+
const stable = Buffer.from(bytes);
|
|
46
|
+
if (createHash("sha256").update(stable).digest("hex") !== hash)
|
|
47
|
+
throw new Error("blind artifact digest mismatch");
|
|
48
|
+
artifacts.set(hash, stable);
|
|
49
|
+
}
|
|
50
|
+
const assessment = assessIntervention(stableManifest, stableEvidence, { ...claims, artifacts });
|
|
51
|
+
const seed = randomBytes(32).toString("hex");
|
|
52
|
+
createBlindComparison(stableManifest, assessment, seed); // Refuse incomplete inputs BEFORE writes.
|
|
53
|
+
const referenced = new Set(stableEvidence.flatMap(e => e.artifactDigests));
|
|
54
|
+
if ([...artifacts.keys()].some(h => !referenced.has(h)))
|
|
55
|
+
throw new Error("unreferenced blind artifact");
|
|
56
|
+
const refs = [...artifacts].sort(([a], [b]) => a.localeCompare(b)).map(([hash, bytes]) => ({ hash,
|
|
57
|
+
manifestId: retainArchiveSource(root, { sourceId: `blind-artifact-${hash}`, parser: { id: "blind-artifact", version: "1" }, retention: "exact", bytes }).manifestId }));
|
|
58
|
+
const bundle = { version: "retained-blind-intervention-v1", manifest: stableManifest, evidence: stableEvidence, qualification: claims, artifacts: refs, seed, author };
|
|
59
|
+
return retainArchiveSource(root, { sourceId: `blind-${stableManifest.id}`, parser: { id: "blind-intervention", version: "1" }, retention: "exact", bytes: Buffer.from(encode(bundle)) }).manifestId;
|
|
60
|
+
}
|
|
61
|
+
function load(root, id, author) {
|
|
62
|
+
authorValid(author);
|
|
63
|
+
const source = readArchiveSource(root, id);
|
|
64
|
+
if (source.status !== "available" || source.reference.retention !== "exact" || source.reference.parser.id !== "blind-intervention" || source.reference.parser.version !== "1")
|
|
65
|
+
throw new Error("blind input unavailable");
|
|
66
|
+
let bundle;
|
|
67
|
+
try {
|
|
68
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(source.bytes);
|
|
69
|
+
bundle = JSON.parse(text);
|
|
70
|
+
if (encode(bundle) !== text)
|
|
71
|
+
throw new Error();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw new Error("invalid blind input JSON");
|
|
75
|
+
}
|
|
76
|
+
keys(bundle, ["version", "manifest", "evidence", "qualification", "artifacts", "seed", "author"]);
|
|
77
|
+
if (bundle.version !== "retained-blind-intervention-v1" || bundle.author !== author)
|
|
78
|
+
throw new Error("blind author or version mismatch");
|
|
79
|
+
claimsValid(bundle.qualification, bundle.manifest);
|
|
80
|
+
if (!Array.isArray(bundle.artifacts) || bundle.artifacts.length > 4096)
|
|
81
|
+
throw new Error("invalid blind artifacts");
|
|
82
|
+
const artifacts = new Map();
|
|
83
|
+
let total = 0;
|
|
84
|
+
for (const ref of bundle.artifacts) {
|
|
85
|
+
keys(ref, ["hash", "manifestId"]);
|
|
86
|
+
if (!SHA.test(ref.hash) || artifacts.has(ref.hash))
|
|
87
|
+
throw new Error("invalid blind artifact identity");
|
|
88
|
+
const artifact = readArchiveSource(root, ref.manifestId);
|
|
89
|
+
if (artifact.status !== "available" || artifact.reference.retention !== "exact" || artifact.reference.parser.id !== "blind-artifact" || artifact.reference.parser.version !== "1" || artifact.reference.sha256 !== ref.hash || (total += artifact.bytes.length) > 64 * 1024 * 1024)
|
|
90
|
+
throw new Error("blind artifact unavailable");
|
|
91
|
+
artifacts.set(ref.hash, artifact.bytes);
|
|
92
|
+
}
|
|
93
|
+
return createBlindComparison(bundle.manifest, assessIntervention(bundle.manifest, bundle.evidence, { ...bundle.qualification, artifacts }), bundle.seed);
|
|
94
|
+
}
|
|
95
|
+
function directory(path) {
|
|
96
|
+
const s = lstatSync(path);
|
|
97
|
+
if (!s.isDirectory() || s.isSymbolicLink() || (s.mode & 0o077) || (process.getuid && s.uid !== process.getuid()))
|
|
98
|
+
throw new Error("private blind directory required");
|
|
99
|
+
}
|
|
100
|
+
function syncDirectory(path) {
|
|
101
|
+
const fd = openSync(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
102
|
+
try {
|
|
103
|
+
fsyncSync(fd);
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
closeSync(fd);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function readChoice(root, id) {
|
|
110
|
+
const parent = join(root, "blind-decisions"), dir = join(parent, id);
|
|
111
|
+
try {
|
|
112
|
+
directory(parent);
|
|
113
|
+
directory(dir);
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
if (missing(e))
|
|
117
|
+
return null;
|
|
118
|
+
throw e;
|
|
119
|
+
}
|
|
120
|
+
let fd;
|
|
121
|
+
try {
|
|
122
|
+
fd = openSync(join(dir, "choice.json"), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
if (missing(e))
|
|
126
|
+
throw new Error("blind choice incomplete; explicit recovery required");
|
|
127
|
+
throw e;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const s = fstatSync(fd);
|
|
131
|
+
if (!s.isFile() || s.nlink !== 1 || (s.mode & 0o077) || (process.getuid && s.uid !== process.getuid()) || s.size > 16384)
|
|
132
|
+
throw new Error("invalid blind choice file");
|
|
133
|
+
const bytes = Buffer.alloc(16385);
|
|
134
|
+
let used = 0;
|
|
135
|
+
while (used < bytes.length) {
|
|
136
|
+
const n = readSync(fd, bytes, used, bytes.length - used, used);
|
|
137
|
+
if (!n)
|
|
138
|
+
break;
|
|
139
|
+
used += n;
|
|
140
|
+
}
|
|
141
|
+
if (used > 16384)
|
|
142
|
+
throw new Error("invalid blind choice bound");
|
|
143
|
+
try {
|
|
144
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, used));
|
|
145
|
+
const value = JSON.parse(text);
|
|
146
|
+
if (encode(value) !== text)
|
|
147
|
+
throw new Error();
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
throw new Error("invalid blind choice JSON; explicit recovery required");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
closeSync(fd);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** One immutable quality choice per comparison. Reopening cannot reset the reveal gate. */
|
|
159
|
+
export function openBlindIntervention(root, id, author) {
|
|
160
|
+
if (!SHA.test(id))
|
|
161
|
+
throw new Error("invalid blind comparison identity");
|
|
162
|
+
const current = () => load(root, id, author);
|
|
163
|
+
return Object.freeze({
|
|
164
|
+
view: () => current().view(),
|
|
165
|
+
quality() { const blind = current(), choice = readChoice(root, id); return choice ? blind.choose(choice) : null; },
|
|
166
|
+
readArtifact: (label, hash) => current().readArtifact(label, hash),
|
|
167
|
+
choose(input) {
|
|
168
|
+
const blind = current(), choice = blind.choose(input);
|
|
169
|
+
const before = readChoice(root, id);
|
|
170
|
+
if (before) {
|
|
171
|
+
blind.choose(before);
|
|
172
|
+
if (encode(before) !== encode(choice))
|
|
173
|
+
throw new Error("blind quality choice locked");
|
|
174
|
+
return before;
|
|
175
|
+
}
|
|
176
|
+
const parent = join(root, "blind-decisions"), dir = join(parent, id);
|
|
177
|
+
try {
|
|
178
|
+
mkdirSync(parent, { mode: 0o700 });
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
if (e.code !== "EEXIST")
|
|
182
|
+
throw e;
|
|
183
|
+
}
|
|
184
|
+
directory(parent);
|
|
185
|
+
// Atomic mkdir is the single-writer claim. Never remove or recover an incomplete claim automatically.
|
|
186
|
+
mkdirSync(dir, { mode: 0o700 });
|
|
187
|
+
const fd = openSync(join(dir, "choice.json"), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
188
|
+
try {
|
|
189
|
+
const data = Buffer.from(encode(choice));
|
|
190
|
+
let offset = 0;
|
|
191
|
+
while (offset < data.length) {
|
|
192
|
+
const n = writeSync(fd, data, offset, data.length - offset);
|
|
193
|
+
if (!n)
|
|
194
|
+
throw new Error("blind choice write stalled");
|
|
195
|
+
offset += n;
|
|
196
|
+
}
|
|
197
|
+
fsyncSync(fd);
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
closeSync(fd);
|
|
201
|
+
}
|
|
202
|
+
syncDirectory(dir);
|
|
203
|
+
syncDirectory(parent);
|
|
204
|
+
syncDirectory(root);
|
|
205
|
+
return choice;
|
|
206
|
+
},
|
|
207
|
+
reveal() { const blind = current(), choice = readChoice(root, id); if (!choice)
|
|
208
|
+
throw new Error("durable quality choice required before reveal"); blind.choose(choice); return blind.reveal(); },
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=blind-intervention.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CodexSdkBinding } from './codex-sdk-transport.js';
|
|
2
|
+
export interface CodexDiagnosticModelPin {
|
|
3
|
+
path: string;
|
|
4
|
+
sha256: string;
|
|
5
|
+
}
|
|
6
|
+
/** Local catalogue declaration only, NOT canonical resolution or account entitlement. */
|
|
7
|
+
export declare function validateCodexDiagnosticModel(raw: unknown): CodexSdkBinding['model'];
|
|
8
|
+
export declare function loadCodexDiagnosticModel(pin: CodexDiagnosticModelPin): {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
id: string;
|
|
11
|
+
provider: string;
|
|
12
|
+
api: string;
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { isAbsolute } from 'node:path';
|
|
3
|
+
import { learningCopy, learningFile } from './learning-journal.js';
|
|
4
|
+
const closed = (v, keys) => { if (!v || typeof v !== 'object' || Array.isArray(v) || Object.keys(v).sort().join() !== keys.sort().join())
|
|
5
|
+
throw Error('closed diagnostic model definition required'); };
|
|
6
|
+
/** Local catalogue declaration only, NOT canonical resolution or account entitlement. */
|
|
7
|
+
export function validateCodexDiagnosticModel(raw) {
|
|
8
|
+
const m = learningCopy(raw);
|
|
9
|
+
closed(m, ['id', 'name', 'provider', 'api', 'baseUrl', 'reasoning', 'input', 'cost', 'contextWindow', 'maxTokens', 'thinkingLevelMap', 'compat']);
|
|
10
|
+
if (m.id !== 'gpt-6-astra' || m.name !== 'GPT-6 Astra' || m.provider !== 'openai-codex' || m.api !== 'openai-codex-responses' || m.baseUrl !== 'https://chatgpt.com/backend-api' || m.reasoning !== true || JSON.stringify(m.input) !== '["text","image"]' || ![m.contextWindow, m.maxTokens].every(n => Number.isSafeInteger(n) && n > 0))
|
|
11
|
+
throw Error('diagnostic model identity/capability mismatch');
|
|
12
|
+
closed(m.thinkingLevelMap, ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
13
|
+
if (m.thinkingLevelMap.off !== null || m.thinkingLevelMap.minimal !== 'low' || ['low', 'medium', 'high', 'xhigh', 'max'].some(k => m.thinkingLevelMap[k] !== k))
|
|
14
|
+
throw Error('diagnostic effort mapping mismatch');
|
|
15
|
+
closed(m.compat, ['supportsOpenAIGrammarTools', 'supportsAdditionalTools', 'supportsToolSearch']);
|
|
16
|
+
if (!Object.values(m.compat).every(v => typeof v === 'boolean'))
|
|
17
|
+
throw Error('diagnostic compatibility mismatch');
|
|
18
|
+
const prices = ['input', 'output', 'cacheRead', 'cacheWrite'];
|
|
19
|
+
closed(m.cost, [...prices, 'tiers']);
|
|
20
|
+
if (!Array.isArray(m.cost.tiers) || m.cost.tiers.length > 8)
|
|
21
|
+
throw Error('diagnostic cost declaration');
|
|
22
|
+
for (const [i, cost] of [m.cost, ...m.cost.tiers].entries()) {
|
|
23
|
+
if (i)
|
|
24
|
+
closed(cost, ['inputTokensAbove', ...prices]);
|
|
25
|
+
if (![...prices, ...(i ? ['inputTokensAbove'] : [])].every(k => typeof cost[k] === 'number' && Number.isFinite(cost[k]) && cost[k] >= 0))
|
|
26
|
+
throw Error('diagnostic cost declaration');
|
|
27
|
+
}
|
|
28
|
+
return m;
|
|
29
|
+
}
|
|
30
|
+
export function loadCodexDiagnosticModel(pin) {
|
|
31
|
+
closed(pin, ['path', 'sha256']);
|
|
32
|
+
if (typeof pin.path !== 'string' || !isAbsolute(pin.path) || !/^[a-f0-9]{64}$/.test(pin.sha256))
|
|
33
|
+
throw Error('diagnostic definition pin required');
|
|
34
|
+
const bytes = learningFile(pin.path, 8192);
|
|
35
|
+
if (createHash('sha256').update(bytes).digest('hex') !== pin.sha256)
|
|
36
|
+
throw Error('diagnostic definition source mismatch');
|
|
37
|
+
return validateCodexDiagnosticModel(JSON.parse(bytes.toString('utf8')));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=codex-diagnostic-model.js.map
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
import { type CodexSdkBinding, type CodexWireTransport } from './codex-sdk-transport.js';
|
|
3
|
+
/** LOCAL host protocol with an inert installed-SDK seam; no auth loader or live network switch.
|
|
4
|
+
* The trusted host owns this module and transport streams; the subject gets framed IPC only.
|
|
5
|
+
* Stream finish proves a host-side write, NOT provider receipt, backend identity or token limits.
|
|
6
|
+
* Journal integrity assumes a trusted cooperative host/filesystem, not hostile same-UID rollback. */
|
|
7
|
+
export declare const CODEX_SUBSCRIPTION_DESTINATION = "https://chatgpt.com/backend-api/codex/responses";
|
|
8
|
+
type Role = 'proposer' | 'subject' | 'judge';
|
|
9
|
+
export interface LocalCodexInvocation {
|
|
10
|
+
id: string;
|
|
11
|
+
role: Role;
|
|
12
|
+
model: string;
|
|
13
|
+
effort: 'low' | 'medium' | 'high';
|
|
14
|
+
instructions: string;
|
|
15
|
+
input: string;
|
|
16
|
+
expectedSha256: string;
|
|
17
|
+
subjectId: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface LocalCodexHostSpec {
|
|
20
|
+
version: 'codex-host-local-v1';
|
|
21
|
+
maxCalls: number;
|
|
22
|
+
wallMs: number;
|
|
23
|
+
invocations: LocalCodexInvocation[];
|
|
24
|
+
}
|
|
25
|
+
export interface SubscriptionReservations {
|
|
26
|
+
charterSha256: string;
|
|
27
|
+
mode: 'fixture' | 'subscription-live';
|
|
28
|
+
requestBytes: number;
|
|
29
|
+
responseBytes: number;
|
|
30
|
+
totalRequestBytes: number;
|
|
31
|
+
totalResponseBytes: number;
|
|
32
|
+
callMs: number;
|
|
33
|
+
}
|
|
34
|
+
export interface LocalCodexObservation {
|
|
35
|
+
id: string;
|
|
36
|
+
sequence: number;
|
|
37
|
+
requestBody: string;
|
|
38
|
+
requestSha256: string;
|
|
39
|
+
outputBase64: string;
|
|
40
|
+
outputSha256: string;
|
|
41
|
+
objective: 'PASS' | 'FAIL';
|
|
42
|
+
providerInternalFacts: null;
|
|
43
|
+
liveQualified: false;
|
|
44
|
+
}
|
|
45
|
+
/** This checks supplied policy consistency, never authenticates its source or invents lineage. */
|
|
46
|
+
export declare function inspectCodexRoleSeparation(raw: Array<{
|
|
47
|
+
role: Role;
|
|
48
|
+
model: string;
|
|
49
|
+
canonical: string | null;
|
|
50
|
+
lineage: string | null;
|
|
51
|
+
}>): {
|
|
52
|
+
state: "BLOCKED";
|
|
53
|
+
reason: string;
|
|
54
|
+
liveQualified: false;
|
|
55
|
+
} | {
|
|
56
|
+
state: "CONSISTENT_DECLARATION_ONLY";
|
|
57
|
+
reason: string;
|
|
58
|
+
disclosures: string[];
|
|
59
|
+
liveQualified: false;
|
|
60
|
+
};
|
|
61
|
+
export declare function createLocalCodexHost(path: string, input: LocalCodexHostSpec, rolePolicy?: Parameters<typeof inspectCodexRoleSeparation>[0], subscription?: SubscriptionReservations): {
|
|
62
|
+
inspect: () => {
|
|
63
|
+
calls: number;
|
|
64
|
+
complete: boolean;
|
|
65
|
+
aborted: boolean;
|
|
66
|
+
liveQualified: false;
|
|
67
|
+
};
|
|
68
|
+
exchangeSubscriptionSdk(subjectFrames: Readable, binding: CodexSdkBinding, transport: CodexWireTransport, charterSha256: string, sourceSignal?: AbortSignal): Promise<LocalCodexObservation>;
|
|
69
|
+
exchangeSdk(subjectFrames: Readable, binding: CodexSdkBinding, fixture: () => Promise<Response>): Promise<LocalCodexObservation>;
|
|
70
|
+
exchange(subjectFrames: Readable, hostTransport: Writable, hostResponse: Readable, subscriptionMode?: boolean, sourceSignal?: AbortSignal): Promise<LocalCodexObservation>;
|
|
71
|
+
panel(subjectId: string, judgeIds: string[], rawPolicy: Parameters<typeof inspectCodexRoleSeparation>[0]): {
|
|
72
|
+
label: string;
|
|
73
|
+
collapse: import("@skill-harness/core").VotePanelCollapse;
|
|
74
|
+
identityStatus: "CONSISTENT_DECLARATION_ONLY";
|
|
75
|
+
disclosures: string[];
|
|
76
|
+
liveQualified: false;
|
|
77
|
+
routingDefault: null;
|
|
78
|
+
};
|
|
79
|
+
eligibleOutputs(): {
|
|
80
|
+
label: string;
|
|
81
|
+
outputBase64: string;
|
|
82
|
+
outputSha256: string;
|
|
83
|
+
liveQualified: false;
|
|
84
|
+
}[];
|
|
85
|
+
};
|
|
86
|
+
export declare function openLocalCodexHost(path: string): {
|
|
87
|
+
inspect: () => {
|
|
88
|
+
calls: number;
|
|
89
|
+
complete: boolean;
|
|
90
|
+
aborted: boolean;
|
|
91
|
+
liveQualified: false;
|
|
92
|
+
};
|
|
93
|
+
exchangeSubscriptionSdk(subjectFrames: Readable, binding: CodexSdkBinding, transport: CodexWireTransport, charterSha256: string, sourceSignal?: AbortSignal): Promise<LocalCodexObservation>;
|
|
94
|
+
exchangeSdk(subjectFrames: Readable, binding: CodexSdkBinding, fixture: () => Promise<Response>): Promise<LocalCodexObservation>;
|
|
95
|
+
exchange(subjectFrames: Readable, hostTransport: Writable, hostResponse: Readable, subscriptionMode?: boolean, sourceSignal?: AbortSignal): Promise<LocalCodexObservation>;
|
|
96
|
+
panel(subjectId: string, judgeIds: string[], rawPolicy: Parameters<typeof inspectCodexRoleSeparation>[0]): {
|
|
97
|
+
label: string;
|
|
98
|
+
collapse: import("@skill-harness/core").VotePanelCollapse;
|
|
99
|
+
identityStatus: "CONSISTENT_DECLARATION_ONLY";
|
|
100
|
+
disclosures: string[];
|
|
101
|
+
liveQualified: false;
|
|
102
|
+
routingDefault: null;
|
|
103
|
+
};
|
|
104
|
+
eligibleOutputs(): {
|
|
105
|
+
label: string;
|
|
106
|
+
outputBase64: string;
|
|
107
|
+
outputSha256: string;
|
|
108
|
+
liveQualified: false;
|
|
109
|
+
}[];
|
|
110
|
+
};
|
|
111
|
+
export {};
|