Skip to content

feat(cli): stamp commits with the AIDD run id #630

Closed

Description

@blafourcade

As a team measuring AI spend
I want each agent commit to carry the session that produced it
So that cost attaches at commit precision, not only at session precision

Acceptance

  • A commit created by an agent in an enabled repository carries AIDD-Session-Id.
  • The trailer carries the AIDD aidd_id, never a vendor identifier.
  • A commit created by a human while a session is open carries no trailer, including when it lands in the window between the marker being written and the agent's own commit.
  • Installing on a repository using core.hooksPath, one using lefthook, one using husky, and one using none, leaves every pre-existing handler invoked on commit, asserted by its side effect.
  • A failing, missing or slow hook never blocks a commit; the commit succeeds unstamped, and the hook returns under 200 ms at p95.
  • Disabling removes the entries it added and nothing else.
  • git log --format='%(trailers:key=AIDD-Session-Id,valueonly)' returns the identifiers.

Scope

Two halves, because neither can do it alone. The host hook knows the session id but cannot write the commit message; the git hook owns the message but knows nothing about the session.

  1. Host hook on PreToolUse for Bash: when the command is a git commit, write a one-shot marker under $(git rev-parse --absolute-git-dir)/aidd/.
  2. Git hook prepare-commit-msg: consume the marker — read, then delete — and append the trailer with git interpret-trailers.

Consuming the marker is the guarantee: one marker, one commit.

The concurrent-human case needs a real answer, not a claim. Marker consumption alone does not exclude a human commit landing in the same window; that commit would consume the marker and be stamped. Scoping the marker to the agent's own invocation is part of this issue, not an assumption of it.

Hook manager detection is load-bearing. Writing .git/hooks/prepare-commit-msg on a repository that sets core.hooksPath produces a hook git never runs, and a silent hole in the data. Observed live during this design work: a worktree on the author's machine had core.hooksPath pointing at a different path's .git/hooks.

Why this is not in the first milestone

The run journal already covers sessions that produce no commit — planning, exploring, debugging, answering a review — which are the most expensive and the worst counted. The trailer adds precision per commit, not the ability to measure.

Out of scope

  • The diagnostic and the report, which are skills.
  • Rewriting history to stamp past commits.

Relations

Field Value
parent #652
depends_on #620

Activity

  1. added this to the milestone on Aug 14, 2026
  2. blafourcade commented on Aug 20, 2026

    @blafourcade
    ContributorAuthor

    Why this matters more than the acceptance criteria above suggest

    Measured while building #663's journal, and it sharpens the case for this ticket.

    The run journal records a file_written line only when the path looks like a task folder (aidd_docs/tasks/<yyyy_mm>/<slug>/). That filter is a volume decision, not a task-identity one - it keeps the hook from appending a line for every stray Write in a repository. But it has a consequence the journal cannot fix on its own:

    A session spent entirely outside the task flow leaves a cost with no content. Debugging, an ad-hoc prompt, a refactor driven from chat - the collector still records what it cost, the journal still records that the session happened and which skills ran, and nothing anywhere records what it produced.

    And separately: nothing in the repository distinguishes what a human wrote from what an agent wrote.

    A commit trailer answers both at once, at commit precision rather than session precision, which is why this ticket is the right shape for it rather than widening the journal's filter.


    Closing #679 as a duplicate of this. It was filed without checking the backlog first; this ticket came first and is more precise - it already pins the trailer to the AIDD aidd_id rather than a vendor identifier, and already names the core.hooksPath / lefthook / husky coexistence and the p95 budget, none of which #679 covered.

  3. moved this from Ideation to Todo in AIDD Roadmapon Aug 20, 2026
  4. blafourcade commented on Sep 2, 2026

    @blafourcade
    ContributorAuthor

    Delivered by #706, squash-merged into next as 627408f.

  5. blafourcade commented on Sep 11, 2026

    @blafourcade
    ContributorAuthor

    Closed for the delivered commit-to-session link, with the remaining hook-lifecycle work owned by #746.

    #706 proves the core path on real commits: an AI-session commit carries AIDD-Session-Id, a commit without a session carries nothing, amend does not duplicate it, telemetry off stops it, and an existing prepare-commit-msg still runs.

    The trailer value is the existing session anchor (CLAUDE_CODE_SESSION_ID or CODEX_THREAD_ID), not a separately minted AIDD identifier. That keeps the commit directly joinable to the telemetry records.

    #746 owns the unproven host layouts, regenerated-hook repair, diagnostic coverage, and timing bound.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    Priority

    High

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions