owlrunkit 0.19.1 → 0.20.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 (42) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +107 -3
  3. package/docs/architecture/OWLCODA_RUNKIT_0191_PROFILE_RECONCILE_PATCH_PRODUCT_DECISION_20260813.md +11 -5
  4. package/docs/architecture/OWLCODA_RUNKIT_0192_FORMAL_USABILITY_PRODUCT_DECISION_20260813.md +141 -0
  5. package/docs/architecture/OWLCODA_RUNKIT_020_TEAM_DELIVERY_PHASE1_PRODUCT_DECISION_20260813.md +296 -0
  6. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +74 -9
  7. package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
  8. package/package.json +1 -1
  9. package/packages/attest/distribution-manifest-v1.json +10 -0
  10. package/packages/attest/src/quick.mjs +42 -4
  11. package/registry-release-policy-v1.json +5 -5
  12. package/sbom.spdx.json +5 -5
  13. package/scripts/runkit-contract/core-contract.mjs +42 -2
  14. package/scripts/runkit-contract/efficiency-metrics.mjs +9 -7
  15. package/scripts/runkit-contract/formal-preflight.mjs +352 -0
  16. package/scripts/runkit-contract/formal-supplemental-evidence.mjs +713 -0
  17. package/scripts/runkit-contract/formal-workflow.mjs +529 -59
  18. package/scripts/runkit-contract/onboarding-doctor.mjs +32 -13
  19. package/scripts/runkit-contract/project-cli-resolver.mjs +33 -3
  20. package/scripts/runkit-contract/project-external-delivery.mjs +16 -9
  21. package/scripts/runkit-contract/quick-attest.mjs +24 -0
  22. package/scripts/runkit-contract/runkit-cli.mjs +445 -52
  23. package/scripts/runkit-contract/schemas/candidate-transfer-packet-v1.schema.json +98 -0
  24. package/scripts/runkit-contract/schemas/formal-check-v2.schema.json +231 -0
  25. package/scripts/runkit-contract/schemas/formal-envelope-preflight-v1.schema.json +212 -0
  26. package/scripts/runkit-contract/schemas/formal-evidence-summary-v1.schema.json +114 -0
  27. package/scripts/runkit-contract/schemas/formal-supplemental-evidence-v1.schema.json +103 -0
  28. package/scripts/runkit-contract/schemas/team-acceptance-packet-v2.schema.json +109 -0
  29. package/scripts/runkit-contract/schemas/team-delivery-status-v1.schema.json +72 -0
  30. package/scripts/runkit-contract/schemas/team-packet-validation-v1.schema.json +33 -0
  31. package/scripts/runkit-contract/schemas/team-project-event-v5.schema.json +89 -0
  32. package/scripts/runkit-contract/schemas/team-project-status-v3.schema.json +173 -0
  33. package/scripts/runkit-contract/schemas/team-recommendation-v1.schema.json +121 -0
  34. package/scripts/runkit-contract/schemas/team-task-packet-v2.schema.json +228 -0
  35. package/scripts/runkit-contract/snapshot.mjs +125 -5
  36. package/scripts/runkit-contract/source-candidate.mjs +271 -69
  37. package/scripts/runkit-contract/sync-release-identity.mjs +39 -4
  38. package/scripts/runkit-contract/team-delivery.mjs +906 -0
  39. package/scripts/runkit-contract/team-project-successor.mjs +7 -4
  40. package/scripts/runkit-contract/team-project.mjs +440 -28
  41. package/scripts/runkit-contract/usage-mode.mjs +9 -3
  42. package/scripts/runkit-contract/verification-envelope.mjs +425 -37
