diff --git a/docs/decisions.md b/docs/decisions.md index 62880b7..8ddcdc9 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -6,6 +6,8 @@ Newest first. A decision that changes `docs/design.md` lands in the same commit | Date | Decision | Reason | |---|---|---| +| 2026-09-17 | A compromised `loopd` can degrade the shared `llama-server` for other clients (large prompts, unpinned requests). Accepted for v0 and written into the threat model. `inferproxy` stays a byte forwarder with a connection cap and an accept-rate limit; it does not enforce slot or model policy. If isolation is wanted later, do it on the server side. | The harm is availability only, the owner would notice, and a policy proxy would put a parser for untrusted input into the component meant to have none. | +| 2026-09-17 | M2a limits: 10 min wait for a busy slot, 3 min for a model load, 30 s liveness after the first byte, thinking cap 4,096 tokens with `max_tokens` 8,192 as backstop. All are config values. The slot gate is held per request, never across a tool call. | Owner's choices during the M2a design review; measurements (j) to (n) in `docs/inference-contract.md`. | | 2026-09-17 | SHA-256 comes from the owner's `emsha` crate, version 1.0.4 or later, not `sha2` and not hand-written code in this repo. It is wrapped behind one function in `proto`, whose tests carry their own vectors: `abc`, the million-`a` message, and lengths 55, 56, 63, 64 and 65. The crate's custom licence is not an issue: the owner is its author. | No dependencies, no `unsafe`, `no_std`, owner-maintained. Version 1.0.3 hashed every message of length 63 mod 64 wrongly; a differential test against `sha256sum` found it while the crate was being vetted, and the owner fixed it in 1.0.4 (3,204 cases pass). | | 2026-09-17 | M2 is split. M2a is the inference path (`inferproxy`, HTTP and SSE client, llama client, fake server, startup self-test). M2b is the agent loop (session log, turn loop, channel protocol, `bxctl chat`). Review happens after each. | The risky, timing-dependent work gets reviewed before the turn loop is built on it. | | 2026-09-17 | Tool results are untrusted by default: each grant has `untrusted`, default true, and `brokerd` tracks a per-session untrusted flag beside taint. Review of Laguna's work is once per milestone, as an experiment for M1 to be revisited after the M1 review. Laguna keeps `docs/implementer-log.md`. | Owner's choices during the pre-M1 design review. Details in `docs/specs/2026-09-17-pre-m1-design.md`. | @@ -25,6 +27,7 @@ Newest first. A decision that changes `docs/design.md` lands in the same commit | Decision | Needed by | |---|---| +| Thinking cap size. It starts at 4,096 tokens so that the right size can be found from data. From M2b every completion logs its reasoning-token count and whether the cap fired. Revisit once 200 completions are logged, or sooner if the owner sees answers cut short: raise the cap if more than 5% of completions hit it. Each hit also costs a re-read of that turn. | after M2b has run for a while | | Repository licence. Crates are `publish = false` until it is chosen. | before publishing | | Audit integrity beyond a self-contained hash chain (for example anchoring the chain head outside `brokerd`). Deferred by the owner on 2026-09-17 to a later revision. | after v0 | | Secret store backend, and where the v0 file's key lives. straylight has no secrets manager today. | M3 | diff --git a/docs/inference-contract.md b/docs/inference-contract.md index 3d9314e..bad95ca 100644 --- a/docs/inference-contract.md +++ b/docs/inference-contract.md @@ -125,6 +125,23 @@ checkpoint at the end of the previous prompt. The cost is bounded by the thinkin answer, and it is paid once. The control run also shows that streamed deltas, concatenated, replay byte for byte. +### (l) Closing the connection cancels generation + +Measured 2026-09-17: a streaming request was closed by the client while the model was thinking. +`/slots` showed the slot idle 0.1 s later. A client that aborts frees the GPU. + +### (m) Exact token counts while streaming + +With `timings_per_token: true` every streamed chunk carries a `timings` object, including +`predicted_n`, the number of tokens generated so far. A thinking cap can count real tokens. + +### (n) Tool-call arguments stream token by token + +Measured 2026-09-17: the model wrote a 1,500-word essay into a `write_file` call. 1,999 tokens over +30 s arrived as 1,948 tool-call deltas, the longest gap between events was 0.33 s, and the +concatenated `arguments` fragments were valid JSON. The server does not hold a tool call back +until it parses, so a silence-based liveness limit is safe during long tool calls. + ### (a) Throughput Method: timed requests, server-reported `timings`, thinking off. "At depth 32k" means a 2k-token