An archive lookup should survive a dashboard changing its summary. Consider a design scenario: a worker can retrieve the latest Enterprise invoice, but after payment the Overview card shows an estimate instead. A selector waiting for the old heading fails. If the job converts that failure into “no invoice,” it has confused a page state with document history.
I work on BrowserAct. While adapting our GitHub billing guide, this transition suggested a useful developer example: an explicit lookup plan that distinguishes summary states from historical evidence. The Python below is an application-side contract tested on fictional observations. It does not access GitHub billing, call an API, make a payment, retrieve a real invoice or validate a GitHub Bot.
An estimate is a routing signal
Our GitHub source guide follows official instructions checked on November 9. For invoiced Enterprise customers, Overview can expose Latest invoice and View invoice. When all invoices are paid, GitHub describes the section changing to Estimated next payment. Historical documents remain a separate Past invoices route, using the invoice reference.
Personal and organization Payment history have their own available receipt or invoice controls. Azure-connected billing and Enterprise Server without the corresponding GitHub.com account also require separate context. This example deliberately handles only a known invoice reference for an invoiced Enterprise account. It does not use a repository URL, paid seat or personal receipt to infer that context.
The operational implication is small but important: when the summary becomes an estimate, plan another read of Past invoices. Do not click a payment control, edit billing information or request a new arrangement just to make the previous summary appear again.
Model observations rather than CSS failures
The request contains a reviewed enterprise reference, billing model and known invoice reference. The view contains independently observed account context, surface, heading and evidence reference. The names in this contract are ours, not GitHub API fields or promised DOM attributes. A separately tested adapter must derive them from the actual authorized page.
Use stable internal account references rather than display names. An administrator can manage several enterprises while also owning a personal plan. Matching an amount or seeing a familiar avatar does not establish the charge owner. Unknown account scope goes to review before any document action is planned.
The function returns action names, not URLs, browser clicks or completion flags. That makes the estimate transition testable without putting credentials or billing links into the example.
def plan_invoice_lookup(request, view): required = ("enterprise_ref", "invoice_ref") if any(not isinstance(request.get(k), str) or not request[k].strip() for k in required): return "review_request" if request.get("billing_model") != "invoiced_enterprise": return "review_billing_route" if view.get("enterprise_ref") != request["enterprise_ref"]: return "review_account_scope" if not view.get("evidence_ref"): return "review_observation" surface = view.get("surface") if surface == "overview": if view.get("heading") == "estimated_next_payment": return "inspect_past_invoices" if view.get("heading") != "latest_invoice": return "review_page_state" elif surface != "past_invoices": return "review_billing_route" rows = view.get("rows") if not isinstance(rows, list) or any(not isinstance(x, dict) for x in rows): return "review_observation" matches = [x for x in rows if x.get("invoice_ref") == request["invoice_ref"]] if len(matches) > 1: return "review_ambiguous_reference" if len(matches) == 1: row = matches[0] if row.get("document_kind") != "invoice": return "review_document_kind" if row.get("download_available") is not True or not row.get("evidence_ref"): return "review_download_control" return "open_latest_invoice" if surface == "overview" else "open_past_reference" if surface == "overview": return "inspect_past_invoices" return "not_found_in_reviewed_view" if view.get("listing_complete") is True \ else "continue_history_inspection" An unknown heading is not silently treated as an estimate. That could hide a permission message or a changed interface. Similarly, a receipt or estimated amount with the requested reference is not accepted as an invoice. A matching reference still requires the observed invoice document kind and a current download control.
These evidence fields are trust boundaries. The function does not authenticate an observation, check the operator's role, verify a PDF or prevent the UI changing after observation. A browser worker must recheck the account and selected invoice immediately before following a planned control, then save a separate artifact receipt after inspecting the downloaded document.
Give history lookup a bounded meaning
| Observed state | Planned result | What it does not establish |
|---|---|---|
| Overview shows an estimate | inspect_past_invoices | No historical invoices exist |
| Latest invoice matches the requested reference | open_latest_invoice | File delivery is complete |
| Latest invoice is another reference | inspect_past_invoices | The requested invoice was deleted |
| Past invoices has one matching invoice control | open_past_reference | The saved PDF has been verified |
| History observation is incomplete and has no match | continue_history_inspection | Absence from complete history |
| Reviewed view is complete and has no match | not_found_in_reviewed_view | Supplier-wide document absence |
listing_complete is supplied by the adapter after it has reviewed the bounded view and its pagination or filters. It is not inferred from an empty rows array. Even a complete reviewed view has a scope and observation time; it may not cover every historical period or another billing account. Keep that boundary in the task record.
Duplicate matches are ambiguous, even when they appear visually similar. Preserve both observations and review the mapping. Do not pick the first row based on DOM order or collapse different references because the amounts happen to match.
Test the transition before wiring browser actions
The local synthetic checks exercise estimate-to-history routing, a known latest reference, another latest reference, a matching past reference, incomplete history, strict boolean handling, duplicate matches, wrong account scope, missing evidence and document-kind mismatch. They run only this pure function; no actual GitHub page, API response or invoice file is used.
In production, capture the reason for each planned read, execute only the corresponding document-navigation action, and record the new observation before replanning. Apply a bounded inspection budget so an incomplete listing does not create an endless history loop. A download error should remain a delivery error, while a page-state review remains a page-state review.
BrowserAct or another authorized browser worker would need a separately validated adapter for these routes. The implementation boundary is useful regardless of the worker: a dashboard estimate can change where the lookup continues, while the original invoice request stays open until the specific document is actually delivered and verified.




