Skip to content

fix(ariba): retry a swallowed trigger click — both #183 documents now capture - #198

Closed
alexwolson wants to merge 1 commit into
mainfrom
fix-183-swallowed-trigger-click
Closed

fix(ariba): retry a swallowed trigger click — both #183 documents now capture#198
alexwolson wants to merge 1 commit into
mainfrom
fix-183-swallowed-trigger-click

Conversation

@alexwolson

Copy link
Copy Markdown
Collaborator

Closes #183.

Why this stopped being low priority

#183 called these two documents "worth a look next time the event page is open in a browser
anyway; not worth a dedicated live run" — on the reading that Part 2 - Construction Agreement_A1.pdf
was something specific to that row on that event.

Today's nightly hit the identical failure on a different solicitation:

Doc5713434353 (run 5):  Part 2 - Construction Agreement_A1.pdf
Doc5540340341 (today):  PART 2 - Consulting Agreement (V1.4) ...pdf
both → menu did not open within 15s (no VISIBLE 'Download this attachment' among 3 candidates)

Same position, same document class, byte-identical error. Lining the two events up names the
pattern:

event Part 1 Part 2 Part 3
Doc5713434353
Doc5540340341

Works, fails, works — parity, not a bad row.

Root cause (measured, not inferred)

A live read-only probe established both halves:

  • The three PML triggers own mutually exclusive popup containers — clicking Part 2 measurably
    drove _nhkn2b from 1 visible to 0, and Appendices ….zip vanished from the visible controls.
  • A clean click on the very Part 2 anchor that fails in a real run opens its menu in ~3s
    (item _atwlvisible: true, its container dropping is-dnone).

So the row is fine and the widget's state is not. _dismiss_menu's Escape hides the previous
menu while AribaWeb still believes it is open, so the next trigger click is consumed as a close —
the same trap _open_section already documents for the References toggles, one widget over.

The fix

_open_attachment_menu clicks the trigger again, bounded. The retry is safe for exactly the
reason _await_menu_clear is the wrong-bytes guard (#174 M1): that hazard needs a visible
stale menu item, and _await_menu_item only raises when zero are visible — the identical
precondition _await_menu_clear establishes before the first click. The zero is re-verified
immediately before the retry
rather than inferred from the raise, because the menu can land in
the gap between them, and a second click would then close what just opened.

_ensure_clickable runs up to _EXPAND_ATTEMPTS re-expansion passes instead of one — that is
#183's other half (schedule-b2.pdf's shape), reproduced live.

What is deliberately NOT claimed

The second expansion pass works; why is not established, and neither the code nor CLAUDE.md
says otherwise. It is tempting to reuse the parity proof above — and they may well be one bug —
but parity was measured on the PML trigger and nothing has measured the References
trigger. #174 already recorded this same behaviour as unexplained ("re-running the expansion
restores visibility while reporting it opened zero sections"). The post-condition is verified
after every pass for that reason, and a still-hidden control raises rather than falling into a
scroll_into_view timeout that says nothing about why.

An earlier draft of this change asserted #183 parity in the log line and comment for that path.
That was an overclaim and was corrected before commit.

Verification

Measured against the live event at each step, on an isolated data dir (~/tb-data untouched):

state result
before 3/4 — Part 2 omitted
PML retry only 3/4 — Part 2 captured, Appendices then omitted
both fixes 4/4, and no gap record written at all

That last point is the complete-capture signal working end to end: clear_omitted_when_complete
saw nothing missing and removed the record.

9 new tests, against fakes rather than a browser. Confirmed genuinely red→green by reverting
each fix in place: 5 fail against pre-fix behaviour, all 9 pass after. They pin the observable
behaviour (a swallowed click is retried; the retry stands down when a menu is already visible;
both loops are bounded) and deliberately assert nothing about the second pass's mechanism.

779 tests passing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W53WHx8mm2UHuLFAQWeF62

… capture

#183 listed two documents the capture "cannot reach" and called them low
priority, worth a look only if a browser happened to be open. Today's
nightly changed that: it hit the IDENTICAL failure on a different event,
so this is a class, not a row quirk.

    Doc5713434353   Part 1 ok   Part 2 FAILED   Part 3 ok
    Doc5540340341   Part 1 ok   Part 2 FAILED   Part 3 ok

Works, fails, works — parity. A live probe proved both halves: the PML
triggers own mutually exclusive popup containers (opening one measurably
closes another, _nhkn2b 1 -> 0 visible), and a CLEAN click on the very
Part 2 anchor that fails in a real run opens its menu in ~3s. The row is
fine; the widget's state is not. `_dismiss_menu`'s Escape hides the
previous menu while AribaWeb still believes it is open, so the next
trigger click is consumed as a close — the same trap `_open_section`
already recorded for the References toggles, one widget over.

`_open_attachment_menu` clicks again, bounded. The retry is safe for
exactly the reason `_await_menu_clear` is the wrong-bytes guard: that
hazard needs a VISIBLE stale item, and `_await_menu_item` only raises when
ZERO are visible — the identical precondition. The zero is re-verified
immediately before the retry rather than inferred from the raise, since
the menu can land in the gap and a second click would close it.

The other half (#183's schedule-b2.pdf shape) is the same fix one widget
over: a hidden menu-ITEM needed TWO re-expansion passes, not one.

Measured against the live event at every step, on an isolated data dir:
    before          3/4, Part 2 omitted
    PML retry only  3/4, Part 2 captured, Appendices then omitted
    both fixes      4/4, and NO gap record written at all

Deliberately NOT claimed: why the second expansion pass works. It is
tempting to reuse the parity proof, and they may be one bug — but parity
was measured on the PML trigger and nothing has measured the References
trigger. #174 already recorded that behaviour as unexplained. The
post-condition is verified after every pass for that reason.

9 new tests, confirmed red against pre-fix behaviour (5 fail) and green
after. 779 passing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W53WHx8mm2UHuLFAQWeF62
@alexwolson
alexwolson marked this pull request as draft July 28, 2026 16:54
@alexwolson

Copy link
Copy Markdown
Collaborator Author

Closing unmerged — the change is not safe, established by testing it against production.

It regressed the large event. Re-capturing Doc5713434353 with these fixes wrote 20/39 over an existing 37/39 bundle — 18 documents lost. The capture floor did not catch it: 20/39 = 51%, just above _MIN_CAPTURE_RATIO. Only having moved the original aside rather than deleted it prevented permanent loss.

And the claimed win does not survive the fuller data. Re-reading the measurements with the big event included:

small event (1 reference doc) large event (36)
before 3/4 37/39
PML retry only 3/4 — captured Part 2, then lost Appendices not measured
both fixes 4/4 20/39

The PML retry alone changed which document was lost, not how many. The PR generalised from a single small event; neither half is established as a net win, and together they are destructive at scale.

Per systematic-debugging's own rule — fixes that reveal new problems in different places mean stop and question the architecture rather than attempt fix #3 — this is closed rather than patched further. #183 is being re-scoped around understanding the popup-menu state machine first.

Production was restored and verified (37 + 4 entries, zip integrity clean, DB reindexed to 1855 leaves). Net effect of the exercise: +1 document recovered on Doc5540340341. Evidence kept at ~/tb-data/ariba/_183_backup_20260728/ (originals, pre-run DB, and the regressed 20-file zip).

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.

ariba: understand the popup-menu state machine — point fixes regress at scale (#174)

1 participant