Integrate runtime-v2 starter baseline and verification tooling
1432 unmodified linesExpand all14331434143514361437143814391440144114421443144414451446144714481449145014511452145314542502 unmodified linesExpand all1432 unmodified linesExpand all "serde_json",]
[[package]]name = "klbr-runtime"version = "0.1.0"dependencies = [ "anyhow", "rusqlite", "serde", "serde_json", "sha2 0.10.9", "tempfile", "tokio", "uuid",]
[[package]]name = "lazy_static"version = "1.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"2502 unmodified linesExpand all1234567843 unmodified lines[workspace]members = [ "klbr-core", "klbr-runtime", "klbr-bench", "klbr-daemon", "klbr-discord", "klbr-ipc",43 unmodified lines12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485# klbr runtime starter — code before the next plan
This is a **non-production implementation slice** of the Rust-engine / Python-policy design.It is additive: the existing daemon, provider adapters, Discord integration, UI and legacymemory database have not been migrated or replaced.
**Validation:** 48 Python tests passed in the producing environment. These exercise realPython subprocesses, the exact SQL migration, and protocol fixtures. **Rust was not compiled,formatted, linted or executed:** the environment has no Cargo/rustc, and compiler downloadwas unavailable. Seventeen Rust tests are included but unrun. Read that distinction literally.
Start with [implementation status](docs/runtime-v2/STATUS.md) and the[next-agent handoff](docs/runtime-v2/HANDOFF.md). The [wire contract](docs/runtime-v2/PROTOCOL.md)explains the boundary without making you infer it from tests.
## Run what is testable without Rust
From the repository root, including from Nushell:
```textpython tools/check_runtime.py```
Python >=3.11 and a Unix platform are required. No pip installation, provider key, Discordbot, network service or dependency resolver is used by these Python tests.
For the first real Rust validation, use a machine with Cargo/rustc, the C toolchain needed bybundled SQLite, and the repository's toolchain requirements:
```textpython tools/check_runtime.py --rust --format --report /tmp/klbr-checks.json```
`--format` explicitly formats only `klbr-runtime`. Without it, rustfmt runs in check mode.The original Linux Cargo configuration expects clang and the wild linker. To use `cc`instead, without changing that configuration:
```textpython tools/check_runtime.py --rust --format --portable-linker --report /tmp/klbr-checks.json```
A Rust-requested check **fails** when Cargo/rustc are unavailable; it never reports them aspassed/skipped inside an otherwise green integration result. Missing crate sources mayneed the network on the validating machine. Cargo.lock's new local-package entry was editedand structurally checked here, not regenerated by Cargo. No new registry dependencies wereintroduced by this crate.
After Rust validation:
```textcargo run --locked -p klbr-runtime --example workbench```
The example makes a temporary **new-format** database, evaluates cells, explicitly publishesone local message, switches to a holding Python guard without discarding a variable, andyields. It uses no model and sends nothing to Discord. With the portable linker overridein Nushell, the equivalent launch is:
```nuwith-env { CARGO_ENCODED_RUSTFLAGS: "", CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER: "cc" } { cargo run --locked -p klbr-runtime --example workbench}```
## The actual source map
| Path | Responsibility ||---|---|| `klbr-runtime/src/protocol.rs` | Typed IDs, framed/versioned messages, role/outcome validation || `klbr-runtime/src/worker.rs` | Dedicated control socket, bounded process actor, deadlines and stop path || `klbr-runtime/src/store.rs` and `migrations/` | Separate SQLite format, durable admission, executions, local effects and waits || `klbr-runtime/src/session.rs` | Host-owned execution, explicit sends through a separate guard, hook epoch pinning || `klbr-runtime/src/hooks.rs` | Two real decision slots; fail-closed delivery review || `klbr-runtime/src/behavior.rs` | Content-addressed snapshots, separate from database activation authority || `python/klbr-runtime/src/klbr_runtime/` | Persistent evaluator and hook-worker roles || `python/klbr-runtime/src/klbr/` | `local.send`, terminal `runtime.wait`, typed hooks and discovery || `behavior/` | Editable Python defaults for attention and delivery || `tests/runtime-fixtures/` | Shared wire values and source fingerprint || `python/klbr-runtime/tests/peer.py` | **Test double only** for the protocol host; not a second production orchestrator || `klbr-runtime/tests/` | Authored, unrun Rust/store/end-to-end integration tests |
There is no LCM, provider loop, client adapter, Discord rewrite, RLM, tree-sitter port,durable observer dispatcher or Python behavior-publishing SDK in this slice. The host-siderevision activation API exists; the complete autonomous edit/test/publish workflow does not.Do not mistake an available hook name in the design documents for an implemented hook.1{"version":1,"hooks":{"attention.plan":"klbr_hooks.defaults:attention","delivery.review":"klbr_hooks.defaults:delivery"}}123456789101112131415# New runtime slice
Read `../RUNTIME-V2.md`, `../docs/runtime-v2/STATUS.md` and `HANDOFF.md` first.This crate is an additive replacement boundary, not yet the live daemon.
The producer had no Rust toolchain. Compile, format and run the real Rust tests beforeexpanding the design; do not cite the Python peer tests as Rust integration coverage.Keep core invariants in Rust and ordinary policies in editable Python. No SQL transactionor domain mutation lock across a hook. No automatic replay of arbitrary cells. Preservescratchpad/workbench-output versus explicit speech. A missing required guard holds its effect.Hook-only replacement pins in-flight cells and must not wipe a compatible workbench namespace.
Add hooks only with their real domain, typed input/result and failure contract. Do not addan empty facade for every future slot. The Python test peer is not production orchestration.Do not migrate or replace the old memory DB until a deterministic importer/cutover is tested.12345678910111213141516[package]name = "klbr-runtime"version = "0.1.0"edition = "2021"rust-version = "1.89"publish = false
[dependencies]anyhow.workspace = truerusqlite.workspace = trueserde.workspace = trueserde_json.workspace = truesha2.workspace = truetempfile.workspace = truetokio.workspace = trueuuid.workspace = true123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129#!/usr/bin/env python3"""Run starter checks without a shell or package installation.
Default: real Python subprocess + shared schema/fixture tests.--rust: also run the authored Rust tests. Missing Cargo is an ERROR, not a skip.--format: explicitly allow rustfmt to edit only the new Rust crate."""from __future__ import annotations
import argparseimport datetimeimport jsonimport osfrom pathlib import Pathimport platformimport shutilimport sqlite3import subprocessimport sysimport timeimport tomllib
ROOT = Path(__file__).resolve().parents[1]
def static_contracts() -> dict: """Only manifest consistency, not dependency resolution or Rust compilation.""" workspace = tomllib.loads((ROOT / "Cargo.toml").read_text()) lock = tomllib.loads((ROOT / "Cargo.lock").read_text()) assert "klbr-runtime" in workspace["workspace"]["members"] packages = lock["package"] entry = next(p for p in packages if p["name"] == "klbr-runtime") for dependency in entry["dependencies"]: parts = dependency.split() matches = [p for p in packages if p["name"] == parts[0] and (len(parts) == 1 or p["version"] == parts[1])] assert len(matches) == 1, f"ambiguous/missing lock entry: {dependency}" crate = tomllib.loads((ROOT / "klbr-runtime/Cargo.toml").read_text()) assert set(crate["dependencies"]) == {d.split()[0] for d in entry["dependencies"]} tomllib.loads((ROOT / "python/klbr-runtime/pyproject.toml").read_text()) return {"status": "passed", "meaning": "manifest/lock-reference consistency only; Cargo resolver not run"}
def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--rust", action="store_true", help="run Cargo tests and lint checks") parser.add_argument("--format", action="store_true", help="run rustfmt in write mode; requires --rust") parser.add_argument("--portable-linker", action="store_true", help="override the existing Linux clang/wild config with cc") parser.add_argument("--report", type=Path, help="write machine-readable evidence and separate step logs") args = parser.parse_args() if sys.version_info < (3, 11): parser.error("Python >=3.11 is required") if args.format and not args.rust: parser.error("--format requires --rust") if os.name != "posix": parser.error("this first slice requires Unix-domain sockets (Linux/macOS)")
environment = os.environ.copy() environment["PYTHONPATH"] = str(ROOT / "python/klbr-runtime/src") environment["PYTHONDONTWRITEBYTECODE"] = "1" environment["KLBR_PYTHON"] = sys.executable if args.portable_linker: # CARGO_ENCODED_RUSTFLAGS takes precedence over .cargo/config.toml. # Empty intentionally clears --ld-path=wild, independently of Nushell. environment["CARGO_ENCODED_RUSTFLAGS"] = "" environment["CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER"] = "cc"
report = { "created_at_utc": datetime.datetime.now(datetime.timezone.utc).isoformat(), "python": sys.version, "platform": platform.platform(), "python_sqlite": sqlite3.sqlite_version, "python_sqlite_scope": "serial in-memory migration tests only; not runtime WAL qualification", "cargo_available": shutil.which("cargo") is not None, "rustc_available": shutil.which("rustc") is not None, "rust_checks_requested": args.rust, "steps": [], } try: report["manifests"] = static_contracts() except (AssertionError, ValueError, StopIteration, KeyError) as error: report["manifests"] = {"status": "failed", "error": str(error)}
def run(name: str, command: list[str]) -> None: print(f"\n== {name} ==", flush=True) started = time.monotonic() try: completed = subprocess.run(command, cwd=ROOT, env=environment, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, errors="replace", check=False) code, output = completed.returncode, completed.stdout except OSError as error: code, output = 127, str(error) print(output, end="" if output.endswith("\n") else "\n", flush=True) step = {"name": name, "argv": command, "exit_code": code, "elapsed_seconds": round(time.monotonic() - started, 3)} if args.report: args.report.parent.mkdir(parents=True, exist_ok=True) log = args.report.with_name(f"{args.report.stem}-{name}.log") log.write_text(output) step["log"] = log.name report["steps"].append(step)
run("python", [sys.executable, "-B", "-m", "unittest", "discover", "-s", "python/klbr-runtime/tests", "-v"]) if args.rust: if not report["cargo_available"] or not report["rustc_available"]: report["steps"].append({"name": "rust", "exit_code": 127, "reason": "Cargo/rustc unavailable; no Rust tests or integration checks ran"}) else: run("rust-version", ["rustc", "--version", "--verbose"]) run("rustfmt", ["cargo", "fmt", "-p", "klbr-runtime"] + ([] if args.format else ["--", "--check"])) run("rust-tests", ["cargo", "test", "--locked", "-p", "klbr-runtime", "--all-targets"]) # Warnings are visible; denying all Clippy style lints before the # first toolchain pass would hide more useful compilation evidence. run("clippy", ["cargo", "clippy", "--locked", "-p", "klbr-runtime", "--all-targets"]) else: report["rust_status"] = "not run; pass --rust on a machine with Cargo/rustc" passed = report["manifests"]["status"] == "passed" and all(s["exit_code"] == 0 for s in report["steps"]) report["requested_checks_passed"] = passed if args.report: args.report.parent.mkdir(parents=True, exist_ok=True) args.report.write_text(json.dumps(report, indent=2) + "\n") print(f"\nEvidence: {args.report}") return 0 if passed else 1
if __name__ == "__main__": raise SystemExit(main())1"""Editable policies. Durable state belongs to the Rust host."""1234567891011121314151617181920"""Compatibility defaults: optional ambient participation, deliberate speech."""from klbr.hooks import (AttentionDecision, AttentionRequest, DeliveryDecision, DeliveryRequest, HookContext)
def attention(request: AttentionRequest, context: HookContext) -> AttentionDecision: match request.source: case "operator": return AttentionDecision.wake("operator") case "discord.dm" | "discord.mention": return AttentionDecision.wake("directed") case "discord.ambient": return AttentionDecision.defer(8) raise ValueError("unknown source; never silently discard it")
def delivery(request: DeliveryRequest, context: HookContext) -> DeliveryDecision: # Additional policy belongs here. Rust still validates the destination, # execution authority and receipt; allowing is not evidence of delivery. return DeliveryDecision.allow()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158# Handoff: continue from the source, not from a blank page
Read `RUNTIME-V2.md`, `STATUS.md`, and the tests before expanding the scope. The archivedv2 plans retain the product direction; they are not evidence of implemented behavior.The uploaded Lucid pack is retained as `design/lucid-code-skill-pack-main.tar.gz`; the originalv2 plan, hook spec and behavior source trace are beside it. Read those contract/skill sourcesbefore changing the architecture.
This starter covers parts of plan slices 1, 2, 3 and 3a, plus a narrow local-effect/wait sliceof 4 and host-side hook activation from 9. No numbered slice should be marked fully complete.
## First task: establish the Rust baseline
Use the user's actual toolchain/dev environment. Run:
```textpython tools/check_runtime.py --rust --format --report /tmp/klbr-runtime-checks.json```
Use `--portable-linker` when clang/wild are absent. It overrides the original repositoryconfiguration for this command only. Do not rewrite the existing flake just to make atemporary machine's linker happy. Do not use a Bash-only invocation in user-facing instructions;the helper launches subprocesses directly and works from Nushell.
Fix compilation, formatting, real integration failures and lockfile resolution beforeadding features. The producer could not run Cargo, so this is actual work, not ceremonialverification. Record exact Rust, Cargo, Python and linked SQLite versions. The SQLite guardis intentional; validate a fixed runtime rather than weakening the guard. If a dependencyneeds an update, make it explicit and regenerate Cargo.lock on this machine.
Rust test entrypoints:
- `tests/protocol.rs`: shared envelopes, framing failures, IDs, role/output boundaries.- `tests/store.rs`: snapshot hash, source/session dedupe, owner lock, legacy DB refusal, local receipt identity, wait/input ordering, reopen without replay.- `tests/session.rs`: real Rust/Python execution, separate review, fail-closed guards, invalid activation, blocked worker deadlines, admission during blocked hooks, pinned in-flight revisions, independent stop, and terminal shutdown.
Run the `workbench` example only after these checks. It is a no-network demonstration,not an agent or an interactive client. The Python peer is a test double, and must not bepromoted into a production Python orchestrator to sidestep a Rust integration problem.
## Next coherent change: daemon-owned session and inbox coordinator
Add a single-owner registry in the existing daemon. The integration should own one newruntime `Store` and one `SessionRuntime` for each active session. Preserve the current one-rootagent across local and Discord conversations; a channel is routing provenance, not a newagent by default. Use a separate new runtime database filename and do not open the legacymemory DB through this constructor.
Durably accept authenticated input before acknowledging it. Pass a canonical source dedupekey, source kind, immutable conversation identity, author and receipt timestamps. Admissionmust not wait for a Python hook. Channels/notifications are wake signals, not the only data.Wire `attention.plan` only after admission. A failure retains pending work; the basic operatorcontrol path never requires a successful policy callback.
Do not call `acknowledge_inputs` merely because attention was planned or a cell ran. Add atransactional turn/attention-frame record linking the consumed input IDs, routing handles,context epoch and policy revision. Acknowledgement is a consequence of this accepted frame.The current API comment marks this boundary rather than pretending it is implemented.
Provide operator stop and activation/recovery endpoints independently of the model. Protectthese endpoints. The library's `shutdown` is not by itself a complete daemon drain protocol;await accepted host tasks and finish their durable outcomes before exiting the service.
Acceptance: burst inputs during blocked work, cancel/replace a kernel, and still find eachaccepted input and its disposition. No remote sends in this stage.
## Then wire the model loop, scratchpad and the existing client
Adapt the existing provider boundary instead of copying the old memory/tool coupling.Persist complete provider blocks/tool-call IDs before execution. Use one model-visiblePython tool. Ordinary assistant text goes to typed scratchpad records, not automatic speech.Partial stream text remains partial. Preserve the user's scratchpad diagnostics withoutmisrepresenting that text as delivered to a conversation.
`local.send` already has a host-side durable publication contract. Teach the client torender that lane separately from scratchpad and cell output, using event sequence cursors.A reconnect replays completed durable records; transient token animation can remain lossy.Add protocol adapter tests rather than reexporting provider/storage types into `klbr-ipc`.
Replace tool-name string matches (`wait_and_continue`, `local_send`, restart controls, etc.)in the new loop with explicit outcomes/commands. Do not leave the old tool registry activeunder the new Python executor. Add `model.plan`, `context.prepare` and `turn.next` when thoseactual domains exist, with documented failure semantics and editable Python defaults.
Acceptance: scratchpad + cells + one explicit send yields one conversational message; aterminal wait ends code, resumes only from a new wake/model boundary, and consumes no idleinference loop. Persisted provider sequences remain valid after interruption.
## Build complete revision editing around the existing activation primitive
The next SDK work is `behavior.draft/publish/activate/rollback` and `hooks.bind/test/trace`,not a new loader. Existing code already snapshots sources and activates host-side candidates.Stage normal source files and tests in a writable draft, retain the base epoch, run trustedfake-effect validation, publish immutable content, then call the existing guarded switch.The agent should be able to edit ordinary hook/skill code without touching Rust.
Do not accept a candidate's own boolean claim that it passed trusted checks. Add environmentand component fingerprints so a shared dependency change replaces every affected processrole. Keep source-only compatible hook activation separate from workbench replacement.
Expand startup from “fail on corrupt active snapshot” to a persisted last-good recovery paththat does not need user hooks to succeed. Expose failed candidate diagnostics and invocationtrace references. Do not replay old events solely because a handler revision changed.
Acceptance: the agent edits a hook through the SDK, tests/activates it, keeps a live workbenchobject, and sees new behavior in the next cell. An in-flight cell remains pinned. A badcandidate or broken active revision remains repairable without model cooperation.
## Discord, LCM, then durable jobs/children
Bring the existing Discord/Twilight transport behind the new domain commands; preserve thesocial semantics recorded in the design's behavior companion. Add canonical conversations,immutable attention frames, per-effect destinations/reply anchors, and an outbox with honestpending/attempting/confirmed/failed/unknown states. Do not generalize the current *local*atomic publication into a claim of atomic remote send. Only consume reply state when actualreceipt evidence permits it. Keep ambient silence and explicit ignore/reaction decisions.
For LCM, first replace discarded large output with artifact spooling. Then add immutablestructured session items, chronological summary coverage, transactional context replacement,lexical retrieval and exact source reads. Maintain provider-valid tool groups. Preserve thedifference between a scratchpad draft and a confirmed message across summaries. Compactionmust not depend on reflection, embeddings, skill editing, or note-garden reconciliation.The current append-only event table is a useful substrate, not a completed context manager.
For jobs/RLM, add explicit identities, revision/workspace pinning, budgets and completionnotifications. Never implement durability by pickling a coroutine or replaying arbitrarycells. Add durable observers only with an atomic acknowledgement/state/proposed-commandcommit and stable causation/action identities. The current prototype deliberately does notimplement generic transforms/observers with vague dictionaries and no durability contract.
Move useful tree-sitter vocabulary into Python skills using maintained Python bindings.Preserve version-bound source/symbol ranges and checked patches rather than recreating eachold JSON tool as a Python function. No tree-sitter capability was ported in this starter.
## Review/failure work before unattended deployment
Process groups/cgroups and tracked command ownership are needed before arbitrary subprocesswork can be cleaned up reliably. Today only the direct Python child is killed. Add boundedartifact disk use and input/output backpressure, auth on operator APIs, global process andmodel budgets, current runtime health, hook backlog diagnostics and explicit cleanup policy.
Exercise actual kill/fault windows: SQLite commit-before-notify; local publish-before-reply;wait-before-wake; hook activation during an execution; corrupt active release; truncatedcontrol frames; failed artifact writes; a handler catching cancellation; and daemon shutdownwith an accepted execution still completing. Verify backups with artifacts/releases beforecutover. Keep the old production database and owner stopped, never two live senders.
## What was deliberately not done here
No old production paths were deleted, no key was used, no migration ran against user state,and no existing note was reinterpreted as truth. No Git remote or live beads tool wasavailable in the supplied archive/environment. No commits were pushed or issue IDs invented.Use the repository's actual issue workflow when continuing; this file is an artifact handoff,not a replacement issue database. Source was written anew for this slice, not copied fromPrime's implementation. Consult upstream licenses before later borrowing source.123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138# Runtime control protocol v1
Implementation authority: `klbr-runtime/src/protocol.rs` and the Python runtime, checkedagainst `tests/runtime-fixtures/envelopes.json`. This protocol is local to the starter,not a claimed compatible implementation of Prime or the old klbr IPC protocol.
## Transport and bounds
One dedicated Unix-domain stream socket per worker, located in a private temporary directorycreated by the host. A random startup token binds the expected subprocess handshake. Thisis distinct from stdout/stderr, and is not a network-accessible service. Processes run withsame-user trust; the token and framing are not an OS sandbox.
Each frame is four unsigned big-endian bytes giving the UTF-8 JSON payload length, followedby that many bytes. Length must be 1..1,048,576. All outer fields are required:
```json{"version":1,"session_id":"root","generation":"g-1","message":{"kind":"shutdown"}}```
Identifiers are 1..128 ASCII letters/digits/underscore/dot/hyphen. Unknown envelope and typedmessage fields fail. Version, generation and session mismatches fail. NaN/Infinity are notvalid wire numbers. Python's frame decoder rejects duplicate JSON object keys; Rust derivesreject duplicate typed fields. Arbitrary nested `serde_json::Value` payload maps are not yeta duplicate-key equivalence guarantee between parsers; strengthen the shared decoder beforeaccepting third-party wire producers. This is a trusted local protocol, not a claim of afully fuzzed hostile-input parser.
On EOF, bad framing, timed-out/abandoned Rust exchange, or identity mismatch, invalidate theconnection/generation. Never attempt to resume a new frame after a partial payload. Outputlimits: cell source <=262,144 bytes; returned text <=65,536 bytes across <=256 records;error text <=65,536 bytes. The Python runtime currently returns output on completion, not asa continuous stream. Excess is counted and discarded. Raw/native stdout/stderr are continuouslydrained by the Rust worker into separate bounded 8 KiB diagnostic tails.
## Message vocabulary
`hello`: token, role (`workbench` or `hooks`), revision (null for workbench), and slots(empty for workbench; exactly `attention.plan`, `delivery.review` for this hook worker).
`execute`: operation `id` and `code`, allowed in workbench only. One foreground operationper worker. Namespace and future flags persist. The final expression has a displayed repr;`_` retains its last non-None value. Evaluation is arbitrary CPython, not sandboxed Python.
`invoke`: operation `id`, exact `slot`, typed domain `input`, hook role only. A handler is animportable source entrypoint, not a pickled closure. The workbench is never made to executean authoritative send-review hook behind the cell waiting for that review.
`host_request`: request `id`, `execution_id`, and `request`. Implemented request variants:
```json{"method":"local.send","text":"hello"}{"method":"runtime.wait","seconds":null,"reason":"waiting for input"}{"method":"hooks.list"}{"method":"hooks.describe","slot":"delivery.review"}```
`host_reply` repeats request/execution identity and contains either`{"kind":"ok","value":...}` or `{"kind":"error","code":"...","message":"..."}`.The worker host enforces a maximum of 128 requests per foreground cell. Pending repliesare correlated by identity, not arrival order. The Python reader keeps running while a cellawaits an RPC. Late replies after cancellation are discarded rather than satisfying anothercell's request.
`completed` repeats the operation `id` with one of:
```json{"kind":"cell","status":"ok","output":[{"stream":"result","text":"42"}],"truncated_bytes":0,"error":null}{"kind":"hook","value":{"action":"allow"}}{"kind":"failed","error":"worker-level failure description"}```
Cell statuses: `ok`, `error`, `yielded`, `interrupted`. Output streams: `stdout`, `stderr`,`result`. Worker death has no invented completion; the host creates a failed/interruptedrecord from its own observation. A worker cannot claim a committed yield without the hosthaving accepted the wait.
`interrupt` targets one operation ID. Python supports cooperative task cancellation; thecurrent Rust management API conservatively terminates the generation instead. `shutdown`requests clean worker exit. Rust retains the final hard-stop authority when code blocks orcatches cancellation. Only the direct child is currently managed, not all descendants.
## Scope, waiting and receipts
Host effects require the current live execution plus matching generation. Background tasksinherit an origin for diagnostics, but that scope expires when the foreground cell ends.After terminal wait, catching the interpreter sentinel does not restore scope authority.The host also rejects further requests from a yielded execution.
Wait seconds are null or finite >0 and <=600. The host records the deadline/state and checksfor already-pending input in one transaction. No suspended Python continuation is persisted.Wakeups start a future model/cell boundary; code below `await runtime.wait(...)` does notrun normally. The caller must not mistake ordinary `asyncio.sleep` for this durable wait.
Local send receipt is `effect_id`, `status` (`confirmed` or `held`), `event_id` (nullable),and `reason` (nullable). Confirmed means a durable operator-lane event exists. Held is notapproval, queue-success or proof anyone received the message. There is no Discord transportin this slice. A retry with the same execution/request identity returns the existing receipt;a deliberately new request can send identical text again.
## Implemented decision slots
`attention.plan` input: positive event_id, host-classified source (`operator`, `discord.dm`,`discord.mention`, `discord.ambient`), nonnegative receipt timestamp. Result: wake with priority,defer with bounded seconds, or ignore with reason. Operator attention cannot be suppressedor forged from an external source by returning a priority. This is a policy API awaitingauthenticated ingress/model-coordinator integration.
`delivery.review` input: effect_id, destination=`operator`, bounded message text. Result:`allow` or `hold` with a reason. Any invalid/unavailable required review holds the send.No host-effect scope is given to a hook. Additional domain hooks should be added alongsidethe owning implementation, not as no-op placeholders.
The host's two-second invocation budget includes queueing. One bounded actor serves a hookworker; a hung callback can delay other calls until timeout invalidates that generation.There is no separate per-handler scheduling or automatic hook restart yet.
## Source revisions and activation
A manifest contains version 1 and exactly the two implemented entrypoints:
```json{"version":1,"hooks":{"attention.plan":"klbr_hooks.defaults:attention","delivery.review":"klbr_hooks.defaults:delivery"}}```
Handlers receive `(request, context)` and return the corresponding SDK decision dataclass,synchronously or asynchronously. Startup validates the import/call signature, not semanticbehavior. Imports themselves are trusted executable code and can fail or block.
Source identity hashes sorted POSIX relative filenames and exact bytes. For each file feedSHA-256: u64BE name-byte-length, UTF-8 name, u64BE content-length, content. Source snapshotsallow `.py`, `.json`, `.md`, maximum 128 files/2 MiB, no symlinks. Run source tests with `-B`or put caches outside the draft. The shared `behavior.json` fixture fixes the initial digest.
Database epoch is activation authority; a path/symlink is not a second active pointer. Candidatehandshake precedes the compare-and-swap switch. Each executing cell pins its policy object,so later hooks in that cell use the same revision even during activation. A hook-only changedoes not replace the workbench. A broader environment change is not yet implemented.123456789101112# Source provenance
The base is the user's supplied `klbr.tar`, SHA-256 `6c7e4e0b7a1d1b860017d07b1f02b5c0adc708ccbcb3693c53bccd509841cd8c`.
The new code was authored for this implementation slice. No Prime runtime source was copied.The uploaded Lucid pack and v2 architecture/hook plans informed the implementation. Archivedplans are in `design/`; current truth is in `STATUS.md` and the actual source/tests.
The delivery includes a full modified source archive and a Git-compatible patch against thisexact supplied snapshot. No remote repository was modified. Temporary build-maker scripts andPython bytecode are not part of the deliverable. No compiler installation succeeded in thisenvironment; the included evidence explicitly separates Python checks from unrun Rust tests.123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133# 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 Discordparticipation, 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` isrecorded in `evidence/full-checks.json`: Python passed again, and the requested combinedcheck exited nonzero because Cargo/rustc were unavailable. It does not report a green Rustbuild. 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`, Rustprocess 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 verifiesthat its named dependencies uniquely resolve to existing lock entries. That is not Cargoresolver 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 forserial, in-memory schema tests**. The proposed Rust deployment checks the actual SQLiteruntime 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 themachine 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 boundedJSON 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 longPython 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 typeddecisions; 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, enforcesabsolute deadlines and invalidates a broken generation. A separate control path stops theworker without asking a hook. Mid-exchange cancellation kills the process instead of tryingto 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 routestransactions through bounded blocking tasks. Dropping the caller does not cancel an acceptedSQLite 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 executionsare reconciled on reopen without replaying Python. The old memory database is refused, notimplicitly migrated.
Local sends have proposal, confirmed or held records. Required review runs outside anytransaction/session mutation lock in the separate hook worker. Final local publication,receipt and review trace commit together. Here confirmed means durably published to theoperator lane, **not** that a client connected or a human read it. There are no remote effectsin 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; admissionwakes 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 explicithost API, not automatically inferred from a cell or scratchpad.
`SessionRuntime` binds these mechanisms into a host-side slice. It owns accepted executionrather 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 workerbefore a database epoch switch. Old cells retain their policy reference; compatible workbenchglobals 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-shapedinputs, and propose an eight-second ambient defer. Rust validates results, including operatorpriority. It is an exposed/tested policy primitive, **not yet integrated into real ingress ora 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, malformedresult 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 anddurable 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 schemaare 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 oldruntime. It is not intended to become a second permanent competing orchestration dialect.