ive harnessed the harness
klbr docs runtime-v2 STATUS.md
12 kB
Markdown
at main

Runtime v2 — implementation status #

Date: September 6, 2026. Status: additive starter; not ready for production cutover. This document supersedes implementation-status claims in the archived design documents, not the user's intended experience. Keep the scratchpad, deliberate speech, social Discord participation, and Rust-mechanism/Python-policy split.

Evidence, not aspirations #

The producer ran python tools/check_runtime.py --report docs/runtime-v2/evidence/checks.json. The report and its adjacent full log are included. A second invocation with --rust is recorded in evidence/full-checks.json: Python passed again, and the requested combined check exited nonzero because Cargo/rustc were unavailable. It does not report a green Rust build. The Python suite contains:

  • 26 tests using the real workbench/hook subprocesses with a test-only host peer.
  • 22 tests for framing, typed Python values, content identity and the exact shipped SQL migration.

All 48 passed. This is not 48 Rust tests. The peer does not exercise SessionRuntime, Rust process timeouts, rusqlite transactions, epoch compare-and-swap, or direct-child reaping.

Seventeen Rust tests are written in klbr-runtime/tests/ (3 protocol, 6 storage/release, 8 session tests). None ran here. Cargo, rustc, rustfmt, Clippy and Nushell were unavailable. Rust source was reviewed manually, but syntax/type errors remain possible until compiled. The original Cargo.lock was given a local klbr-runtime package stanza; the helper verifies that its named dependencies uniquely resolve to existing lock entries. That is not Cargo resolver validation. cargo test --locked is a first-agent gate, not an already-passed claim.

Python tests used Python 3.13.5 and Python-linked SQLite 3.46.1. The latter is used only for serial, in-memory schema tests. The proposed Rust deployment checks the actual SQLite runtime for the documented WAL-reset fix (3.51.3+, or the 3.50.7/3.44.6 fixed branches). Do not relax this guard to make an older test host green. Verify the bundled library on the machine that first runs Rust. See https://sqlite.org/wal.html for the upstream advisory.

No real model calls, Discord traffic, production database migration, NixOS deployment, resource benchmark, backup restore, filesystem fault injection or long-duration soak was run.

What is implemented in source #

Python runtime, executed in tests. Separate workbench/hook process roles share bounded JSON framing over a Unix-domain socket. Workbench globals and future flags survive cells; there is top-level await, expression display, typed outcomes and background asyncio work. The control channel is independent of stdout/stderr. Python output has byte/record bounds; late background output retains an origin instead of becoming the next cell's output. SystemExit and ordinary exceptions become cell outcomes; native process death remains death.

local.send is an explicit RPC, not print. runtime.wait is a terminal yield, not a long Python sleep. Execution scopes expire, including references inherited by background tasks. Late replies after cancellation do not satisfy another execution's request. The SDK offers hooks.list and hooks.describe. Hook handlers receive typed snapshots and return typed decisions; no active effect scope is supplied to the hook role.

Rust host, authored but unexecuted. Worker supervises the real Python executable, validates handshake/identity, keeps a bounded request queue and diagnostic tails, enforces absolute deadlines and invalidates a broken generation. A separate control path stops the worker without asking a hook. Mid-exchange cancellation kills the process instead of trying to reuse a potentially half-read frame. The first Rust stop implementation is hard-stop; Python supports cooperative interruption, but host-driven in-place reuse is not yet shipped.

Store opens a new-format SQLite file, takes a cooperating single-owner lock, and routes transactions through bounded blocking tasks. Dropping the caller does not cancel an accepted SQLite write or release its owner lock before the write finishes. Originals are append-only. Source keys deduplicate within a session, not by identical content. Unfinished executions are reconciled on reopen without replaying Python. The old memory database is refused, not implicitly migrated.

Local sends have proposal, confirmed or held records. Required review runs outside any transaction/session mutation lock in the separate hook worker. Final local publication, receipt and review trace commit together. Here confirmed means durably published to the operator lane, not that a client connected or a human read it. There are no remote effects in this implementation, so the local ledger must not be advertised as a Discord outbox.

Host waits check pending input in the same transaction as changing wait state; admission wakes an existing wait. Persisted deadlines can be consumed idempotently with wake_due. There is no autonomous scheduler calling that function yet. Input consumption is an explicit host API, not automatically inferred from a cell or scratchpad.

SessionRuntime binds these mechanisms into a host-side slice. It owns accepted execution rather than the caller's connection, pins a policy revision for each cell and its sends, and rejects a second foreground cell. Hard interruption can be followed by a fresh workbench; shutdown cannot silently revive it. Hook-only activation starts and checks a candidate worker before a database epoch switch. Old cells retain their policy reference; compatible workbench globals remain intact. At most one activation is admitted per session at a time.

