Commit Graph

841 Commits

Author SHA1 Message Date
8cb531e0cd feat(core-eslint): add usecase-must-be-wired conformance rule
Catches manifest use cases that aren't wired through wireUseCase(...) in
bind-production.ts / bind-dev-seed.ts. wireUseCase is the canonical helper
that attaches __instrumented / __captured / __audited brands — skipping
it produces an unbranded binding that assertFeatureConformance would
reject at boot. This rule shifts that detection from ~3s (boot) to <1s
(lint), keeping the layered conformance pattern: TS brands (compile),
ESLint (lint), boot assertion (dev), smoke tests (CI).

CLAUDE.md + conformance-quickref.md updated for the new rule (5 → 6).
2026-05-18 11:03:17 +02:00
bd770cad5d test(features): exercise bind-production conformance assertion in CI
Each feature's bind-production.ts already ends with
assertFeatureConformance(), but that check only fired on `pnpm dev`.
Adds a smoke test per feature that invokes the binder with a Noop ctx,
so missing __instrumented / __captured / __audited brands now fail
under `pnpm test` (and therefore in CI), closing the gap between the
TypeScript brand layer and the boot-time runtime assertion.
2026-05-18 10:57:20 +02:00
756e36c720 refactor(work): move epic folders into docs/work/epics/
The previous layout placed epic folders directly under docs/work/
alongside prds/ and _system/. Tightening: epics now live in their
own docs/work/epics/ subfolder, peer to prds/ and _system/. Same
shape as the existing prds/ bucket.

Final docs/work/ layout:
  README.md
  prds/<slug>.prd.md
  _system/_state.json
  epics/<slug>/_epic.md + <story-folder>/_story.md

Renames (git mv preserves history):
- docs/work/binder-wrap-helper/
    -> docs/work/epics/binder-wrap-helper/
- docs/work/library-evaluation-policy/
    -> docs/work/epics/library-evaluation-policy/
- docs/work/ci-security-and-supply-chain/
    -> docs/work/epics/ci-security-and-supply-chain/

Tooling updates:
- state-builder.mjs walks workRoot/epics/ directly; SKIP_FOLDERS
  obsoleted (no more sibling folders to filter out).
- dispatch.mjs's findNextTask, tickStoryBulletInEpic, and
  flipEpicDoneIfAllStoriesDone all join with "epics" segment.
- prd-ship.mjs's deriveShippingCommits walks workRoot/epics/ and
  git-logs docs/work/epics/<epic>/.
- decomposer.prompt.md emits epics under docs/work/epics/<epic-id>/.
- handoff + grill-with-docs glossary references updated.
- Glossary entry for Epic updated.

Reserved future shape: when a task-tracker integration (ClickUp,
Linear) ships, the epics/ subfolder hosts <task-id>-<slug>/
folders. Today it just hosts bare slugs.
2026-05-14 21:21:51 +02:00
bae4b66fa4 refactor(work): drop date prefixes + move _state.json into _system/
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.
2026-05-14 21:16:51 +02:00
90fc2853f2 feat(work): add ISO timestamps + auto-bump on staged work-doc changes
- New scripts/work/bump-updated-timestamps.mjs stamps the `updated:`
  frontmatter field to the current ISO 8601 UTC timestamp on every
  staged docs/work/**/*.md file. Idempotent; adds the field after
  `created:` if missing.
- .husky/pre-commit invokes the bump script as step 2 (before
  rebuild-state) so _state.json sees the fresh timestamp.
- Backfill all existing work docs (4 PRDs + 3 epics + 21 stories):
    * created: promoted from \`YYYY-MM-DD\` -> ISO timestamp using
      git log --diff-filter=A on each file (first-commit date for
      stories that had no \`created:\` line, midnight UTC for PRDs
      and epics that had date-only created).
    * updated: added from \`git log -1 --format=%aI\` on each file
      (last-commit timestamp); will be re-stamped to "now" by the
      pre-commit hook on this commit.

Stories that had no \`created:\` line now get one.
2026-05-14 21:10:34 +02:00
3fc5c0f1ca feat(work): auto-tick epic story bullets when a story finishes
- Add tickStoryBulletInEpic(workRoot, epic, story) helper that finds
  the bullet in the parent epic's `## Stories` section linking to the
  given story folder and flips `- [ ]` to `- [x]`. Idempotent.
