Skip to content

Self-repair qualified end to end on macOS AX; same_fields reads OCR-glued words - #1715

Merged
abrichr merged 14 commits into
mainfrom
claude/repair-same-fields-glued
Nov 3, 2026
Merged

abrichr merged 14 commits into
mainfrom
claude/repair-same-fields-glued

Conversation

@abrichr

@abrichr abrichr commented Nov 3, 2026

Copy link
Copy Markdown
Member

Stacked on #1714; retarget to main after it merges.

Result. Backend-neutral self-repair (#1709) now runs end to end on native macOS. The test is a native Cocoa test app with a SQLite database, driven through MacOSBackend. The AX tree, screen capture, input and database are live; the repair agent and the approver are scripted.

  1. The run stops at a new "Update available" notice before any save.
  2. The "Later" click is admitted on element_and_record_check (button 'Later').
  3. The probe passes: nothing written, target found, same record, same fields.
  4. The replay campaign passes (1/1).
  5. The fault campaign passes (1/1): another patient's chart stops before the save.
  6. One person approves through the decision portal.
  7. The resumed run is VERIFIED, with exactly one new row for the patient.

Under demo, and with no verifier, the click is refused and nothing is written.

That passing run holds the app's caret steady (--steady-caret). With a blinking caret, the save click is refused at the frame lease and nothing is written: #1713.

Changes

  • repair/self_repair.py, _pre_save_checks: on a backend with no form to read, OCR may glue a field's words together (REPAIREDRUNFOLLOWUPINTHREEWEEKS). A value of two or more words and at least six letters now also counts when it appears on one line with its words joined (_glued_on_a_line). Single words, and any value too short, keep the word rule. This is a screen pre-check; the record check verifies the saved value.
  • benchmark/repair_every_backend/qualify_macos.py:
    • provisions a throwaway approver roster in the work folder, the way the test fixture does, so the scripted answer is signed like a phone answer;
    • adds --steady-caret.
  • The benchmark README, the design note's "Qualified so far" section, the results JSON and the changelog.

Tests: _glued_on_a_line unit test; the self-repair, auto-repair and element-identity suites: 80 passed.

This changes a repair check, so it needs its own adversarial review.

…fields, a throwaway approver roster, --steady-caret
…; typed refusals; TYPE focus label

Review fixes for #1714: the element must still be the one match with the
same fingerprint, and the hit-test at the point must be that element or a
part of it that can't be pressed, before each press (both edges of a double
click). Refusals before the first press raise StructuralResolutionRefused.
The TYPE focusing click labels a physical receipt dom, as CLICK does.
… names its commit and mode; scrubbed app env
…ady caret VERIFIED; blinking caret and pixels stop before any save
… in the live AX tree with nothing pressable between

Re-review blocker on #1714: bounds alone admitted a nested button's label or
an overlay. QuartzMacAXClient.is_part_of walks AXParent with CFEqual from the
hit to the target and refuses any node offering an action other than
scrolling or a context menu; a client without it refuses every structural
click.
@abrichr

abrichr commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

Independent adversarial review

The reviewer was an independent subagent, given the diff and the product's safety rules, read-only. There were three rounds.

Round 1 (9ea78be): REQUEST CHANGES.

  • Blocker: the glued same_fields match was a raw substring. "5 mg bid" passed against "25 mg bid", and "John Smith" against "JOHNSMITHSON".
  • Non-blockers:
    • the evidence named the parent commit;
    • the blinking-caret result had no file;
    • "one person approved" overstated a scripted approver;
    • the approver roster settings leaked into the app subprocess.

Round 2 (0c3e3f1 and a355989): REQUEST CHANGES. The code fixes were sound:

  • whole consecutive OCR words only, with the five negative cases as tests;
  • git_sha and git_dirty in each result;
  • one result file per mode;
  • the scripted approver named as such;
  • a scrubbed app environment.

The remaining blocker: one doc sentence said the blinking-caret run was refused at the save, while the clean-tree evidence stopped in the probe.

Round 3 (641f3b9): APPROVE. The README and the doc match macos-ax-steady-caret-20261103.json (resumed, VERIFIED, exactly one row) and macos-ax-20261103.json (no_fix at step_001's identity check, no rows). Both were recorded at c6c07d5 with a clean tree.

Open non-blockers:

  • the pixel evidence is from 0c3e3f1; the pixel path doesn't use the macOS changes after it;
  • the screen check is word presence on the whole screen, not per field;
  • a browser whose DOM read fails falls back to OCR instead of failing closed.

Base automatically changed from claude/macos-structural-receipt to main November 3, 2026 00:45
@abrichr
abrichr merged commit 03ca247 into main Nov 3, 2026
45 checks passed
@abrichr
abrichr deleted the claude/repair-same-fields-glued branch November 3, 2026 01:23
abrichr added a commit that referenced this pull request Nov 3, 2026
abrichr added a commit that referenced this pull request Nov 3, 2026
Self-repair and repair by default run outside a browser with
repair.session, qualified end to end on macOS AX and not yet on Windows
UI Automation or RDP. Teaching the fix (--hold-on-halt) and rollback
stay web-only.
abrichr added a commit that referenced this pull request Nov 3, 2026
…1706)

* Backend parity: capability by surface, with evidence for every cell

Rewrites docs/BACKEND_PARITY.md as a capability x surface matrix (web,
Windows, macOS, Linux, RDP, Citrix), each cell QUALIFIED, TESTED,
CODE ONLY or MISSING with its evidence path, and links the twelve
backend-parity issues.

Corrects claims the evidence doesn't support: Citrix in-session has no
run inside a Citrix session, the Linux GTK3 job doesn't run in the
monorepo, the macOS trials drove the backend directly, repair and
rollback run on web apps only, and the RDP numbers name their apps and
scripted harness.

* Backend parity: apply the adversarial review

Split rollback (refused off the web) from undo (code only off the web);
add the surface-neutral guarded save; one rule for scripted recordings;
Windows compile and record were run on a real VM, with the full 4 of 10
run tally; shadow mode gets the same verdict on every surface; web
approvals drop to tested (scripted person, local Cloud stand-in); live
repair vs offline teach; more refusals; the Aardwolf RDP batch was a
Windows 11 VM; flow's linux-atspi-x11 job, not capture's AT-SPI read,
is the one that never runs.

* Backend parity: non-web self-repair exists (#1709, #1715, #1717)

Self-repair and repair by default run outside a browser with
repair.session, qualified end to end on macOS AX and not yet on Windows
UI Automation or RDP. Teaching the fix (--hold-on-halt) and rollback
stay web-only.

* Backend parity: describe qualified surfaces with evidence
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