Skip to content

bench: silent-saves 1.1.0, repeated runs under UI change, four arms (stacked on #1352) - #1380

Merged
abrichr merged 15 commits into
mainfrom
bench/silent-saves-change
Oct 20, 2026
Merged

abrichr merged 15 commits into
mainfrom
bench/silent-saves-change

Conversation

@abrichr

@abrichr abrichr commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Stacked on #1352 (itself stacked on #1303). Until those merge, the diff here includes them. This PR adds fault set 1.1.0 of silent-saves: repeated execution under UI change. It touches only packages/flow/benchmark/silent_saves/ and public-artifacts.json.

What 1.1.0 is

openadapt-flow silent-saves --fault-set 1.1.0 --agent <adapter>: the same MockMed task 100 times, with one UI change switched on per block, all MockMed's existing drift modes: renamed controls, display scaling, moved controls, a What's New screen, latency, a reordered queue, a moved New Encounter control, a look-alike referral, a relabeled type, and the target referral gone (where the right answer is to stop). Five items get a 1.0.0 server fault, including a duplicate that lands despite the page's save key. Versioned in fault_set_1.1.0.json.

Per arm it reports verified saves, silent wrong saves, false stops, items left for a person, human minutes per 100 items (only minutes a person logged; scripted approvals count as 0-minute events), and cost per verified item. Detection (server-fault bad saves reported as success) is kept apart from prevention (trap items where a wrong record landed).

Results (MockMed, 100 items per arm, 2026-10-19)

Arm Verified saves Silent wrong saves False stops Items left for a person Human minutes per 100 items Cost per verified item
1. Agent alone 90 of 90 5 of 100 0 of 90 5 0.0 $0.0433
1 + read-back (same runs) 90 of 90 0 of 100 0 of 90 10 0.0 $0.0433
2. Agent's first run under OpenAdapt 90 of 90 1 of 100 0 of 90 9 0.0 (93 scripted events) $0.0140
3. Program 62 of 90 0 of 100 28 of 90 38 0.0 $0.0000
3r. Program with self-repair 62 of 90 0 of 100 28 of 90 38 0.0 $0.0077
Arm Detection: server-fault bad saves reported as success Prevention: trap items where a wrong record landed Stopped when no correct save existed
1. Agent alone 5 of 5 0 of 25 5 of 5
1 + read-back (same runs) 0 of 5 0 of 25 5 of 5
2. Agent's first run under OpenAdapt 1 of 5 0 of 25 5 of 5
3. Program 0 of 5 0 of 25 5 of 5
3r. Program with self-repair 0 of 5 0 of 25 5 of 5
  • Arm 1 adapted to every change and stopped when Jane Sample was gone, but reported all 5 server-fault bad saves as successes. Gated on verify-run, the same runs reported none of them, with no clean save blocked. That is detection; the rows had already landed.
  • No arm wrote a wrong record on a trap item. The $0 screen-script reference, which clicks by position, wrote the wrong record on 20 of 25 trap items and reported every one as a success, so the traps do bite.
  • Arms 3 and 3r stopped on every item of three blocks (display scaling, What's New, moved New Encounter). Self-repair changed none of those: it declined the display-scaling halts, and no proposal passed its probe for the other two. No approval was asked.
  • Spend: $5.69 (arm 1 $3.90, arm 2 $1.31, arm 3r $0.48), within the approved caps. Every call is in each run's ledgers/; totals are in results/spend.json. Combined with the scoreboard's ledger, about $18.23, under the $20 stop.

Issues filed from these runs

Runner changes

  • compile_arm.py (arm 2) and repair_arm.py (arm 3r, a minimal MockMed SelfRepair target over the shipped ReplayTarget).
  • spend.py: a locked, per-arm cost ledger that reads the scoreboard's ledger and stops before an arm's cap or a $20 combined total.
  • A 300 s per-item watchdog that stops a hung Playwright driver. Arm 3 once hung for 2.5 hours at item 42; it was resumed from there.
  • table_1_1.py builds the README tables from the runs, and a test fails if they drift.

Honest notes

Tests

python -m pytest benchmark/silent_saves/tests -q from packages/flow: 25 passed (including the browser tests). Also passed: ruff check on the package, and the prospect-name check.

🤖 Generated with Claude Code

abrichr and others added 14 commits October 19, 2026 10:56
One runner (openadapt-flow silent-saves --agent <adapter>) drives an executor
through MockMed while its fault server breaks the save, and scores each item
from the store read before and after. Fault set 1.0.0 uses only kinds already
published in EFFECT_E2E.md and the scoreboard's claims run. Baselines are
rebuilt from committed scoreboard rows; no new runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…om prevention

- proof.py renders four claims-run items side by side: the agent's final
  message and the store before and after, with verify-run's verdict. The run
  kept no screenshots; the screen panel is a labeled local re-render.
- $0 reference runs of the screen-script, with and without the read-back.
- screen-script reads the banner and error in one page evaluation; the old
  two-call read raced MockMed's re-render under optimistic.
- README leads with the one-command runner and reports detection apart from
  prevention, which fault set 1.0.0 does not measure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tifact inventory

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One change per block over 100 items (MockMed drift modes), five server faults
from 1.0.0, a duplicate that lands despite the save key, metrics that keep
detection apart from prevention, human-event logging, and a cost ledger with
per-arm caps and a stop before $20 total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
compile_arm.py: the agent records once under compile_agent, scripted
admission, then the program; re-record only on a halt that wrote nothing and
was not a record check. repair_arm.py: the admitted program under SelfRepair
with the shipped ReplayTarget, a missing-referral fault probe and the
scoreboard's scripted approver. Spend goes to the benchmark's own ledger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ult through admission

Admission reset the page's fault to ok before the item ran. Only item 60
(duplicate) was affected; its invalid row is kept as item-060-invalid.csv and
the item was re-run alone after the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h a regex

CodeQL py/polynomial-redos on the FAULT pattern. An exact line match also
fails closed if the hook changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h a regex

CodeQL py/polynomial-redos on the FAULT pattern. An exact line match also
fails closed if the hook changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….0 table generator

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… 2, 3 and 3r

100 items per arm on MockMed; README tables generated from each run's
summary; screen-script reference run shows the traps catch a positional
executor. Spend $5.69 in results/spend.json, every call in the run ledgers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilent-saves-change

# Conflicts:
#	packages/flow/benchmark/silent_saves/app.py
abrichr added a commit that referenced this pull request Oct 19, 2026
…page zoom

Silent-saves 1.1.0 (#1380) stopped the compiled MockMed program on all 28
items of three UI-change blocks, and self-repair fixed none. Two causes are
fixed here:

- relink: a repaired copy of an admitted agent-compiled (JIT) program was
  refused by the run gate (DraftNotAdmitted), because its admission pins the
  digest every patch changes. A repair keeps the record check, so the
  admission now carries over: lifecycle.admit_repair writes a repair_probe
  admission (runs only behind a gate that stops before the save) and, after
  the person's approval or a signed standard change, a repair admission that
  embeds and re-verifies the prior one. A copy that changes the record check
  or parameters is refused.
- zoom: at 125% a correct screen failed its region_stable postcondition (the
  content is 25% larger and further from the origin). The check now also
  looks at the page scale this step's own click showed, only when both axes
  agree, within one percent, at the same thresholds. A covered region fails.

Measured on the same program and items: 18 of 28 now end correct (zoom 9 of 9
with no stop, relink 9 of 9 after one repair), 0 wrong saves. The What's New
block (notice) still stops: its fix clicks "Continue to tasks", which the
fail-closed write classifier reads as a possible save; the same
classification causes #1377. Both need a person's classification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	CAPABILITIES.md
#	packages/flow/public-artifacts.json
@abrichr

abrichr commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

Included in batch #1385, which runs CI once for several reviewed PRs. This PR is marked merged when #1385 merges. Please don't push here unless asked; a new commit leaves it out of the batch.

@abrichr
abrichr merged commit 111f2a5 into main Oct 20, 2026
34 of 41 checks passed
abrichr added a commit that referenced this pull request Oct 20, 2026
@abrichr
abrichr deleted the bench/silent-saves-change branch October 20, 2026 02:22
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