feat(doctor): tamper-evident skills manifest + freshness guard (#159)

skills/ ships fat-markdown files that agents execute as instructions, but
nothing detected silent edits to them (#159). This adds lightweight tamper
EVIDENCE (a committed sha256 manifest), not a signature system:

- skills/skills.lock.json — committed manifest mapping every bundled file
  under skills/ to its sha256 (sorted relative paths, deterministic JSON,
  trailing newline; excludes itself from its own hash set).
- src/core/skills-integrity.ts — pure, unit-testable core: compute /
  render / verify(dir, manifest) -> { modified, missing, extra }.
- scripts/generate-skills-manifest.ts — regenerator
  (bun run scripts/generate-skills-manifest.ts).
- gbrain doctor check `skills_manifest_integrity` (SKILL group) — WARNS on
  drift, never fails or blocks; fail-safe ok/skip when no manifest is
  present at the resolved skills dir (user workspaces, compiled-binary
  installs far from the repo).
- scripts/check-skills-manifest-fresh.sh — CI freshness guard modeled on
  check-eval-glossary-fresh.sh; wired as `check:skills-manifest` in
  package.json and into bun run verify (run-verify-parallel.sh).
- test/skills-integrity.test.ts — clean / modified / missing / extra /
  self-exclusion / deterministic-render, over tmp-dir fixtures.

Docs: regeneration workflow in docs/TESTING.md + a KEY_FILES.md entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-07-27 16:19:41 -07:00
co-authored by Claude Fable 5
parent 032af6e5f7
commit f489243159
11 changed files with 423 additions and 0 deletions
+1
View File
@@ -49,6 +49,7 @@ CHECKS=(
"check:cli-exec"
"check:system-of-record"
"check:eval-glossary"
"check:skills-manifest"
"check:no-pii-agent-voice"
"check:synthetic-corpus-privacy"
"check:skill-brain-first"