cadrumo.application.provisioning module¶
Typed dependency probes and CLI startup dependency provisioning.
The doctor probes in this module are read-only: each asks whether one external
service or optional package extra is usable on this workstation and returns a
typed DependencyStatus. The startup coordinator is the separate,
explicit composition boundary that provisions application-owned directories
and validates operator-owned and shipped dependencies before command dispatch.
The on-host readers are probed per role by
probe_local_reader(), so a down server or
an unpulled model becomes an instructive refusal instead of a raw stack trace.
The aeat config check command renders this module’s
statuses as
CheckDependencyPayload
rows beside the active profile’s capability posture from
resolve_active_capability(). Optional-extra
probes walk the core OPTIONAL_EXTRAS catalogue of
OptionalExtra records, so CLI diagnostics and adapter import
guards share one registry.
- ensure_cli_startup_dependencies()[source]¶
Provision owned storage defaults and validate the shipped authority.
Explicit storage overrides are dependencies and are validated by the materializer rather than created. Authority admission validates the published descriptor and content-addressed SQLite generation without hydrating registry components or reaching development authoring inputs.
- Return type:
- class DependencyStatus(**data)[source]¶
Bases:
ProvisioningOutcomeAvailability result for one external dependency.
serviceis the stable row id shown by the configuration check.factsrecords the measured state andprecondition_verdictcloses every unavailable outcome without embedding presentation or executable text. The model is intentionally generic so Ollama, subprocess CLIs, Playwright browser binaries, andOptionalExtrapackage extras all render through the same payload shape and can be validated intoCheckDependencyPayload.- Parameters:
data (Any)
- service: str¶
- available: bool¶
- class SystemMemoryReading(**data)[source]¶
Bases:
BaseModelMeasured total and free physical system memory, either of which may be unreadable.
Both figures are carried because they answer different questions and the provisioning decision separates them deliberately:
total_bytesis what a diagnostic row reports about the machine,free_bytesis the only figure a load decision may act on. A machine with 64 GiB installed and 2 GiB free cannot host a 4 GiB model, and reading the total as headroom is exactly the admission error the contention check exists to prevent.Nonemeans “not measured”, never “zero”. SeeAcceleratorKindfor the same distinction on the device side.- Parameters:
data (Any)
- total_bytes: int | None¶
- free_bytes: int | None¶
- read_system_memory()[source]¶
Measure total and free physical system memory, reporting either as
Nonewhen unreadable.Dependency-free on every supported platform: POSIX reads the
sysconfpage-size pair, Windows callsGlobalMemoryStatusExthroughctypes. The free counterpart costs nothing to obtain – the Windows struct already carriesullAvailPhysin the same call, and POSIX exposesSC_AVPHYS_PAGESbeside the total – so both figures come from one measurement and cannot disagree about the moment they describe.A platform that answers nothing yields
None, never a guess: an unknown quantity must not be reported as a shortfall byprobe_model_runtime_hardware_floor(), nor mistaken for headroom byassess_model_load_contention().- Return type:
- read_total_system_memory_bytes()[source]¶
Return total physical system memory in bytes, or
Nonewhen unreadable.A narrowing of
read_system_memory()for the hardware-floor diagnostic, which judges the machine’s installed capacity rather than its present headroom. Kept as the one total-only reader so there is no second platform branch to drift.
- probe_model_runtime_hardware_floor(settings=None, *, total_memory_bytes=None)[source]¶
Report whether this machine meets the local model runtime’s memory floor.
The third capability axis. The product already distinguishes installed (
OptionalExtra) from permitted (ServiceCapability); this answers capable – and is named for the floor it measures rather than for the word “capability”, which already denotes four unrelated concepts in this tree (modelo-revision capability, terminal capability, operator service capability, optional-extra capability).Below the floor the local runtime does not refuse. It loads and thrashes, or is killed mid-read, and the operator sees an unexplained timeout. This probe turns that into a typed row naming the shortfall and the accepted floor.
Unknown memory reports
availabletrue with a detail saying so. That is deliberate and is the safe direction for a diagnostic: an unreadable platform must not manufacture a shortfall that blocks a machine which may be perfectly adequate. The refusal is raised only on a measured shortfall.- Parameters:
settings (
Settings|None) – Settings carrying the configured floor; loaded when omitted.total_memory_bytes (
int|None) – Observed total memory, for callers that have already measured it. Defaults toread_total_system_memory_bytes().
- Return type:
- Returns:
A
DependencyStatuson themodel-runtime-hardware-floorrow.
- probe_optional_extra(extra)[source]¶
Probe whether an optional package extra is importable, never raising.
Wraps the core
optional_extra_available()spec-only check for oneOptionalExtra(no import, no side effects) in the doctor’sDependencyStatus, retaining only the extra’s machine identity when absent. The feature-boundary guard is the sibling corerequire_optional_extra(), which raises the typedMissingOptionalExtraErrorwhen a command actually requires the feature.- Return type:
- Parameters:
extra (OptionalExtra)
- class AcceleratorDevice(**data)[source]¶
Bases:
BaseModelOne enumerated accelerator device and its measured VRAM figures.
Per-device rather than aggregated because a model loads onto ONE device: two cards with 3 GiB free each are not 6 GiB of headroom for a 4 GiB model. The aggregation rules that follow from that live on
HardwareProfile.- Parameters:
data (Any)
- index: NonNegativeInt¶
- name: str¶
- total_vram_bytes: int | None¶
- free_vram_bytes: int | None¶
- class AcceleratorReading(**data)[source]¶
Bases:
BaseModelWhat the accelerator measurement found: a kind, and the devices behind it.
kindisAcceleratorKind; an emptydevicestuple is consistent with bothNONE(measured: there are none) andUNKNOWN(not measured), which is precisely why the kind is carried separately rather than inferred from the tuple being empty.- Parameters:
data (Any)
- kind: AcceleratorKind¶
- devices: tuple[AcceleratorDevice, ...]¶
- detail: str¶
- class HardwareProfile(**data)[source]¶
Bases:
BaseModelThe measured local-inference capacity of this machine.
Carries totals AND free amounts on both the system-memory and the device axis, and the two are not interchangeable: totals are for reporting, free amounts are for acting. A diagnostic row may say “16 GiB card”; a load decision may only consult
free_vram_bytes. Deciding on a total is the concrete defect this model exists to prevent – the machine this was built for has a 16 GiB card with under 4 GiB free, shared with a resident search service, and a load admitted against the total takes the host down with every running process on it.Every figure is independently optional.
Nonemeans the measurement was not obtainable, and per the provisioning decision the two directions differ: diagnostic rows report an unreadable figure as unverified and stay available, whileassess_model_load_contention()treats it as a refusal input. Seeprobe_hardware_profile().- Parameters:
data (Any)
- memory: SystemMemoryReading¶
- accelerator: AcceleratorReading¶
- property total_vram_bytes: int | None¶
Return summed device VRAM for REPORTING, or
Nonewhen any device is unreadable.Summed because the reporting question is “what is installed in this machine”, which is additive. Deliberately NOT the figure any load decision consults – see
free_vram_bytes.
- property free_vram_bytes: int | None¶
Return the largest single-device free VRAM for ACTING, or
Nonewhen unreadable.The maximum, never the sum: a model is resident on one device, so the headroom that decides admission is the best single device’s, and summing would manufacture capacity that no allocation can reach. Devices whose free figure is unreadable are skipped rather than counted as zero – they cannot host the load either way, and treating them as zero would not change the maximum.
Nonewhen no device reported a free figure at all, which fails closed at the act.
- read_accelerator()[source]¶
Measure the local accelerator through NVML, never raising and never loading a model.
NVML (the
nvidia-ml-pybinding declared in thellmextra) is preferred over anvidia-smishell-out because it yields per-device total and free figures from an in-process query with no subprocess. The distinction is load-bearing for attribution: a whole-device free figure is contaminated by every process on the card, which is exactly the quantityassess_model_load_contention()must split between this runtime’s residents and peer processes – so NVML is authoritative for the free-VRAM figure, and the runtime’s own/api/psreport (seeread_runtime_residents()) is authoritative for how much of it is ours.Returns
UNKNOWNwhen NVML is absent or uninitialisable, andNONEonly on the positive reading that NVML initialised and enumerated zero devices.- Return type:
- probe_hardware_profile(*, memory=None, accelerator=None)[source]¶
Measure this machine into a
HardwareProfile, never raising.Both measurements are injectable arguments rather than patched module internals, so every branch of the profile and of
assess_model_load_contention()is exercised against real model construction with real readings – a test must never depend on this host’s actual device state, which changes minute to minute while an agent fleet runs on it.- Parameters:
memory (
SystemMemoryReading|None) – A system-memory reading; measured viaread_system_memory()when omitted.accelerator (
AcceleratorReading|None) – An accelerator reading; measured viaread_accelerator()when omitted.
- Return type:
- Returns:
The composed
HardwareProfile.
- binding_free_bytes(profile)[source]¶
Return free memory in the arena that actually binds a model load, or
None.The one place the arena rule lives, shared by
assess_model_load_contention()(which acts on it) andselect_model_for_role()(which plans against it), so the two can never disagree about which figure binds. A device load is bound by device memory, a measured-accelerator-free machine by system memory, and an unmeasurable accelerator by nothing that may be trusted – which isNone, and is whyUNKNOWNdoes not fall through to system memory: a card this build cannot read may still be holding the memory a load needs.- Return type:
- Parameters:
profile (HardwareProfile)
- probe_local_inference_hardware(profile=None)[source]¶
Report the measured hardware profile as a diagnostic row, unknown shown as unverified.
Follows the shipped direction of
probe_model_runtime_hardware_floor(): an unreadable figure keepsavailabletrue and is rendered asunverified, because a diagnostic must not manufacture a shortfall on a platform it merely cannot measure. The opposite direction governsassess_model_load_contention(), which acts rather than reports and so refuses on the same unknown.- Parameters:
profile (
HardwareProfile|None) – A measured profile; probed viaprobe_hardware_profile()when omitted.- Return type:
- Returns:
A
DependencyStatuson thelocal-inference-hardwarerow.
- class ModelSelection(**data)[source]¶
Bases:
ProvisioningOutcomeWhich model a role resolved to, and everything the operator should know about it.
A planning result, not an admission decision. It answers “which model should this role use on this machine”; whether that model may be loaded right now is
assess_model_load_contention()’s question, asked later and against readings taken at that moment. Keeping the two apart is what lets selection stay useful on a machine whose headroom is momentarily gone.selectedfalse means no catalogued candidate cleared the bars, andruntime_idis thenNonerather than a fallback – naming a model that cannot serve the role would push the failure into inference, where it surfaces as a timeout instead of as a refusal.advisoriesis never empty for an override that carries a licence, context or headroom concern. An override is honoured, because the operator’s explicit setting outranks the catalogue’s preference – but it is never honoured silently.- Parameters:
data (Any)
- role: ModelRole¶
- runtime: ModelRuntime¶
- runtime_id: str | None¶
- candidate: ModelCandidate | None¶
- posture: DeploymentLicencePosture¶
- tier: HardwareTier¶
- binding_free_bytes: int | None¶
- required_context_tokens: int¶
- safety_margin_bytes: NonNegativeInt¶
- override_applied: bool¶
- selected: bool¶
- advisories: tuple[ModelSelectionAdvisory, ...]¶
- property assessable_load: tuple[str, int] | None¶
Return
(runtime_id, required_bytes)when a load can be assessed at all.Nonewhen this role selected nothing, or when the chosen candidate declares no memory requirement. The second case matters as much as the first and is easier to miss: an unknown requirement read as zero flows intoassess_model_load_contention()as the amount the model needs, so the check reports the load ADMITTED on evidence nobody has.Owned here because every caller was re-deriving the same three-part guard – selected, runtime id, candidate – and each one that forgot the fourth part (the requirement itself being optional) fail-opened in its own way. A caller that cannot assess should say so rather than assess against an invented number.
- property licence_advisory: str¶
Return the localised non-commercial licence advisory, or an empty string.
Non-empty exactly when
LICENCE_COMMERCIAL_USE_BARREDis present, which automatic selection can never produce – so this string appearing is itself the signal that an override reached past the commercial posture.
- select_model_for_role(role, *, profile=None, settings=None, override=None, posture=DeploymentLicencePosture.COMMERCIAL, runtime=ModelRuntime.LOCAL_OLLAMA)[source]¶
Resolve
roleto the weakest catalogued model that clears every bar.Bounded from below, never maximised. Candidates are ordered by ascending memory requirement and the FIRST survivor wins, so a machine with headroom to spare still gets the small model. A larger model is an operator’s explicit choice, which is why nothing here ranks on capability above the floor.
Three bars, applied in this order and each for a different reason:
Context window. A model whose window cannot hold the configured request window is excluded on capability, not preference – it cannot do the job at any price.
Licence. Under a
COMMERCIALposture a candidate whose publisher text bars commercial use is not eligible. This is the bar that moved the shipped default.Measured headroom. Requirement plus the configured safety margin against free memory in the binding arena.
An unmeasurable machine does not refuse here, and that is deliberate rather than a softening of the fail-closed rule: refusing to name a model because headroom is momentarily unreadable would break provisioning on exactly the machines that most need to pull one, while the load itself is still failed closed by
assess_model_load_contention()at the act. The selection says so withFIT_UNVERIFIED.- Parameters:
role (
ModelRole) – The role to resolve.profile (
HardwareProfile|None) – Measured hardware; probed when omitted.settings (
Settings|None) – Settings carrying the context window and safety margin; loaded when omitted.override (
str|None) – An operator-named runtime id that outranks selection. Honoured even when uncatalogued or licence-barred, always with advisories.posture (
DeploymentLicencePosture) – The deployment’s licence posture; commercial by default, because that is what this product is.runtime (
ModelRuntime) – Which runtime to resolve against; on-host by default, because the on-host route is the one the product prefers and the one that keeps evidence on the operator’s machine. A hosted runtime skips the headroom bar (nothing runs here) and keeps the capability and licence bars, which apply wherever the prompt is served.
- Returns:
an unsatisfiable role returns
selectedfalse carrying the measured reason and closed outcome.- Return type:
A
ModelSelection. Never raises
- LOCAL_MODEL_PROVISIONING_SERVICE¶
The doctor row id for the local-inference provisioning coherence check.
- probe_local_model_provisioning(*, installed=None, installed_measured=True, settings=None)[source]¶
Detect a PARTIALLY-installed local-inference posture, in both directions.
Local inference has two independent halves: the
llmpackage extra, which an operator installs with pip, and the models themselves, which an operator pulls into the runtime. Either half can be present without the other, and the two broken states are not variations of one problem – they have different causes and different remedies, so a row detecting only one strands every operator who lands in the other with no signal at all.Extra present, no selected model installed. The code path is live and the model it would load is absent. The remedy is a pull.
A selected model installed, extra absent. Multi-gigabyte models occupy disk that nothing can use, typically after a core reinstall. The remedy is the extra’s install command – or a removal, to reclaim the disk.
The two conditions are disjoint by construction: each requires the extra state the other forbids, so neither can be satisfied by the other’s evidence and a check for one can never stand in for the other.
Coherent postures – both halves present, or neither – report available. So does the case where the inventory cannot be read while the extra is ALSO absent: nothing indicates an opted-in local-inference posture, and the detail says plainly that the inventory was not readable so the models-without-extra direction could not be ruled out. When the extra IS present, an unreadable inventory is itself reported, because an operator who opted into local inference and cannot be told what is installed has a real problem rather than an absence.
- Parameters:
installed (
tuple[InstalledModel,...] |None) – The on-disk inventory; read viaread_installed_models()when omitted.installed_measured (
bool) – False when the inventory could not be read.settings (
Settings|None) – Settings carrying the runtime endpoint and role models.
- Return type:
- Returns:
A
DependencyStatusnaming the direction and its remedy.
- probe_optional_extras()[source]¶
Probe each
OptionalExtraintoDependencyStatusrows.The result set is keyed by the same
OPTIONAL_EXTRAScatalogue used byrequire_optional_extra(), keepingaeat config checkand runtime feature guards aligned.- Return type: