Summary
Filed by an agent is a literal string that fabrika's report file writes into every issue footer, and that v1's triage reads to decide whether an issue was agent-filed (auto-closable) or hand-typed by a human (structurally protected, never swept). Nothing pins one side's bytes against the other's expectation — fabrika's tests pin only its own output, and triage states its expectation as prose in a SKILL.md. A reword on either side leaves both sides green while the seam silently breaks, and the breakage looks exactly like a healthy backlog.
What I was doing
Reviewing the /report producer/consumer seam after PR #4757 (feat(fabrika-cli): the three /report verbs — dedup, file, note, from #4748) landed the fabrika-side footer composition, and tracing what actually carries provenance between fabrika and v1 triage.
What I observed
The marker is a wire format, not prose. It is ADR 0159's never-auto-close signal, and the only usable provenance signal between two independently-versioned systems.
Producer — packages/fabrika-cli/src/report/compose.ts:98, where the literal is hardcoded as the first element of the footer's parts array and joined with · inside ---\n<sub>…</sub> (render at :104):
const parts = [
"Filed by an agent",
fields.session === null ? null : `session \`${fields.session}\``,
…
].filter((p): p is string => p !== null);
return `---\n<sub>${parts.join(" · ")}</sub>`;
Consumer — claude-plugins/kampus-pipeline/skills/triage/SKILL.md (the provenance block, ~L460–493), which matches <sub>Filed by an agent · …</sub> and calls the literal marker the signal.
The semantics it carries:
- marker present ⇒ agent-filed ⇒ eligible for auto-close after confirmation
- marker absent ⇒ hand-typed by a human ⇒ structurally protected, never closed by a sweep
Authorship cannot serve this role: every pipeline-filed issue goes through one shared login, so GitHub's author field is constant across both humans and agents. The literal string is all there is.
The defect: nothing pins the producer's bytes against the consumer's expectation.
packages/fabrika-cli/src/report/compose.unit.test.ts pins fabrika's own output string — including a test explicitly named for never dropping the marker, and a sparse-footer case proving it survives when every optional field is absent. Good tests. They pin one side.
- Triage states its expectation in prose in a SKILL.md. There is no executable assertion.
So a reword on either side leaves both sides green independently while the seam silently breaks. No test fails, no guard reds, no CI job notices.
Why the failure is invisible rather than loud. If the marker drifts, triage reclassifies every fabrika-filed issue as human-typed. That direction fails safe — over-protection, not data loss; nothing gets wrongly closed. That is exactly what makes it dangerous to operate: the symptom is kill sweeps quietly finding nothing to close, which looks identical to a healthy backlog with no stale agent-filed issues. There is no error state to notice. The system degrades into permanent over-protection and reports success the whole way.
This is the same defect class this campaign has catalogued repeatedly (#4520, #4700, #4666, #4752, #4754): a check that cannot see what it is looking for, failing as a plausible value rather than as an error. Here the "check" is triage's provenance test, and the plausible value is "human-typed."
What is already right — a fix must not regress it:
- The producer treats the marker as unconditional, not a droppable field — first element of the parts array, outside the
null-filter that removes absent optional fields.
packages/fabrika-cli/src/report/file-verb.ts:81 performs a read-back assertion: after creating the issue it re-reads the body and refuses if the marker is absent (the body is missing the \Filed by an agent` marker`), so a composition regression fails loudly at file time rather than silently producing an unmarked issue.
report note deliberately does not emit the marker, and a test asserts its absence. That is correct — a note is a comment, not an issue, and issue provenance does not belong on it. A naive "make everything emit the marker" fix would be wrong.
- Triage's five-section fingerprint is a soft recognizer that explicitly leans on the marker and tolerates missing best-effort fields. A sparse footer is still a footer. The marker is the invariant; the rest is not.
Why it matters
The two protections that exist both sit on the producer's side of the seam: fabrika's unit tests and its read-back assertion both catch fabrika drifting from itself. Neither can see the consumer. If triage's matcher is reworded — or if a future producer change alters the surrounding <sub>/· envelope that triage's pattern depends on — every fabrika-filed issue silently becomes "human-typed" and permanently exempt from auto-close.
The operational cost is not a wrong close; it is a sweep that reports success while doing nothing, indistinguishable from a clean backlog. Backlog hygiene degrades with no signal that it has stopped working, and the degradation is only discoverable by someone independently noticing that agent-filed issues never get closed anymore.
Pointers
Suggested next step (non-binding)
Guesses only; triage owns the decision.
- A single shared constant both sides import, so a reword is a compile error rather than a silent divergence. Complicated by the fact that one side is a skill's markdown and the other is TypeScript — and by ADR 0238, which forbids
fabrika-cli importing anything from packages/pipeline-cli/ or claude-plugins/kampus-pipeline/. A fix must not create a tether; that constraint is load-bearing and a naive shared-import fix violates it.
- Or an executable conformance check that reads the marker out of the consumer's stated contract and asserts the producer emits it — a test that fails if either side moves, owned by neither.
- Worth recording either way: two systems deliberately forbidden from calling each other still share a wire format, and that seam needs a pin that is not a call.
Filed by an agent · session fcd74bd3-8872-4023-b100-a81ac870eb43 · branch main · 2026-08-02T19:09:46Z
Summary
Filed by an agentis a literal string that fabrika'sreport filewrites into every issue footer, and that v1's triage reads to decide whether an issue was agent-filed (auto-closable) or hand-typed by a human (structurally protected, never swept). Nothing pins one side's bytes against the other's expectation — fabrika's tests pin only its own output, and triage states its expectation as prose in a SKILL.md. A reword on either side leaves both sides green while the seam silently breaks, and the breakage looks exactly like a healthy backlog.What I was doing
Reviewing the
/reportproducer/consumer seam after PR #4757 (feat(fabrika-cli): the three /report verbs — dedup, file, note, from #4748) landed the fabrika-side footer composition, and tracing what actually carries provenance between fabrika and v1 triage.What I observed
The marker is a wire format, not prose. It is ADR 0159's never-auto-close signal, and the only usable provenance signal between two independently-versioned systems.
Producer —
packages/fabrika-cli/src/report/compose.ts:98, where the literal is hardcoded as the first element of the footer's parts array and joined with·inside---\n<sub>…</sub>(render at:104):Consumer —
claude-plugins/kampus-pipeline/skills/triage/SKILL.md(the provenance block, ~L460–493), which matches<sub>Filed by an agent · …</sub>and calls the literal marker the signal.The semantics it carries:
Authorship cannot serve this role: every pipeline-filed issue goes through one shared login, so GitHub's author field is constant across both humans and agents. The literal string is all there is.
The defect: nothing pins the producer's bytes against the consumer's expectation.
packages/fabrika-cli/src/report/compose.unit.test.tspins fabrika's own output string — including a test explicitly named for never dropping the marker, and a sparse-footer case proving it survives when every optional field is absent. Good tests. They pin one side.So a reword on either side leaves both sides green independently while the seam silently breaks. No test fails, no guard reds, no CI job notices.
Why the failure is invisible rather than loud. If the marker drifts, triage reclassifies every fabrika-filed issue as human-typed. That direction fails safe — over-protection, not data loss; nothing gets wrongly closed. That is exactly what makes it dangerous to operate: the symptom is kill sweeps quietly finding nothing to close, which looks identical to a healthy backlog with no stale agent-filed issues. There is no error state to notice. The system degrades into permanent over-protection and reports success the whole way.
This is the same defect class this campaign has catalogued repeatedly (#4520, #4700, #4666, #4752, #4754): a check that cannot see what it is looking for, failing as a plausible value rather than as an error. Here the "check" is triage's provenance test, and the plausible value is "human-typed."
What is already right — a fix must not regress it:
null-filter that removes absent optional fields.packages/fabrika-cli/src/report/file-verb.ts:81performs a read-back assertion: after creating the issue it re-reads the body and refuses if the marker is absent (the body is missing the \Filed by an agent` marker`), so a composition regression fails loudly at file time rather than silently producing an unmarked issue.report notedeliberately does not emit the marker, and a test asserts its absence. That is correct — a note is a comment, not an issue, and issue provenance does not belong on it. A naive "make everything emit the marker" fix would be wrong.Why it matters
The two protections that exist both sit on the producer's side of the seam: fabrika's unit tests and its read-back assertion both catch fabrika drifting from itself. Neither can see the consumer. If triage's matcher is reworded — or if a future producer change alters the surrounding
<sub>/·envelope that triage's pattern depends on — every fabrika-filed issue silently becomes "human-typed" and permanently exempt from auto-close.The operational cost is not a wrong close; it is a sweep that reports success while doing nothing, indistinguishable from a clean backlog. Backlog hygiene degrades with no signal that it has stopped working, and the degradation is only discoverable by someone independently noticing that agent-filed issues never get closed anymore.
Pointers
packages/fabrika-cli/src/report/compose.ts— the producer (marker at:98, footer render at:104)packages/fabrika-cli/src/report/compose.unit.test.ts— the one-sided pinpackages/fabrika-cli/src/report/file-verb.ts— the read-back assertion at:81claude-plugins/kampus-pipeline/skills/triage/SKILL.md— the consumer's provenance block (~L460–493).claude/.pipelinelink is absent — "never ran" can read as "said no" #4666, spec defect: report dedup reports "none" over a nonexistent --label — a proven negative on zero scope #4752, banking a §CP PR does not arm the approval-watcher — an approved PR can strand indefinitely with no error #4754Suggested next step (non-binding)
Guesses only; triage owns the decision.
fabrika-cliimporting anything frompackages/pipeline-cli/orclaude-plugins/kampus-pipeline/. A fix must not create a tether; that constraint is load-bearing and a naive shared-import fix violates it.Filed by an agent · session
fcd74bd3-8872-4023-b100-a81ac870eb43· branchmain· 2026-08-02T19:09:46Z