Version. 0.1 · Date. 2026-08-10 · Author. Claude.ai (drafting) / Marvin Percival (approving).
Target. /Users/dunin7/loomworks-engine, branch main.
Baseline. Engine 4ae5509. CC confirms at Step 0.
Companion to. inspection-briefs/ — B-81's scoping brief (record 6674f5a), the source for every fact below. Where this CR and the brief disagree, the brief governs.
Charter. Autonomous regime. Status. Ready for CC execution.
Closes. B-81's truthfulness half, and B-82, which the brief establishes is member 4 of this same class.
The Companion tells people it did things it did not do. Observed live: "Saved to your personal memory across all projects…" against no write anywhere.
The brief establishes this is not one bug. It is a four-member class with one root enabler, and one member is worse than the instance that surfaced it.
What is structurally excluded, and should be stated so the fix does not chase it: every writing branch composes its acknowledgement server-side after the write returns, and the request's single transaction commits at dependency teardown before the response is sent. A commit failure becomes a 500, never a false claim. The three writing branches of the personal path cannot lie by construction. The exposure is entirely in branches that write nothing and hand the reply to the model.
Per the brief. CC verifies each against the code at Step 1 rather than trusting this list.
add_knowledge's error branches — worst in the codebase. No project, or empty extraction: no write, no delegated reply, and a one-line success-voiced template with no {operation_result} placeholder. The corrective failure formatter exists, is well written, is computed — and thrown away, because the splice only happens when the placeholder is present.request_draft / request_revision voice a failed dispatch as a fait accompli. The executed formatter never reads execution_result["status"], so {"status": "failed"} renders as a completed report. The neighbouring approve_draft formatter branches on status correctly — the discipline exists in the same file, unapplied. Currently dormant for the three Tier-1 capabilities because CR-2026-197's per_action_only makes executed unreachable there; live for any future unflagged dispatcher.no_personal_fact, under a template preamble that falsely asserts "the substrate has already acted on this turn"; and the general_conversation fallback, which forbids triggering operations and says nothing about claiming them.The persona's truthfulness rules govern state naming — held versus saved — and contain no rule of the form: never claim to have performed an action the system did not report performing.
That absence is what makes three of the four members live. Add the rule. But a persona rule is an instruction the model is asked to honour, which is the weakest guarantee available and unverifiable from outside — so it is necessary and not sufficient.
The structural fix is member 1's mechanism, and it is the priority. A failure formatter that is computed and discarded because a placeholder is absent is a check that cannot fire — the same family this project has now caught six times. A formatter that computes a failure instruction and silently drops it must not be able to do so. CC decides the mechanism and states it: whether the splice fails loudly on a missing placeholder, whether templates are validated at registration, or another approach. The requirement is that the failure cannot be silently discarded, not any particular implementation.
The brief names it: save_filter / tune_setting — action-first formatters, every failure enumerated. Follow it rather than inventing a new shape.
per_action, which that CR's own completion note records as slice-scoped, not a permanent position. Leaving it relies on a flag someone is expected to remove.Per member: a branch that writes nothing must not produce a reply asserting a write.
Observing failure matters unusually much here, because the assertion is about absence of a claim — and a test asserting "the reply does not say 'saved'" passes trivially against a reply that says nothing at all. Each test must be shown failing against the current code, and CC states how it established the test would catch a differently-worded false claim rather than only the exact string it checks.
B-69 applies. Reply formatting is unlikely to touch seed state — record Kind C if so. A null finding is an entry.
| Step | What | Mode |
|---|---|---|
| 0 | Pre-flight. | Auto |
| 1 | Verify the four members against the code. Halt if a fifth is found — the class was sized by a sweep, and a member the sweep missed changes what the sweep proved. | Auto, conditional halt |
| 2 | Structural fix per §3. State the mechanism chosen. | Auto |
| 3 | Four members corrected + tests, each observed failing. | Auto |
| 4 | Persona rule added. | Auto |
| 5 | Full engine suite; ruff 0; mypy at/below baseline. | Auto |
| A | Checkpoint. | Checkpoint |
| 6 | Tag cr-2026-199-truthful-replies. Push. Watch the CI run and report its result. | Auto |
Execute CR-2026-199 v0.1 at ~/Downloads/cr-2026-199-loomworks-truthful-
replies-v0_1.md. Confirm the CR number first.
Drafted from your own B-81 scoping brief, which governs where it and
this CR disagree.
The Companion tells people it did things it didn't do. Four members, one
root enabler. This closes B-81's truthfulness half and B-82.
The priority is §3's structural fix, not the persona rule. A failure
formatter computed and discarded because a placeholder is absent is a
check that cannot fire — sixth instance of that family. The persona rule
is necessary and not sufficient: it's an instruction the model is asked
to honour, which is the weakest guarantee available. Add it, and record
that the structure is what holds.
You choose the mechanism for making a discarded failure impossible or
loud, and state it. I'm not specifying the implementation.
Follow save_filter / tune_setting's shape — action-first, failures
enumerated. Don't invent a new one.
Fix member 2 even though it's dormant. It's dormant only because
CR-2026-197 forced per_action, and that CR's own note records the flag
as slice-scoped, not permanent. Leaving it relies on a flag someone is
expected to remove.
§6 matters: these tests assert the ABSENCE of a claim, which passes
trivially against a reply that says nothing. Show each failing against
current code, and state how you established the test catches a
differently-worded false claim rather than only its exact string.
HALT at Step 1 if you find a fifth member. The class was sized by a
sweep; a member the sweep missed changes what the sweep proved.
DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-199 — truthful replies — v0.1 — 2026-08-10