@skill-harness/adapters 0.17.0 → 0.18.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.
Files changed (118) hide show
  1. package/dist/index.d.ts +0 -30
  2. package/dist/index.js +0 -30
  3. package/dist/pi.js +21 -133
  4. package/package.json +2 -3
  5. package/dist/archive-access.d.ts +0 -58
  6. package/dist/archive-access.js +0 -61
  7. package/dist/archive-checkpoint.d.ts +0 -47
  8. package/dist/archive-checkpoint.js +0 -116
  9. package/dist/archive-facts.d.ts +0 -19
  10. package/dist/archive-facts.js +0 -20
  11. package/dist/archive-observer.d.ts +0 -21
  12. package/dist/archive-observer.js +0 -79
  13. package/dist/archive-policy.d.ts +0 -107
  14. package/dist/archive-policy.js +0 -135
  15. package/dist/archive-read-capability.d.ts +0 -49
  16. package/dist/archive-read-capability.js +0 -45
  17. package/dist/archive-retention-policy.d.ts +0 -52
  18. package/dist/archive-retention-policy.js +0 -49
  19. package/dist/archived-work.d.ts +0 -45
  20. package/dist/archived-work.js +0 -78
  21. package/dist/blind-intervention.d.ts +0 -35
  22. package/dist/blind-intervention.js +0 -218
  23. package/dist/codex-diagnostic-model.d.ts +0 -14
  24. package/dist/codex-diagnostic-model.js +0 -39
  25. package/dist/codex-host-observer.d.ts +0 -111
  26. package/dist/codex-host-observer.js +0 -309
  27. package/dist/codex-https.d.ts +0 -7
  28. package/dist/codex-https.js +0 -221
  29. package/dist/codex-model-profile.d.ts +0 -38
  30. package/dist/codex-model-profile.js +0 -54
  31. package/dist/codex-producer-ipc.d.ts +0 -55
  32. package/dist/codex-producer-ipc.js +0 -67
  33. package/dist/codex-sdk-transport.d.ts +0 -50
  34. package/dist/codex-sdk-transport.js +0 -294
  35. package/dist/codex-subscription.d.ts +0 -114
  36. package/dist/codex-subscription.js +0 -268
  37. package/dist/evidence-archive.d.ts +0 -65
  38. package/dist/evidence-archive.js +0 -225
  39. package/dist/execution-projection-schema.d.ts +0 -10
  40. package/dist/execution-projection-schema.js +0 -30
  41. package/dist/execution-retention-archive.d.ts +0 -69
  42. package/dist/execution-retention-archive.js +0 -154
  43. package/dist/generated/retention-v2-contract.d.ts +0 -72
  44. package/dist/generated/retention-v2-contract.js +0 -105
  45. package/dist/generated/retention-v2-json.d.ts +0 -24
  46. package/dist/generated/retention-v2-json.js +0 -268
  47. package/dist/generated/retention-v2-native-json.d.ts +0 -2
  48. package/dist/generated/retention-v2-native-json.js +0 -33
  49. package/dist/generated/retention-v2-native.d.ts +0 -58
  50. package/dist/generated/retention-v2-native.js +0 -155
  51. package/dist/generated/retention-v2-pin.d.ts +0 -2
  52. package/dist/generated/retention-v2-pin.js +0 -4
  53. package/dist/generated/retention-v2-types.d.ts +0 -49
  54. package/dist/generated/retention-v2-types.js +0 -2
  55. package/dist/generated/retention-v2-work-types.d.ts +0 -260
  56. package/dist/generated/retention-v2-work-types.js +0 -13
  57. package/dist/generated/work-v4/execution-id.d.ts +0 -5
  58. package/dist/generated/work-v4/execution-id.js +0 -14
  59. package/dist/generated/work-v4/json.d.ts +0 -24
  60. package/dist/generated/work-v4/json.js +0 -268
  61. package/dist/generated/work-v4/occurrences.d.ts +0 -226
  62. package/dist/generated/work-v4/occurrences.js +0 -116
  63. package/dist/generated/work-v4/pin.d.ts +0 -1
  64. package/dist/generated/work-v4/pin.js +0 -3
  65. package/dist/generated/work-v4/projection.d.ts +0 -294
  66. package/dist/generated/work-v4/projection.js +0 -238
  67. package/dist/generated/work-v4/reader.d.ts +0 -24
  68. package/dist/generated/work-v4/reader.js +0 -109
  69. package/dist/generated/work-v4/snapshot.d.ts +0 -28
  70. package/dist/generated/work-v4/snapshot.js +0 -268
  71. package/dist/generated/work-v4/types.d.ts +0 -260
  72. package/dist/generated/work-v4/types.js +0 -13
  73. package/dist/generated/work-v4/validation.d.ts +0 -13
  74. package/dist/generated/work-v4/validation.js +0 -227
  75. package/dist/installed-review-session.d.ts +0 -28
  76. package/dist/installed-review-session.js +0 -166
  77. package/dist/intervention-run.d.ts +0 -403
  78. package/dist/intervention-run.js +0 -169
  79. package/dist/learning-case.d.ts +0 -12
  80. package/dist/learning-case.js +0 -15
  81. package/dist/learning-journal.d.ts +0 -18
  82. package/dist/learning-journal.js +0 -256
  83. package/dist/learning-lifecycle.d.ts +0 -28
  84. package/dist/learning-lifecycle.js +0 -66
  85. package/dist/learning-trust-setup.d.ts +0 -64
  86. package/dist/learning-trust-setup.js +0 -55
  87. package/dist/learning-workspace.d.ts +0 -1084
  88. package/dist/learning-workspace.js +0 -705
  89. package/dist/principal-payload-port.d.ts +0 -25
  90. package/dist/principal-payload-port.js +0 -40
  91. package/dist/producer-product.d.ts +0 -70
  92. package/dist/producer-product.js +0 -186
  93. package/dist/producer-review.d.ts +0 -53
  94. package/dist/producer-review.js +0 -207
  95. package/dist/prompt-capture-extension.d.ts +0 -10
  96. package/dist/prompt-capture-extension.js +0 -26
  97. package/dist/prompt-provenance.d.ts +0 -22
  98. package/dist/prompt-provenance.js +0 -146
  99. package/dist/reviewed-archive-export.d.ts +0 -42
  100. package/dist/reviewed-archive-export.js +0 -78
  101. package/dist/session-observation.d.ts +0 -50
  102. package/dist/session-observation.js +0 -186
  103. package/dist/session-retention.d.ts +0 -48
  104. package/dist/session-retention.js +0 -121
  105. package/dist/trust-lifecycle.d.ts +0 -152
  106. package/dist/trust-lifecycle.js +0 -209
  107. package/dist/weekly-investigation.d.ts +0 -237
  108. package/dist/weekly-investigation.js +0 -330
  109. package/dist/work-candidates.d.ts +0 -29
  110. package/dist/work-candidates.js +0 -78
  111. package/dist/work-case-archive.d.ts +0 -25
  112. package/dist/work-case-archive.js +0 -63
  113. package/dist/work-case-review.d.ts +0 -45
  114. package/dist/work-case-review.js +0 -220
  115. package/dist/work-signal-cases.d.ts +0 -15
  116. package/dist/work-signal-cases.js +0 -54
  117. package/dist/work-signal-observation.d.ts +0 -23
  118. package/dist/work-signal-observation.js +0 -89
