Initial commit

This commit is contained in:
fraqtal
2026-07-12 08:15:46 +00:00
commit ee0fec0691
1397 changed files with 127242 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
---
id: 01-trace-schema-foundation
epic: library-evaluation-policy
title: Trace schema module + docs/library-decisions/ foundation
type: technical-story
status: done
feature: scripts
depends-on: []
blocks:
[
02-pre-commit-check-script,
04-evaluate-library-skill,
07-generator-pre-shipped-traces,
08-backfill-traces,
]
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Create the shared Zod-validated trace-schema module (`scripts/library-decisions/schema.mjs`) that every enforcement layer imports, and establish `docs/library-decisions/` with a `_template.md` schema reference that documents the required frontmatter + heading shape for all future traces.
## Why
All four enforcement layers (skill, pre-commit check, generator templates, sandcastle reviewer) need a single authoritative definition of what a valid library trace looks like. Without a shared module, each layer would re-implement the parse/validate logic independently and drift. The `_template.md` gives human contributors and agents a copy-pasteable starting point.
## Done when
- `scripts/library-decisions/schema.mjs` exists and exports: (1) a Zod schema validating the full trace frontmatter (all fields from ADR-022 §4 including nested `filter-results` object), (2) a `parseTrace(filePath)` function that reads + validates a `.md` file's frontmatter, (3) a `validateTrace(raw)` function for validating already-parsed objects.
- `scripts/library-decisions/schema.test.mjs` covers: valid trace round-trips without error; missing required field throws; unknown filter key rejected; invalid enum value rejected; `accepted-cves` optional field accepted.
- `docs/library-decisions/_template.md` exists with the complete frontmatter schema (all fields, all enums documented) and all required section headings (`## Filter: <name>` × 8 + `## Prompt: <name>` × 3) in the machine-checkable order from ADR-022.
- `docs/library-decisions/` directory is committed (can be just `_template.md` + `.gitkeep` if no traces yet).
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
## In scope
- `scripts/library-decisions/schema.mjs` — Zod schema + parse/validate exports.
- `scripts/library-decisions/schema.test.mjs` — unit tests (vitest or node:test; match the pattern used by `scripts/work/` tests).
- `docs/library-decisions/_template.md` — schema reference document.
## Out of scope
- The pre-commit check script (`check.mjs`) — Story 02.
- The skill itself — Story 04.
- Actual trace files (backfill) — Story 08.
- Generator template changes — Story 07.
## Tasks
- [x] Create `scripts/library-decisions/schema.mjs` with Zod frontmatter schema (all fields from ADR-022 §4: `package`, `version`, `tier`, `decision`, `date`, `deciders`, `adr`, `filter-results` nested object with all 8 filter keys and their enum values, `verification-commands`, `accepted-cves` optional), plus `parseTrace(filePath)` and `validateTrace(raw)` exports; write `schema.test.mjs` covering valid round-trip, missing-field rejection, invalid-enum rejection, and optional `accepted-cves`; create `docs/library-decisions/_template.md` with full frontmatter schema + all 11 required headings in ADR-022 order; all gates pass on this single commit.

View File

