Repository navigation
verify-run: frame conditions (nothing outside the declared delta changed) - #1443
Merged
Merged
Conversation
…anged A record check said a save was right while another chart was edited in place (#1365). The frame judge compares the whole read set before and after the save, once per contract: any record outside the declared records that was added, removed or changed, or a target changed outside its declared fields, is collateral. A change that the app's audit log or a modified-by field with a new version attributes to another user is a concurrent edit and does not count; a change by the bot's own ids or one nothing explains does. - runtime/effects/frame.py: FrameSpec, FrameAttribution (audit_read, record_field), judge_frame. - verify-run: optional frame: section; the audit read is taken with the baseline; the frame judge replaces the per-effect collateral rules when a baseline exists; without one the frame is not_checked and the run is not verified. - Receipt: optional signed field checked {delta, frame, source}; source is 'instruction' (the --params). verified requires every part. evidence.frame carries counts and field names only. - countersign verify shows and checks it; qualify ignores frame:. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scaffold-verifier reads each table by id and by content (records_drop_fields: [id]). The frame judged the twin as its own slice, so the saved row looked like an undeclared addition there. Surfaces that differ only in dropped fields now share their declared records. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 20, 2026
The safety review of #1443 set three conditions on excusing a change as another user's concurrent edit: - record_field attribution must name fields the app sets on the server, declared per app in server_set; a field the run writes, or a run parameter names, refuses the attribution (every change unattributed). - the executor's own id joins the bot's ids: never another user. - another actor's change to a record the save declares blocks verified (the saved value may not stand); only changes outside the declared delta are excused. Server-set bookkeeping fields are ignored as content: they say who wrote, not what changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
|
Coordinator safety review: approve at 81034b7.
🤖 Generated with Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 1 of the design in #1434 (
docs/VERIFICATION_COVERAGE.md): frame conditions forverify-runand the guarded save.Problem
In #1365's OpenEMR fault run,
verify-runreportedverifiedon all 5 saves where another chart was edited in place. #1375 addedforbid_collateral_change, but it judges one effect at a time. Two effects on one read set flag each other's targets, a stray added record passes, and it can't tell a legitimate edit by another user from a stray write.Change
runtime/effects/frame.py:judge_framecompares the whole read set before and after the save, once per contract. Any record that no effect declares and that was added, removed or changed is a frame change. So is a pre-existing target changed outside the fields the effects name.frame.attribution):audit_read: a second read-only read of the app's audit log. Entries new since the baseline are the window.record_field: a modified-by field plus a version or ETag on each record.self, literals or params), or one nothing explains, is collateral. Withaudit_read, a bot log entry on an undeclared record is collateral even if the read shows no change.effect_verdictREFUTED, so older readers see what they saw before.not_checkedand the run is notverified.checked: {delta, frame, source}.sourceisinstructionhere (the--params); provenance comes in a later PR.verifiedrequires every part, whichreceipt_problemandcountersign verifyboth enforce.evidence.frameholds counts and field names only, never records or actors.countersign verifyprints a "Checked" line. qualify ignoresframe:, so oneverify.yamlstill serves both commands.Safety review: changes to when
verifiedis issuedCoordinator review requested (local_bcd23d2d) before merge.
No baseline means no
verified. Before, an absolute-count contract could verify without one.A record added to the read set that no effect declares now refutes.
A wrong-patient write is
reconciliation_required, no longerhalted_before_effect. A record was written;test_wrong_patient_is_refutedchanged accordingly.Two effects on one read set no longer refute each other's targets.
The only loosening, with the review's three conditions (commit 81034b7, a test each):
server_set). A field the run writes, or a run parameter names, refuses attribution.verified(target_changed_by_other); only changes outside the declared delta are excused.Before the conditions: a change that an audit log or a modified-by field with a new version attributes to a named non-bot user is not collateral. Unattributed changes, and an unreadable log, still refute.
Flow replay's
verifiedis unchanged by this PR; the design doc says so and plans it separately.Tests
tests/test_frame_conditions.py(28): the judge, both attribution kinds, verify-run end to end on MockMed, and a SQLite store with its own audit log where another user's edit staysverifiedand the bot's own edit is refuted.test_qualification_gate_campaign::test_cli_durable_authority_failure_preserves_the_original_failure) fails the same way on a cleanorigin/maincheckout here.The fresh OpenEMR and openIMIS benchmark runs follow in their own PR.
🤖 Generated with Claude Code