DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/cr-2026-199-loomworks-truthful-replies-v0_1.md

DUNIN7-M4 — INFRASTRUCTURE CHANGE REQUEST

CR-2026-199 — replies that claim actions the system did not perform (v0.1)

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.


1. Summary

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.


2. The four members

Per the brief. CC verifies each against the code at Step 1 rather than trusting this list.

  1. 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.
  2. 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.
  3. The remember-path non-writing branches. 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.
  4. The fallback's overclaim — B-82's "I'm drafting an application specification … now." Same member as 3's fallback.

3. The root enabler, and the fix that matters most

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.


4. The pattern to copy

The brief names it: save_filter / tune_settingaction-first formatters, every failure enumerated. Follow it rather than inventing a new shape.


5. Scope

  1. The structural fix per §3 — a discarded failure instruction becomes impossible or loud.
  2. All four members corrected, following §4's pattern.
  3. The persona rule added.
  4. Member 2 fixed even though it is dormant. It is dormant only because CR-2026-197 forced 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.

6. Tests

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.


7. Out of scope


8. Seed-mutability impact

B-69 applies. Reply formatting is unlikely to touch seed state — record Kind C if so. A null finding is an entry.


9. Build steps

| 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 |


10. Acceptance gate

  1. No branch that writes nothing produces a reply asserting a write — tested per member, each observed failing first.
  2. A computed failure instruction cannot be silently discarded. The mechanism is stated.
  3. The persona rule is added, and recorded as insufficient on its own — the structural fix is what holds.
  4. Member 2 fixed despite being dormant, with the reason recorded.
  5. Suite green, both gates clean, CI run watched and reported.
  6. Seed-mutability recorded, including as a null finding.

11. Kickoff prompt


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