Repository navigation
feat(flow): build a working record check from the app's own reads - #1284
Merged
Merged
Conversation
scaffold-verifier now finds the GET the app made after the save (network capture, a SQLite read path, or a verifier section) by the recorded values, fills in a check bound to run parameters, guards every other table, and tests it against the effect_e2e fault classes before review: on the recorded records always, and end to end through the replayer on MockMed or the effect_e2e service with --prove. A check that misses a fault is a draft with the misses listed (exit 1). Nothing is approved. Adds effects.kind: surfaces (one read per table or resource, effects routed by probe) and an identity coverage report for unarmed clicks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A table --db can't read, or a write no read covers, keeps the check a draft. - stale is a miss when no checked field tells records of one subject apart. - Reads with ids get a content twin (records_drop_fields: [id]); new changed/deleted faults; guards catch changed or deleted rows. - One name space across sources; record ids in URLs stay out of names and a pinned record path is a miss. - The save is timed from its write request (events are stamped after settle); an empty before-read is a baseline. - Generated reads are built, and --db reads run, inside the proof; SQL placeholders are :p0..; literal braces stay single without placeholders. - A broken capture falls back to the TODO draft; a demo with no write step is refused on the new path too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 19, 2026
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.
scaffold-verifierused to write a draft that checked nothing until a person filled it in. It now builds the record check from the reads the app made after the save, and tries to break it before anyone reviews it.What it does
openadapt-flow scaffold-verifier rec/ [--db app.sqlite] [--verifier verify.yaml] [--prove mockmed|effect-e2e] [--bundle bundle/] [--complete-read]meta.jsonparams): REST lists and FHIRBundles from the network capture (network.jsonl, theopenadapt.network-capture/1format from feat(flow): API steps compiled from a recording's network capture #1269, read without importing the recorder side), a SQLite database (--db, every table), or a reviewed verifier section (--verifier).record_check.proposed.yaml(theverify.yamlshape). The check expects exactly one new record, matched on the recorded values bound as{param: ...}plus fixed values the save sent. No other record may change or disappear. A read whose records carry anidgets a content twin (records_drop_fields: [id]), so a changed row with the same id is caught. With--db, every other table gets a guard: no row added, changed or removed. A write no read covers, or a table that couldn't be read, keeps the check a draft.record_check.proof.jsonholds the results of the effect_e2e fault classes applied to the recorded records. With--prove, the same check also runs end to end through the real replayer against MockMed or the effect_e2e service, judged by that fixture's own ground truth. Free-text values change on every run, so a check that froze the demo values fails the clean save. If the check misses any fault, it's written as# DRAFTwith eachMISS:listed, and the command exits 1.needs_operator_confirmation: true.verify-runandqualifyrefuse the file until a person removes those lines.--bundle, it reports how many clicks have the right-record check armed, before and after evidence from the recording's DOM or accessibility text at each unarmed click. It only proposes evidence the runtime checks on that surface. The evidence text goes toidentity.proposed.json(mode 0600).New engine piece:
effects.kind: surfaces(runtime/effects/surfaces.py) gives one read per table or resource. Each effect names its read inprobe. An effect that names no read, or one that isn't configured, halts. Whensurfacesis unset, existing verifier identity digests don't change.Results (synthetic, no model calls)
/api/records)--db(encounters, banner, billing)--break-itserver/api/db--complete-read(declared, recorded as such); then 6 of 6 faults caught end to end.Observation?patient=/apis/default/api/patientbenchmark/openemr_local/verify.yaml.Review
An independent review found two fail-open bugs, both fixed with regression tests. Skipped tables still counted as "every table read". A
stalefault was credited when the selector couldn't tell the records apart. The same pass fixed:Not done
scripts/build_llms_full.pyexist only in docs: one map of what OpenAdapt can do #1260 (open). I'll update the row and re-run the script here once docs: one map of what OpenAdapt can do #1260 lands.--dbreads SQLite only. Other databases go through--verifierwithkind: sql.Docs: EFFECT_KIT.md (new section and the
surfaceskind), claims.yaml → VERIFICATION.md (new claimrecord-check-from-app-reads; the identity caveat now names the coverage report).🤖 Generated with Claude Code