DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/cr-2026-200-loomworks-b81-grant-pathway-v0_1.md

DUNIN7-M4 — INFRASTRUCTURE CHANGE REQUEST

CR-2026-200 — B-81: the grant reads the Operator's own words, and the confirm names what it grants (v0.1)

Version. 0.1 · Date. 2026-08-10 · Author. Claude Code (drafting, from the grant-pathway brief) / Marvin Percival (approving). Target. /Users/dunin7/loomworks-engine, branch main. Surface touched only if Step 1 proves a render site lives there (verify-then-do; live surface is /Users/dunin7/loomworks). Baseline. Engine 5e6cd17. CC confirms at Step 0. Companion to. inspection-briefs/loomworks-b81-grant-pathway-step-0-findings-v0_1 (record c80cd99) — the source for every fact below; where this CR and the brief disagree, the brief governs, verified against code. Charter. Autonomous regime. Status. DRAFT — awaiting the gate. Do not execute. Closes. B-81 (its remaining, grant-pathway half — the truthfulness half closed at CR-2026-199).


0. Settled — the Operator's four rulings, 2026-08-10. Do not re-raise.

  1. Scope defaults to this engagement. A sentence typed inside a project is about the project unless it says otherwise — the same principle as CR-2026-197's produce_artifact ruling: a grant does what its own words say and nothing wider. It also inverts safely: someone who meant everywhere can say so; someone who meant here and got everywhere can't know they did. The held card must name the scope explicitly. (No schema change needed: DelegationScope is already "all" | [engagement ids] and verify_companion_authorization already matches scope-covers-engagement.)
  2. Fix the held card and the ack BEFORE adding reachability — same CR, that order. Raw JSON in the tray and an ack that quotes the sentence without saying it's a grant means confirming a false positive confirms something whose consequence isn't named. Reachability added first widens an unreadable confirm. The build steps below are ordered accordingly and the order is load-bearing.
  3. Two minimal wires, not the pre-dispatch interception. A new interception on every turn's hot path to fix two known sites is more surface for less certainty.
  4. The matcher is not loosened. The Operator's original "unmoderated write access" ground is corrected on the record — per_action cards each act — but both actual mitigations are the wrong kind to lean on: the "always" markers producing pre_authorized are exactly what a loose matcher over-catches, and the Tier-1 forcing flag is slice-scoped by its own record. Loosening stays out; per the brief's deciding finding it is unnecessary anyway — the exact-prefix matcher stays exact and is shown the Operator's own words.

1. Summary

Two sub-causes from the brief, both now cheap because the deciding question answered well:

And the blocker in front of both, per ruling 2: a held delegation renders as raw JSON (HeldItem.content = a.content verbatim, router.py:966-975; to_assertion_content is json.dumps) and the ack quotes the sentence without naming it a grant — the confirm cannot carry the knowability the seed requires.

2. Scope, in ruling-2 order

First — the confirm becomes readable (engine, possibly surface):

  1. The grant ack is server-composed naming the consequence: capability, scope, and approval mode, in Operator vocabulary — e.g. "Got it, held: a standing authority for me to draft specifications in this project, asking you each time. It takes effect only when you confirm it on its held card." Composed from the parsed DelegationContent, never from the model.
  2. Every surface through which a held grant is confirmed renders it as that sentence, not JSON. Step 1 enumerates the render sites (the conversational held tray's HeldItem, show_held, and the Memory-room held card's API path at minimum) and the fix composes the human rendering server-side from the parsed content. Preference: compose into the existing content-string channel so no wire-schema change is needed; HALT if a render site genuinely requires one — a new wire field is a decision, not an implementation detail.

