Files
agentic-dev/docs/superpowers/refactor-logs/2026-05-05-lazar-pattern-conformance.md
Danijel Martinek aa325f91cc refactor(features): rename mock/payload/interface files per Lazar pattern
Convention now: <name>.repository.{ts,mock.ts,interface.ts}.
Renames .mock prefix to .mock suffix; drops .payload prefix from real
impls (canonical name = real impl); dot-separates the .repository
qualifier in interface filenames. Class names follow suit:
PayloadXRepository → XRepository; Mock* unchanged.

Refactor log: §1, §3
Spec: §9.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 23:50:01 +02:00

13 KiB

Refactor Changelog — Lazar Pattern Conformance

Started: 2026-05-05 Spec: 2026-05-05-lazar-pattern-conformance-design.md Plan: 2026-05-05-plan-8-lazar-conformance.md Branch: feature/lazar-conformance

This document captures every architectural change made during Plan 8 execution, organized by category. After the plan is merged, use the "Doc update checklist" at the bottom to update external docs in a single follow-up pass.


Summary

(Filled in at Task 10 — total files added/modified/deleted/renamed; net test count change; commits.)


1. File renames (before → after)

Task 3: File and class renames

File renames — 27 files (git mv — history preserved):

auth:

  • packages/auth/src/infrastructure/repositories/mock-users.repository.tsusers.repository.mock.ts
  • packages/auth/src/infrastructure/repositories/mock-users.repository.test.tsusers.repository.mock.test.ts
  • packages/auth/src/application/repositories/users-repository.interface.tsusers.repository.interface.ts
  • packages/auth/src/infrastructure/services/mock-authentication.service.tsauthentication.service.mock.ts
  • packages/auth/src/application/services/authentication-service.interface.tsauthentication.service.interface.ts

blog:

  • packages/blog/src/infrastructure/repositories/mock-articles.repository.tsarticles.repository.mock.ts
  • packages/blog/src/infrastructure/repositories/mock-articles.repository.test.tsarticles.repository.mock.test.ts
  • packages/blog/src/infrastructure/repositories/payload-articles.repository.tsarticles.repository.ts
  • packages/blog/src/infrastructure/repositories/payload-articles.repository.test.tsarticles.repository.test.ts
  • packages/blog/src/application/repositories/articles-repository.interface.tsarticles.repository.interface.ts

marketing-pages:

  • packages/marketing-pages/src/infrastructure/repositories/mock-pages.repository.tspages.repository.mock.ts
  • packages/marketing-pages/src/infrastructure/repositories/mock-pages.repository.test.tspages.repository.mock.test.ts
  • packages/marketing-pages/src/infrastructure/repositories/payload-pages.repository.tspages.repository.ts
  • packages/marketing-pages/src/infrastructure/repositories/payload-pages.repository.test.tspages.repository.test.ts
  • packages/marketing-pages/src/application/repositories/pages-repository.interface.tspages.repository.interface.ts
  • packages/marketing-pages/src/infrastructure/repositories/mock-site-settings.repository.tssite-settings.repository.mock.ts
  • packages/marketing-pages/src/infrastructure/repositories/mock-site-settings.repository.test.tssite-settings.repository.mock.test.ts
  • packages/marketing-pages/src/infrastructure/repositories/payload-site-settings.repository.tssite-settings.repository.ts
  • packages/marketing-pages/src/infrastructure/repositories/payload-site-settings.repository.test.tssite-settings.repository.test.ts
  • packages/marketing-pages/src/application/repositories/site-settings-repository.interface.tssite-settings.repository.interface.ts

navigation:

  • packages/navigation/src/infrastructure/repositories/mock-header.repository.tsheader.repository.mock.ts
  • packages/navigation/src/infrastructure/repositories/mock-header.repository.test.tsheader.repository.mock.test.ts
  • packages/navigation/src/infrastructure/repositories/payload-header.repository.tsheader.repository.ts
  • packages/navigation/src/infrastructure/repositories/payload-header.repository.test.tsheader.repository.test.ts
  • packages/navigation/src/application/repositories/header-repository.interface.tsheader.repository.interface.ts

