Task ID or area
GH-C37 (design / docs) — interaction pattern catalog
Technical direction
Core control-plane hardening
Intent
I want to claim an existing task
Summary
The catalog has a pattern for how a decision is written (IP-014) and one for what
happens to a durable decision when its todo leaves the active window (IP-032), but
nothing names the boundary between a refusal and no decision at all.
Under loopx/control_plane/todos/standing_decision.ts, an explicit reject or
cancel stays a standing_decision_receipt_v0 entry: its scope, owner and
chronology survive exactly like an approval's, archive retains it, and it is
counted under inactive_count. Only decision_outcome === "approve" sets
active. So "no active approval" must never be rendered as "no decision was
made", and a retained, done, global todo must never be read as the approval it
structurally resembles.
This slice curates that shape as one public-safe catalog entry.
Proposed scope
In scope:
- add IP-033 under Human Decision (P1): trigger signals, user channel, agent
channel, expected behavior, visual model, bad smells, validation references;
- list it in the Pattern-To-Canary coverage matrix;
- pin the entry in
examples/interaction-pattern-catalog-smoke.py.
Out of scope:
- new runtime contracts, schemas, or protocol changes;
- production code changes;
- renumbering or editing existing patterns.
Intended base branch
main
Relevant files or commands
docs/concepts/interaction-pattern-catalog.md
examples/interaction-pattern-catalog-smoke.py
python3 examples/interaction-pattern-catalog-smoke.py
loopx check --scan-path docs/concepts/interaction-pattern-catalog.md
Validation plan
python3 examples/interaction-pattern-catalog-smoke.py
loopx check --scan-path docs/concepts/interaction-pattern-catalog.md
Public/private boundary
Task ID or area
GH-C37 (design / docs) — interaction pattern catalog
Technical direction
Core control-plane hardening
Intent
I want to claim an existing task
Summary
The catalog has a pattern for how a decision is written (IP-014) and one for what
happens to a durable decision when its todo leaves the active window (IP-032), but
nothing names the boundary between a refusal and no decision at all.
Under
loopx/control_plane/todos/standing_decision.ts, an explicitrejectorcancelstays astanding_decision_receipt_v0entry: its scope, owner andchronology survive exactly like an approval's, archive retains it, and it is
counted under
inactive_count. Onlydecision_outcome === "approve"setsactive. So "no active approval" must never be rendered as "no decision wasmade", and a retained, done, global todo must never be read as the approval it
structurally resembles.
This slice curates that shape as one public-safe catalog entry.
Proposed scope
In scope:
channel, expected behavior, visual model, bad smells, validation references;
examples/interaction-pattern-catalog-smoke.py.Out of scope:
Intended base branch
main
Relevant files or commands
docs/concepts/interaction-pattern-catalog.mdexamples/interaction-pattern-catalog-smoke.pypython3 examples/interaction-pattern-catalog-smoke.pyloopx check --scan-path docs/concepts/interaction-pattern-catalog.mdValidation plan
python3 examples/interaction-pattern-catalog-smoke.pyloopx check --scan-path docs/concepts/interaction-pattern-catalog.mdPublic/private boundary