Skip to content

Onboard OpenRouter Nemotron 3 Ultra (free) as a quota-leased harness backend - #13357

Queued
gunbai-bot[bot] wants to merge 19 commits into
mainfrom
session/neat-lark-813
Queued

gunbai-bot[bot] wants to merge 19 commits into
mainfrom
session/neat-lark-813

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

What this does

Adds OpenRouter's free nvidia/nemotron-3-ultra-550b-a55b:free endpoint as a backend for the gunbc agentic-coding harness. Every request is rate-limited through the existing fabric quota lease. Context: personal agentic coding for free tokens. It is evaluation-only and never offered to customers.

Facts were read live on 2026-10-05 from openrouter.ai/api/v1/models/nvidia/nemotron-3-ultra-550b-a55b:free/endpoints, GET /api/v1/models, OpenRouter's limits and reasoning-tokens docs, the NVIDIA model card, and the NVIDIA API Trial Terms PDF (v. September 19, 2025). Each fact cites its source in the module that owns it.

Shape, each fact in its own home

extdeps: one module per independently governed upstream (DESIGN §3)

  • extdeps.openrouter.openrouter: the router itself. Chat-completions and key-read URLs (HTTPS only), the bearer header line, and the UpstreamRateLimit rows: openrouter_free_models_per_minute (20/min) and openrouter_free_models_per_day(credits) (50 or 1000/day).
    • The daily tier is not a literal. It comes from the typed OpenRouterCreditsPurchased fact, which openrouter_credits_from_daily_limit derives from the key read's free_model_daily_requests.limit. A limit that matches neither published tier is refused.
    • Typed 402/429 decode: closed enums OpenRouterLimitSource and OpenRouterLimitReason. An unpublished spelling refuses instead of being mapped to the nearest known value. remedy_hint is carried as log-only text.
    • Key read with OpenRouterKeySpendLimit (uncapped / capped at zero / capped above zero).
    • OpenRouter's reasoning-effort vocabulary, plus openrouter_effort_admitted against a listing's supported set.
  • extdeps.openrouter.nvidia_nemotron_3_ultra_free: OpenRouter's listing of the model.
    • Model id, 1,000,000-token window, 65,536 max completion tokens, price 0.
    • supported_efforts = [high, medium] and reasoning not mandatory, both from /api/v1/models.
    • Terms: points at the NVIDIA trial terms.
    • Which Nemotron mode each effort reaches is not published, so it is not asserted (§4d). Only the published effort order is used.
  • extdeps.nvidia.nemotron_3_ultra: the model card's facts (the anchor and the </think> closer). The card's chat-template reasoning modes are deliberately not modelled: nothing on this route could send them, so the declarations would have no consumer.
  • extdeps.nvidia.api_trial_terms: the terms as a typed record, not prose. NvidiaApiTrialObligation has one arm per obligation, each citing its section: 1.2/1.4 trial use only, no production; 2.6(a)/4.3 no confidential or personal data; 3.3(iv) content may be used to improve NVIDIA products; 4.2 no redistribution; 4.12 no competing-product development. Each hosted binding carries these terms, and they are rendered in the access wire.

Checked pool transitions (gunbc.fabric_event_log fabric_pool_transition). Quota settlement and upstream observation no longer use the unchecked fabric_pool_event_append. Each one:

  • reads and folds the partition;
  • applies the transition with the replay's own product.capacity.pool_events pool_apply_payload, newly factored out of pool_apply_event;
  • compare-and-set appends only a transition that advances the pool, retrying when the head has moved.

A settlement whose lease lapsed at rollover is therefore refused typed and never written. Previously it was written, reported as settled, and made the whole partition unfoldable. product.capacity.pool observe_upstream_remaining now keys its hold by the reading's identity (the event id at replay, the decided-against head before append) instead of its second, so two same-second readings no longer collide. QuotaLeased carries its UpstreamRateLimit, so settlement folds against the pool it was granted from; gunbc.roadmap.roadmap_publish_observe gets the checked settlement too.

Transport. New extdeps.http.client PostJsonFromFileWithHeaderFile. The Authorization header is passed with -H @{header_file}, exactly as in GetFollowRedirectsBoundedWithHeaderFile, so the bearer is never an argv word (gunbc.credential_argv_exposure). --fail-with-body keeps the error body, which is where OpenRouter's typed refusal lives, and -D dumps the response headers to a caller-owned file because a refusal's retry hints are headers.