package/dist/index.d.ts CHANGED
@@ -1,36 +1,6 @@
1
- export * from './producer-product.js';
2
1
  import type { HarnessAdapter } from "@skill-harness/core";
3
2
  import { piAdapter } from "./pi.js";
4
3
  export declare function getAdapter(name: string): HarnessAdapter;
5
4
  export { piAdapter };
6
- export * from "./prompt-provenance.js";
7
5
  export * from "./trajectory.js";
8
6
  export * from "./pi-daddy-ledger-v3.js";
9
- export * from "./evidence-archive.js";
10
- export * from "./archive-checkpoint.js";
11
- export * from "./archive-policy.js";
12
- export * from "./execution-retention-archive.js";
13
- export * from "./work-candidates.js";
14
- export * from "./work-case-archive.js";
15
- export * from "./work-signal-observation.js";
16
- export * from "./work-signal-cases.js";
17
- export * from "./work-case-review.js";
18
- export * from "./archive-read-capability.js";
19
- export * from "./archived-work.js";
20
- export * from "./blind-intervention.js";
21
- export * from "./learning-lifecycle.js";
22
- export * from "./learning-workspace.js";
23
- export * from "./learning-trust-setup.js";
24
- export { learningHash, learningFile } from "./learning-journal.js";
25
- export * from "./learning-case.js";
26
- export * from "./archive-observer.js";
27
- export * from "./weekly-investigation.js";
28
- export * from "./intervention-run.js";
29
- export * from "./principal-payload-port.js";
30
- export * from "./reviewed-archive-export.js";
31
- export * from "./archive-access.js";
32
- export * from "./archive-facts.js";
33
- export * from "./trust-lifecycle.js";
34
- export * from "./producer-review.js";
35
- export * from './session-observation.js';
36
- export * from './session-retention.js';
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './producer-product.js';
2
1
  import { piAdapter } from "./pi.js";
