DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path scoping-notes/loomworks-conversational-fidelity-scoping-note-v0_1.html

DUNIN7 · Loomworks · Scoping Note

Conversational fidelity gap — the Companion's "saved" problem

Version. v0.1
Date. 2026-06-25
Author. Claude.ai (scoping), under Operator direction.
Status. Scoping note. Names a defect, its root cause in exact code, and a proposed fix. Precedes a Change Request. No build authorized.
Surfaced by. Live observation at :3001 engagement E0060 (2026-06-25, ~07:32): the Companion told the Operator a held draft was "saved" and "in the record," and said it does not use the words "held"/"committed" — while three held assertions sat awaiting commit.
Grounded against. Exact current text of companion_persona.md (dd21818, Phase 42) and commit_assertion.md (40eff76, CR-2026-121); responder-path confirmation from inspection of prompt.py / router.py / converse.py.

Plain-language summary

The Companion lies about the state of a draft when you talk to it in normal conversation. If you have a held draft — something you noted but have not committed — and you ask the Companion about it in chat, it tells you the draft is "saved" and "in the record." It is not. It is held, awaiting your commit. The dashboard's held cards tell the truth ("Held, awaiting your commit"); the conversation does not. Same drafts, same moment, opposite statements.

This happens because two parts of the Companion's wiring were never reconciled. The conversational voice runs through a persona file that tells it to replace engine words with plainer words — and the plainer word it offers for a held draft is "saved." The commit affordance built in CR-2026-121 runs through a different path that knows the honest distinction. The conversation got the wrong word.

The fix is small and does not require inventing new vocabulary. The persona already approves an honest word — "waiting" — alongside the dishonest one. It just never tells the Companion which state gets which word. The fix teaches the persona the state-to-word mapping the commit path already knows, using words the persona already permits. It does not reintroduce "held"/"committed" into the conversational voice; the plain-terms discipline stays intact.

This note also records a correction to the CR-2026-121 completion record: acceptance item #8, as worded, claimed more than was built. That correction is detailed at the end.

The two seed commitments in tension

This gap sits at the meeting point of two things the seed commits to, both real, both seed-faithful.

Plain-terms discipline. The seed commits that methodology nouns — assertion, engagement, held, committed — appear in plain terms on Operator-facing surfaces; the Companion speaks plainly and does not expose engine vocabulary. The persona's NEVER list is the implementation of this commitment. Banning "held"/"committed" from the conversational voice is correct under the seed.

Fidelity about state. The seed commits to Operator-authority over artifact state transitions: the system surfaces and signals, the Operator approves; an artifact is not in a state until the Operator has moved it there. Calling a held draft "saved to the record" is a false claim that a state transition has occurred — precisely the false confidence the fidelity rule exists to prevent. Telling the Operator their un-committed work is filed is a lie about an approval they have not given.

The apparent collision: plain-terms says don't say "held"; fidelity says don't say "saved" for something only held. If those were the only two words available, they would genuinely conflict.

They are not the only two words available — and this is the crux. The persona's own substitution list offers both saved and waiting. The honest word is already approved. The conflict is not vocabulary-scarcity; it is that the persona hands the Companion a bag of approved words with no rule about which word describes which state. The Companion reaches for "saved" because nothing tells it that a held draft is "waiting," not "saved."

So the resolution does not require choosing between the two commitments or minting new words. It requires assigning the already-approved plain words to the correct states. Plain-terms and fidelity are both satisfied by the same small change.

Root cause, in exact code

The Companion composes replies on two kinds of path. They handle state-words oppositely, and only one was ever brought under the fidelity rule.

Path 1 — the responder LLM path (free conversation). Governed by the persona. The defect site.

Free conversation flows: general_conversationroute_intent returns None (router.py:2709) → converse.py no-route branch → assemble_prompt(...)generate_response(...). Every intent not short-circuited earlier falls through to this responder path.

assemble_prompt opens with the persona, unconditionally — section 1, no guard; every later section is conditional and appended after. So companion_persona.md governs every LLM-composed reply, including all free conversation. The persona's NEVER list (exact text):

Never use engine vocabulary. Never say: engagement, assertion, shape, render, manifestation, specialist, materializer, normative_force, held, committed, retracted. Use Operator vocabulary: project, note, specification, artifact, draft, saved, waiting.

This is the defect. The list bans the state-words and offers saved and waiting as replacements — but it does not say a held draft is "waiting," a committed assertion is "saved"/"on the record." The mapping is state-blind. Faced with a held draft and asked about it, the LLM picks "saved," and produces "it's saved, it's in the record" — a false state claim, generated in good faith from an under-specified instruction.

