core.typedshims
core.typedshims
Outer-ring residue of the typed-shim boundary (dn-inner-outer-core §2.7, K1 / bp-090).
The package's inner init text moved to core/kernel/typedshims/. The shims themselves stay here in
the outer ring: each wraps an untyped third-party surface (lancedb, sknetwork, psutil) that is
inadmissible to the inner base, so the shim modules compute outer. Core imports the shim, never the
raw package. This init is stdlib-import-free so it stays inner by construction (a pure package
marker); the residue shim submodules beside it are the outer machinery.
lancedb
Typed facade over lancedb (type-system-as-core-audit.md §2.5 boundary wrapper).
lancedb ships no py.typed (V2, 2026-07-11), so a raw import launders Any
through every downstream call. This module is the ONE place core touches the raw
package: values coming back from lancedb are pinned to the minimal Protocol
surface the vector store actually uses, so the checked region sees honest types.
Compute/storage-only dependency — embedded, no daemon, no network (Invariant 2).
Do not widen these Protocols speculatively: they describe what core calls today, and each addition should arrive with the call that needs it.
[cross-ref: extension] bp-103 (warrant finding-0176) brings four such calls, all
for VectorStore.supersede_source/rows_for_source: update() (in-place column
write), a FILTERED count_rows(filter), select() (column projection) and
scan(). Additive — every pre-existing caller compiles and behaves unchanged.
Why this file stopped being a pure typing facade. Until bp-103 connect() simply
annotated the raw object and returned it; nothing was wrapped at runtime. scan()
has no counterpart on the raw Table — it is search(None), an overload whose
None arm means "no vector, just filter/project". Absorbing that overload is
precisely what a boundary shim is for (finding-0176: "the shim is the place where the
raw package's overloads are made honest"), and it cannot be done with an annotation
alone. So connect() now returns thin ADAPTERS that add scan() and forward the
rest. The adapters spell every method out rather than forwarding through
__getattr__, because a __getattr__ wrapper would launder Any straight back into
the checked region — the exact hole this module exists to close.
Row = dict[str, object]
module-attribute
ArrowTable
Bases: Protocol
The slice of pyarrow.Table the store consumes from to_arrow().
to_pylist()
TableNames
Bases: Protocol
Result of list_tables() — we read only the name list.
tables
instance-attribute
UpdateResult
Bases: Protocol
Result of Table.update — rows matched-and-written, and the new table version.
[banner: correction] Declared for completeness of the boundary, but the store deliberately
does NOT read rows_updated. UpdateResult is the 0.33 return shape and pyproject.toml:12
pins lancedb>=0.10, a range whose older members returned None from update(); the pin is
outside bp-103's write_scope, so VectorStore.supersede_source derives its count from a
filtered count_rows() instead (bp-103 §11, first parked decision). Raising the floor pin is
the re-entry condition for trusting this field.
rows_updated
instance-attribute
version
instance-attribute
VectorQuery
Bases: Protocol
LanceDB's chained query builder — VectorStore.search (KNN) and .scan() (filter-only).
metric(name)
where(predicate, *, prefilter=...)
select(columns)
limit(k)
to_list()
VectorTable
Bases: Protocol
The slice of a LanceDB table the store calls.
add(rows)
count_rows(filter=...)
delete(predicate)
update(where, values)
to_arrow()
search(vector)
scan()
VectorDB
Bases: Protocol
The slice of a LanceDB connection the store calls.
list_tables()
open_table(name)
create_table(name, *, schema)
drop_table(name)
connect(uri)
Open/create an embedded LanceDB at uri — the sole typed entry point.
psutil
Typed facade over psutil (type-system-as-core-audit.md §2.5 boundary wrapper).
psutil ships no py.typed (V2, 2026-07-11). This module is the ONE place the REPO
touches the raw package; the vitals path and the lifecycle launcher read system
measurements through these typed functions only. Local measurement only — no
network (Invariant 2).
[banner: correction] That first sentence used to read "the ONE place core
touches the raw package", and it was aspirational, not enforced — until bp-106
nothing anywhere (ops/type_gate.py, ops/import_lint.py, scripts/check_imports.py,
the hooks, CI, [tool.ruff]) mentioned typedshims at all, so the rule was a
docstring sentence. bp-105 then imported raw psutil in ops/lifecycle/launcher.py
(finding-0198) and nothing objected — the violation was authored, reviewed, gated and
merged. Two corrections, both from bp-106: the scope is the whole repo, not only
core/ (bp-105's violation was in ops/, which the old wording arguably did not
cover), and the rule is now scanned mechanically by ops.type_gate
(raw_shim_imports), with an inline # typedshim-exempt: <reason> as the only
waiver. See bp-106 §3 Q1 and docs/findings/finding-0223.md.
Exceptions are ABSORBED here, never re-raised (bp-106 §3 Q5). The states a caller
must distinguish — NoSuchProcess, AccessDenied — are psutil types. A facade that
raises them forces every caller to import psutil to name them in an except, which
moves the import while keeping the type dependency: a quarantine in name only. So the
process accessors below return None on any failure. loadavg_1m() set this
precedent before the rule was written.
VirtualMemory
dataclass
The fields of psutil.virtual_memory() the vitals emitter reads.
total
instance-attribute
available
instance-attribute
percent
instance-attribute
virtual_memory()
process_rss(pid)
Resident-set size of pid, in bytes.
cpu_percent()
System-wide CPU percent since the previous call (non-blocking: interval=None).
loadavg_1m()
1-minute load average, or None on a platform without getloadavg.
process_create_time(pid)
Unix epoch seconds at which pid's process was created, or None if unreadable.
None, never an exception: psutil.NoSuchProcess / AccessDenied are psutil TYPES, so a
raising facade would force every caller to import psutil to name them — moving the import
while keeping the dependency. Absorbing them here is what makes the quarantine real.
The launcher's D1 disproof reads this: a process created after its run row's started_at
cannot have written that row (finding-0198).
process_exe_name(pid)
Basename of the binary pid is actually EXECUTING, or None if unreadable.
The BASENAME and not the whole path: an interpreter living under ~/python-projects/ would
otherwise make every binary on that path read as one, and the launcher's D2 disproof ("is this
process a Python interpreter?") could never fire.
⚑ Empty is UNREADABLE, not an answer. psutil returns '' — it does not raise — when a
process's executable cannot be determined, so '' -> None and the caller falls through to its
fallback. Taking '' as the answer would make D2 fire against every such process
(test_an_empty_exe_is_treated_as_unreadable_not_as_an_answer is the mutation pin).
exe() and not cmdline(): on macOS cmdline() raises AccessDenied for a foreign owner
(measured against pid 1) while name()/exe() read fine — and a foreign owner is exactly the
deployed case, the daemon running as the ouroboros principal.
process_name(pid)
pid's process name (e.g. 'launchd', 'python3.13'), or None if unreadable.
This is the comm/argv0 basename, which depends on HOW the process was invoked — under
uv run pytest on Linux it resolves to the console script, not the interpreter
(warrant finding-0211). It is therefore the launcher's FALLBACK, never its first choice; see
_process_identity for why the order is load-bearing in both directions.
name() and not cmdline(), for the same AccessDenied reason recorded on process_exe_name.
Emptiness is deliberately NOT folded to None here, unlike process_exe_name: name() is the
last probe, so '' there is a real (if uninformative) answer that the launcher's D2 reads as
"not a Python interpreter". Folding it to None would silently convert a disproof into
ambiguity, and ambiguity REFUSES (finding-0186) — a behaviour change, not a tidy-up.
sknetwork
Typed facade over sknetwork (type-system-as-core-audit.md §2.5 boundary wrapper).
scikit-network ships no py.typed (V2, 2026-07-11). This module is the ONE
place core touches the raw package — today that is the Louvain cross-check the
reasoning complex runs as a diagnostic beside its spectral partition. Offline
compute only — no network (Invariant 2).
The raw import stays lazy (inside the function): sknetwork is heavy and the
Louvain cross-check is off the live path, matching the call site's prior
behavior in core/complex/spectral.py.
louvain_labels(adjacency, *, resolution=1.0, random_state=0)
Modularity (Louvain) community labels for a (sparse) adjacency — one label per node.
Deterministic under the fixed random_state.