Widget And Action Correctness Guideline
This page documents the committed source. Treat revision-sensitive RuneLite UI, packet, or in-game outcomes as pending live-client verification unless the page records direct evidence.
Stage 1 established the inventory and enforcement boundary. Stage 2 uses the same check to migrate findings without weakening compatibility guidelines. Run the inventory with:
.\gradlew.bat auditStageOneCorrectness --console plain
The task parses and semantically analyzes src/main/java with the JDK compiler tree API and writes build/reports/correctness/stage-1-audit.json. The report records its source HEAD revision, audited-source/config dirty state, audited-source/config content digest, category and disposition totals, and a source-located entry for each audited declaration or use. Unrelated worktree changes do not affect auditedSourceDirty.
Categories
| Category | What it records | Stage 2 direction |
|---|---|---|
widget_constant | Canonical widget declarations and legacy/reference aliases | Removed local WidgetInfoExtended / WidgetID wrappers are not production sources; live widgets remain a separate gate |
raw_widget_lookup | Two-argument getWidget(group, child) calls | Use a canonical WidgetCatalog address or typed target |
packed_widget_id | Packed (group << 16) | child expressions | Use a canonical constant or WidgetAddress |
semantic_first_match | Widgets.search(...).first() selection | Resolve zero, one, and multiple matches explicitly |
legacy_widget_action | Legacy void widget-action queues | Preserve compatibility facades; migrate modern consumers around them |
direct_widget_packet | Direct widget packet calls | Route modern callers through Api.actions.* |
deprecated_api | Deprecated declarations and WidgetInfo imports | Isolate compatibility code under a legacy boundary |
deprecated_use | Compiler-resolved uses of deprecated declarations | Move modern consumers to supported guidelines |
ambiguous_action_match | First-match ActionResolver.findActionIndex(...) calls | Require a unique match or explicit op index |
optimistic_result | InteractionResult.success(...) calls | Distinguish dispatch from observed confirmation |
action_helper, query_helper, widget_helper | Shared helper declarations | Preserve ownership while migration proceeds |
Boundaries And Dispositions
modernentries are current production paths. Raw, optimistic, or deprecated uses remain visible asfindingentries until a later stage migrates them.legacyentries are physically under alegacypackage. Location alone does not suppress a finding.exceptionentries must match a committed allowlist item by category and path plus an exact stable finding ID, symbol, or narrow source locator. The task rejects whole-file and wildcard suppression.dispositionrecords source status:compliant,finding, orallowed.liveEvidenceStatusis independent and identifies canonical widget constants that still require controlled RuneLite evidence on the target revision.- Catalog source accounting and alias consistency never promote a mapping to live evidence. Reference-only targets remain searchable but are rejected by safe address resolution and stay visible to the check. A reference alias resolves only through a matching current authoritative actionable target.
Deprecated named WidgetPackets compatibility facades delegate to WidgetActions; production code does not call those facades. Modern result-aware actions preserve click ownership through WidgetActions: check ActionPacer, queue the click through MousePackets.tryQueueClickPacket(), issue the widget packet, verify its PacketSendResult, then record the action. A paced or failed click queues no widget packet. A failed widget packet returns PACKET_NOT_QUEUED, does not record pacing, and is never reported as DISPATCHED.
Client-owned widget operations that depend on local listeners require the native RuneLite menu-action path. Named WidgetActions.interact(...) automatically selects native CC_OP when getOnOpListener() is non-null; interactViaMenuAction(...) remains the explicit native path used by side-tab actions. Both paths queue the click first. Bank closing likewise queues a click before the native WIDGET_CLOSE action because the close behavior is client-local. These native operations use the shared revision-cached MenuDispatcher, not an injected Client.menuAction(...) API. Server-owned widget operations continue to use direct packet dispatch after the same click gate.
A successful check task proves that the inventory was generated, the allowlist is structurally valid, and no finding was added outside the reviewed structural fingerprint baseline. It does not prove that existing findings are migrated or that revision-sensitive widgets work in the live client.
Allowlist Guideline
src/test/resources/audits/stage-one-correctness-allowlist.json is reserved for proven exceptions. Each entry includes an ID, category, exact path, an exact stable finding ID, symbol, or narrow locator, plus reason, authority, reviewed revision, and removal condition. Every entry must match exactly one compiler-AST finding.
The same resource stores the reviewed finding count and digest for each category. Stable finding IDs use structural owner, category, subcategory, normalized evidence, and deterministic occurrence rather than source line. Blank-line movement therefore does not change the reviewed identity.
Stage 2 Migration Progress
Result-aware packet helpers use ActionResolver.findUniqueActionIndex(...). NPC, object, player, ground-item, and modern widget actions fail closed when zero or multiple slots match. ActionResolver.hasAction(...) retains any-match query semantics. Named widget actions go directly through WidgetActions, including its unique action resolution, pacing, click ordering, and listener-aware dispatch.
The modern semantic-first-match, two-argument widget lookup, ad hoc packed-ID, direct widget-packet, and optimistic-result slices are resolved or explicitly classified. Intentional low-level or direct-packet boundaries use exact allowlist entries. The removed BankInteraction, BankInventoryInteraction, and InventoryInteraction facades are covered by the migration guide; current production callers use result-aware actions, and source guards verify that reviewed direct widget-packet callers queue a click first.
Modern bank, trade, break-handler, utility-event, world, deposit-box, combat, prayer, production, Grand Exchange, and walker widget operations use the paced result-aware boundary. Walker and Break Handler state machines retry PACED and transient results instead of advancing or treating them as terminal.
InteractionResult distinguishes accepted dispatch from observed state: DISPATCHED means the packet or action was accepted for dispatch, while CONFIRMED means the requested state or postcondition was observed. Legacy SUCCESS remains supported for compatibility. accepted() includes all three statuses; succeeded() is limited to legacy success or observed confirmation, so a dispatched action cannot by itself complete a workflow step.
Aggregate counts are generated by auditStageOneCorrectness and belong in its build log rather than this guideline. A passing structural check does not award LIVE_VERIFIED for revision-sensitive widgets.