- applyApprovedState now ticks the parent epic bullet whenever a
  story flips to status: done (alongside the existing per-task tick
  and epic-status flip). Epic file gets staged on either ticked-or-
  flipped, not just flipped.
- Backfill all 3 existing epics: 21 bullets ticked to match their
  already-done story statuses (binder-wrap-helper x3, library-
  evaluation-policy x9, ci-security-and-supply-chain x9).
2026-05-14 21:05:06 +02:00
dd58974067 chore(work): finish epic 2026-05-14-ci-security-and-supply-chain 2026-05-14 20:17:29 +02:00
bb5502737c chore(work): tick task in 09-ci-security-guide-and-docs 2026-05-14 20:14:57 +02:00
9d83a6a5a2 docs(ci-security): add CI security guide + CLAUDE.md convention bullet
Covers the four-pillar stack (Renovate, Socket, trace revalidation,
GitHub-native gates), the failure-mode hierarchy table from ADR-023 §5,
consumer-toggleable settings, Socket App + gitleaks install instructions,
CodeQL private-repo note, and two worked examples (minor-bump auto-merge;
major-bump block + hard-divergence revalidation issue).

CLAUDE.md Key Conventions gains the CI security bullet pointing to
ADR-023 + docs/guides/ci-security.md for agent discoverability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 18:12:29 +00:00
33ed9e97e4 chore(work): finish 08-reviewer-prompt-update 2026-05-14 20:05:17 +02:00
83b6119ca6 docs(sandcastle): add CI security checks section to reviewer prompt
Instructs the reviewer agent to inspect Socket critical findings and
CodeQL error-severity findings via gh run view before issuing a verdict.
Composes with the existing library-trace check — all three must pass for
approval.
2026-05-14 18:03:36 +00:00
41bf107fc4 chore(work): finish 07-gitleaks-precommit 2026-05-14 20:01:16 +02:00
9b235c7d1c ci(tooling): add gitleaks pre-commit secret scan with __seeds__ allowlist
Blocks commits containing known secret patterns (e.g. Stripe sk_test_*)
before they reach the remote. Exits gracefully with a warning when
gitleaks is not in $PATH so developers who haven't installed it are not
blocked. .gitleaks.toml extends the upstream default ruleset and
allowlists __seeds__/** to prevent false positives from test fixtures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:59:10 +00:00
2f57003b55 chore(work): finish 06-codeql-and-audit-signatures 2026-05-14 19:56:40 +02:00
63b3cb0c10 ci(security): add CodeQL javascript-typescript analysis workflow
Adds CodeQL static analysis on push to main, pull_request, and weekly
on Wednesday 02:00 UTC (staggered from trace-revalidation Monday cron).
Uses the default security-and-quality query suite. Includes a consumer
note that private repos require GitHub Advanced Security.
2026-05-14 17:55:41 +00:00
1979041197 chore(work): tick task in 06-codeql-and-audit-signatures 2026-05-14 19:54:42 +02:00
480ec67a48 ci(security): add pnpm audit signatures step to validate job
Catches tampered package signatures (compromised maintainer
supply-chain attack) before they reach CI artifacts.
2026-05-14 17:53:40 +00:00
331573bc4f chore(work): finish 05-trace-revalidation-workflow 2026-05-14 19:53:07 +02:00
6869a51541 ci(scripts): add trace-revalidation-weekly workflow
Adds .github/workflows/trace-revalidation-weekly.yml to run the library
trace revalidation script on a weekly Monday cron (06:30 UTC) and on
workflow_dispatch. Permissions scoped to issues:write + contents:read
only — no contents:write, workflow does not auto-edit traces.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:52:01 +00:00
a7a4299213 chore(work): tick task in 05-trace-revalidation-workflow 2026-05-14 19:50:49 +02:00
1b6e7189c7 feat(scripts): add trace revalidation script and tests
Walks every approved/pre-shipped trace, re-runs its verification-commands,
classifies soft/hard divergence, and manages GitHub issues via the gh CLI:
- hard drift (non-zero exit or CVE/abandoned keywords) → per-dep
  library-policy/re-evaluation issue; duplicate-issue guard prevents spam
- soft drift (dormant/warning/deprecated keywords at exit 0) → rolling
  library-policy/dashboard issue (create or update)
- clean + lastRevalidated set → close any stale re-evaluation issue
- rejected traces skipped entirely

ghRunner and commandRunner are injectable for hermetic integration tests;
12 fixture-based tests cover all six story scenarios plus edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:48:20 +00:00
88d3d4b362 chore(work): finish 04-major-bump-reevaluation 2026-05-14 19:34:44 +02:00
1bee0544de feat(scripts): add --renovate-pr mode to library-decisions check
Extends check.mjs with checkRenovatePr() (and a matching CLI flag) that
runs on Renovate PR branches: it parses the pnpm-lock.yaml diff to find
bumped packages, classifies each as major/minor/patch, and for any
feature- or core-tier major bump requires the trace's lastRevalidated
field to equal today's ISO date.

- App-tier deps and non-Renovate branches pass unconditionally.
- Minor/patch bumps pass unconditionally (semver-compatible by contract).
- On failure, the output references the evaluate-library skill and the
  stale trace path (ADR-023 close-the-drift-gate intent).

Six integration tests cover all required cases: minor bump, major+fresh,
major+stale, app-tier major, patch, and non-Renovate branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:32:48 +00:00
3d98a14e45 chore(work): finish 03-renovate-adoption 2026-05-14 19:18:20 +02:00
0d2ae73d2a chore(deps): add Renovate config with ecosystem grouping and automerge
Adds .github/renovate.json extending config:base,
helpers:pinGitHubActionDigests, :separateMajorReleases, :automergeMinor,
and :automergePatch. Groups Sentry, OpenTelemetry, tRPC, Payload, and
Inversify into weekly per-cluster PRs to reduce noise. Enables Dockerfile
manager for .sandcastle/Dockerfile. Sets dependencyDashboard:true for a
single Renovate-managed tracking issue. Uses chore(deps): / chore(deps-major):
commit prefixes so release-please bump rules apply cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:17:14 +00:00
0e748ae714 chore(work): finish 02-socket-integration 2026-05-14 19:16:31 +02:00
ea5db36da6 ci(tooling): add socket-cli scan step to validate job
Adds a supply-chain scan step that runs `socket-cli` against the
lockfile on PRs that touch package.json or pnpm-lock.yaml. The step
is gated behind a git-diff paths check so it only fires when dependency
files change. The repo-root .socket.json (critical → error) causes the
step to exit non-zero on any critical finding, blocking the PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:15:08 +00:00
49619931d5 chore(work): tick task in 02-socket-integration 2026-05-14 19:11:34 +02:00
432a606411 feat(tooling): add .socket.json and Filter 9 to evaluate-library skill
Add repo-root .socket.json (critical=error, high=warn, medium/low=ignore)
and extend the evaluate-library skill's 8-filter protocol to 9 filters by
adding Filter 9 — Supply-chain behavior (Socket). Positions Socket last in
Phase 2 (most expensive: network call), documents socket-cli as the
verification command, and maps clean/flagged/<finding-summary> to the
trace's socketRisk field. Updates short-circuit skip lists for all earlier
Phase 2 filters and adds socketRisk to TRACE-TEMPLATE.md frontmatter.
2026-05-14 17:10:15 +00:00
f704cc5a01 chore(work): finish 01-trace-schema-extensions 2026-05-14 19:06:11 +02:00
3bf6a55481 feat(scripts): extend trace schema with socketRisk and lastRevalidated
Add socketRisk (9th filter result) and lastRevalidated (nullable ISO date)
to the library-decision trace schema. Downstream enforcement layers
(evaluate-library skill, check.mjs major-bump mode, revalidate.mjs cron)
all depend on these fields being validated at the schema layer first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:04:05 +00:00
c17d3f147d chore(work): decompose 2026-05-14-ci-security-and-supply-chain epic
Decomposer produced 9 stories under docs/work/2026-05-14-ci-
security-and-supply-chain/, ordered to land the schema foundation
first and the cross-referencing content (reviewer prompt, guide)
last:

01 - trace schema extensions (socketRisk + lastRevalidated)
02 - Socket integration (skill + CI)
03 - Renovate adoption
04 - major-bump re-evaluation flow
05 - trace revalidation workflow
06 - CodeQL + audit signatures
07 - gitleaks pre-commit
08 - reviewer prompt update
09 - CI security guide + docs

Also fixes a one-char status typo in the PRD frontmatter
(\`appoved\` -> \`approved\`) that landed with the decompose run.

Anchored by ADR-023 + the approved PRD at
docs/work/prds/2026-05-14-ci-security-and-supply-chain.prd.md.
Sequencing: depends on stories 01/02/04/06 of the in-flight
library-evaluation epic landing first.
2026-05-14 18:59:12 +02:00
90341ff475 docs: introduce CI security + supply-chain stack (ADR-023 + PRD)
- 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.
2026-05-14 18:47:25 +02:00
bb9983f10b chore(work): finish epic 2026-05-14-library-evaluation-policy 2026-05-14 12:14:21 +02:00
239faf7e56 docs(claude-md): add library evaluation policy bullet to Key Conventions
New runtime dependencies require a library trace produced by the
/evaluate-library skill — without this bullet the policy is invisible
to agents starting a fresh session (ADR-022).
2026-05-14 10:13:08 +00:00
085bb2ad29 chore(work): finish 08-backfill-traces 2026-05-14 12:12:37 +02:00
1108e24ea0 chore(deps): backfill library traces for un-cited cluster
Add approved trace files for payload, @trpc/server, @trpc/client, zod,
superjson, @payloadcms/db-postgres, @payloadcms/richtext-lexical, globals,
react, react-dom, vitest, @tanstack/react-query, and all @testing-library/*
packages. All traces dated 2026-05-14, decision: approved, adr: null.

Establishes the baseline so the pre-commit library-decisions gate is
additive (new deps require traces) rather than disruptive (old deps fail
immediately). All 34 trace files pass validateTrace() from schema.mjs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:10:23 +00:00
b0f1db8151 chore(work): tick task in 08-backfill-traces 2026-05-14 12:03:07 +02:00
9ff861667a chore(deps): backfill library traces for ADR-017 cluster
Adds approved trace files dated 2026-05-14 for all 13 OpenTelemetry
packages in packages/core-shared and packages/core-audit:

  @opentelemetry/api, api-logs, context-async-hooks,
  instrumentation, instrumentation-http, instrumentation-pg,
  instrumentation-undici, resources, sdk-logs, sdk-metrics,
  sdk-node, sdk-trace-base, semantic-conventions

All files pass validateTrace() from schema.mjs. The @sentry/opentelemetry
bridge was already covered in the ADR-014 cluster commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:01:30 +00:00
112df2cfe7 chore(work): tick task in 08-backfill-traces 2026-05-14 11:57:10 +02:00
cf3f160148 chore(deps): backfill library traces for ADR-014 cluster
Approved traces for @sentry/nextjs, @sentry/opentelemetry,
@sentry/node, and @sentry/react — all at ^10.51.0 in
packages/core-shared. Without these files the pre-commit
library-trace hook would fire retroactively on any future
package.json touch; backfill establishes the baseline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:53:04 +00:00
9e7723f9a5 fix(scripts): remove broken session-resume from dispatch loop
Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests + visual regression (push) Has been cancelled
Coverage snapshot / snapshot (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
Sandcastle rejects `resumeSession` when `maxIterations > 1` with
"Resume applies to iteration 1 only; multi-iteration resume
semantics are not supported." Since a TDD slice needs the full
30-iteration budget, the session-resume path we shipped in d5c0120
is dead infrastructure that breaks dispatch mid-run.

Rip it out cleanly:
- runOneSlice drops the resumeSession param + the
  context-exhaustion safety net + sessionId/usage return fields
- executeDispatch drops the currentStory/currentSession bookkeeping
  and the token-reset threshold
- helpers totalInputTokens + isContextExhaustedError go (only used
  by the resume path)
- SANDCASTLE_SESSION_TOKEN_RESET removed from .env.example

Net: -153 lines. Each slice is again an independent sandcastle
session; token cost per slice goes up (each implementer
re-discovers context) but the multi-iteration TDD shape works.
A different cross-slice context-passing mechanism (e.g. a
story-level context summary injected into each task spec) is left
as future work.
2026-05-14 11:48:32 +02:00
68426b83b0 chore(work): tick task in 08-backfill-traces 2026-05-14 11:42:09 +02:00
091cd6d593 chore(deps): backfill library traces for ADR-002 cluster
Add approved trace files for inversify ^6.2.0 and reflect-metadata
^0.2.2, both mandated by ADR-002 (InversifyJS for DI) and used across
all five feature packages. Both pass validateTrace() from schema.mjs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:40:29 +00:00
543412ea42 chore(work): finish 07-generator-pre-shipped-traces 2026-05-14 11:37:37 +02:00
b1e2e8a788 feat(tooling): pre-ship approved library traces in optional core generator templates
Each of the five optional core package generators (events, realtime, audit,
trpc, ui) now copies pre-written decision: approved trace files into
docs/library-decisions/ at scaffold time, covering every direct runtime
dependency of that core package.

This prevents a pre-commit gate failure the first time a developer runs
pnpm turbo gen core-package <name> — the generator is the policy-compliant
path, so the traces land by construction.

- Added docs/library-decisions/*.md.hbs trace files under each of the five
  core-package template directories (15 files total)
- Updated generator config to emit traces into workspace docs/library-decisions/
  via a second emitTemplateTree call per core package
- Updated all five __snapshots__/core-package/*.snapshot.json to include the
  new trace file entries
- Added verify-doc-shas.test.ts to pin SHA256 hashes of all 15 trace templates
  so snapshot and file content cannot drift independently

ADR refs: events→ADR-015, realtime→ADR-016, audit→ADR-018;
trpc and ui cite closest ADR or null where no specific ADR exists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:34:17 +00:00
090410e9c3 chore(work): finish 06-sandcastle-reviewer-prompt 2026-05-14 07:58:55 +02:00
26bcbb7a91 feat(scripts): add --staged-against flag to library-decisions check
Adds `--staged-against <base>` CLI flag to `check.mjs` so the reviewer
agent can compare `git diff <base>...HEAD` instead of the git index.
This gives the sandcastle reviewer a CI-compatible code path that works
in its clean sandbox where `git diff --cached` may be empty.

Appends a "Library-trace check" section to `.sandcastle/reviewer.prompt.md`
instructing the reviewer to run the command before issuing a verdict.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 05:57:10 +00:00
6890526ced chore(work): finish 05-human-guide 2026-05-14 07:53:06 +02:00
603104ca97 docs(guides): add adding-a-library.md human reading-room guide
Translates ADR-022 from decision-record density into an onboarding
narrative: why the policy exists, the tier trigger, the four enforcement
layers, a step-by-step walkthrough, and worked approved/rejected examples
(clsx pass, trpc-to-openapi named-consumer fail).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 05:52:08 +00:00