Files
agentic-dev-template/docs/glossary.md
Danijel Martinek 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

27 KiB
Raw Blame History

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. In architecture-refactor conversations (the improve-codebase-architecture skill), "module" defaults to "feature" — they're the same unit at the highest level of granularity. Avoid: domain, vertical (use "feature" or "vertical feature"). "Module" is acceptable inside the refactor skill specifically, where it abstractly covers "anything with interface + implementation" at any scale (use case, controller, repository port, or full 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.

Architecture refactor vocabulary

Terms used by the improve-codebase-architecture skill (.claude/skills/improve-codebase-architecture/) when proposing refactors. Distinct from the everyday domain terms above — these are abstractions for reasoning about shape. Both vocabularies are in scope during refactor conversations.

Module (refactor sense, = feature by default): The abstract unit a refactor operates on: anything with an interface + implementation. In this repo, "module" almost always means "feature" (packages/<name>/) since that's our primary unit of organization. At narrower scales it also covers a use case, controller, repository/service port, or binder. Don't introduce "module" as a competing top-level term in domain conversations — the refactor skill is the only place this abstraction is appropriate. Avoid: using "module" outside the refactor skill (say "feature", "use case", "controller", "package" as appropriate).

Interface (refactor sense): Everything a caller must know to use a module — type signatures, invariants, ordering, error modes, Zod schemas, manifest declarations, DI symbol contract. Strictly broader than the TS interface keyword.

Implementation: What's inside a module. Distinct from adapter: an adapter is a role (fills a slot at a seam); an implementation is the substance (the code itself).

Depth: Leverage at the interface — behaviour per unit of interface a caller must learn. A deep module packs a lot of behaviour behind a small interface; a shallow module has an interface nearly as complex as its body. Pure factory-function use cases are usually deep; one-line wrappers and (x) => x presenters are usually shallow.

Seam (from Michael Feathers): A place where behaviour can be altered without editing in place — the location of a module's interface. Concrete seams in this repo: *.interface.ts files, DI symbols (*_SYMBOLS.IX*), feature.manifest.ts entries, // <gen:*> anchors, the protocol types in core-shared/di/bind-protocols.ts. Avoid: "boundary" — that term is reserved in this repo for ESLint workspace-tag rules (feature may depend on core + tooling only).

Adapter: A concrete thing satisfying an interface at a seam. In this repo a typical port has two or three adapters: real (<x>.repository.ts), mock (<x>.repository.mock.ts), and sometimes recording (Recording* test doubles in core-testing).

Leverage: What callers get from depth — more capability per unit of interface they must learn.

Locality: What maintainers get from depth — change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers.

Deletion test: Imagine deleting a module: if complexity vanishes, it was a pass-through; if complexity reappears across N callers, it was earning its keep. The signal for "this module is shallow" is when deletion just moves the complexity rather than reducing it.

Deepening: A refactor that turns shallow modules into deeper ones — merging pass-throughs into the modules that justified them, exposing a smaller interface, or relocating the seam to a more useful place. Subject to the hard constraints in the skill's SKILL.md (no ADR violations, no boundary breaks, no manifest drift).

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.

Coverage

Coverage band: The per-path threshold declared in feature.manifest.ts under coverage.bands — one entry per Clean Architecture layer (entities, use-cases, controllers) plus a baseline for everything else. Single source of truth read by vitest, assertFeatureConformance, and pnpm coverage:diff. See ADR-020.

L0 / L1 / L2 / L3: The four coverage layers (ADR-020). L0 = vitest per-layer thresholds (test-time). L1 = pnpm coverage:diff cover-the-diff gate (post-test, CI + dispatch loop). L2 = pnpm coverage:aggregate → committed coverage/summary.json (observability). L3 = pnpm mutate Stryker mutation testing on entities + use-cases (on-demand, not default).

Diff coverage: The gate that asserts every changed executable line has execution count > 0 in the merged lcov. Cover-the-diff (modified + new lines both count), not cover-the-new-code. Run via pnpm coverage:diff [<base-ref>]. Avoid: patch coverage, delta coverage (use "diff coverage" canonically).

Mutation testing: A test-quality signal that mutates source code and re-runs tests; surviving mutants mean the test exists + executes the code but doesn't actually assert behavior. Scoped to entities/ + application/use-cases/ per feature. Run via pnpm mutate [--filter @repo/<feature>].

Mutation score: The percentage of mutants killed (i.e., caught by tests) out of all mutants generated. Per-feature threshold defaults to 80% (overridable in feature.manifest.ts via coverage.mutationThreshold).

coverage/summary.json: The aggregated per-package + repo-level coverage snapshot, committed on merge to main. Grep-able from git history via git log -- coverage/summary.json. Includes timestamp + commit SHA for correlation with deploys.

Releasing

Conventional Commits: The commit-message spec mandated by this template — <type>(<scope>): <imperative subject>. Types: feat | fix | docs | style | refactor | test | chore | perf | ci | build | revert. ! for breaking changes. See CLAUDE.md Key Conventions.

release-please: The Google-maintained automation that reads Conventional Commits, derives semver bumps, and opens a rolling release PR with version bumps + per-package CHANGELOG entries on every push to main. Configured in release-please-config.json + .release-please-manifest.json. ADR-021.