Then — reachability, as two minimal wires (ruling 3):

  1. (1b) In _route_remember_about_me: extraction runs on message (already in scope); the note text for non-grant facts keeps using the extracted paraphrase.
  2. (1a) route_intent forwards message into _route_add_knowledge (one kwarg, one parameter); the same extraction runs ahead of the plain-note path. A recognized grant follows the grant flow (held delegation + the ruling-2 ack); everything else falls through to the note path unchanged.
  3. Scope defaulting (ruling 1): a grant recognized with engagement_id present defaults scope=[that engagement]; scope="all" only on an explicit everywhere-marker (an enumerated, exact list — e.g. "across all projects", "everywhere", "on all my projects" — extending the extractor's existing marker discipline, not loosening it). The personal path (no project context) keeps "all" — there is no narrower referent to default to, and the sentence was said outside any project.

3. What this CR does not do

4. Tests — each observed failing first

  1. (1b) With a classified personal_fact that is a paraphrase and a message carrying the grant sentence: a delegation is held (fails today — plain note).
  2. (1a) The grant sentence routed through add_knowledge with message forwarded: a delegation is held, not a project note (fails today — no wire).
  3. Scope default: in-engagement grant → scope == [engagement_id]; with an everywhere-marker → "all"; personal-path grant → "all" (fails today — always "all").
  4. The readable confirm: the ack names capability, scope, and mode (string assertions on the server-composed ack); the held rendering of a delegation contains no raw JSON and names all three (fails today — JSON).
  5. Negative control (ruling 4): "you can imagine how hard this was" and one capability-less "you can …" sentence extract to None and stay notes (passes today; pinned so no fix loosens it).
  6. Authorization end-to-end: an engagement-scoped grant authorizes request_draft in that engagement and is denied in another (exercises the existing scope matching under the new default).

Per the CR-2026-199 discipline: the positive tests assert the presence of the grant object/rendering in the controlled channel, not word-absence; each is run against pre-fix code and its failure observed before the fix is trusted.

5. Out-of-scope observations

Report anything found; fix nothing beyond §2. The Step 1 render-site enumeration in particular reports every place delegation JSON currently escapes to a surface, even ones out of this CR's reach.

6. Seed-mutability impact

B-69 applies. Delegation content, prompt acks, and routing wires are unlikely to touch seed state — record Kind C with what was checked. A null finding is an entry.

7. Build steps

| Step | What | Mode | |---|---|---| | 0 | Pre-flight — baseline 5e6cd17, tree clean. | Auto | | 1 | Enumerate every render site a held delegation's content reaches. HALT if readable rendering requires a wire-schema change at any site. | Auto, conditional halt | | 2 | The readable confirm: server-composed grant ack + human rendering at every Step-1 site. | Auto | | 3 | Reachability wires (1b then 1a) + scope defaulting. Strictly after Step 2 (ruling 2 — the order is load-bearing). | Auto | | 4 | Tests per §4, each observed failing first; full suite; ruff; mypy. | Auto | | A | Checkpoint — including the product eye-test plan for the gate. | Checkpoint | | 5 | Tag cr-2026-200-b81-grant-pathway. Push. Watch the CI run and report its result. | Auto |

8. Acceptance gate

  1. The full circle, in the product: the denial reply's own suggested sentence, typed in-engagement by the test persona, produces a held grant whose card names capability, scope ("in this project"), and mode; confirming it creates the delegation; "Draft a specification." then produces the approval card per CR-2026-197. Run under the E2E cleanup rule (throwaway engagement, torn down; the anomalous-turn lesson applied: capture classified_intent of every eye-test turn before teardown).
  2. Paraphrase-robustness and scope-defaulting proven by the §4 tests, each observed failing first.
  3. The negative control stands: no sentence extracts that did not before, except by reading the original words.
  4. No raw JSON reaches any surface a held grant is confirmed through; the ack and card name capability + scope + mode.
  5. Suite green (zero failures), both gates clean, push run watched and reported.
  6. Seed-mutability recorded, including as a null finding.

9. Kickoff prompt


Execute CR-2026-200 v0.1 at change-requests/cr-2026-200-loomworks-b81-
grant-pathway-v0_1.md in loomworks-record. Confirm the CR number and
the baseline first.

§0 carries the Operator's four rulings verbatim. Don't re-raise them.
The order in §2 is load-bearing: the confirm becomes readable BEFORE
reachability is added — reachability first would widen a confirm that
can't be read.

The deciding finding from the brief: the raw text is already a
parameter of _route_remember_about_me, and route_intent drops it one
hop from _route_add_knowledge. Two minimal wires. No pre-dispatch
interception. No matcher loosening — pin that with the negative
controls.

Scope defaults to this engagement when granted in-project; "all" only
on an enumerated everywhere-marker; personal-path grants keep "all".
The held card names the scope.

HALT at Step 1 if making the held grant readable requires a wire-schema
change at any render site — a new wire field is a decision, not an
implementation detail.

Gate item 1 is the arc closing: the sentence the Companion itself
suggests, typed in a project, must finally do what it says — and the
card the Operator confirms must say what it does.

DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-200 — B-81 grant pathway — v0.1 — 2026-08-10 The matcher stays exact; it is shown the Operator's own words; and the confirm says what it grants.