@@ -0,0 +1,43 @@
---
id: 02-pre-commit-check-script
epic: library-evaluation-policy
title: Pre-commit check script for library trace presence
type: technical-story
status: done
feature: scripts
depends-on: [01-trace-schema-foundation]
blocks: [06-sandcastle-reviewer-prompt]
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Write `scripts/library-decisions/check.mjs` — the script that walks staged `package.json` diffs, derives the tier of each affected package, and fails the commit when a new runtime dependency in a feature- or core-tier package has no sibling approved trace staged. Wire it into `.husky/pre-commit` as step 4.
## Why
Human and agent reviewers cannot reliably check trace presence during code review. The pre-commit hook is the last mechanical gate before a dep reaches the repo; it runs unconditionally, composes with `--no-verify` protection already in the bash-guard hook, and gives the committer immediate actionable feedback.
## Done when
- `scripts/library-decisions/check.mjs` exists and: (1) reads `git diff --cached --name-only -- '**/package.json'`; (2) for each staged `package.json`, derives tier from path (`apps/*` → app, `packages/core-*` → core, `packages/*` → feature); (3) for each newly added line in `dependencies` (not `devDependencies` / `peerDependencies`), checks that `docs/library-decisions/*-<name>.md` is also staged with `decision: approved`; (4) exits 1 with a per-package error report + pointer to the skill when any check fails; (5) app-tier and devdep additions exit 0 silently.
- `.husky/pre-commit` invokes `node scripts/library-decisions/check.mjs` after the existing state-sync guard.
- `scripts/library-decisions/check.test.mjs` covers (using a temp git repo fixture): new feature-tier dep without trace → exit 1; new feature-tier dep with approved trace staged → exit 0; new feature-tier dep with rejected-decision trace staged → exit 1; new app-tier dep → exit 0; new devdep → exit 0; multi-file diff with mixed pass/fail → exit 1 with per-package report; `peerDependencies`-only change → exit 0.
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.
## In scope
- `scripts/library-decisions/check.mjs` — the check script (imports `schema.mjs` from Story 01 for trace validation).
- `scripts/library-decisions/check.test.mjs` — integration tests using a temp git repo fixture (mirror pattern from `scripts/work/state-sync-guard.mjs` tests).
- `.husky/pre-commit` — one added line.
## Out of scope
- Sandcastle reviewer prompt integration — Story 06.
- `--staged-against <base>` flag for CI/sandcastle use — added in Story 06 when the reviewer prompt is written.
- `pnpm libs check` ergonomic wrapper — deferred per PRD.
## Tasks
- [x] Write `scripts/library-decisions/check.mjs` (imports schema from Story 01; parses `git diff --cached` output; tier derivation from path; staged-trace presence + `decision: approved` check; exit-1 report with skill pointer); wire into `.husky/pre-commit`; write `check.test.mjs` integration tests with temp git repo fixture covering all 7 cases from Done when; all gates pass on this single commit.

View File

@@ -0,0 +1,44 @@
---
id: 03-claude-hooks
epic: library-evaluation-policy
title: Claude PreToolUse / PostToolUse hooks for library-policy nudge
type: technical-story
status: done
feature: tooling
depends-on: []
blocks: []
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Write `.claude/hooks/library-policy-nudge.sh` — a single hook script that dispatches on `tool_use_type` to handle both `PreToolUse` (Bash invocations matching `pnpm add` / `pnpm i <pkg>`) and `PostToolUse` (Edit/Write on any `**/package.json`). On match, emit a non-blocking system-reminder pointing the agent at the `evaluate-library` skill with the exact invocation pattern. Register the hook in `.claude/settings.json` following the same pattern as `generator-first-nudge.sh`.
## Why
Agents (and developers) running `pnpm add` by reflex bypass the policy before the pre-commit gate fires. The PreToolUse hook injects the skill reminder _before_ the install runs — the cheapest possible intervention point. The PostToolUse hook catches the rarer case where an agent edits `package.json` directly without running the install command.
## Done when
- `.claude/hooks/library-policy-nudge.sh` exists, is executable, dispatches on `CLAUDE_TOOL_USE_TYPE` (or equivalent hook env var), and emits the reminder to stdout when a `pnpm add`/`pnpm i <pkg>` bash command is detected or when an Edit/Write tool targets a path matching `**/package.json`.
- The hook is registered in `.claude/settings.json` (or `.claude/settings.local.json` if per-repo convention) under both `PreToolUse` and `PostToolUse` event types, matching the registration pattern of `generator-first-nudge.sh`.
- The reminder text includes the literal string `/evaluate-library` and the argument template `<name> --tier <feature|core|app> --target <package-path>` so the agent sees the exact invocation.
- Bash smoke tests (same style as any existing hook tests): pipe a mocked Claude hook payload `{ "tool_input": { "command": "pnpm add foo" } }` into the script and assert stdout contains the skill-reminder marker; pipe a payload for `pnpm add -D foo` (devdep) and assert no reminder emitted; pipe an Edit payload on `src/feature.manifest.ts` and assert no reminder emitted.
- `pnpm lint && pnpm fallow:audit` pass.
## In scope
- `.claude/hooks/library-policy-nudge.sh` — the hook script.
- `.claude/settings.json` (or equivalent) — hook registration lines.
- Bash smoke tests for the hook script.
## Out of scope
- Hook auto-deny or blocking behavior — the hook is advisory only (non-blocking system-reminder).
- Hooks for `npm install` / `yarn add` — the repo is pnpm-only.
- Integration with the skill implementation (Story 04) — the hook emits a text reminder; the skill is a separate file.
## Tasks
- [x] Investigate how `generator-first-nudge.sh` is registered (read `.claude/settings.json` and the existing hook script) to confirm the env-var names, payload shape, and registration keys; then write `.claude/hooks/library-policy-nudge.sh` + register it in the settings file + write bash smoke tests covering `pnpm add <pkg>` (reminder), `pnpm add -D <pkg>` (no reminder), Edit on non-package.json (no reminder), Edit on `package.json` (reminder); all gates pass on this single commit.

