From 8bd4f7e2c208c3e175854b57aa9d5673cf7daf0c Mon Sep 17 00:00:00 2001 From: A Tobey Date: Thu, 27 Aug 2026 08:40:11 -0400 Subject: [PATCH 1/4] AGENTS.md: number rules, errors as feedback, and the working method Three rules from the number-parsing work are stated where every session loads them. Number rules: $(( )) owns bases and checked arithmetic with bash's spellings only; a leading zero is text and every number position refuses it naming the fix; fromjson is JSON-only and no cast builtin or --base flag exists. The error-handling section gains the no-silent- fallback rule, with printf '%d' 0xff printing 0 as the shape to refuse. The writing-style section states the stance behind it: an error is feedback for the next turn, so refusing with the fix named beats degrading quietly. Version control gains the working method: one medium PR per hunk, coding delegated against a written spec with tests that fail first, gates and kaibo review run by the orchestrator, and review claims verified against a built binary. A claim that models habitually write some spelling is a measurable thing: give cheap casts the help text and count before adding syntax. Commit messages: a clinical engineering narrative; design stories and plans live in exomemory and are never referenced from a commit. Co-Authored-By: Claude Fable 5 --- AGENTS.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 48530824..f5b167db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,6 +58,28 @@ cargo insta review # Interactive review of pending snapsho - Never discard errors. - If an error is impossible in practice, the program must still panic if it occurs. - When an error is deliberately ignored, a comment must say why. +- No silent fallback. A parse that yields a default on failure (`parse().unwrap_or(0)`, + `as i64` on a float) is a bug: `printf '%d' 0xff` printing `0` is the shape to refuse. + Return an error that names the value and the fix. + +### Number rules + +`$(( ))` is where kaish reads a number in another base and does checked 64-bit integer +arithmetic. `docs/LANGUAGE.md`, "Arithmetic" is the contract; these are the decisions +behind it: + +- Base spellings are bash's: `0xff` and `base#digits` (base 2 to 36). `0b101` and + `0o17` are errors that name `2#101` and `8#17`. Add a spelling only after a model + panel shows models writing it. +- A leading zero is text (`007`, `0644`). Where kaish needs a number — `$(( ))`, + `[[ -eq ]]`, `test`, a loop count, a list index — it is an error naming `8#10`, + `10`, or `10#$x`. kaish never answers octal or a third number. +- An integer literal must fit in 64 bits; overflow, division by zero, an unset + variable, an empty `$(( ))`, and assignment inside `$(( ))` are errors, never + wraps or zeros. A string is a value, never an expression. +- `fromjson` parses JSON and nothing else (it is the string-to-number coercion: + `fromjson 1e3`). No `cast` builtin, no `--base` flag. `printf %x` / `%o` format + the other direction; `$(random --max N)` replaces `$RANDOM`. ### Code style @@ -98,6 +120,13 @@ cargo insta review # Interactive review of pending snapsho (`--all-targets` so test code is linted too — see the note below) CI enforces these (plus the sandbox and WASI legs) on the PR — run them locally first anyway; the feedback loop is minutes faster. +- **One PR per hunk of work, medium-sized.** Coding is delegated to a subagent with a + written spec and named tests that must fail first; the orchestrator runs the gates + (a subagent told to run them stalls) and gets a kaibo review of the branch before + pushing. Verify every review claim against a built binary before acting on it. +- **A claim about what models "habitually" write is testable.** Before adding a + spelling or a shortcut for their sake, give a few cheap casts the proposed help + text and a task list, and count. One syntax until the count says otherwise. `unwrap_used` is denied and `expect_used` warned workspace-wide, so the lints carry that rule and this guide does not repeat it. What the lints cannot tell @@ -114,6 +143,10 @@ change, **drawn from the conversation with the user**. The commit message is whe the narrative of agent and user can be persisted. A useful commit message will remind us how we got to the code it contains. The code can speak for itself. +Write it as a clinical engineering narrative: the problem, the evidence, the decision, +the rule now in force. Design stories, plans, review transcripts, and model-panel +results live in exomemory, not in the repo, and a commit never references them. + ## Architecture The kernel is the unit of execution. Multiple frontends can connect to the same kernel: @@ -232,6 +265,11 @@ Errors that face users, agents, and models must not leak internals. Internal cod and references will be unresolvable and should only be exposed for assertions and errors that indicate a real problem in kaish. +An error is feedback, not a problem. A model that reads `` write `10#$m` `` gets it right +next turn; a silent coercion teaches nothing. When the choice is between degrading quietly +and refusing with the fix named, refuse. Keep the text clinical: the value, the rule in +a few words, the fix. + ### Published builtin text A `///` comment on a builtin argument is published to agents. `params_from_clap` copies From 38112c9447962eb6099f3bafc9ccf74ed9c04614 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Thu, 27 Aug 2026 08:45:35 -0400 Subject: [PATCH 2/4] AGENTS.md: state the fromjson rule without the alternatives A rule names what kaish does. The sentence listing the builtin and flag that were not built dragged discarded ideas into a file every session loads; it is gone. Co-Authored-By: Claude Fable 5 --- AGENTS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f5b167db..d5670d4e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,9 +77,9 @@ behind it: - An integer literal must fit in 64 bits; overflow, division by zero, an unset variable, an empty `$(( ))`, and assignment inside `$(( ))` are errors, never wraps or zeros. A string is a value, never an expression. -- `fromjson` parses JSON and nothing else (it is the string-to-number coercion: - `fromjson 1e3`). No `cast` builtin, no `--base` flag. `printf %x` / `%o` format - the other direction; `$(random --max N)` replaces `$RANDOM`. +- `fromjson` parses JSON and nothing else; it is also the string-to-number coercion + (`fromjson 1e3`). `printf %x` / `%o` format the other direction; `$(random --max N)` + replaces `$RANDOM`. ### Code style From 2cea1a40a7694c8ee79613edc90efbd601fee436 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Thu, 27 Aug 2026 08:54:41 -0400 Subject: [PATCH 3/4] AGENTS.md: keep the theory-testing loop, drop the session workflow The two bullets under version control described how one session ran its work, which does not belong in a file every session loads. The measurable half survives as its own short section: a claim about what models or users will write is tested by handing cheap casts or subagents the proposed help text and counting, and one syntax stands until the count says otherwise. Co-Authored-By: Claude Fable 5 --- AGENTS.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d5670d4e..2b38a30b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,6 +81,14 @@ behind it: (`fromjson 1e3`). `printf %x` / `%o` format the other direction; `$(random --max N)` replaces `$RANDOM`. +### Test a theory before building it + +A claim about what models or users will write is measurable. Before adding syntax, a +spelling, or a shortcut on their behalf, hand a few cheap kaibo casts or subagents the +proposed help text and a task list, and count what they produce. Keep one syntax until +the count says otherwise. The same loop works for an error message: show the message, +ask for the next command, and see whether it lands. + ### Code style - Comments should be short and direct. Comments are not a space for narratives; @@ -120,13 +128,6 @@ behind it: (`--all-targets` so test code is linted too — see the note below) CI enforces these (plus the sandbox and WASI legs) on the PR — run them locally first anyway; the feedback loop is minutes faster. -- **One PR per hunk of work, medium-sized.** Coding is delegated to a subagent with a - written spec and named tests that must fail first; the orchestrator runs the gates - (a subagent told to run them stalls) and gets a kaibo review of the branch before - pushing. Verify every review claim against a built binary before acting on it. -- **A claim about what models "habitually" write is testable.** Before adding a - spelling or a shortcut for their sake, give a few cheap casts the proposed help - text and a task list, and count. One syntax until the count says otherwise. `unwrap_used` is denied and `expect_used` warned workspace-wide, so the lints carry that rule and this guide does not repeat it. What the lints cannot tell From e9be3f82e88439bb96892a2bf5f2bc43215e8a43 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Thu, 27 Aug 2026 08:55:15 -0400 Subject: [PATCH 4/4] AGENTS.md: name agent memory, not a private tool "exomemory" is the name of one maintainer's memory store; the rule is about where design stories live, so it names agent memory outside the repo instead. Co-Authored-By: Claude Fable 5 --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 2b38a30b..c8ca25db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -146,7 +146,7 @@ remind us how we got to the code it contains. The code can speak for itself. Write it as a clinical engineering narrative: the problem, the evidence, the decision, the rule now in force. Design stories, plans, review transcripts, and model-panel -results live in exomemory, not in the repo, and a commit never references them. +results live in agent memory outside the repo, and a commit never references them. ## Architecture