Skip to content

loader-PL1 (d): a late completion never lands on the next op's handle; a failed open publishes no instance; dead pub items deleted - #678

Merged
MattJackson merged 9 commits into
predevfrom
loader-pl1-d
Oct 10, 2026
Merged

MattJackson merged 9 commits into
predevfrom
loader-pl1-d

Conversation

@MattJackson

Copy link
Copy Markdown
Collaborator

Loader-PL1 (d): three dispatcher/plugin correctness fixes and a dead-code cleanup.

  • deps: bump bytes from 1.11.1 to 1.12.0 #5: a late completion never lands on the next op's handle. Each ticket's service results live under an epoch, minted fresh by the op's first stored result and ended by a forget (a new op or tick on the ticket, or its recycle). Every Completer carries its op's epoch. A completion from an epoch that is over is dropped and wakes nothing (THE DESIGN §11.11 H2, §11.12).
  • deps: bump getrandom from 0.2.17 to 0.3.4 #6: a failed open publishes no instance. An OpenEnded guard nulls the instance pointer on every exit except READY/PENDING. is_open() reads an opened flag that only READY sets, so a half-open box is never open. A box the plugin still holds after a host-judged FAULT is closed at once. A pended open that the host cancels is closed once, inside the open's own lifecycle exclusion.
  • deps: bump rustls from 0.23.40 to 0.23.41 #10: dead pub items are deleted. These are services::UNIMPLEMENTED, OutboundInstance::open, ticket::Completions/Redeem and Dispatcher::completions. They were a second, unused home for completion handles. ServiceStore::held is now test-only.

Merge of origin/predev: host_services_tests.rs conflicted on the test double's trust_sight override, which predev removed because the shared contract double already refuses it. Took predev's side.

RED arms: a_late_completion_from_an_ended_op_never_lands_on_the_next_ops_handle, red_an_open_that_faults_on_its_resume_leaves_no_instance, red_an_open_the_host_judged_fault_is_closed_never_leaked, red_a_cancelled_pended_open_is_closed_once, red_a_late_close_after_the_auto_close_is_refused_never_double_freed.

Proof (Latchkey cli-86390d04-dab4-4d83-ac66-19a57319d86b): fmt, workspace examples and clippy -D warnings rc 0. busbar-plugin-loader had 614 passing with and without conformance. The only failures were the two busbar_secret_env_plugin both-ways tests (cdylib not built on the runner, known). kind-isolation answered no-base because origin/predev moved during the job. The branch was then merged with predev 5c23d75 (no loader files); CI judges that merge.