View File

@@ -0,0 +1,48 @@
---
id: 04-evaluate-library-skill
epic: library-evaluation-policy
title: evaluate-library skill (SKILL.md + supporting files)
type: technical-story
status: done
feature: tooling
depends-on: [01-trace-schema-foundation]
blocks: [05-human-guide]
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Create the `.claude/skills/evaluate-library/` directory with `SKILL.md` (the authoritative agent runbook), `POLICY.md` (ADR-022 mirror for quick reference), `TRACE-TEMPLATE.md` (showing the YAML frontmatter + heading shape the skill must emit), and an `EXAMPLES/` directory with two worked cases (one approved, one rejected). The skill must be invocable as `/evaluate-library <name> --tier <feature|core|app> --target <package-path>`.
## Why
Without a deterministic skill runbook, every agent evaluating a library does so ad hoc — different filters, different order, inconsistent trace format. The skill is the single source of truth for the 8-filter + 3-prompt sequence, the collect-cheap-skip-expensive ordering, and the trace write step. It also provides the canonical invocation the Claude hook emits.
## Done when
- `.claude/skills/evaluate-library/SKILL.md` exists and covers: invocation signature (`/evaluate-library <name> --tier <tier> --target <pkg-path>`), the 8 filters in collect-cheap-skip-expensive order (license, types, shadow-check, boundary-fit run to completion; maintenance, CVE scan, EU residency, named-consumer short-circuit after first reject), the 3 prompts, trace-write step (unconditional at evaluation end, including rejections), and the fail/skip sentinel for skipped expensive filters.
- `.claude/skills/evaluate-library/POLICY.md` summarises ADR-022 in ≤2 pages — the filters, the tier trigger, the trace schema fields, the four enforcement layers.
- `.claude/skills/evaluate-library/TRACE-TEMPLATE.md` shows the complete YAML frontmatter (all fields, real sentinel values for skipped filters) + all 11 required headings in order.
- `.claude/skills/evaluate-library/EXAMPLES/` contains at least two worked trace files: one `decision: approved` trace and one `decision: rejected` trace (use `trpc-to-openapi` as the rejected example per the PRD, with `named-consumer: fail` and prose citing the grill-session conversation as provenance).
- The skill is listed in `.claude/settings.json` (or wherever skills are registered) so `/evaluate-library` resolves to the SKILL.md via the Skill tool.
- `pnpm lint && pnpm fallow:audit` pass.
## In scope
- `.claude/skills/evaluate-library/SKILL.md`
- `.claude/skills/evaluate-library/POLICY.md`
- `.claude/skills/evaluate-library/TRACE-TEMPLATE.md`
- `.claude/skills/evaluate-library/EXAMPLES/approved-example.md`
- `.claude/skills/evaluate-library/EXAMPLES/rejected-trpc-to-openapi.md`
- Skill registration in `.claude/settings.json` (match existing skill registration pattern).
## Out of scope
- Automated tests for the skill (it is a prose runbook; correctness is verified by the success criterion in the PRD — running it against `trpc-to-openapi` produces the documented trace).
- The schema module (Story 01) — already landed.
- The human guide with worked examples for non-agent readers (Story 05).
## Tasks
- [x] Investigate the existing skill registration pattern (read `.claude/settings.json` and one existing skill's SKILL.md to confirm format and registration key); then write all five skill files (`SKILL.md`, `POLICY.md`, `TRACE-TEMPLATE.md`, `EXAMPLES/approved-example.md`, `EXAMPLES/rejected-trpc-to-openapi.md`) and register the skill; all gates pass on this single commit.

View File

@@ -0,0 +1,39 @@
---
id: 05-human-guide
epic: library-evaluation-policy
title: Human reading-room guide — docs/guides/adding-a-library.md
type: technical-story
status: done
feature: docs
depends-on: [04-evaluate-library-skill]
blocks: [09-claude-md-update]
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Write `docs/guides/adding-a-library.md` — the human-readable guide explaining the library evaluation policy with worked examples (one approved, one rejected), the tier trigger, the four enforcement layers, and how to invoke the skill. The guide targets a maintainer reading the repo for the first time.
## Why
ADR-022 is the source of truth but is written for decision-record density, not onboarding. The guide translates the policy into a narrative that answers "why does this exist?" and "what do I actually do?" before a developer encounters the pre-commit gate for the first time. Worked examples anchor the abstract filter list to concrete outcomes.
## Done when
- `docs/guides/adding-a-library.md` exists with: (1) a "Why this exists" section explaining the uncodified-surface problem and the three signals from the PRD; (2) the tier trigger (feature/core packages require traces; app-tier does not; devdeps exempt); (3) the four enforcement layers (Claude hook → skill → pre-commit → sandcastle) in latency order; (4) step-by-step "how to add a library" walkthrough pointing at the `/evaluate-library` skill; (5) a worked approved example (brief — the full trace lives in `EXAMPLES/` from Story 04); (6) a worked rejected example (`trpc-to-openapi`, `named-consumer: fail`); (7) a link to ADR-022 and `docs/library-decisions/_template.md`.
- `pnpm lint && pnpm fallow:audit` pass.
## In scope
- `docs/guides/adding-a-library.md` — the guide document.
## Out of scope
- The skill itself (Story 04) — already landed.
- CLAUDE.md update (Story 09) — that bullet points here and to ADR-022 but lands separately.
- Changing any existing guide or ADR.
## Tasks
- [x] Write `docs/guides/adding-a-library.md` with all seven sections from Done when (why, tier trigger, four layers, how-to walkthrough, worked approved + rejected examples, cross-links); all gates pass on this single commit.

View File

@@ -0,0 +1,43 @@
---
id: 06-sandcastle-reviewer-prompt
epic: library-evaluation-policy
title: Sandcastle reviewer prompt — Library-trace check section
type: technical-story
status: done
feature: tooling
depends-on: [02-pre-commit-check-script]
blocks: []
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Append a "Library-trace check" section to `.sandcastle/reviewer.prompt.md` instructing the reviewer agent to run `node scripts/library-decisions/check.mjs --staged-against <base>` before issuing its verdict, and add the `--staged-against <base>` flag to `check.mjs` so it can compare against a given base ref rather than only the git index.
## Why
The sandcastle reviewer runs in a clean sandbox where `git diff --cached` may not reflect the full branch diff. The `--staged-against <base>` flag allows the reviewer to pass the PR's base branch as the comparison point, giving the same check a CI-compatible code path. Without this, the fourth enforcement layer is advisory only — it has no mechanical check to back it up.
## Done when
- `scripts/library-decisions/check.mjs` accepts a `--staged-against <base>` flag; when present, compares `git diff <base>...HEAD -- '**/package.json'` instead of `git diff --cached`.
- `check.test.mjs` has a new test case: `--staged-against main` mode with a new feature-tier dep and no trace → exit 1.
- `.sandcastle/reviewer.prompt.md` contains a "Library-trace check" section (appended, not replacing existing content) instructing the reviewer to run `node scripts/library-decisions/check.mjs --staged-against <base-branch>` and reject the slice if it exits non-zero.
- `pnpm lint && pnpm test && pnpm fallow:audit && pnpm coverage:diff` all pass.
## In scope
- `scripts/library-decisions/check.mjs` — add `--staged-against` flag.
- `scripts/library-decisions/check.test.mjs` — add test for the new flag.
- `.sandcastle/reviewer.prompt.md` — append the Library-trace check section.
## Out of scope
- Changing the reviewer prompt's existing sections.
- The pre-commit (index-mode) check behavior — already in Story 02.
- CI integration (GitHub Actions) — deferred.
## Tasks
- [x] Add `--staged-against <base>` flag to `check.mjs` (switches from `git diff --cached` to `git diff <base>...HEAD`); add a test covering `--staged-against` mode (temp git repo fixture, new feature-tier dep, no trace → exit 1); append "Library-trace check" section to `.sandcastle/reviewer.prompt.md` with the `node scripts/library-decisions/check.mjs --staged-against <base>` invocation and reject instruction; all gates pass on this single commit.

View File

@@ -0,0 +1,46 @@
---
id: 07-generator-pre-shipped-traces
epic: library-evaluation-policy
title: Generator templates — pre-shipped traces for optional core packages
type: technical-story
status: done
feature: tooling
depends-on: [01-trace-schema-foundation]
blocks: []
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Update the five optional-core generator templates (`events`, `realtime`, `audit`, `trpc`, `ui`) so that when `pnpm turbo gen core-package <name>` runs, it copies pre-written `decision: approved` library traces into `docs/library-decisions/` for every direct runtime dependency of that core package. Update the corresponding `__snapshots__` files so the snapshot tests cover the new trace files.
## Why
A developer who scaffolds an optional core via the generator should not immediately face a pre-commit failure for its bundled deps — the generator is the policy-compliant path, so the traces should land by construction. Without pre-shipped traces, the very act of using the generator would trigger the enforcement gate it's supposed to clear.
## Done when
- Each of the five generator templates (`turbo/generators/templates/core-package/{events,realtime,audit,trpc,ui}/`) contains a `docs/library-decisions/` subtree with one `.md` trace file per direct runtime dependency of that core, dated at generation time (use the template variable for date, or freeze to the scaffold date with a comment), `decision: approved`, and citing the relevant ADR (`events` → ADR-015, `realtime` → ADR-016, `audit` → ADR-018; `trpc` and `ui` cite their closest ADR or `null` if none).
- The generator copies these files into the workspace when run.
- The `turbo/generators/__snapshots__/core-package/<name>.snapshot.json` files are updated to include the new trace files; `pnpm turbo gen core-package events` (or any other optional core) passes the existing snapshot test.
- `pnpm lint && pnpm fallow:audit` pass.
## In scope
- `turbo/generators/templates/core-package/events/` — pre-shipped trace(s).
- `turbo/generators/templates/core-package/realtime/` — pre-shipped trace(s).
- `turbo/generators/templates/core-package/audit/` — pre-shipped trace(s).
- `turbo/generators/templates/core-package/trpc/` — pre-shipped trace(s).
- `turbo/generators/templates/core-package/ui/` — pre-shipped trace(s).
- Snapshot JSON updates for all five cores.
- Generator copy logic (if not already handled by the template mechanism).
## Out of scope
- Backfill traces for already-installed optional cores in the live workspace — Story 08.
- Generator templates for non-core-package generators (feature, event, job, realtime, component) — no runtime deps are emitted by those generators.
## Tasks
- [x] Inventory the direct runtime deps of each of the five optional core generator templates (read each template's `package.json`); write one approved trace file per dep in the correct generator template subtree with ADR citation; update the five snapshot JSON files to include the new trace file entries; verify `pnpm turbo gen core-package events` (or equivalent dry-run) matches the updated snapshot; all gates pass on this single commit.

View File

@@ -0,0 +1,50 @@
---
id: 08-backfill-traces
epic: library-evaluation-policy
title: Backfill library traces for existing feature- and core-tier runtime deps
type: technical-story
status: done
feature: docs
depends-on: [01-trace-schema-foundation]
blocks: []
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Write approved library trace files dated 2026-05-14 in `docs/library-decisions/` for every existing runtime dependency in feature- and core-tier packages, grouped by ADR provenance into four commits. No package.json is changed; these commits are pure trace-file additions.
## Why
Without backfill, every existing dep becomes a pre-commit-hook failure the first time someone touches a `package.json` — the enforcement gate would fire retroactively. Backfill establishes the baseline so the gate is additive (new deps require traces) rather than disruptive (old deps fail immediately). Grouping by ADR cluster makes the commit history readable and keeps each commit focused on a coherent rationale.
## Done when
- All runtime deps in `packages/` (feature- and core-tier) have a corresponding `docs/library-decisions/YYYY-MM-DD-<name>.md` with `decision: approved`, `date: 2026-05-14`, and the relevant `adr` citation (or `null` for un-cited deps).
- Four commits land, one per cluster:
- **ADR-002 cluster**: `inversify`, `reflect-metadata`.
- **ADR-014 cluster**: `@sentry/node`, `@sentry/nextjs`, `@sentry/react`, and any other Sentry packages present.
- **ADR-017 cluster**: `@opentelemetry/api`, `@opentelemetry/sdk-node`, and any other OTel packages present.
- **Un-cited cluster**: `payload`, `@trpc/server`, `zod`, `superjson`, and any remaining runtime deps not covered by an ADR.
- All trace files pass `validateTrace()` from `schema.mjs` (Story 01).
- `pnpm lint && pnpm fallow:audit` pass after all four commits.
## In scope
- `docs/library-decisions/<date>-<name>.md` trace files — one per dep.
- Four conventional commits: `chore(deps): backfill library traces for <cluster>`.
## Out of scope
- Deps in `apps/*` — app-tier is out of scope per the PRD.
- devDeps in any tier — exempt from traces.
- Changing any `package.json` — backfill is trace-only.
- Optional core packages not yet installed in the workspace — covered by Story 07 (generator pre-shipped traces) when they are scaffolded.
## Tasks
- [x] Inventory all runtime deps in `packages/` (run `jq '.dependencies // {} | keys' packages/*/package.json packages/core-*/package.json` or equivalent); write approved trace files for the ADR-002 cluster (`inversify`, `reflect-metadata`) in `docs/library-decisions/`; commit as `chore(deps): backfill library traces for ADR-002 cluster`.
- [x] Write approved trace files for the ADR-014 cluster (Sentry packages); commit as `chore(deps): backfill library traces for ADR-014 cluster`.
- [x] Write approved trace files for the ADR-017 cluster (OpenTelemetry packages); commit as `chore(deps): backfill library traces for ADR-017 cluster`.
- [x] Write approved trace files for the un-cited cluster (`payload`, `@trpc/server`, `zod`, `superjson`, and any remaining runtime deps); commit as `chore(deps): backfill library traces for un-cited cluster`; all gates pass after this final commit.

View File

@@ -0,0 +1,39 @@
---
id: 09-claude-md-update
epic: library-evaluation-policy
title: CLAUDE.md Key Conventions — library policy bullet
type: technical-story
status: done
feature: docs
depends-on: [05-human-guide]
blocks: []
created: 2026-05-14T06:52:02+02:00
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Add one bullet to the "Key Conventions" section of `CLAUDE.md` pointing agents and developers at ADR-022, the `evaluate-library` skill, and `docs/guides/adding-a-library.md`. No other changes to `CLAUDE.md`.
## Why
`CLAUDE.md` is the first file agents and developers read. Without a Key Conventions entry, the library evaluation policy is invisible to any agent starting a fresh session — it may run `pnpm add` without knowing the policy exists, and only hit the hook or pre-commit gate after the fact. The bullet closes the discoverability gap.
## Done when
- `CLAUDE.md` Key Conventions section contains a bullet: _"New runtime dependencies in feature- or core-tier packages require a library trace at `docs/library-decisions/<date>-<name>.md` produced by the `/evaluate-library` skill — see ADR-022 and `docs/guides/adding-a-library.md`."_ (exact wording may vary; substance must include ADR-022, the skill, and the guide path).
- No other changes to `CLAUDE.md`.
- `pnpm lint && pnpm fallow:audit` pass.
## In scope
- `CLAUDE.md` — one bullet in Key Conventions.
## Out of scope
- `docs/glossary.md` — the glossary entries for **Library trace** and **Pre-shipped trace** landed during the 2026-05-14 grill session and are already present.
- Any other documentation changes.
## Tasks
- [x] Add the one-line library-policy bullet to CLAUDE.md Key Conventions (after confirming glossary entries are already present); all gates pass on this single commit.

View File

@@ -0,0 +1,30 @@
---
id: library-evaluation-policy
prd: docs/work/prds/library-evaluation-policy.prd.md
title: Library evaluation policy — skill, traces, enforcement stack
type: epic
status: done
features: [scripts, tooling, docs]
created: 2026-05-14T00:00:00Z
updated: 2026-05-14T19:21:52.308Z
---
## Goal
Implement a four-layer enforcement stack — Claude hook, skill, pre-commit hook, sandcastle reviewer prompt — that makes every new runtime dependency in a feature- or core-tier package produce a permanent **library trace** at `docs/library-decisions/<YYYY-MM-DD>-<package-name>.md`. Rejection traces are first-class records. Codifies ADR-022.
## Why
The repo's narrow third-party surface is uncodified. New dependencies enter via `pnpm add` with no checkpoint. Three signals exposed the gap: a near-miss adding a build-time-only library, post-hoc ADR records (002/014/017), and a silent EU-data-residency risk from US-only SaaS defaults. The enforcement stack mirrors the 5-gate conformance pattern — same vocabulary, same agent feedback loop.
## Stories
- [x] [01 — Trace schema module + docs/library-decisions/ foundation](01-trace-schema-foundation/_story.md)
- [x] [02 — Pre-commit check script](02-pre-commit-check-script/_story.md)
- [x] [03 — Claude PreToolUse / PostToolUse hooks](03-claude-hooks/_story.md)
- [x] [04 — evaluate-library skill](04-evaluate-library-skill/_story.md)
- [x] [05 — Human guide: docs/guides/adding-a-library.md](05-human-guide/_story.md)
- [x] [06 — Sandcastle reviewer prompt update](06-sandcastle-reviewer-prompt/_story.md)
- [x] [07 — Generator pre-shipped traces for optional cores](07-generator-pre-shipped-traces/_story.md)
- [x] [08 — Backfill traces for existing runtime deps](08-backfill-traces/_story.md)
- [x] [09 — CLAUDE.md Key Conventions bullet](09-claude-md-update/_story.md)