Commit Graph

469 Commits

Author SHA1 Message Date
6d4522438d feat(core-shared): SentryLogger with double-report guard + R36 user-context strip 2026-05-06 23:45:45 +02:00
a324da09c5 feat(core-shared): SentryTracer adapter 2026-05-06 23:45:05 +02:00
e133b92fe6 feat(core-shared): symbols + barrel for instrumentation subpath 2026-05-06 23:42:26 +02:00
0ffda8078f feat(core-shared): add withSpan higher-order helper 2026-05-06 23:41:54 +02:00
fdd4e9141b feat(core-shared): add ILogger interface + NoopLogger 2026-05-06 23:41:27 +02:00
f1051ded9b feat(core-shared): add NoopTracer 2026-05-06 23:41:01 +02:00
fcd10e8774 feat(core-shared): add ITracer/ISpan interfaces 2026-05-06 23:40:35 +02:00
10479c4d55 feat(features): add bind-dev-seed binders for auth/marketing-pages/navigation/media
Mirrors the canonical blog pattern landed earlier on this branch.

Per feature:
- src/__seeds__/dev.ts — lazy buildDev<Entities>() function using the
  feature's existing factory for sensible defaults
- src/di/bind-dev-seed.ts — bindDevSeed<Feature>() async function that
  rebinds the repo symbol(s) to a populated MockXRepository via
  .toConstantValue
- src/di/bind-dev-seed.test.ts — 3+ tests per feature (populates,
  reachable by id/slug, idempotent)
- package.json — adds ./di/bind-dev-seed subpath export

Tests + use cases continue to construct mocks directly; the seed never
runs from a *.test.ts path. App boot wiring (USE_DEV_SEED env branch)
follows in a separate commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 19:04:33 +02:00
e6560bc9cb feat(blog): add bind-dev-seed binder + dev seed
Sets the canonical pattern for all 5 features. Three new files:

- src/__seeds__/dev.ts — buildDevArticles() function returning 3
  realistic articles (welcome, vertical-feature-architecture,
  wip-post) built from articleFactory with id/slug/title/status
  overrides only.
- src/di/bind-dev-seed.ts — bindDevSeedBlog() async function that
  unbinds IArticlesRepository, constructs MockArticlesRepository,
  seeds it via buildDevArticles(), and rebinds via .toConstantValue.
- src/di/bind-dev-seed.test.ts — 3 tests: populated repo, welcome
  article reachable by slug, idempotent (callable twice).

package.json adds the ./di/bind-dev-seed subpath export, parallel to
./di/bind-production.

Tests + use cases continue to construct MockArticlesRepository
directly — they never go through bindDevSeedBlog. The seed only attaches
when called explicitly at app boot.
2026-05-06 19:00:31 +02:00
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
ef2b8e300e docs(plan-9): doc-pass slice 1 — CLAUDE.md, core-shared AGENTS, architecture, plan-8 annotations
First slice of the combined Plan 8 + Plan 9 doc-update pass:
- CLAUDE.md Key Conventions: append schema-in-use-case, presenter,
  controller unknown input, feature-scoped tRPC error mapping, public
  surface split (./ui)
- packages/core-shared/AGENTS.md: document defineErrorMiddleware export
  + t re-export from trpc/init
- docs/superpowers/plans/2026-05-05-plan-8-*.md and matching spec:
  one-line note that some controller/router patterns shifted in Plan 9;
  link to the Plan 9 refactor log
- docs/architecture/overview.md: data-flow box now shows xProcedure +
  xInputSchema + xOutputSchema.parse + presenter + middleware lanes;
  three explanatory paragraphs added (schemas, presenter, error mapping)
- docs/architecture/dependency-flow.md: app-side ./ui subpath note,
  allowed/disallowed examples updated for Plan 9 paths

Remaining doc-pass items (root AGENTS.md, per-feature AGENTS.md ×5,
core-testing AGENTS.md, adding-a-feature.md, tdd-workflow.md,
testing-strategy.md, vertical-feature-spec.md) follow in subsequent
commits — to be dispatched in parallel.
2026-05-06 16:43:13 +02:00
2b67964213 refactor(media): unify use-case I/O schemas + presenter + feature error map
Per Plan 9 (spec R1-R28):
- Use cases: input + output schemas (getMedia, listMedia); deleteMedia
  has input schema only (void output, R12 — no presenter).