Note: loader-pl1-a (#671) touches the same line in dispatch/watchdog.rs. Whichever lands second keeps a's purge and drops completions.forget_worker.

…e next op's handle (loader-PL1 #5)

A new op on a live ticket forgets the ticket's results and its handles count
from 0 again, but an earlier op's Completer held only (ticket, seq): if that op
ended while its service was Running and the new op issued the same seq, the
late completion was stored under the new op's handle, woke it, and the new
op's own completion was dropped (THE DESIGN 11.11 H2, 11.12).

Each ticket's results now live under an epoch minted fresh (never reused) by
the op's first stored result; a forget (a new op or tick on the ticket, or its
recycle) ends it. Every Completer carries its op's epoch, and a completion
whose epoch is not the ticket's current one is dropped and wakes nothing.
RED: a_late_completion_from_an_ended_op_never_lands_on_the_next_ops_handle,
proven red on Latchkey against the unfixed services.rs/worker.rs (test kept):
"a completion of an op that is over wakes nothing" (the late completion was
stored under the new op's handle and woke it); green with the fix.
… no instance published (loader-PL1 #6)

A PENDING open stored its half-open box in ptr, so is_open() was already true
while the open was in flight and refuse() admitted non-lifecycle ops into it.
If the resumed open answered FAULT, the SDK freed the box but judge returned
Crossed::host(Fault) before the (OPEN, _) arm that nulled ptr: ptr dangled and
is_open() stayed true, so a later close/tick/drive/cancel/retire handed the
plugin freed memory (THE DESIGN 11.13; Plugin::is_open: open answered READY).

The open's crossing is now armed with an OpenEnded guard that nulls ptr on
every exit but READY/PENDING, FAULT included (the plugin's answer or the
host's judgement of it). is_open() reads a separate opened flag set only by
READY (cleared by close), so a half-open box is not open: non-lifecycle ops
and a second open are refused while it is in flight. A half-open box is
crossed only by the cancel of its pended open and by its close (admitted by
the lifecycle exclusion only once the open is over), as before.
A box the plugin still holds is never leaked either: when the plugin answered
READY or PENDING but the host judged the open FAULT (a PENDING on a ticket-less
crossing, a mirror that disagrees, a kind check that fails), the box stays
half-open and the host sends it close at once (Instance::close_half_open, the
close a half-open box admits; the open's lifecycle exclusion is still held),
which nulls the pointer. Closing a half-open box frees it but does not mark the
instance closed for good: only an open instance is.
The plane door double whose open answers READY over the lifecycle structs
(red_a_plane_open_over_the_lifecycle_structs_publishes_no_snapshot_and_faults)
hands back a token, not a box; the host now closes what such an open leaves the
plugin holding, so the double states the close that goes with its token (it
takes it back, frees nothing) and the test asserts the host closed it once.
A pended open the host cancels (its deadline, or its client went away) never
answers, so the plugin keeps its half-open box and no caller will close an
instance that never opened: the worker's cancel now crosses close on that box
right after the open's cancel, once, inside the open's own lifecycle
exclusion; a later caller's close finds nothing and is refused (never a
second free).

RED: open_faults_on_its_resume::red_an_open_that_faults_on_its_resume_leaves_no_instance,
proven red on Latchkey against the unfixed plugin.rs (test kept): "an open
that FAULTed on its resume is not open"; green with the fix. Its tail also
holds the in-flight arm (an open in flight is not open; a tick is refused).
RED: open_left_live_is_closed::red_an_open_the_host_judged_fault_is_closed_never_leaked
(a counting plugin: opened minus closed is 0 after a host-judged FAULT, ticket-less
PENDING and ticketed READY with a disagreeing mirror), proven red on Latchkey
against the plugin.rs before the close ("the host closes the live box of a
PENDING it judged FAULT": left 1); green with it.
RED: open_left_live_is_closed::red_a_cancelled_pended_open_is_closed_once
(deadline and client-drop arms: opened minus closed is 0) and
open_left_live_is_closed::red_a_late_close_after_the_auto_close_is_refused_never_double_freed.
…handles (loader-PL1 #10, cleanup)

- services::UNIMPLEMENTED had no caller and its doc (a slot not served yet)
  contradicted the module's "every slot of the table is served"; the test
  double names busbar_contract::services::UNSERVED itself.
- ServiceStore::held has no production caller: test-only (cfg(test)).
- OutboundInstance::open had no caller; production opens through open_with.
- ticket::Completions/Redeem and Dispatcher::completions were a second, unused
  home for completion handles (the workers only forgot an always-empty map);
  deleted with their test, and the ticket/dispatch module docs now point at
  services::ServiceStore, the one home.
# Conflicts:
#	crates/plugin-loader/src/tests/host_services_tests.rs
@MattJackson
MattJackson enabled auto-merge October 8, 2026 02:46
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

promote into predev: BOARD @0134cc8d7: 0 failing test row(s), 11 DENY row(s)

DENY rows (11)

gate row detail
construction one-pick-site 3 production call site(s) of 'pick_among(' (ceiling 2): crates/busbar-kernel-egress/src/walk.rs:298; crates/busbar-llm/src/engine/exhaustion/fallback.rs:120; crates/busbar-llm/src/engine/pipeline.rs:8
kind-isolation kind-isolation:deps 3 finding(s), 94 shipped edge instance(s) over 31 class(es), 94 declaration(s); 57 '[[dep]]' row(s), 0 question(s): unlisted-dep-edge legacy -> plane busbar-llm -> busbar-plane-llm is a shipped edge w
kind-isolation kind-isolation:test-deps 3 finding(s), 35 test edge instance(s) over 21 class(es), 35 declaration(s); 20 '[[dep]]' row(s), 0 question(s): unlisted-dep-edge cleanliness -> legacy busbar-core-admin -> busbar-a2a is a test edge
kind-isolation kind-isolation:law0 18 finding(s) over 14 neutral crate(s): law0-rise busbar × auth 51 hit(s) against a ceiling of 46: this landing grew a neutral crate's instance vocabulary. Ceilings only fall (measured on predev f830f
kind-isolation-ship kind-isolation:deps 11 finding(s) over 94 shipped edge(s): ship-edge kernel -> hooks busbar-kernel -> busbar-hook-ranking is 'not-allowed': the architecture grants no kernel -> hooks edge, and the ship criterion is the a
kind-isolation-ship kind-isolation:test-deps 10 finding(s) over 35 test edge(s): ship-edge cleanliness -> export busbar-core-admin -> busbar-export-prometheus is 'not-allowed': the architecture grants no cleanliness -> export edge, and the ship
kind-isolation-ship kind-isolation:law0 18 finding(s) over 14 neutral crate(s): law0-rise busbar × auth 51 hit(s) against a ceiling of 46: this landing grew a neutral crate's instance vocabulary. Ceilings only fall (measured on predev f830f
kind-isolation-ship kind-isolation:faces 2 finding(s) over 40 crate(s): foreign-entry crates/busbar busbar is kind 'root' and implements 'Transport' 1 time(s) in shipped source — the entry face of kind 'transport'. A trait implementation is
kind-isolation-ship kind-isolation:legacy-drain 3 finding(s): transitional-live qa/kind-isolation.toml 'busbar-a2a -> busbar-core-admin' (legacy drain: the retiring A2A engine's tests drive the admin surface that drained into the cleanliness tier)
ship-ready ship-ready:ship-twin 'kind-isolation-ship' is not green: kind-isolation:deps (a dependency the architecture does not grant is still in the graph); kind-isolation:test-deps (a dependency the architecture does not grant is
structure-lint structure-lint:plane-dup:unledgered 22 finding(s): PLANE-DUPLICATE (module): 'config.rs' — a2a:crates/busbar-a2a/src/a2a/config.rs decisions:crates/busbar-plane-decisions/src/config.rs voice:crates/busbar-voice/src/config.rs (the ledger

Judged against base 9c0a39477: 0 new red, 0 worse, 5 standing (excused).

tests passed: 22808, failed: 0. Run: https://github.com/GetBusbar/busbar/actions/runs/38025247530 . Artifact verdict-0134cc8d7018c41f7bb15c028658d04f747f9c36 (failures.json, junit.xml, raw.log; 90 days).

@MattJackson MattJackson added fixing and removed fixing labels Oct 10, 2026
…add no "C" literal (law0 18 -> 19)

- dispatch/plugin.rs: the open-publishes-its-instance arm is an `if` over
  `s == slot::OPEN && matches!(outcome, Ready | Pending)` instead of a
  one-arm `match` with `_ => {}` (clippy::single_match, -D warnings: the
  gate:build:clippy and every gate:test:* row that runs clippy).
- tests/dispatch_tests.rs: the two restated doors' seven `extern "C"` fns
  (open_faults_on_its_resume, open_left_live_is_closed) are written through
  one `c_abi!` macro, and the panic_child comment says "C-ABI slot". The Law 0
  scan reads each "C" literal as busbar-secret-c's id, so the seven took
  busbar-plugin-loader x instance:secret from its ceiling 111 to 118 (the
  kind-isolation:law0 and kind-isolation-ship law0 rows, 18 -> 19 findings);
  the file now spells it twice, as at base.

Proved on Latchkey: cargo clippy -p busbar-plugin-loader --all-targets
--all-features -D warnings is clean; cargo xtask gate kind-isolation reports
law0 at 18 findings (base's standing ones), no plugin-loader instance:secret
row; cargo test -p busbar-plugin-loader dispatch_tests passes the new tests
(the 5 both-ways failures need the example cdylibs built first, which a
filtered run on the runner does not do).
@MattJackson
MattJackson added this pull request to the merge queue Oct 10, 2026
Merged via the queue into predev with commit 4f36b97 Oct 10, 2026
8 checks passed
@MattJackson
MattJackson deleted the loader-pl1-d branch October 10, 2026 14:42
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