Skip to content

feat(verified): seal_write.t27 -- what one seal write must guarantee (REA 6.6.0 patterns) - #10458

Merged
gHashTag merged 2 commits into
masterfrom
claude/seal-write-safety
Oct 18, 2026
Merged

gHashTag merged 2 commits into
masterfrom
claude/seal-write-safety

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Refs #10457.

This adds specs/verified/seal_write.t27 (module VerifiedSealWrite) and its seal. The spec states what one seal write must guarantee before it lands in .trinity/seals/, taken from REA 6.6.0's three write-safety patterns (release).

pattern seal pipeline today (lab, t27c 0.5.2 at 89254d2) rule
colliding paths refused before any write missing: seal --save of two module SameName; specs both exit 0 into one file; the first then fails --verify dest_check: free, own, or refused; an unreadable owner fails closed; case-variant names count as the same file
hash re-checked after the final write missing: a failing spec swapped for a passing one 0-4 ms into --save seals "1/1 pass" under the failing bytes' hash; --verify MATCH, frontier reuses it post_write_check: re-hashed spec, tested bytes and read-back must all equal the recorded seal
completed seals survive a cut present for finished seals (SIGINT/TERM/KILL left 4/2/3 verifying seals); the seal in flight is not protected after_cut / proto_cut_safe: stage then rename leaves the old seal or the new checked one

The full lab evidence is in #10457.

  • Tests: 14 tests, 0 vacuous (t27c test-report).
  • Negative controls: they compare the rule against today's behaviour, modelled as dest_check_today and post_write_check_today (both always OK) and PROTO_IN_PLACE / PROTO_WRITE_THEN_RESTORE.
  • Mutants, run on the lab:
    • letting a collision through fails 3 tests;
    • dropping the tested-bytes check fails 3;
    • making stage-then-rename write in place fails 1.
  • What it does not restate: it uses verified::reuse and does not restate seal_identity.t27 (remint_keeps already names the colliding file for frontier).
  • Seal: written on the lab with t27c seal --save, no --force; --verify gives all hashes MATCH.

This PR is spec-only. Closing the gaps needs Rust changes in run_seal / run_frontier, which go in a separate draft PR that waits for owner-approved-foreign.

🤖 Generated with Claude Code

…(REA 6.6.0 patterns)

Three write-safety patterns from REA 6.6.0, checked against `t27c seal
--save` and `t27c frontier --reseal` on the Railway lab (t27c 0.5.2,
master 89254d2):

- colliding seal paths refused before any write: missing
- the spec hash re-checked after the final write: missing
- completed seals survive a cut run: present, except the seal in flight

specs/verified/seal_write.t27 writes the rule: dest_check (free, own or
refused; an unreadable owner fails closed), post_write_check (re-hashed
spec, tested bytes and read-back must all equal the recorded seal) and
after_cut / proto_cut_safe (stage then rename leaves the old seal or the
new checked one). Today's save and reseal are modelled as the unsafe
references the negative controls compare against. 14 tests, 0 vacuous;
three weakened mutants each fail their controls.

Sealed on the lab with --save, no --force.

Refs #10457

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 12:51:17 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

…; t27b ledger names it

names_collide() now holds the measured reason for the case-insensitive
seal lookup (751 exact, 4 case-only, 558 bare-module names), so the Rust
copy of that comment can go when run_seal calls the spec (draft fix PR).
The t27b ledger gains the spec's entry (t27b pass), which the ratchet
listed as UNLISTED. Resealed on the lab with --save, no --force: 14/14,
0 vacuous, all hashes MATCH.