- Controllers: unknown input + identity presenter on getMedia/listMedia;
  Promise<void> on deleteMedia.
- New integrations/api/procedures.ts with mediaProcedure
  ([InputParseError → BAD_REQUEST], [MediaNotFoundError → NOT_FOUND]).
- Router uses mediaProcedure + .input(xInputSchema).
- src/index.ts exports schemas + types; src/ui/index.ts placeholder
  (media has no queries today); package.json adds ./ui subpath.
- R25 + R26 tests added.

Refactor log: §1, §2, §3.1, §3.2, §3.3, §5.1, §5.2, §6.1, §6.2
Spec: R1–R6, R8–R15, R18–R20, R22–R26

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:41:08 +02:00
9663c82624 fix(errors): set this.name in every domain error constructor (R6)
Spec reviewer caught a systemic gap during Task 6 (navigation) review:
Plan 8 left every feature's domain error class with a constructor that
didn't set this.name = '<ClassName>'. Plan 9 spec R6 requires it.

Fixed across all 10 error files:
- auth: AuthenticationError, UnauthenticatedError, UnauthorizedError, InputParseError
- blog: ArticleNotFoundError, InputParseError
- marketing-pages: PageNotFoundError, InputParseError
- navigation: HeaderNotFoundError, InputParseError
- media: MediaNotFoundError, InputParseError

Functionally a no-op — defineErrorMiddleware uses instanceof, not name —
but ensures correct serialization, stack traces, and JSON inspection.

Refactor log: §7
Spec: R6
2026-05-06 15:33:28 +02:00
27c79e6e1f refactor(navigation): unify use-case I/O schemas + presenter + feature error map
Per Plan 9 (spec R1-R28):
- getHeader use case: input z.object({}).strict() (R5); output =
  headerSchema parsed at runtime.
- getHeader controller: unknown input + identity presenter.
- New integrations/api/procedures.ts with navigationProcedure
  ([InputParseError → BAD_REQUEST], [HeaderNotFoundError → NOT_FOUND]).
- Router uses navigationProcedure + .input(getHeaderInputSchema).
- src/index.ts: remove headerQuery; export schemas + IUseCase/Controller
  aliases.
- src/ui/index.ts (NEW); package.json adds ./ui subpath.
- R25 + R26 tests added.

Refactor log: §1, §2, §3.1, §3.2, §3.3, §5.1, §5.2, §6.1, §6.2
Spec: R1–R6, R8–R15, R18–R20, R22–R26
2026-05-06 15:23:30 +02:00
f4adf315af refactor(marketing-pages): unify use-case I/O schemas + presenter + feature error map
Per Plan 9 (spec R1-R28):
- Use cases: input + output schemas (getPageBySlug, getSiteSettings).
  Site-settings input is z.object({}).strict() per R5 (uniform input).
- Controllers: unknown input + identity presenter; void output not
  applicable (both use cases return data).
- New integrations/api/procedures.ts with marketingPagesProcedure
  ([InputParseError → BAD_REQUEST], [PageNotFoundError → NOT_FOUND]).
- Router uses marketingPagesProcedure + .input(xInputSchema).
- src/index.ts: remove pageBySlugQuery/siteSettingsQuery; export
  schemas + types + IUseCase/IController aliases.
- src/ui/index.ts (NEW); package.json adds ./ui subpath.
- R25 output-validation tests + R26 router error-mapping test.

Refactor log: §1, §2, §3.1, §3.2, §3.3, §5.1, §5.2, §6.1, §6.2
Spec: R1–R6, R8–R15, R18–R20, R22–R26
2026-05-06 15:15:02 +02:00
614c9014ad style(blog): add section dividers + drop redundant presenter comment
Code-quality reviewer flagged stylistic divergence from auth's pattern:
- All 3 blog use cases now have // ── Input ──... / ── Output ──... /
  ── Use case ──... section dividers (consistent with auth Task 3 + plan
  template §4.1).
- Removed inline comment in get-articles controller's presenter that
  appeared in only 1 of 3 controllers; identity presenters are
  self-explanatory.