Hybrid versioning: The template's versioning strategy (ADR-021) — root template (template-vertical) + 5 feature packages (@repo/{auth,blog,media,marketing-pages,navigation}) version independently from 0.1.0. Core packages, tooling, and apps are NOT versioned (cascade-effect would invalidate the signal).

Tag prefix: The per-package prefix release-please uses to avoid tag collisions in a monorepo — template-v0.1.0 for the root, auth-v0.1.0 / blog-v0.1.0 / etc. for features.

Rolling release PR: The single PR release-please keeps open on main and updates idempotently on every push. Contains all pending version bumps + changelog entries since the last release. Merging it cuts the tags + GitHub releases.

Bump targeting (by commit-path): How release-please decides which tracked package(s) a commit bumps — by the files changed, not the conventional-commit (scope). A commit touching packages/auth/** bumps @repo/auth; a commit touching docs/** or scripts/** bumps the root template; a commit touching both bumps both.

Pre-1.0 bump policy: While each tracked package is <1.0.0: feat: bumps patch, feat!: bumps minor (NOT major). Configured via bump-patch-for-minor-pre-major: true. Once a package crosses 1.0.0, standard semver kicks in.

Release-As: trailer: A commit-body trailer (Release-As: 0.5.0) that overrides release-please's auto-derived bump for the package(s) whose paths the commit touches. Used for manual semver corrections or explicitly crossing 1.0.0.

CHANGELOG.md: A per-package, release-please-managed changelog (one at repo root for the template; one at packages/<feature>/CHANGELOG.md for each feature). Do not edit manually — release-please regenerates from commit history.

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 → shipped (pnpm work prd-ship auto-flips on epic completion). pnpm work decompose refuses to run on draft. Avoid: spec (in this template the ADR is the durable design record; PRDs are the implementation seed).

Epic: A large body of work, one folder under docs/work/epics/<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/_system/_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.

Library trace: A per-decision artifact at docs/library-decisions/<YYYY-MM-DD>-<package-name>.md recording the outcome of the evaluate-library skill against a candidate third-party dependency. Frontmatter is the machine surface (tier, decision, filter-results enum); headings are the human surface (one per filter + one per prompt). Both decision: approved and decision: rejected traces are first-class — the rejection record is the value, since it stops future agents from re-evaluating the same library. Required for any new runtime dep in a feature- or core-tagged package; the pre-commit hook blocks the commit if the trace is missing.

Pre-shipped trace: A library trace emitted by pnpm turbo gen core-package <name> for each direct runtime dep of a pre-curated optional core. Pre-approved by the template's ADRs (015 events / 016 realtime / 018 audit). Generated alongside the core's frozen snapshot so optional cores satisfy the library-evaluation policy by default.

Trace revalidation: The weekly + on-demand CI job (.github/workflows/trace-revalidation-weekly.yml) that re-runs every approved trace's verification-commands block and detects drift in license / maintenance / CVE / EU-residency / Socket-risk signals that don't show up as version bumps. Two-tier divergence action: soft divergence appends to a rolling dashboard issue; hard divergence (license changed, named-consumer gone, critical CVE disclosed, EU residency flipped, Socket-flagged) opens a per-dep issue labeled library-policy/re-evaluation for the dispatch loop to pick up. Never auto-edits the trace — the re-walk needs the evaluate-library skill, not a mechanical edit. Records the most-recent successful pass in the trace's last-revalidated frontmatter field (separate from the original adoption date).

Major-bump re-evaluation: The Renovate-triggered re-walk of evaluate-library when a runtime dep's major version bumps (semver-major, distinct from minor/patch). Updates the existing trace in-place (refreshes version, filter-results, verification-commands, last-revalidated), preserves the original date. Catches license / maintenance / transitive-surface changes that semver-encodes as "breaking." Minor + patch bumps do not trigger re-evaluation.

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.
  • A Coverage band in the Manifest is read by Vitest (L0), assertFeatureConformance (boot), and pnpm coverage:diff (L1) — one decision, three enforcers.
  • Mutation testing is the third dimension of test quality, after "test file exists" (ESLint structural) and "test executes the code" (L0/L1 coverage).

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" — avoid in this template. Durable design records are ADRs (docs/decisions/adr-NNN-*.md); implementation seeds are PRDs (docs/work/prds/*.prd.md). Never use "spec" to refer to a Jest spec file either.
  • "controller" — one verb-noun pair per file; never a multi-method MVC controller.
  • "module" — qualify by context: package (workspace member under packages/ or apps/) | Node ESM/CJS module (file-level import semantics) | refactor-vocabulary "module" (in the improve-codebase-architecture skill, defaults to feature — i.e., a packages/<name>/; can also mean a narrower unit like a use case or controller when the refactor scope is that narrow). Default: prefer "feature" for the common case; "package" for the workspace-member shell; "module" only inside refactor conversations.
  • "seam" — refactor-vocabulary only (where a module's interface lives). Not a synonym for boundary (ESLint workspace-tag rule) or scope (Conventional Commits parenthetical).
  • "adapter" — refactor-vocabulary only (a concrete thing satisfying an interface at a seam). Not a synonym for port (the interface itself) or service (a DI-injected port for non-collection capabilities).
  • "coverage" — qualify when ambiguous: L0 coverage (per-layer thresholds, test-time) | diff coverage / L1 (cover-the-diff gate) | aggregate coverage / L2 (committed summary.json) | mutation coverage / L3 (Stryker mutation score, not line coverage).

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