Skip to content

decisions plane: the nanojev dialect (Q128 finding 3, row 128) - #807

Merged
MattJackson merged 9 commits into
predevfrom
lane-audit-decisions-nanojev
Oct 13, 2026
Merged

MattJackson merged 9 commits into
predevfrom
lane-audit-decisions-nanojev

Conversation

@MattJackson

Copy link
Copy Markdown
Collaborator

Stacked on the decisions-plane audit PR.

Adds the second dialect inside the decisions plane: two op classes, each claim published only when a model of that dialect is configured; a model's dialect is its protocol, else its provider's; an unknown dialect is refused at validate/open/refresh; a model of the wrong dialect gets that dialect's 404; a nanojev unit is billed by its execution states and an answer with no count fails loudly. Conformance rig gains six checks with red arms.

…ed (audit plane-decisions#1, #2)

THE DESIGN section 2, the decisions bullet: "a request routes by its model; one configured model
and none named is the default (byte-identical); more than one and none named is 400; an unknown
model is 404. `upstream_model` rewrites only the top-level model value, by span splice, when it is
set and differs; otherwise the body passes through." DECISIONS D8b (BUSBAR-1.6.0.md:4798, :4802)
lifts the exactly-one-model mount and adds /model to REQUEST_PTRS.

plane-decisions#1: the snapshot claimed POST /v1/systemone only when exactly one model was
configured, and arrive routed every request over that one model whatever its body named. Now the
claim is published whenever at least one model is configured (none: nothing is claimed, and the
kernel's unclaimed-route 404 stands byte for byte), and arrive reads the top-level `model`
(driven::route_model): the named model routes ROUTE_DIRECT; one configured and none named is the
default; several and none named is a refused arrival at 400; a name no model has is 404; a `model`
that is not a string is 400. The refusals render in jev's error shape through the refusal slot.
The door keeps every configured model of the latest generation (name -> upstream_model) in place
of the single routed name.

plane-decisions#2: `decisions.models.<m>.upstream_model` was read nowhere. The routed model's
upstream_model is kept on the unit at arrive, and the caller's body bound for the far end has its
top-level `model` value alone replaced (driven::spliced) when the two differ; every other byte is
the caller's.

The jev rig gains a second boot with two models (one with upstream_model) and three checks:
models.unnamed-400, models.unknown-404, models.upstream-model; the plane's conformance inputs
expect the claim on the two-model refresh.

RED: tests/door.rs every_generation_with_a_model_claims_systemone,
a_request_routes_by_its_model, upstream_model_is_spliced_into_the_top_level_model (over the door's
ABI); src/tests/driven.rs one_or_more_models_mount_the_claim.
…in family decision (audit plane-decisions#4, #5)

THE DESIGN section 7, owner money rulings 2026-09-28: "The decisions plane bills one `decision`
per successful, settled answer from every provider; its card prices `decision`, `input_tokens` and
`output_tokens` (family `decision`, all three required, 0 = free); the hosted provider keeps
1.5.5's `/usage/units` as the decision count (DECISIONS D9, 2026-09-30)." DECISIONS Q1-5
(BUSBAR-1.6.0.md:4780): the usage pointers /usage/units, /usage/input_tokens and
/usage/output_tokens are dialect data. Finding 395 is kept (:4690): a usage member present but not
a whole count is located, never dropped.

plane-decisions#4: the decision count was read with no regard to the status (a 500 carrying
/usage/units billed decisions), a success with no count billed no decision at all, and a count
that was negative, fractional, a string or past i64::MAX was dropped silently. Now one success
rule (FarEndReading::success: a 2xx status and no /error member, a null one being none) gates every
count: a non-success bills nothing; a success bills its whole /usage/units, or one decision when it
reports none, and its request fee; a usage member that is present but not a whole count fails the
far end's last piece (Outcome::Failed, the plane fault the kernel ends the unit on) naming the
member, never a silent 0.

plane-decisions#5: the tail declared `decision` and the fee unit only. It now declares
`input_tokens` and `output_tokens` in family `decision`, appended after the fee unit (the fee
keeps index 1), and a success reports each where its answer carries a whole count. The jev rig's
cards price both at 0, and the docs' declared-class list names them.

RED: tests/door.rs a_success_with_no_count_bills_one_decision, a_non_success_bills_nothing,
a_success_with_an_unreadable_count_fails_loudly,
the_tokens_a_success_reports_are_billed_in_family_decision (over the door's ABI);
src/tests/driven.rs a_success_bills_one_decision_or_the_count_it_reports,
a_non_success_bills_nothing, a_usage_member_that_is_not_a_whole_count_fails_loudly,
a_success_bills_the_tokens_it_reports, the_tail_names_the_decision_class_at_its_index.
…icted, and an answer is read as it passes (audit plane-decisions#6, #8)

THE DESIGN section 11.2 (the shared mechanism): "memory a plugin returns is plugin-owned and valid
until that plugin's next refresh generation; no allocation and no blocking on the hot path". And
section 7: a settled success's count is billed, so a live unit's reading must not be lost.

plane-decisions#6: arrive kept state for every claimed unit, but only a unit's last far-end piece
removed it: a refused unit (rate limit, budget, grant) or a cancelled one stayed until eviction,
and past 4096 the smallest key was popped, which in steady state was a live unit (its ATTEMPT or
its reading lost, so its body was held or its count unbilled). `cancel` dropped nothing and
answered CANCEL_ABORTED even after far-end bytes were relayed. Now `refusal` drops its unit
(RefusalIn.unit); each piece records its ticket and `cancel` drops the unit on the cancelled
ticket, answering CANCEL_ABORTED before the far end answered and CANCEL_OK_PARTIAL after; at
MAX_UNITS a new arrival is refused at 503 about the entry it routed over (the ABI's refused-arrival
rule 6, before anything is charged) and no live unit is dropped. A unit that arrived and never
crossed a piece while MAX_UNITS arrivals followed is reclaimed, so an arrival the kernel never
started cannot leave the instance refusing every arrival for good.

plane-decisions#8: every far-end piece was appended to a growing whole-answer buffer (no bound)
and copied again into the unit's owed bytes before it was written; the caller's fields were a
vector of vectors per arrival. Now the answer is read as it passes (FarEndReading scans the JSON
structure in fixed space for /error and the three /usage counts, wherever the pieces split it),
a piece is written straight into the host's reply buffer and only what does not fit is kept for
the `more` re-calls, and the caller's relayed fields are one buffer sized once per unit. Nothing
caps the answer's size (#41: never a size-based refusal).

RED: tests/door.rs a_refused_unit_is_dropped_and_a_live_unit_kept,
a_cancelled_unit_is_dropped_and_a_live_unit_kept,
a_unit_cancelled_after_its_far_end_answered_is_cut_partway,
past_the_cap_an_arrival_is_refused_and_no_live_unit_dropped (over the door's ABI);
tests/door_alloc.rs relaying_an_answer_piece_by_piece_allocates_nothing; src/tests/driven.rs
the_reading_is_the_pointers_reading_wherever_the_pieces_split.
…execution.states (audit plane-decisions#3)

THE DESIGN section 2, the decisions bullet: "a second dialect exists only where a provider's
request spine really differs (NanoJev is the one, dialect `nanojev`: `/api/evaluate` is its second
exact claim; a model's dialect is its override or its provider's protocol; a model of the wrong
dialect gets that dialect's existing unknown-model refusal; it meters the upstream's own billing
unit, counted from the answer already read (`execution.states`; an answer with no count refuses
loudly; `$`, alone), with no extra egress". DECISIONS (BUSBAR-1.6.0.md:4960): "Plane gets its
referenced providers' dialect fields at open (PlaneOpenIn list ...); the plane resolves
model->dialect and selects itself; no kernel dialect check." :4987: "NanoJev unreadable count =
same outcome as item 395 /usage/units".

plane-decisions#3: the plane spoke `jev` alone, claimed POST /v1/systemone alone, and refused any
other protocol. Now the tail states two dialects (`jev`, `nanojev`, each reached as a bearer), two
op classes (`systemone`, `evaluate`) and two exact claims; a generation publishes each dialect's
claim when it configures a model of that dialect, wearing that dialect for a refusal before
arrive. Each model's dialect is its own `protocol`, else its provider's as the host states it at
open (PlaneOpenIn::providers, kept for every refresh), `jev` for a provider the host states none
for; a dialect the plane does not speak fails closed at validate, open and refresh, naming the
two it does. A request routes among the models of its claim's dialect, so a model of the other
dialect is that dialect's unknown model (404), and one model of the dialect is its default. A
nanojev unit is sent to POST /api/evaluate, and its answer is read by its dialect's count:
`/execution/states` is the decision count, and a success with no count, or one that is not a whole
count, fails the unit loudly; jev's /usage members are not read on it. The PII pointer test reads
each declared pointer by its segments: `/execution/states` passes through no `state` member.

The jev rig gains a third boot (a nanojev provider and model beside the jev one) and three checks:
nanojev.served, nanojev.wrong-dialect-404, nanojev.no-count-refused; the extra boots share one leg
helper; the registry plan names what the rig serves (registry.toml and manifest.json). The binary's
dialect probe in tests/cli_validate.rs reads the two dialects the decisions plane now states.

RED: tests/nanojev.rs evaluate_is_claimed_with_a_nanojev_model,
a_model_of_the_wrong_dialect_is_an_unknown_model,
a_nanojev_unit_is_sent_to_evaluate_and_bills_its_states, an_unspoken_protocol_is_refused_at_validate
(over the door's ABI); src/tests/driven.rs a_nanojev_answer_bills_its_execution_states,
a_model_of_the_other_dialect_is_this_dialects_unknown_model; src/tests/plane_door.rs
each_dialects_claim_is_published_with_a_model_of_it,
a_models_dialect_is_its_override_or_its_providers_protocol; crates/busbar/tests/cli_validate.rs
validate_ok_on_a_decisions_config_in_the_second_dialect (the binary).
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

promote into lane-audit-decisions: NO VERDICT @ed735b21d

The hop ended without writing a verdict (runner lost, timeout, cancel, or it died before the engine judged): preflight: failure at step Run act=(); publish: runner lost at step Run $RUNNER_TEMP/busbar-release ci fallback, Post Run actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1.

No failing-test list exists for this run. Run: https://github.com/GetBusbar/busbar/actions/runs/38349954561 . Re-run the hop, or read the job's step list in the run page.

MattJackson added a commit that referenced this pull request Oct 12, 2026
…cked lane PR (base lane-*) no longer starts the Actions preflight (#807 paid one on 2026-10-12)
…ate, not an atomic the plane holds

busbar-plane-decisions::purity the_plane_holds_no_interior_state failed on the merged tree: 4809d85
(#806) gave DecisionsDoor an `arrivals: AtomicU64` (plane_door.rs:47 import, :427 field, :496 init,
:631 fetch_add) to number each kept unit (Unit::seq) for the stale-unit reclaim. An atomic is interior
state the plane holds of its own, which the purity cell forbids by name.

BUSBAR-1.6.0.md l.345-346 (THE DESIGN, plugins): "A plugin holds no process-global state: what it keeps
is per-instance". The SDK's Keyed is that per-instance state, locked by the SDK for a plugin that holds
no lock of its own (busbar-contract abi/sdk/publish.rs, "PER-INSTANCE KEYED STATE"); the door already
keeps its units and models there, and the mcp plane keeps its one driver value as Keyed<(), _>
(tool_door.rs:185). The count moves into Keyed<(), u64>, taken and advanced under the SDK's lock
(wrapping, as fetch_add did). No behaviour changes: each arrival still gets the next number before its
unit is kept, and reclaim_stale reads it as before. The purity cell is unchanged.
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