2026-05-06 15:10:16 +02:00
86070b236a refactor(blog): unify use-case I/O schemas + presenter + feature error map
Per Plan 9 (spec R1-R28):
- Use cases: input + output schemas (getArticles, createArticle,
  getArticleBySlug). Output validated via outputSchema.parse before
  return. status field uses articleStatusSchema (was loose `string`).
- Controllers: receive `unknown`; safeParse with use-case schema;
  identity presenter (R11) on every controller.
- New integrations/api/procedures.ts with blogProcedure
  ([InputParseError → BAD_REQUEST], [ArticleNotFoundError → NOT_FOUND]).
- Router uses blogProcedure + .input(xInputSchema) for all 3 procedures.
- src/index.ts: remove articleBySlugQuery/listArticlesQuery re-exports;
  export schemas + types + IUseCase/IController aliases.
- src/ui/index.ts (NEW): query builders moved here; package.json adds
  ./ui subpath.
- New tests: R25 output-validation per use case; R26 router error-
  mapping (NOT_FOUND on missing slug, BAD_REQUEST on schema fail).

Refactor log: §1, §2, §3.1, §3.2, §3.3, §5.1, §5.2, §6.1, §6.2
Spec: R1–R6, R8–R15, R18–R20, R22–R26

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 15:04:53 +02:00
70c7b7dfe7 test(auth): tighten R25 + sign-in controller assertions per code review
Code-quality reviewer flagged:
- R25 'malformed output' tests used .rejects.toThrow(/parse|invalid/i)
  which could match unrelated errors. Replaced with
  .rejects.toBeInstanceOf(ZodError) for both sign-in and sign-up.
- sign-in controller test asserted result.name only as truthy; the
  parallel sign-up test was already precise (toBe('session')). Tightened
  to match.

61 tests still passing for @repo/auth.
2026-05-06 13:03:37 +02:00
2bbec70a4e refactor(auth): unify use-case I/O schemas + presenter + feature error map
Per Plan 9 (spec R1-R28):
- Use cases: input + output schemas (signIn, signUp); input-only for
  signOut (void output). Use case body validates output via
  outputSchema.parse before returning.
- Controllers: receive `unknown`; safeParse with the use-case schema;
  presenter (returning cookie) for signIn/signUp; void return for
  signOut.
- New integrations/api/procedures.ts with authProcedure built via
  defineErrorMiddleware([[InputParseError,"BAD_REQUEST"],
  [AuthenticationError,"UNAUTHORIZED"], [UnauthenticatedError,
  "UNAUTHORIZED"], [UnauthorizedError,"FORBIDDEN"]]).
- Router uses authProcedure + .input(xInputSchema) for every procedure.
- src/index.ts exports schemas + types + IUseCase/IController aliases.
- package.json gains ./ui subpath; src/ui/index.ts placeholder
  (auth has no query builders today).
- New tests: R25 output-validation per use case (signIn, signUp);
  R26 router error-mapping (UNAUTHORIZED on missing user,
  BAD_REQUEST on schema fail).

Refactor log: §1, §2, §3.1, §3.2, §3.3, §5.1, §5.2, §6.1, §6.2
Spec: R1–R6, R8–R15, R18, R19, R22–R26
2026-05-06 12:58:10 +02:00
aac37fd9af docs(core-shared): correct defineErrorMiddleware jsdoc to match implementation
Code-quality reviewer flagged a stale 'try/catch' phrase in the jsdoc
that didn't match the actual result.ok inspection pattern. Updated
description to accurately describe how tRPC v11 middleware sees errors
(returned result, not thrown exception) and how the middleware
discriminates and rethrows.

Pure docstring change — no behavioral or signature impact.
2026-05-06 11:54:51 +02:00
e25b1f7a1c feat(core-shared): add defineErrorMiddleware factory + export t
Factory takes [[ErrorCtor, TRPC_CODE], ...] tuples and returns a tRPC
middleware that translates matching domain errors to TRPCError. Discrim-
inates by instanceof; preserves original error as cause; unmapped
errors propagate (tRPC then wraps them as INTERNAL_SERVER_ERROR with
the original error as .cause — middleware does not interfere).