Harness (load-bearing).

  • gunbc.harness.harness_reasoning_wire
    • New HarnessServingUnit arm NemotronUltraFreeOnOpenRouter, threaded through every seam function.
    • harness_unit_placement is a closed choice: PlacedOnFleetSeat or LeasedFromHostedQuota.
    • harness_openrouter_reasoning_kwargs maps off to reasoning.enabled=false (only if the listing does not make reasoning mandatory), standard to effort: medium, and maximum to effort: high. Each is checked against the listing's supported_efforts; anything else is refused.
  • gunbc.harness.harness_hosted_route (new)
    • Route table joined from the extdeps rows.
    • The default reasoning level is selected, not hard-coded. harness_hosted_level_selection goes through std.decision select_realization over the three levels.
      • Axes: depth (from the listing's published descending effort order), money per request and quota per request (both equal across levels, because price is 0 and the limit counts requests), and admissibility.
      • Hard constraint: admissibility, meaning the seam can express the level and max_tokens is within the completion ceiling.
      • Latency is not a funded axis, and that is the stated reason the result is the deepest admitted level. The day a latency budget binds, funding it answers SelectionNeedsEvidence.
    • Credential: fetched through fetch_secret_ref_credential_with_token and written as a 0600 header file in a fresh mktemp -d directory. Liveness is read with GET /api/v1/key (ProbeInert), gated by gunbc.auth.materialized_secret with_materialized_secret.
    • The bind refuses a key that can spend money. The key's credit limit must read back as 0 (an operator guard). Running a "free" route on a key that could spend would be §5 externalized degradation.
    • Each request is charged to both pools before it is sent.
      • Each pool is leased for the rest of its own current window, using gunbc.fabric_quota QuotaTermToWindowEnd, read off the same clock reading the lease is stamped with. The term therefore always fits a lapsing window.
      • Both leases are settled at 1 before the POST, so the charge does not depend on how long the response takes. A request whose fate is unknown (crash, or a transport failure mid-flight) stays charged.
      • Pure hosted_round_decision: if the day pool refuses after the minute pool leased, the minute lease is returned at 0. If a charge fails to record, the request is not sent.
    • The local quota is a close, conservative pre-check, and OpenRouter's 429 is the typed backstop.
      • This route deliberately revises the 2026-09-06 ruling that a caller refuses before the upstream would have answered 429 (gunbc.fabric_quota). That is operator decision B on escalation msg_46a417a3: the pre-check makes an over-spend rare, and the 429 covers the boundary cases it cannot.
      • Two paths can still under-count, both found in side-chat review 5422349016. They are accepted, not closed:
        1. A send that crosses a window is released without charging its arrival window. A send charged and admitted at T+50, paused until it arrives at T+61, then returned and released at T+62 before any other admission in that minute, leaves its arrival-minute liability unrecorded. Twenty later admissions plus that send can reach 21 upstream arrivals in the minute.
        2. The in-flight snapshot and window used to size a charge are not bound to the eventual quota admission. Callers that read an empty in-flight partition and then resume in a later window each charge 1, while a send registered in between lands in that same window.
      • Both are covered by the 429 backstop. The upstream's 429 for an over-spend is decoded to OpenRouterRateLimitRefusal, with its Retry-After and X-RateLimit-* hints, and ends the turn as TurnHostedRateLimited. It is never retried. Retry-After is read as seconds only when it is all digits (otherwise carried as text), and X-RateLimit-Reset is carried verbatim because OpenRouter does not document its unit (§4d).
      • What is deliberately absent: an admission lock, charging every window a send might span, and a send-deadline admission check at the transport boundary. Each existed only to make the local count exact.
      • The in-flight seats stay because they still earn their keep. An admitted send holds a seat in a per-credential in-flight partition (gunbc.harness.harness_seat, the existing harness_seat_pool_root shape) until its transport returns. Each later round charges its pools for its own send plus every seat still held from before that window began (hosted_inflight_carried), so a paused or crashed sender that is still held is counted. They narrow the window for a miss; they do not close it.
      • Stated, not engineered away:
        • Two rounds in one window both count the same carried seat, which is conservative double-charging.
        • A seat whose holder died charges every later window. The quota-full refusal names each held seat, its grant, and the existing harness_release_cli invocation that frees it.
    • The day pool starts from what the upstream says remains, not from the ceiling. At bind, free_model_daily_requests.remaining is recorded on the day partition as the existing PoolUpstreamObserved event (gunbc.fabric_quota fabric_quota_observe_upstream). The fold's observe_upstream_remaining then holds the shortfall: a reading of 0 admits nothing, a partial reading admits exactly that many, and a later, larger reading gives nothing back. If the reading cannot be recorded, the bind refuses.
  • gunbc.harness.harness_seat
    • New binding arm HarnessHostedBound. It carries the selected level and the hosted access in place of a vLLM launch.
    • New harness_bind_hosted entry.
    • harness_bind_seat refuses a hosted exact unit. AnyAdmittedModel is always a fleet seat: an unnamed requirement never routes a turn onto an upstream whose trial terms the caller didn't choose.
    • Release arm HarnessHostedCredentialRemoved removes the header directory.
  • gunbc.harness.harness_turn
    • HarnessTurnConfig.backend_access is either BackendAdmittedBySeat or BackendAdmittedByHostedQuota.
    • Each round leases before the POST with the charge recorded before the POST. A local refusal ends the turn typed as TurnHostedQuotaFull or TurnHostedQuotaUnleasable. An upstream 429 that the pre-check admitted ends it as TurnHostedRateLimited, carrying the upstream's hints, and is never retried.
    • The upstream's error body is decoded to OpenRouter's typed error, so a 402 from openrouter_key_limit reads as "a priced model was requested", which is never retried.
  • gunbc.harness.harness_cli
    • Every binding match now goes through harness_binding_answer and gets one HarnessBoundBackend (url, model, unit, level, access), so the hosted arm does not duplicate every entry body.
    • New entry harness_hosted_probe_cli(worktree, timeout_program, request_scratch_path, events_path).
    • Belt roles still bind AnyAdmittedModel. Letting belt dispatch select the hosted unit is an operator policy decision and is left as a declared frontier.

Secret and its grant (leasing/grants domain, §3b). gunbc.secret_provision openrouter_free_tier_key_secret_ref points at gunbai-secrets/openrouter-free-tier-api-key-harness (alias latest; the fetch proves which version it resolved). The operator created this secret.

Reading it on every bind is a recurring automated effect. So it rides a workload accessor cell, not an operator session:

  • New row openrouter_free_tier_key_accessor_row in gunbc.auth.fleet_secret_accessor_roster. It is converged by that roster's existing approval-gated converge.
  • New row in gunbc.auth.privileged_effect_census classifying the site: gunbc.harness.harness_hosted_route hosted_secret_text, recurring_credential_read, RealizedRunSelected.

Until the grant converges, the hosted bind refuses with a typed cause naming the secret. Nothing falls back to an operator token.

Witnesses

test.claim.openrouter_hosted_route_witness_test. Each refusal arm has a RED, including a lease held for the response deadline refused by the real minute pool as LeaseCrossesLapse, and an exhausted upstream day leaving a fresh day pool zero headroom; there is a positive control for each family, including the production charge admitted by both real pools one second into and one second before the end of their windows, a settlement just after rollover refused before append (the same settlement appended blind is shown to make the partition unfoldable), two decreasing same-second readings folding to the lower, a send paused across the rollover making the next window refuse at 19 already charged (and admit when nothing is carried), a seat released after a late response carrying nothing forward, the release hint naming a held seat and its grant, the spendable-key wall asked at hosted_access_from_key itself (an uncapped key, a positive-cap key and an unpublished tier each build no binding; only a zero-credit key on a published tier does), the production charge run through the real fabric_quota_lease_for for an undeclared host, and the 429 backstop: a 429 body plus its header dump decodes to the typed refusal carrying Retry-After, the reset value and the remaining count; a Retry-After that is not seconds and a missing hint are stated rather than guessed; only a 429 is a rate-limit refusal; and the turn ends on it as a terminal refusal outcome that names the hint and no retry; and there is one inhabitance claim on the real path. In that claim the real unit's real route is quota-leased, HTTPS, and names the listing's id; the real selection picks maximum for the real max_tokens; and that renders effort: high.

Post-merge steps (not merge blockers)

  1. Converge the accessor grant from main through the roster's approval loop (gunbc.auth.fleet_secret_accessor_roster fleet_accessor_grants_request_approval, then fleet_accessor_grants_converge_via_approval). The parent lane is arranging the operator approval.

  2. Live exercise. On a host whose harness run carries workload identity (WIF_ACCESS_TOKEN) and has a fabric event-log store for its short hostname:

    gunbc run --source-root dag --source-root src/v2 \
      --entry dag/gunbc/harness/harness_cli.dag --function harness_hosted_probe_cli \
      --arg worktree=<repo checkout> --arg timeout_program=<GNU timeout path> \
      --arg request_scratch_path=<attempt dir>/request.json --arg events_path=<attempt dir>/events.jsonl
    

    What a successful run shows:

    • The key read passes: credit limit 0 and a 50/1000 daily tier.
    • The turn runs at the selected level (effort: high).
    • Each round leases and settles the 20/min and day pools.
    • The exit is a provider stop, and the release reports "hosted credential removed".

    The events file and its .wire/ directory are the record. The same run grounds the one §4d bet left open: whether medium reaches the card's medium mode, which its reasoning-token counts can show.

🤖 Generated with Claude Code

Declared frontier: the lease producer's success arm is not witnessed by execution here

The producer's success arm (a seat acquired and settled on a real event-log store) needs a store, and the floor refuses a new real-execution witness (v2.workflow.floor_changed_witness). Its pieces are witnessed at their own interfaces: the term derivation and admission through the production pool_acquire, and the checked settlement through the replay's own pool_apply_payload. The production charge is executed through its real producer's refusal arm. The joined success route runs in the post-merge live exercise. Trigger to close it: a hermetic event-log store route, or a floor that admits a new real-execution witness.

Brian Searls and others added 6 commits October 5, 2026 04:43
…ss backend

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ugh admitted_model

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the site in the privileged-effect census

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…13004) beside the OpenRouter row

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eview 76210)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 232c3bc (review 76210, flat-scalar money field). Both places are now typed with the existing std.measure money type:

  • extdeps.openrouter.nvidia_nemotron_3_ultra_free nemotron_ultra_free_price_per_token is MoneyAmountMicro (money_amount_micro(count: 0)).
  • gunbc.harness.harness_hosted_route HarnessHostedRoute.price_per_token is MoneyAmountMicro.

