docs: LLM-Agent-SHA opaque attribution convention, Phase 0 (#86) #87

Merged
sysadmin merged 1 commits from docs/issue-86-llm-agent-sha-phase0 into master 2026-07-02 14:00:47 -05:00
Owner

Implements #86 Phase 0 only, per the owner decision (#86, #issuecomment-1354).

What this adds

docs/llm-agent-sha.md (new) — the full convention:

  • Format llm-<12 lowercase hex>, regex ^llm-[0-9a-f]{12}$; CSPRNG or non-secret-UUID-hash generation; forbidden derivations (token/email/username/hostname/path/model/conversation).
  • Attribution metadata only — never authentication, authorization, review/merge eligibility, or profile permissions. Same Gitea user + different SHA = same actor.
  • Lifetime: per PR/workstream (per-session acceptable when it maps to one workstream).
  • Visible markdown metadata blocks (handoff + review examples); no HTML comments in Phase 0; no SHA in branch/worktree names.
  • Three-way distinction table: same LLM-Agent-SHA (attribution only) vs same authenticated Gitea user (blocks self-review/self-merge) vs same MCP profile (governs allowed_operations).

docs/llm-workflow-runbooks.md — attribution subsection under the "profile is the role" principle; implement/review runbooks now point at the metadata blocks; related-documents link.

Templates start-issue.md / review-pr.md — handoff and review metadata blocks; explicit reviewer rule that a different SHA does NOT make you a different actor.

tests/test_llm_agent_sha.py (new, 10 tests) — negative proof the SHA is inert:

  • Same Gitea user + different LLM-Agent-SHA still fails self-approve and self-merge (gitea_check_pr_eligibility), and the gated gitea_merge_pr / gitea_review_pr tools refuse with no mutating API call.
  • Eligibility results are byte-identical with no SHA, one SHA, and a different SHA in the environment.
  • No gate function (gitea_check_pr_eligibility, gitea_merge_pr, gitea_review_pr, gitea_submit_pr_review) accepts an agent/llm parameter or reads LLM_AGENT_* in its source.
  • Format regex accepts documented examples, rejects identifying/malformed values.

Explicitly NOT in this PR (deferred per owner decision)

No launcher-enforced generation, no LLM_AGENT_SHA/LLM_AGENT_ROLE env handling in tools, no gitea_whoami SHA fields, no automatic PR body injection, no audit schema changes, no lineage tracking. Zero eligibility/gate code changed.

Checks

  • py_compile mcp_server.py / manage_labels.py / gitea_auth.py — OK
  • bash -n scripts/clear-provenance — OK
  • pytest tests/test_review_pr.py -q — 4 passed; tests/test_merge_pr.py -q — 4 passed
  • pytest tests/ -q355 passed (345 → +10)
  • git diff --check — clean
  • Staged-diff secret sweep — clean
  • README untouched (avoids conflict with open PR #84's README edits)

Closes #86 (Phase 0 scope).

LLM Handoff Metadata:

  • LLM-Agent-SHA: llm-2add89f8a617
  • LLM-Role: implementer
  • Authenticated-Gitea-User: jcwalker3
  • MCP-Profile: gitea-default
  • Branch: docs/issue-86-llm-agent-sha-phase0
  • Worktree: branches/docs-issue-86-llm-agent-sha-phase0
  • Self-review allowed: no

🤖 Generated with Claude Code

Implements #86 **Phase 0 only**, per the owner decision (#86, `#issuecomment-1354`). ## What this adds **`docs/llm-agent-sha.md`** (new) — the full convention: - Format `llm-<12 lowercase hex>`, regex `^llm-[0-9a-f]{12}$`; CSPRNG or non-secret-UUID-hash generation; forbidden derivations (token/email/username/hostname/path/model/conversation). - **Attribution metadata only** — never authentication, authorization, review/merge eligibility, or profile permissions. Same Gitea user + different SHA = same actor. - Lifetime: per PR/workstream (per-session acceptable when it maps to one workstream). - Visible markdown metadata blocks (handoff + review examples); no HTML comments in Phase 0; **no SHA in branch/worktree names**. - Three-way distinction table: same `LLM-Agent-SHA` (attribution only) vs same authenticated Gitea user (blocks self-review/self-merge) vs same MCP profile (governs `allowed_operations`). **`docs/llm-workflow-runbooks.md`** — attribution subsection under the "profile is the role" principle; implement/review runbooks now point at the metadata blocks; related-documents link. **Templates** `start-issue.md` / `review-pr.md` — handoff and review metadata blocks; explicit reviewer rule that a different SHA does NOT make you a different actor. **`tests/test_llm_agent_sha.py`** (new, 10 tests) — negative proof the SHA is inert: - Same Gitea user + different `LLM-Agent-SHA` still fails self-**approve** and self-**merge** (`gitea_check_pr_eligibility`), and the gated `gitea_merge_pr` / `gitea_review_pr` tools refuse with **no mutating API call**. - Eligibility results are byte-identical with no SHA, one SHA, and a different SHA in the environment. - No gate function (`gitea_check_pr_eligibility`, `gitea_merge_pr`, `gitea_review_pr`, `gitea_submit_pr_review`) accepts an agent/llm parameter or reads `LLM_AGENT_*` in its source. - Format regex accepts documented examples, rejects identifying/malformed values. ## Explicitly NOT in this PR (deferred per owner decision) No launcher-enforced generation, no `LLM_AGENT_SHA`/`LLM_AGENT_ROLE` env handling in tools, no `gitea_whoami` SHA fields, no automatic PR body injection, no audit schema changes, no lineage tracking. **Zero eligibility/gate code changed.** ## Checks - `py_compile` mcp_server.py / manage_labels.py / gitea_auth.py — OK - `bash -n scripts/clear-provenance` — OK - `pytest tests/test_review_pr.py -q` — 4 passed; `tests/test_merge_pr.py -q` — 4 passed - `pytest tests/ -q` — **355 passed** (345 → +10) - `git diff --check` — clean - Staged-diff secret sweep — clean - README untouched (avoids conflict with open PR #84's README edits) Closes #86 (Phase 0 scope). LLM Handoff Metadata: - LLM-Agent-SHA: llm-2add89f8a617 - LLM-Role: implementer - Authenticated-Gitea-User: jcwalker3 - MCP-Profile: gitea-default - Branch: docs/issue-86-llm-agent-sha-phase0 - Worktree: branches/docs-issue-86-llm-agent-sha-phase0 - Self-review allowed: no 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sysadmin added 1 commit 2026-07-02 13:33:33 -05:00
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>
sysadmin merged commit 104907e311 into master 2026-07-02 14:00:47 -05:00
Sign in to join this conversation.