core-shared never enumerates feature errors — each feature passes its
own constructors in via integrations/api/procedures.ts (Tasks 3-7).

Also exports the `t` instance from trpc/init.ts so feature procedure
files can do t.procedure.use(...).

Also fixes tsconfig.json: rootDir set to "." and @/* path alias added
so test files using @/ resolve correctly under tsc --noEmit.

Refactor log: §1, §2, §4
Spec: R13–R17
2026-05-06 11:43:45 +02:00
8a36d803b3 feat(media): full Clean Architecture scaffold
Media is now a complete vertical-feature package mirroring auth/blog
structure: entities (models + errors), application (repositories +
use-cases), infrastructure (real Payload-backed + mock siblings),
interface-adapters (per-use-case controllers), DI (symbols + module +
container + bind-production), integrations/api (mediaRouter), factory,
contract suite, and feature integration tests.

Wired into:
- packages/core-api/src/root.ts (added `media: mediaRouter`)
- apps/web-next/src/server/bind-production.ts (calls bindProductionMedia)
- tsconfig.base.json (added @repo/media/api and ./di/bind-production aliases)

56 new tests in @repo/media (13 test files); core-api router test updated
to assert media. procedures. All 26 turbo tasks green.

Refactor log: §2, §4.1, §4.2, §5.1, §6.1
Spec: §6.5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 00:29:05 +02:00
69623b995d refactor(navigation): factory-style use case + controller
- Use case (get-header) → factory function with IGetHeaderUseCase alias
- Controller renamed header.controller.ts → get-header.controller.ts (verb-noun); converted to factory function with IGetHeaderController alias
- DI module wires factories with .toDynamicValue()
- tRPC router resolves controller via container
- Use case + controller tests refactored to direct factory injection (no container rebinding)
- container.test.ts verifies IGetHeaderUseCase + IGetHeaderController symbols

Refactor log: §1, §4.1, §4.2, §5.1
Spec: §6.4

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 00:19:15 +02:00
353a41b244 refactor(marketing-pages): factory-style use cases + per-use-case controllers
- Use cases (get-page-by-slug, get-site-settings) → factory functions with I*UseCase aliases
- Controllers split: pages.controller.ts → 2 single-responsibility files
- DI module wires factories with .toDynamicValue()
- tRPC router resolves controllers via container

Refactor log: §2, §3, §4.1, §4.2, §5.1
Spec: §6.3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 00:14:27 +02:00
700d311052 refactor(blog): factory-style use cases + per-use-case controllers + getArticleBySlug
- Use cases (create-article, get-articles, get-article-by-slug NEW) → factory functions
- Controllers split: articles.controller.ts → 3 single-responsibility files
- DI module wires factories with .toDynamicValue()
- tRPC router resolves controllers via container

Refactor log: §2, §3, §4.1, §4.2, §5.1
Spec: §6.2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 00:08:15 +02:00
780d5cb83b refactor(auth): factory-style use cases + controllers + real Payload impls
- Use cases (sign-in, sign-up, sign-out) → factory functions with I*UseCase aliases
- Controllers → factory functions with I*Controller aliases
- DI symbols + module updated with .toDynamicValue() bindings for factories
- New: real UsersRepository (Payload-backed, SanitizedConfig, contract-tested)
- New: real AuthenticationService (node:crypto hashing/UUIDs; createSession/
  validateSession/invalidateSession deferred — see refactor log §7)
- bindProductionAuth swaps both mocks for real impls (was a no-op before)
- Tests refactored to construct mocks and inject directly (no container rebinding)
- Feature test constructs full chain via direct factory injection

Refactor log: §2, §4.1, §4.2, §5.1, §5.2, §6.1, §7
Spec: §6.1, §7

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 00:01:11 +02:00
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
a4c4ca6b6e refactor(features): split entities into models/ + errors/ subdirs
All 5 features (auth, blog, marketing-pages, navigation; media has no
entities yet) now follow Lazar's pattern:
- entities/<x>.ts → entities/models/<x>.ts
- entities/errors.ts → entities/errors/<domain>.ts + errors/common.ts

Updates all import paths across factories, contracts, tests, use cases,
controllers, repositories, integrations, and src/index.ts exports.

navigation divergence: had no errors.ts; errors/header.ts +
errors/common.ts added as new forward-looking stubs.

Refactor log: docs/superpowers/refactor-logs/2026-05-05-lazar-pattern-conformance.md
Spec: §5, §9.3

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:34:32 +02:00
9415eb1c5a test: enforce per-directory coverage thresholds
entities + use-cases + controllers must hit 100% (95% branches).
Project-wide baseline remains 80/75/80/80. Tightening these directories
reflects the architectural intent: these are the pure-logic layers and
should be exhaustively tested.

Added @vitest/coverage-v8@^3 to core-typescript, auth, blog,
marketing-pages, and navigation devDependencies.

Excluded from coverage (legitimately untestable):
- src/di/bind-production.ts — InversifyJS startup bootstrap
- src/application/repositories/** — pure TypeScript interfaces
- src/application/services/** — pure TypeScript interfaces (auth)
- src/integrations/cms/** — declarative Payload CMS config
- src/entities/cookie.ts — pure type aliases (auth)
- src/ui/** — React Query helpers, integration-tested in apps

Tests added (6 new files / 1 extended):
- auth/src/entities/errors.test.ts — UnauthenticatedError, UnauthorizedError,
  AuthenticationError, InputParseError constructors
- blog/src/entities/errors.test.ts — ArticleNotFoundError (default + custom
  message), InputParseError
- marketing-pages/src/entities/errors.test.ts — PageNotFoundError, InputParseError
- marketing-pages/src/entities/site-settings.test.ts — siteSettingsSchema
  (valid, no description, empty name rejection)
- navigation/src/entities/header.test.ts — headerItemSchema and headerSchema
  validation paths
- navigation/src/.../payload-header.repository.test.ts — logo relation-object,
  scalar-id, null, and null-item-field branches for full branch coverage

Spec: §6.9
2026-05-05 19:51:34 +02:00
87112c43b0 docs(navigation): correct file references in Tests section
The previous commit referenced nonexistent files
(navigation-repository.contract.ts, tests/get-header.feature.test.ts).
The actual contract is header-repository.contract.ts and navigation has
no tests/ directory yet. Also adds nav-item.factory.ts to the factories
bullet (created in Task 3).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 19:33:11 +02:00
5ea4c67f93 docs(adr): ADR-011 TDD foundation; update AGENTS.md per-feature
Captures the decision to add @repo/core-testing, factories, contract
suites, vitest safety defaults, coverage thresholds, Storybook
test-runner, and CI as one cohesive TDD foundation. Per-feature
AGENTS.md gains a Tests section pointing to factories, contract suite,
and the canonical test commands.

Spec: §7.4, §7.5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 19:31:31 +02:00
3ff1f4a6a3 feat(core-*): add Vitest configs + composition tests
core-api: appRouter exposes all 4 feature routers + blog procedure shape.
core-cms: payloadConfig registers all collections + globals.
core-trpc: client + provider exports verified.

Spec: §6.1, §6.6
2026-05-05 16:27:26 +02:00
11b5b15105 feat(core-ui): add jsdom Vitest config + RTL tests for components
Adopts jsdomVitestConfig from @repo/core-typescript. Adds
@testing-library/react, @testing-library/user-event, jsdom devDeps.
Writes smoke + interaction tests for every atom/molecule/organism/template
using renderWithProviders from @repo/core-testing/react.

Components covered:
- atoms: Button (5 tests), Input (4), Label (2)
- molecules: FormField (5)
- organisms / templates: empty barrels, no components

Adjustments:
- core-ui/tsconfig.json now extends react-library.json (jsx: react-jsx)
  with rootDir "." + paths {"@/*"} + types [vitest/globals, jest-dom]
- core-typescript/vitest.base.jsdom.ts uses ./vitest.base.node.ts (explicit
  .ts extension) so Node's ESM resolver finds the source file when loaded
  via the package export from a downstream package

Spec: §6.1, §6.5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 16:21:58 +02:00
b3c903fd36 fix(tests): address Task 4 code review feedback
- Deprecate mockPayloadModule with throw guard (hoisting incompatible)
- Replace `as never` with stubPayloadConfig in payload-articles test (consistency)
- Tighten pages contract to use toHaveLength (exact assertions)
- Header contract: define CONTRACT_HEADER_SEED, assert item count + order

Reviewer: superpowers:code-reviewer (Task 4 of Plan 7).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:04:07 +02:00
e1355e6bc7 feat(features): contract suites for all repository interfaces
Each repository interface now has a contract suite under
src/__contracts__/. Both Mock and Payload implementations run the
same suite, eliminating mock-vs-real drift. Payload impls back the
contract with an in-memory stub via vi.mock('payload') + a small
buildPayloadStub helper.

Spec: §5.2, §6.4
2026-05-05 15:28:38 +02:00
a74f217703 fix(features): address Task 3 code review feedback
- Add navItemFactory to navigation (spec §5.1 — was missing)
- Refactor blog/router.test.ts to use articleFactory (eliminate new Date())
- headerFactory uses sequence for logoId (deterministic buildList output)
- Align media/tsconfig.json with other features (jsx + tests/ include)
- Refactor auth/container.test.ts to use userFactory

Reviewer: superpowers:code-reviewer (Task 3 of Plan 7).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 15:18:35 +02:00
53c2fbb9e1 feat(features): add test factories to all 5 features
Adds src/__factories__/<entity>.factory.ts to auth, blog, marketing-pages,
navigation, media. Each factory uses defineFactory from @repo/core-testing
with stable date defaults (2026-01-01) so snapshot diffs reflect SUT
behavior only. Refactors mechanical inline-fixture tests to use factories.

Also adds vitest.config.ts and tsconfig path alias to @repo/media (lacked
both), and adds @repo/core-testing devDependency to @repo/media.

Spec: §5.1, §6.3
2026-05-05 14:56:50 +02:00
52ac978027 fix(core-typescript): tighten jsdom config tests + document cycle avoidance
- Replace arrayContaining with toEqual on setupFiles + include — captures
  actual mergeConfig array-concatenation behavior so future changes to
  setup/node.ts surface in this test.
- Document in core-typescript/AGENTS.md why @repo/core-testing is not a
  devDep here (would create a circular dependency with core-testing).

Reviewer: superpowers:code-reviewer (Task 2 of Plan 7).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:48:20 +02:00
bf6affd404 feat(core-typescript): split vitest base into node + jsdom flavors
Adds vitest.base.node and vitest.base.jsdom with safety defaults
(clearMocks, restoreMocks, mockReset, unstubGlobals, sequence.shuffle)
and coverage thresholds (80/75/80/80). Migrates all feature configs
to the new base. Existing baseVitestConfig kept as backwards-compat
re-export of nodeVitestConfig.

Spec: §6.2
2026-05-05 14:04:19 +02:00
a533be3c3a fix(core-testing): address code review feedback for Task 1
- Remove unused @trpc/tanstack-react-query dependency
- Document renderWithProviders tRPC provider omission (boundary constraint)
- Implement deep merge in defineFactory (preserves nested sibling keys)
- Document httpBatchLink<any> rationale in mock-trpc.ts
- Align core-testing's own vitest.config with safety defaults (mockReset, unstubGlobals)
- Add createMockTrpcClient usage example to AGENTS.md

Reviewer: superpowers:code-reviewer (Task 1 of Plan 7).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:50:32 +02:00
4ca083690f feat(core-testing): scaffold shared testing utilities package
Adds @repo/core-testing (tag: tooling) with:
- factory/defineFactory: monotonic-sequence object factories with overrides
- contract/defineContractSuite: shared test suites runnable against multiple impls
- react/renderWithProviders + createMockTrpcClient: RTL helpers
- payload/stubPayloadConfig + mockPayloadModule: Payload mocking helpers
- setup/{jsdom,node}: vitest setup files

Spec: docs/superpowers/specs/2026-05-05-tdd-foundation-design.md §5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:37:35 +02:00
2c2375920f docs: reflect tooling-package rename + Turbo boundaries enforcement
- Rename eslint-config → core-eslint, typescript-config → core-typescript
  in all docs (package map, AGENTS.md, overview.md, dependency-flow.md, etc.)
- Document the five-tag model (app, feature, core, core-composition,
  tooling) — refinement of ADR-006's three-tag mention
- Document core-trpc's core-composition tag (transitively reaches features
  through core-api's AppRouter type)
- Note Turborepo boundaries as a second enforcement layer alongside ESLint
- Add ADR-010 explaining the two-layer enforcement decision and
  five-tag refinement

Files updated:
- docs/architecture/overview.md: package map, enforcement layers, five-tag section
- docs/architecture/dependency-flow.md: boundary rules, enforcement strategy
- docs/architecture/vertical-feature-spec.md: package names, five-tag model
- AGENTS.md: package map, boundary rules, commands
- CLAUDE.md: tooling package names, quick-start command
- packages/core-eslint/AGENTS.md: tag clarification
- packages/core-typescript/AGENTS.md: tag clarification
- packages/core-api/AGENTS.md: core-composition tag
- packages/core-cms/AGENTS.md: core-composition tag
- packages/core-trpc/AGENTS.md: core-composition tag + rationale
- docs/decisions/adr-010-turbo-boundaries.md: new ADR

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 12:24:04 +02:00
eb55a698f3 fix(turbo-boundaries): resolve 32 violations
- Re-tag core-trpc as core-composition (transitively reaches features
  through core-api's AppRouter type) and allow core-composition packages
  to depend on other core-composition packages in turbo.json
- Add @payloadcms/richtext-lexical as direct dep of apps/cms (was pulled
  transitively via core-cms; Payload's importMap.js imports it directly)
- Add @storybook/react as devDep of core-ui and apps/storybook (stories
  belong with components per Atomic Design)
- Update apps/storybook .storybook/{main,preview}.ts to point at
  packages/core-ui (was still referencing deleted packages/ui) and export
  CSS via package exports instead of direct file import
- Add JSDoc type annotation to Payload-generated importMap.js to suppress
  TypeScript's TS2742 error from complex inferred types
- Add storybook-static to eslint ignores in core-eslint base config

pnpm turbo boundaries now reports zero violations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 12:12:27 +02:00
9899e213ca build(turbo): add boundaries enforcement matching ESLint dependency graph
Per-package tags + root boundaries block now enforce the same three-tag
model as eslint-plugin-boundaries:
- app          → may depend on: app, core, core-composition, feature, tooling
- feature      → may depend on: core, tooling
- core         → may depend on: core, core-composition, tooling
- core-composition (core-api, core-cms) → may depend on: core, feature, tooling
- tooling (core-eslint, core-typescript) → may depend on: tooling

Tags applied: 4 apps (app), 3 core foundation packages (core),
2 core composition packages (core-composition), 5 features (feature),
2 tooling packages (tooling). All test suites pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:59:44 +02:00
0972645ebb refactor: rename eslint-config + typescript-config to core-eslint + core-typescript
Aligns tooling packages with the core-* naming convention used by all
other foundation packages (core-shared, core-cms, core-api, core-trpc,
core-ui). Updates ~50 files: package.json names, devDependencies,
tsconfig extends, eslint.config imports, vitest.config imports, AGENTS.md
references, and the boundaries plugin patterns to match the new paths.

The tooling-specific patterns in boundaries/elements are now ordered BEFORE
the broader core-* pattern to ensure correct first-match-wins behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 10:37:07 +02:00
0ede53998f docs(agents): add per-package AGENTS.md for eslint-config + typescript-config 2026-05-05 09:59:08 +02:00
440315a4c1 docs(agents): add per-package AGENTS.md for all feature packages 2026-05-05 09:58:42 +02:00
956b38fb00 docs(agents): add per-package AGENTS.md for all core-* packages 2026-05-05 09:37:47 +02:00
520749c4e3 build: add root test:e2e task aggregating per-app Playwright suites 2026-05-05 09:29:37 +02:00
22bee5362f feat(eslint-config): add boundaries plugin enforcing app→feature→core graph
- Install eslint-plugin-boundaries@^4.2.2 to enforce three-tag boundary model
- Configure element types: app, core-composition (core-api/core-cms), core, feature, tooling
- Enforce unidirectional dependency graph: apps→features→core, core-composition→features
- Add eslint.config.js to all 17 packages and apps (required for ESLint 9 flat config)
- Fix pre-existing linting issues to achieve clean lint pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 09:21:01 +02:00