The two actual hook slots #

attention.plan: Python defaults prioritize operator input and directed Discord-shaped inputs, and propose an eight-second ambient defer. Rust validates results, including operator priority. It is an exposed/tested policy primitive, not yet integrated into real ingress or a model scheduler. Source classification must come from a future authenticated adapter, never from an arbitrary text label supplied by an external participant.

delivery.review: Allow or hold an explicit local send. A handler exception, malformed result or unavailable/timed-out worker causes a held operation. No accidental approval. This hook is connected to the authored Rust send path, and its Python side was executed.

No empty registrations were added for every future design slot. Ordered transforms and durable observers require their own state/commit contracts and are deliberately absent.

Limits that must remain visible #

  • Output beyond the preview bound is discarded with a truncation count, not spooled to an artifact. Therefore this slice is not a lossless-output or LCM implementation.
  • Background tasks are ephemeral. Direct filesystem/network/subprocess effects are not transactional and are never automatically replayed. No heap checkpoint exists.
  • Processes are trusted same-user Unix processes, not sandboxes. The host clears the worker environment to a limited set, but filesystem access can still expose user credentials. No cgroup/RLIMIT quotas or process-group descendant cleanup are implemented.
  • A deadline kills the direct Python child. Descendant process ownership needs an explicit deployment/job design before untrusted or unattended arbitrary workloads.
  • The hook worker is not automatically restarted after a deadline. Subsequent required reviews hold until a fresh policy worker is activated/restarted. Core control stays usable.
  • Candidate import/signature/handshake validation is not semantic validation. A Python handler returning an invalid decision can pass startup and fail at invocation, then hold. There is no complete draft/publish/test UI or SDK, persisted last-good boot fallback, or durable observer state migration/rollback workflow yet.
  • Source snapshots cover a small .py/.json/.md tree, reject symlinks, and exclude bytecode by requiring clean source. Published bytes must be protected by deployment permissions. Hash verification is not a defense against a malicious same-user writer during import. Release files/directories are synced before activation, but storage crash durability was not tested. No garbage collection or environment fingerprint/lock migration exists yet.
  • One SessionRuntime per session must be owned by a future daemon registry. Global worker budgets, fairness, authentication, reconnect replay and a permanent service lifecycle are not provided by the library alone. Database uniqueness is not that whole registry.
  • SQL state transitions and Rust supervision still need real integration/fault tests. Manually invoking the migration with Python is not a substitute for them.

Boundaries preserved for the next agent #

The legacy klbr-core, klbr-daemon, klbr-discord, klbr-ipc, UI and production schema are unchanged. Root Cargo files merely include the new crate and its existing dependencies. The new crate is separate on purpose so it can be compiled/tested before touching the old runtime. It is not intended to become a second permanent competing orchestration dialect.

Addendum: the instruction head and its revisions #

The sections above describe the pack as its producer left it. This tree has since had the instruction head built out and executed. These checks ran here, with this machine's toolchain:

  • cargo nextest run --workspace --no-fail-fast: 199 tests, 199 passed. cargo fmt --all and cargo clippy --workspace --all-targets are clean.
  • The Python suite in a bare 3.11 interpreter (no site-packages): 125 tests passed. Run it that way: test_remote_sdk.test_closure_serialization_failure_is_not_source_fallback asserts a behaviour that only holds where dill is not importable, so a venv that happens to carry dill fails a test that is not about this work.
  • A live session (headercheck, real provider route, session-local SQLite) recorded its instruction change as form: diff, one 2-line hunk, 340 bytes of patch for 8451 bytes of instruction text. In the same turn, runtime.instructions() returned exactly the digest the host had just recorded for the current text.
  • The failure mode is in that database too. Revision 342 was written by an earlier build that emitted per-source patches against a base whose sources were never recorded. It does not reconstruct, so the chain stops at revision 328 and the next change is patched against that text instead. Nothing ran under a text nobody wrote; the cost of a broken link is a larger patch, which is the trade the design names.

What the head does now, in one paragraph: a transcript pins the text it starts under, and a later change is appended as an observation at the sequence where it was noticed, rendered as a verified patch. The head's bytes move only at session_start and at a fold that covered the observation supporting it. Reading the head and recording what it depends on are one host call, so a request cannot run under a text no later request can reproduce. runtime.inspect reports the pinned and this transcript runs under - instructions.head_digest, head_reason, head_pinned_at_ms, revisions_since_head - beside instructions.known_digest, the newest text the transcript can reconstruct. runtime.instructions resolves that chain for a reader that wants the exact text. Both read the transcript's own records, so neither asks the model to hash a context it cannot reproduce byte for byte.