Class renames (4 classes — Payload prefix dropped; Mock prefix unchanged):

  • PayloadArticlesRepositoryArticlesRepository (in articles.repository.ts)
  • PayloadPagesRepositoryPagesRepository (in pages.repository.ts)
  • PayloadSiteSettingsRepositorySiteSettingsRepository (in site-settings.repository.ts)
  • PayloadHeaderRepositoryHeaderRepository (in header.repository.ts)

Consumers updated (imports + class references): DI modules, bind-production files, contract suites, use case source files, use case tests, controller tests, router tests, feature tests — approximately 35 files total.

Task 2: Entities split

Entity model moves (git mv — history preserved):

  • packages/auth/src/entities/user.tspackages/auth/src/entities/models/user.ts
  • packages/auth/src/entities/user.test.tspackages/auth/src/entities/models/user.test.ts
  • packages/auth/src/entities/session.tspackages/auth/src/entities/models/session.ts
  • packages/auth/src/entities/session.test.tspackages/auth/src/entities/models/session.test.ts
  • packages/auth/src/entities/cookie.tspackages/auth/src/entities/models/cookie.ts
  • packages/auth/src/entities/errors.test.tspackages/auth/src/entities/errors/errors.test.ts
  • packages/blog/src/entities/article.tspackages/blog/src/entities/models/article.ts
  • packages/blog/src/entities/article.test.tspackages/blog/src/entities/models/article.test.ts
  • packages/blog/src/entities/errors.test.tspackages/blog/src/entities/errors/errors.test.ts
  • packages/marketing-pages/src/entities/page.tspackages/marketing-pages/src/entities/models/page.ts
  • packages/marketing-pages/src/entities/page.test.tspackages/marketing-pages/src/entities/models/page.test.ts
  • packages/marketing-pages/src/entities/site-settings.tspackages/marketing-pages/src/entities/models/site-settings.ts
  • packages/marketing-pages/src/entities/site-settings.test.tspackages/marketing-pages/src/entities/models/site-settings.test.ts
  • packages/marketing-pages/src/entities/errors.test.tspackages/marketing-pages/src/entities/errors/errors.test.ts
  • packages/navigation/src/entities/header.tspackages/navigation/src/entities/models/header.ts
  • packages/navigation/src/entities/header.test.tspackages/navigation/src/entities/models/header.test.ts

2. Files added (with purpose)

Task 2: Entities split — new error files

  • packages/auth/src/entities/errors/auth.ts — AuthenticationError, UnauthenticatedError, UnauthorizedError (split from errors.ts)
  • packages/auth/src/entities/errors/common.ts — InputParseError (auth copy)
  • packages/blog/src/entities/errors/article.ts — ArticleNotFoundError (split from errors.ts)
  • packages/blog/src/entities/errors/common.ts — InputParseError (blog copy)
  • packages/marketing-pages/src/entities/errors/page.ts — PageNotFoundError (split from errors.ts)
  • packages/marketing-pages/src/entities/errors/common.ts — InputParseError (marketing-pages copy)
  • packages/navigation/src/entities/errors/header.ts — HeaderNotFoundError (new; navigation had no errors.ts)
  • packages/navigation/src/entities/errors/common.ts — InputParseError (navigation copy)

3. Files deleted (with reason)

Task 2: Entities split — old errors.ts files removed

  • packages/auth/src/entities/errors.ts — replaced by errors/auth.ts + errors/common.ts
  • packages/blog/src/entities/errors.ts — replaced by errors/article.ts + errors/common.ts
  • packages/marketing-pages/src/entities/errors.ts — replaced by errors/page.ts + errors/common.ts
  • (navigation had no errors.ts to delete)

4. Pattern changes (code-level)

4.1 Use cases — factory function pattern

(populated when a use case is migrated)

4.2 Controllers — one per use case

(populated when controllers are split)

4.3 Entities split — models/ + errors/ subdirs