The money axis reading in the level selection goes through money_amount_micro_count. No bare-Int money remains on the path.

Local evidence at this head:

  • test.claim.openrouter_hosted_route_witness_test: 17/17 PASS, max 10.2k eval steps.
  • test.claim.gcp_secret_access_witness_test the_roster_is_the_single_authority_for_the_spark_and_mtcollins1_grants: PASS. It was red on main since alloc unit 1: auth + protected state (browser-bound Google login, cookie transport, owner admission, protected fabric state) #13004 added fabric_state_key_accessor_row without naming it in named_accessor_rows; this PR names both that row and the new OpenRouter row.
  • Mutation control in a scratch worktree: forcing hosted_round_decision's day-full arm to RoundBothLeased, and forcing harness_unit_placement for the hosted unit to PlacedOnFleetSeat, turns the day-full RED and the real-route inhabitance claim red, while the untouched both-leased control stays green.

…kenCount (review 76237)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 26f2c3f (review 76237). Both unit-modeling findings:

  • Deadline. hosted_key_read_deadline is now a std.measure Second (second(count: 20)). It is converted to wire text at the GetFollowRedirectsBoundedWithHeaderFile call, exactly the way the chat POST converts config.request_deadline. The raw "20" string is gone.
  • Token counts. Every new hosted-route signature now takes max_tokens: TokenCount: hosted_level_admitted, hosted_level_entry, harness_hosted_level_field, harness_hosted_level_selection, harness_hosted_level_choice, hosted_bind_with_header, harness_hosted_bind and gunbc.harness.harness_seat harness_bind_hosted. Admission compares the two TokenCounts with token_count_value, so both sides now use the same carrier.
  • The value comes from a new typed row, gunbc.harness.harness_cli harness_default_max_token_count: TokenCount. The existing harness_default_max_tokens: Int is now derived from it rather than standing beside it, so there is still one authority for the figure. That Int feeds the pre-existing HarnessTurnConfig.max_tokens: Int, which this PR does not widen.

Local evidence at this head: test.claim.openrouter_hosted_route_witness_test 17/17 PASS, and the roster identity join PASS.

Brian Searls and others added 2 commits October 5, 2026 18:41
…w-end terms; seed the day pool from the upstream's remaining

P1: the response deadline (2348 s) was the lease term for both pools, and a lapsing 60 s window refuses
any lease that outlives it (LeaseCrossesLapse), so no request could ever be sent. Each pool is now
leased to the end of its own window (gunbc.fabric_quota QuotaTermToWindowEnd, read off the same clock
reading) and settled at one before the POST, so the charge no longer depends on the response lifetime;
a request whose fate is unknown stays charged.