@@ -0,0 +1,713 @@
1
+ import {
2
+ existsSync,
3
+ lstatSync,
4
+ mkdirSync,
5
+ readFileSync,
6
+ readdirSync,
7
+ realpathSync,
8
+ } from "node:fs";
9
+ import path from "node:path";
10
+
11
+ import {
12
+ attestCoreBoundQuickReceiptDetailsFromBytes,
13
+ } from "./quick-attest.mjs";
14
+ import {
15
+ decodeUtf8Strict,
16
+ parseJsonStrict,
17
+ readFileBytesBounded,
18
+ } from "../../packages/attest/src/formal.mjs";
19
+ import { persistEvidenceBytes } from "./evidence-store.mjs";
20
+ import { readFormalChecksV1 } from "./formal-workflow.mjs";
21
+ import {
22
+ readWorkspaceBytesBounded,
23
+ readWorkspaceFileBounded,
24
+ readWorkspaceJsonBounded,
25
+ } from "./onboarding-doctor.mjs";
26
+ import { withControlTransaction } from "./lease-lifecycle.mjs";
27
+ import {
28
+ loadActiveExecution,
29
+ relativeToWorkspace,
30
+ safeIdentifier,
31
+ safeRelativePath,
32
+ sha256,
33
+ writeJsonExclusiveAtomically,
34
+ } from "./provenance-common.mjs";
35
+ import { verifySourceCandidateDetailsV2 } from "./source-candidate.mjs";
36
+
37
+ const SUPPLEMENTAL_SCHEMA = "OwlCodaRunKitFormalSupplementalEvidenceV1";
38
+ const SUMMARY_SCHEMA = "OwlCodaRunKitFormalEvidenceSummaryV1";
39
+ const KINDS = new Set(["supplemental-local", "networked"]);
40
+
41
+ function canonical(value) {
42
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
43
+ if (value && typeof value === "object") {
44
+ return `{${Object.keys(value).sort()
45
+ .map(key => `${JSON.stringify(key)}:${canonical(value[key])}`)
46
+ .join(",")}}`;
47
+ }
48
+ const encoded = JSON.stringify(value);
49
+ if (encoded === undefined) throw new Error("Formal supplemental evidence is not canonical JSON.");
50
+ return encoded;
51
+ }
52
+
53
+ function within(root, candidate) {
54
+ const relative = path.relative(root, candidate);
55
+ return relative === ""
56
+ || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
57
+ }
58
+
59
+ function readRegularJson(filePath, label) {
60
+ try {
61
+ const { bytes } = readFileBytesBounded(filePath);
62
+ return parseJsonStrict(decodeUtf8Strict(bytes));
63
+ } catch (error) {
64
+ throw new Error(`${label} must be a bounded regular JSON file without symlinks.`, {
65
+ cause: error,
66
+ });
67
+ }
68
+ }
69
+
70
+ function writeOrResume(filePath, value, label) {
71
+ if (!existsSync(filePath)) {
72
+ writeJsonExclusiveAtomically(filePath, value);
73
+ return { value, resumed: false };
74
+ }
75
+ const existing = readRegularJson(filePath, label);
76
+ if (canonical(existing) !== canonical(value)) {
77
+ throw new Error(`Existing ${label} differs from the resumed command.`);
78
+ }
79
+ return { value: existing, resumed: true };
80
+ }
81
+
82
+ function supplementalRoot(executionRoot) {
83
+ return path.join(executionRoot, "formal-supplemental-evidence");
84
+ }
85
+
86
+ function ensureRegularDirectory(directory, label) {
87
+ if (!existsSync(directory)) mkdirSync(directory, { recursive: true });
88
+ const stat = lstatSync(directory);
89
+ if (
90
+ stat.isSymbolicLink()
91
+ || !stat.isDirectory()
92
+ || realpathSync(directory) !== path.resolve(directory)
93
+ ) {
94
+ throw new Error(`${label} must be a regular directory without symlinks.`);
95
+ }
96
+ }
97
+
98
+ function exactKeys(value, expected) {
99
+ return value !== null
100
+ && typeof value === "object"
101
+ && !Array.isArray(value)
102
+ && Object.keys(value).sort().join("\0") === [...expected].sort().join("\0");
103
+ }
104
+
105
+ function validHash(value, prefixed = false) {
106
+ return new RegExp(prefixed ? "^sha256:[a-f0-9]{64}$" : "^[a-f0-9]{64}$", "u")
107
+ .test(value ?? "");
108
+ }
109
+
110
+ function frozenQuickMaterials({ workspaceRoot, receiptPath, attestation }) {
111
+ const receiptRoot = path.dirname(receiptPath);
112
+ return attestation.verifiedMaterials
113
+ .filter(material => within(receiptRoot, material.path) || material.path === receiptPath)
114
+ .map(material => {
115
+ const { bytes, absolutePath } = readFileBytesBounded(material.path);
116
+ if (absolutePath !== material.path) {
117
+ throw new Error("Formal supplemental material path must not use symlinks.");
118
+ }
119
+ const stored = persistEvidenceBytes({
120
+ workspaceRoot,
121
+ bytes,
122
+ encoding: "raw",
123
+ });
124
+ if (stored.sha256 !== material.sha256) {
125
+ throw new Error("Formal supplemental material changed after Quick attestation.");
126
+ }
127
+ return {
128
+ sourcePath: relativeToWorkspace(workspaceRoot, material.path),
129
+ evidenceObjectPath: stored.path,
130
+ sha256: stored.sha256,
131
+ sizeBytes: stored.sizeBytes,
132
+ };
133
+ })
134
+ .sort((left, right) => left.sourcePath.localeCompare(right.sourcePath, "en"));
135
+ }
136
+
137
+ function validateFrozenMaterial(value, workspaceRoot) {
138
+ if (!exactKeys(value, [
139
+ "sourcePath", "evidenceObjectPath", "sha256", "sizeBytes",
140
+ ])) return false;
141
+ let sourcePath;
142
+ let evidenceObjectPath;
143
+ try {
144
+ sourcePath = safeRelativePath(value.sourcePath, "frozen material sourcePath");
145
+ evidenceObjectPath = safeRelativePath(
146
+ value.evidenceObjectPath,
147
+ "frozen material evidenceObjectPath",
148
+ );
149
+ } catch {
150
+ return false;
151
+ }
152
+ if (
153
+ sourcePath !== value.sourcePath
154
+ || evidenceObjectPath !== value.evidenceObjectPath
155
+ || !evidenceObjectPath.startsWith(".owlcoda/runkit/evidence/raw-sha256/")
156
+ || !validHash(value.sha256, true)
157
+ || !Number.isSafeInteger(value.sizeBytes)
158
+ || value.sizeBytes < 0
159
+ ) return false;
160
+ try {
161
+ const bytes = readWorkspaceBytesBounded(
162
+ workspaceRoot,
163
+ evidenceObjectPath,
164
+ { maxBytes: Math.max(value.sizeBytes, 1) },
165
+ );
166
+ const sourceBytes = readWorkspaceBytesBounded(
167
+ workspaceRoot,
168
+ sourcePath,
169
+ { maxBytes: Math.max(value.sizeBytes, 1) },
170
+ );
171
+ return bytes.byteLength === value.sizeBytes
172
+ && sourceBytes.byteLength === value.sizeBytes
173
+ && `sha256:${sha256(bytes)}` === value.sha256
174
+ && `sha256:${sha256(sourceBytes)}` === value.sha256;
175
+ } catch {
176
+ return false;
177
+ }
178
+ }
179
+
180
+ function validateSupplemental(value, { runId, evidenceId, workspaceRoot }) {
181
+ const { supplementalEvidenceSha256, ...body } = value ?? {};
182
+ let receiptPath;
183
+ let candidatePath;
184
+ try {
185
+ receiptPath = safeRelativePath(value?.quickEvidence?.receiptPath, "receiptPath");
186
+ candidatePath = safeRelativePath(value?.sourceBinding?.candidatePath, "candidatePath");
187
+ } catch {
188
+ return false;
189
+ }
190
+ return exactKeys(value, [
191
+ "schemaVersion", "runId", "evidenceId", "kind", "classificationBasis",
192
+ "status", "gating", "sourceBinding", "quickEvidence", "limitations",
193
+ "frozenMaterials", "authorizationGranted", "supplementalEvidenceSha256",
194
+ ])
195
+ && value.schemaVersion === SUPPLEMENTAL_SCHEMA
196
+ && value.runId === runId
197
+ && value.evidenceId === evidenceId
198
+ && KINDS.has(value.kind)
199
+ && value.classificationBasis === "operator_declared_not_attested"
200
+ && value.status === "attached"
201
+ && value.gating === false
202
+ && value.authorizationGranted === false
203
+ && supplementalEvidenceSha256 === sha256(canonical(body))
204
+ && exactKeys(value.sourceBinding, [
205
+ "candidatePath", "candidateSha256", "sourceFingerprint", "quickWorkspaceFingerprint",
206
+ ])
207
+ && candidatePath === value.sourceBinding.candidatePath
208
+ && validHash(value.sourceBinding.candidateSha256, true)
209
+ && validHash(value.sourceBinding.sourceFingerprint)
210
+ && validHash(value.sourceBinding.quickWorkspaceFingerprint, true)
211
+ && exactKeys(value.quickEvidence, [
212
+ "receiptId", "receiptPath", "receiptSha256", "receiptSchemaVersion",
213
+ "exactCommand", "attestationDecision", "attestationIssueCodes",
214
+ ])
215
+ && receiptPath === value.quickEvidence.receiptPath
216
+ && typeof value.quickEvidence.receiptId === "string"
217
+ && value.quickEvidence.receiptId.length > 0
218
+ && validHash(value.quickEvidence.receiptSha256, true)
219
+ && typeof value.quickEvidence.receiptSchemaVersion === "string"
220
+ && value.quickEvidence.receiptSchemaVersion.length > 0
221
+ && value.quickEvidence.exactCommand !== null
222
+ && typeof value.quickEvidence.exactCommand === "object"
223
+ && !Array.isArray(value.quickEvidence.exactCommand)
224
+ && value.quickEvidence.attestationDecision === "GO"
225
+ && Array.isArray(value.quickEvidence.attestationIssueCodes)
226
+ && value.quickEvidence.attestationIssueCodes.every(code => typeof code === "string")
227
+ && Array.isArray(value.frozenMaterials)
228
+ && value.frozenMaterials.length > 0
229
+ && value.frozenMaterials.every(material => validateFrozenMaterial(material, workspaceRoot))
230
+ && value.frozenMaterials.some(material => (
231
+ material.sourcePath === value.quickEvidence.receiptPath
232
+ && material.sha256 === value.quickEvidence.receiptSha256
233
+ ))
234
+ && Array.isArray(value.limitations)
235
+ && value.limitations.length > 0
236
+ && value.limitations.every(limit => typeof limit === "string" && limit.length > 0);
237
+ }
238
+
239
+ function readSupplementals(workspaceRoot, executionRoot, runId) {
240
+ const root = supplementalRoot(executionRoot);
241
+ if (!existsSync(root)) return [];
242
+ const stat = lstatSync(root);
243
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
244
+ throw new Error("Formal supplemental evidence root must be a regular directory.");
245
+ }
246
+ return readdirSync(root, { withFileTypes: true })
247
+ .filter(entry => entry.name.endsWith(".json"))
248
+ .sort((left, right) => left.name.localeCompare(right.name))
249
+ .map(entry => {
250
+ if (entry.isSymbolicLink() || !entry.isFile()) {
251
+ throw new Error(`Formal supplemental evidence must be a regular file: ${entry.name}`);
252
+ }
253
+ const artifactPath = path.join(root, entry.name);
254
+ const value = readWorkspaceJsonBounded(
255
+ workspaceRoot,
256
+ relativeToWorkspace(workspaceRoot, artifactPath),
257
+ );
258
+ const evidenceId = entry.name.slice(0, -".json".length);
259
+ if (!validateSupplemental(value, { runId, evidenceId, workspaceRoot })) {
260
+ throw new Error(`Formal supplemental evidence contract is invalid: ${entry.name}`);
261
+ }
262
+ return value;
263
+ });
264
+ }
265
+
266
+ function latestCurrentCandidate({ workspaceRoot, executionRoot, runId }) {
267
+ const checks = readFormalChecksV1({ workspaceRoot, executionRoot, runId });
268
+ if (checks.length === 0) {
269
+ throw new Error("Formal supplemental evidence requires at least one existing Formal check candidate.");
270
+ }
271
+ const latest = checks.at(-1);
272
+ const details = verifySourceCandidateDetailsV2({
273
+ workspaceRoot,
274
+ candidatePath: latest.candidatePath,
275
+ });
276
+ if (
277
+ details.gate.status !== "valid"
278
+ || details.gate.candidatePath !== latest.candidatePath
279
+ || details.gate.candidateSha256 !== latest.candidateSha256
280
+ || details.gate.sourceFingerprint !== latest.sourceFingerprint
281
+ ) {
282
+ throw new Error("Formal supplemental evidence requires the latest source candidate to remain current.");
283
+ }
284
+ const candidate = details.candidateDocument;
285
+ return { checks, latest, candidate };
286
+ }
287
+
288
+ function quickReceiptMatchesCandidate(receipt, candidate) {
289
+ if (receipt.workspaceAfter.headCommit !== candidate.baseline.head) return false;
290
+ const expected = new Map();
291
+ for (const entry of candidate.sourceManifest.entries) {
292
+ if (entry.operation === "deleted") {
293
+ expected.set(entry.path, { path: entry.path, state: "deleted", sha256: null });
294
+ continue;
295
+ }
296
+ if (entry.operation === "renamed") {
297
+ expected.set(entry.previousPath, {
298
+ path: entry.previousPath,
299
+ state: "deleted",
300
+ sha256: null,
301
+ });
302
+ }
303
+ expected.set(entry.path, {
304
+ path: entry.path,
305
+ state: entry.status === "??" ? "untracked" : "modified",
306
+ sha256: `sha256:${entry.sha256}`,
307
+ });
308
+ }
309
+ const actual = [...receipt.workspaceAfter.dirtyOverlay]
310
+ .sort((left, right) => left.path.localeCompare(right.path, "en"));
311
+ const projected = [...expected.values()]
312
+ .sort((left, right) => left.path.localeCompare(right.path, "en"));
313
+ return canonical(actual) === canonical(projected);
314
+ }
315
+
316
+ function attachWithinControlTransaction({
317
+ workspaceRoot,
318
+ runId,
319
+ evidenceId,
320
+ kind,
321
+ receiptPath,
322
+ }) {
323
+ safeIdentifier(evidenceId, "evidenceId");
324
+ if (!KINDS.has(kind)) {
325
+ throw new Error("Formal supplemental evidence kind must be supplemental-local or networked.");
326
+ }
327
+ const root = realpathSync(workspaceRoot);
328
+ const { executionRoot, pinGate } = loadActiveExecution(root, runId);
329
+ if (pinGate.status !== "valid") return { ...pinGate, authorizationGranted: false };
330
+ if (existsSync(path.join(executionRoot, "closeout-receipt.json"))) {
331
+ throw new Error(`Execution is already closed: ${runId}`);
332
+ }
333
+ const requestedPath = path.resolve(receiptPath);
334
+ if (!within(root, requestedPath)) {
335
+ throw new Error("Formal supplemental Quick receipt must remain inside the workspace.");
336
+ }
337
+ const requestedRelativePath = relativeToWorkspace(root, requestedPath);
338
+ const requestedText = readWorkspaceFileBounded(root, requestedRelativePath);
339
+ const requestedReceipt = {
340
+ absolutePath: requestedPath,
341
+ bytes: Buffer.from(requestedText, "utf8"),
342
+ };
343
+ const receipt = parseJsonStrict(decodeUtf8Strict(requestedReceipt.bytes));
344
+ const attested = attestCoreBoundQuickReceiptDetailsFromBytes({
345
+ receiptPath: requestedReceipt.absolutePath,
346
+ receiptBytes: requestedReceipt.bytes,
347
+ workspaceRoot: root,
348
+ });
349
+ if (attested.attestation.decision !== "GO") {
350
+ throw new Error(
351
+ `Formal supplemental Quick attestation must be GO: ${attested.attestation.issueCodes.join(",")}.`,
352
+ );
353
+ }
354
+ const { latest, candidate } = latestCurrentCandidate({
355
+ workspaceRoot: root,
356
+ executionRoot,
357
+ runId,
358
+ });
359
+ if (!quickReceiptMatchesCandidate(receipt, candidate)) {
360
+ throw new Error("Formal supplemental Quick receipt does not describe the current source candidate.");
361
+ }
362
+ const frozenMaterials = frozenQuickMaterials({
363
+ workspaceRoot: root,
364
+ receiptPath: requestedReceipt.absolutePath,
365
+ attestation: attested.attestation,
366
+ });
367
+ if (frozenMaterials.length === 0) {
368
+ throw new Error("Formal supplemental evidence requires frozen Quick receipt materials.");
369
+ }
370
+ const body = {
371
+ schemaVersion: SUPPLEMENTAL_SCHEMA,
372
+ runId,
373
+ evidenceId,
374
+ kind,
375
+ classificationBasis: "operator_declared_not_attested",
376
+ status: "attached",
377
+ gating: false,
378
+ sourceBinding: {
379
+ candidatePath: latest.candidatePath,
380
+ candidateSha256: candidate.candidateSha256,
381
+ sourceFingerprint: latest.sourceFingerprint,
382
+ quickWorkspaceFingerprint: attested.sourceFingerprint,
383
+ },
384
+ quickEvidence: {
385
+ receiptId: receipt.receiptId,
386
+ receiptPath: requestedRelativePath,
387
+ receiptSha256: attested.attestation.subjectRef.receiptSha256,
388
+ receiptSchemaVersion: receipt.schemaVersion,
389
+ exactCommand: structuredClone(receipt.exactCommand),
390
+ attestationDecision: attested.attestation.decision,
391
+ attestationIssueCodes: [...attested.attestation.issueCodes],
392
+ },
393
+ limitations: [
394
+ "supplemental_evidence_is_not_formal_sandbox_evidence",
395
+ "network_classification_is_operator_declared_not_attested",
396
+ "supplemental_evidence_cannot_grant_acceptance_or_authority",
397
+ ],
398
+ frozenMaterials,
399
+ authorizationGranted: false,
400
+ };
401
+ const value = {
402
+ ...body,
403
+ supplementalEvidenceSha256: sha256(canonical(body)),
404
+ };
405
+ const evidenceRoot = supplementalRoot(executionRoot);
406
+ ensureRegularDirectory(evidenceRoot, "Formal supplemental evidence root");
407
+ const artifactPath = path.join(evidenceRoot, `${evidenceId}.json`);
408
+ const written = writeOrResume(artifactPath, value, "Formal supplemental evidence");
409
+ return {
410
+ status: "formal_supplemental_evidence_attached",
411
+ exitCode: 0,
412
+ runId,
413
+ evidenceId,
414
+ kind,
415
+ sourceFingerprint: latest.sourceFingerprint,
416
+ quickWorkspaceFingerprint: attested.sourceFingerprint,
417
+ evidencePath: relativeToWorkspace(root, artifactPath),
418
+ supplementalEvidenceSha256: written.value.supplementalEvidenceSha256,
419
+ gating: false,
420
+ resumed: written.resumed,
421
+ authorizationGranted: false,
422
+ };
423
+ }
424
+
425
+ export function attachFormalSupplementalEvidenceV1(options) {
426
+ const root = realpathSync(options.workspaceRoot);
427
+ return withControlTransaction(root, () => attachWithinControlTransaction({
428
+ ...options,
429
+ workspaceRoot: root,
430
+ }));
431
+ }
432
+
433
+ export function summarizeFormalEvidenceWithinControlTransaction({
434
+ workspaceRoot,
435
+ runId,
436
+ summaryId,
437
+ }) {
438
+ safeIdentifier(summaryId, "summaryId");
439
+ const root = realpathSync(workspaceRoot);
440
+ const { executionRoot, pinGate } = loadActiveExecution(root, runId);
441
+ if (pinGate.status !== "valid") return { ...pinGate, authorizationGranted: false };
442
+ const { checks, latest, candidate } = latestCurrentCandidate({
443
+ workspaceRoot: root,
444
+ executionRoot,
445
+ runId,
446
+ });
447
+ const allSupplemental = readSupplementals(root, executionRoot, runId);
448
+ const currentSupplemental = allSupplemental.filter(row => (
449
+ row.runId === runId
450
+ && row.sourceBinding.candidatePath === latest.candidatePath
451
+ && row.sourceBinding.sourceFingerprint === latest.sourceFingerprint
452
+ && row.sourceBinding.candidateSha256 === candidate.candidateSha256
453
+ ));
454
+ for (const row of currentSupplemental) {
455
+ const receiptText = readWorkspaceFileBounded(
456
+ root,
457
+ row.quickEvidence.receiptPath,
458
+ );
459
+ const quickReceipt = {
460
+ absolutePath: path.join(root, row.quickEvidence.receiptPath),
461
+ bytes: Buffer.from(receiptText, "utf8"),
462
+ };
463
+ const receipt = parseJsonStrict(decodeUtf8Strict(quickReceipt.bytes));
464
+ const attested = attestCoreBoundQuickReceiptDetailsFromBytes({
465
+ receiptPath: quickReceipt.absolutePath,
466
+ receiptBytes: quickReceipt.bytes,
467
+ workspaceRoot: root,
468
+ });
469
+ if (
470
+ attested.attestation.decision !== "GO"
471
+ || attested.attestation.subjectRef.receiptSha256
472
+ !== row.quickEvidence.receiptSha256
473
+ || attested.sourceFingerprint
474
+ !== row.sourceBinding.quickWorkspaceFingerprint
475
+ || receipt.receiptId !== row.quickEvidence.receiptId
476
+ || receipt.schemaVersion !== row.quickEvidence.receiptSchemaVersion
477
+ || canonical(receipt.exactCommand) !== canonical(row.quickEvidence.exactCommand)
478
+ || canonical(attested.attestation.issueCodes)
479
+ !== canonical(row.quickEvidence.attestationIssueCodes)
480
+ || !quickReceiptMatchesCandidate(receipt, candidate)
481
+ ) {
482
+ throw new Error(
483
+ `Formal supplemental Quick attestation must remain GO: ${row.evidenceId}.`,
484
+ );
485
+ }
486
+ }
487
+ const currentChecks = checks.filter(row => (
488
+ row.sourceFingerprint === latest.sourceFingerprint
489
+ && row.verificationContextFingerprint
490
+ === latest.verificationContextFingerprint
491
+ ));
492
+ const body = {
493
+ schemaVersion: SUMMARY_SCHEMA,
494
+ runId,
495
+ summaryId,
496
+ sourceBinding: {
497
+ candidatePath: latest.candidatePath,
498
+ candidateSha256: candidate.candidateSha256,
499
+ sourceFingerprint: latest.sourceFingerprint,
500
+ },
501
+ formalChecks: currentChecks.map(row => ({
502
+ checkId: row.checkId,
503
+ status: row.status,
504
+ failureCategory: row.failureCategory ?? null,
505
+ formalEligible: row.status === "formal_check_passed",
506
+ snapshotPath: row.snapshotPath,
507
+ envelopeReceiptPath: row.envelopeReceiptPath ?? null,
508
+ })),
509
+ supplementalEvidence: currentSupplemental.map(row => ({
510
+ evidenceId: row.evidenceId,
511
+ kind: row.kind,
512
+ classificationBasis: row.classificationBasis,
513
+ evidencePath: relativeToWorkspace(
514
+ root,
515
+ path.join(supplementalRoot(executionRoot), `${row.evidenceId}.json`),
516
+ ),
517
+ supplementalEvidenceSha256: row.supplementalEvidenceSha256,
518
+ gating: false,
519
+ })),
520
+ staleFormalCheckCount: checks.length - currentChecks.length,
521
+ staleSupplementalEvidenceCount: allSupplemental.length - currentSupplemental.length,
522
+ formalAcceptanceDerivedOnlyFromFormalChecks: true,
523
+ limitations: [
524
+ "supplemental_evidence_is_non_gating",
525
+ "network_classification_is_operator_declared_not_attested",
526
+ "source_acceptance_does_not_grant_git_release_deployment_or_business_authority",
527
+ ],
528
+ authorizationGranted: false,
529
+ };
530
+ const value = { ...body, evidenceSummarySha256: sha256(canonical(body)) };
531
+ const artifactPath = path.join(
532
+ executionRoot,
533
+ "formal-evidence-summaries",
534
+ `${summaryId}.json`,
535
+ );
536
+ ensureRegularDirectory(
537
+ path.dirname(artifactPath),
538
+ "Formal evidence summary root",
539
+ );
540
+ const written = writeOrResume(artifactPath, value, "Formal evidence summary");
541
+ return {
542
+ status: "formal_evidence_summarized",
543
+ exitCode: 0,
544
+ runId,
545
+ evidenceSummaryPath: relativeToWorkspace(root, artifactPath),
546
+ evidenceSummarySha256: written.value.evidenceSummarySha256,
547
+ formalCheckCount: written.value.formalChecks.length,
548
+ supplementalEvidenceCount: written.value.supplementalEvidence.length,
549
+ staleSupplementalEvidenceCount: written.value.staleSupplementalEvidenceCount,
550
+ resumed: written.resumed,
551
+ authorizationGranted: false,
552
+ };
553
+ }
554
+
555
+ export function summarizeFormalEvidenceV1(options) {
556
+ const root = realpathSync(options.workspaceRoot);
557
+ return withControlTransaction(root, () => summarizeFormalEvidenceWithinControlTransaction({
558
+ ...options,
559
+ workspaceRoot: root,
560
+ }));
561
+ }
562
+
563
+ function validateSummaryDocument(value, {
564
+ workspaceRoot,
565
+ runId,
566
+ summaryId,
567
+ }) {
568
+ const { evidenceSummarySha256, ...body } = value ?? {};
569
+ if (
570
+ !exactKeys(value, [
571
+ "schemaVersion",
572
+ "runId",
573
+ "summaryId",
574
+ "sourceBinding",
575
+ "formalChecks",
576
+ "supplementalEvidence",
577
+ "staleFormalCheckCount",
578
+ "staleSupplementalEvidenceCount",
579
+ "formalAcceptanceDerivedOnlyFromFormalChecks",
580
+ "limitations",
581
+ "authorizationGranted",
582
+ "evidenceSummarySha256",
583
+ ])
584
+ || value.schemaVersion !== SUMMARY_SCHEMA
585
+ || value.runId !== runId
586
+ || value.summaryId !== summaryId
587
+ || evidenceSummarySha256 !== sha256(canonical(body))
588
+ || !exactKeys(value.sourceBinding, [
589
+ "candidatePath", "candidateSha256", "sourceFingerprint",
590
+ ])
591
+ || !validHash(value.sourceBinding.candidateSha256, true)
592
+ || !validHash(value.sourceBinding.sourceFingerprint)
593
+ || !Array.isArray(value.formalChecks)
594
+ || !Array.isArray(value.supplementalEvidence)
595
+ || !Number.isSafeInteger(value.staleFormalCheckCount)
596
+ || value.staleFormalCheckCount < 0
597
+ || !Number.isSafeInteger(value.staleSupplementalEvidenceCount)
598
+ || value.staleSupplementalEvidenceCount < 0
599
+ || value.formalAcceptanceDerivedOnlyFromFormalChecks !== true
600
+ || !Array.isArray(value.limitations)
601
+ || value.limitations.length === 0
602
+ || value.limitations.some(limit => typeof limit !== "string" || limit.length === 0)
603
+ || value.authorizationGranted !== false
604
+ ) {
605
+ throw new Error("Formal evidence summary contract is invalid.");
606
+ }
607
+ for (const check of value.formalChecks) {
608
+ if (
609
+ !exactKeys(check, [
610
+ "checkId",
611
+ "status",
612
+ "failureCategory",
613
+ "formalEligible",
614
+ "snapshotPath",
615
+ "envelopeReceiptPath",
616
+ ])
617
+ || typeof check.checkId !== "string"
618
+ || !new Set(["formal_check_passed", "formal_check_failed"]).has(check.status)
619
+ || typeof check.snapshotPath !== "string"
620
+ || !(check.envelopeReceiptPath === null
621
+ || typeof check.envelopeReceiptPath === "string")
622
+ || (check.status === "formal_check_passed"
623
+ ? check.formalEligible !== true || check.failureCategory !== null
624
+ : check.formalEligible !== false
625
+ || !new Set([
626
+ "source_check_failed",
627
+ "envelope_capability_missing",
628
+ "toolchain_resolution_failed",
629
+ "network_policy_blocked",
630
+ ]).has(check.failureCategory))
631
+ ) {
632
+ throw new Error("Formal evidence summary check contract is invalid.");
633
+ }
634
+ }
635
+ for (const row of value.supplementalEvidence) {
636
+ if (!exactKeys(row, [
637
+ "evidenceId",
638
+ "kind",
639
+ "classificationBasis",
640
+ "evidencePath",
641
+ "supplementalEvidenceSha256",
642
+ "gating",
643
+ ])) {
644
+ throw new Error("Formal evidence summary supplemental row is invalid.");
645
+ }
646
+ safeIdentifier(row.evidenceId, "evidenceId");
647
+ const expectedPath = `.owlcoda/runkit/executions/${runId}`
648
+ + `/formal-supplemental-evidence/${row.evidenceId}.json`;
649
+ if (
650
+ row.evidencePath !== expectedPath
651
+ || !KINDS.has(row.kind)
652
+ || row.classificationBasis !== "operator_declared_not_attested"
653
+ || !validHash(row.supplementalEvidenceSha256)
654
+ || row.gating !== false
655
+ ) {
656
+ throw new Error("Formal evidence summary supplemental row is invalid.");
657
+ }
658
+ const artifact = readWorkspaceJsonBounded(workspaceRoot, row.evidencePath);
659
+ if (
660
+ !validateSupplemental(artifact, {
661
+ runId,
662
+ evidenceId: row.evidenceId,
663
+ workspaceRoot,
664
+ })
665
+ || artifact.supplementalEvidenceSha256
666
+ !== row.supplementalEvidenceSha256
667
+ ) {
668
+ throw new Error("Formal evidence summary supplemental binding is invalid.");
669
+ }
670
+ }
671
+ return value;
672
+ }
673
+
674
+ export function readFormalEvidenceSummaryV1({
675
+ workspaceRoot,
676
+ runId,
677
+ summaryId,
678
+ }) {
679
+ safeIdentifier(runId, "runId");
680
+ safeIdentifier(summaryId, "summaryId");
681
+ const root = realpathSync(workspaceRoot);
682
+ const artifactPath = path.join(
683
+ root,
684
+ ".owlcoda",
685
+ "runkit",
686
+ "executions",
687
+ runId,
688
+ "formal-evidence-summaries",
689
+ `${summaryId}.json`,
690
+ );
691
+ if (!existsSync(artifactPath)) return null;
692
+ const value = validateSummaryDocument(
693
+ readWorkspaceJsonBounded(
694
+ root,
695
+ relativeToWorkspace(root, artifactPath),
696
+ ),
697
+ { workspaceRoot: root, runId, summaryId },
698
+ );
699
+ const { evidenceSummarySha256 } = value;
700
+ return {
701
+ evidenceSummaryPath: relativeToWorkspace(root, artifactPath),
702
+ evidenceSummarySha256,
703
+ formalCheckCount: value.formalChecks.length,
704
+ supplementalEvidenceCount: value.supplementalEvidence.length,
705
+ staleSupplementalEvidenceCount: value.staleSupplementalEvidenceCount,
706
+ summaryDocument: value,
707
+ authorizationGranted: false,
708
+ };
709
+ }
710
+
711
+ export function reattestFormalEvidenceSummaryV1(options) {
712
+ return readFormalEvidenceSummaryV1(options);
713
+ }