Skip to content

docs(decisions): 0251 — fabrika pins shared wire formats, and owns their tests (#4892) - #5252

Merged
usirin merged 2 commits into
mainfrom
usirin/adr-epic-envelope-wire-format-4892-018DCBE1
Aug 10, 2026
Merged

docs(decisions): 0251 — fabrika pins shared wire formats, and owns their tests (#4892)#5252
usirin merged 2 commits into
mainfrom
usirin/adr-epic-envelope-wire-format-4892-018DCBE1

Conversation

@usirin

@usirin usirin commented Aug 10, 2026

Copy link
Copy Markdown
Member

fabrika's rule was "calls pipeline-cli nowhere". But the envelope fabrika writes on an epic and the splicer that plans that epic have to agree on the same bytes, and neither side can re-implement its way out of that. This records the founder-delegated ruling: fabrika owns those bytes as a wire format with a committed golden fixture, and the other side conforms by pinning that fixture in a test of its own. The rule, in one line, is re-implement calls, pin formats — and a test asserting a fabrika property lives in fabrika's package.

The evidence that this was already costing something: fabrika's envelope grew a <!-- fabrika:enriched … --> marker line under the #4866 ruling, and the copy of the envelope inside v1's test file — the one whose docblock says "byte for byte" — still has no marker. Nothing went red.

Fixes #4892

What changed

  • .decisions/0251-shared-formats-are-pinned-not-reimplemented.md — the ruling. Extends ADR 0238 (which stands unchanged on calls) and ADR 0241 (whose ownership law this applies to a format whose second party sits outside fabrika). Names the sanctioned gate-deferral carve-out — pitch-guard, homing-guard, cp-classify — explicitly, so the ruled class is not caught by the new rule.
  • claude-plugins/fabrika/README.md — the absent-list's "no dependency on v1" bullet now says what the calls rule does not cover.
  • claude-plugins/fabrika/skills/triage/contract.md — four sites stopped grounding the envelope's survival in epic-splice.ts line numbers (one of which was already two lines stale) and now cite the ruling instead. The observed behaviour is unchanged; what changed is which side owes it.

Against the issue's acceptance criteria

Deviations

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

No preview deploy

  • No preview deploy for this PR — its diff touches no deploy-relevant path, so no preview stack was minted and e2e is not applicable. (042fdee)
  • web — Stage pr-5252 torn down.

@usirin
usirin force-pushed the usirin/adr-epic-envelope-wire-format-4892-018DCBE1 branch from 4621fc4 to 82f3707 Compare August 10, 2026 02:27
@usirin usirin changed the title docs(decisions): 0250 — fabrika pins shared wire formats, and owns their tests (#4892) docs(decisions): 0251 — fabrika pins shared wire formats, and owns their tests (#4892) Aug 10, 2026
@usirin

usirin commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

review-doc: FAIL @ 82f3707 — changes-requested

Reviewed-head: @ 82f3707

Verified PR #5252 against #4892's acceptance criteria + the doc-hygiene checklist. Read the PR head (§HEAD): every file under review was sourced from 82f3707a through a per-run ref, never from the launched checkout's working copy.

Classification — §CP by CONTENT (ADR 0164), not by path. The path axis is clean: a live CODEOWNERS read carries no .decisions/ row and no claude-plugins/fabrika/ row (fabrika is not control-plane, founder veto #5036). But pipeline-cli guard-content-probe classify returns guard-touching on .decisions/0251-shared-formats-are-pinned-not-reimplemented.md ([guard-vocabulary-match]), which puts this PR in the blocking set by content. A clean path read alone was not sufficient — recording it because a bindable PASS here would have been the ADR-0164 routing hole.

Acceptance criteria (#4892)

The AC-3 failure, in detail

claude-plugins/fabrika/skills/plan-epic/contract.md:167-169 — present in this PR's own tree at head, landed in b5465b6a (2026-08-09T21:44:34Z, PR #5178) — already rules:

…with the marker doing the detecting, appending the plan below the brief envelope breaks no detector, so the wrap-last layout inversion, its three coupled changes and its legacy migration are all unnecessary. #4892's remedy (c) — making the --epic envelope independent of a splicer's anchor set — is thereby moot; that issue owns its own ADR write-up and this contract does not pre-empt it.

ADR 0251 ## Sequencing instead says remedy (c) "is deferred, and #4712 is its decider… Whether the anchor relationship dissolves entirely depends on where fabrika's own plan-epic writes its plan, which is #4712's decision (live as Q5 on #4890, riding map #4891). Taking (c) here would decide #4712's question from the wrong seat."

Three problems, all checkable:

  1. Authoring brief: /plan-epic — fabrika skill (wave 2) #4712 is closed (2026-08-09T21:50:05Z), and it closed by delivering exactly the contract quoted above — roughly 4.7 hours before this PR's head commit (2026-08-10T02:26:14Z). The seat the ADR declines to sit in is already occupied; the decision exists.
  2. That contract handed the write-up to this ADR. "That issue owns its own ADR write-up and this contract does not pre-empt it" means ADR 0251 is the document where the mootness was supposed to land. It records a deferral instead, so the answer is written nowhere.
  3. The "live" pointer names three closed issues. Land the 2026-08-07 fabrika skill-set audits as a dated reports/ snapshot (grounding for the design session) #4890 closed 2026-08-09T14:55:03Z, fabrika's skill set — live/die/merge/split over the 16 authoring briefs #4891 closed 2026-08-08T07:07:36Z, and Investigation: can fabrika's plan-epic preserve terminality and unify enrich's two detectors? #4896 — the Q5 investigation the parenthetical points at — closed 2026-08-08T04:59:19Z. Q5 is real (a comment on Land the 2026-08-07 fabrika skill-set audits as a dated reports/ snapshot (grounding for the design session) #4890) but nothing in that chain is live.

The net effect is the failure mode the criterion's "not left silently open" clause exists to prevent, and it leaves two live records disagreeing: a shipped skill contract says remedy (c) is moot, a shipped ADR says it is open pending #4712. Which one an agent obeys depends on which file it opens first.

Remedy. Take remedy (c) as moot rather than deferred, and say why: #4712's plan-epic contract made envelope detection the whole-line fabrika:enriched marker (enrich.ts:41), which is position-independent, so the plan may sit below the brief envelope and the anchor coupling dissolves on its own. Cite that contract's ruling, and drop the (live as Q5 on #4890, riding map #4891) parenthetical or re-point it at the closed record. Nothing else in the ADR needs to move — the fixture pin is correct either way, as the ADR's own ## Not decided here already says.

Doc hygiene

  • [PASS] House-format — ADR 0251 carries id/title/status/date/tags and ## Context / ## Decision / ## Consequences; the extra ## Sequencing / ## Not decided here / ## Records sections match house precedent.
  • [PASS] Index row — no .decisions/index.md committed (ADR 0126, discovery is ambient); frontmatter status: accepted is the rendered source.
  • [PASS] Links resolve — every relative link in the three changed files resolves against the head tree.
  • [PASS] No leaked local/home paths — the shared matcher over the added lines returned clean.
  • [PASS] Supersession noted + cross-linked — 0251 extends 0238 (which it states stands unchanged on calls) and applies 0241's ownership law; neither is narrowed or contradicted, so no forward pointer is owed. 0180's readGoldenFixture is cited and verified to exist.
  • [PASS] Status sanity — accepted is coherent for a record of a founder-delegated ruling.
  • [PASS] Single Diátaxis mode — single-mode: explanation for the ADR; the README and contract additions stay in their hosts' modes.
  • [PASS] Clear, concise prose — active voice, concrete, no AI-tell density.

ADR contradiction sweep (Step 4a)

  • [FAIL] Three questions enumerated (is a shared byte format a call? where does a test asserting a fabrika property live? how does a non-fabrika side conform?); 207 uncited live-accepted ADRs swept; the 8-entry shortlist (0242, 0229, 0245, 0236, 0210, 0073, 0220, 0231) was opened and none rules on a question 0251 re-decides. The two adjacent ADRs — 0238 and 0241 — are both cited and correctly framed as extended, not amended. The conflict is not with an ADR: it is with the shipped skill contract quoted above, which the mechanical sweep does not cover because it sweeps .decisions/ only. Recorded so the miss is visible.

Renumber + collision checks

Closing-keyword check (load-bearing)

  • [PASS] A case-insensitive scan of the whole PR body for a closing keyword followed by an issue number returns exactly one hit — Fixes #4892, in plain prose, not a code span. That matches the expected closing set of exactly #4892. The PR's commit messages carry no closing keyword either. Nothing else will auto-close on merge.

Deviation disclosure (§DEV)

  • [FAIL] deviation-disclosure — the ## Deviations section is present and discloses five departures, including the double renumber, honestly and in detail. It does not disclose the AC-3 departure above: the ADR defers a question that a contract shipped in the same tree calls moot (§DEV class 2, a departure from a governing decision). Disclose it, or take remedy (c) as moot per the remedy above, which removes the departure entirely.

Routing note — this PR needs two more gates. pipeline-cli class-probe classify --namespaces reports three required namespaces for this diff, not one: review-code, review-doc, review-skill. claude-plugins/fabrika/skills/triage/contract.md is has-skills, and claude-plugins/fabrika/README.md matches no class regex so it rides has-code under the §CLASS no-class fail-closed rule. Only review-doc has a verdict at this head; review-code and review-skill are still empty and ship-it will fail-close on them.

Failing items above must be addressed before this PR can merge. The PR stays open and unmerged; #4892 stays open and assigned. Re-request review once they are satisfied.

Note on authority: this PR is §CP by content (ADR 0164), so even a clean review-doc verdict here would be advisory only — a @kamp-us/control-plane approval at head is what authorizes the merge, and ship-it enqueues on it (ADR 0135). review-doc does not merge.

Verdict-written: 2026-08-10T02:42:55Z

usirin added 2 commits August 9, 2026 19:49
review-doc AC-3: the shipped plan-epic contract (#4712, b5465b6) already rules remedy (c) moot, and it handed the write-up to this ADR. Recording a deferral instead left the answer written nowhere and pointed at three closed issues. Verified at the owner module: detection is enrich.ts's whole-line-anchored MARKER_RE matched at its first occurrence, so no splicer anchor set reaches it.
@usirin

usirin commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

review-doc: advisory — PASS (repair round 1 verified; prior FAIL discharged)

Reviewed-head: @ 042fdee
Issue: #4892 · Class: has-docs (.decisions/0251-…md, claude-plugins/fabrika/README.md)
§CP: control-plane by contentcp-classify classifycontent-undetermined [content-source-present] (no path match), then guard-content-probe classifyguard-touching (§CP, ADR 0164) [guard-vocabulary-match] on the ADR. Under ADR 0164 this verdict is advisory (ADR 0111 shape: no first-line @sha; head bound above). A @kamp-us/control-plane approval at this head authorizes the merge, not this comment.

The prior FAIL, re-checked

review-doc: FAIL @ 82f3707a (comment 5235303392) blocked on AC-3: the ADR said remedy (c) was "deferred, #4712 is its decider, live as Q5 on #4890" while plan-epic/contract.md — in this PR's own tree — already ruled it moot, and #4712/#4890/#4891/#4896 are all closed.

  • [PASS] Repaired. ## Sequencing now reads "Remedy (c) is moot — Authoring brief: /plan-epic — fabrika skill (wave 2) #4712 already dissolved the coupling."
  • [PASS] The mootness ruling exists as claimed. origin/main:claude-plugins/fabrika/skills/plan-epic/contract.md:168-169"fabrika's --epic envelope is behaviourally pinned to v1 epic-splice, and its survival invariant is tested inside pipeline-cli #4892's remedy (c) … is thereby moot; that issue owns its own ADR write-up". The ADR is that write-up. Authoring brief: /plan-epic — fabrika skill (wave 2) #4712 confirmed CLOSED 2026-08-09T21:50:05Z.
  • [PASS] The source grounding holds — verified independently at the owner module, not on the ADR's word. packages/fabrika-cli/src/triage/enrich.ts @ this head:
    • L41 export const MARKER_RE = /^<!-- fabrika:enriched issue=(\d+) mode=(rewrite|wrap) -->$/m;whole-line anchored (^…$ under /m), exactly as the ADR states, and no /g, so exec carries no lastIndex state.
    • L70-82 splitAtMarker calls MARKER_RE.exec(body) once and uses match.index — the first match, as the ADR states and as its own docblock declares load-bearing.
    • Therefore detection asks nothing about position, and no splicer anchor set can reach it. The repair's claim is true. Had either half failed, this would be a FAIL again; it does not.

Acceptance criteria

Deviations disclosure

  • [PASS] The reversal is disclosed — entry 28: "(repair round 1) Reversed round 0's remedy-(c) deferral (class: departure from a governing decision, now discharged)", with the two contradicting records, the four closed issues, and the new grounding all named. The prior FAIL's second [FAIL] is discharged.
  • [PASS] Round 0's entry was marked superseded, not rewritten — entry 24 still carries its original "deferred" text with "(Superseded in repair round 1 — see below. Left standing as the log of what round 0 shipped.)" appended. Entry 29 additionally logs the stale-local-ref/rebase hazard.

ADR number 0251

Hygiene

  • [PASS] Scope is exactly the three files. prototyping/, graduate/, handoff/, plan-epic/**, wayfinding/ are absent from the diff.
  • [PASS] Closing set exactly {#4892} — whole-body case-insensitive (fix|close|resolve)[a-z]* +#[0-9]+ returns one prose hit, Fixes #4892. No code-span false positives.
  • [PASS] No home / local / absolute / sibling-repo paths in any changed file. Referenced ADRs 0180 / 0238 / 0241 all exist. check docs have no dead internal links green.
  • [PASS] All CI checks pass or skip; zero non-passing.

Verdict: PASS (advisory). Merge authority is the @kamp-us/control-plane approval at 042fdee.

@usirin

usirin commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

review-skill: advisory — PASS

Reviewed-head: @ 042fdee
Issue: #4892 · Class: has-skills (claude-plugins/fabrika/skills/triage/contract.md)
§CP: control-plane by content (guard-content-probe classifyguard-touching (§CP, ADR 0164) [guard-vocabulary-match] on the ADR in the same diff). Advisory under ADR 0164, ADR 0111 shape.

Round 0 posted only review-doc, leaving this namespace empty. class-probe classify --namespaces returns review-code, review-doc, review-skill for this diff, so this marker closes one of the two gaps.

What changed in the behavioral artifact

The contract stops grounding a fabrika property in another package's line numbers, at four sites — this is AC-4's skill half and the ADR's first binding constraint applied to its own surface.

  • [PASS] Site 1 (L11-18, the clean-cut preamble) — adds the two sanctioned edges (a CI gate stays the authority on its own question; a shared byte format is pinned by fixture) and cites ADR 0251. Correctly frames neither as a call, so ADR 0238 is not re-armed.
  • [PASS] Site 2 (L1019-1025)packages/pipeline-cli/src/tools/epic-splice/epic-splice.ts:48-51 removed. Now reads "A planner splices around the envelope … That is an agreement rather than a coincidence", citing 0251. The observed behaviour claim is unchanged; only which side owes it moved.
  • [PASS] Site 3 (L1090-1094)epic-splice.ts:128-130 removed (the citation fabrika's --epic envelope is behaviourally pinned to v1 epic-splice, and its survival invariant is tested inside pipeline-cli #4892 found already two lines stale). Replaced with a plan-epic-side statement plus the first-time-plan append case, which is fabrika's own behaviour to assert.
  • [PASS] Site 4 (L1176-1189) — the "checked against the implementation" argument is gone; survival is now stated as "the splicer's obligation to this format rather than a fact fabrika inherits", settled in 0251.

Residual citations — checked, all sanctioned

  • [PASS] The one remaining epic-splice mention (L1188) is a bare path with no line numbers, naming where the block presently lives and that it is scheduled to split. That is the ADR's own recorded plan, not a property grounded in v1's source.
  • [PASS] pitch-guard.ts:219-223 / :244-246 / :89-93 remain and are the explicitly sanctioned gate-deferral carve-out the ADR preserves (ADR 0238's "where a question is already decided by a gate, fabrika expects the answer"). The ADR names this class specifically so the new rule does not catch it; correct to leave.
  • [PASS] packages/fabrika-cli/src/triage/enrich.unit.test.ts citations are fabrika's own package — the direction the ADR wants, not a pin.

Skill hygiene

  • [PASS] No behavior change to any verb. The envelope shape, the marker rule, the detector semantics and the idempotency contract are all byte-identical; only the justifying prose moved.
  • [PASS] Consistent with the source at head — enrich.ts L41 MARKER_RE is whole-line anchored (^…$, /m, no /g) and L70-82 splitAtMarker takes the first exec match, so the contract's "re-enrich detector tests position nowhere" is true at the module.
  • [PASS] The known residue (ADR 0241 bans restating a wire format's shape in a skill body; the contract still spells the envelope out) is disclosed in the ADR's Consequences, in the PR's Deviations entry 27, and scoped to Land the epic-envelope wire format: owner module, golden fixture, and the test split #5249. Correct call — there is no owner module to move it into yet.
  • [PASS] All four new ADR links use ../../../../.decisions/… which resolves from claude-plugins/fabrika/skills/triage/. check docs have no dead internal links green. validate skill frontmatter green.
  • [PASS] No home / local / absolute / sibling-repo paths.
  • Not gated: SKILL.md line count — the 7–140 band is repealed (docs(fabrika): delete the dead line band from the sizing convention (#4701) #5240).

Nit, non-blocking: the L1190-1191 sentence wraps mid-clause (in / newline / `…enrich.unit.test.ts` / , which). Cosmetic only.

Verdict: PASS (advisory).

@usirin

usirin commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

review-code: advisory — PASS

Reviewed-head: @ 042fdee
Issue: #4892 · Class: has-code
§CP: control-plane by content (guard-content-probe classifyguard-touching (§CP, ADR 0164) [guard-vocabulary-match]). Advisory under ADR 0164, ADR 0111 shape.

Why this namespace is required

claude-plugins/fabrika/README.md matches none of the three §CLASS regexes (HAS_CODE_RE, HAS_SKILLS_RE — it is not under skills/ or agents/ — nor HAS_DOCS_RE after the ^claude-plugins/ carve-out), so it rides has-code under §CLASS's no-class fail-closed rule. class-probe classify --namespaces confirms: review-code, review-doc, review-skill. Round 0 posted only review-doc; this marker closes the second gap so ship-it does not fail-closed on an empty namespace.

Executable surface

  • [PASS] Zero executable files in the diff. The changed set is exactly .decisions/0251-…md, claude-plugins/fabrika/README.md, claude-plugins/fabrika/skills/triage/contract.md — three markdown files, +216/-19. No .ts, no test, no package.json, no workflow, no config. Nothing to build, type-check or run.
  • [PASS] No import edge created. The ADR's own ban — "an import edge in either direction between fabrika-cli and pipeline-cli" — is trivially satisfied: no source file changed, and the conformance mechanism the ADR rules is a test-time golden-fixture read, not an import or a call. ADR 0238 is not re-armed and v1's retirement is not blocked.
  • [PASS] The one falsifiable source claim in the changed prose checks out — verified at packages/fabrika-cli/src/triage/enrich.ts @ this head rather than taken on the artifact's word (CLAUDE.md's ground-falsifiable-claims rule):
    • L41 export const MARKER_RE = /^<!-- fabrika:enriched issue=(\d+) mode=(rewrite|wrap) -->$/m; — whole-line anchored, /m, no /g.
    • L70-82 splitAtMarkerMARKER_RE.exec(body), single call, uses match.index; with no /g there is no lastIndex carry, so it is deterministically the first match.
    • Consequence: detection is position-independent, so no splicer anchor set can reach it — which is exactly what the ADR asserts to declare remedy (c) moot.
  • [PASS] The README edit is accurate to the ruling. The "no dependency on v1" bullet gains the re-implement calls, pin formats rule, the fixture-conformance direction, and the test-ownership line; it does not weaken or contradict the existing calls prohibition above it.

Repo conventions

  • [PASS] catalog: dep rule — not applicable, no package.json touched (catalog-guard green).
  • [PASS] fate-live fanout rule — not applicable, no mutation touched (fanout-guard green).
  • [PASS] Package README rule — not applicable, no packages/* member added (readme-guard green).
  • [PASS] No home / local / absolute / sibling-repo paths in any changed file.
  • [PASS] Every CI check passes or skips; zero non-passing, including no bare pipeline-cli invocation in runnable shell, scan PR commits for secrets, check docs have no dead internal links and check every registered tool has a one-line description.

Verdict: PASS (advisory) — vacuous on executable surface, and the source claim the changed prose rests on is verified true at the owner module.

@usirin usirin added the status:cp-banked Control-plane PR banked on the board, awaiting a control-plane approval label Aug 10, 2026
@usirin
usirin requested a review from notusirin August 10, 2026 03:03
@usirin
usirin added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit 6c22230 Aug 10, 2026
46 checks passed
@usirin
usirin deleted the usirin/adr-epic-envelope-wire-format-4892-018DCBE1 branch August 10, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:cp-banked Control-plane PR banked on the board, awaiting a control-plane approval

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fabrika's --epic envelope is behaviourally pinned to v1 epic-splice, and its survival invariant is tested inside pipeline-cli

2 participants