DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path current-status/cr-2026-161-step-2-halt-report-v0_1.md

CR-2026-161 — Step 2 halt report — v0.1

Version. 0.1 Date. 2026-08-01 Executed by. Claude Code, execution session on DUNIN7-M4. CR. change-requests/cr-2026-161-authorship-truth-v0_1.md — confirmed the highest version present. Charter. standing-notes/dunin7-standing-authorization-charter-v0_1. Halt condition. A-2 — divergence from the CR's evidence base (C-3). Fired at Step 2, on Group D. Status. HALTED. Steps 0 and 1 are complete and committed on branch cr-2026-161-authorship-truth. Nothing merged. Nothing pushed. Engine main untouched at e106917.


1. What halted, in one paragraph

Group D's specified fix cannot be applied to the code it names. The CR says of site 4: "Distinguish absent from explicitly-null, and write the agent the client named." But the coalesce at considerations.py:195 fires only when the client named no agent at all — and the request schema documents that behaviour as intended, in a published API description. There is no named agent being lost, so there is nothing to recover; and the distinction the CR asks for is one the declared contract does not draw. The remedy does not fit the defect as the code actually stands.

This is not a judgment I am entitled to resolve in flight. C-3 forbids in-flight scope absorption; the correction is a CR version bump from a drafting session.


2. The evidence

The construction, at api/routers/considerations.py:193-197:


agent_actor = ActorRef(
    kind="agent",
    id=body.agent_actor_id or uuid.uuid4(),
    instruction_version=body.instruction_version,
)

The schema that governs it, at api/schemas.py:4251-4259:


agent_actor_id: UUID | None = Field(
    None,
    title="Agent",
    description=(
        "The agent identity to attribute the summarisation to. Optional; "
        "when omitted a fresh agent identity is allocated for the run. "
        "Supply one to tie the summary to a known agent."
    ),
)

The coalesce implements the declared contract exactly. "When omitted a fresh agent identity is allocated for the run" is what or uuid.uuid4() does. The field is UUID | None with default None, so an explicitly-supplied null and an omitted field are indistinguishable after parsing — and the description draws no distinction between them, because under the declared contract they mean the same thing: no agent named.

Contrast site 11, which is genuinely the shape the CR describes. There, converse.py:678-686's own comment states a contract — "when both are absent the scope stays None so the intent handlers ask" — that the or cannot honour. The engine says one thing and the code does another. At site 4 the engine's own schema says the same thing the code does. The two sites look alike and are not alike, and the difference is exactly the distinguishing test.


3. Where the evidence base went wrong — and it was mine

**The Step 0 findings recorded site 4 as "a falsy-coalesce on an agent identifier, self-contained" and did not read the request schema.** The CR inherited that characterisation in good faith and built a remedy on it.

What a full read establishes is that the only defensible B-25 claim against site 4 is a different and larger one: that allocating an ephemeral agent identity which exists in no registry, and stamping it onto both the summary and the event, puts a plausible-and-meaningless identifier in the permanent record. That may well be a real finding — it is recognisably the B-25 class. But it is:

Deciding any of that in flight would be scope absorption. It is precisely what C-3 forbids and what the two prior halts in CR-2026-159 were caused by not doing.


4. What is done, and is sound

| Step | Commit | State | |---|---|---| | 0 — pre-flight and three determinations | 6a1bb13 | complete | | 1 — Group A, sites 5–9 | 725ef21 | complete, suite at baseline |

Both stand on their own and neither depends on Group D. The branch is cr-2026-161-authorship-truth, off main e106917. Not merged, not pushed, not tagged. The working tree is clean; no partial Group B or D edit exists, and site 4 is byte-unchanged.

Baseline, recorded at Step 0 by name:


FAILED tests/test_stele_router_mount.py::test_stele_router_mounts_and_begin_resolves_end_to_end
1 failed, 3444 passed, 68 skipped

After Step 1: identical. 1 failed, 3444 passed, 68 skipped — the baseline set exactly, no new failure. Acceptance gate item 2 is already met: the Step 0 sweep re-run returns zero ActorRef in src/ carrying kind="contributor" with id=person.id.

The three determinations all settled and are recorded in docs/phase-crs/cr-2026-161-step-0-determinations-v0_1.md on the branch:

  1. wasAttributedTo is REQUIRED (memory/base.py:146) → D-5's sentinel branch.
  2. The spoken door writes Companion-authored content → D-3's first branch; site 10 is struck as a defect.
  3. Yes, consumers branch on actor.kindconversation_turns.py:364 and conversation_history.py:173, both as their _is_human test, and NON_HUMAN_ACTOR_KINDS = {"agent","companion"} (base.py:31) is what the commit gates reject. Collapsing site 10 would have made the Companion's own draft committable as a human act. This closes the findings' one unread.

Determination 2 and 3 removed work rather than adding it — Group E reduces to the compounding site alone.


5. The decision queued

Q-8 — what is site 4's defect, and is there one?

| | | |---|---| | Question | The coalesce at considerations.py:195 implements a documented contract. Is the real finding that ephemeral agent identities — fabricated UUIDs naming no registered agent, stamped onto the summary and the event — do not belong in the permanent record? If so, that is a change to a declared API contract, and it may reach beyond site 4. | | Default | Strike site 4 from B-25 and open it as its own item. The record write is declared, not accidental, so it fails B-25's own distinguishing test — the same test that struck seed_conversation.py:116. | | Blocks | Group D only. | | Proceeds regardless | Groups A (done), B, C, E, F. |

A second, smaller queue item rides with it.

Q-9 — the D-5 sentinel's kind. Determination 1 settled that wasAttributedTo is required, so the legacy path needs a sentinel. The CR specifies the sentinel's UUID, display name and comment but not its kind, and the choice is consequential: person would assert the session-cookie path that is absent; agent or companion fall inside NON_HUMAN_ACTOR_KINDS and would revoke commit authority on a path that legitimately has it. The only non-falsifying option is contributor — truthful about the auth path (the legacy route is the bearer-token path by construction), with the sentinel UUID and display name carrying the unknown identity explicitly. Recorded rather than applied, because the CR did not specify it and Group C is not yet built.


6. Recommendation

A v0.2 of the CR from a drafting session, carrying:

  1. Group D struck or re-scoped, per Q-8. If re-scoped, it needs its own evidence — the schema read this session performed, plus a sweep for every other ephemeral-identity allocation.
  2. The D-5 sentinel's kind specified, per Q-9.
  3. Group E already reduced to the compounding site by Determination 2, and site 10 struck — the CR's §3 Group E and gate item 8 should say so rather than leaving it to the determination.
  4. The "twelve lines" error corrected in §3 — it is 214 lines from site 7 and 549 from site 6. Inherited from the Step 0 findings' headline; the findings owe a v0.2 for the same line.

Everything in Groups B, C, E and F remains executable as written and is unblocked by Q-8. A v0.2 could reasonably keep Step 1 as landed and resume at Step 2.


DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-161 — Step 2 halt report — v0.1 — 2026-08-01 The remedy did not fit the defect. The schema said so, and the sizing had not read it.