This is part nine of Ship the Proof. The previous part argued that DORA metrics go wrong unless you segment AI-assisted changes from the rest, and that the cohort label has to be recorded as fact, not guessed afterward. This part is how you record it so the label is worth trusting.

A developer accepts a few AI completions, finishes the change by hand, and commits. The editor quietly adds Co-authored-by: Copilot to the message. The developer never typed that line, never reviewed it, and in some cases had AI features explicitly turned off. That is not a hypothetical. It is the kind of provenance you cannot trust, and it is why “just use co-authored-by” is the wrong answer for recording AI involvement.

If you want to know later which changes were AI-assisted, for the cohort analysis that makes your delivery metrics honest, for an audit, for a security review after the fact, you need that record to be a deliberate, durable fact. Two places matter: the commit, and the build provenance. Both have a conformant way to carry the metadata, and Co-authored-by is neither.

Why co-authored-by is the wrong field

Co-authored-by is a human-identity trailer. It asserts that a named person co-wrote the change and shares authorship credit. Pointing it at an AI tool overloads a field that means something specific, and the tooling that populates it has demonstrably gotten it wrong.

VS Code 1.117 changed the AI co-author setting default to on, and the release history is candid: “there was a bug in the code that was not found in testing that attributed non-Copilot code completions to Copilot,” emitting Co-authored-by: Copilot “even when the disableAIfeatures setting was turned on.” The default was reverted in 1.118, with permanent fixes in 1.119 (microsoft/vscode#314311).

Read that carefully. The trailer was added to commits where AI was disabled. Provenance was rewritten after the developer’s last review, by a tool the developer was not watching. A field that can be silently mutated to say the opposite of the truth is not a provenance record. It is noise that looks like signal. And because it overloads a human-credit field, you cannot even cleanly distinguish “a person named Copilot co-authored this” from “a tool was involved.”

Use a dedicated disclosure trailer

The invariant: disclose AI assistance in a field built for disclosure, separate from human authorship credit, so the human stays the accountable author and the tool is recorded without being credited.

Open-source projects that take this seriously have converged on exactly that. The Linux kernel prescribes an Assisted-by: trailer and is explicit on the line you must not cross: “AI agents MUST NOT add Signed-off-by tags. Only humans can legally certify the Developer Certificate of Origin (DCO)” (kernel coding-assistants). Fedora’s policy uses a similar Assisted-by: trailer and holds that “the contributor is always the author and is fully accountable” (Fedora AI-assisted policy).

The shape of the convention matters more than the exact spelling. Assisted-by records that AI helped without claiming AI authored or certified anything. The human remains the author and the accountable party. The AI is disclosed, not credited. Inject it at commit time with a prepare-commit-msg hook, the documented point “right after preparing the default log message, and before the editor is started” (git githooks):

# .git/hooks/prepare-commit-msg
# Flatten to one line so a newline in AI_AGENT cannot inject extra
# trailers (a smuggled Signed-off-by would defeat the DCO rule above).
agent=$(printf '%s' "${AI_AGENT:-}" | tr -d '\n\r')
[ -n "$agent" ] && git interpret-trailers --in-place \
  --trailer "Assisted-by: $agent" "$1"

One precision point for anyone writing tooling against these: git trailers “look similar to RFC 822 e-mail headers” but git explicitly disclaims following the RFC 822 rules (git interpret-trailers). Parse them with git interpret-trailers, not an email header parser.

Carry it into build provenance, conformantly

The commit trailer is the authoring record. The build provenance is the artifact record, and SLSA has a defined place for vendor extensions rather than requiring you to invent one. The provenance predicate holds externalParameters for inputs under external control, and extension fields “SHOULD use names of the form <vendor>_<fieldname>” and “MUST NOT alter the meaning of any other field” (SLSA provenance predicate).

So in the build, extract the Assisted-by trailers from the commit range and place them under a vendor-namespaced key:

"externalParameters": {
  "myorg_ai_authoring": { "assisted_by": ["<agent:model>"], "source_ref": "<sha>" }
}

A consumer that does not recognize myorg_ai_authoring ignores it and interprets the attestation identically to one without it. That is the conformance guarantee: you carry your extension without breaking anyone else’s verifier.

Anchor autonomous builds with identity, not a self-asserted string

The trailer convention assumes a human is in the loop, accountable for the change. As more of the work is done by autonomous agents, “who ran this build” gets sharper, and you cannot answer it with a string in a commit message that anyone can type. You answer it with the build’s own identity.

Sign the provenance keyless, using the build job’s OpenID Connect identity rather than a stored key, and anchor the record to the workflow execution through its identity claims (the workflow ref, the repository, the run, the commit) (GitHub OIDC). The signature ties the attestation to a specific workflow at a specific commit, an identity an attacker cannot forge by editing a commit message. Verify the whole thing end to end: that the signature checks against the expected workflow identity, and that your vendor field survived into the signed predicate.

The result is a record that says which commits in a build were AI-assisted, carried in a signed attestation tied to a real workflow identity, with the human author still on the hook. That is provenance you can act on, and it is the opposite of a co-author line a tool slipped in while no one was looking.

The final part of this series steps back from any single signal and asks how to observe the whole pipeline, so a deploy that stalls or an attestation that fails to verify produces a signal a human actually acts on.

Sources