Pattern now in place across auth, blog, marketing-pages, navigation (media skipped — no entities yet):

  • Entity Zod schemas + types live at entities/models/<x>.ts
  • Domain errors live at entities/errors/<domain>.ts (e.g. errors/auth.ts, errors/article.ts)
  • Shared InputParseError lives at entities/errors/common.ts (one copy per feature — ~6 lines each)
  • Colocated entity test files moved alongside their respective sources (models/*.test.ts, errors/errors.test.ts)
  • All imports across factories, contracts, repositories, use cases, controllers, tests, and src/index.ts updated to new paths
  • navigation divergence: no errors.ts existed pre-refactor; errors/header.ts (HeaderNotFoundError) and errors/common.ts added as new forward-looking stubs

5. DI changes

5.1 Inversify .toDynamicValue bindings

(populated when DI modules are updated)

5.2 Mock siblings registered as default bindings

(populated when modules are updated)

6. Test refactor patterns

6.1 Direct injection (no container rebinding)

(populated when tests are migrated)

7. Open issues / deferred decisions

(populated as encountered)


Doc update checklist (deferred — run after merge)

After Plan 8 is merged to main, work through this list in a single batched doc-update pass. Each item points at an external doc that references the pre-Plan-8 layout or pattern and needs to be brought in line.

  • CLAUDE.md — Key Conventions section: update file path examples to use entities/models/<x>.ts; mention factory-function use cases; show I*UseCase type aliases
  • AGENTS.md (root) — Per-Package Conventions: update naming examples (<x>.repository.{ts,mock.ts,interface.ts}); add note about I*UseCase / I*Controller type aliases; document factory-style DI
  • docs/guides/adding-a-feature.md — restructure to use factory-function pattern in every step; update file paths to new layout; show .toDynamicValue() bindings
  • docs/guides/tdd-workflow.md — update "When to mock" decision tree to show direct factory injection (signInUseCase(mocks)(input)) instead of container rebinding; update factory usage examples to reference entities/models/* paths
  • docs/guides/testing-strategy.md — Mocking section: remove DI-rebinding pattern as the default; show direct factory injection
  • docs/architecture/vertical-feature-spec.md — update §10 (file shape examples) to new template; update §13 (testing) to reflect factory pattern + direct injection
  • docs/architecture/overview.md — layer descriptions: mention factory-function use cases; add note that controllers are one-per-use-case
  • docs/architecture/dependency-flow.md — verify dep flow still accurate with new DI bindings; update examples if any reference old paths
  • docs/decisions/adr-012-lazar-conformance.md — NEW ADR documenting the conformance decision and the four intentional divergences (per-feature DI, inversify retained, colocated tests, no Sentry/instrumentation services)
  • Per-feature AGENTS.md (auth/blog/media/marketing-pages/navigation) — update file path references; document factory pattern; update Tests section
  • packages/core-testing/AGENTS.md — update factory examples to reference entities/models/<x>.ts paths
  • packages/auth/AGENTS.md — document the new real UsersRepository and AuthenticationService (Payload-backed)
  • packages/media/AGENTS.md — full rewrite — media now has all Clean Architecture layers (entities, application, infrastructure, interface-adapters, DI, integrations/api)
  • Plan 7 plan/spec docs — add a one-line note at the top noting that paths reference the pre-Plan-8 layout; link to refactor changelog

Notes for the doc-update pass author

When updating external docs, apply these substitutions globally:

Old reference New reference
entities/<x>.ts entities/models/<x>.ts
entities/errors.ts entities/errors/<domain>.ts (or entities/errors/common.ts)
mock-<x>.repository.ts <x>.repository.mock.ts
payload-<x>.repository.ts <x>.repository.ts (real impl is now the canonical name)
<x>-repository.interface.ts <x>.repository.interface.ts
class PayloadXRepository class XRepository
Use case calls container.get(...) inside its body Use case is a factory function: (deps) => async (input) => result
Controller bundles multiple methods (articles.controller.ts) One controller per use case (get-articles.controller.ts, create-article.controller.ts)
Test does container.unbind(...).bind(...) in beforeEach Test constructs mocks and injects: const useCase = signInUseCase(mockUsers, mockAuth);
DI binds use case with .to(...) DI binds use case with .toDynamicValue((ctx) => factoryFn(ctx.container.get(...)))
Use case + controller imports inject via container Imports take dependencies as constructor/factory args

Add I*UseCase and I*Controller type alias examples wherever use cases / controllers are explained.