P2: the day pool started from the tier ceiling and ignored free_model_daily_requests.remaining. The
bind now records that reading on the day partition as the existing PoolUpstreamObserved event
(gunbc.fabric_quota fabric_quota_observe_upstream), so observe_upstream_remaining holds the shortfall.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…carry the charge's deadline to a send admission at the transport boundary

P1: settlement and upstream observation went through the unchecked fabric_pool_event_append, so a
settle whose lease lapsed at rollover, or two same-second readings with one hold reference, were
appended and reported as success while making the partition unfoldable. New gunbc.fabric_event_log
fabric_pool_transition folds, applies the transition with the replay's own pool_apply_payload, and
compare-and-set appends only an advancing transition. Observation holds are keyed by the reading's
event identity, not its second.

P2: the hosted round now prepares the request before charging, the charge carries the earlier of its
two leases' window ends, and the send is admitted against that deadline (plus a connect allowance the
transport enforces) immediately before the POST; a lapsed admission refuses the send and keeps the charge.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

CI failure at 747619a is the required rust-unit-tests lane, and it is not a test failure. The step Run the v1 unit tests hit its 40-minute timeout ("The action 'Run the v1 unit tests' has timed out after 40 minutes"). Every test line before the cutoff is ok, and there is no FAILED or panicked anywhere in the log.

It is not specific to this PR. The same lane timed out the same way, at roughly 40 minutes, on four other PR heads in the preceding two hours, on four different hosts:

I read both quoted logs and they end in the identical timeout line. This diff also touches no Rust and no test harness; it is .dag only.

So there is nothing on this branch to fix. I'll let the lane re-run once its timeout or population is addressed upstream, rather than pushing a no-op to retrigger it.

— sent from neat-lark-813

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NO-LAND at 747619a: the prior P1 ledger findings are addressed; one P2 send-window finding remains.

Closed: fabric_pool_transition reads/folds the partition, runs pool_apply_payload before event_log_append, writes nothing for PoolRefused, and re-reads/re-decides on a moved head. Both quota settlement and upstream observation use it, with the lease carrying the limit used to reconstruct its pool. Upstream observation holds use reading identity instead of epoch-second identity. The rollover and same-second fold controls cover the prior semantic counterexamples. Moving request preparation before charging and retaining the earlier window end are also real improvements.

[P2] A connect timeout is not enforcement of send_by. In harness_hosted_round_post, harness_hosted_send_admission returns fieldless HostedSendAdmitted, then harness_send_round/harness_post_json invoke PostJsonFromFileWithHeaderFile with connect_seconds=5 and the long request deadline. The transport receives no absolute send_by. curl's connect timeout ends at connection establishment (DNS and TCP/TLS/QUIC handshakes); it neither bounds application-data transmission after the handshake nor fences a caller paused after the admission check.

Independent EXECUTED transport control (not the gunbc emitter, witness suite, or a live OpenRouter request): real curl 8.10.1 to a local TLS endpoint, --connect-timeout 5 and --max-time 2348, a prepared regular request file and dummy bearer header file. The admission predicate was true with send_by about 5.984 seconds ahead. A test-only shim injected an 8-second scheduling pause immediately before the first TLS application write of the POST headers. TLS completed at +0.009 seconds; the server received the FIRST request byte at +8.009 seconds, after send_by. curl exited 0. Positive control without the send pause, but with an 8-second response delay, sent within its window and also exited 0.

This is stronger than the source's stated residual of headers still in flight: no request byte had been sent before the deadline. The existing tests supply time to the admission helper; they do not delay transmission after that helper succeeds.

Required: retain/enforce the absolute send deadline in the actual sending operation, including after connection establishment, or keep conservative pending-send accounting that survives the relevant rollover. A local write deadline alone is not proof of upstream receipt time; uncertain arrival still needs covered accounting. Keep response waiting separate. Increasing the fixed allowance does not repair this. Add a control that pauses after successful admission/before the first request write and verifies no uncovered next-window send, alongside the existing long-response positive control.

CI is a separate gate and is not waived. I did not independently run the gunbc witness suite.

…he window they may land in

curl's connect deadline does not bound when the first request byte leaves, and a process can pause between
admission and write (executed: first byte at +8.0 s against a +5.98 s send_by, exit 0). An admitted send now
also holds a seat in a per-credential in-flight partition (gunbc.harness.harness_seat, the existing
harness_seat_pool_root shape: no replenishment, quiescence-required) until its transport returns. Each round
charges its minute and day pools for its own send plus every seat still held from before that window began
(hosted_inflight_carried). Two rounds in one window both count a carried seat (conservative, stated). A seat
whose holder died charges every later window; the quota-full refusal names each held seat, its grant and the
existing harness_release_cli invocation that frees it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 6582f88 (review 5422195181: an admitted send was bounded only by --connect-timeout). I took the conservative in-flight accounting route rather than trying to bound the sender, because curl cannot bound when the first request byte leaves.

What changed:

  • In-flight seats. An admitted send holds a seat in a per-credential in-flight partition until its transport returns. The partition is gunbc.harness.harness_seat hosted_inflight_partition, using the existing harness_seat_pool_root shape: no replenishment, quiescence-required, so a held seat charges until it is released and never by expiry.
  • Carried charge. Every round charges its minute and day pools for its own send plus the seats still held from before that window began (hosted_inflight_carried). A send paused across the rollover is therefore covered in whatever later window it may land in.
  • Release. The seat is released when the transport returns, with any outcome. A release that fails is a turn.inflight_release_unrecorded event naming the seat.
  • Admission check. The send_by admission check stays as a cheap early refusal; it no longer carries correctness.
  • Stated conservatism:
    • Two rounds in one window both count a carried seat, so a carried send can be charged twice.
    • A seat held by a dead process charges every later window. The quota-full refusal names each held seat, its grant and the harness_release_cli invocation that frees it, which is the existing release path.

