Files
agentic-dev/packages/navigation/AGENTS.md
Danijel Martinek edc98f8f9a docs(agents): per-feature + core-testing AGENTS.md for Plan 8 + Plan 9 conventions
Each per-feature AGENTS.md now reflects the post-Plan-9 layout:
entity/error paths, public-API split (./ui), use-case schemas, presenter
pattern, feature-scoped tRPC error map, and feature-specific
errors-to-codes table.

core-testing/AGENTS.md gains a Plan 9 test-patterns section documenting
R25 (output validation), R26 (router error mapping), R27/R28
(presenter shape) test obligations.

auth: documents real PayloadUsersRepository + AuthenticationService and
the deferred session methods.
media: documents the full Clean Architecture scaffold introduced in
Plan 8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:47:56 +02:00

5.6 KiB

AGENTS.md — navigation

Header global for main site navigation. Provides the Header Payload global and tRPC procedures for dynamic navigation content.

Overview

@repo/navigation owns: Header and HeaderItem domain models, navigation-scoped errors, the IHeaderRepository interface, one use case, one controller, a real Payload-backed repository, and the tRPC navigationRouter. The headerQuery React Query builder lives in ./ui.

Layer responsibilities

Layer Key files
entities/models header.tsHeader, HeaderItem Zod schemas + types
entities/errors header.ts (HeaderNotFoundError), common.ts (InputParseError)
application/use-cases get-header.use-case.ts — factory function + exported schemas
application/repositories header.repository.interface.tsIHeaderRepository
infrastructure/repositories header.repository.ts (real Payload-backed), header.repository.mock.ts (in-memory)
interface-adapters/controllers get-header.controller.ts — one file per use case
di symbols.ts (NAVIGATION_SYMBOLS), module.ts, container.ts, bind-production.ts
integrations/api procedures.ts (navigationProcedure), router.ts (navigationRouter)
integrations/cms globals/header.ts — Payload Header GlobalConfig
ui src/ui/index.ts — re-exports headerQuery

Public exports

Subpath Contents
. Header, HeaderItem types; HeaderNotFoundError, InputParseError; getHeaderInputSchema, getHeaderOutputSchema, GetHeaderInput, GetHeaderOutput, IGetHeaderUseCase; IGetHeaderController type alias; NavigationRouter type
./ui headerQuery — React Query option builder
./api navigationRouter (tRPC router)
./cms Payload Header global definition
./di/bind-production bindProductionNavigation(container, config)

Use-case + controller patterns

See CLAUDE.md Key Conventions and docs/architecture/overview.md for the canonical factory templates.

Use case

Use case Input schema Output schema Notes
getHeaderUseCase getHeaderInputSchemaz.object({}).strict() (void input) getHeaderOutputSchema= headerSchema Takes _input: GetHeaderInput; throws HeaderNotFoundError when repository returns falsy; ends with getHeaderOutputSchema.parse(header)

Controller

getHeaderController uses an identity presenter — function presenter(value: GetHeaderOutput) { return value; } — and returns Promise<ReturnType<typeof presenter>>. Accepts unknown input and safeParse with getHeaderInputSchema, throwing InputParseError on failure.

Errors → tRPC codes

Error class tRPC code Thrown by
InputParseError BAD_REQUEST controller (safeParse failure; also triggers on strict() rejecting unknown keys)
HeaderNotFoundError NOT_FOUND getHeaderUseCase when repository returns falsy

Defined in src/integrations/api/procedures.ts via navigationProcedure = t.procedure.use(defineErrorMiddleware([...])).

Tests

  • Factories: src/__factories__/header.factory.ts, src/__factories__/nav-item.factory.ts
  • Contract suite: src/__contracts__/header-repository.contract.ts — runs against mock and real HeaderRepository
  • Unit tests: colocated *.test.ts next to each source file
  • R25 (output validation): get-header.use-case.test.ts has a test using an inline malformed repository mock (e.g., { items: [{ label: "", href: "/", external: false }] }, label failing min(1)) to assert .rejects.toBeInstanceOf(ZodError).
  • R26 (router error mapping): router.test.ts asserts BAD_REQUEST when input has extra unknown keys (strict mode rejection → InputParseError), and NOT_FOUND via an inline NullHeaderRepository rebind causing HeaderNotFoundError.
pnpm test --filter @repo/navigation
pnpm test --filter @repo/navigation -- --watch

See docs/guides/tdd-workflow.md for the full cycle.

Directory structure

src/
  entities/
    models/
      header.ts        # Header, HeaderItem schemas + types
    errors/
      header.ts        # HeaderNotFoundError
      common.ts        # InputParseError
  application/
    repositories/
      header.repository.interface.ts
    use-cases/
      get-header.use-case.ts
  infrastructure/
    repositories/
      header.repository.ts          # real Payload-backed
      header.repository.mock.ts
  interface-adapters/
    controllers/
      get-header.controller.ts
  integrations/
    api/
      procedures.ts    # navigationProcedure
      router.ts        # navigationRouter
    cms/
      globals/
        header.ts
      index.ts
  di/
    symbols.ts
    module.ts
    container.ts
    bind-production.ts
  ui/
    index.ts           # headerQuery
    query.ts
  index.ts
  __factories__/
    header.factory.ts
    nav-item.factory.ts
  __contracts__/
    header-repository.contract.ts

What it must NOT import

  • Any other feature package (@repo/auth, @repo/blog, etc.)
  • Any app package
  • @repo/core-api, @repo/core-cms, @repo/core-trpc, @repo/core-ui directly; only @repo/core-shared
  • ADR-012 (docs/decisions/adr-012-lazar-conformance.md) — factory-style use cases, per-use-case controllers, file-naming conventions
  • ADR-013 (docs/decisions/adr-013-input-output-unification.md) — schemas-in-use-case, presenter, ./ui subpath, error middleware
  • Refactor logs: docs/superpowers/refactor-logs/2026-05-05-lazar-pattern-conformance.md (Plan 8), docs/superpowers/refactor-logs/2026-05-06-input-output-unification.md (Plan 9)