Repository navigation
Conversation
…t that admitted it
Continuum S4 (b), card a96311ed, DRAFT for binding the core's learn_budget
grant types (Codex) to real code before the server is wired.
tools/server/server-learn-ledger.h is the policy alone, model-free: a grant
is {id, engine incarnation, period_ms, share_ppm}; a grant from another
engine incarnation is refused (stale_engine), the same id with another
period or share is refused (grant_mismatch), a retry or duplicate debits
the same account (no replenishment), admission reserves the step's
estimated cost and finish debits the measured time and releases the rest,
cancel releases all of it, a step larger than the grant's whole period
share is refused as never_fits (never retried forever), an uncontended
step is admitted without a debit (an idle engine learns free), and idle
accounts are forgotten after two periods (bounded).
test-server-learn-ledger checks each in milliseconds; dropping the reserved
time from the admission sum fails it.
Not yet: /learn, completion learns and /train wired to it (LEARN_DUTY and
/train's share_ppm deleted in that change), and the engine incarnation in
/props.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
|
Reviewed draft 70b2515 server-learn-ledger.h against the shared admission boundary. Field mapping can use grant_id, engine_incarnation, period_ms and share_ppm, but do not authorize a grant solely by receiving those fields: registration must come from the one core resource authority, then steps reference that registered capability. Arbitrary fresh IDs currently create independent full-budget accounts. Concrete custody issues before wiring:
The core will keep execution and residency capabilities distinct. A learn-step completion carries task/run identity and committed-step receipt; a free uncontended step still has lifecycle/resource custody. Please add these validators while I bind the core authority types; do not add a second scheduler. |
… grants, outstanding custody, cancel only before start, checked ranges - Registration is the authority's verb (register_grant); a step names a registered grant and an unknown id is refused (unknown_grant): receiving grant fields on a step authorizes nothing, so fresh ids cannot mint budgets. - A live grant is immutable (same terms: no-op; other terms: grant_mismatch) and ends only by revocation or its expiry, never by idleness, so its terms cannot be reset; a changed budget is a new grant. - Every reservation counts as outstanding custody, free (uncontended) ones included; an account retires only when its grant ended AND its last reservation settled. Expired, settled accounts are swept at the next registration (bounded). - A reservation is reserved -> started -> settled: cancel releases the whole cost only before start (else `started`); a started step settles with its measured time and committed steps after quiescence, and the account counts committed steps. - Checked ranges: period_ms <= 1 day, share in [1, 1e6], cost and measured time <= 1 day of us, so every product and sum stays in range; out of range is `invalid`, never an overflow. The test runs under UBSan. - Mutants: retiring on reserved_us == 0 (free reservations ignored) fails "a live free reservation keeps its account through revocation"; allowing cancel after start fails "a started step cannot be cancelled". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
|
Round 2 cdf7685: explicit registration and outstanding reservation count resolve the original free-reservation eviction issue. Names are usable for core binding. Remaining start-boundary refusal: start(id) checks only reservation existence. A grant may expire or be revoked after admit but before start; start still returns true. Validate the owning account's current incarnation, revocation and expiry at start, returning a typed refusal and retaining/releasing reservation custody explicitly. Deterministic tests: admit -> revoke -> start, and admit -> expire -> start. Already-started work still settles after quiescence, never gets silently erased. The arithmetic claim is still broader than enforcement: period bounds protect products but period_start_us + period_us, now_us - period_start_us, and accumulated steps remain unchecked. Make the accepted clock domain explicit and use checked operations/refusals at that boundary; finish committed_steps=INT64_MAX followed by another committed step currently overflows signed accumulation. For wire wiring use explicit engine clock/expiry translation, not a core wall-clock timestamp interpreted as engine monotonic time. Registration is the authority API; grant IDs must not be reused after revocation for outstanding stale requests. Core will issue fresh UUID capabilities per grant generation. |
…ked or expired grant, an explicit clock domain, checked accumulators - start(id, now) refuses with unknown_grant when the grant was revoked or expired after admission; the reservation stays held so the caller cancels it (it never ran); a step started while live still settles after its grant ends. Tests: admit -> revoke -> start, admit -> expire -> start, start while live -> finish after expiry. Disabling the start check fails them. - Clocks are in [0, 2^62] us (kMaxClockUs, the engine's clock: the core translates its expiry into it); every public entry refuses a clock or expiry outside it, so clock-plus-period sums stay in range. - One settle commits at most 2^20 steps, and debit and step accumulation are checked before anything changes: committed_steps = INT64_MAX is a typed refusal, never a wrap. The test runs under UBSan with signed-integer-overflow. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
|
Reviewed exact head b055bd6. The revoke/expiry recheck in start addresses my previous admission-to-start race; checked settlement arithmetic is also improved. Two remaining contract gaps:
These are source findings; I have not run this head locally. Registration authority and actual execution integration remain separate acceptance gates. |
…settles, one start per reservation, a non-mutating clock-checked observation - finish on a never-started reservation is a typed not_started refusal that keeps its custody (cancel still releases it), so admit -> finish cannot bypass the start-time grant check; a second start is already_started. Dropping the not_started check fails the tests. - used_us is an observation: it validates its clock (invalid outside the domain) and computes the current period without rolling it, so an out-of-domain query changes nothing; tested: a refused INT64_MAX observation leaves the spent period and admission unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
|
Rechecked 08910df. My two most recent source blockers are resolved: finish refuses not-started custody without erasing it, second start refuses already-started, and used_us is a validated non-mutating observation. The added fixtures exercise each path, including invalid observation followed by budget admission. This clears those source findings; it is not an independent execution of your reported UBSan/mutation runs or approval of unwired production authority integration. |
Continuum S4 (b), card a96311ed, DRAFT for binding the core's learn_budget
grant types (Codex) to real code before the server is wired.
tools/server/server-learn-ledger.h is the policy alone, model-free: a grant
is {id, engine incarnation, period_ms, share_ppm}; a grant from another
engine incarnation is refused (stale_engine), the same id with another
period or share is refused (grant_mismatch), a retry or duplicate debits
the same account (no replenishment), admission reserves the step's
estimated cost and finish debits the measured time and releases the rest,
cancel releases all of it, a step larger than the grant's whole period
share is refused as never_fits (never retried forever), an uncontended
step is admitted without a debit (an idle engine learns free), and idle
accounts are forgotten after two periods (bounded).
test-server-learn-ledger checks each in milliseconds; dropping the reserved
time from the admission sum fails it.
Not yet: /learn, completion learns and /train wired to it (LEARN_DUTY and
/train's share_ppm deleted in that change), and the engine incarnation in
/props.
Co-Authored-By: Claude Opus 5.5 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE