LearnNewsExamplesServices
Frontmatter
id17195
titleCo-author trailers credit real human accounts, and the guard is blind off-domain
stateClosed
labels
bugaibuild
assigneesneo-opus-ada
createdAtAug 15, 2026, 6:49 PM
updatedAtAug 15, 2026, 11:22 PM
githubUrlhttps://github.com/neomjs/neo/issues/17195
authorneo-opus-ada
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 15, 2026, 11:22 PM

Co-author trailers credit real human accounts, and the guard is blind off-domain

neo-opus-ada
neo-opus-ada commented on Aug 15, 2026, 6:49 PM

Context

Operator escalation, 2026-08-15. GitHub's Top committers insight for this repo credits two accounts that belong to no maintainer on this project — 9 commits to one, 3 to another. The operator's own login is neither. His words: hallucinated identities causing real damage.

They are not commit authors. They are Co-Authored-By trailers, and GitHub resolves a trailer by its email address and credits whatever account owns it — the display name in the trailer is cosmetic. A trailer naming an agent, carrying a real person's address, credits that person.

#16280 built a guard for exactly this class and closed. This ticket is that guard's insufficiency, not a duplicate of it: three independent properties of the shipped check let the damaging case through untouched.

Addresses are deliberately not reproduced below. One is a personal address and one carries a client-identifying domain; both are real and neither belongs in a public artifact. They are enumerable from git log by anyone who needs them.

The Problem

Measured across all refs, 36h window, grouped by the committing agent:

emitting agent trailer address class commits
one agent seat a personal off-domain address 10
same seat the operator's harness-injected address, under that agent's own display name 6
another seat (mine) an on-domain address that is not that seat's commit identity 5

The second row is the sharpest: the trailer reads as the agent crediting itself, while the address credits a human account.

Root cause is systemic, not carelessness. The operator's address is injected into every agent's context by the harness as a standing field. Any agent composing a trailer can reach for it, and the current guard cannot stop it. A rule that depends on no agent ever reaching for a value that is placed in front of every agent has already failed.

The existing module's own JSDoc names the mechanism from the previous round: "Every address below is observed in committed history, never derived from a handle. Deriving is the defect this module exists to catch." Seats are still deriving.

The Architectural Reality

buildScripts/util/agentCoAuthorEmails.mjsfindUnknownCoAuthors() is the check. Three properties, each independently sufficient to miss this:

1. Domain-scoped, so it is blind to the damaging set.

if (!email.endsWith('@neomjs.com') || known.has(email) || seen.has(email)) continue

The scoping is deliberate and its stated reason is sound — "a trailer for a human contributor, an outside collaborator, or a bot is out of scope and can never warn", so the guard cannot wall off someone whose address it was never meant to know. The consequence is that every off-domain address is invisible, and off-domain is precisely where a real person's account lives. It catches the on-domain row above and cannot see the other two.

This is a carve-out that quiets a guard opening a silent channel: the reasoning was right and the blind spot it created is the half that does harm.

2. Advisory. It never blocks.

check-commit-authorship.mjs prints This is advisory — the push proceeds. Even for the row it can see, nothing stops.

3. Hook-only. Wired at .husky/pre-push:16 and nowhere else, so --no-verify or any environment without husky bypasses it. spec-retirement-lint.yml:22 already records both pre-push guards as hook-only.

The adjacent operator-identity guard in the same file does block (process.exit(1)) — but it inspects the commit author only, never trailers. The blocking guard and the trailer guard are disjoint.

The Fix

Make the allowlist author-aware and domain-independent.

The rule: when a commit's author is a roster agent, every Co-Authored-By on that commit must be a roster address — regardless of domain.

This closes the off-domain channel completely while preserving the exact case the original scoping protected. An outside human contributor's commit is not agent-authored, so their trailers remain out of scope by construction rather than by a domain heuristic. The boundary moves from "which domain is this address on" — which cannot distinguish a fabricated address from a legitimate outside one — to "who authored this commit", which is known exactly.

Concretely:

  • findUnknownCoAuthors() takes the commit author email and returns offenders when the author is a known roster address and a trailer is not.
  • The check fails (non-zero exit) for the agent-authored case rather than warning.
  • Add a CI workflow so the gate is not hook-only. Pre-push stays as the fast local signal.

Existing merged commits are not repairable — the trailers are in merged history on dev and rewriting it is off the table. This gate stops the bleeding; the historical credits stand as noise.

Acceptance Criteria

  • A commit authored by a roster agent carrying a Co-Authored-By whose address is not in EMAIL_BY_LOGIN is reported, whatever the domain — proved by a fixture using an off-domain address, which the current implementation passes
  • The agent-authored case exits non-zero. A fixture asserting the current advisory behaviour must go red
  • A commit whose author is NOT a roster agent is unaffected — an outside contributor's trailers still cannot warn, proved by its own fixture rather than by the domain rule that used to imply it
  • The gate runs in CI, not only in .husky/pre-push, and the CI arm is proved by a run rather than by the workflow file existing
  • The advisory text is replaced by a message naming the actual consequence: GitHub credits the account owning the address, so a fabricated trailer credits a real person
  • reconcileWithRegistry()'s existing drift detection is preserved

Out of Scope

  • Rewriting merged history. The 16 commits are on dev. Prevention only.
  • The noreply@* rule in AGENTS.md §critical_gates. Still correct, still narrower than this; a denylist of one pattern is not the mechanism.
  • The operator-identity author guard in the same file. It works, it blocks, and it addresses a different failure.
  • Removing the harness's injected operator address. Not ours to change, and a gate that assumes it will disappear is the same class of mistake as assuming nobody will derive.
  • Whether agents should emit co-author trailers at all. A real question — most of these commits have a single author — but a separate one from making the trailers truthful.

Avoided Traps

  • Widening the domain allowlist. Adding more domains keeps the denylist shape and fails on the next address nobody enumerated.
  • Reading the guard's existence as coverage. #16280 shipped a check for this exact class and closed; the class recurred at higher severity. A guard that warns is not a guard that gates.
  • Blaming a seat. The operator's address is placed into every agent's context by the harness. The next seat will reach for it too.
  • Deleting the domain check outright. That would wall off outside contributors, which is the harm the original scoping correctly avoided. The author-aware form is what preserves it.

Evidence class

L2 — the offender inventory is reproducible from git log --all over the window, grouped by author; the three guard properties are readable at the cited lines.

Related

#16280 (the guard this extends — closed, and its check is the one that missed this) · #12535 (per-clone commit-identity provisioning) · AGENTS.md §critical_gates item 4 (the noreply@* rule)

Origin Session ID: 00348bc3-c011-4035-90a3-f0eb62b8c95c

Retrieval Hint: query_raw_memories("co-author trailer credits a real account domain-scoped guard blind off-domain") · falsification anchor: the !email.endsWith('@neomjs.com') early-continue in findUnknownCoAuthors.

Live latest-open sweep: latest 20 open issues at 2026-08-15T16:50Z plus a targeted co-author trailer attribution operator email search over 100 open+closed — nearest is #16280, CLOSED, whose fix this corrects. A2A in-flight claim sweep: 12 most recent across all read-states — no competing claim. Structure-map gate: N/A, modifies existing build scripts, no file relocated.

tobiu referenced in commit a2347a0 - "fix(build): co-author trailers on agent commits are gated by roster, not domain (#17195) (#17196) on Aug 15, 2026, 11:22 PM
tobiu closed this issue on Aug 15, 2026, 11:22 PM