diff --git a/docs/superpowers/plans/2026-05-04-plan-2-blog-feature.md b/docs/superpowers/plans/2026-05-04-plan-2-blog-feature.md index eb1d156..392ea0e 100644 --- a/docs/superpowers/plans/2026-05-04-plan-2-blog-feature.md +++ b/docs/superpowers/plans/2026-05-04-plan-2-blog-feature.md @@ -1042,6 +1042,14 @@ export class PayloadArticlesRepository implements IArticlesRepository { > Note: `as never` casts on the Payload `data` arguments are needed because Payload's generated types (which we don't have for the empty-collection core-cms config) would normally constrain these. With empty `collections: []`, the generated types don't include `'articles'`, so we cast through `never`. After Plan 3 wires articles into core-cms.collections AND `pnpm generate:types` runs, these casts can potentially be removed — but for Plan 2's purpose (decoupled feature with deferred wiring) the casts are correct. +> **Critical architectural note (revised after execution):** The repo takes `SanitizedConfig` via its constructor instead of `import config from '@repo/core-cms'` (which would create a workspace dependency cycle: blog ↔ core-cms). Constructor injection breaks the cycle at the package-graph level. The DI binding for production (Plan 5, app boot) supplies the config: +> ```ts +> import config from '@repo/core-cms' +> blogContainer.bind(BLOG_SYMBOLS.IArticlesRepository) +> .toDynamicValue(() => new PayloadArticlesRepository(config)) +> ``` +> The blog `package.json` does NOT declare `@repo/core-cms` as a dependency. Apply this pattern to every payload-backed feature repository. + - [ ] **Step 4: Run — expect pass** Run: `cd packages/blog && pnpm vitest run src/infrastructure/repositories/payload-articles.repository.test.ts`