owlrunkit 0.19.0 → 0.19.2

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 (36) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +81 -3
  3. package/docs/architecture/OWLCODA_RUNKIT_0190_CONSOLIDATED_DAILY_USE_PRODUCT_DECISION_20260812.md +12 -9
  4. package/docs/architecture/OWLCODA_RUNKIT_0191_PROFILE_RECONCILE_PATCH_PRODUCT_DECISION_20260813.md +36 -0
  5. package/docs/architecture/OWLCODA_RUNKIT_0192_FORMAL_USABILITY_PRODUCT_DECISION_20260813.md +141 -0
  6. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +52 -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 +35 -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/profile-onboarding.mjs +52 -33
  20. package/scripts/runkit-contract/project-cli-resolver.mjs +33 -3
  21. package/scripts/runkit-contract/project-external-delivery.mjs +16 -9
  22. package/scripts/runkit-contract/quick-attest.mjs +24 -0
  23. package/scripts/runkit-contract/runkit-cli.mjs +365 -49
  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-project-event-v5.schema.json +89 -0
  29. package/scripts/runkit-contract/schemas/team-project-status-v3.schema.json +173 -0
  30. package/scripts/runkit-contract/snapshot.mjs +125 -5
  31. package/scripts/runkit-contract/source-candidate.mjs +271 -69
  32. package/scripts/runkit-contract/sync-release-identity.mjs +39 -4
  33. package/scripts/runkit-contract/team-project-successor.mjs +7 -4
  34. package/scripts/runkit-contract/team-project.mjs +440 -28
  35. package/scripts/runkit-contract/usage-mode.mjs +9 -3
  36. package/scripts/runkit-contract/verification-envelope.mjs +425 -37
@@ -13,6 +13,8 @@ import {
13
13
  validateCoreArtifact,
14
14
  } from "./core-contract.mjs";
15
15
  import { runFinalize } from "./finalize.mjs";
16
+ import { preflightFormalEnvelopeV1 } from "./formal-preflight.mjs";
17
+ import { readWorkspaceJsonBounded } from "./onboarding-doctor.mjs";
16
18
  import { derivedVerificationContext } from "./lifecycle-orchestration.mjs";
17
19
  import { withControlTransaction } from "./lease-lifecycle.mjs";
