Skip to content

flow: classify common local edits from the recording, on strict evidence - #1366

Merged
abrichr merged 3 commits into
mainfrom
flow/local-edit-classification
Oct 20, 2026
Merged

abrichr merged 3 commits into
mainfrom
flow/local-edit-classification

Conversation

@abrichr

@abrichr abrichr commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Approved by the founder on 2026-10-19, with a strict rule. Design: packages/flow/docs/design/LOCAL_EDIT_CLASSIFICATION.md.

Why

A compiled program flags every special key and every unlabelled or navigation-shaped click for a person. On the OpenEMR referral that is 8 × Control+a before typing, 4 × Enter after typing a dropdown option, and an in-form tab click. On MockMed's What's New change, the "Continue to tasks" dismiss is treated as a write, so effect mining gives it a placeholder record_written and admission refuses every recording (#1377).

The rule

The compiler classifies a step only when both of these hold:

  • The recording shows no mutating request for it. Network capture is required, with no request other than GET, HEAD or OPTIONS between the previous event and the next. URL, title and page count must be recorded on both sides and unchanged. If the recorder snapshotted the record store, the snapshots must be equal.
  • A runtime check confirms only the expected local change. The check runs every time, fails closed, and halts the run if the action did anything else.

Anything else goes to a person, as today. Write-shaped context and risk_overrides still win. The duplicate-prevention key is untouched.

Pattern Step evidence Runtime check
select_all: Control+a / Meta+a previous step clicked a text field with a selector; next step types local_edit: focus still on that field; URL, title and page count unchanged
confirm_option: Enter in a dropdown dropdown click, then a typed parameter local_edit + field_value (the dropdown shows this run's value)
confirm_entry: Enter in a text field text-field click, then a typed parameter local_edit + field_value (the field's value matches exactly)
in_form_tab role tab, or a button whose only mined check is a region change; next acting step in the same frame local_edit
dismiss_dialog button/link labelled only "Continue", "Continue to …", "Next", "Close", "OK", "Got it", "Dismiss", "Not now", "Maybe later" or "Skip for now" local_edit + text_absent of the label
  • continue and next are write words, so a dismiss starts irreversible. It is reconsidered only when those are its only write words and its risk is still the per-step keyword inference. A click that a later rule made irreversible is never reconsidered: the click that confirms a dialog, or an icon-only click presumed to save. "Continue to checkout" and "Continue and save" stay irreversible.
  • The run gate's risk re-inference recognizes a classified step only from what the bundle seals: the local edit: explanation and its checks.
  • A classified tab click is no longer tagged entity_navigation. clinical-write's prohibit_unarmed_clicks still applies to it.
  • Postcondition's new fields are left out when unset, so existing bundles serialize byte-for-byte as before.
  • Since the last review, this also fixes the CI crash on a structural target with no frame_path, and a mypy index error.

Limit: network capture is opt-in (record --capture-network). A recording made without it classifies nothing. To clear #1377 in the silent-saves arm, the agent has to record with capture on.

OpenEMR referral, re-admitted offline (main merged + this PR)

Policy main with this PR
permissive 12 1
clinical-write 32 9

These counts are the same under no profile, Standard and Regulated.

  • Classified: 11 of the 12 keys, and the Contact tab.
  • Still for a person: step_007 (Control+a in Last Name). OpenEMR's background POST /library/ajax/execute_background_services.php landed in its window.
  • Still blocked:
    • step_015 (the Contact tab) is unarmed under clinical-write.
    • step_039 is unarmed and has no identity contract or record check on its GUI path.
    • step_039 and step_040 have no duplicate-prevention key, which stays a person's choice.
    • The bundle isn't encrypted at rest. Sealing it fixes that.

Tests

tests/test_local_edit_classification.py, 45 tests. Every case has a positive test and a test where a write request was sent, which must refuse:

  • Control+a in a textbox;
  • Enter in a textbox and in a combobox;
  • a tab click in the same form;
  • the What's New dismiss, both unit-level and compiled end to end with effect mining on. Compiled, the dismiss gets no record_written and the save keeps its own.

Also covered:

  • no capture, a changed URL, or a changed record store refuses;
  • dismiss-shaped labels with another write word, and the click that confirms a dialog, are never reconsidered;
  • the re-inference needs the sealed checks;
  • the runtime checks fail on a URL change, lost or unreadable focus, the wrong dropdown label, or a text value that isn't an exact match.

🤖 Generated with Claude Code

Draft for the founder; not for merging until decided
(docs/design/LOCAL_EDIT_CLASSIFICATION.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
abrichr and others added 2 commits October 19, 2026 19:01
…eld and a dialog's dismiss

Every pattern now needs network capture showing no write in the step's window,
URL, title and page count unchanged, and equal record-store snapshots when
the recorder took them. Control+a no longer classifies without capture.

New patterns: confirm_entry (Enter after typing into a text field; the
field_value check reads the text field's exact value) and dismiss_dialog
(an informational dialog's dismiss, e.g. MockMed's What's New 'Continue to
tasks'; checks the page is unchanged and the label is gone). A dismiss is
reconsidered only when 'continue' or 'next' are its only write words and its
risk is still the per-step keyword inference, so effect mining no longer
attaches a placeholder record_written to it (#1377).

Fixes the CI crash on a structural target with no frame_path and the mypy
index error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abrichr abrichr changed the title flow (proposal): classify common local edits from the recording flow: classify common local edits from the recording, on strict evidence Oct 19, 2026
@abrichr
abrichr marked this pull request as ready for review October 19, 2026 23:15
@abrichr

abrichr commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

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

@abrichr
abrichr merged commit 7ce9e60 into main Oct 20, 2026
24 of 40 checks passed
abrichr added a commit that referenced this pull request Oct 20, 2026
batch: API-step fixes, compatibility matrix and local-edit classification (#1370 #1371 #1372 #1364 #1374 #1366)
@abrichr
abrichr deleted the flow/local-edit-classification branch October 20, 2026 00:24
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