Controls (local claim_batch, 28/28 PASS, max 32k eval steps):

  • a_send_paused_across_the_rollover_is_charged_in_the_next_window: a send admitted at T+58 is still held at T+61. With 19 already charged in the new minute, the round must cover 2 and the real minute pool_acquire refuses. The same round with nothing carried is admitted.
  • a_send_released_after_a_late_response_carries_nothing_forward: a send made in its window and released at T+300 carries 0 into later windows.
  • a_held_inflight_seat_is_named_with_its_release_in_the_refusal_hint: the hint names the seat reference, its admitting grant, the partition and harness_release_cli.

— sent from neat-lark-813

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NO-LAND at 6582f88. Re-review against 5422195181. Pending-send accounting is an appropriate repair direction; I am not requesting another curl deadline. The prior checked-transition/replay fixes remain accepted. Two under-accounting paths remain in the new integration:

[P2] Releasing a cross-window send erases its arrival-window liability without recording that window's consumption.
Locations: dag/gunbc/harness/harness_seat.dag hosted_inflight_held / hosted_inflight_carried / harness_hosted_inflight_release; dag/gunbc/harness/harness_turn.dag harness_hosted_round_charged_post.
The carried projection explicitly excludes Released entries. The successful transport-return path releases the in-flight seat without charging any additional minute/day window. Thus a send charged and admitted at T+50 (including the early check 50+5<60), paused until it arrives at T+61, and returned/released at T+62 disappears before the first fresh N+1 admission. Its original minute charge belongs to N. No other admission occurred while it was held in N+1, so no carry charge was ever recorded for N+1. Twenty subsequent normal admissions at T+63..T+82 can each charge one and send: 20 locally charged requests but 21 possible upstream arrivals in the minute. This needs neither a crash nor an unsuccessful response. The seat ceiling does not prevent it; peak occupancy is one.
Required: preserve the completed send's possible expenditure in every still-relevant window, rather than treating concurrency release as quota refund. A released seat's acquisition-to-confirmed-completion interval, or a committed consumption transfer before liability is removed, must still cover the arrival window. An unknown-fate transport result must not silently become confirmed completion.
Control: acquire/admit in N; delay actual send into N+1; receive a successful response and release BEFORE any new N+1 admission; then admit 19 normal requests and verify a twentieth new request refuses. Repeat across the daily boundary. The submitted late-response positive control only shows that Released entries no longer count; it does not establish that their arrival window was charged.

[P2] The in-flight snapshot and window used to size the charge are not bound to the eventual quota admission.
Locations: harness_turn.dag harness_hosted_round_post; fabric/fabric_quota.dag fabric_quota_lease_for.
harness_hosted_round_post retains pool p from a partition read, discards generation, computes carried counts, and passes bare Nats into quota leasing. fabric_quota_lease_for reads its own later clock and admits against its own current window. Neither the quota CAS nor the later in-flight seat acquire revalidates p or the windows used to compute the amounts.
Concrete schedule: twenty callers read an empty in-flight partition at T+10 and pause. A registers a seat and passes send admission at T+50, then pauses before transmission. The twenty callers resume sequentially at T+61..T+80; their clocks/windows are current but their retained p is empty, so each charges one, sends, and releases. A resumes and arrives at T+90. All twenty new quota admissions fit; peak in-flight occupancy is only two; the minute can receive 21 requests. Separately, even a snapshot containing A can undercount when carried=0 is computed in N and quota leasing resumes in N+1.
Required: make exposure observation, window selection, charge sizing, and publication of a new possible sender one coherent admission. Validate/retry against the relevant in-flight version AND the actual quota windows; independent successful CAS operations on separate partitions do not establish their joint invariant. The integration control must pause at these production effect boundaries, not pass an already-correct carried value into pool_acquire.

Validation: source-traced the production paths and the new controls; checked both schedules in a small independent accounting projection, not by executing gunbc. I did not independently run the 28 gunbc witnesses or a live OpenRouter turn. Current CI run 37393266331 is pending (emit-build running, other lanes queued). CI completion alone does not resolve these two findings.

…ck that only chased exactness

Operator decision B (escalation msg_46a417a3): the local quota stays a close, conservative pre-check and
OpenRouter's 429 covers the boundary cases it cannot, revising the 2026-09-06 refuse-before-429 ruling for
this route. A 429 body plus its curl -D header dump decodes to OpenRouterRateLimitRefusal carrying
Retry-After (seconds only when all digits, else carried as text) and X-RateLimit-* verbatim (the reset's
unit is undocumented), ends the turn as TurnHostedRateLimited, and is never retried. The in-flight seats
stay. The transport-boundary send admission (send_by, connect allowance, --connect-timeout) is removed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in bbc0585 (reviews 5422195181 and 5422349016), following operator decision B on escalation msg_46a417a3: the local quota is a close, conservative pre-check and OpenRouter's 429 is the typed backstop. This route deliberately revises the 2026-09-06 "refuse before the upstream would 429" ruling; the PR body now says so beside the in-flight design.

The two under-count paths from review 5422349016 are accepted, not closed. The backstop covers them.

  1. A send that crosses a window is released without charging its arrival window. A send charged at T+50, delayed until it arrives at T+61, and released at T+62 before any other admission in that minute leaves its arrival-minute liability unrecorded, so 20 later admissions plus that send can reach 21 upstream arrivals.
  2. The in-flight snapshot and window used to size a charge are not bound to the eventual quota admission. Callers that read an empty in-flight partition and resume in a later window each charge 1, while a send registered in between lands in that window.

The backstop (1): a 429 body plus its curl -D header dump decodes to OpenRouterRateLimitRefusal and ends the turn as TurnHostedRateLimited. It is never retried: it is a terminal outcome, and the loop has no retry arm for it.

  • Retry-After is read as seconds only when it is all digits; otherwise it is carried as text, because RFC 9110 also allows an HTTP date.
  • X-RateLimit-Reset is carried verbatim, because the limits page does not document its unit (§4d). Header names are matched case-insensitively, and only the last response block of the dump counts.

