Development record
The attribution gate is provider-asymmetric: its POSITIVE check is vendor-agnostic while its NEGATIVE check and the prose it enforces are Claude-specific, so the gate stops the failure it was built for only as long as the assisting model is Claude. Verified 2026-08-11 against scripts/check-attribution.sh: TRAILER_RE accepts any '<Vendor>:<version>' pair, so 'Assisted-by: OpenAI:gpt-5' and 'Assisted-by: Google:gemini-3' both PASS — correct and desirable. But GENERATED_RE bans only 'Generated with [', the robot-emoji 'Generated with', and 'Co-authored-by: Claude' / 'Co-Authored-By: Claude', so a body carrying 'Co-authored-by: ChatGPT <bot@openai.com>' alongside a valid trailer PASSES. That is precisely the failure mode the workflow header says it exists to stop — itd-91 records a reconciliation sweep across 78 pull requests after PR bodies picked up a tool's default footer — merely wearing a different vendor's name. The AI-co-authorship objection AGENTS.md:132 states is about authorship the tool does not hold and contributor-graph inflation, neither of which is Claude-specific. Second half of the same asymmetry: the documented convention hardcodes one vendor in the template — CONTRIBUTING.md:31 writes 'Assisted-by: Claude:<model-version>' and AGENTS.md:132 gives 'Assisted-by: Claude:claude-opus-4-8' — so prose names a vendor the gate does not require, leaving a contributor using another provider without a stated correct form even though the gate would accept one. Fix direction is itd-91's, whose scope is a per-repo declared attribution preference every surface reads; .github/workflows/attribution.yml calls itself a stopgap until that lands, and iss-211 already raises itd-91's priority on multi-project adoption. Two things this record asks of that work specifically: make the co-authorship ban match on the TRAILER KEY rather than on a vendor name, so 'Co-authored-by:' naming any AI is refused; and state the convention as '<Vendor>:<model-version>' with Claude as an example rather than as the literal.
The attribution gate is provider-asymmetric: its POSITIVE check is vendor-agnostic while its NEGATIVE check and the prose it enforces are Claude-specific, so the gate stops the failure it was built for only as long as the assisting model is Claude. Verified 2026-08-11 against scripts/check-attribution.sh: TRAILER_RE accepts any '<Vendor>:<version>' pair, so 'Assisted-by: OpenAI:gpt-5' and 'Assisted-by: Google:gemini-3' both PASS — correct and desirable. But GENERATED_RE bans only 'Generated with [', the robot-emoji 'Generated with', and 'Co-authored-by: Claude' / 'Co-Authored-By: Claude', so a body carrying 'Co-authored-by: ChatGPT bot@openai.com' alongside a valid trailer PASSES. That is precisely the failure mode the workflow header says it exists to stop — itd-91 records a reconciliation sweep across 78 pull requests after PR bodies picked up a tool's default footer — merely wearing a different vendor's name. The AI-co-authorship objection AGENTS.md:132 states is about authorship the tool does not hold and contributor-graph inflation, neither of which is Claude-specific. Second half of the same asymmetry: the documented convention hardcodes one vendor in the template — CONTRIBUTING.md:31 writes 'Assisted-by: Claude:<model-version>' and AGENTS.md:132 gives 'Assisted-by: Claude:claude-opus-4-8' — so prose names a vendor the gate does not require, leaving a contributor using another provider without a stated correct form even though the gate would accept one. Fix direction is itd-91's, whose scope is a per-repo declared attribution preference every surface reads; .github/workflows/attribution.yml calls itself a stopgap until that lands, and iss-211 already raises itd-91's priority on multi-project adoption. Two things this record asks of that work specifically: make the co-authorship ban match on the TRAILER KEY rather than on a vendor name, so 'Co-authored-by:' naming any AI is refused; and state the convention as '<Vendor>:<model-version>' with Claude as an example rather than as the literal.
Frontmatter
| id | iss-215 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-215-attribution-gate-is-provider-asymmetric.md
open on GitHub ↗ · commit history ↗
mentions3
- iss-211Multi-project adoption raises the priority of itd-91 (AI-attribution preference) and itd-92 (branch-protection verification) from 'good hygiene' to 'the product claim'. What abcd-cli has today is its OWN answer hard-coded: scripts/check-attribution.sh names specific banned footers and a fixed required trailer, and .github/workflows/attribution.yml is a hand-written file in one repo. Neither is portable, which is exactly the gap itd-91 already states — a project adopting abcd inherits abcd's preference by reading its docs but has no first-class way to declare its own (Co-Authored-By, none at all, or house style). The durable home is a rule in internal/core/lint beside deliverystate, indexdrift and citations: reachable from CLI and plugin, run in any managed repo, reading a declared per-repo preference rather than a constant. Two further observations from the 2026-08-11 session. (1) SCAFFOLD IS THE DELIVERY MECHANISM. internal/core/launch/scaffold renders exactly three artefacts into a managed repo today (release.yml, auto-release.yml, the runbook); an attribution workflow becomes the fourth, so every managed repo inherits the gate from one template instead of someone copying a file. It would automatically gain the self-scaffold parity property — and with it the dependabot pin problem of iss-209, which the sync tool merged in PR #215 already handles. The work just landed is the delivery rail for making this portable. (2) ITD-92 GATES EVERYTHING ELSE. A scaffolded gate that no repo adds to its required status checks is decoration; across N repos the required-check wiring and the enforce_admins policy stop being settings a maintainer clicks and become policy abcd asserts and verifies. That makes itd-92 arguably the higher-leverage of the pair: it is what converts every abcd-scaffolded check, present and future, from advisory into binding. itd-92's own capture note already says this in miniature — 'captured 2026-07-17, the day abcd-cli's own main was protected by hand — work the tool should carry for every repo it manages'. Both intents are still ungrilled drafts.
- iss-2608290810032799The attribution gate validates the Assisted-by trailer's SHAPE but cannot tell whether the model id names the model that actually did the work, so a wrong but well-formed id passes green. In the itd-150..162 run four implementation agents were briefed with an incorrect model id: two used it as instructed and their commits passed the gate, two recognised it as a false disclosure and stamped their real id instead. The convention exists precisely to prevent a false disclosure, and the gate is blind to the only failure that matters. A full mechanical fix may be impossible because the runner cannot attest which model produced a commit, but two partial rungs exist: refuse a vendor and model pair absent from a maintained known-models list, so a typo or a stale id is caught; and have the dispatching harness supply its own model id to the agent, so a hand-written briefing cannot introduce a wrong one. Distinct from iss-211 (making the attribution preference portable) and iss-220 (composing the trailer at creation time): this is about the truthfulness of a trailer that is present and well-formed.
- itd-91A Project Declares Once How It Wants AI Acknowledged — And Every Commit, PR, And Record Follows