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).
This commit is contained in:
@@ -86,13 +86,14 @@ The symbol map declares which container symbol each manifest use-case key resolv
|
||||
|
||||
## ESLint rules
|
||||
|
||||
| Rule | Severity | What it does |
|
||||
| ----------------------------------------- | -------- | -------------------------------------------------------------------------------------- |
|
||||
| `conformance/feature-must-have-manifest` | error | Use-case files require a sibling manifest |
|
||||
| `conformance/usecase-must-have-test-file` | error | Every `*.use-case.ts` has a sibling `*.use-case.test.ts` |
|
||||
| `conformance/required-cores-installed` | error | Manifest's `requiredCores` must exist as `core-<name>` packages in pnpm-workspace.yaml |
|
||||
| `conformance/no-undeclared-event-publish` | warn | `bus.publish("X")` literal must match the manifest's `publishes` for the use case |
|
||||
| `conformance/no-undeclared-audit` | warn | `auditLog.record({ type: "X" })` literal must match the manifest's `audits` |
|
||||
| Rule | Severity | What it does |
|
||||
| ----------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| `conformance/feature-must-have-manifest` | error | Use-case files require a sibling manifest |
|
||||
| `conformance/usecase-must-have-test-file` | error | Every `*.use-case.ts` has a sibling `*.use-case.test.ts` |
|
||||
| `conformance/required-cores-installed` | error | Manifest's `requiredCores` must exist as `core-<name>` packages in pnpm-workspace.yaml |
|
||||
| `conformance/no-undeclared-event-publish` | warn | `bus.publish("X")` literal must match the manifest's `publishes` for the use case |
|
||||
| `conformance/no-undeclared-audit` | warn | `auditLog.record({ type: "X" })` literal must match the manifest's `audits` |
|
||||
| `conformance/usecase-must-be-wired` | error | Every manifest use case must be bound via `wireUseCase({ name: "<key>" })` in `bind-production.ts` / `bind-dev-seed.ts` |
|
||||
|
||||
## Workflow ordering for new use cases
|
||||
|
||||
@@ -105,7 +106,8 @@ For the fast path: `pnpm turbo gen feature <name>` scaffolds steps 1 + 2 in a si
|
||||
|
||||
## Common drift patterns and the gate that catches them
|
||||
|
||||
- **Forgot `withSpan` at bind time** → tsc TS2322 + boot assertion
|
||||
- **Forgot `withSpan` at bind time** → tsc TS2322 + `usecase-must-be-wired` ESLint error + boot assertion + bind-production smoke test
|
||||
- **Manifest entry has no `wireUseCase` call in either binder** → `usecase-must-be-wired` ESLint error + boot assertion + bind-production smoke test
|
||||
- **Manifest declares `audits: ["X"]` but factory doesn't call `auditLog.record({type:"X"})`** → no automatic catch yet; future story
|
||||
- **Factory calls `bus.publish("Y")` but manifest doesn't declare it** → `conformance/no-undeclared-event-publish` (warn)
|
||||
- **Feature has use cases but no manifest** → `conformance/feature-must-have-manifest` (error)
|
||||
|
||||
Reference in New Issue
Block a user