18
20
  import {
@@ -30,12 +32,18 @@ import {
30
32
  } from "./snapshot.mjs";
31
33
  import {
32
34
  freezeSourceCandidateWithinControlTransactionV2,
35
+ previewSourceCandidateWithinControlTransactionV2,
36
+ verifySourceCandidateDetailsV2,
33
37
  verifySourceCandidateV2,
34
38
  } from "./source-candidate.mjs";
35
39
  import { validateReceiptLineage } from "./receipt-lineage.mjs";
36
- import { verificationContextFingerprint } from "./verification-context.mjs";
40
+ import {
41
+ validateVerificationContext,
42
+ verificationContextFingerprint,
43
+ } from "./verification-context.mjs";
37
44
  import {
38
45
  runVerificationEnvelopeV1,
46
+ validateEnvelopeSourceCandidateBoundaryV1,
39
47
  validateVerificationEnvelopeV1,
40
48
  verifyVerificationEnvelopeReceiptV1,
41
49
  } from "./verification-envelope.mjs";
@@ -126,6 +134,17 @@ function canonicalJson(value) {
126
134
  return encoded;
127
135
  }
128
136
 
137
+ function formalCheckHash(value) {
138
+ return `sha256:${sha256(canonicalJson(value))}`;
139
+ }
140
+
141
+ function hasExactKeys(value, keys) {
142
+ return Boolean(value)
143
+ && typeof value === "object"
144
+ && !Array.isArray(value)
145
+ && canonicalJson(Object.keys(value).sort()) === canonicalJson([...keys].sort());
146
+ }
147
+
129
148
  function readRegularJson(filePath, label) {
130
149
  const stat = lstatSync(filePath);
131
150
  if (stat.isSymbolicLink() || !stat.isFile()) {
@@ -137,6 +156,20 @@ function readRegularJson(filePath, label) {
137
156
  return JSON.parse(readFileSync(filePath, "utf8"));
138
157
  }
139
158
 
159
+ function readWorkspaceRegularJson(workspaceRoot, filePath, label) {
160
+ try {
161
+ return readWorkspaceJsonBounded(
162
+ workspaceRoot,
163
+ relativeToWorkspace(workspaceRoot, filePath),
164
+ { maxBytes: 64 * 1024 * 1024, maxNodes: 2_000_000 },
165
+ );
166
+ } catch (error) {
167
+ throw new Error(`${label} must be bounded regular JSON inside the workspace.`, {
168
+ cause: error,
169
+ });
170
+ }
171
+ }
172
+
140
173
  function writeOrResumeExactJson(filePath, value, label) {
141
174
  if (!existsSync(filePath)) {
142
175
  writeJsonExclusiveAtomically(filePath, value);
@@ -335,7 +368,224 @@ export function validateLegacyVerificationSideEffectsV1({ commandArgv }) {
335
368
  };
336
369
  }
337
370
 
338
- function readChecks(executionRoot) {
371
+ const FORMAL_CHECK_V2_KEYS = [
372
+ "schemaVersion",
373
+ "runId",
374
+ "checkId",
375
+ "sequence",
376
+ "status",
377
+ "candidatePath",
378
+ "candidateSha256",
379
+ "payloadSha256",
380
+ "sourceFingerprint",
381
+ "verificationContext",
382
+ "verificationContextFingerprint",
383
+ "snapshotRequestPath",
384
+ "snapshotPath",
385
+ "commandExitCode",
386
+ "verificationCommandPolicy",
387
+ "envelopePath",
388
+ "envelopeSha256",
389
+ "envelopeReceiptPath",
390
+ "envelopeReceiptSha256",
391
+ "envelopeFormalEligible",
392
+ "failureCategory",
393
+ "failureDetail",
394
+ "finalized",
395
+ "authorizationGranted",
396
+ "formalCheckSha256",
397
+ ];
398
+
399
+ const FORMAL_POLICY_V2_KEYS = [
400
+ "schemaVersion",
401
+ "mode",
402
+ "riskClassification",
403
+ "profileCommandIds",
404
+ "envelopeSha256",
405
+ "envelopeReceiptSha256",
406
+ "authorizationGranted",
407
+ ];
408
+
409
+ function expectedFormalPath(workspaceRoot, executionRoot, ...segments) {
410
+ return relativeToWorkspace(
411
+ workspaceRoot,
412
+ path.join(executionRoot, ...segments),
413
+ );
414
+ }
415
+
416
+ function validateFormalCheckV2({
417
+ workspaceRoot,
418
+ executionRoot,
419
+ runId,
420
+ fileName,
421
+ check,
422
+ }) {
423
+ const checkId = path.basename(fileName, ".json");
424
+ const { formalCheckSha256, ...checkBody } = check ?? {};
425
+ if (
426
+ !hasExactKeys(check, FORMAL_CHECK_V2_KEYS)
427
+ || check.schemaVersion !== "OwlCodaRunKitFormalCheckV2"
428
+ || check.runId !== runId
429
+ || check.checkId !== checkId
430
+ || !Number.isSafeInteger(check.sequence)
431
+ || check.sequence < 1
432
+ || !new Set(["formal_check_passed", "formal_check_failed"]).has(check.status)
433
+ || check.finalized !== false
434
+ || check.authorizationGranted !== false
435
+ || !/^sha256:[a-f0-9]{64}$/u.test(formalCheckSha256)
436
+ || formalCheckSha256 !== formalCheckHash(checkBody)
437
+ ) {
438
+ throw new Error(`Formal Check V2 contract is invalid: ${fileName}`);
439
+ }
440
+ const expected = {
441
+ candidatePath: expectedFormalPath(
442
+ workspaceRoot,
443
+ executionRoot,
444
+ "source-candidates",
445
+ `${checkId}.json`,
446
+ ),
447
+ snapshotRequestPath: expectedFormalPath(
448
+ workspaceRoot,
449
+ executionRoot,
450
+ "formal-check-requests",
451
+ `${checkId}.json`,
452
+ ),
453
+ snapshotPath: expectedFormalPath(
454
+ workspaceRoot,
455
+ executionRoot,
456
+ "snapshots",
457
+ `${checkId}-snapshot.json`,
458
+ ),
459
+ envelopePath: expectedFormalPath(
460
+ workspaceRoot,
461
+ executionRoot,
462
+ "formal-envelopes",
463
+ `${checkId}.json`,
464
+ ),
465
+ envelopeReceiptPath: expectedFormalPath(
466
+ workspaceRoot,
467
+ executionRoot,
468
+ "verification-envelopes",
469
+ checkId,
470
+ "verification-envelope-receipt.json",
471
+ ),
472
+ };
473
+ for (const [field, expectedPath] of Object.entries(expected)) {
474
+ if (check[field] !== expectedPath) {
475
+ throw new Error(`Formal Check V2 ${field} is invalid: ${fileName}`);
476
+ }
477
+ }
478
+ const candidate = verifySourceCandidateDetailsV2({
479
+ workspaceRoot,
480
+ candidatePath: check.candidatePath,
481
+ requireCurrentWorkspace: false,
482
+ });
483
+ const candidateDocument = candidate.candidateDocument;
484
+ if (
485
+ candidate.gate.status !== "valid"
486
+ || candidateDocument === null
487
+ || candidateDocument.runId !== runId
488
+ || candidateDocument.candidateId !== checkId
489
+ || candidateDocument.candidateSha256 !== check.candidateSha256
490
+ || candidateDocument.payload.sha256 !== check.payloadSha256
491
+ || candidateDocument.sourceFingerprint.sha256 !== check.sourceFingerprint
492
+ ) {
493
+ throw new Error(`Formal Check V2 candidate binding is invalid: ${fileName}`);
494
+ }
495
+ const context = validateVerificationContext(check.verificationContext);
496
+ if (
497
+ !context.valid
498
+ || verificationContextFingerprint(check.verificationContext)
499
+ !== check.verificationContextFingerprint
500
+ ) {
501
+ throw new Error(`Formal Check V2 verification context is invalid: ${fileName}`);
502
+ }
503
+ if (
504
+ !hasExactKeys(check.verificationCommandPolicy, FORMAL_POLICY_V2_KEYS)
505
+ || check.verificationCommandPolicy.schemaVersion
506
+ !== "OwlCodaRunKitFormalVerificationCommandPolicyV1"
507
+ || check.verificationCommandPolicy.mode !== "verification_envelope_v1"
508
+ || check.verificationCommandPolicy.riskClassification
509
+ !== "enforced_verification_envelope"
510
+ || canonicalJson(check.verificationCommandPolicy.profileCommandIds) !== "[]"
511
+ || check.verificationCommandPolicy.envelopeSha256 !== check.envelopeSha256
512
+ || check.verificationCommandPolicy.envelopeReceiptSha256
513
+ !== check.envelopeReceiptSha256
514
+ || check.verificationCommandPolicy.authorizationGranted !== false
515
+ ) {
516
+ throw new Error(`Formal Check V2 command policy is invalid: ${fileName}`);
517
+ }
518
+ const envelope = readWorkspaceRegularJson(
519
+ workspaceRoot,
520
+ path.join(workspaceRoot, check.envelopePath),
521
+ "Formal Verification Envelope",
522
+ );
523
+ const validatedEnvelope = validateVerificationEnvelopeV1({
524
+ workspaceRoot,
525
+ envelope,
526
+ requireCurrentEnvironment: false,
527
+ });
528
+ if (validatedEnvelope.envelopeSha256 !== check.envelopeSha256) {
529
+ throw new Error(`Formal Check V2 envelope binding is invalid: ${fileName}`);
530
+ }
531
+ const envelopeReceiptPath = path.join(workspaceRoot, check.envelopeReceiptPath);
532
+ const envelopeReceipt = readWorkspaceRegularJson(
533
+ workspaceRoot,
534
+ envelopeReceiptPath,
535
+ "Verification Envelope receipt",
536
+ );
537
+ const verifiedEnvelope = verifyVerificationEnvelopeReceiptV1({
538
+ workspaceRoot,
539
+ receiptPath: envelopeReceiptPath,
540
+ requireCurrentSource: false,
541
+ });
542
+ if (
543
+ verifiedEnvelope.receiptSha256 !== check.envelopeReceiptSha256
544
+ || verifiedEnvelope.envelopeSha256 !== check.envelopeSha256
545
+ || verifiedEnvelope.formalEligible !== check.envelopeFormalEligible
546
+ ) {
547
+ throw new Error(`Formal Check V2 envelope receipt binding is invalid: ${fileName}`);
548
+ }
549
+ const snapshot = readWorkspaceRegularJson(
550
+ workspaceRoot,
551
+ path.join(workspaceRoot, check.snapshotPath),
552
+ "Formal snapshot",
553
+ );
554
+ const snapshotGate = verifySnapshotEvidence({
555
+ workspaceRoot,
556
+ runId,
557
+ snapshot,
558
+ requirePassed: false,
559
+ });
560
+ if (
561
+ !snapshotGate.valid
562
+ || snapshot.snapshotId !== `${checkId}-snapshot`
563
+ || snapshot.verificationContextFingerprint !== check.verificationContextFingerprint
564
+ || snapshot.command.exitCode !== check.commandExitCode
565
+ || snapshot.command.exitCode !== (envelopeReceipt.formalEligible ? 0 : 2)
566
+ ) {
567
+ throw new Error(`Formal Check V2 snapshot binding is invalid: ${fileName}`);
568
+ }
569
+ const expectedStatus = snapshot.status === "snapshot_passed"
570
+ && envelopeReceipt.formalEligible
571
+ ? "formal_check_passed"
572
+ : "formal_check_failed";
573
+ const expectedFailure = classifyFormalEnvelopeFailureV1({
574
+ envelopeReceipt,
575
+ snapshotStatus: snapshot.status,
576
+ finalStatus: expectedStatus,
577
+ });
578
+ if (
579
+ check.status !== expectedStatus
580
+ || check.failureCategory !== expectedFailure.failureCategory
581
+ || check.failureDetail !== expectedFailure.failureDetail
582
+ ) {
583
+ throw new Error(`Formal Check V2 derived fields are invalid: ${fileName}`);
584
+ }
585
+ return check;
586
+ }
587
+
588
+ function readChecks(workspaceRoot, executionRoot, runId) {
339
589
  const root = checkRoot(executionRoot);
340
590
  if (!existsSync(root)) return [];
341
591
  const stat = lstatSync(root);
@@ -349,11 +599,27 @@ function readChecks(executionRoot) {
349
599
  if (entry.isSymbolicLink() || !entry.isFile()) {
350
600
  throw new Error(`Formal check must be a regular file: ${entry.name}`);
351
601
  }
352
- const value = readJson(path.join(root, entry.name));
602
+ const value = readWorkspaceRegularJson(
603
+ workspaceRoot,
604
+ path.join(root, entry.name),
605
+ "Formal check",
606
+ );
607
+ if (value.schemaVersion === "OwlCodaRunKitFormalCheckV2") {
608
+ return validateFormalCheckV2({
609
+ workspaceRoot,
610
+ executionRoot,
611
+ runId,
612
+ fileName: entry.name,
613
+ check: value,
614
+ });
615
+ }
353
616
  if (
354
617
  value.schemaVersion !== "OwlCodaRunKitFormalCheckV1"
618
+ || value.runId !== runId
619
+ || value.checkId !== path.basename(entry.name, ".json")
355
620
  || !Number.isSafeInteger(value.sequence)
356
621
  || value.sequence < 1
622
+ || value.authorizationGranted !== false
357
623
  ) {
358
624
  throw new Error(`Formal check contract is invalid: ${entry.name}`);
359
625
  }
@@ -362,6 +628,60 @@ function readChecks(executionRoot) {
362
628
  .sort((left, right) => left.sequence - right.sequence);
363
629
  }
364
630
 
631
+ export function readFormalChecksV1({ workspaceRoot, executionRoot, runId }) {
632
+ return readChecks(realpathSync(workspaceRoot), executionRoot, runId);
633
+ }
634
+
635
+ export function classifyFormalEnvelopeFailureV1({
636
+ envelopeReceipt,
637
+ snapshotStatus,
638
+ finalStatus,
639
+ }) {
640
+ if (finalStatus === "formal_check_passed") {
641
+ return { failureCategory: null, failureDetail: null };
642
+ }
643
+ if (
644
+ envelopeReceipt.status === "policy_backend_unavailable"
645
+ || envelopeReceipt.commandExecuted === false
646
+ ) {
647
+ return {
648
+ failureCategory: "envelope_capability_missing",
649
+ failureDetail: envelopeReceipt.backend?.reason ?? "enforcement_backend_unavailable",
650
+ };
651
+ }
652
+ const phases = envelopeReceipt.phases ?? [];
653
+ const launched = phases.find(phase => phase.launchError !== null && phase.launchError !== undefined);
654
+ if (launched) {
655
+ return {
656
+ failureCategory: "toolchain_resolution_failed",
657
+ failureDetail: `phase_${launched.name}_launch_failed`,
658
+ };
659
+ }
660
+ if (snapshotStatus === "invalidated_by_target_write") {
661
+ return {
662
+ failureCategory: "envelope_capability_missing",
663
+ failureDetail: "verification_evidence_snapshot_not_current",
664
+ };
665
+ }
666
+ if (
667
+ phases.some(phase => phase.timedOut || phase.outputOverflow)
668
+ || envelopeReceipt.source?.unchanged === false
669
+ || envelopeReceipt.cleanup?.teardownCompleted === false
670
+ || (envelopeReceipt.cleanup?.terminatedProcessIds?.length ?? 0) > 0
671
+ || (envelopeReceipt.cleanup?.remainingProcessIds?.length ?? 0) > 0
672
+ || (envelopeReceipt.cleanup?.issues?.length ?? 0) > 0
673
+ ) {
674
+ return {
675
+ failureCategory: "envelope_capability_missing",
676
+ failureDetail: "verification_envelope_constraints_not_satisfied",
677
+ };
678
+ }
679
+ return {
680
+ failureCategory: "source_check_failed",
681
+ failureDetail: "verification_command_returned_nonzero",
682
+ };
683
+ }
684
+
365
685
  function resumeOrFreezeCandidate({
366
686
  workspaceRoot,
367
687
  executionRoot,
@@ -375,30 +695,41 @@ function resumeOrFreezeCandidate({
375
695
  `${checkId}.json`,
376
696
  );
377
697
  if (!existsSync(candidatePath)) {
698
+ const candidate = freezeSourceCandidateWithinControlTransactionV2({
699
+ workspaceRoot,
700
+ runId,
701
+ workItemId,
702
+ candidateId: checkId,
703
+ });
704
+ if (candidate.status !== "source_candidate_frozen") {
705
+ return { candidate, candidateDocument: null, resumed: false };
706
+ }
707
+ const verified = verifySourceCandidateDetailsV2({
708
+ workspaceRoot,
709
+ candidatePath: candidate.candidatePath,
710
+ });
711
+ if (verified.gate.status !== "valid" || verified.candidateDocument === null) {
712
+ throw new Error(`New Formal source candidate failed verification: ${checkId}`);
713
+ }
378
714
  return {
379
- candidate: freezeSourceCandidateWithinControlTransactionV2({
380
- workspaceRoot,
381
- runId,
382
- workItemId,
383
- candidateId: checkId,
384
- }),
715
+ candidate,
716
+ candidateDocument: verified.candidateDocument,
385
717
  resumed: false,
386
718
  };
387
719
  }
388
- const candidateDocument = readRegularJson(
389
- candidatePath,
390
- "Formal source candidate",
391
- );
392
720
  const candidateRelativePath = relativeToWorkspace(
393
721
  workspaceRoot,
394
722
  candidatePath,
395
723
  );
396
- const gate = verifySourceCandidateV2({
724
+ const verified = verifySourceCandidateDetailsV2({
397
725
  workspaceRoot,
398
726
  candidatePath: candidateRelativePath,
399
727
  });
728
+ const gate = verified.gate;
729
+ const candidateDocument = verified.candidateDocument;
400
730
  if (
401
731
  gate.status !== "valid"
732
+ || candidateDocument === null
402
733
  || candidateDocument.runId !== runId
403
734
  || candidateDocument.candidateId !== checkId
404
735
  || candidateDocument.discovery?.fromLease !== workItemId
@@ -421,6 +752,7 @@ function resumeOrFreezeCandidate({
421
752
  ownedPaths: [...candidateDocument.sourceManifest.ownedPaths],
422
753
  authorizationGranted: false,
423
754
  },
755
+ candidateDocument,
424
756
  resumed: true,
425
757
  };
426
758
  }
@@ -464,6 +796,7 @@ function resumeSnapshot({
464
796
  workspaceRoot,
465
797
  runId,
466
798
  snapshot,
799
+ requirePassed: false,
467
800
  });
468
801
  if (
469
802
  !evidence.valid
@@ -577,7 +910,7 @@ function recordFormalCheckWithinControlTransaction({
577
910
  ? readRegularJson(receiptPath, "Formal check receipt")
578
911
  : null;
579
912
  const sequence = existingReceipt?.sequence
580
- ?? readChecks(executionRoot).length + 1;
913
+ ?? readChecks(root, executionRoot, runId).length + 1;
581
914
  const status = snapshot.status === "snapshot_passed"
582
915
  ? "formal_check_passed"
583
916
  : "formal_check_failed";
@@ -646,11 +979,137 @@ async function recordFormalEnvelopeCheckWithinControlTransaction({
646
979
  const root = realpathSync(workspaceRoot);
647
980
  const { executionRoot, pinGate } = loadActiveExecution(root, runId);
648
981
  if (pinGate.status !== "valid") return { ...pinGate, authorizationGranted: false };
649
- const validatedEnvelope = validateVerificationEnvelopeV1({
982
+ const structurallyValidatedEnvelope = validateVerificationEnvelopeV1({
650
983
  workspaceRoot: root,
651
984
  envelope,
985
+ requireCurrentEnvironment: false,
652
986
  });
653
987
  const receiptPath = path.join(checkRoot(executionRoot), `${checkId}.json`);
988
+ if (existsSync(receiptPath)) {
989
+ const existing = readChecks(root, executionRoot, runId)
990
+ .find(check => check.checkId === checkId);
991
+ if (
992
+ existing?.schemaVersion !== "OwlCodaRunKitFormalCheckV2"
993
+ || existing.envelopeSha256 !== structurallyValidatedEnvelope.envelopeSha256
994
+ ) {
995
+ throw new Error(`Existing Formal check differs from the resumed command: ${checkId}`);
996
+ }
997
+ const current = verifySourceCandidateDetailsV2({
998
+ workspaceRoot: root,
999
+ candidatePath: existing.candidatePath,
1000
+ });
1001
+ if (
1002
+ current.gate.status !== "valid"
1003
+ || current.candidateDocument?.discovery?.fromLease !== workItemId
1004
+ ) {
1005
+ throw new Error(`Existing Formal check source differs from the resumed command: ${checkId}`);
1006
+ }
1007
+ return {
1008
+ ...existing,
1009
+ exitCode: existing.status === "formal_check_passed" ? 0 : 2,
1010
+ checkReceiptPath: relativeToWorkspace(root, receiptPath),
1011
+ resumed: true,
1012
+ };
1013
+ }
1014
+ const envelopePath = path.join(
1015
+ executionRoot,
1016
+ "formal-envelopes",
1017
+ `${checkId}.json`,
1018
+ );
1019
+ if (existsSync(envelopePath)) {
1020
+ const existingEnvelope = readRegularJson(
1021
+ envelopePath,
1022
+ "Formal Verification Envelope",
1023
+ );
1024
+ if (
1025
+ canonicalJson(existingEnvelope)
1026
+ !== canonicalJson(structurallyValidatedEnvelope.envelope)
1027
+ ) {
1028
+ throw new Error("Existing Formal Verification Envelope differs from the resumed command.");
1029
+ }
1030
+ }
1031
+ const candidatePath = path.join(
1032
+ executionRoot,
1033
+ "source-candidates",
1034
+ `${checkId}.json`,
1035
+ );
1036
+ const requestPath = path.join(
1037
+ executionRoot,
1038
+ "formal-check-requests",
1039
+ `${checkId}.json`,
1040
+ );
1041
+ const snapshotPath = path.join(
1042
+ executionRoot,
1043
+ "snapshots",
1044
+ `${checkId}-snapshot.json`,
1045
+ );
1046
+ const envelopeReceiptPath = path.join(
1047
+ executionRoot,
1048
+ "verification-envelopes",
1049
+ checkId,
1050
+ "verification-envelope-receipt.json",
1051
+ );
1052
+ if (
1053
+ !existsSync(candidatePath)
1054
+ && [requestPath, snapshotPath, envelopeReceiptPath].some(existsSync)
1055
+ ) {
1056
+ throw new Error("Incomplete Formal check artifacts require a new check id.");
1057
+ }
1058
+ if (existsSync(snapshotPath) && !existsSync(requestPath)) {
1059
+ throw new Error("Incomplete Formal snapshot artifacts require a new check id.");
1060
+ }
1061
+ const preflight = preflightFormalEnvelopeV1({
1062
+ workspaceRoot: root,
1063
+ envelope: structurallyValidatedEnvelope.envelope,
1064
+ });
1065
+ if (preflight.status === "blocked") return preflight;
1066
+ const validatedEnvelope = validateVerificationEnvelopeV1({
1067
+ workspaceRoot: root,
1068
+ envelope: structurallyValidatedEnvelope.envelope,
1069
+ });
1070
+ const preview = previewSourceCandidateWithinControlTransactionV2({
1071
+ workspaceRoot: root,
1072
+ runId,
1073
+ workItemId,
1074
+ });
1075
+ if (preview.status !== "source_candidate_previewed") return preview;
1076
+ validateEnvelopeSourceCandidateBoundaryV1({
1077
+ envelope: validatedEnvelope.envelope,
1078
+ sourceManifest: preview.sourceManifest,
1079
+ });
1080
+ const context = derivedVerificationContext(root);
1081
+ const commandArgv = [
1082
+ realpathSync(process.execPath),
1083
+ VERIFICATION_ENVELOPE_CHECKER,
1084
+ "--workspace",
1085
+ root,
1086
+ "--receipt",
1087
+ envelopeReceiptPath,
1088
+ ];
1089
+ const buildSnapshotRequest = sourceManifest => ({
1090
+ schemaVersion: "OwlCodaRunKitSnapshotRequestV1",
1091
+ snapshotId: `${checkId}-snapshot`,
1092
+ mode: "project",
1093
+ targetRoot: root,
1094
+ cwd: ".",
1095
+ executable: commandArgv[0],
1096
+ argv: commandArgv.slice(1),
1097
+ launcherVersion: "owlrunkit-formal-envelope-v1",
1098
+ toolVersions: structuredClone(context.toolchains),
1099
+ selectedPaths: sourceManifest.entries
1100
+ .filter(entry => entry.operation !== "deleted")
1101
+ .map(entry => entry.path)
1102
+ .sort(),
1103
+ statusMode: "porcelain-v1-z-untracked-all-runkit-excluded",
1104
+ verificationContext: context,
1105
+ });
1106
+ const previewRequest = buildSnapshotRequest(preview.sourceManifest);
1107
+ if (existsSync(requestPath)) {
1108
+ const existingRequest = readRegularJson(requestPath, "Formal check request");
1109
+ if (canonicalJson(existingRequest) !== canonicalJson(previewRequest)) {
1110
+ throw new Error("Existing Formal check request differs from the resumed command.");
1111
+ }
1112
+ }
654
1113
  const candidateResult = resumeOrFreezeCandidate({
655
1114
  workspaceRoot: root,
656
1115
  executionRoot,
@@ -661,12 +1120,15 @@ async function recordFormalEnvelopeCheckWithinControlTransaction({
661
1120
  const candidate = candidateResult.candidate;
662
1121
  if (candidate.status !== "source_candidate_frozen") return candidate;
663
1122
  hooks.afterCandidatePersist?.();
664
- const candidateDocument = readJson(path.join(root, candidate.candidatePath));
665
- const envelopePath = path.join(
666
- executionRoot,
667
- "formal-envelopes",
668
- `${checkId}.json`,
669
- );
1123
+ const candidateDocument = candidateResult.candidateDocument;
1124
+ validateEnvelopeSourceCandidateBoundaryV1({
1125
+ envelope: validatedEnvelope.envelope,
1126
+ sourceManifest: candidateDocument.sourceManifest,
1127
+ });
1128
+ const request = buildSnapshotRequest(candidateDocument.sourceManifest);
1129
+ if (canonicalJson(request) !== canonicalJson(previewRequest)) {
1130
+ throw new Error("Formal source changed after preflight; create a new check id.");
1131
+ }
670
1132
  const envelopeResult = writeOrResumeExactJson(
671
1133
  envelopePath,
672
1134
  validatedEnvelope.envelope,
@@ -683,14 +1145,6 @@ async function recordFormalEnvelopeCheckWithinControlTransaction({
683
1145
  artifactRoot: envelopeArtifactRoot,
684
1146
  });
685
1147
  hooks.afterEnvelopePersist?.();
686
- const commandArgv = [
687
- realpathSync(process.execPath),
688
- VERIFICATION_ENVELOPE_CHECKER,
689
- "--workspace",
690
- root,
691
- "--receipt",
692
- envelopeReceipt.receiptPath,
693
- ];
694
1148
  const verificationCommandPolicy = {
695
1149
  schemaVersion: "OwlCodaRunKitFormalVerificationCommandPolicyV1",
696
1150
  mode: "verification_envelope_v1",
@@ -702,29 +1156,6 @@ async function recordFormalEnvelopeCheckWithinControlTransaction({
702
1156
  envelopeReceiptSha256: envelopeReceipt.receiptSha256,
703
1157
  authorizationGranted: false,
704
1158
  };
705
- const context = derivedVerificationContext(root);
706
- const request = {
707
- schemaVersion: "OwlCodaRunKitSnapshotRequestV1",
708
- snapshotId: `${checkId}-snapshot`,
709
- mode: "project",
710
- targetRoot: root,
711
- cwd: ".",
712
- executable: verificationCommandPolicy.executable,
713
- argv: verificationCommandPolicy.argv,
714
- launcherVersion: "owlrunkit-formal-envelope-v1",
715
- toolVersions: structuredClone(context.toolchains),
716
- selectedPaths: candidateDocument.sourceManifest.entries
717
- .filter((entry) => entry.operation !== "deleted")
718
- .map((entry) => entry.path)
719
- .sort(),
720
- statusMode: "porcelain-v1-z-untracked-all-runkit-excluded",
721
- verificationContext: context,
722
- };
723
- const requestPath = path.join(
724
- executionRoot,
725
- "formal-check-requests",
726
- `${checkId}.json`,
727
- );
728
1159
  const requestResult = writeOrResumeExactJson(
729
1160
  requestPath,
730
1161
  request,
@@ -745,13 +1176,18 @@ async function recordFormalEnvelopeCheckWithinControlTransaction({
745
1176
  ? readRegularJson(receiptPath, "Formal check receipt")
746
1177
  : null;
747
1178
  const sequence = existingReceipt?.sequence
748
- ?? readChecks(executionRoot).length + 1;
1179
+ ?? readChecks(root, executionRoot, runId).length + 1;
749
1180
  const status = snapshot.status === "snapshot_passed"
750
1181
  && envelopeReceipt.formalEligible
751
1182
  ? "formal_check_passed"
752
1183
  : "formal_check_failed";
753
- const receipt = {
754
- schemaVersion: "OwlCodaRunKitFormalCheckV1",
1184
+ const failure = classifyFormalEnvelopeFailureV1({
1185
+ envelopeReceipt,
1186
+ snapshotStatus: snapshot.status,
1187
+ finalStatus: status,
1188
+ });
1189
+ const receiptBody = {
1190
+ schemaVersion: "OwlCodaRunKitFormalCheckV2",
755
1191
  runId,
756
1192
  checkId,
757
1193
  sequence,
@@ -779,9 +1215,15 @@ async function recordFormalEnvelopeCheckWithinControlTransaction({
779
1215
  envelopeReceiptPath: relativeToWorkspace(root, envelopeReceipt.receiptPath),
780
1216
  envelopeReceiptSha256: envelopeReceipt.receiptSha256,
781
1217
  envelopeFormalEligible: envelopeReceipt.formalEligible,
1218
+ failureCategory: failure.failureCategory,
1219
+ failureDetail: failure.failureDetail,
782
1220
  finalized: false,
783
1221
  authorizationGranted: false,
784
1222
  };
1223
+ const receipt = {
1224
+ ...receiptBody,
1225
+ formalCheckSha256: formalCheckHash(receiptBody),
1226
+ };
785
1227
  const receiptResult = writeOrResumeExactJson(
786
1228
  receiptPath,
787
1229
  receipt,
@@ -812,7 +1254,7 @@ export function recordFormalEnvelopeCheckV1(options) {
812
1254
  );
813
1255
  }
814
1256
 
815
- function finalizeFormalChecksWithinControlTransaction({
1257
+ export function finalizeFormalChecksWithinControlTransaction({
816
1258
  workspaceRoot,
817
1259
  runId,
818
1260
  finalizeId,
@@ -822,7 +1264,7 @@ function finalizeFormalChecksWithinControlTransaction({
822
1264
  const root = realpathSync(workspaceRoot);
823
1265
  const { executionRoot, pinGate } = loadActiveExecution(root, runId);
824
1266
  if (pinGate.status !== "valid") return { ...pinGate, authorizationGranted: false };
825
- const checks = readChecks(executionRoot);
1267
+ const checks = readChecks(root, executionRoot, runId);
826
1268
  if (checks.length === 0) throw new Error("Formal finish requires at least one check.");
827
1269
  const latest = checks.at(-1);
828
1270
  const currentCandidate = verifySourceCandidateV2({
@@ -917,6 +1359,9 @@ export function resumeCompletedFormalFinishV1({
917
1359
  const closeout = readRegularJson(closeoutPath, "Formal closeout receipt");
918
1360
  const gate = validateCoreArtifact(closeout.artifact);
919
1361
  const payload = closeout.artifact?.payload;
1362
+ const formalEvidenceBinding = closeout.artifact?.extensions?.[
1363
+ "dev.owlcoda.formal-evidence"
1364
+ ] ?? null;
920
1365
  if (
921
1366
  !gate.valid
922
1367
  || closeout.acceptanceSha256 !== gate.acceptanceSha256
@@ -944,9 +1389,33 @@ export function resumeCompletedFormalFinishV1({
944
1389
  closeoutArtifactSha256: closeout.artifactSha256,
945
1390
  releasedLeaseIds: [],
946
1391
  resumed: true,
1392
+ formalEvidenceBinding: null,
947
1393
  authorizationGranted: false,
948
1394
  };
949
1395
  }
1396
+ if (
1397
+ closeout.artifact.core?.coreVersion === "0.19.2"
1398
+ && (
1399
+ !hasExactKeys(formalEvidenceBinding, [
1400
+ "schemaVersion",
1401
+ "summaryPath",
1402
+ "summarySha256",
1403
+ "formalCheckCount",
1404
+ "supplementalEvidenceCount",
1405
+ "staleSupplementalEvidenceCount",
1406
+ "authorizationGranted",
1407
+ ])
1408
+ || formalEvidenceBinding.schemaVersion
1409
+ !== "OwlCodaRunKitFormalEvidenceCloseoutBindingV1"
1410
+ || formalEvidenceBinding.summaryPath
1411
+ !== `.owlcoda/runkit/executions/${runId}`
1412
+ + `/formal-evidence-summaries/${finalizeId}-evidence.json`
1413
+ || !/^[a-f0-9]{64}$/u.test(formalEvidenceBinding.summarySha256)
1414
+ || formalEvidenceBinding.authorizationGranted !== false
1415
+ )
1416
+ ) {
1417
+ throw new Error("Existing closeout Formal evidence summary binding is invalid.");
1418
+ }
950
1419
  const requestPath = path.join(
951
1420
  executionRoot,
952
1421
  "formal-finalize-requests",
@@ -1016,7 +1485,7 @@ export function resumeCompletedFormalFinishV1({
1016
1485
  "Existing closeout Formal sourceArtifact bytes changed.",
1017
1486
  );
1018
1487
  }
1019
- const checks = readChecks(executionRoot);
1488
+ const checks = readChecks(root, executionRoot, runId);
1020
1489
  const selected = checks.filter((check) => (
1021
1490
  check.status === "formal_check_passed"
1022
1491
  && check.sourceFingerprint === active.receipt.sourceFingerprint
@@ -1046,6 +1515,7 @@ export function resumeCompletedFormalFinishV1({
1046
1515
  ...payload.verification.releasedLeaseIds,
1047
1516
  ],
1048
1517
  resumed: true,
1518
+ formalEvidenceBinding,
1049
1519
  authorizationGranted: false,
1050
1520
  };
1051
1521
  }