Skip to content

continuum-base, the floor crate: leaf utilities and probe macros leave the monolith (redo of #5194 on post-split canary) - #5249

Merged
joelteply merged 4 commits into
canaryfrom
fable/continuum-base-v2
Oct 21, 2026
Merged

joelteply merged 4 commits into
canaryfrom
fable/continuum-base-v2

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

Supersedes #5194.

What moved

New workspace crate core/continuum-base (continuum-core depends on it), git mv of whole module trees from continuum-core/src:

  • time/ (mod, age), config_env, secrets, id_resolve, fs_portable/ (mod, replace), shell_portable, audio_constants
  • the pure-tracing macros probe!, time_sync!, time_probe! -> continuum-base/src/probe.rs, carrying canary's new probe!(target: ..., class = ...) arm. stack! stays in routing/macros.rs (needs continuum-core's routing).
  • Root pub use audio_constants::* deleted; no re-exports anywhere. None of the moved modules had a crate:: path into continuum-core (leaf modules, as expected).

References rewritten

1,779 substitutions across 538 files by script (crate::/continuum_core::/$crate:: to continuum_base::; ~451 module refs + ~1,327 macro call sites, matching #5194's count). Done by script on fresh canary (71fbc89) because plain rebase conflicted over the canary file splits.

Carried fixes

  • fs_portable::fault_injection behind test-fixtures (continuum-core's test-fixtures enables it); the spill test uses it instead of a private test module.
  • config_env temp paths: canary's own config_env tests: fresh temp dir per call (card 4c820b46) #5242 fix kept.
  • source-hygiene audits continuum-base too (SPLIT_CRATES + audited_files()); wall_clock owner/wrapper spellings follow time.
  • Windows: windows-sys (Win32_Storage_FileSystem, Win32_Foundation) for fs_portable in continuum-base; protocol/typescript/keys/KeysSetResult.ts doc path updated (ts-rs copies doc comments).

Local verification (M5, own target dir, nice 19)

  • cargo test -j 6 -p continuum-base: 27 passed, 0 failed.
  • cargo check -j 6 -p continuum-core --tests --features metal,accelerate: 0 errors (first run found one missed ref, the spill test's fs_portable::tests::; fixed, re-run Finished clean).
  • cargo test -q -p source-hygiene: 43 passed; no baseline changed (none raised or lowered).
  • Warnings: rustc lint count not comparable to the CI baseline locally (CI uses default features and --lib test profile); the one lint mentioning the moved macros (unused_braces at routing/macros.rs test) is pre-existing, reproduced with a same-crate macro. CI's rust-warnings-baseline check is the authority.
  • Not run locally: windows-msvc, ts-rs drift (left to CI).

🤖 Generated with Claude Code

joelteply and others added 4 commits October 21, 2026 08:04
…e leaf modules into it

Card a31492cb, redone on post-split canary (supersedes #5194, whose branch cannot rebase
over the many files canary has since split). New crate core/continuum-base joins the
workspace and continuum-core depends on it. Moved with git mv, whole module trees:
time (mod + age), config_env, secrets, id_resolve, fs_portable (mod + replace),
shell_portable, audio_constants. They have zero Continuum dependencies, so none of their
crate:: paths needed repair. The probe!, time_sync! and time_probe! macros (pure tracing)
move out of routing/macros.rs into continuum-base/src/probe.rs, carrying canary's
probe!(target: ..., class = ...) arm; stack! stays because it needs continuum-core's
routing. The root `pub use audio_constants::*` is deleted: users name the owner.

fs_portable's publication-fence fault hook moves to fs_portable::fault_injection behind a
test-fixtures feature that continuum-core's test-fixtures enables, so continuum-core's
spill test no longer reaches into a private test module. config_env keeps canary's own
temp-dir fix (#5242).

References are rewritten in the next commit; this one is the move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…e macros to name continuum-base

Mechanical rewrite by script, no re-exports left behind: crate::/continuum_core::/$crate::
time, config_env, secrets, id_resolve, fs_portable, shell_portable, audio_constants and
the probe!, time_sync!, time_probe! macros become continuum_base::... in continuum-core's
src, tests, benches and examples (1,779 substitutions across 538 files: ~451 module
references and ~1,327 macro call sites, matching #5194's count). The macros.rs doc example
now imports probe from its owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…time to continuum-base

source-hygiene audited only continuum-core/src, so code split into a crate would silently
leave every ratchet (unwraps, file size, wall clock, layer discipline). audited_files() now
covers continuum-core plus each SPLIT_CRATES entry, with the crate name as a path prefix so
totals stay continuous across the cut and per-path rules stay unambiguous; a listed crate
with no src fails loudly instead of auditing nothing. wall_clock's owner path and bare
wrapper spellings follow time to continuum-base. Same change as #5194's 8d69153, applied
cleanly onto canary's current scanner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…ws the moved module

continuum-base's fs_portable calls MoveFileExW on Windows, which continuum-core declares
and the new crate did not (windows-msvc would fail with E0433 windows_sys, as #5194's CI
did). Declared with only the two features it uses. KeysSetResult.ts changes because its
Rust doc comment now names continuum_base::secrets (ts-rs copies doc comments).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
@joelteply

Copy link
Copy Markdown
Contributor Author

Author-side verification of #5249 at bd80212 (not a peer review; one is needed to merge):

  • 12 moves via git mv. 11 are 100% renames; fs_portable/mod.rs is 93%, with its test hook split out to fault_injection.rs.
  • All 545 modified files were normalized by stripping continuum_base:: / continuum_core:: / crate:: / $crate:: / super:: and whitespace, ignoring use-lines and mod-lines of the moved modules. Only 7 have any residual difference, and each is expected: Cargo.lock, Cargo.toml, continuum-core/Cargo.toml (the dependency, and test-fixtures forwarding to continuum-base/test-fixtures), spill/tests.rs (fs_portable::tests -> fs_portable::fault_injection), routing/macros.rs (probe!/time_sync!/time_probe! leave, stack! stays), source-hygiene lib.rs (SPLIT_CRATES plus audited_files so the new crate stays under every gate), and wall_clock.rs (the OWNER path follows time).
  • Nit for the reviewer: wall_clock.rs's bare list now contains the "time::EpochMs::now().millis()/secs()" pair twice after the rewrite (harmless, but one copy should go).
  • CI all green: core lib tests, Windows compile and custody, windows-msvc check, hygiene ratchets, ts-rs drift, Windows installer.

@joelteply

Copy link
Copy Markdown
Contributor Author

Codex independent source review: PASS at bd80212.

Compared Git blobs against 71fbc89: 537 modified files equal the original after only the declared module/macro path substitutions. Inspected the eight remaining modified files (manifests/lock, lib exports, routing macros, spill fixture, hygiene traversal and wall-clock ownership). Moved leaf utilities preserve source; config_env and shell_portable are byte-identical without path normalization. All three exported macro bodies are byte-identical, including the explicit tracing target arm. The filesystem fault injection remains test/test-fixtures gated, and continuum-core's dev dependency enables it for the spill regression. The new base crate has no upward Continuum dependency; hygiene continues across the split without baseline changes.

Exact-head CI is green, including core tests, Windows compilation, Windows installer, windows-msvc, hygiene and ts-rs. No local compilation or deployment performed. This is source/integration approval, not live performance or learning evidence.

@joelteply
joelteply merged commit eb4193b into canary Oct 21, 2026
8 checks passed
@joelteply
joelteply deleted the fable/continuum-base-v2 branch October 21, 2026 14:28
joelteply added a commit that referenced this pull request Oct 21, 2026
…moved the macro)

CI on f153640 failed to compile the merge with canary: #5249 moved the probe macros
into the continuum-base floor crate, and request_body.rs's other probes now call
continuum_base::probe!. Rebased onto canary 445ae4b; the one new probe follows.
source-hygiene 43/43 on IntelMac.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
joelteply added a commit that referenced this pull request Oct 21, 2026
…; a dense model's GGUF is read once (card 60f74ac5, f3ba3b56 item 19)

Re-applied onto canary 445ae4b after #5245 split serving_daemon.rs (the builder
and its readers now live in serving_daemon/placement.rs and moe_cache.rs) and #5249
moved the probe macro to continuum_base.

moe_serving_context returned None both for a dense model and for a GGUF it could not
read (open or header error, no architecture, a layout error other than NotMoe, no
router top-k, no block_count). A MoE with unreadable geometry was served dense, with
no expert placement and no word. It now returns Result<Option<ctx>, why>: Ok(None) is
dense (NotMoe), and an expert count with no stacked tensors or a malformed layout is
an error, not dense.

The placement cache held only a MoE context, so for a dense model every call re-opened
and parsed the GGUF header. The guard now caches the verdict per model (Option<ctx>,
dense included) and probes serving.moe.geometry_unreadable once when it is built. A
GGUF that does not resolve yet is not cached, so it is read once it lands. The two
readers match Some((id, Some(ctx))).

source-hygiene 43/43 on IntelMac. Core compile is CI's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
joelteply added a commit that referenced this pull request Oct 21, 2026
…s are re-asked (card 6080a28f, f3ba3b56 items 11 and 13)

Re-applied onto canary 445ae4b after #5245 split llama_server.rs (prepare.rs,
kv_support.rs, genome.rs) and #5249 moved the probe macro to continuum_base.

Item 13: server_bin() falls through to a bare 'llama-server' from PATH when no
override, slot or legacy install resolves. A stock build there runs without the fork's
routes (slot save-size, /train, MTP). prepare_local_launch now calls
engine_slots::note_unowned_launch, which probes serving.engine.unslotted when the
engine is a bare PATH name no operator override chose. Resolved::Path's doc says what
actually happens.

Item 11: ensure_engine_kv_support_recorded latched once per process before probing, so
a failed or timed-out --help probe left /train off and KV to the backend table for the
core's life, and an engine promote kept the old binary's answers. The latch is now the
binary that answered; a failure is asked again at the next launch, a promoted binary
afresh, and a failure resets ENGINE_TRAIN_DIR and ENGINE_QUANTIZED_KV to unknown.

source-hygiene 43/43 on IntelMac. Core compile is CI's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
joelteply added a commit that referenced this pull request Oct 21, 2026
…ned over a resident (card 1ca5abe1, f3ba3b56 item 4)

Re-applied onto canary 445ae4b after #5245 split slots.rs and openai_adapter.rs
(the request placement now lives in openai_adapter/stream.rs) and #5249 moved the
probe macro to continuum_base. The slots test move this PR used to carry is already
on canary.

A Turn with no (persona, room) key (a nil-room eval on her live lane, or a caller that
dropped its room) went out UNPINNED with cache_prompt on whenever the pool had a
scratch slot, so the server placed it by similarity and could overwrite a resident's
KV. The one placement rule is now slots::placement (slots/placement.rs): only a keyed
Turn owns a slot. Every other request, a keyless Turn included, takes the slot its
admission borrowed or the scratch slot, and without a scratch slot never persists a
cache. A keyless Turn probes inference.turn.keyless with its purpose, and only a keyed
Turn registers an in-flight slot guard.

Test: slots::tests::only_a_keyed_turn_owns_a_slot pins the four cases.
source-hygiene 43/43 on IntelMac. Core compile is CI's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
joelteply added a commit that referenced this pull request Oct 21, 2026
…s, not a silent re-prefill (card f3ba3b56, items 1, 3 and 6)

Re-applied onto canary 445ae4b after #5245 split openai_adapter.rs (the completion
probe now lives in openai_adapter/stream.rs) and #5249 moved the probe macro to
continuum_base. The turn_admission test move this PR used to carry is already on canary.

- turn_admission: TurnAdmission records how its KV reached the slot, as PageIn
  {None, Resident, Restored, RestoreRejected}, instead of a restored bool. A restore
  the engine refuses is probed at the decision (inference.restored_turn
  outcome=restore_rejected), so it counts even for a turn that never completes.
- stream.rs: at completion, Restored is judged warm/cold as before. A Resident slot
  that reused nothing is its own class (inference.resident_prefix_lost), kept out
  of the restore verdict.
- track-canary.sh: the deploy self-check counts restore_rejected against the economy,
  reports lost resident prefixes on their own line (a failure when they outnumber warm
  restores), and reports refused KV page ledger adoptions with their reasons.

source-hygiene 43/43 on IntelMac. Core compile is CI's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE
joelteply added a commit that referenced this pull request Oct 21, 2026
…split canary as one commit)

