Files
Gitea-Tools/docs/llm-agent-sha.md
T
sysadmin 86141bfa0f docs: LLM-Agent-SHA opaque attribution convention, Phase 0 (#86)
Implements the Phase 0 owner decision on #86 (issuecomment-1354):

- docs/llm-agent-sha.md: format llm-<12 lowercase hex> (^llm-[0-9a-f]{12}$),
  generation rules, per-PR/workstream lifetime, visible markdown metadata
  blocks, no SHA in branch/worktree names, same-SHA vs same-user vs
  same-profile distinction. Attribution only — never an eligibility input.
- docs/llm-workflow-runbooks.md: attribution subsection + handoff/review
  runbook pointers.
- templates start-issue.md / review-pr.md: handoff and review metadata
  blocks; reviewer rule that a different SHA is not a different actor.
- tests/test_llm_agent_sha.py: negative tests — same Gitea user with a
  different LLM-Agent-SHA still fails self-review and self-merge; eligibility
  results are identical with/without/across SHA env values; no gate accepts
  or reads any agent-SHA input.

No launcher/env handling, no gitea_whoami fields, no PR auto-injection, no
audit schema changes. No eligibility behavior changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 14:33:02 -04:00

5.0 KiB

LLM-Agent-SHA — Opaque Agent Attribution (Phase 0)

Convention for attributing work to a specific LLM session/workstream across issues, branches, PRs, and review handoffs, without exposing a human or model identity. Approved by the owner decision on issue #86 (#issuecomment-1354); this document implements Phase 0 only.

The one rule that matters

LLM-Agent-SHA is informational attribution metadata only. It must never be used for authentication, authorization, review eligibility, merge eligibility, profile permissions, or any other security decision.

The security gates remain, unchanged:

  • the authenticated Gitea user (self-review/self-merge protection),
  • the active MCP profile and its allowed_operations (see gitea-execution-profiles.md),
  • the fail-closed eligibility checks in gitea_check_pr_eligibility.

Two sessions with different LLM-Agent-SHA values that authenticate as the same Gitea user are the same actor for review/merge safety. A different SHA never unlocks self-review or self-merge. tests/test_llm_agent_sha.py proves the eligibility logic never consults the SHA.

Format

LLM-Agent-SHA: llm-<12 lowercase hex chars>

Validation regex:

^llm-[0-9a-f]{12}$

Examples: llm-8f3a9c2d6b41, llm-41d0e7aa9f2c, llm-b7c93d441a08.

Generation

Generate 48 random bits, e.g. python3 -c "import secrets; print('llm-' + secrets.token_hex(6))", or hash a non-secret session UUID. An operator-provided opaque ID is also fine.

Do not derive the value from any of:

  • a Gitea token or other secret,
  • an email address or username,
  • a machine hostname or private filesystem path,
  • a model or provider name,
  • conversation contents.

The SHA must contain no model name, provider name, human name, email, hostname, token, private path, or conversation-derived content. It is safe to include in PR bodies, issue comments, and audit logs — and only there.

Lifetime

Canonical lifetime is per PR/workstream: pick one SHA when starting an issue and keep it through the branch, PR, and handoff for that workstream. A per-session SHA is acceptable when the session maps cleanly to one workstream. Do not reuse a SHA across unrelated workstreams.

Placement

Phase 0 uses visible markdown metadata blocks (not hidden HTML comments). Include the block in PR bodies and review handoffs; keep it out of ordinary comments unless attribution is genuinely useful there.

Never put the SHA in branch or worktree names. Branches stay issue-linked and human-readable (docs/issue-86-llm-agent-sha-phase0), per the branch standard.

Handoff metadata block (implementer → PR body / handoff report)

LLM Handoff Metadata:
- LLM-Agent-SHA: llm-8f3a9c2d6b41
- LLM-Role: implementer
- Authenticated-Gitea-User: jcwalker3
- MCP-Profile: gitea-default
- Branch: docs/example-branch
- Worktree: branches/docs-example-branch
- Self-review allowed: no

Review metadata block (reviewer → review comment)

Review Metadata:
- LLM-Agent-SHA: llm-41d0e7aa9f2c
- LLM-Role: reviewer
- Authenticated-Gitea-User: sysadmin
- MCP-Profile: prgs-reviewer
- Eligibility: passed

Same SHA vs same user vs same profile

Reviewers and operators must keep three distinct identities straight:

Comparison Meaning Effect on eligibility
same LLM-Agent-SHA same LLM session/workstream wrote both artifacts none — attribution only
same authenticated Gitea user same Gitea actor blocks self-review / self-merge, regardless of SHA
same MCP profile same capability set governs allowed_operations (what actions are permitted at all)

Concretely: an implementer session (llm-8f3a…, user jcwalker3) and a would-be reviewer session (llm-41d0…, also user jcwalker3) have different SHAs but the same Gitea user — the reviewer session is still the PR author to Gitea and must not review, approve, or merge. Review handoffs require a genuinely different authenticated user (e.g. sysadmin / prgs-reviewer).

Phase 0 scope (and what is deferred)

Phase 0 is documentation, handoff/review templates, and negative tests only. Deferred to later owner-approved phases; none of this exists yet:

  • launcher-enforced SHA generation,
  • LLM_AGENT_SHA / LLM_AGENT_ROLE environment injection,
  • gitea_whoami returning SHA/role,
  • automatic PR body injection by MCP tools,
  • audit schema changes requiring the SHA,
  • release/orchestrator lineage tracking.

MCP tools neither read nor emit the SHA. Setting an LLM_AGENT_SHA environment variable has no effect on any tool; the negative tests assert eligibility results are byte-identical with and without it.