feat: full-context integrity lock — agents.lock + agents.sum (SPEC-008) - #81
Merged
Conversation
…k/verify (SPEC-008) Add `sync-agents lock` and `sync-agents verify`: a whole-tree integrity lock covering every artifact in every bucket, closing the provenance + tamper-detection gap that sources.lock leaves for local/imported/linked and non-source buckets. - agents.lock (provenance, YAML): one entry per artifact with path, bucket, name, origin (local | source:<entry> | linked:<file:path> | imported:<url>), resolved SHA, and SPEC-003 tree_hash. Path-sorted for minimal diffs; generated_at only advances when other bytes change. - agents.sum (integrity, go.sum-style): one line per file `<path> sha256:<hex>`, plus `<path> link:<target>` for symlinks so a re-pointed link is caught. Sums sources.yaml/sources.lock/config and agents.lock itself (the sum is the single root of trust). - verify: sum + lock + coverage checks with the SPEC-008 severity policy (pulled/local edit = ERROR, unlocked file = ERROR, hand-edited lock = ERROR, linked drift = INFO/--strict ERROR, swapped symlink = ERROR). Exit 0 clean / 1 drift / 2 usage-IO; no lock = friendly no-op. --json stable schema, --strict, --explain <path>. - Coverage honors OS-scoped subdirs regardless of host GOOS and excludes .quarantine/.sources/origin-metadata/unshared STATE_*.md. - ExitError type + main wiring for distinct process exit codes. - Docs: docs/integrity.md + README feature bullet. Implements SPEC-008 PR1 (writer + lock) and PR2 (verify). Auto-refresh of the lock from mutating commands (pull/update/approve/detach/add/ import/remove) is the remaining PR3 and is tracked in #73. Refs #73 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 tasks
🤖 AI Code ReviewThe diff introduces a full-context integrity lock feature with lock and verify commands. The implementation has a critical security vulnerability in symlink handling that allows including arbitrary files outside the agents tree, and a minor correctness bug when reading a symlink fails. Findings: 1 critical · 0 warning · 0 suggestion Findings not anchorable to a diff line:
model: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the core of SPEC-008 (#73): a full-tree integrity lock for
.agents/.What lands (SPEC-008 PR1 + PR2)
sync-agents lock— writes two committed files at the.agents/root:agents.lock(provenance, YAML) — one entry per artifact across every bucket:path,bucket,name,origin(local/source:<entry>/linked:<file:path>/imported:<url>),resolved_sha, and the SPEC-003tree_hash. Path-sorted;generated_atonly advances when some other byte changed (no-op runs stay diff-free).agents.sum(integrity, go.sum-style) — one line per file<path> sha256:<hex>, plus a<path> link:<target>line per symlink so a re-pointed link is caught even when contents match. Also sumssources.yaml,sources.lock,config, andagents.lockitself — the sum is the single root of trust.sync-agents verify— sum + lock + coverage checks with the SPEC-008 severity policy:agents.lock→ ERROR (via its sum line); linked-checkout drift → INFO (ERROR under--strict); swapped symlink → ERROR.0clean ·1drift ·2usage/IO. No lock on disk → friendly no-op (exit 0).--json(stable{status, findings, counts}schema),--strict,--explain <path>.Coverage includes OS-scoped subdirs (
macos/…) regardless of host GOOS, and excludes.quarantine/,.sources/, origin metadata, and unsharedSTATE_*.md(honorsshared: true).Tests
New
internal/agent/integrity_test.gocovers: determinism, ordering, all four origin classes, exclusions, OS subdirs, sum-includes-lock/sources, clean verify, local/pulled edit, unlocked file, missing artifact, tampered lock, no-lock no-op, JSON schema,--explain, and the full linked-source flow (linked origin, INFO-then-strict drift, re-pointed link). Package coverage ~73% (gate 70%).Verified end-to-end against a real tree (
lock→verifyclean → tamper →verifyexit 1 →--json→--explain).Remaining (not in this PR)
pull/update/approve/detach/add/import/source remove). Until then, re-runsync-agents lockafter a sync. Documented indocs/integrity.mdand tracked in SPEC-008: full-context integrity lock (agents.lock + agents.sum) #73.Refs #73
🤖 Generated with Claude Code