Squash of the #5215 branch (9 commits plus its canary merge) re-applied onto
current canary after #5245 split the files it edited and #5249 moved the probe
macros: the same edits, landed in the split child modules. Ratchet baselines
are canary's; CI measures the exact lowered counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
joelteply added a commit that referenced this pull request Oct 21, 2026
…st-only items (rebased onto split canary as one commit)

Squash of the #5195 branch (8 commits plus review fix) re-applied onto current
canary: the same deletions landed in the split child modules from #5245, the
probe path from #5249, and files #5200 already removed are skipped. Ratchet
baselines are canary's; CI measures the exact lowered counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
joelteply added a commit that referenced this pull request Oct 21, 2026
…amed (card 912e606d) (#5252)

* serving: no request decodes past one lane window; an uncapped request is named (card 912e606d)

Measured on the MacBookPro node (5159a48b), 2026-10-21, core d3c6e86:
- 13:50:42Z, /slots slot 1: params n_predict -1 / max_tokens -1, prompt 29,238 tokens,
  n_decoded 27,794; 27,854 at 13:51:24Z. Context-shifting past the 32k window, so it
  never has to end. It held one of the node's 2 lanes.
- Same hour: Eitan, Iris and SmokeProbe waited 472-519 s for a lane (turn_bound
  496 s) and gave up (persona.act.lane_starved waited_secs).

Cause: build_base_body (request_body.rs) sends max_tokens only when the request
carries one, and lane_args::base_invocation passed no --n-predict, so the engine's
default for an uncapped request is -1, infinite.

- base_invocation passes `--n-predict <total_ctx / lanes>`. In llama-server, -n is
  the default for a request without a cap and the per-slot ceiling on one with a
  larger cap, so no request decodes past one window, which is the most any turn
  can use. A legitimate capped request is unchanged.
- build_base_body probes inference.request.uncapped (purpose, model) when
  max_tokens is absent, so the callers that still owe a cap are found from probes.
- Test: no_request_may_decode_past_one_lane_window pins the flag at the per-lane
  window for 1, 2 and 5 lanes.

source-hygiene 43/43 on IntelMac. Core compile and lib tests are CI's. Deployed
measurement owed (owner Cormac, on this node's next deploy): /slots shows no
n_predict -1 slot, and persona.act.lane_starved waits drop.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

* serving: --n-predict is the uncapped default, not a ceiling (Codex on #5252)

The pinned fork's server-context.cpp:1794-1795 sets slot.n_predict_max from the
request's own n_predict when it names one and from the server's -n only when it
doesn't, so an explicit max_tokens above the lane window still wins. This change
bounds the uncapped request (the MacBookPro's n_predict -1 case) and leaves
explicit limits unchanged. The comment, the test name (an_uncapped_request_
defaults_to_one_lane_window) and the probe text now say only that.
source-hygiene green on IntelMac.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

* serving: the uncapped-request probe uses continuum_base::probe! (#5249 moved the macro)

CI on f153640 failed to compile the merge with canary: #5249 moved the probe macros
into the continuum-base floor crate, and request_body.rs's other probes now call
continuum_base::probe!. Rebased onto canary 445ae4b; the one new probe follows.
source-hygiene 43/43 on IntelMac.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request Oct 21, 2026
…ned over a resident (card 1ca5abe1, f3ba3b56 item 4) (#5191)

Re-applied onto canary 445ae4b after #5245 split slots.rs and openai_adapter.rs
(the request placement now lives in openai_adapter/stream.rs) and #5249 moved the
probe macro to continuum_base. The slots test move this PR used to carry is already
on canary.

A Turn with no (persona, room) key (a nil-room eval on her live lane, or a caller that
dropped its room) went out UNPINNED with cache_prompt on whenever the pool had a
scratch slot, so the server placed it by similarity and could overwrite a resident's
KV. The one placement rule is now slots::placement (slots/placement.rs): only a keyed
Turn owns a slot. Every other request, a keyless Turn included, takes the slot its
admission borrowed or the scratch slot, and without a scratch slot never persists a
cache. A keyless Turn probes inference.turn.keyless with its purpose, and only a keyed
Turn registers an in-flight slot guard.

Test: slots::tests::only_a_keyed_turn_owns_a_slot pins the four cases.
source-hygiene 43/43 on IntelMac. Core compile is CI's.


Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request Oct 21, 2026
…s are re-asked (f3ba3b56 items 11 and 13) (#5213)

* serving: the engine binary a launch runs is named and its capabilities are re-asked (card 6080a28f, f3ba3b56 items 11 and 13)

Re-applied onto canary 445ae4b after #5245 split llama_server.rs (prepare.rs,
kv_support.rs, genome.rs) and #5249 moved the probe macro to continuum_base.

Item 13: server_bin() falls through to a bare 'llama-server' from PATH when no
override, slot or legacy install resolves. A stock build there runs without the fork's
routes (slot save-size, /train, MTP). prepare_local_launch now calls
engine_slots::note_unowned_launch, which probes serving.engine.unslotted when the
engine is a bare PATH name no operator override chose. Resolved::Path's doc says what
actually happens.

Item 11: ensure_engine_kv_support_recorded latched once per process before probing, so
a failed or timed-out --help probe left /train off and KV to the backend table for the
core's life, and an engine promote kept the old binary's answers. The latch is now the
binary that answered; a failure is asked again at the next launch, a promoted binary
afresh, and a failure resets ENGINE_TRAIN_DIR and ENGINE_QUANTIZED_KV to unknown.

source-hygiene 43/43 on IntelMac. Core compile is CI's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

* fix: prepare.rs reaches engine_override through its parent module (card 6080a28f)

The re-port onto the split llama_server/ called engine_override() unqualified;
it lives in llama_server/engine_install.rs and llama_server.rs re-exports it, so
the child prepare.rs names it super::engine_override (CI E0425, job 119360256492).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

* fix: prepare.rs names engine_install::engine_override; the parent's re-export is windows-only (card 6080a28f)

llama_server.rs re-exports engine_override only under #[cfg(windows)], so
super::engine_override failed on the Linux lib test (job 119369995569). The
child module reaches its parent's private engine_install directly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request Oct 21, 2026
…; a dense model's GGUF is read once (card 60f74ac5, f3ba3b56 item 19) (#5214)

Re-applied onto canary 445ae4b after #5245 split serving_daemon.rs (the builder
and its readers now live in serving_daemon/placement.rs and moe_cache.rs) and #5249
moved the probe macro to continuum_base.

moe_serving_context returned None both for a dense model and for a GGUF it could not
read (open or header error, no architecture, a layout error other than NotMoe, no
router top-k, no block_count). A MoE with unreadable geometry was served dense, with
no expert placement and no word. It now returns Result<Option<ctx>, why>: Ok(None) is
dense (NotMoe), and an expert count with no stacked tensors or a malformed layout is
an error, not dense.

The placement cache held only a MoE context, so for a dense model every call re-opened
and parsed the GGUF header. The guard now caches the verdict per model (Option<ctx>,
dense included) and probes serving.moe.geometry_unreadable once when it is built. A
GGUF that does not resolve yet is not cached, so it is read once it lands. The two
readers match Some((id, Some(ctx))).

source-hygiene 43/43 on IntelMac. Core compile is CI's.


Claude-Session: https://claude.ai/code/session_01FRQWzgSfo79JtnwZywHKrE

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant