Part of GH-C37 (docs/development/contributor-tasks.md): curate the interaction pattern catalog with one new public-safe good/bad case.
Gap / 缺口
The catalog has patterns for what a projection must keep visible (IP-037 a retired setting, IP-033 a recorded rejection, IP-032 a durable decision across an archive) and for what a lost transport means (IP-036 a lost response is not an absent commit). It has no entry for the read-side twin: a component publishes a typed reason, the consumer cannot recover it, and the consumer then reports its own observation as the cause.
That shape is not hypothetical in this repository. On current main the managed effect runtime publishes invalid_idle_timeout with the offending value quoted back, and the caller raises runtime_exited_before_ready (exit_code=N) whenever its parse of that channel fails — which it does for U+0085, U+2028 and U+2029, because str.splitlines() treats those as line breaks while JSON.stringify leaves them raw. #5057 records the defect and #5058 fixes the framing. This task registers the reusable interaction shape, not the one-line repair.
Scope
One new entry, IP-038 A Generic Fallback Is Not A Typed Diagnosis, in the State And Boundary family, with the three registrations the catalog requires:
- the family matrix row,
- the classification index row (
Importance | ID | Name | Primary Owner | User Channel | Agent Channel),
- the detail section with Trigger / Expected behavior / Visual Model / Bad smell / Validation.
Four rules, each anchored to shipped code and to a test that already holds it:
- ask the typed channel before the fallback (
loopx/control_plane/effect_runtime.py:776-791);
- frame the reason channel by the separator the publisher writes (
:588 against :665);
- reject by code before any mutation, naming the guard (
loopx/control_plane/runtime/runtime_projection_writer.py:27-31, :88);
- report a fallback as coverage, never as health (
loopx/control_plane/subagent_context.ts:31, :52).
Explicitly out
Per the catalog's own maintenance rule, this is not a place for a validation technique, smoke group, release checklist or rollout procedure, so the entry carries no canary profile or runbook. It is also not a second home for #5051's host-receipt work or #5058's framing repair; both are cited as evidence and neither is restated as a new pattern.
Acceptance
python3 examples/interaction-pattern-catalog-smoke.py passes with the new entry present in all three registrations.
- The structural failures stay detectable: removing the detail section, listing the id under two families, and renaming the index id each make the smoke fail with a distinct assertion.
loopx check --scan-path docs/concepts/interaction-pattern-catalog.md is clean.
- Every file:line in the entry resolves on current
main, and no private log, chat or benchmark artifact is copied in.
Part of GH-C37 (
docs/development/contributor-tasks.md): curate the interaction pattern catalog with one new public-safe good/bad case.Gap / 缺口
The catalog has patterns for what a projection must keep visible (IP-037 a retired setting, IP-033 a recorded rejection, IP-032 a durable decision across an archive) and for what a lost transport means (IP-036 a lost response is not an absent commit). It has no entry for the read-side twin: a component publishes a typed reason, the consumer cannot recover it, and the consumer then reports its own observation as the cause.
That shape is not hypothetical in this repository. On current
mainthe managed effect runtime publishesinvalid_idle_timeoutwith the offending value quoted back, and the caller raisesruntime_exited_before_ready (exit_code=N)whenever its parse of that channel fails — which it does for U+0085, U+2028 and U+2029, becausestr.splitlines()treats those as line breaks whileJSON.stringifyleaves them raw. #5057 records the defect and #5058 fixes the framing. This task registers the reusable interaction shape, not the one-line repair.Scope
One new entry, IP-038 A Generic Fallback Is Not A Typed Diagnosis, in the State And Boundary family, with the three registrations the catalog requires:
Importance | ID | Name | Primary Owner | User Channel | Agent Channel),Four rules, each anchored to shipped code and to a test that already holds it:
loopx/control_plane/effect_runtime.py:776-791);:588against:665);loopx/control_plane/runtime/runtime_projection_writer.py:27-31,:88);loopx/control_plane/subagent_context.ts:31,:52).Explicitly out
Per the catalog's own maintenance rule, this is not a place for a validation technique, smoke group, release checklist or rollout procedure, so the entry carries no canary profile or runbook. It is also not a second home for #5051's host-receipt work or #5058's framing repair; both are cited as evidence and neither is restated as a new pattern.
Acceptance
python3 examples/interaction-pattern-catalog-smoke.pypasses with the new entry present in all three registrations.loopx check --scan-path docs/concepts/interaction-pattern-catalog.mdis clean.main, and no private log, chat or benchmark artifact is copied in.