3
2
  /**
4
3
  * Registered harnesses. pi is the only one (per project scope). The interface
@@ -15,35 +14,6 @@ export function getAdapter(name) {
15
14
  return a;
16
15
  }
17
16
  export { piAdapter };
18
- export * from "./prompt-provenance.js";
19
17
  export * from "./trajectory.js";
20
18
  export * from "./pi-daddy-ledger-v3.js";
21
- export * from "./evidence-archive.js";
22
- export * from "./archive-checkpoint.js";
23
- export * from "./archive-policy.js";
24
- export * from "./execution-retention-archive.js";
25
- export * from "./work-candidates.js";
26
- export * from "./work-case-archive.js";
27
- export * from "./work-signal-observation.js";
28
- export * from "./work-signal-cases.js";
29
- export * from "./work-case-review.js";
30
- export * from "./archive-read-capability.js";
31
- export * from "./archived-work.js";
32
- export * from "./blind-intervention.js";
33
- export * from "./learning-lifecycle.js";
34
- export * from "./learning-workspace.js";
35
- export * from "./learning-trust-setup.js";
36
- export { learningHash, learningFile } from "./learning-journal.js";
37
- export * from "./learning-case.js";
38
- export * from "./archive-observer.js";
39
- export * from "./weekly-investigation.js";
40
- export * from "./intervention-run.js";
41
- export * from "./principal-payload-port.js";
42
- export * from "./reviewed-archive-export.js";
43
- export * from "./archive-access.js";
44
- export * from "./archive-facts.js";
45
- export * from "./trust-lifecycle.js";
46
- export * from "./producer-review.js";
47
- export * from './session-observation.js';
48
- export * from './session-retention.js';
49
19
  //# sourceMappingURL=index.js.map
package/dist/pi.js CHANGED
@@ -1,72 +1,9 @@
1
- import { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
1
+ import { existsSync, mkdtempSync, readFileSync, statSync } from "node:fs";
2
2
  import { tmpdir, homedir } from "node:os";
3
- import { randomBytes } from "node:crypto";
4
3
  import { join, resolve } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
4
  import { runPiJson } from "./pi-json.js";
7
- import { collectTrajectorySources, normalizePiTraces, resequence } from "./trajectory.js";
8
- import { bindPromptObservation, observeProviderPayload, promptCaptureIsTrusted, verifyPromptSummary } from "./prompt-provenance.js";
9
- import { exec, onPath, envNum, traceSha256, withProviderFailure, splitPromptDoc } from "@skill-harness/core";
5
+ import { exec, onPath, envNum, traceSha256, withProviderFailure } from "@skill-harness/core";
10
6
  const PI_TIMEOUT_MS = envNum("PI_TIMEOUT_MS", 300_000);
11
- const PROMPT_CAPTURE_EXTENSION = fileURLToPath(new URL("./prompt-capture-extension.js", import.meta.url));
12
- function contractFor(req) {
13
- if (req.systemPromptFile) {
14
- const raw = readFileSync(req.systemPromptFile, "utf8");
15
- return { text: raw, raw, mechanism: "system-prompt-file" };
16
- }
17
- const raw = readFileSync(join(requireSkillDir(req.skillDir, req.mode), "SKILL.md"), "utf8");
18
- const body = splitPromptDoc(raw).body;
19
- if (req.mode === "red")
20
- return { text: body, raw, mechanism: "none" };
21
- return { text: body, raw, mechanism: req.mode === "green" ? "pi-skill" : "append-system-prompt" };
22
- }
23
- const RUNTIME_INJECTION_ENV = ["NODE_OPTIONS", "NODE_PATH", "LD_PRELOAD", "DYLD_INSERT_LIBRARIES"];
24
- function hasRuntimeInjection(req) {
25
- return Boolean(req.armEnv && Object.keys(req.armEnv).length) || RUNTIME_INJECTION_ENV.some(key => Boolean(process.env[key]));
26
- }
27
- function captureSetup(req, env, contract, counter) {
28
- if (!req.onPromptObservation)
29
- return { env, finish: () => { } };
30
- // Arbitrary scenario/arm extensions and runtime-injection env execute in Pi's
31
- // process with full Node authority. Refuse a forgeable positive observation.
32
- if (!promptCaptureIsTrusted(req.extensions?.length ?? 0, hasRuntimeInjection(req)))
33
- return { env, finish: () => {
34
- const empty = observeProviderPayload({}, contract.text, contract.mechanism, counter.value++);
35
- req.onPromptObservation?.({ ...empty, status: "ERROR", error: "prompt delivery provenance is unauthenticated when subject extensions or runtime-injection env share Pi's process" });
36
- } };
37
- const dir = mkdtempSync(join(tmpdir(), "skill-harness-prompt-"));
38
- const path = join(dir, "observations.jsonl"), contractPath = join(dir, "contract.json");
39
- const authenticationKey = randomBytes(32).toString("hex");
40
- writeFileSync(path, "", { mode: 0o600 });
41
- writeFileSync(contractPath, JSON.stringify({ text: contract.text, mechanism: contract.mechanism, authentication_key: authenticationKey }), { mode: 0o600 });
42
- const finish = () => {
43
- try {
44
- const lines = readFileSync(path, "utf8").split("\n").filter(Boolean);
45
- const parsed = lines.map(line => { try {
46
- return JSON.parse(line);
47
- }
48
- catch {
49
- return null;
50
- } });
51
- const records = parsed.slice(0, -1), summary = parsed.at(-1);
52
- if (!verifyPromptSummary(summary, records.length, authenticationKey)) {
53
- const empty = observeProviderPayload({}, contract.text, contract.mechanism, counter.value++);
54
- req.onPromptObservation?.({ ...empty, status: "ERROR", error: "Pi prompt observation log is missing, truncated, replayed, or unauthenticated" });
55
- }
56
- else
57
- records.forEach((record, observerRequestIndex) => {
58
- req.onPromptObservation?.(bindPromptObservation(record, contract.text, contract.mechanism, counter.value++, authenticationKey, observerRequestIndex));
59
- });
60
- }
61
- finally {
62
- rmSync(dir, { recursive: true, force: true });
63
- }
64
- };
65
- return { env: { ...(env ?? process.env), SKILL_HARNESS_PROMPT_CAPTURE_FILE: path, SKILL_HARNESS_PROMPT_CONTRACT_FILE: contractPath }, finish };
66
- }
67
- function observerFlags(req) {
68
- return req.onPromptObservation && promptCaptureIsTrusted(req.extensions?.length ?? 0, hasRuntimeInjection(req)) ? ["--extension", PROMPT_CAPTURE_EXTENSION] : [];
69
- }
70
7
  /**
71
8
  * stderr fragments that mean the provider refused the request, so the run measured
72
9
  * nothing about the model. Substring matching on a message pi passes through from
@@ -160,7 +97,6 @@ function header(turnNo, total, text) {
160
97
  }
161
98
  export const piAdapter = {
162
99
  name: "pi",
163
- observesPrompts: true,
164
100
  available() {
165
101
  return Promise.resolve(onPath("pi"));
166
102
  },
@@ -196,18 +132,14 @@ export const piAdapter = {
196
132
  "--no-context-files",
197
133
  "--no-extensions",
198
134
  ...extensionFlags(req.extensions),
199
- ...observerFlags(req),
200
135
  "--provider",
201
136
  req.model.provider,
202
137
  "--model",
203
138
  req.model.model,
204
139
  ];
205
- // Bind bytes once: argv and provenance must describe the same contract even if a file changes mid-run.
206
- const contract = contractFor(req);
207
140
  const flags = req.systemPromptFile
208
- ? ["--no-skills", "--append-system-prompt", contract.raw]
209
- : skillFlags(req.mode, req.skillDir, contract.raw);
210
- const requestCounter = { value: 0 };
141
+ ? ["--no-skills", "--append-system-prompt", readFileSync(req.systemPromptFile, "utf8")]
142
+ : skillFlags(req.mode, req.skillDir);
211
143
  const total = req.turns.length;
212
144
  const parts = [];
213
145
  // The arm's env, merged over the harness's own — undefined (not `process.env`)
@@ -222,14 +154,7 @@ export const piAdapter = {
222
154
  let providerFailure = null;
223
155
  if (total === 1) {
224
156
  const args = [...flags, ...common, "--no-session", "-p", req.turns[0]];
225
- const capture = captureSetup(req, env, contract, requestCounter);
226
- let r;
227
- try {
228
- r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env: capture.env });
229
- }
230
- finally {
231
- capture.finish();
232
- }
157
+ const r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env });
233
158
  parts.push(header(1, 1, req.turns[0]));
234
159
  parts.push(`<<< ASSISTANT:\n${r.stdout.trim()}\n`);
235
160
  if (r.code !== 0) {
@@ -243,14 +168,7 @@ export const piAdapter = {
243
168
  for (let i = 0; i < total; i++) {
244
169
  const turnFlags = i === 0 ? ["--session-dir", session] : ["--session-dir", session, "-c"];
245
170
  const args = [...flags, ...common, ...turnFlags, "-p", req.turns[i]];
246
- const capture = captureSetup(req, env, contract, requestCounter);
247
- let r;
248
- try {
249
- r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env: capture.env });
250
- }
251
- finally {
252
- capture.finish();
253
- }
171
+ const r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env });
254
172
  parts.push(header(i + 1, total, req.turns[i]));
255
173
  parts.push(`<<< ASSISTANT:\n${r.stdout.trim()}\n`);
256
174
  if (r.code !== 0) {
@@ -282,17 +200,14 @@ export const piAdapter = {
282
200
  "--no-context-files",
283
201
  "--no-extensions",
284
202
  ...extensionFlags(req.extensions),
285
- ...observerFlags(req),
286
203
  "--provider",
287
204
  req.model.provider,
288
205
  "--model",
289
206
  req.model.model,
290
207
  ];
291
- const contract = contractFor(req);
292
208
  const flags = req.systemPromptFile
293
- ? ["--no-skills", "--append-system-prompt", contract.raw]
294
- : skillFlags(req.mode, req.skillDir, contract.raw);
295
- const requestCounter = { value: 0 };
209
+ ? ["--no-skills", "--append-system-prompt", readFileSync(req.systemPromptFile, "utf8")]
210
+ : skillFlags(req.mode, req.skillDir);
296
211
  const piVersion = await this.version();
297
212
  const total = req.turns.length;
298
213
  const traces = [];
@@ -309,26 +224,19 @@ export const piAdapter = {
309
224
  ? ["--session-dir", session]
310
225
  : ["--session-dir", session, "-c"];
311
226
  const args = [...flags, ...common, "--mode", "json", ...turnFlags, "-p", req.turns[i]];
312
- const capture = captureSetup(req, env, contract, requestCounter);
313
- let r;
314
- try {
315
- r = await runPiJson({
316
- args,
317
- cwd: req.cwd,
318
- timeoutMs: PI_TIMEOUT_MS,
319
- piVersion,
320
- subject: req.model,
321
- scenarioId: req.scenarioId ?? "(unknown)",
322
- mode: req.mode,
323
- rep: req.rep ?? 0,
324
- turn: i,
325
- homeDir: homedir(),
326
- env: capture.env,
327
- });
328
- }
329
- finally {
330
- capture.finish();
331
- }
227
+ const r = await runPiJson({
228
+ args,
229
+ cwd: req.cwd,
230
+ timeoutMs: PI_TIMEOUT_MS,
231
+ piVersion,
232
+ subject: req.model,
233
+ scenarioId: req.scenarioId ?? "(unknown)",
234
+ mode: req.mode,
235
+ rep: req.rep ?? 0,
236
+ turn: i,
237
+ homeDir: homedir(),
238
+ env,
239
+ });
332
240
  // A stream with no terminal events at all is not evidence of a clean run.
333
241
  // Fail loudly here rather than let an empty trace satisfy a `forbid_calls`
334
242
  // gate — "the model called nothing" and "we recorded nothing" must not
@@ -356,29 +264,9 @@ export const piAdapter = {
356
264
  if (r.code !== 0)
357
265
  parts.push(`[pi exited ${r.code} on turn ${i + 1}]\n${r.stderr.trim()}\n`);
358
266
  }
359
- const native = req.eventSources?.length
360
- ? collectTrajectorySources(req.cwd, req.eventSources)
361
- : { events: [], errors: [] };
362
- const piEvents = normalizePiTraces(traces);
363
- const combined = [...piEvents, ...native.events];
364
- const chronologyErrors = [];
365
- if (piEvents.length && native.events.length) {
366
- if (combined.some((event) => !event.at || !Number.isFinite(Date.parse(event.at)))) {
367
- chronologyErrors.push("pi/native events cannot be globally ordered because at least one event has no valid `at` timestamp");
368
- }
369
- else {
370
- const piTimes = new Set(piEvents.map((event) => Date.parse(event.at)));
371
- if (native.events.some((event) => piTimes.has(Date.parse(event.at)))) {
372
- chronologyErrors.push("pi/native events contain equal timestamps, so strict cross-source order is ambiguous");
373
- }
374
- }
375
- }
376
- const eventErrors = [...native.errors, ...chronologyErrors];
377
267
  return {
378
268
  transcript: withProviderFailure(parts.join("\n"), providerFailure),
379
269
  traces,
380
- events: resequence(combined),
381
- ...(eventErrors.length ? { eventErrors } : {}),
382
270
  ...(providerFailure ? { providerFailure } : {}),
383
271
  };
384
272
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skill-harness/adapters",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "skill-harness harness adapters — pi runner + claude-code judge routing (internal API)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,7 +40,6 @@
40
40
  "prepack": "node ../../scripts/release-pack.mjs --guard"
41
41
  },
42
42
  "dependencies": {
43
- "@skill-harness/core": "0.17.0",
44
- "typebox": "1.3.4"
43
+ "@skill-harness/core": "0.18.0"
45
44
  }
46
45
  }
@@ -1,58 +0,0 @@
1
- export interface ArchiveAccessPolicy {
2
- archiveRoot: string;
3
- id: string;
4
- expiresAt: number;
5
- maxCalls: number;
6
- maxBytes: number;
7
- purposes: string[];
8
- }
9
- export interface ArchiveConsent {
10
- manifestId: string;
11
- purpose: string;
12
- expiresAt: number;
13
- }
14
- export interface GovernedArchiveRoute {
15
- directory: string;
16
- purpose: string;
17
- }
18
- export declare function createArchiveAccess(path: string, raw: ArchiveAccessPolicy, permissions: string[]): {
19
- inspect: () => {
20
- policy: ArchiveAccessPolicy;
21
- lastObservedNow: number;
22
- consents: {
23
- id: unknown;
24
- grant: ArchiveConsent;
25
- state: string;
26
- }[];
27
- calls: number;
28
- bytes: number;
29
- pending: number;
30
- };
31
- previewConsent: (g: ArchiveConsent) => string;
32
- previewRevocation: (id: string) => string;
33
- consent(raw: ArchiveConsent, permissions: string[], now: number): string;
34
- revoke(id: string, permissions: string[], now: number): void;
35
- read(manifestId: string, purpose: string, maxBytes: number, now?: number): import("./evidence-archive.js").ArchiveRead;
36
- };
37
- /** Shared cooperative access owner. No history deletion, authentication, OS
38
- * deadline guarantee, or reinterpretation of legacy raw archive APIs. */
39
- export declare function openArchiveAccess(path: string): {
40
- inspect: () => {
41
- policy: ArchiveAccessPolicy;
42
- lastObservedNow: number;
43
- consents: {
44
- id: unknown;
45
- grant: ArchiveConsent;
46
- state: string;
47
- }[];
48
- calls: number;
49
- bytes: number;
50
- pending: number;
51
- };
52
- previewConsent: (g: ArchiveConsent) => string;
53
- previewRevocation: (id: string) => string;
54
- consent(raw: ArchiveConsent, permissions: string[], now: number): string;
55
- revoke(id: string, permissions: string[], now: number): void;
56
- read(manifestId: string, purpose: string, maxBytes: number, now?: number): import("./evidence-archive.js").ArchiveRead;
57
- };
58
- export declare function readGovernedArchive(root: string, manifestId: string, maxBytes: number, route: GovernedArchiveRoute, now?: number): import("./evidence-archive.js").ArchiveRead;
@@ -1,61 +0,0 @@
1
- import { learningCopy, learningHash, learningJournal, registerLearningStore, verifyLearningStore } from './learning-journal.js';
2
- import { readArchiveSource } from './evidence-archive.js';
3
- export function createArchiveAccess(path, raw, permissions) {
4
- const policy = learningCopy(raw), binding = learningHash(policy);
5
- if (!permissions.includes(binding))
6
- throw Error('exact archive policy permission required');
7
- validate(policy);
8
- registerLearningStore(policy.archiveRoot, 'access', learningHash(policy.id), path, binding);
9
- learningJournal(path, { type: 'archive-access-v1', policy, binding });
10
- return openArchiveAccess(path);
11
- }
12
- function validate(p) { if (typeof p.id !== 'string' || !p.id.length || p.id.length > 128 || !Number.isSafeInteger(p.expiresAt) || p.expiresAt < 0 || !Number.isSafeInteger(p.maxCalls) || p.maxCalls < 1 || p.maxCalls > 1024 || !Number.isSafeInteger(p.maxBytes) || p.maxBytes < 1 || p.maxBytes > 64 * 1024 * 1024 || !Array.isArray(p.purposes) || !p.purposes.length || p.purposes.length > 16 || new Set(p.purposes).size !== p.purposes.length || p.purposes.some(s => typeof s !== 'string' || !s.length || s.length > 128))
13
- throw Error('bounded archive access policy required'); }
14
- /** Shared cooperative access owner. No history deletion, authentication, OS
15
- * deadline guarantee, or reinterpretation of legacy raw archive APIs. */
16
- export function openArchiveAccess(path) {
17
- const journal = learningJournal(path), first = journal.read()[0].value, policy = learningCopy(first.policy);
18
- validate(policy);
19
- if (first.type !== 'archive-access-v1' || learningHash(policy) !== first.binding)
20
- throw Error('archive policy changed');
21
- const history = () => { verifyLearningStore(policy.archiveRoot, 'access', learningHash(policy.id), path, String(first.binding)); return journal.read(); };
22
- const clock = (now) => { const rows = history(); if (!Number.isSafeInteger(now) || now < Math.max(0, ...rows.map(e => Number(e.value.now ?? 0))))
23
- throw Error('archive access clock rewind'); journal.append(rows.at(-1).id, { type: 'clock', now }); if (now >= policy.expiresAt)
24
- throw Error('archive access expired'); };
25
- const consent = (raw) => { const g = learningCopy(raw); if (!/^[a-f0-9]{64}$/.test(g.manifestId) || !policy.purposes.includes(g.purpose) || !Number.isSafeInteger(g.expiresAt) || g.expiresAt < 0 || g.expiresAt > policy.expiresAt)
26
- throw Error('consent outside policy'); return g; };
27
- const digest = (g) => learningHash({ policy: String(first.binding), consent: consent(g) });
28
- const revokeDigest = (id) => learningHash({ policy: String(first.binding), revoke: id });
29
- const inspect = () => { const rows = history(), claims = rows.filter(e => e.value.type === 'read-claim'), lastObservedNow = Math.max(0, ...rows.map(e => Number(e.value.now ?? 0))); return { policy: learningCopy(policy), lastObservedNow, consents: rows.filter(e => e.value.type === 'consented').map(e => { const grant = e.value.grant; return { id: e.value.consentId, grant: learningCopy(grant), state: rows.some(r => r.value.type === 'revoked' && r.value.consentId === e.value.consentId) ? 'revoked' : lastObservedNow >= Math.min(policy.expiresAt, grant.expiresAt) ? 'expired' : 'not-revoked-at-last-observed-clock' }; }), calls: claims.length, bytes: claims.reduce((n, e) => { const settled = rows.find(s => s.value.type === 'read-settled' && s.value.claim === e.id); return n + Number(settled ? settled.value.bytes : e.value.reserved); }, 0), pending: claims.filter(e => !rows.some(s => s.value.type === 'read-settled' && s.value.claim === e.id)).length }; };
30
- return { inspect, previewConsent: digest, previewRevocation: revokeDigest,
31
- consent(raw, permissions, now) { clock(now); const g = consent(raw), id = digest(g), rows = history(); if (!permissions.includes(id) || now >= g.expiresAt)
32
- throw Error('exact current consent permission required'); if (rows.some(e => e.value.type === 'revoked' && e.value.consentId === id))
33
- throw Error('consent revoked'); if (!rows.some(e => e.value.type === 'consented' && e.value.consentId === id))
34
- journal.append(rows.at(-1).id, { type: 'consented', consentId: id, grant: g, now }); return id; },
35
- revoke(id, permissions, now) { clock(now); const rows = history(); if (!permissions.includes(revokeDigest(id)) || !rows.some(e => e.value.type === 'consented' && e.value.consentId === id))
36
- throw Error('exact revocation permission required'); if (!rows.some(e => e.value.type === 'revoked' && e.value.consentId === id))
37
- journal.append(rows.at(-1).id, { type: 'revoked', consentId: id, now }); },
38
- read(manifestId, purpose, maxBytes, now = Date.now()) {
39
- clock(now);
40
- const rows = history(), valid = rows.filter(e => e.value.type === 'consented').filter(e => { const g = e.value.grant; return g.manifestId === manifestId && g.purpose === purpose && now < g.expiresAt && !rows.some(r => r.value.type === 'revoked' && r.value.consentId === e.value.consentId); });
41
- if (valid.length !== 1)
42
- throw Error('unique active manifest/purpose consent required');
43
- if (!Number.isSafeInteger(maxBytes) || maxBytes < 0 || maxBytes > 8 * 1024 * 1024)
44
- throw Error('archive read bound');
45
- const used = inspect();
46
- if (used.calls >= policy.maxCalls || maxBytes > policy.maxBytes - used.bytes)
47
- throw Error('shared archive budget exhausted');
48
- const claim = journal.append(rows.at(-1).id, { type: 'read-claim', manifestId, purpose, consentId: valid[0].value.consentId, reserved: maxBytes, now });
49
- const result = readArchiveSource(policy.archiveRoot, manifestId, maxBytes);
50
- journal.append(claim.id, { type: 'read-settled', claim: claim.id, bytes: result.status === 'available' ? result.bytes.length : 0, status: result.status, now });
51
- return result;
52
- },
53
- };
54
- }
55
- export function readGovernedArchive(root, manifestId, maxBytes, route, now = Date.now()) {
56
- const access = openArchiveAccess(route.directory);
57
- if (access.inspect().policy.archiveRoot !== root)
58
- throw Error('governed archive root mismatch');
59
- return access.read(manifestId, route.purpose, maxBytes, now);
60
- }
61
- //# sourceMappingURL=archive-access.js.map
@@ -1,47 +0,0 @@
1
- import { type ArchiveRead, type ArchiveSourceInput, type ArchiveRetention } from "./evidence-archive.js";
2
- export type SnapshotChange = "initial" | "append" | "replaced" | "unknown";
3
- export interface ArchiveCheckpoint {
4
- version: "archive-checkpoint-v1";
5
- sourceId: string;
6
- sourceManifestId: string;
7
- sourceSha256: string;
8
- sourceBytes: number;
9
- previousCheckpointId: string | null;
10
- lineage: string;
11
- declaredParser: {
12
- id: string;
13
- version: string;
14
- };
15
- reader: "jsonl-syntax-v1";
16
- retention: ArchiveRetention;
17
- change: SnapshotChange;
18
- syntax: "complete" | "partial" | "error" | "unavailable";
19
- completeBytes: number;
20
- pendingBytes: number;
21
- invalidLines: number;
22
- issues: string[];
23
- activeBranch: null;
24
- acceptance: "not-assessed";
25
- }
26
- export interface ArchivedRecord {
27
- id: string;
28
- line: number;
29
- start: number;
30
- end: number;
31
- value: unknown;
32
- }
33
- export interface CheckpointRead {
34
- checkpoint: ArchiveCheckpoint;
35
- source: ArchiveRead;
36
- records: ArchivedRecord[];
37
- }
38
- /** Restart from the immutable checkpoint ID. This never advances a worker or invokes a gate. */
39
- export declare function readArchiveCheckpoint(root: string, checkpointId: string): CheckpointRead;
40
- /** Caller supplies an explicit snapshot, policy and prior receipt. No inferred active branch or acceptance. */
41
- export declare function ingestArchiveSnapshot(root: string, input: ArchiveSourceInput & {
42
- previousCheckpointId?: string;
43
- }): CheckpointRead & {
44
- checkpointId: string;
45
- change: SnapshotChange | "repeat";
46
- newRecords: ArchivedRecord[];
47
- };
@@ -1,116 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { parseArchivedJsonl, readArchiveSource, retainArchiveSource, } from "./evidence-archive.js";
3
- const hash = (value) => createHash("sha256").update(value).digest("hex");
4
- const SHA = /^[a-f0-9]{64}$/;
5
- const LIMIT = 8 * 1024 * 1024;
6
- const parserEqual = (a, b) => a.id === b.id && a.version === b.version;
7
- function reject() { throw new Error("invalid archive checkpoint"); }
8
- function parseCheckpoint(bytes) {
9
- const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
10
- const v = JSON.parse(text);
11
- if (JSON.stringify(v) !== text)
12
- reject();
13
- const names = ["version", "sourceId", "sourceManifestId", "sourceSha256", "sourceBytes", "previousCheckpointId", "lineage", "declaredParser", "reader", "retention", "change", "syntax", "completeBytes", "pendingBytes", "invalidLines", "issues", "activeBranch", "acceptance"];
14
- if (!v || Object.keys(v).length !== names.length || Object.keys(v).some(k => !names.includes(k))
15
- || v.version !== "archive-checkpoint-v1" || v.reader !== "jsonl-syntax-v1"
16
- || typeof v.sourceId !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(v.sourceId)
17
- || ![v.sourceManifestId, v.sourceSha256, v.lineage].every(h => typeof h === "string" && SHA.test(h))
18
- || !(v.previousCheckpointId === null || (typeof v.previousCheckpointId === "string" && SHA.test(v.previousCheckpointId)))
19
- || ![v.sourceBytes, v.completeBytes, v.pendingBytes, v.invalidLines].every(n => Number.isSafeInteger(n) && n >= 0 && n <= LIMIT)
20
- || v.completeBytes + v.pendingBytes !== v.sourceBytes
21
- || !v.declaredParser || Object.keys(v.declaredParser).sort().join() !== "id,version"
22
- || ![v.declaredParser.id, v.declaredParser.version].every(s => typeof s === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(s))
23
- || !["exact", "redacted", "reference-only"].includes(v.retention)
24
- || !["initial", "append", "replaced", "unknown"].includes(v.change)
25
- || !["complete", "partial", "error", "unavailable"].includes(v.syntax)
26
- || (v.retention === "reference-only" && (v.syntax !== "unavailable" || v.completeBytes !== 0 || v.invalidLines !== 0))
27
- || !Array.isArray(v.issues) || v.issues.length > 16 || v.issues.some(i => typeof i !== "string" || i.length > 128)
28
- || v.activeBranch !== null || v.acceptance !== "not-assessed")
29
- reject();
30
- return v;
31
- }
32
- function records(checkpoint, source) {
33
- if (source.status !== "available")
34
- return [];
35
- const parsed = parseArchivedJsonl(source.bytes);
36
- return parsed.records.map(record => ({
37
- ...record, id: hash(JSON.stringify([checkpoint.sourceId, checkpoint.lineage, record.start, hash(source.bytes.subarray(record.start, record.end))])),
38
- }));
39
- }
40
- /** Restart from the immutable checkpoint ID. This never advances a worker or invokes a gate. */
41
- export function readArchiveCheckpoint(root, checkpointId) {
42
- const stored = readArchiveSource(root, checkpointId);
43
- if (stored.status !== "available" || stored.reference.retention !== "exact")
44
- reject();
45
- const checkpoint = parseCheckpoint(stored.bytes);
46
- const source = readArchiveSource(root, checkpoint.sourceManifestId);
47
- if (source.status === "available") {
48
- const ref = source.reference;
49
- if (ref.sourceId !== checkpoint.sourceId || ref.sha256 !== checkpoint.sourceSha256 || ref.bytes !== checkpoint.sourceBytes
50
- || ref.retention !== checkpoint.retention || !parserEqual(ref.parser, checkpoint.declaredParser))
51
- reject();
52
- const actual = parseArchivedJsonl(source.bytes);
53
- if (actual.status !== checkpoint.syntax || actual.completeBytes !== checkpoint.completeBytes
54
- || actual.pendingBytes !== checkpoint.pendingBytes || actual.errors.length !== checkpoint.invalidLines)
55
- reject();
56
- }
57
- return { checkpoint, source, records: records(checkpoint, source) };
58
- }
59
- /** Caller supplies an explicit snapshot, policy and prior receipt. No inferred active branch or acceptance. */
60
- export function ingestArchiveSnapshot(root, input) {
61
- // Inspect the prior bytes BEFORE storing this snapshot, so reacquisition cannot disguise a prior gap.
62
- const previous = input.previousCheckpointId ? readArchiveCheckpoint(root, input.previousCheckpointId) : undefined;
63
- if (previous && previous.checkpoint.sourceId !== input.sourceId)
64
- throw new Error("checkpoint source mismatch");
65
- const captured = retainArchiveSource(root, input);
66
- const source = readArchiveSource(root, captured.manifestId);
67
- const issues = [];
68
- let change = previous ? "unknown" : "initial";
69
- let lineage = captured.manifestId;
70
- if (previous) {
71
- if (!parserEqual(previous.checkpoint.declaredParser, captured.reference.parser) || previous.checkpoint.retention !== input.retention) {
72
- issues.push("parser-or-representation-changed");
73
- }
74
- else if (previous.source.status !== "available") {
75
- issues.push("previous-content-unavailable");
76
- }
77
- else if (input.retention !== "exact") {
78
- issues.push("non-exact-continuity-unknown");
79
- }
80
- else if (source.status === "available") {
81
- if (captured.manifestId === previous.checkpoint.sourceManifestId) {
82
- return { ...previous, checkpointId: input.previousCheckpointId, change: "repeat", newRecords: [] };
83
- }
84
- if (source.bytes.length >= previous.source.bytes.length && source.bytes.subarray(0, previous.source.bytes.length).equals(previous.source.bytes)) {
85
- change = "append";
86
- lineage = previous.checkpoint.lineage;
87
- }
88
- else {
89
- change = "replaced";
90
- issues.push("source-replaced");
91
- }
92
- }
93
- }
94
- if (input.retention === "redacted")
95
- issues.push("redacted-representation");
96
- if (source.status !== "available")
97
- issues.push("content-not-retained");
98
- const syntax = source.status === "available" ? parseArchivedJsonl(source.bytes) : undefined;
99
- const checkpoint = {
100
- version: "archive-checkpoint-v1", sourceId: input.sourceId,
101
- sourceManifestId: captured.manifestId, sourceSha256: captured.reference.sha256, sourceBytes: captured.reference.bytes,
102
- previousCheckpointId: input.previousCheckpointId ?? null, lineage,
103
- declaredParser: captured.reference.parser, reader: "jsonl-syntax-v1", retention: input.retention, change,
104
- syntax: syntax?.status ?? "unavailable", completeBytes: syntax?.completeBytes ?? 0,
105
- pendingBytes: syntax?.pendingBytes ?? captured.reference.bytes, invalidLines: syntax?.errors.length ?? 0,
106
- issues, activeBranch: null, acceptance: "not-assessed",
107
- };
108
- const result = retainArchiveSource(root, {
109
- sourceId: `checkpoint-${hash(input.sourceId)}`, parser: { id: "archive-checkpoint", version: "1" },
110
- retention: "exact", bytes: Buffer.from(JSON.stringify(checkpoint)),
111
- });
112
- const all = records(checkpoint, source);
113
- return { checkpointId: result.manifestId, checkpoint, source, records: all, change,
114
- newRecords: change === "append" ? all.filter(record => record.start >= previous.checkpoint.completeBytes) : all };
115
- }
116
- //# sourceMappingURL=archive-checkpoint.js.map
@@ -1,19 +0,0 @@
1
- import type { WorkSignalFacts } from '@skill-harness/core';
2
- import { type GovernedArchiveRoute } from './archive-access.js';
3
- /** Operational fixed-order fact adapter, not arbitrary model/host fact inference.
4
- * The caller supplies independent scope/source pins; all actual bytes use consent. */
5
- export declare function readFixedOrderFacts(root: string, manifestId: string, route: GovernedArchiveRoute, raw: {
6
- producerCommit: string;
7
- scopeDigest: string;
8
- population: string;
9
- obligations: string[];
10
- }, now?: number): {
11
- facts: WorkSignalFacts;
12
- source: {
13
- manifestId: string;
14
- sha256: string;
15
- producerCommit: string;
16
- };
17
- unknownNodes: any;
18
- acceptance: "not-assessed";
19
- };
@@ -1,20 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { readGovernedArchive } from './archive-access.js';
3
- import { learningCopy } from './learning-journal.js';
4
- /** Operational fixed-order fact adapter, not arbitrary model/host fact inference.
5
- * The caller supplies independent scope/source pins; all actual bytes use consent. */
6
- export function readFixedOrderFacts(root, manifestId, route, raw, now = Date.now()) {
7
- const expected = learningCopy(raw);
8
- if (!/^[a-f0-9]{40}$/.test(expected.producerCommit) || !/^[a-f0-9]{64}$/.test(expected.scopeDigest) || typeof expected.population !== 'string' || !expected.population.length || expected.population.length > 512 || /[\u0000-\u001f\u007f]/.test(expected.population) || !Array.isArray(expected.obligations) || expected.obligations.length > 128 || expected.obligations.some(h => !/^[a-f0-9]{64}$/.test(h)))
9
- throw Error('explicit fact source/scope pins required');
10
- const read = readGovernedArchive(root, manifestId, 1024 * 1024, route, now);
11
- if (read.status !== 'available' || read.reference.retention !== 'exact' || read.reference.parser.id !== 'factory-order-readback' || read.reference.parser.version !== '1')
12
- throw Error('exact governed order readback required');
13
- const value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(read.bytes));
14
- if (value.kind !== 'actual-fixed-profile-order' || value.producerCommit !== expected.producerCommit || !Array.isArray(value.nodes) || !value.nodes.length || value.nodes.length > 128 || value.nodes.some((n) => !n || !expected.obligations.includes(n.obligation?.digest) || typeof n.state !== 'string'))
15
- throw Error('order facts source/scope mismatch');
16
- const digest = createHash('sha256').update(read.bytes).digest('hex');
17
- const facts = { scopeDigest: expected.scopeDigest, version: 'fixed-order-facts-v1', population: expected.population, expectedWaits: [], checkpoints: [], violations: value.nodes.filter((n) => n.state === 'exhausted').map((n) => ({ obligationDigest: n.obligation.digest, status: 'FAIL', evidence: digest })), priorAccepted: [] };
18
- return { facts, source: { manifestId, sha256: digest, producerCommit: expected.producerCommit }, unknownNodes: value.nodes.filter((n) => !['satisfied', 'exhausted'].includes(n.state)).length, acceptance: 'not-assessed' };
19
- }
20
- //# sourceMappingURL=archive-facts.js.map