docs: surface fallow as 5th conformance gate in CLAUDE.md
This commit is contained in:
41
CLAUDE.md
41
CLAUDE.md
@@ -39,23 +39,24 @@ Turborepo + pnpm monorepo organized by vertical features. Each feature (`auth`,
|
||||
- `docs/architecture/vertical-feature-spec.md` — Design spec with rationale and decision log
|
||||
- `docs/guides/scaffolding-a-feature.md` — `turbo gen feature` reference (fast path; prefer this over the manual walkthrough)
|
||||
- `docs/guides/adding-a-feature.md` — End-to-end new feature walkthrough (manual path; for cases the generator's Phase-1 scope doesn't cover)
|
||||
- `docs/guides/events-and-jobs.md` — publish/consume/schedule cookbook (cross-feature events + background jobs; *requires `gen core-package events`*)
|
||||
- `docs/guides/realtime.md` — Socket.IO channels, broadcasts, handlers (*requires `gen core-package realtime`*)
|
||||
- `docs/guides/audit-and-compliance.md` — DPA-compliant audit logging cookbook (*requires `gen core-package audit`*)
|
||||
- `docs/guides/events-and-jobs.md` — publish/consume/schedule cookbook (cross-feature events + background jobs; _requires `gen core-package events`_)
|
||||
- `docs/guides/realtime.md` — Socket.IO channels, broadcasts, handlers (_requires `gen core-package realtime`_)
|
||||
- `docs/guides/audit-and-compliance.md` — DPA-compliant audit logging cookbook (_requires `gen core-package audit`_)
|
||||
- `docs/architecture/template-tiers.md` — must-have vs optional packages and how to scaffold the optionals
|
||||
|
||||
## Conformance system
|
||||
|
||||
Every feature has a `src/feature.manifest.ts` declaring its use cases, audits, publishes, consumes, and required cores. Drift is caught at four latencies:
|
||||
Every feature has a `src/feature.manifest.ts` declaring its use cases, audits, publishes, consumes, and required cores. Drift is caught at five latencies:
|
||||
|
||||
| Layer | Latency | Catches |
|
||||
|---|---|---|
|
||||
| **TypeScript brands** | 0s | forgotten `withSpan` / `withCapture` / `withAudit` at bind time |
|
||||
| **ESLint rules** | <1s | manifest ↔ code drift; undeclared `bus.publish` / `auditLog.record`; missing manifest; missing sibling test |
|
||||
| **Boot assertion** (`pnpm dev`) | ~3s | binding without required brand at runtime; manifest edited without rebinder |
|
||||
| **CI drift gate** (`pnpm conformance`) | ~120s | orphan event consumers across features |
|
||||
| Layer | Latency | Catches |
|
||||
| -------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| **TypeScript brands** | 0s | forgotten `withSpan` / `withCapture` / `withAudit` at bind time |
|
||||
| **ESLint rules** | <1s | manifest ↔ code drift; undeclared `bus.publish` / `auditLog.record`; missing manifest; missing sibling test |
|
||||
| **Boot assertion** (`pnpm dev`) | ~3s | binding without required brand at runtime; manifest edited without rebinder |
|
||||
| **CI drift gate** (`pnpm conformance`) | ~120s | orphan event consumers across features |
|
||||
| **Fallow** (`pnpm fallow`) | ~30–60s | dead exports / unused files; duplicate code; circular deps; complexity hotspots; AI-change audit drift |
|
||||
|
||||
The five conformance ESLint rules: `feature-must-have-manifest` (error), `usecase-must-have-test-file` (error), `required-cores-installed` (error), `no-undeclared-event-publish` (warn), `no-undeclared-audit` (warn).
|
||||
The five conformance ESLint rules: `feature-must-have-manifest` (error), `usecase-must-have-test-file` (error), `required-cores-installed` (error), `no-undeclared-event-publish` (warn), `no-undeclared-audit` (warn). Fallow runs as a fifth layer, post-ESLint, whole-codebase.
|
||||
|
||||
See `docs/architecture/agent-first-workflow-and-conformance.md` for the full design and `docs/guides/conformance-quickref.md` for the day-to-day reference.
|
||||
|
||||
@@ -83,11 +84,11 @@ See `docs/architecture/agent-first-workflow-and-conformance.md` for the full des
|
||||
- **PII handling is non-negotiable** — `sendDefaultPii: false` everywhere (R31, CI grep gate); replay default-masks all text/inputs/media (R34, R35, allowlist starts empty); `setUser({ id })` only — no email/username (R36); server-side PII scrubbing happens at the OTel processor layer (`PiiScrubSpanProcessor` + `PiiScrubLogRecordProcessor`) before any exporter sees the data (R32, R33, ADR-017 §7)
|
||||
- **Three apps, three Sentry projects** — `WEB_NEXT_SENTRY_DSN`, `CMS_SENTRY_DSN`, `WEB_TANSTACK_SENTRY_DSN`. Browser DSNs use `NEXT_PUBLIC_` (web-next) and `VITE_` (web-tanstack) prefixes
|
||||
- **Instrumentation binding is orthogonal to repo binding** — `bindAll()`'s Rule 0 (DSN → OTel+Sentry vs Noop) is independent of `USE_DEV_SEED` / `NODE_ENV`. Run `pnpm dev` with `WEB_NEXT_SENTRY_DSN` set to test the integration locally
|
||||
- **Cross-feature events go through `IEventBus` (E0)** — In-feature reactions are direct use-case calls, not bus publishes. The bus is for *crossing* feature boundaries (e.g. `auth` → `marketing-pages` welcome email)
|
||||
- **Cross-feature events go through `IEventBus` (E0)** — In-feature reactions are direct use-case calls, not bus publishes. The bus is for _crossing_ feature boundaries (e.g. `auth` → `marketing-pages` welcome email)
|
||||
- **Event contracts are public; handlers are private (E1)** — Publisher's `events/<x>.event.ts` is exported from the feature root barrel. Consumer's `events/handlers/on-<publisher>-<event>.handler.ts` is never re-exported (ESLint-enforced via `core-eslint/rules/no-handler-reexport`)
|
||||
- **Jobs are for *deferred* work, not abstraction (J0)** — Synchronous code stays synchronous. A job exists only when something must run off the request path (latency, retries, cron). Feature packages enqueue via `IJobQueue` only — direct `payload.jobs.queue()` is ESLint-blocked outside `core-shared/jobs/`
|
||||
- **Jobs are for _deferred_ work, not abstraction (J0)** — Synchronous code stays synchronous. A job exists only when something must run off the request path (latency, retries, cron). Feature packages enqueue via `IJobQueue` only — direct `payload.jobs.queue()` is ESLint-blocked outside `core-shared/jobs/`
|
||||
- **Realtime is for state delivery, not for replacing tRPC (R0)** — Persistent request/response operations belong on tRPC procedures. Use realtime when the server needs to push without a request or the data is too high-frequency for HTTP
|
||||
- **Realtime channel descriptors are exported; handlers are private (R1)** — A feature's `realtime/<name>.channel.ts` is re-exported from the root barrel; `realtime/handlers/*.handler.ts` is wired only in bind-* files and never re-exported (ESLint-enforced via `no-realtime-handler-reexport`)
|
||||
- **Realtime channel descriptors are exported; handlers are private (R1)** — A feature's `realtime/<name>.channel.ts` is re-exported from the root barrel; `realtime/handlers/*.handler.ts` is wired only in bind-\* files and never re-exported (ESLint-enforced via `no-realtime-handler-reexport`)
|
||||
- **`socket.io` lives in `@repo/core-realtime` only (R2)** — Feature packages MUST NOT import `socket.io` or `socket.io-client`. ESLint rule `no-direct-socket-io` enforces this; allowlist covers `core-realtime/src/socket-io-*.ts` and `apps/*/server.ts`
|
||||
- **Manifest-first ordering** — for any new use case, the workflow is **(1) manifest entry** → **(2) contracts** (`xInputSchema`, `xOutputSchema`, `IXUseCase`) → **(3) tests (red)** → **(4) implementation (green)**. The generator emits the manifest + a self-asserting `bind-production.ts` so new features are conformance-compliant by default
|
||||
- **Self-asserting `bindProductionX(ctx)`** — every feature's bind-production calls `assertFeatureConformance(container, manifest, symbols, ctx)` at its tail. `pnpm dev` refuses to boot on drift
|
||||
@@ -101,10 +102,10 @@ Storybook MCP available at `http://localhost:6006/mcp` — use `list-all-documen
|
||||
|
||||
## Key Ports
|
||||
|
||||
| Service | Port |
|
||||
|---|---|
|
||||
| Next.js | 3000 |
|
||||
| Payload CMS | 3001 |
|
||||
| Service | Port |
|
||||
| -------------- | ---- |
|
||||
| Next.js | 3000 |
|
||||
| Payload CMS | 3001 |
|
||||
| TanStack Start | 3002 |
|
||||
| PostgreSQL | 5432 |
|
||||
| Storybook | 6006 |
|
||||
| PostgreSQL | 5432 |
|
||||
| Storybook | 6006 |
|
||||
|
||||
Reference in New Issue
Block a user