docs: add canonical glossary + install mattpocock skills adapted for repo

docs/glossary.md is the shared vocabulary source for humans and agents.
Resolves every cross-cutting term used in this repo (feature, use case,
manifest, slice, conformance, dispatch, ...) with one-sentence definitions,
relationships, and flagged ambiguities. Linked from CLAUDE.md "Read First"
and AGENTS.md preamble so every session loads it early.

.claude/skills/ installs four mattpocock skills adapted to this monorepo:
  - to-prd: writes to docs/work/prds/ with the repo's PRD frontmatter +
    merged user-stories/implementation/testing sections
  - grill-with-docs: points at docs/decisions/ + docs/glossary.md; adds
    feature.manifest.ts + conformance-rule cross-checks
  - grill-me: minor — adds pnpm work / fallow / manifest shortcuts
  - handoff: adds the repo's specific don't-duplicate artifacts list

Also fixes a missed "Phase-1" residual in CLAUDE.md's Read First section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 13:04:42 +02:00
parent 2edc76002a
commit a372eeda86
8 changed files with 587 additions and 1 deletions

253
docs/glossary.md Normal file
View File

@@ -0,0 +1,253 @@
# Glossary
Canonical vocabulary for `template-vertical`. Shared by humans and AI agents — every term means **the same thing** here. Terms specific to this repo's domain (monorepo / Clean Architecture / agent-first workflow / conformance). General programming concepts (DI, retries, errors, etc.) don't belong unless they have a project-specific meaning.
**Rules:**
- One sentence per definition. Define what it **is**, not what it does.
- Pick one canonical term; list aliases under `_Avoid:_`.
- Relationships expressed with bold term names + cardinality.
- Flag ambiguities under "Flagged ambiguities" with a resolution.
- Reference ADRs by ID (`ADR-NNN`); reference paths sparingly (they rot fast).
---
## Packages
**Package**:
A workspace member under `packages/` or `apps/` with its own `package.json` and tag. The atomic unit of dependency, build, and boundary enforcement.
_Avoid:_ module, library, app (unless specifically `apps/`).
**Tag**:
The boundary classification on a package (`app`, `core`, `core-composition`, `feature`, `tooling`). Enforced by ESLint (`eslint-plugin-boundaries`) and Turborepo `boundaries`. See `AGENTS.md` → Boundary Rules.
**Feature** (a.k.a. **feature package**):
A vertical slice owning its Clean Architecture layers + integrations under `packages/<name>/`. Currently: `auth`, `blog`, `media`, `marketing-pages`, `navigation`.
_Avoid:_ domain, module, vertical (use "feature" or "vertical feature").
**Must-have core**:
A core package the template can't run without — `core-shared`, `core-cms`, `core-api`.
_Avoid:_ baseline core, base core.
**Optional core**:
A core package scaffolded on demand via `pnpm turbo gen core-package <name>``core-realtime`, `core-events`, `core-trpc`, `core-ui`, `core-audit`. See `docs/architecture/template-tiers.md`.
**Core-composition**:
A tag for packages that compose feature exports — `core-api`, `core-cms`, `core-trpc`. The only packages allowed to import from `@repo/<feature>/api` or `@repo/<feature>/cms` subpaths.
**Tooling package**:
A package providing build/lint/test infrastructure — `core-eslint`, `core-typescript`, `core-testing`. May only depend on other tooling.
**App**:
A runtime entry point under `apps/``web-next`, `web-tanstack`, `cms`, `storybook`.
## Clean Architecture layers (per feature)
**Entities layer** (`packages/<feature>/src/entities/`):
Domain models (`models/<x>.ts`) and domain errors (`errors/<domain>.ts` + `errors/common.ts`). No I/O.
**Application layer** (`packages/<feature>/src/application/`):
**Use cases**. Pure orchestration over repository + service ports.
**Infrastructure layer** (`packages/<feature>/src/infrastructure/`):
**Repository** and **service** implementations (real Payload-backed + mock).
**Interface-adapters layer** (`packages/<feature>/src/interface-adapters/`):
**Controllers** — one per use case. Translate `unknown` input → use-case input via Zod `safeParse`; thread the output through a `presenter`.
**Integrations layer** (`packages/<feature>/src/integrations/`):
Vendor-specific glue — `integrations/api/` (tRPC routers), `integrations/cms/` (Payload collections + tasks).
**DI folder** (`packages/<feature>/src/di/`):
**Container**, **symbols**, and the two **binders**. The wiring layer.
## Feature building blocks
**Use case**:
A single business action expressed as a factory: `(deps) => async (input) => output`. Always paired with a Zod `xInputSchema` + (non-void) `xOutputSchema` co-located in the same file. Exports the type alias `I*UseCase = ReturnType<typeof xUseCase>`.
_Avoid:_ command, action, service method.
**Controller**:
The thin adapter from `unknown` input to a use case. One per use case. Co-located top-level `function presenter` for non-void outputs.
_Avoid:_ multi-method controller (forbidden — one verb-noun per file).
**Repository**:
A port for collection-style entity access. Lives in `infrastructure/<x>.repository.{ts,mock.ts,interface.ts}`. Real impls drop the `payload-` prefix; mocks use the `.mock.ts` suffix.
**Service**:
A port for non-collection capabilities (auth, mailer, etc.). Same `.ts` / `.mock.ts` / `.interface.ts` triad as repositories.
**Manifest** (`feature.manifest.ts`):
The per-feature contract declaring `useCases`, `audits`, `publishes`, `consumes`, and `requiredCores`. Source of truth for the conformance system. Always edited **before** code (manifest-first ordering).
**Symbol**:
A DI token in `packages/<feature>/src/di/symbols.ts`. Used by Inversify to identify a binding.
**Binder**:
A function that registers DI bindings — `bindProductionX(ctx)` (real Payload) or `bindDevSeedX(ctx)` (populated mock). Lives at `src/di/bind-production.ts` and `src/di/bind-dev-seed.ts`. Self-asserts conformance at its tail via `assertFeatureConformance(...)`.
**`bindAll()`**:
The app-level DI dispatcher (e.g. `apps/web-next/src/server/bind-production.ts`). Picks each feature's binder by env (`USE_DEV_SEED`, `NODE_ENV`) and threads a single shared `ctx` through them. Idempotent.
**`ctx`** (a.k.a. **bind context**):
The object passed to every binder. Required fields: `tracer`, `logger`, plus `config` for production. Optional fields: `bus`, `queue`, `realtime`, `realtimeRegistry` (only when the corresponding optional cores are scaffolded).
**Dev-seed**:
The populated in-memory mock mode. Lives in `src/__seeds__/dev.ts` per feature, exported as a lazy `buildDev<Entities>()` function. Selected by `USE_DEV_SEED=true` or by default when not in production.
**Public surface**:
A feature's allowed import surface — `.` (contracts: types, errors, schemas, `I*UseCase` aliases, router type), `./ui` (queries, components), `./cms`, `./api`, `./di/bind-production`, `./di/bind-dev-seed`. No deep source paths exist in `exports` maps.
**Anchor**:
A `// <gen:*>` comment marking where a generator injects code (e.g. `<gen:events>`, `<gen:job-symbols>`, `<gen:realtime-handlers>`). A CI guard at `packages/core-eslint/anchors.test.js` keeps them present.
## Conformance system
**Conformance**:
The 5-gate enforcement chain that keeps a feature's manifest and code in sync. Layers:
1. **TypeScript brands** (0s) — `Instrumented`, `Captured`, `Audited` on every wired use case / controller.
2. **ESLint conformance rules** (<1s) five custom rules in `core-eslint`.
3. **Boot assertion** (~3s) `assertFeatureConformance(...)` at the tail of every binder.
4. **CI drift gate** (`pnpm conformance`, ~120s) cross-feature event closure.
5. **Fallow** (`pnpm fallow`, ~3060s) whole-codebase dead exports / dupes / complexity / AI-change audit.
**Brand**:
A TypeScript phantom type attached to a wired use case / controller `Instrumented` (after `withSpan`), `Captured` (after `withCapture`), `Audited` (after `withAudit`). Enforces the wrapper composition at bind time.
**Manifest-first ordering**:
The non-negotiable authoring order for any new use case: **(1) manifest entry (2) contracts (`xInputSchema`, `xOutputSchema`, `IXUseCase`) (3) tests (red) (4) implementation (green)**. The generator scaffolds (1)+(2)+test stubs so new features are conformance-compliant by default.
**Fallow**:
The whole-codebase auditor (`pnpm fallow`) dead exports, unused files, duplicate code, circular deps, complexity hotspots, AI-change audit drift. The fifth conformance gate. Run `pnpm fallow:audit` before commits.
**Drift**:
Any disagreement between a feature's manifest and its code. The conformance gates are designed to catch drift at the earliest possible latency.
## Cross-feature mechanisms
**Event bus** (`IEventBus`):
The vendor-neutral cross-feature pub/sub interface in `@repo/core-events`. Two implementations: `InMemoryEventBus` (dev/test, synchronous) and `PayloadJobsEventBus` (production, durable via Payload tasks). Selected by `bindAll()`. See ADR-015.
_Use when:_ feature A's success must trigger feature B's reaction. **Don't use for in-feature flow control** that's a direct use-case call (rule E0).
**Event descriptor**:
A `defineEvent(...)` declaration with a `name` (wire format) + Zod payload schema. Lives at `packages/<feature>/src/events/<event>.event.ts`. Publishers re-export from the feature root; consumers do **not**.
**Event handler**:
A consumer's reaction to a published event. Lives at `packages/<feature>/src/events/handlers/on-<publisher>-<event>.handler.ts`. **Always private** never re-exported (rule E1, enforced by `no-handler-reexport`).
**Job queue** (`IJobQueue`):
The vendor-neutral deferred-work interface in `@repo/core-shared/jobs/`. Two implementations: `InMemoryJobQueue` (dev/test, `setImmediate`) and `PayloadJobQueue` (production). Feature packages enqueue via `IJobQueue` only direct `payload.jobs.queue()` is ESLint-blocked (rule J0).
**Realtime channel descriptor**:
A `defineRealtimeChannel(...)` declaration in `packages/<feature>/src/realtime/<channel>.channel.ts`. Re-exported from the feature root. Carries a Zod payload schema + a **scope**.
**Channel scope**:
A channel's subscription rule `public` | `authenticated` | `role:<name>` | `user-scoped`. See ADR-016.
**Broadcaster** (`IRealtimeBroadcaster`):
The server-side push interface in `@repo/core-realtime`. Use cases call `broadcaster.broadcast(channel, payload)` after the success path.
**Realtime handler**:
A consumer's reaction to an inbound client message on a channel. Lives at `packages/<feature>/src/realtime/handlers/*.handler.ts`. **Always private** never re-exported (rule R1, enforced by `no-realtime-handler-reexport`).
**Audit log**:
A DPA-compliant record of a use case's side effects. Emitted via `auditLog.record(...)`; declared in the manifest's `audits:` array. See ADR-018.
## Instrumentation
**Tracer** (`ITracer`):
The span interface in `@repo/core-shared/instrumentation/`. Three impls: `NoopTracer`, `OtelTracer`, `RecordingTracer` (test-only, from `core-testing`).
**Logger** (`ILogger`):
The capture interface. Same three-impl shape as `ITracer`. Used for exception reporting and structured logs.
**Metrics** (`IMetrics`):
The counter/gauge/histogram interface. Same three-impl shape.
**`withSpan`** / **`withCapture`** / **`withAudit`**:
The three wrapper composers applied at DI bind time. Composition: `withSpan(tracer, opts, withCapture(logger, tags, withAudit(auditLog, schema, factory(deps))))` `withSpan` outermost. Together they attach the `Instrumented` / `Captured` / `Audited` brands.
**Span**:
A traced unit of work. Emitted by `tracer.startSpan(...)` (inline in repos) or `withSpan(...)` (composed for use cases + controllers).
**Capture**:
The act of recording an exception once. Guarded by the non-enumerable `__sentryReported` flag so a bubbled error surfaces exactly once.
**PII scrub**:
The server-side scrubbing of email/passwords/tokens/cookies/auth/IPs at the OTel processor layer (`PiiScrubSpanProcessor` + `PiiScrubLogRecordProcessor`) before any exporter sees the data. `sendDefaultPii: false` everywhere, CI grep-enforced. See ADR-017 §7.
**Rule 0**:
The `bindAll()` decision that selects OTel+Sentry instrumentation when a DSN env var is present, otherwise the Noop chain. Orthogonal to `USE_DEV_SEED` / `NODE_ENV` (those control repo bindings, not instrumentation).
## Workflow
**PRD**:
The top-level requirements doc at `docs/work/prds/<date>-<slug>.prd.md`. Status flows `draft → in-review → approved → superseded`. `pnpm work decompose` refuses to run on `draft`.
_Avoid:_ spec (use "spec" only for `docs/superpowers/specs/` design docs).
**Epic**:
A large body of work, one folder under `docs/work/<epic-slug>/` with `_epic.md`. Decomposed from a PRD.
**Story**:
One use case or one technical capability, one folder under `<epic>/<story-slug>/` with `_story.md`. Type metadata: `user-story` or `technical-story`.
**Task**:
One vertical slice = one PR = one commit. File `<slug>.task.md` under the story folder.
**Slice** (a.k.a. **vertical slice**):
A change that exercises every Clean Architecture layer end-to-end for one capability manifest entry + contracts + tests + impl + DI wiring + integration. The unit of a task.
**Sandcastle**:
The agent dispatch orchestrator (https://github.com/mattpocock/sandcastle). Invoked via `pnpm work dispatch --execute`. See ADR-019.
**`_state.json`**:
The orchestrator-managed derived index at `docs/work/_state.json`. Regenerated from markdown via `pnpm work rebuild-state`. Committed.
**Generator**:
A `pnpm turbo gen <kind>` invocation. Generator-first is **non-negotiable** agents always prefer the generator over hand-rolled scaffolding. Available kinds: `feature`, `event`, `job`, `realtime`, `core-package`, `core-ui-component`.
**Slice = task = PR = commit**:
The shipping rhythm. One vertical slice closes one task, becomes one PR, lands as one commit.
## Modes
**Production mode**:
`NODE_ENV=production` (and `USE_DEV_SEED` unset) `bindAll()` wires Payload-backed repositories + `PayloadJobsEventBus` + `PayloadJobQueue`.
**Dev-seed mode**:
`USE_DEV_SEED=true` (or default fallback when not in production) `bindAll()` wires populated mocks + `InMemoryEventBus` + `InMemoryJobQueue`. Developer default so `pnpm dev` boots without Payload running.
## Relationships
- A **PRD** decomposes into one or more **Epics**.
- An **Epic** contains one or more **Stories**.
- A **Story** is implemented by one or more **Tasks**, each a **Slice**.
- A **Use case** is declared in a **Manifest** before it has code (manifest-first ordering).
- A **Use case** has exactly one **Controller**.
- A **Controller** has at most one **`presenter`** (omitted for void outputs).
- A **Feature** owns its **Repositories**, **Services**, **Use cases**, **Controllers**, **Events**, **Jobs**, **Channels**, and **DI Container**.
- **Cross-feature reactions** travel through the **Event bus**; **in-feature reactions** are direct use-case calls.
- An **Event descriptor** is public; its **Event handler** is always private.
- A **Channel descriptor** is public; its **Realtime handler** is always private.
- **Brands** are attached only at **DI bind time**, by **`withSpan` / `withCapture` / `withAudit`**.
- **Conformance** asserts the **Manifest** and code agree, at five latency tiers.
## Flagged ambiguities
- **"feature"** always a vertical feature package; never a CMS-collection field or a generic capability.
- **"service"** a DI-injected port (e.g. `IAuthenticationService`); not a Kubernetes service, Payload collection, or generic "service object".
- **"handler"** qualify by context: **event handler** (cross-feature) | **realtime handler** (inbound socket message) | **task handler** (Payload job).
- **"schema"** qualify: **Zod schema** (input/output contracts) | **Payload collection schema** (CMS field definitions).
- **"config"** qualify: **Payload config** | **Next config** | **Vitest config** | **TS config**.
- **"bind"** DI binding (`bind<I>(SYMBOL).toDynamicValue(...)`); not a `Function.prototype.bind`.
- **"spec"** `docs/superpowers/specs/` design doc; never a PRD or a Jest spec file.
- **"controller"** one verb-noun pair per file; never a multi-method MVC controller.
- **"module"** avoid for packages (use "package"); reserve for Node ESM/CJS module semantics if needed.
## Cross-references
- Architecture: `docs/architecture/overview.md`, `docs/architecture/vertical-feature-spec.md`, `docs/architecture/agent-first-workflow-and-conformance.md`
- ADRs: `docs/decisions/adr-NNN-<slug>.md`
- Workflow: `docs/work/README.md`, `AGENTS.md` § "Agent-driven development"
- Guides: `docs/guides/runbook.md`, `docs/guides/conformance-quickref.md`, `docs/guides/tdd-workflow.md`