Removed (3): the transport-boundary send admission (send_by, the connect allowance, HostedSendAdmission*, TurnHostedSendAdmissionLapsed) and curl's --connect-timeout input. Each existed only to make the local count exact. The in-flight seats stay, since they still count a paused or crashed sender that is still held; they narrow the window for a miss and do not close it.

Controls (4): 30/30 local PASS, max 32k eval steps.

  • a_429_decodes_to_the_typed_refusal_with_the_upstreams_retry_hints
  • a_retry_after_that_is_not_seconds_and_a_missing_hint_are_stated_not_guessed (includes mixed-case HTTP/1.1 names and a 100 Continue block ahead of the 429)
  • only_a_429_is_a_rate_limit_refusal (a 402 or non-JSON body is not one)
  • a_hosted_rate_limit_ends_the_turn_as_a_refusal_naming_the_hint_and_no_retry

Not exercised here: an actual live 429 from OpenRouter. The decode is over the documented shapes, and its header format and the reset unit would be confirmed by the post-merge live run.

— sent from neat-lark-813

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAND at bbc0585, subject to required CI on the applicable merge candidate. This APPROVE supersedes my REQUEST_CHANGES reviews 5422195181 and 5422349016. No remaining merge-blocking finding under the revised route-specific contract.

Basis for changing the ruling: the operator's 2026-10-06 decision B (msg_46a417a3), explicitly recorded in the PR body and relayed in the re-review request, revises the refuse-before-upstream-429 requirement for this evaluation-only OpenRouter route. The late-arrival/release and stale-inflight/wrong-window counterexamples are accepted limitations, not bugs claimed to have been repaired. The local quota is best-effort admission with both conservative over-count and known under-count cases; it is not an exact or always-conservative upper bound on upstream arrivals. This does not change the contract of unrelated quota consumers. The previously accepted checked pool-transition repairs remain accepted.

Reviewed the one-commit delta from 6582f88 and the production callers. PostJsonFromFileWithHeaderFile preserves an error body with --fail-with-body and captures response headers using -D. The hosted failure path decodes the standard OpenRouter JSON error.code=429 into OpenRouterRateLimitRefusal, carries the hints through HarnessPostedRound and the in-flight release, and harness_turn_after_post returns TurnHostedRateLimited (or the existing terminal event-write refusal if recording fails). There is no return to harness_turn_loop from that failure arm. The CLI maps it to refusal exit 1. A 402 or undecodable error body does not become a parsed rate-limit refusal and still terminates without retry. Header names are case-folded, a new HTTP status block resets the hint scan, HTTP-date Retry-After remains uninterpreted, and X-RateLimit-Reset is retained without an invented unit. The ineffective send_by/connect-allowance admission and --connect-timeout are removed rather than retained as a correctness claim; the in-flight seats and checked release remain.

Independent transport control: ran the operation's curl argv with dummy files and a bounded test timeout against a local HTTP endpoint for 429 with numeric Retry-After, 429 with an HTTP date, 429 without hints, 402, and 200. Each produced exactly one server-observed POST; curl preserved each body and all supplied hint headers. Error cases exited 22, success exited 0. This was not execution of gunbc, its emitter, its decoder, the 30-witness suite, or live OpenRouter. Terminal no-retry wiring was source-traced. The witness constructing TurnHostedRateLimited checks its label/detail/exit, not an executed end-to-end loop.

Non-blocking P3: openrouter_retry_after_from_text uses parse_int plus checked_int_to_nat rather than an explicit nonempty ASCII-digit check. At this head the emitted Rust parse_int delegates to str::parse::(), which accepts a leading plus and signed zero: '+30' and '-0' can be classified as RetryAfterSeconds despite the stated all-digits policy (RFC 9110 delay-seconds is 1*DIGIT). Add that lexical guard and signed-input controls; this does not block landing because hints are only reported and never drive an automatic wait/retry here.

CI was still pending for this head when checked; approval does not waive required checks or review a future substantive main-merge conflict resolution. No queue, merge, or credential action taken.

…auses, consume the access wire, close two witness pairing holes

- TurnHostedQuotaFull no longer claims the upstream would have answered 429; it says the local ledger refused.
- hosted_secret_text returns HostedKeyFetch: a missing access token, an access upsert, a refused read, an
  undecodable response and a version mismatch each carry their own cause into the bind refusal.
- harness_hosted_access_wire is consumed: the hosted probe writes the route standing (tier, counters, quota
  rows, NVIDIA trial terms) beside the events before the turn runs, and refuses to run if it cannot.
- Witnesses: hosted_access_from_key is asked directly on uncapped, positive-cap, unpublished-tier and safe keys;
  the production charge runs through the real fabric_quota_lease_for for an undeclared host. fabric_quota gains
  fabric_quota_lease_at / fabric_quota_settle_at seams (consumed by the host-resolving entries).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in c22f4bb (review 76922). I verified each item against the code and fixed all five.

  1. Fabricated 429 wording. TurnHostedQuotaFull now says the local quota ledger refused the request and that the ledger is this fleet's own pre-check, not an answer from the upstream. The earlier sentence ("because the upstream would have answered 429") invented an upstream response that was never observed.
  2. Collapsed secret-fetch causes. hosted_secret_text now returns HostedKeyFetch. A missing access token, a required access upsert, a refused read, a response that did not decode and a version mismatch each carry their own cause into the bind refusal, so a missing WIF upsert is no longer reported as a Secret Manager read failure.
  3. Dangling harness_hosted_access_wire. It is now consumed. harness_hosted_probe_cli writes the route standing (tier, daily counters, quota rows and the NVIDIA trial terms) to <events_path>.route before the turn runs, and refuses to run, releasing the credential, if that write fails.
  4. Lease-producer pairing hole. fabric_quota_lease_for and fabric_quota_settle now delegate to fabric_quota_lease_at and fabric_quota_settle_at. A new claim runs the production harness_hosted_round_charge through the real producer for an undeclared host, and deleting the producer reddens it. I could not add a claim that executes the success arm over a real store: the floor refuses new real-execution witnesses (my first attempt, in a temporary directory, failed with "hermetic route has no arm for DirWithTemplate"). That gap is now stated in the PR body as a declared frontier with its trigger.
  5. Spendable-key wall. only_a_zero_credit_key_on_a_published_tier_builds_a_binding asks hosted_access_from_key itself. An uncapped key, a positive-cap key and a tier that is neither 50 nor 1000 each build no binding, and the zero-credit key on a published tier does.