Path 2 — the server-composed bypass path (commit replies). Does not use the persona. Already honest.

The commit replies — commit_assertion via delegated_response, plus create_project, finalize_project, commit_project_draft, orient, the completeness-check — never call assemble_prompt/generate_response. They emit fixed text directly, so the persona is not in play. CR-2026-121's commit_assertion.md carries the honest distinction (exact text):

A draft you have noted but not yet committed is "held, awaiting your commit" — never "saved" or "in the record." Only once it is committed do you say it is "committed to the record."

Two things to note. First, it is honest about state — it draws exactly the awaiting-commit vs. on-the-record distinction the persona is missing. Second, it is effectively dormant as an LLM instruction: the commit path is server-composed, so this template's words are not what the Operator sees. It documents the intended distinction more than it drives output. But it proves the honest distinction already exists in the system's own vocabulary — and the honest word it reaches for ("awaiting") is already in the persona's approved list as "waiting."

The gap in one sentence: the honest state-to-word mapping exists on the bypass path (commit_assertion.md) and is missing from the persona that governs all conversation, even though the persona already approves the honest word.

Proposed fix

A persona amendment that adds the state-to-word mapping, using only words the persona already approves. No new vocabulary; no reintroduction of "held"/"committed" into the conversational voice.

What changes: the persona's NEVER list currently bans the state-words and offers saved/waiting as an undifferentiated pair. The amendment keeps the ban exactly as-is and adds a state-fidelity instruction that assigns the approved plain words to states — so the LLM knows a draft awaiting the Operator's commit is described as waiting / awaiting your okay, and only work the Operator has committed is described as saved / in the record / on the record.

Candidate plain-and-honest vocabulary (all consistent with plain-terms; all honest about state):

State (engine word, banned on this surface)Dishonest plain word (current)Honest plain word (proposed)
held — noted, not yet committed"saved," "in the record""waiting for your okay," "a draft, not saved yet," "held for your go-ahead"
committed — Operator-approved, on the record(correct)"saved," "in the record," "on the record"
retracted — superseded / withdrawn(varies)"set aside," "withdrawn," "no longer current"

The exact wording is a drafting decision for the CR; the principle is fixed: a state the Operator has not yet approved is never described with a word that implies they have. "Waiting" / "awaiting your okay" carries the honest meaning in the Operator's own register — and "waiting" is already on the approved list, so the change is additive, not a vocabulary expansion.

Why this satisfies both commitments:

Scope of the change:

  1. companion_persona.md — add the state-to-word fidelity mapping to (or just after) the NEVER list. The single substantive change.
  2. commit_assertion.md — optional reconciliation. It currently uses the literal words "held"/"committed" in an instruction that is dormant (server-composed path). If it is ever brought onto an LLM-composed path, those literal words would violate the persona ban. Recommend aligning its wording to the same plain-and-honest vocabulary now, so the two documents agree and a future path change does not resurface the engine words. Low priority; flagged so it is not lost.
  3. A conversational-path fidelity test — the test acceptance item #8 should have had. Asserts that a free-conversation reply about a held draft does not contain "saved"/"in the record" and does carry the waiting/awaiting language. This is the regression guard; without it the persona could drift back. Names the responder path (assemble_promptgenerate_response) explicitly, distinct from the commit-path tests CR-2026-121 already has.

What this fix deliberately does not do:

Correction to the CR-2026-121 completion record

Corrections-preserved — record amendment required

The completion record (phases/companion-commit-affordance/…v0_1) lists acceptance item #8 as met:

Fidelity — held drafts are never described as "saved" or "in the record"; held and committed are named distinctly.

As worded, this claims a property of the whole Companion. What was actually built and tested was narrower: the two persona-bypassing surfaces — the server-composed commit replies and the static card copy — were brought under the fidelity rule and verified. The conversational voice was never under the rule and falsifies item #8 today, by persona design.

The record is not wrong about what was built; it is wrong about the scope of item #8's claim. Per corrections-preserved discipline, this is recorded, not smoothed: a completion-record v0.2 should add a note stating item #8 as worded was broader than what shipped — it held on the commit-reply and card surfaces, and the conversational surface was outside CR-2026-121's scope (CR §5.2 scoped D8 to the held card, the confirm-back, and the post-commit response only). The conversational gap and its fix are this note and the CR that follows. The prior wording stays visible alongside the correction; the trajectory is preserved.

This correction can ride with the fix CR's completion record, or be filed as a standalone record amendment — Operator's call when the CR is scoped.

What this note does not decide