fix: address final-review polish (docs + comments + test coverage)

- AGENTS.md bind-production code block: shows the slim default state
  (no @repo/core-events / @repo/core-realtime imports, BindProductionContext
  with no generic args) with a comment pointing to the scaffold workflow.
  The previous block showed a fully-wired post-scaffold state without
  signaling that none of those packages exist in main.
- bind-protocols.test.ts: top-of-file comment clarifies what these tests
  actually verify (protocol shapes have required methods) vs what the
  spec text might suggest (full assignability of optional packages'
  interfaces — that's verified by the e2e reconstruction tests, not here).
- core-package-generator.md: drops two stale "Until Phases 3-6 land"
  parentheticals — the phases shipped.
- config.test.ts: extends the choices assertion to cover all 4 names
  (realtime, events, trpc, ui).
- marketing-pages bind-* comments: reverse the inverted optional/required
  language. queue (IJobQueue) is from core-shared and always present;
  bus is the optional one (from @repo/core-events when scaffolded).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 15:01:40 +02:00
parent ce550f60e0
commit ee069574ba
6 changed files with 22 additions and 17 deletions

View File

@@ -321,24 +321,21 @@ Each app (`web-next`, `web-tanstack`, `cms`) imports both binders per feature an
```typescript
// apps/web-next/src/server/bind-production.ts
// Slim default template — no optional packages scaffolded yet.
// After running e.g. `pnpm turbo gen core-package events`, the full
// IEventBus type can be plugged via the generic args
// `BindProductionContext<IEventBus, ...>` and the bus/queue construction
// (resolveEventsAndJobsProduction) wires back in per the printed next-steps.
import type { BindProductionContext, BindContext } from "@repo/core-shared/di";
import type { IEventBus } from "@repo/core-events";
import type { IRealtimeBroadcaster, IRealtimeHandlerRegistry } from "@repo/core-realtime";
export async function bindAllProduction(deps: BindAllDeps): Promise<void> {
export async function bindAllProduction(): Promise<void> {
const { tracer, logger } = resolveInstrumentation();
const { bus, queue } = await resolveEventsAndJobsProduction();
const resolvedConfig = await config;
const { realtime, realtimeRegistry } = deps;
const ctx: BindProductionContext<IEventBus, IRealtimeBroadcaster, IRealtimeHandlerRegistry> = {
const ctx: BindProductionContext = {
config: resolvedConfig,
tracer,
logger,
bus,
queue,
realtime,
realtimeRegistry,
};
bindProductionAuth(ctx);
@@ -348,10 +345,8 @@ export async function bindAllProduction(deps: BindAllDeps): Promise<void> {
bindProductionMedia(ctx);
}
export async function bindAllDevSeed(deps: BindAllDeps): Promise<void> {
export async function bindAllDevSeed(): Promise<void> {
const { tracer, logger } = resolveInstrumentation();
const { bus, queue } = resolveEventsAndJobsDevSeed();
const { realtime, realtimeRegistry } = deps;
const ctx: BindContext<IEventBus, IRealtimeBroadcaster, IRealtimeHandlerRegistry> = {
tracer, logger, bus, queue, realtime, realtimeRegistry,

View File

@@ -24,8 +24,6 @@ The generator emits the package files, updates consuming-app config (e.g. `apps/
| `trpc` | tRPC server setup | Phase 5 |
| `ui` | Design-system package | Phase 6 |
(Until Phases 3-6 land, the generator will list an empty choices array and reject any selection.)
## Verifying an existing project
If your project already has a core-* package and you want to verify the generator's template hasn't drifted from the shipped source, use the byte-identical reconstruction snapshot:

View File

@@ -5,6 +5,14 @@ import type {
RealtimeRegistryProtocol,
} from "./bind-protocols";
// Protocol-shape tests. These verify each protocol type EXPORTS the
// expected method names. Full assignability of `IEventBus` /
// `IRealtimeBroadcaster` / `IRealtimeHandlerRegistry` to their respective
// protocols is verified at the optional-package level — when those packages
// are scaffolded back via `pnpm turbo gen core-package <name>`, the
// `extends`-link in their interface declarations forces a typecheck
// failure if the protocol surface ever drifts.
describe("EventBusProtocol", () => {
it("requires publish(event, payload) and subscribe(event, consumer, handler)", () => {
type Bus = EventBusProtocol;

View File

@@ -139,7 +139,8 @@ export async function bindDevSeedMarketingPages(ctx: BindContext): Promise<void>
// <gen:event-handlers>
// onAuthUserSignedUpHandler subscription — generated, edit the handler file (not this block) for behavior.
// queue is optional: guard so the handler is only bound when core-jobs is wired (Phase 3+).
// bus is optional: when @repo/core-events is not scaffolded, ctx.bus is undefined and the handler is not bound.
// queue (IJobQueue) is in core-shared and always provided; the inner if (queue) below is belt-and-suspenders.
if (queue) {
const wrappedAuthUserSignedUp = withSpan(
tracer,

View File

@@ -129,7 +129,8 @@ export function bindProductionMarketingPages(ctx: BindProductionContext): void {
// <gen:event-handlers>
// onAuthUserSignedUpHandler subscription — generated, edit the handler file (not this block) for behavior.
// queue is optional: guard so the handler is only bound when core-jobs is wired (Phase 3+).
// bus is optional: when @repo/core-events is not scaffolded, ctx.bus is undefined and the handler is not bound.
// queue (IJobQueue) is in core-shared and always provided; the inner if (queue) below is belt-and-suspenders.
if (queue) {
const wrappedAuthUserSignedUp = withSpan(
tracer,

View File

@@ -17,6 +17,8 @@ describe("core-package generator", () => {
expect(prompts[0]!.name).toBe("name");
expect(prompts[0]!.choices).toContain("realtime");
expect(prompts[0]!.choices).toContain("events");
expect(prompts[0]!.choices).toContain("trpc");
expect(prompts[0]!.choices).toContain("ui");
});
});