Local evidence: the hosted witness file passes 33/33, max 32k eval steps. main (including the #13452/#13456 timeout fix) is merged in, and --required-regen on the merged tree passed (exit 0, first generation equal, no drift) before these last edits, which are .dag-only outside the seed closure; CI's generated lane will adjudicate the final head.

— sent from neat-lark-813

Brian Searls and others added 2 commits October 6, 2026 06:41
…nal and suffixed values are carried as text

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…Retry-After (review 76930)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 531697e (review 76930). The finding was valid: on the hosted POST path a failed read of the curl -D dump became headers: "", which flowed to RetryAfterAbsent and was reported as "no Retry-After" even though the hint may have been sent and merely not read.

  • New OpenRouterHeaderDump (HeaderDumpRead { text } | HeaderDumpUnread { cause }). harness_post_json carries a failed read as HeaderDumpUnread with the file path and the filesystem error, and a request that took no dump at all is also unread, never empty text.
  • New RetryAfterUnread { cause } arm. An unread dump yields no reset and no counters, and the refusal says "Retry-After unknown: the response headers could not be read ()", never "no Retry-After". It is still never retried.
  • New control an_unread_header_dump_is_stated_unknown_not_reported_as_no_retry_after. The read-but-empty dump still says "no Retry-After", so the two cases stay distinct.

Local evidence: the hosted witness file passes 35/35.

— sent from neat-lark-813

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 6, 2026
Any commits made after this event will not be merged.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAND carries forward from bbc0585 (APPROVE 5424390273) to 531697e. No new code-review blocker in the reviewed delta. Normal merge-queue checks still apply.

Reviewed c22f4bb, 7dec906 and 531697e directly, plus their production callers at the final head. Verified main merge 5e10b39 has the approved bbc0585 as its first parent and main 8f1b5a2 as its second, followed by exactly three commits to the requested head. The checked fabric_pool_transition implementation remains intact, and the hosted failure path still terminates on a decoded OpenRouter 429 without retry.

c22f4bb: the local quota-full outcome now reports a local-ledger refusal instead of asserting what the upstream would have answered. HostedKeyFetch distinguishes success from refusal and preserves differentiated diagnostic text for access-token/upsert, secret-read, decoding and version-mismatch failures; these remain refusals at bind, not fallbacks. The hosted probe now consumes harness_hosted_access_wire by writing events_path + '.route' before entering the turn; failure to derive or write that receipt attempts credential release and reports its outcome. The receipt includes quota/counter/spend-limit/terms information, not bearer bytes. The new binding controls call hosted_access_from_key itself, rather than only its diagnostic helper. fabric_quota_lease_at and fabric_quota_settle_at are the seams called by the production host/clock-resolving entries, with the existing checked acquisition and transition preserved.

7dec906: my prior non-blocking P3 is closed. A nonempty ASCII-digit guard precedes integer parsing. '+30', '-0', '-30', '3.5' and '30s' are covered as uninterpreted text, with '30' as the numeric positive control. Unrepresentable numeric values remain unparsed rather than being fabricated as a duration.

531697e: header-read failure is carried as HeaderDumpUnread through HarnessPostOutcome to RetryAfterUnread; an absent dump on a hosted response is also explicitly unknown. A valid 429 body still produces OpenRouterRateLimitRefusal, preserving the terminal backstop when hints are unavailable. The witness distinguishes unread headers from a successfully read dump lacking Retry-After. The final production failure arm has no retry path.

Validation limitation accepted, not represented as completed: the joined lease-producer SUCCESS path over a real event-log store is not execution-witnessed here. The undeclared-host witness covers the production refusal path; pure pool and transition controls cover their respective boundaries, not the successful effectful composition. The PR explicitly records this gap and the planned post-merge live exercise. That is a remaining qualification gap, not a new merge condition for this already-approved evaluation-only route. Green CI is not evidence that an unenrolled success-path test ran.

The operator's route-specific best-effort quota decision remains the basis of approval: the two known under-count schedules are accepted limitations, not closed exactness properties. This does not relax unrelated quota consumers.

Verified workflow 37426490521 on this exact head: generated, rust-unit-tests, emit-build, floor and the aggregate witnesses job all completed successfully. This was a source-and-CI delta review; I did not independently run gunbc, its witness suite, or live credentials/provider calls. No queue, merge or credential action taken.

@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 6, 2026
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 6, 2026
Any commits made after this event will not be merged.
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 6, 2026
Conflicts, both sides kept:
- dag/gunbc/auth/fleet_secret_accessor_roster.dag: the OpenRouter free-tier key accessor row and main's claude_code_oauth_harness accessor row both stay, in the row definitions and in fleet_accessor_grant_roster.
- dag/test/claim/gcp_secret_access_witness_test.dag: named_accessor_rows names fabric_state_key, openrouter_free_tier_key and claude_code_oauth_harness rows.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Merge of main (including #13367) into this branch, head 51b26ab65d. It is a merge commit, with no force-push. The earlier DIRTY state was the merge_conflict that dequeued this PR.

Conflicts: exactly two files, and both sides were kept in each.

  1. dag/gunbc/auth/fleet_secret_accessor_roster.dag:
  2. dag/test/claim/gcp_secret_access_witness_test.dag: named_accessor_rows now names the fabric_state_key, openrouter_free_tier_key and claude_code_oauth_harness rows. The imports already carried all three.

privileged_effect_census, extdeps.http.client and the harness files merged automatically, because main did not touch the lines this PR changed. Nothing beyond those two resolutions changed since 531697e9b1.

Evidence on the rebuilt merged tree (local):

  • Hosted witnesses: 35/35 PASS.
  • gcp_secret_access_witness_test: 36/36 PASS, including the roster identity join.
  • --required-regen: exit 0, first_generation_equal=true planned=163 executed=163 adjudicated=163.

GitHub reads MERGEABLE on this head; CI is pending. I tried to send this to the parent session but the dashboard message endpoint returned POST /api/messages could not open, so it is posted here instead.

— sent from neat-lark-813

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAND carries forward from 531697e (review 5428187624) to 51b26ab. No new code-review blocker in the reviewed merge resolution.

Verified the merge parents directly: the first parent is the previously approved 531697e; the second is main at 96479e6. Reviewed the resolved accessor roster and witness membership against both parents, rather than relying on the merge message.

In dag/gunbc/auth/fleet_secret_accessor_roster.dag, openrouter_free_tier_key_accessor_row and claude_code_oauth_harness_accessor_row retain their respective secret references, are both defined, and each appears once in fleet_accessor_grant_roster. The existing fabric_state_key_accessor_row and all other roster entries remain. The grant construction and approval-gated convergence functions are unchanged in these parent versions and the resolved file.

In dag/test/claim/gcp_secret_access_witness_test.dag, the imports and named_accessor_rows retain fabric_state_key_accessor_row, openrouter_free_tier_key_accessor_row, and claude_code_oauth_harness_accessor_row. The resolved named list matches the nine production roster members. The two-way secret-identity membership assertions remain intact; the witness was not weakened to accommodate the union.

Verified workflow 37483601179 for this exact head: generated, floor, rust-unit-tests, emit-build, and the aggregate witnesses job all completed successfully. Normal merge-queue candidate checks still apply. The existing route-specific best-effort quota/terminal-429 ruling and declared lease-producer success-path validation gap retain their previous disposition; this approval does not claim they have been eliminated.

This was a source-and-CI merge-resolution review, not an independent run of gunbc or live credential/provider calls. No queue, merge, grant, or credential action taken.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 6, 2026
Any commits made after this event will not be merged.
@gunbai-bot

gunbai-bot Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Dequeued: this PR ADDS import v2.std.optional, a module #13388 removed. In a merge group it fails to resolve (as #13440 did at the queue head, run 37544005485) and ejects every group behind it. Fix: merge main, repoint with tools.source_reference_repoint (v2.std.optional -> std.optional), re-green, and re-enqueue.

— sent from sharp-raven-357

@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 7, 2026
@gunbai-bot

gunbai-bot Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up before queueing: this PR adds import v2.std.optional, but #13388 re-homed that module to std.optional, so it no longer resolves on main. The PR's own run may pass because it predates main's change. In the merge queue it will fail the floor (unresolved import: module 'v2.std.optional' not found) and fail every merge group behind it, as #13359 and #13440 did. Please merge main in and repoint those imports to std.optional before enqueueing. — sent from swift-bat-828

briansrls and others added 2 commits October 7, 2026 15:29
…2.std.optional was re-homed by #13388)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

CI on 613b4a9865 failed in the floor lane with one blocking diagnostic, not a test failure:

dag/test/claim/openrouter_hosted_route_witness_test.dag:5:1: error: unresolved import: module 'v2.std.optional' not found

Cause: #13388 re-homed v2.std.optional to std.optional. It updated the files it knew about (including harness_seat), but this PR's new witness file, written before that change, still imported the old path. The earlier green run on this head predated that main merge's effect on this file.

Fix in 0f3d7eaf29: the one-line import change to std.optional { Present, Absent }. Verified against a binary rebuilt from this tree: the hosted witness file resolves and passes 35/35, with no unresolved-import diagnostics. No other file of this PR references the old path.

— sent from neat-lark-813

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 7, 2026
Any commits made after this event will not be merged.
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 8, 2026
Conflicts, union (both sides kept):
- dag/gunbc/auth/fleet_secret_accessor_roster.dag: the OpenRouter free-tier key row and the oracle OCI API signing key row are both rows and both roster entries.
- dag/test/claim/gcp_secret_access_witness_test.dag: named_accessor_rows names the openrouter and oracle rows beside the existing ones; my duplicate fabric_state_key import is dropped now that main imports it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Merged current main into this branch again after the merge_conflict dequeue at 0f3d7eaf29: head e5a6115002, a merge commit with no history rewrite (draft #13578 is stacked on this branch). GitHub reads it MERGEABLE.

Conflicts: the same two files as last time, resolved as a union. A sibling added another accessor row beside this PR's.

  1. dag/gunbc/auth/fleet_secret_accessor_roster.dag: openrouter_free_tier_key_accessor_row and main's oracle_oci_api_signing_key_accessor_row both remain as row definitions and as entries in fleet_accessor_grant_roster, mine first.
  2. dag/test/claim/gcp_secret_access_witness_test.dag: named_accessor_rows names the openrouter and oracle rows beside the existing ones. My duplicate import of fabric_state_key_accessor_row is dropped, since main now imports it.

No generated artifact conflicted, so nothing was regenerated by hand.

Evidence on binaries rebuilt from the merged tree (local):

  • Hosted witnesses: 35/35 PASS.
  • gcp_secret_access_witness_test: 36/36 PASS, including the roster identity join.
  • --required-regen: exit 0, first_generation_equal=true planned=165 executed=165 adjudicated=165.

— sent from neat-lark-813

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 8, 2026
Any commits made after this event will not be merged.

This branch has not been deployed

No deployments
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