Refs #10457

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 13:06:11 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 50
PRs with All Checks Green 0
READY 0
FAILING 50
PENDING 0
NO CHECKS YET 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 1c83555 into master Oct 18, 2026
30 of 34 checks passed
gHashTag added a commit that referenced this pull request Oct 18, 2026
…ions, recheck, stage then rename (Closes #10454)

#10458 put the rules for one seal write in specs/verified/seal_write.t27,
but nothing in t27c called them. This commit makes the three seal writers
call the code generated from that spec. The Rust left in main.rs and
service.rs is I/O glue only. No second spec: seal_identity.t27 is the
same as on master.

seal_write.t27 gains the rules the glue needed that it did not have, each
with a test and a negative control:
- dest_allowed(code, force): --force lifts WRITE_OWNER_UNKNOWN (a torn
  or legacy seal) and never WRITE_COLLISION (another spec's file).
- gens_check(code, gens_same) and WRITE_GEN_MOVED: generating the spec a
  second time must give the recorded gen hashes.
- SEAL_STAGE_SUFFIX ".part": the staging file is .<seal>.part-<pid>,
  which is not a *.json seal name.
19 tests, 19 pass, 0 vacuous.

The glue:
- run_seal finds the destination with names_collide (exact or
  case-folded), reads its spec_path, and asks dest_check and
  dest_allowed before any write.
- write_seal_atomic stages the bytes beside the seal, syncs, lets
  post_write_check + gens_check judge the staged file, then renames. Any
  other answer removes the stage and leaves the old seal.
- tested = the hash of the spec bytes test-report built its tests from
  (new Report.read field); after = the spec hashed again after the tests.
- The twin seals and frontier --reseal go through the same staged write.

On the Railway lab, at master 1c83555 plus this commit:
- check: OK. test-report seal_write.t27: 19/19, 0 vacuous.
- seal --save, then seal --verify of seal_write.t27: all hashes MATCH. The
  committed gen file's sha256 equals the seal's gen_hash_rust.
- Collision: the second spec is refused, with or without --force; the
  first spec's seal is byte-identical afterwards.
- Torn seal: refused without --force, replaced with --force, parses.
- Spec edited mid-seal, at ten points from 0.05 s to 0.6 s: all ten are
  refused ("the spec changed while it was being sealed"), and no seal
  file is left.
- No .part file left behind in any control.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 18, 2026
…ions, recheck, stage then rename (Closes #10454) (#10466)

#10458 put the rules for one seal write in specs/verified/seal_write.t27,
but nothing in t27c called them. This commit makes the three seal writers
call the code generated from that spec. The Rust left in main.rs and
service.rs is I/O glue only. No second spec: seal_identity.t27 is the
same as on master.

seal_write.t27 gains the rules the glue needed that it did not have, each
with a test and a negative control:
- dest_allowed(code, force): --force lifts WRITE_OWNER_UNKNOWN (a torn
  or legacy seal) and never WRITE_COLLISION (another spec's file).
- gens_check(code, gens_same) and WRITE_GEN_MOVED: generating the spec a
  second time must give the recorded gen hashes.
- SEAL_STAGE_SUFFIX ".part": the staging file is .<seal>.part-<pid>,
  which is not a *.json seal name.
19 tests, 19 pass, 0 vacuous.

The glue:
- run_seal finds the destination with names_collide (exact or
  case-folded), reads its spec_path, and asks dest_check and
  dest_allowed before any write.
- write_seal_atomic stages the bytes beside the seal, syncs, lets
  post_write_check + gens_check judge the staged file, then renames. Any
  other answer removes the stage and leaves the old seal.
- tested = the hash of the spec bytes test-report built its tests from
  (new Report.read field); after = the spec hashed again after the tests.
- The twin seals and frontier --reseal go through the same staged write.

On the Railway lab, at master 1c83555 plus this commit:
- check: OK. test-report seal_write.t27: 19/19, 0 vacuous.
- seal --save, then seal --verify of seal_write.t27: all hashes MATCH. The
  committed gen file's sha256 equals the seal's gen_hash_rust.
- Collision: the second spec is refused, with or without --force; the
  first spec's seal is byte-identical afterwards.
- Torn seal: refused without --force, replaced with --force, parses.
- Spec edited mid-seal, at ten points from 0.05 s to 0.6 s: all ten are
  refused ("the spec changed while it was being sealed"), and no seal
  file is left.
- No .part file left behind in any control.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant