Adds CONSENT_GRANT, CONSENT_WITHDRAW, RESTRICT, UNRESTRICT to the
AuditAction closed enum per GDPR Art. 7 and Art. 18 requirements.
core-consent and core-dsr optional cores (Epic B Stories 03/06) emit
these action types via core-audit's IAuditLog channel; the values must
exist in core-shared's enum before either optional core can be built.
No change to IAuditLog's interface surface — new values flow through
AuditEntry.action automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Amends ADR-022 §9 with the `is-sub-processor` / `processes-pii` discriminated
union spec, including the five conditional fields required when a library is a
true GDPR sub-processor. Updates the evaluate-library skill to prompt for these
fields during every trace authoring pass and adds the updated frontmatter
template. Backfills all nine existing library-decision traces with the new
fields; payload gets `processes-pii: true` (self-hosted CMS that stores user
data); all pure in-process libraries get `false / false`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ADR-025 plans 4 epics that raise the template's DPA/GDPR coverage from
~50% (ADR-017/018/022/023/024) to ~80%. Adds two optional cores
(core-dsr, core-consent), a fourth conformance channel (rate-limit),
three new manifest fields, three new generators with CI drift gates,
and a docs/compliance/ + compliance/ split for templates vs evidence.
Documents the audit ↔ DSR sibling-not-overlap distinction (audit
records access; DSR acts on the underlying data). Four explicit
deferrals with revisit triggers (RBAC, MFA, breach detection, Art. 22).
Glossary updated with DSR, Consent, Rate-limit, PII inventory, Retention
policy, Sub-processor, docs/compliance/ vs compliance/ entries.
ADR-024 codifies IAnalytics as an optional-core channel parallel to
IAuditLog. Mirrors the audit pattern (inline emission, manifest field,
brand at bind time, ESLint cross-check) with three deliberate
divergences: no `mutates` gate on the brand check, flush() on the
interface for batched server-side SDKs, and a React provider scaffold
in core-analytics/react so server + client share the same contract.
PII boundary is explicitly distinct from ADR-017's observability policy:
traits-allowed at the interface, consumer owns consent + retention.
Glossary updated with IAnalytics and withAnalytics entries.
Convention shift: epic folders + PRD filenames + frontmatter id
fields are now bare slugs. The created: timestamp (Phase 2) carries
the date; folder names don't repeat it. A future <task-id>-<slug>
shape (e.g. ClickUp) lands cleanly when that integration ships.
Renames (git mv preserves history):
- docs/work/2026-05-13-binder-wrap-helper/
-> docs/work/binder-wrap-helper/
- docs/work/2026-05-14-library-evaluation-policy/
-> docs/work/library-evaluation-policy/
- docs/work/2026-05-14-ci-security-and-supply-chain/
-> docs/work/ci-security-and-supply-chain/
- docs/work/prds/2026-05-13-binder-wrap-helper.prd.md
-> docs/work/prds/binder-wrap-helper.prd.md
- docs/work/prds/2026-05-13-coverage-architecture.prd.md
-> docs/work/prds/coverage-architecture.prd.md
- docs/work/prds/2026-05-14-library-evaluation-policy.prd.md
-> docs/work/prds/library-evaluation-policy.prd.md
- docs/work/prds/2026-05-14-ci-security-and-supply-chain.prd.md
-> docs/work/prds/ci-security-and-supply-chain.prd.md
Frontmatter updates inside the renamed files: epic id, epic prd,
story epic, PRD id, PRD builds-on all drop date prefixes.
System folder + state file move:
- New docs/work/_system/ holds framework-managed state.
- docs/work/_state.json -> docs/work/_system/_state.json.
- state-builder.mjs adds _system to SKIP_FOLDERS.
- cli.mjs + state-sync-guard.mjs + .husky/pre-commit point at the
new path.
template-reset-v1 epic deleted entirely (one-off cleanup epic from
the pre-date-convention era; status was already done).
Generator-template updates (so new artifacts ship in the right
shape):
- .sandcastle/decomposer.prompt.md emits bare-slug folder names +
ISO created: timestamp.
- .claude/skills/to-prd/SKILL.md template uses bare-slug filename +
bare-slug id field + ISO created: timestamp.
Doc reference updates: glossary, runbook, agent-first-workflow-
and-conformance, reviewer prompt, ADR-020, ADR-022, ADR-023 all
point at the new paths/slugs.
- ADR-023 codifies the four-pillar enforcement stack: Renovate for
bumps + Action SHA pinning via pinGitHubActionDigests, Socket.dev
as a 9th hard filter in evaluate-library (free App + self-hosted
socket-cli + reviewer-prompt enforcement), weekly trace
revalidation cron with two-tier divergence action (rolling
dashboard issue + per-dep re-evaluation issues), and the baseline
GitHub-native gates (CodeQL, pnpm audit signatures, gitleaks
pre-commit + native push protection). Failure-mode hierarchy is
the single source of truth referenced by the sandcastle reviewer.
- Section 6 amends ADR-022 in place: major-bump re-evaluation
trigger (minor/patch bumps skip), last-revalidated frontmatter
field (preserves original date for adoption provenance), and
Socket as the 9th hard filter. ADR-022 stays unedited; both ADRs
read as a composed policy.
- PRD at docs/work/prds/2026-05-14-ci-security-and-supply-chain.prd.md
seeds the implementation epic; explicit sequencing -- depends on
the in-flight library-evaluation epic's stories 01/02/04/06
landing first.
- Glossary gains "Trace revalidation" + "Major-bump re-evaluation"
entries referenced by both ADRs.
Catalyst: 2026-05-14 audit confirmed zero security tooling in the
repo + GitHub Actions pinned to major-version tags (the tj-actions/
changed-files attack class). ADR-022 closes the adoption-time gate;
ADR-023 closes the post-adoption drift gate.
- ADR-022 codifies the tiered library-evaluation policy: 8 hard
auto-reject filters (license, types, maintenance, boundary-fit,
shadow-check, EU residency, CVE scan, named consumer), 3
discussion prompts, per-decision trace artifact at
docs/library-decisions/, and a 4-layer enforcement stack
(Claude PreToolUse/PostToolUse hook -> evaluate-library skill ->
pre-commit hook -> sandcastle reviewer prompt). Mirrors the
conformance-system latency pattern from ADR-012.
- PRD at docs/work/prds/2026-05-14-library-evaluation-policy.prd.md
seeds the implementation epic; status: approved, ready for
\`pnpm work decompose\`.
- Glossary gains "Library trace" + "Pre-shipped trace" entries
referenced by both artifacts.
Catalyst: the 2026-05-14 grill session nearly adopted
trpc-to-openapi + zod-to-json-schema before someone asked who the
HTTP consumer was. Honest answer: none -- all callers are TS via
createCaller. This policy makes that question structurally
unavoidable for any future feature- or core-tier dep.
Closes the user's ask: versioning + a changelog generated on merging
to main, building on the just-mandated Conventional Commits substrate
(CLAUDE.md Key Conventions).
Architecture: ADR-021. Cookbook: docs/guides/releasing.md.
Initial state — six tracked packages at v0.1.0:
- . -> template-vertical (tag: template-v...)
- packages/auth -> @repo/auth (tag: auth-v...)
- packages/blog -> @repo/blog (tag: blog-v...)
- packages/media -> @repo/media (tag: media-v...)
- packages/marketing-pages -> @repo/marketing-pages (tag: marketing-pages-v...)
- packages/navigation -> @repo/navigation (tag: navigation-v...)
Core packages, tooling, and apps are NOT independently versioned
(ADR-021 rationale: core bumps cascade; apps aren't consumables;
surfacing them would create noise without information).
Configuration:
- release-please-config.json - 6 tracked packages, hybrid scope,
pre-1.0 conservative bump policy
(feat: -> patch, feat!: -> minor),
conventional-commit type mapping
- .release-please-manifest.json - baseline 0.1.0 for all 6 packages
- .github/workflows/release-please.yml - googleapis/release-please-
action@v4 on push to main,
concurrency-gated, write
permissions for the rolling PR
Workflow: on every push to main, release-please scans commits since
the last release tag PER PACKAGE (using commit-path, not the
conventional-commit scope), updates a single rolling release PR with
version bumps + per-package CHANGELOG entries. Merging that PR cuts
per-package tags + GitHub releases.
CHANGELOG files seeded at v0.1.0 baseline:
- CHANGELOG.md (root)
- packages/<feature>/CHANGELOG.md (5 features)
Subsequent versions are appended by release-please from commit
history. Do not edit manually.
Visibility surfaces updated (every agent entry point):
- CLAUDE.md Read First + new "Versioning is hybrid" Key Conventions
bullet (with bump policy summary)
- AGENTS.md preamble - new "Releases:" callout alongside Commits
- docs/glossary.md - new Releasing section with 8 terms (Conventional
Commits, release-please, Hybrid versioning, Tag prefix, Rolling
release PR, Bump targeting, Pre-1.0 bump policy, Release-As trailer,
CHANGELOG.md)
- docs/README.md - guides tree updated with releasing.md
- .claude/hooks/session-start.sh - one-line release reminder
- .claude/hooks/prompt-context.sh - new keyword group for
release/version/bump/semver/tag prompts
Package.json version bumps:
- root: name "template" -> "template-vertical", version "0.1.0"
- packages/auth, blog, media, marketing-pages, navigation: "0.0.0" -> "0.1.0"
Root rename rationale: release-please tags use the package-name + the
component prefix; "template-vertical" matches the repo identity (and
the user's question preview).
First release-please PR after this lands will sweep all subsequent
post-baseline commits into 0.1.1 / 0.2.0 bumps as appropriate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The docs/superpowers/{specs,plans}/ directory was archived to .archive/
in an earlier session (and .archive/ is gitignored). Every md link
into that path is now a broken reference for anyone consuming the
template fresh.
Stripped:
- ADR-011: **Spec:** header line
- ADR-015: **Spec:** + **Plan:** header lines
- ADR-016: **Spec:** + **Plan:** header lines + footer "Spec —"
bullet (the design rationale is captured in the ADR body itself)
- ADR-017: **Spec:** + **Plan:** header lines
- ADR-018: **Spec:** + **Plan:** header lines
- guides/realtime.md: inline "the full spec" link + footer
[Spec] entry (folded its description into the ADR-016 entry)
- guides/events-and-jobs.md: inline "the full spec" link
- architecture/vertical-feature-spec.md: stale "Deleted" subsection
referencing docs/superpowers/plans/*
Updated:
- glossary.md "PRD" entry: clarified status flow now matches the
shipped pnpm work prd-ship lifecycle (draft -> in-review ->
approved -> shipped); removed the parenthetical pointing at
docs/superpowers/specs/ as a definition of "spec"
- glossary.md "spec" flagged-ambiguity: rewritten to reflect that
durable design lives in ADRs (docs/decisions/adr-NNN-*.md) and
implementation seeds live in PRDs (docs/work/prds/*.prd.md) —
"spec" should be avoided in this template
Preserved (legitimate refs to the SuperPowers plugin, not the dir):
- agent-first-workflow-and-conformance.md mentions of
`superpowers:brainstorming` — these reference the external
plugin skill, not a file in the repo
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the staleness gap after the 10-commit coverage epic shipped.
Doc sync (item 1 from the user's choice):
- CLAUDE.md Quick Start: adds pnpm coverage:aggregate / coverage:diff
/ mutate to the command listing
- CLAUDE.md: new "Sibling architecture: coverage (ADR-020)" section
after the conformance gate table — captures the 4-layer table +
points at docs/guides/coverage.md + ADR-020 + says agents must run
coverage:diff before reporting complete
- AGENTS.md preamble: now lists coverage as a parallel multi-latency
quality system alongside conformance, with the same gate / latency
framing
- PRD frontmatter: status draft -> shipped + shipped date +
shipping-commits list (all 10 SHAs anchoring the trace)
- PRD findings table: each row gets a Resolution column citing the
commit that closed it; conclusion text updated to past tense
- ADR-020 implementation phasing: rewritten as a status table with
each step linked to the commit that shipped it + Boot-time
assertFeatureConformance explicitly marked Deferred with rationale
- docs/guides/coverage.md: removed "Boot wiring lands in the next
story" line; replaced with the deferral rationale + clarified
that two readers (vitest, coverage:diff) consume the manifest
Sandcastle prompts (item 2 from the user's choice):
- .sandcastle/implementer.prompt.md: new "Coverage gates" section
after the conformance-gates list, requiring `pnpm test --coverage`,
`pnpm coverage:aggregate`, and `pnpm coverage:diff` to all pass
before reporting `complete`. Machine-readable JSON shape of
coverage:diff documented (status / uncovered[] / kind enum), with
explicit instructions on how to interpret each kind. Allowlist
expansion requires justification + test.
- .sandcastle/reviewer.prompt.md: AC coverage relabeled to "AC
coverage (acceptance criteria, not test coverage)" to disambiguate;
new check #7 "Coverage gates (ADR-020)" requiring CI's
Coverage — diff (L1) step green + per-layer thresholds met +
no silent allowlist expansion + manifest band drift detection.
Effect: future agent runs through sandcastle now treat coverage as a
first-class blocking gate, parallel to conformance. PRs no longer
discover coverage failures only via CI; the implementer is required
to check before reporting done, and the reviewer is required to
verify.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Architecture record for the agent-first coverage initiative seeded by
the 2026-05-13 PRD. Captures the durable decisions:
- 4-layer architecture (L0 vitest, L1 diff, L2 aggregate, L3 mutation)
- Manifest-driven coverage band as single source of truth (vitest +
assertFeatureConformance + pnpm coverage:diff all read from it)
- Cover-the-diff (changed lines), not cover-the-new-code
- Committed coverage/summary.json (no SaaS), trend via git log
- Mutation testing scoped to entities + use-cases, on-demand only
- Machine-first output format (JSON stdout, human stderr)
Glossary gets a new "Coverage" section with 7 entries (coverage band,
L0-L3 layers, diff coverage, mutation testing, mutation score,
coverage/summary.json), plus two relationship rows and a flagged
ambiguity for "coverage" qualifiers.
prompt-context.sh hook gets a 9th keyword group — when a prompt
mentions coverage / uncovered / lcov / mutation / stryker, the
relevant ADR + guide path are injected as additional context for
the turn.
This is the documentation layer of the coverage epic. Implementation
(manifest schema, vitest auto-derive, scripts, boot assertion,
mutation tooling) lands in subsequent stories.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final sweep for setup-process bookkeeping not caught by template-reset-v1.
ADRs drop Plan-N qualifiers; spec collapses the historical 11-phase
migration table; scaffolding guide drops "Phase added" column; comment
prefixes referencing R-numbers in test describes / eslint inline comments
are normalized. Architecture-level rule IDs (R40, R52, E0, J0, etc.) are
preserved where they serve as stable cross-references in ADRs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Rename docs/decisions/adr-012-lazar-conformance.md → adr-012-feature-conventions.md
- Strip "Lazar", "Plan 8/9/10/11", "refactor-logs" refs from all ADRs,
architecture docs, HTML explainers, and feature/core AGENTS.md files
- Update all incoming links in docs/, packages/*/AGENTS.md, HTML explainers
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures the decision to adopt @ai-hero/sandcastle as the orchestration
substrate for agent-driven development in this template. Records the
8-point decision (workspace dep, .sandcastle/ prompts, Dockerfile,
dispatch.mjs orchestrator, planning vs execute modes, generator-first
reviewer check, bring-your-own-key, per-task max-attempts), the four
alternatives considered (bare CLI / Copilot Workspace / custom-from-
scratch / no orchestrator), and four trade-offs (external dep, token
cost, Docker dependency, manual state mutation in v1).
Surfaces the decision at the top of README.md and AGENTS.md so new
contributors see the agent-driven framing before they hit the package
map or daily commands.
- ADR-015: Status → Optional with scaffold command + behavior note (bus absent
means no-op, IJobQueue unaffected)
- events-and-jobs.md: prerequisite callout block explaining core-events is
optional, how to scaffold, and which features require it
- data-flow-explainer.html: note bus is optional in BindProductionContext blurb;
add inline comment in code snippet that bus is scaffoldable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Five fixes surfaced by the branch-wide code review on the realtime layer:
- server.ts: replace dynamic `import("@repo/auth/di/container")` with a
static top-of-file import. The dynamic-import workaround from 6a0ac63 is
no longer needed once the root tsconfig + TSX_TSCONFIG_PATH expose
decorator metadata to tsx; verified by booting `pnpm dev` clean.
- server.ts: correct the inline structural type for `validateSession` to
match the real `IAuthenticationService` contract (non-nullable, throws
on invalid session) and wrap the call in try/catch so unauthenticated
bubbles to a `null` return instead of dead-code `result ? ... : null`.
- bind-production.ts: extract `maybeRegisterRealtimePing()` that wraps the
built-in ping inbound handler in the same `withSpan(withCapture(...))`
sandwich the realtime-handler generator emits (R41–R44), so the
proof-of-life channel models the convention rather than registering raw.
- bind-production.test.ts: add 4 tests for the `REALTIME_PING_DISABLED`
env-gate (registered when unset in both binders, not registered when
"true", treated as enabled when "1").
- docs/guides/realtime.md: correct the integration-test reference at
line 285 — the test does not call `bindAllDevSeed()`; it builds the
Socket.IO server inline and exercises gates 1+2 only (gates 3+4 live in
socket-io-realtime-server.test.ts).
- adr-016: add a "Known follow-ups" section recording 6 lower-priority
refinements deferred from this branch (bridge stub test scaffolding,
registry register/registerChannel precedence, channel-template dot
constraint, server bare catch{}, BindAllDeps Partial widening, AGENTS.md
anchor count phrasing).
CI gates: lint 0 errors / 4 warnings (pre-existing turbo.json warnings),
typecheck clean, 24 web-next tests pass (was 20; 4 new env-gate tests),
boundaries 0 issues across 504 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Also folds in the spec correction noted in the plan's known follow-up
\#1: subscribe takes consumerFeature: string as a second arg between
descriptor and handler. § 3.3 and § 5.4 updated.
Plan 10 documented R44 (capture at originating-throw layer) but only the
R43 repo leg was wired. captureException had zero call sites in any
controller or use-case body. This commit closes the gap.
Mechanism:
- Extract __sentryReported flag helpers into core-shared/instrumentation/
reported-flag.ts. SentryLogger switches to importing them; RecordingLogger
carries an inlined copy (tooling → core boundary disallows the import).
- Add withCapture(logger, tags, fn) higher-order wrapper paralleling
withSpan. On throw: capture-with-tags, mark, re-throw. Bail if the flag
was already set — covers the bubbled-from-repo case so each error
surfaces in the logger exactly once with the inner-most layer's tags.
- Apply withSpan(withCapture(factory)) in every feature's bind-production
and bind-dev-seed: auth (3 use cases × 3 controllers), blog (3×3),
marketing-pages (2×2), navigation (1×1), media (3×3). Span is outermost
so the errored span timing reflects the capture-and-rethrow.
- RecordingLogger.captureException now also honours the flag — test
capture counts stay honest when both repo and outer layer wrap.
Tests:
- packages/core-shared/src/instrumentation/with-capture.test.ts —
4 cases covering success, capture-on-throw, mark-on-capture, no-double
via the flag.
- packages/blog/tests/r44-no-double-capture.test.ts — 3 cases: repo throw
→ 1 capture with repo tags; controller parse fail → 1 capture with
controller tags; success → 0 captures.
Verification: pnpm test 26/26, pnpm lint 15/15, pnpm typecheck 14/14.
Docs: ADR-014 and the refactor log gain a "Post-merge follow-up" section
recording the gap, the fix, and the underlying lesson (don't describe
intent as shipped state — grep first).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the ADR-014 stub with the full Accepted-status decision record:
context, the 7 numbered decisions (vendor-neutral interfaces, full-depth
instrumentation, throw-site capture, PII rules, three Sentry projects,
ESLint boundary, Recording* test pair), alternatives considered,
positive/negative consequences, and an "execution notes" section
covering the spec deviations and surprises encountered.
Updates the refactor log: ticks all 33 tasks, populates "Decisions
deviated from spec" (PII key list extended with ipaddress; spec
section appended as §16 not §10; vite.config skipped; HTML section
numbering kept conservative) and "Notable surprises" (apps needed
direct core-shared deps; deep subpath exports for dynamic import;
peerDependenciesMeta.optional for @sentry/node and @sentry/react;
pre-existing lint debt; allowlist patterns needed **/-prefix for
flat-config glob matching from sub-package cwd).
Final verification (run before commit):
- pnpm test → 26/26 tasks pass
- pnpm lint → 15/15 tasks pass (warnings-only)
- pnpm typecheck → 14/14 tasks pass
- R31 grep gate (sendDefaultPii: true) → clean, no matches
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Records the Plan 9 architectural decision (schemas in use-case file,
runtime output validation, presenter pattern, feature-scoped error
middleware, ./ui subpath split). ADR-012 gets a one-line cross-
reference to the new ADR. Refactor log gets a Summary section with
commit table and conformance checklist.
Plan 9 complete. The deferred doc-update pass (CLAUDE.md / AGENTS.md /
guides) — combined with the still-pending Plan 8 items — is the next
follow-up.
Refactor log: Summary, doc-update checklist
Spec: R29, R30
First slice of the Plan 8 deferred doc-update checklist:
- CLAUDE.md Key Conventions: factory-function use cases/controllers,
entities/models/<x>.ts paths, .toDynamicValue DI bindings, direct
injection in tests
- docs/architecture/overview.md data-flow box updated to factory style
(controller resolved via container.get<IXController>; use case factory
takes deps as args)
- docs/decisions/adr-012-lazar-conformance.md created — records the
conformance decision and four intentional divergences
- docs/superpowers/plans/2026-05-05-plan-7-tdd-foundation.md and the
matching spec annotated with a "pre-Plan-8 layout" note pointing at
the refactor log
Remaining Plan 8 doc-update items (root AGENTS.md, per-feature AGENTS.md,
adding-a-feature.md, tdd-workflow.md, testing-strategy.md,
vertical-feature-spec.md §6/§10, core-testing AGENTS.md) intentionally
paused — Plan 9 (input/output unification) will change overlapping
content, so resuming after Plan 9 lands avoids double-churn.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures the decision to add @repo/core-testing, factories, contract
suites, vitest safety defaults, coverage thresholds, Storybook
test-runner, and CI as one cohesive TDD foundation. Per-feature
AGENTS.md gains a Tests section pointing to factories, contract suite,
and the canonical test commands.
Spec: §7.4, §7.5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>