@powerhousedao/codegen 6.0.2-staging.6 → 6.0.2-staging.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2205,6 +2205,56 @@ After doing changes to the code, or after creating a new document model or a new
2205
2205
 
2206
2206
  - **TypeScript Check**: Run \`npm run tsc\` to validate type safety
2207
2207
  - **ESLint Check**: Run \`npm run lint:fix\` to check for errors with ESLint
2208
+ - **Reducer Test Coverage**: Run \`npm run test:coverage\` after any change to a document model reducer. Document model reducers are pure synchronous functions and **MUST** stay at or above **95%** coverage on lines, branches, functions, and statements. If coverage drops below the threshold, add tests in \`document-models/<name>/v<n>/tests/\` until the threshold is restored — **DO NOT** lower the threshold or exclude files to make the check pass. Cover the happy path _and_ every error code defined via \`ADD_OPERATION_ERROR\` (each error is a branch that needs explicit test coverage). Push toward 100% by following the strategy below.
2209
+
2210
+ #### Strategy: reaching 100% reducer coverage
2211
+
2212
+ 95% is the enforced floor (vitest will fail below it). This strategy describes how to push toward 100% when feasible — and how to recognize when an uncovered branch indicates an implementation problem rather than a missing test.
2213
+
2214
+ ##### Phase 1: Baseline measurement
2215
+
2216
+ Run coverage and identify the gap. Statements and lines reach high coverage quickly — the real challenge is **branch coverage**. Every \`||\`, \`??\`, \`if\`, and \`&&\` creates two branches; V8 counts them independently.
2217
+
2218
+ ##### Phase 2: Write scenario tests first
2219
+
2220
+ Before chasing branches, write a small number of tests that exercise **realistic operation sequences**. Each test should chain multiple operations together the way a real consumer would use them. This covers the majority of code paths naturally and reveals which branches remain uncovered.
2221
+
2222
+ Prefer fewer tests that each cover wide ranges of behavior over many isolated unit tests per branch. A single "full conversation flow" test that exercises 14 operations in sequence is more valuable and more maintainable than 14 separate tests.
2223
+
2224
+ ##### Phase 3: Categorize every uncovered branch
2225
+
2226
+ Don't write tests to hit uncovered branches yet. First, examine each one and classify it:
2227
+
2228
+ 1. **Wrong nullability in the schema** — The type allows \`null\` but the value is always initialized and never null at runtime. The defensive fallback (\`?? 0\`, \`?? defaultValue\`) creates an unreachable branch. No test can meaningfully cover it because the condition cannot occur through any valid operation sequence.
2229
+ 2. **Missing validation** — The type is nullable because the schema uses a flattened structure (e.g. a tagged union where fields are optional per variant). Some fields are _required for specific variants_ but the reducer silently accepts their absence. The fallback branch is reachable but only with invalid input that should be rejected.
2230
+ 3. **Wrong coercion operator** — \`||\` is used where \`??\` is needed. Values like \`0\`, \`false\`, and \`""\` are valid but \`||\` coerces them to the fallback. This is a bug, not a coverage gap.
2231
+ 4. **Legitimate optionality** — The field is genuinely optional. Both branches (value provided / not provided) are reachable through valid inputs. These are the only branches worth covering with tests.
2232
+
2233
+ ##### Phase 4: Fix the implementation, don't test around it
2234
+
2235
+ For each category:
2236
+
2237
+ - **Wrong nullability** → Tighten the type definition. Make the field non-nullable at the source (e.g. \`Int!\` instead of \`Int\` in the GraphQL schema). This eliminates the fallback code entirely, removing the untestable branch. Update the source schema via MCP (\`SET_STATE_SCHEMA\` / \`SET_OPERATION_SCHEMA\`) and regenerate — see "Document Model Modification Process" below.
2238
+ - **Missing validation** → Add validation that throws a specific named error for invalid input (define it via \`ADD_OPERATION_ERROR\` — see "Error Handling in Operations" below). This converts a silent fallback into an explicit rejection. The validation branch is now both reachable and worth testing.
2239
+ - **Wrong operator** → Fix \`||\` to \`??\` (or vice versa). Add a test that passes a falsy-but-valid value (\`0\`, \`false\`, \`""\`) and asserts it is preserved.
2240
+ - **Legitimate optionality** → Add test cases that exercise both sides. Often these can be folded into existing scenario tests by varying inputs (e.g. one call provides the field, another omits it).
2241
+
2242
+ ##### Phase 5: Extend scenario tests to cover remaining branches
2243
+
2244
+ With the implementation corrected, extend the existing scenario tests to hit newly-testable branches:
2245
+
2246
+ - Add a test that skips initialization to cover "not yet initialized" false branches.
2247
+ - Add error path tests that chain multiple invalid operations in sequence, asserting each error and verifying state is unchanged (use the operation-index pattern from "Testing Reducer Errors" below — never \`.toThrow()\`).
2248
+ - Add a test that uses minimal/empty inputs to cover fallback-to-null branches on optional fields.
2249
+ - Vary inputs across tests so both sides of legitimate \`||\` / \`??\` operators are hit (e.g. one test provides \`stepIndex: 0\`, another omits it).
2250
+
2251
+ ##### Phase 6: Verify
2252
+
2253
+ Run \`npm run test:coverage\`. Reducers should be at or near 100% across all four metrics. If any branches remain uncovered, repeat the categorization in Phase 3: is it a type problem, a validation gap, an operator bug, or a legitimate test gap? Do not stop at 95% if a small number of uncovered branches remain — they are usually the cheapest signals of an underlying implementation issue.
2254
+
2255
+ ##### The principle
2256
+
2257
+ **Don't test around bad types — fix the types.** When a branch is untestable, the problem is almost never a missing test. It is a type that is too loose, a validation that is missing, or an operator that is wrong. Fix the implementation so that every branch is either reachable and meaningful, or eliminated entirely. Coverage follows naturally from correct types, proper validation, and realistic test scenarios.
2208
2258
 
2209
2259
  ## Document editor creation flow
2210
2260
 
@@ -2228,7 +2278,7 @@ After doing changes to the code, or after creating a new document model or a new
2228
2278
  Only **after** the codegen has produced the boilerplate files, proceed with the UI implementation:
2229
2279
 
2230
2280
  - Inspect the generated files in the \`editors/\` folder — do NOT create new files for the main editor component; edit the generated one
2231
- - Inspect the hooks in \`editors/hooks\` as they should be useful
2281
+ - Hooks for each document model are auto-generated at \`document-models/<name>/v<n>/hooks.ts\` and re-exported through the top-level barrel \`document-models/<name>\` (which always points at the latest version). Import them from the barrel — there is **no** \`editors/hooks/\` folder.
2232
2282
  - Read the schema of the document model that the editor is for to know how to interact with it
2233
2283
  - Every editor **MUST** include \`<DocumentToolbar />\` imported from \`@powerhousedao/design-system/connect/index\`. Place it at the top of the editor component — do not put anything next to it.
2234
2284
  - Style the editor using tailwind classes or a style tag. If using a style tag, make sure to make the selectors specific to only apply to the editor component.
@@ -2258,25 +2308,424 @@ Using a "Todo" document model as example:
2258
2308
 
2259
2309
  ~~~typescript
2260
2310
  import { generateId } from "document-model";
2261
- import { useSelectedTodoDocument } from "../hooks/useTodoDocument.js";
2262
- import {
2263
- addTodo,
2264
- } from "../../document-models/todo/gen/creators.js";
2311
+ import { actions, useSelectedTodoDocument } from "document-models/todo";
2265
2312
 
2266
2313
  export default function Editor() {
2267
2314
  const [document, dispatch] = useSelectedTodoDocument();
2268
2315
 
2269
2316
  function handleAddTodo(values: { title: string }) {
2270
2317
  if (values.title) {
2271
- dispatch(addTodo({ id: generateId(), title: values.title }));
2318
+ dispatch(actions.addTodo({ id: generateId(), title: values.title }));
2272
2319
  }
2273
- };
2320
+ }
2321
+
2322
+ // ...
2323
+ }
2274
2324
 
2275
- // Note: The \`useSelectedTodoDocument\` hook is auto-generated. Check the \`editors/hooks\` folder for the exact hook name.
2276
- // Action creators like \`addTodo\` are exported from the document model's \`gen/creators.js\` file.
2325
+ // Note: The \`useSelectedTodoDocument\` hook is auto-generated at
2326
+ // \`document-models/todo/v<n>/hooks.ts\` and re-exported via the top-level
2327
+ // barrel \`document-models/todo\` (which always points at the latest version).
2328
+ // Action creators are exposed as \`actions.<actionName>\` from the same barrel
2329
+ // (e.g. \`actions.addTodo(...)\`) — never import from a deep \`gen/creators.js\` path.
2277
2330
  ~~~
2278
2331
 
2279
- The \`useSelectedTodoDocument\` gets generated automatically so you don't need to implement it yourself.
2332
+ The \`useSelectedTodoDocument\` (and every other document hook) is auto-generated and re-exported from the \`document-models/<name>\` top-level barrel, so you don't need to implement it yourself. See the "Editor code conventions" section below for the full import-path rules.
2333
+
2334
+ ### Editor code conventions (TypeScript & module resolution)
2335
+
2336
+ These rules apply to **every** editor regardless of which UI library you use. They come from the project's \`tsconfig\` (\`module: nodenext\`, \`strict\`, \`verbatimModuleSyntax\`) and ESLint config — they are constraints, not stylistic preferences.
2337
+
2338
+ #### Always use the top-level barrel for document-model imports
2339
+
2340
+ Every document model exposes a single public surface via its top-level barrel. Use it for **all** document-model symbols (types, actions, hooks, utils):
2341
+
2342
+ ~~~typescript
2343
+ // ✅ GOOD — barrel always points at the latest version
2344
+ import { actions, useSelectedTodoDocument } from "document-models/todo";
2345
+ import type { TodoAction, TodoDocument } from "document-models/todo";
2346
+
2347
+ // ❌ BAD — deep paths bypass the barrel and break when the version increments
2348
+ import { useSelectedTodoDocument } from "../hooks/useTodoDocument.js";
2349
+ import { addTodo } from "../../document-models/todo/gen/creators.js";
2350
+ import type { Todo } from "document-models/todo/v1/gen/schema/types.js";
2351
+ ~~~
2352
+
2353
+ The barrel re-exports types, \`actions.<actionName>\` action creators, the four generated hooks (\`useSelected<Name>Document\`, \`use<Name>DocumentById\`, \`use<Name>DocumentsInSelectedDrive\`, \`use<Name>DocumentsInSelectedFolder\`), and \`utils\`. There is **no** \`editors/hooks/\` folder — that path does not exist in generated projects.
2354
+
2355
+ #### Use the configured tsconfig path aliases — do NOT add \`@/*\`
2356
+
2357
+ The boilerplate \`tsconfig.json\` already exposes the following path aliases:
2358
+
2359
+ - \`document-models\`, \`document-models/<name>\`
2360
+ - \`editors\`, \`editors/<name>\`
2361
+ - \`processors/<name>\`
2362
+ - \`subgraphs\`, \`subgraphs/<name>\`
2363
+
2364
+ Use these directly. **Do NOT** introduce a \`@/*\` alias — \`baseUrl\` is not configured in the boilerplate, and any \`@/...\` import will fail to resolve under \`nodenext\`.
2365
+
2366
+ #### Relative imports MUST include \`.js\` extensions
2367
+
2368
+ The boilerplate uses \`"module": "nodenext"\`, which requires explicit \`.js\` extensions on every relative import (even when the source file is \`.ts\` / \`.tsx\`):
2369
+
2370
+ ~~~typescript
2371
+ // ✅ GOOD
2372
+ import { Button } from "./components/ui/button.js";
2373
+ import { cn } from "../lib/utils.js";
2374
+
2375
+ // ❌ BAD — fails at compile time
2376
+ import { Button } from "./components/ui/button";
2377
+ import { cn } from "../lib/utils";
2378
+ ~~~
2379
+
2380
+ When a third-party CLI generates extensionless imports, do a bulk find-and-replace after install to add \`.js\` to every relative path.
2381
+
2382
+ #### Stringifying \`unknown\` values
2383
+
2384
+ The boilerplate ESLint config enables \`@typescript-eslint/no-base-to-string\` (via \`recommendedTypeChecked\`). \`String(value ?? "")\` on a value typed as \`unknown\` will trip the rule because the default \`Object.prototype.toString\` produces \`"[object Object]"\`. Use a small helper:
2385
+
2386
+ ~~~typescript
2387
+ function str(v: unknown): string {
2388
+ if (v == null) return "";
2389
+ if (typeof v === "string") return v;
2390
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
2391
+ return JSON.stringify(v);
2392
+ }
2393
+ ~~~
2394
+
2395
+ ### Drag-and-drop file uploads (optional pattern)
2396
+
2397
+ Use this pattern **only** when your editor needs to accept arbitrary file drops (images, PDFs, CSVs, attachments, etc.). Default editors do **not** need any of this — skip this entire section if your editor does not handle file uploads.
2398
+
2399
+ #### Why the default does not work
2400
+
2401
+ Connect wraps every editor inside a \`DropZoneWrapper\` (from \`@powerhousedao/design-system/connect\`). That outer wrapper:
2402
+
2403
+ 1. Only accepts \`.phd\`, \`.phdm\`, and \`.zip\` files (Powerhouse document files).
2404
+ 2. Sets \`dataTransfer.dropEffect = "none"\` (the blocked / no-entry cursor) for any other file type.
2405
+ 3. Calls \`event.stopPropagation()\` on \`dragover\`, \`dragenter\`, and \`dragleave\` so events do not bubble past it.
2406
+ 4. Shows a full-screen overlay when a valid Powerhouse document is dragged in.
2407
+
2408
+ Your editor is a **descendant** of \`DropZoneWrapper\`. DOM events bubble inner → outer, so your editor's handlers run **before** DropZone's. Calling \`stopPropagation()\` in your editor prevents DropZone from ever seeing the event — that is how you bypass the \`dropEffect = "none"\` block and accept arbitrary files.
2409
+
2410
+ #### Implementation recipe
2411
+
2412
+ Attach all four drag handlers (\`onDragOver\`, \`onDragEnter\`, \`onDragLeave\`, \`onDrop\`) to your editor's **root \`div\`**. Always gate every handler on \`event.dataTransfer.types.includes("Files")\` so internal Connect drags (e.g. sidebar nodes carrying \`UI_NODE\`) bubble through to DropZone untouched — only intercept file drags.
2413
+
2414
+ ~~~tsx
2415
+ import { useCallback, useRef, useState, type DragEvent } from "react";
2416
+
2417
+ const ALLOWED_EXTENSIONS = [".png", ".jpg", ".jpeg", ".pdf"]; // adjust per editor
2418
+
2419
+ function filterAcceptedFiles(fileList: FileList): File[] {
2420
+ return Array.from(fileList).filter((file) => {
2421
+ const lower = file.name.toLowerCase();
2422
+ return ALLOWED_EXTENSIONS.some((ext) => lower.endsWith(ext));
2423
+ });
2424
+ }
2425
+
2426
+ export default function Editor() {
2427
+ const [isDragOver, setIsDragOver] = useState(false);
2428
+ const dragDepthRef = useRef(0);
2429
+
2430
+ const onEditorDragOver = useCallback((e: DragEvent) => {
2431
+ if (e.dataTransfer.types.includes("Files")) {
2432
+ e.preventDefault(); // signals "drop is allowed here"
2433
+ e.stopPropagation(); // blocks DropZone from setting dropEffect="none"
2434
+ }
2435
+ }, []);
2436
+
2437
+ const onEditorDragEnter = useCallback((e: DragEvent) => {
2438
+ if (e.dataTransfer.types.includes("Files")) {
2439
+ e.stopPropagation();
2440
+ dragDepthRef.current += 1;
2441
+ if (dragDepthRef.current === 1) setIsDragOver(true);
2442
+ }
2443
+ }, []);
2444
+
2445
+ const onEditorDragLeave = useCallback((e: DragEvent) => {
2446
+ if (e.dataTransfer.types.includes("Files")) {
2447
+ e.stopPropagation();
2448
+ dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
2449
+ if (dragDepthRef.current === 0) setIsDragOver(false);
2450
+ }
2451
+ }, []);
2452
+
2453
+ const onEditorDrop = useCallback((e: DragEvent) => {
2454
+ if (e.dataTransfer.types.includes("Files")) {
2455
+ e.preventDefault(); // prevents the browser from opening the file
2456
+ e.stopPropagation();
2457
+ dragDepthRef.current = 0;
2458
+ setIsDragOver(false);
2459
+
2460
+ const accepted = filterAcceptedFiles(e.dataTransfer.files);
2461
+ if (accepted.length === 0) return; // silently ignore rejected files
2462
+ handleFiles(accepted);
2463
+ }
2464
+ }, []);
2465
+
2466
+ return (
2467
+ <div
2468
+ onDragOver={onEditorDragOver}
2469
+ onDragEnter={onEditorDragEnter}
2470
+ onDragLeave={onEditorDragLeave}
2471
+ onDrop={onEditorDrop}
2472
+ className="relative"
2473
+ >
2474
+ {isDragOver && (
2475
+ <div className="pointer-events-none absolute inset-0 z-50 flex items-center justify-center bg-black/40">
2476
+ <div className="border-primary/60 bg-background/90 flex flex-col items-center gap-3 rounded-2xl border-2 border-dashed px-10 py-8 shadow-lg">
2477
+ <p className="text-foreground text-base font-medium">
2478
+ Drop files to attach
2479
+ </p>
2480
+ </div>
2481
+ </div>
2482
+ )}
2483
+ {/* ... editor content ... */}
2484
+ </div>
2485
+ );
2486
+ }
2487
+ ~~~
2488
+
2489
+ #### Drag-depth counter (flicker-free overlay)
2490
+
2491
+ \`dragenter\` and \`dragleave\` fire every time the cursor crosses **any** child boundary inside the editor. Without a depth counter the overlay flickers on/off as the cursor moves over nested elements. The required pattern:
2492
+
2493
+ - \`dragenter\`: increment depth; show the overlay when depth goes \`0\` → \`1\`.
2494
+ - \`dragleave\`: decrement depth; hide the overlay when depth returns to \`0\`.
2495
+ - \`drop\`: reset depth to \`0\` and hide the overlay unconditionally.
2496
+
2497
+ #### Drop overlay rules
2498
+
2499
+ The overlay \`div\` **MUST** use \`pointer-events-none\`. Without it, the overlay element captures the \`drop\` event and your handler on the root \`div\` will never fire. Use theme tokens (\`bg-background\`, \`text-foreground\`, \`text-primary\`, etc.) so the overlay renders correctly in both light and dark mode.
2500
+
2501
+ #### File-type validation
2502
+
2503
+ Always validate dropped files at the editor level — do not assume the user dropped what you expect. The \`filterAcceptedFiles\` helper above filters by file-name extension (case-insensitive). For stricter validation, additionally check \`file.type\` (MIME type) before processing. Files that fail validation should be **silently ignored** or surfaced via a toast/notification — never throw on unexpected input, since drag-and-drop is a user-initiated action and exceptions will surface as uncaught render errors.
2504
+
2505
+ #### Bridging file handlers in child component contexts
2506
+
2507
+ If your file-upload handler lives inside a **child** component's React context (for example, \`usePromptInputAttachments().add\` inside a \`PromptInput\`), you cannot call it directly from the editor root. Use a ref bridge:
2508
+
2509
+ ~~~tsx
2510
+ // editor.tsx — expose a ref the child fills in:
2511
+ const addFilesRef = useRef<((files: File[]) => void) | null>(null);
2512
+
2513
+ // inside onEditorDrop, after filtering:
2514
+ addFilesRef.current?.(accepted);
2515
+
2516
+ // pass the ref down to the child:
2517
+ <ChatInputBar addFilesRef={addFilesRef} />;
2518
+ ~~~
2519
+
2520
+ ~~~tsx
2521
+ // ChatInputBar.tsx — bridge component mounted inside the consumer's context:
2522
+ import type { MutableRefObject } from "react";
2523
+ import { useEffect } from "react";
2524
+
2525
+ function DropBridge({
2526
+ addFilesRef,
2527
+ }: {
2528
+ addFilesRef?: MutableRefObject<((files: File[]) => void) | null>;
2529
+ }) {
2530
+ const { add } = usePromptInputAttachments();
2531
+ useEffect(() => {
2532
+ if (addFilesRef) addFilesRef.current = add;
2533
+ return () => {
2534
+ if (addFilesRef) addFilesRef.current = null;
2535
+ };
2536
+ }, [add, addFilesRef]);
2537
+ return null;
2538
+ }
2539
+
2540
+ <PromptInput onSubmit={handleSubmit} multiple>
2541
+ <DropBridge addFilesRef={addFilesRef} />
2542
+ {/* ... */}
2543
+ </PromptInput>;
2544
+ ~~~
2545
+
2546
+ #### Common pitfalls — DO NOT make these mistakes
2547
+
2548
+ 1. **Do NOT use \`globalDrop\` together with \`stopPropagation\`.** \`PromptInput\`'s \`globalDrop\` prop attaches drop handlers on \`document\`. \`stopPropagation()\` at the editor root prevents events from ever reaching \`document\`. The two are incompatible — use the ref-bridge pattern instead.
2549
+ 2. **Always \`preventDefault()\` on BOTH \`dragover\` AND \`drop\`.** Without \`preventDefault\` on \`dragover\`, the browser signals "drop not allowed" and the \`drop\` event will not fire at all. Without \`preventDefault\` on \`drop\`, the browser navigates away to open the dropped file.
2550
+ 3. **Always gate handlers on \`e.dataTransfer.types.includes("Files")\`.** Connect uses non-file drag types internally (e.g. \`UI_NODE\` for sidebar items). Those drags must bubble through to DropZone untouched — only intercept file drags.
2551
+ 4. **\`dragenter\` and \`dragleave\` do NOT need \`preventDefault\`.** \`stopPropagation()\` alone is enough on those two; only \`dragover\` and \`drop\` require \`preventDefault\`.
2552
+ 5. **The overlay \`div\` MUST have \`pointer-events-none\`.** Otherwise the overlay swallows the \`drop\` event and your drop handler never fires.
2553
+ 6. **Reset \`dragDepthRef.current = 0\` inside \`onDrop\`.** Otherwise a subsequent drag will start with stale depth and the overlay logic breaks.
2554
+
2555
+ ### Using shadcn / Vercel AI Elements in editors (optional)
2556
+
2557
+ Use this section **only** when your editor needs UI primitives that are not covered by \`@powerhousedao/design-system\` or \`@powerhousedao/document-engineering\` — typically chat-style UIs that consume Vercel's AI Elements (\`Conversation\`, \`Message\`, \`Reasoning\`, \`Tool\`, \`PromptInput\`, etc.). Default editors should prefer the design-system / document-engineering primitives and skip this entire section.
2558
+
2559
+ #### Why manual setup is required
2560
+
2561
+ \`shadcn init\` will fail with \`Error: We could not detect a supported framework\`. The project is a Powerhouse reactor package, not a Next.js / Vite app, so the shadcn CLI cannot run its init flow. Set up shadcn manually with the steps below.
2562
+
2563
+ #### Step 1 — install runtime dependencies
2564
+
2565
+ ~~~bash
2566
+ pnpm add class-variance-authority clsx tailwind-merge lucide-react tw-animate-css
2567
+ ~~~
2568
+
2569
+ #### Step 2 — create \`components.json\` at the project root
2570
+
2571
+ Substitute \`<name>\` with your editor's name (e.g. \`chat-session-editor\`):
2572
+
2573
+ ~~~json
2574
+ {
2575
+ "$schema": "https://ui.shadcn.com/schema.json",
2576
+ "style": "new-york",
2577
+ "rsc": false,
2578
+ "tsx": true,
2579
+ "tailwind": {
2580
+ "config": "",
2581
+ "css": "style.css",
2582
+ "baseColor": "neutral",
2583
+ "cssVariables": true
2584
+ },
2585
+ "aliases": {
2586
+ "components": "@/editors/<name>/components",
2587
+ "utils": "@/editors/<name>/lib/utils",
2588
+ "ui": "@/editors/<name>/components/ui",
2589
+ "lib": "@/editors/<name>/lib",
2590
+ "hooks": "@/editors/<name>/hooks"
2591
+ },
2592
+ "iconLibrary": "lucide"
2593
+ }
2594
+ ~~~
2595
+
2596
+ The \`@/*\` alias inside \`components.json\` is consumed by the shadcn / AI Elements CLIs at install time only — they generate \`@/...\` imports inside the components they produce. You will rewrite those imports to relative paths in Step 7. **Do NOT** add a corresponding \`@/*\` alias to \`tsconfig.json\` — see the "Editor code conventions" section above.
2597
+
2598
+ #### Step 3 — create \`lib/utils.ts\` under your editor
2599
+
2600
+ ~~~typescript
2601
+ // editors/<name>/lib/utils.ts
2602
+ import { clsx, type ClassValue } from "clsx";
2603
+ import { twMerge } from "tailwind-merge";
2604
+
2605
+ export function cn(...inputs: ClassValue[]) {
2606
+ return twMerge(clsx(inputs));
2607
+ }
2608
+ ~~~
2609
+
2610
+ #### Step 4 — extend \`style.css\` with the shadcn theme variables
2611
+
2612
+ The boilerplate \`style.css\` already imports \`tailwindcss\`, \`@powerhousedao/design-system/theme.css\`, and \`@powerhousedao/connect/style.css\`. **Append** (do not replace) the shadcn additions:
2613
+
2614
+ - \`@import "tw-animate-css";\` (after the existing \`@import "tailwindcss";\`)
2615
+ - \`@custom-variant dark (&:is(.dark *));\`
2616
+ - A \`@theme inline { ... }\` block mapping \`--color-*\` and \`--radius-*\` to the shadcn variables
2617
+ - \`:root { ... }\` and \`.dark { ... }\` blocks with \`oklch(...)\` color values
2618
+ - \`@layer base { * { @apply border-border outline-ring/50; } body { @apply bg-background text-foreground; } }\`
2619
+
2620
+ ⚠️ **Theme conflict warning**: \`@powerhousedao/design-system/theme.css\` already declares its own theme tokens. Adding shadcn's color variables on top has not been verified for conflicts — after this step, render a Connect view and confirm both the editor and the rest of Connect still look correct in light and dark mode. If the design-system theme breaks, fall back to using \`@powerhousedao/design-system\` and \`@powerhousedao/document-engineering\` primitives instead of shadcn.
2621
+
2622
+ #### Step 5 — install AI Elements (Vercel's CLI, NOT shadcn's)
2623
+
2624
+ Vercel ships its own CLI for AI chat components — use it, **not** \`npx shadcn add\`:
2625
+
2626
+ ~~~bash
2627
+ npx ai-elements@latest add conversation message reasoning tool prompt-input code-block
2628
+ ~~~
2629
+
2630
+ **Verify each component name exists in the AI Elements registry before adding** — names that aren't in the registry will hard-error and abort the entire install. The registry list is at https://ai-sdk.dev/elements .
2631
+
2632
+ The CLI auto-installs supporting deps: \`ai\` (the Vercel AI SDK, used for types like \`UIMessage\`, \`ToolUIPart\`), \`use-stick-to-bottom\` (auto-scroll for \`Conversation\`), \`streamdown\` plus its plugins (\`@streamdown/cjk\`, \`@streamdown/code\`, \`@streamdown/math\`, \`@streamdown/mermaid\`) for markdown rendering, and \`@radix-ui/react-use-controllable-state\` (for the \`Reasoning\` toggle). These are pulled into your \`package.json\` automatically.
2633
+
2634
+ #### Step 6 — relocate AI Elements files into the editor directory
2635
+
2636
+ The CLI puts AI Elements files at \`components/ai-elements/\` at the **project root**, not inside your editor. Move them:
2637
+
2638
+ ~~~
2639
+ components/ai-elements/ → editors/<name>/components/ai-elements/
2640
+ ~~~
2641
+
2642
+ After the move, the project-root \`components/\` directory should be empty and can be deleted. UI primitives installed under \`editors/<name>/components/ui/\` are already correctly placed.
2643
+
2644
+ #### Step 7 — rewrite all \`@/...\` imports to relative paths with \`.js\` extensions
2645
+
2646
+ The shadcn / AI Elements CLIs generate imports like:
2647
+
2648
+ ~~~typescript
2649
+ import { Button } from "@/editors/<name>/components/ui/button";
2650
+ import { cn } from "@/editors/<name>/lib/utils";
2651
+ ~~~
2652
+
2653
+ Both forms break under \`nodenext\`: \`@/*\` does not resolve (no \`baseUrl\`), and the missing \`.js\` extension fails compilation. Do a bulk find-and-replace across **every file generated in Steps 5–6**. From an \`ai-elements/\` file, rewrite:
2654
+
2655
+ - \`@/editors/<name>/components/ui/button\` → \`../ui/button.js\`
2656
+ - \`@/editors/<name>/lib/utils\` → \`../../lib/utils.js\`
2657
+
2658
+ From a \`ui/\` file, rewrite:
2659
+
2660
+ - \`@/editors/<name>/components/ui/button\` → \`./button.js\`
2661
+ - \`@/editors/<name>/lib/utils\` → \`../../lib/utils.js\`
2662
+
2663
+ Also fix relative imports between AI Elements files that the CLI generated without extensions — e.g. \`./shimmer\` → \`./shimmer.js\`, \`./code-block\` → \`./code-block.js\`.
2664
+
2665
+ #### Step 8 — bridge document-model types to AI Elements types
2666
+
2667
+ AI Elements components use Vercel AI SDK types (\`UIMessage\`, \`ToolUIPart\`, \`DynamicToolUIPart\`). Your document model has its own types (\`Message\`, \`ContentPart\`, etc.).
2668
+
2669
+ **Do NOT try to convert between them.** Instead, use the **low-level primitives** (which accept plain props — strings, ReactNode) and write thin wrapper components that bridge your document-model types to those primitives:
2670
+
2671
+ - Plain-prop primitives: \`Message\`, \`MessageContent\`, \`Conversation\`, \`ConversationContent\`, \`Reasoning\`, \`ReasoningTrigger\`, \`ReasoningContent\`, \`Tool\`, \`ToolHeader\`, \`ToolContent\`, \`ToolInput\`, \`ToolOutput\`, \`MessageResponse\`.
2672
+ - For \`ToolHeader\`, use \`type="dynamic-tool"\` with explicit \`toolName\` and \`state\` props.
2673
+
2674
+ ##### Tool state mapping
2675
+
2676
+ | Document-model state | AI Elements \`ToolPart["state"]\` |
2677
+ | ---------------------------- | ------------------------------- |
2678
+ | Tool call with no result yet | \`"input-available"\` |
2679
+ | Tool call with result | \`"output-available"\` |
2680
+ | Tool call with error result | \`"output-error"\` |
2681
+
2682
+ ##### Index-signature mismatch when bridging types
2683
+
2684
+ When passing a concrete document-model interface into a function or component typed as \`Record<string, unknown> & { id: string; type: ... }\`, TypeScript will complain:
2685
+
2686
+ ~~~
2687
+ Type 'MyInterface' is not assignable to type 'Record<string, unknown>'.
2688
+ Index signature for type 'string' is missing in type 'MyInterface'.
2689
+ ~~~
2690
+
2691
+ **Fix**: add \`[key: string]: unknown;\` to the concrete interface so it satisfies the index signature.
2692
+
2693
+ #### Recommended file structure
2694
+
2695
+ ~~~
2696
+ editors/<name>/
2697
+ editor.tsx ← main editor (edit codegen output)
2698
+ module.ts ← DO NOT EDIT (codegen)
2699
+ lib/
2700
+ utils.ts ← cn() helper
2701
+ components/
2702
+ ai-elements/ ← moved from project root in Step 6
2703
+ conversation.tsx
2704
+ message.tsx
2705
+ reasoning.tsx
2706
+ tool.tsx
2707
+ code-block.tsx
2708
+ prompt-input.tsx
2709
+ ui/ ← shadcn primitives installed by ai-elements CLI
2710
+ button.tsx
2711
+ badge.tsx
2712
+ tooltip.tsx
2713
+ ... etc
2714
+ <wrapper components that bridge document-model types to AI Elements primitives>
2715
+ ~~~
2716
+
2717
+ #### Quick checklist for a shadcn-using editor
2718
+
2719
+ 1. Create the editor document via MCP and confirm its status (see "Phase 1" above).
2720
+ 2. Wait for codegen to produce the editor boilerplate.
2721
+ 3. \`pnpm add class-variance-authority clsx tailwind-merge lucide-react tw-animate-css\`
2722
+ 4. Create \`components.json\` and \`editors/<name>/lib/utils.ts\`.
2723
+ 5. Extend \`style.css\` with the shadcn theme additions; verify the design-system theme still renders correctly.
2724
+ 6. \`npx ai-elements@latest add <components>\` — verify component names against the registry first.
2725
+ 7. Move \`components/ai-elements/\` into \`editors/<name>/components/ai-elements/\`.
2726
+ 8. Bulk-rewrite every \`@/...\` import to a relative path with a \`.js\` extension; also add \`.js\` to extensionless relative imports.
2727
+ 9. Use the top-level \`document-models/<name>\` barrel for all document-model imports (see "Editor code conventions" above).
2728
+ 10. Run \`npm run tsc\` and \`npm run lint:fix\`.
2280
2729
 
2281
2730
  ## ⚠️ CRITICAL: Generated Files & Modification Rules
2282
2731
 
@@ -2737,7 +3186,7 @@ RUN apk add --no-cache python3 make g++ git bash \\
2737
3186
 
2738
3187
  # Setup pnpm
2739
3188
  ENV PNPM_HOME="/pnpm"
2740
- ENV PATH="$PNPM_HOME:$PATH"
3189
+ ENV PATH="$PNPM_HOME/bin:$PNPM_HOME:$PATH"
2741
3190
  RUN corepack enable && corepack prepare pnpm@latest --activate
2742
3191
 
2743
3192
  # Configure JSR registry
@@ -2826,7 +3275,7 @@ RUN apk add --no-cache curl openssl
2826
3275
 
2827
3276
  # Setup pnpm
2828
3277
  ENV PNPM_HOME="/pnpm"
2829
- ENV PATH="$PNPM_HOME:$PATH"
3278
+ ENV PATH="$PNPM_HOME/bin:$PNPM_HOME:$PATH"
2830
3279
  RUN corepack enable && corepack prepare pnpm@latest --activate
2831
3280
 
2832
3281
  # Configure JSR registry
@@ -2965,9 +3414,8 @@ const documentModelsTemplate = ts$1`
2965
3414
  * WARNING: DO NOT EDIT
2966
3415
  * This file is auto-generated and updated by codegen
2967
3416
  */
2968
- import type { DocumentModelModule } from "document-model";
2969
3417
 
2970
- export const documentModels: DocumentModelModule<any>[] = [];
3418
+ export const documentModels = [] as const;
2971
3419
  `.raw;
2972
3420
  //#endregion
2973
3421
  //#region src/templates/boilerplate/document-models/index.ts
@@ -3085,7 +3533,7 @@ const typescriptLanguageOptions = {
3085
3533
  },
3086
3534
  parserOptions: {
3087
3535
  projectService: {
3088
- allowDefaultProject: ["eslint.config.js", "vitest.config.ts"],
3536
+ allowDefaultProject: ["eslint.config.js", "vitest.config.ts", "main.tsx"],
3089
3537
  },
3090
3538
  tsconfigRootDir: import.meta.dirname,
3091
3539
  ecmaFeatures: {
@@ -3543,6 +3991,7 @@ coverage
3543
3991
  node_modules
3544
3992
  .eslintcache
3545
3993
  .env.local
3994
+ *.tsbuildinfo
3546
3995
 
3547
3996
  .ph
3548
3997
  projects-import.js
@@ -4247,18 +4696,16 @@ const mainTsxTemplate = tsx`
4247
4696
  * WARNING: DO NOT EDIT
4248
4697
  * This file is auto-generated and updated by codegen
4249
4698
  */
4250
- import { startConnect } from "@powerhousedao/connect";
4699
+ import { startConnect, type ImportHmr } from "@powerhousedao/connect";
4251
4700
  import * as localPackage from "./index.js";
4252
4701
 
4253
4702
  const { updateLocalPackage } = startConnect(localPackage);
4254
4703
 
4255
- if (import.meta.hot) {
4256
- import.meta.hot.accept(["./index.js"], ([newModule]) => {
4257
- if (newModule) {
4258
- updateLocalPackage(newModule);
4259
- }
4260
- });
4261
- }
4704
+ (import.meta as ImportHmr).hot?.accept(["./index.js"], ([newModule]) => {
4705
+ if (newModule) {
4706
+ updateLocalPackage(newModule);
4707
+ }
4708
+ });
4262
4709
  `.raw;
4263
4710
  //#endregion
4264
4711
  //#region src/templates/boilerplate/mcp.json.ts
@@ -4279,37 +4726,37 @@ const npmrcTemplate = `@jsr:registry=https://npm.jsr.io`;
4279
4726
  //#region src/file-builders/constants.ts
4280
4727
  const packageJsonExports = {
4281
4728
  ".": {
4282
- types: "./dist/browser/index.d.ts",
4729
+ types: "./dist/types/index.d.ts",
4283
4730
  browser: "./dist/browser/index.js",
4284
4731
  node: "./dist/node/index.mjs"
4285
4732
  },
4286
4733
  "./document-models": {
4287
- types: "./dist/browser/document-models/index.d.ts",
4734
+ types: "./dist/types/document-models/index.d.ts",
4288
4735
  browser: "./dist/browser/document-models/index.js",
4289
4736
  node: "./dist/node/document-models/index.mjs"
4290
4737
  },
4291
4738
  "./document-models/*": {
4292
- types: "./dist/browser/document-models/*/index.d.ts",
4739
+ types: "./dist/types/document-models/*/index.d.ts",
4293
4740
  browser: "./dist/browser/document-models/*/index.js",
4294
4741
  node: "./dist/node/document-models/*/index.mjs"
4295
4742
  },
4296
4743
  "./editors": {
4297
- types: "./dist/browser/editors/index.d.ts",
4744
+ types: "./dist/types/editors/index.d.ts",
4298
4745
  browser: "./dist/browser/editors/index.js",
4299
4746
  node: "./dist/node/editors/index.mjs"
4300
4747
  },
4301
4748
  "./editors/*": {
4302
- types: "./dist/browser/editors/*/editor.d.ts",
4749
+ types: "./dist/types/editors/*/editor.d.ts",
4303
4750
  browser: "./dist/browser/editors/*/editor.js",
4304
4751
  node: "./dist/node/editors/*/editor.mjs"
4305
4752
  },
4306
4753
  "./subgraphs": {
4307
- types: "./dist/browser/subgraphs/index.d.ts",
4754
+ types: "./dist/types/subgraphs/index.d.ts",
4308
4755
  browser: "./dist/browser/subgraphs/index.js",
4309
4756
  node: "./dist/node/subgraphs/index.mjs"
4310
4757
  },
4311
4758
  "./processors": {
4312
- types: "./dist/browser/processors/index.d.ts",
4759
+ types: "./dist/types/processors/index.d.ts",
4313
4760
  browser: "./dist/browser/processors/index.js",
4314
4761
  node: "./dist/node/processors/index.mjs"
4315
4762
  },
@@ -4332,10 +4779,10 @@ const packageScripts = {
4332
4779
  "service-unstartup": "bash ./node_modules/@powerhousedao/ph-cli/dist/scripts/service-unstartup.sh"
4333
4780
  };
4334
4781
  const externalDependencies = {
4335
- "@powerhousedao/document-engineering": "1.40.1",
4782
+ "@powerhousedao/document-engineering": "1.40.3",
4336
4783
  graphql: "16.12.0",
4337
4784
  "graphql-tag": "^2.12.6",
4338
- zod: "^4.3.5",
4785
+ zod: "4.3.6",
4339
4786
  react: "^19.2.3",
4340
4787
  "react-dom": "^19.2.3"
4341
4788
  };
@@ -4346,7 +4793,7 @@ const externalDevDependencies = {
4346
4793
  "@tailwindcss/cli": "^4.1.18",
4347
4794
  "@types/node": "^24.9.2",
4348
4795
  "@types/react": "^19.2.3",
4349
- "@vitejs/plugin-react": "6.0.1",
4796
+ "@vitest/coverage-v8": "4.1.1",
4350
4797
  eslint: "^9.38.0",
4351
4798
  "eslint-config-prettier": "^10.1.8",
4352
4799
  "eslint-plugin-prettier": "^5.5.4",
@@ -4356,7 +4803,6 @@ const externalDevDependencies = {
4356
4803
  tailwindcss: "^4.1.16",
4357
4804
  typescript: "^5.9.3",
4358
4805
  "typescript-eslint": "^8.46.2",
4359
- vite: "8.0.8",
4360
4806
  "vite-tsconfig-paths": "6.1.1",
4361
4807
  vitest: "4.1.1"
4362
4808
  };
@@ -4388,6 +4834,7 @@ const externalDevDepsTemplate = innerJsonBody(externalDevDependencies);
4388
4834
  const scriptsTemplate = json`
4389
4835
  "test": "vitest run",
4390
4836
  "test:watch": "vitest",
4837
+ "test:coverage": "vitest run --coverage",
4391
4838
  "lint": "eslint --config eslint.config.js --cache --cache-strategy content",
4392
4839
  "lint:fix": "npm run lint -- --fix",
4393
4840
  "tsc": "tsc",
@@ -4435,6 +4882,14 @@ const packageJsonTemplate = (projectName, versionedDependencies, versionedDevDep
4435
4882
  }
4436
4883
  `.raw;
4437
4884
  //#endregion
4885
+ //#region src/templates/boilerplate/pnpm-workspace.ts
4886
+ const pnpmWorkspaceTemplate = `allowBuilds:
4887
+ "@apollo/protobufjs": true
4888
+ "@parcel/watcher": true
4889
+ esbuild: true
4890
+ protobufjs: true
4891
+ `;
4892
+ //#endregion
4438
4893
  //#region src/templates/boilerplate/package.json.legacy.ts
4439
4894
  const packageJsonScriptsTemplate = {
4440
4895
  build: "npm run tsc && npm run tailwind",
@@ -4786,7 +5241,6 @@ const tsconfigPathsTemplate = json`
4786
5241
  const tsConfigTemplate = json`
4787
5242
  {
4788
5243
  "compilerOptions": {
4789
- "outDir": "./dist",
4790
5244
  "rootDir": ".",
4791
5245
  // paths for easy access to project modules
4792
5246
  "paths": {
@@ -4796,11 +5250,13 @@ const tsConfigTemplate = json`
4796
5250
  "moduleDetection": "force",
4797
5251
  "target": "esnext",
4798
5252
  "jsx": "react-jsx",
4799
- "types": ["node", "vite/client", "vitest/globals"],
5253
+ "types": ["node", "vitest/globals"],
4800
5254
  "lib": ["ESNext", "dom", "dom.iterable"],
4801
5255
  "declaration": true,
5256
+ "declarationDir": "./dist/types",
4802
5257
  "declarationMap": true,
4803
5258
  "emitDeclarationOnly": true,
5259
+ "incremental": true,
4804
5260
  "strict": true,
4805
5261
  "verbatimModuleSyntax": true,
4806
5262
  "isolatedModules": true,
@@ -4808,21 +5264,30 @@ const tsConfigTemplate = json`
4808
5264
  "skipLibCheck": true
4809
5265
  },
4810
5266
  "include": ["**/*", "./powerhouse.manifest.json"],
4811
- "exclude": ["dist", "node_modules", ".ph", "vitest.config.ts"]
5267
+ "exclude": ["dist", "node_modules", ".ph", "vitest.config.ts", "main.tsx"]
4812
5268
  }
4813
5269
  `.raw;
4814
5270
  //#endregion
4815
5271
  //#region src/templates/boilerplate/vitest.config.ts.ts
4816
5272
  const vitestConfigTemplate = ts$1`
4817
5273
  import { defineConfig } from "vitest/config";
4818
- import react from "@vitejs/plugin-react";
4819
5274
  import tsconfigPaths from "vite-tsconfig-paths";
4820
5275
 
4821
5276
  export default defineConfig({
4822
5277
  test: {
4823
5278
  globals: true,
5279
+ coverage: {
5280
+ provider: "v8",
5281
+ include: ["document-models/**/src/reducers/**"],
5282
+ thresholds: {
5283
+ lines: 95,
5284
+ branches: 95,
5285
+ functions: 95,
5286
+ statements: 95,
5287
+ },
5288
+ },
4824
5289
  },
4825
- plugins: [tsconfigPaths(), react()],
5290
+ plugins: [tsconfigPaths()],
4826
5291
  });
4827
5292
 
4828
5293
  `.raw;
@@ -5902,13 +6367,13 @@ function documentModelModuleFileTemplate({ phStateName, pascalCaseDocumentType,
5902
6367
  import { utils } from "./utils.js";
5903
6368
 
5904
6369
  /** Document model module for the ${pascalCaseDocumentType} document type */
5905
- export const ${pascalCaseDocumentType}: DocumentModelModule<${phStateName}> = {
6370
+ export const ${pascalCaseDocumentType} = {
5906
6371
  version: ${version},
5907
6372
  reducer,
5908
6373
  actions,
5909
6374
  utils,
5910
6375
  documentModel: createState(defaultBaseState(), documentModel),
5911
- };
6376
+ } as const satisfies DocumentModelModule<${phStateName}>;
5912
6377
  `.raw;
5913
6378
  }
5914
6379
  //#endregion
@@ -6593,7 +7058,7 @@ function getEditorMetadata(project, dirName) {
6593
7058
  }
6594
7059
  function getAppMetadata(project, dirName) {
6595
7060
  const editorMetadata = getEditorMetadata(project, dirName);
6596
- if (!editorMetadata || isIncludedIn("powerhouse/document-drive", editorMetadata.documentTypes)) return void 0;
7061
+ if (!editorMetadata || !isIncludedIn("powerhouse/document-drive", editorMetadata.documentTypes)) return void 0;
6597
7062
  return merge(editorMetadata, pipe(project.getSourceFile(join("editors", dirName, "config.ts")), (sourceFile) => ({
6598
7063
  isDragAndDropEnabled: getBooleanPropertyValue(sourceFile, "isDragAndDropEnabled", true),
6599
7064
  allowedDocumentTypes: getStringArrayPropertyElements(sourceFile, "allowedDocumentTypes")
@@ -7138,10 +7603,11 @@ async function writeAiConfigFiles(projectDir = process.cwd()) {
7138
7603
  await writeFileEnsuringDir(join(projectDir, ".claude/settings.local.json"), claudeSettingsLocalTemplate);
7139
7604
  }
7140
7605
  async function writeProjectRootFiles(args, projectDir = process.cwd()) {
7141
- const { name, tag, version, remoteDrive } = args;
7606
+ const { name, tag, version, remoteDrive, packageManager } = args;
7142
7607
  await writeFileEnsuringDir("LICENSE", licenseTemplate);
7143
7608
  await writeFileEnsuringDir("README.md", readmeTemplate);
7144
7609
  await writeFileEnsuringDir(".npmrc", npmrcTemplate);
7610
+ if (packageManager === "pnpm") await writeFileEnsuringDir("pnpm-workspace.yaml", pnpmWorkspaceTemplate);
7145
7611
  const packageJson = await buildBoilerplatePackageJson({
7146
7612
  name,
7147
7613
  tag,
@@ -7710,8 +8176,18 @@ async function makeOperationModuleTestFile(args) {
7710
8176
  const testCaseNames = describeCall.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => {
7711
8177
  const expressionText = call.getExpression().getText();
7712
8178
  return expressionText === "it" || expressionText === "test";
7713
- }).map((c) => c.getArguments()[0].getText());
7714
- const testCasesToAdd = pipe(module.operations, filter((o) => !isIncludedIn(camelCase(o.name ?? ""), testCaseNames)), map((o) => makeTestCaseForOperation(o, isPhDocumentOfTypeFunctionName)));
8179
+ }).map((c) => {
8180
+ const firstArg = c.getArguments()[0];
8181
+ const stringLiteral = firstArg.asKind(SyntaxKind.StringLiteral);
8182
+ if (stringLiteral) return stringLiteral.getLiteralValue();
8183
+ const noSubstitutionTemplate = firstArg.asKind(SyntaxKind.NoSubstitutionTemplateLiteral);
8184
+ if (noSubstitutionTemplate) return noSubstitutionTemplate.getLiteralValue();
8185
+ return firstArg.getText();
8186
+ });
8187
+ const testCasesToAdd = pipe(module.operations, filter((o) => {
8188
+ const expectedTestCaseName = `should handle ${camelCase(o.name ?? "")} operation`;
8189
+ return !testCaseNames.some((name) => name === expectedTestCaseName);
8190
+ }), map((o) => makeTestCaseForOperation(o, isPhDocumentOfTypeFunctionName)));
7715
8191
  describeCallBody.addStatements(testCasesToAdd);
7716
8192
  const GENERATE_MOCK_NAME = "generateMock";
7717
8193
  const GENERATE_MOCK_MODULE_SPECIFIER = "@powerhousedao/codegen";
@@ -8360,6 +8836,6 @@ async function makeSubgraphsIndexFile(args) {
8360
8836
  await formatSourceFileWithPrettier(sourceFile);
8361
8837
  }
8362
8838
  //#endregion
8363
- export { getOrCreateDirectory as $, dockerfileTemplate as $n, getDocumentModelSpecByVersionNumber as $t, writeProjectRootFiles as A, defaultManifest as An, upgradeTransitionTemplate as At, getAllImportModuleSpecifiers as B, legacyIndexHtmlTemplate as Bn, documentModelIndexTemplate as Bt, writeCIFiles as C, readmeTemplate as Cn, processorsIndexTemplate as Ct, writeGeneratedProjectRootFiles as D, packageJsonScriptsTemplate as Dn, analyticsIndexTemplate as Dt, writeGeneratedProcessorsFiles as E, packageJsonExportsTemplate as En, analyticsProcessorTemplate as Et, validateDocumentModelState as F, npmrcTemplate as Fn, makeTestCaseForOperation as Ft, getProperyAssignmentByName as G, eslintConfigTemplate as Gn, documentModelGenReducerFileTemplate as Gt, getBooleanPropertyValue as H, gitIgnoreTemplate as Hn, documentModelGenUtilsTemplate as Ht, getInitialStates as I, mcpTemplate as In, documentModelTestFileTemplate as It, getVariableDeclarationByTypeName as J, upgradeManifestsTemplate as Jn, documentModelOperationsModuleErrorFileTemplate as Jt, getStringArrayPropertyElements as K, editorsIndexTemplate as Kn, documentModelPhFactoriesFileTemplate as Kt, DEFAULT_PROJECT_OPTIONS as L, mainTsxTemplate as Ln, documentModelSrcUtilsTemplate as Lt, makeEditorModuleFile as M, externalDevDependencies as Mn, documentModelOperationsModuleTestFileTemplate as Mt, makeEditorsFile as N, packageJsonExports as Nn, makeOperationImportNames as Nt, writeGeneratedSubgraphsFiles as O, exportsTemplate as On, analyticsFactoryTemplate as Ot, makeEditorsIndexFile as P, packageScripts as Pn, makeOperationsImports as Pt, ensureDirectoriesExist as Q, nginxConfTemplate as Qn, getDocumentModelDirName as Qt, buildTsMorphProject as R, licenseTemplate as Rn, documentModelSrcIndexFileTemplate as Rt, writeAllGeneratedProjectFiles as S, styleTemplate as Sn, relationalDbFactoryTemplate as St, writeGeneratedEditorsFiles as T, buildPowerhouseConfigTemplate as Tn, factoryBuildersTemplate as Tt, getObjectLiteral as U, syncAndPublishWorkflowTemplate as Un, documentModelGenTypesTemplate as Ut, getAllImportNames as V, indexHtmlTemplate as Vn, documentModelHooksFileTemplate as Vt, getObjectProperty as W, geminiSettingsTemplate as Wn, documentModelSchemaIndexTemplate as Wt, buildObjectLiteral as X, documentModelsTemplate as Xn, documentModelOperationModuleActionsFileTemplate as Xt, loadDocumentModelInDir as Y, documentModelsIndexTemplate as Yn, documentModelOperationsModuleCreatorsFileTemplate as Yt, buildStringLiteral as Z, switchboardEntrypointTemplate as Zn, getModuleExportType as Zt, getCommandsHelpInfo as _, docsFromCliHelpTemplate as _n, subgraphIndexFileTemplate as _t, getOrCreateManifestFile as a, getActionInputTypeNames as an, appConfigFileTemplate as ar, getEditorMetadata as at, buildBoilerplatePackageJson as b, tsconfigPathsTemplate as bn, relationalDbMigrationsTemplate as bt, operationHasEmptyInput as c, documentModelGenIndexFileTemplate as cn, appFoldersFileTemplate as cr, runPrettier as ct, generateDocumentModelZodSchemas as d, documentModelGenCreatorsFileTemplate as dn, driveExplorerFileTemplate as dr, configSpec as dt, getDocumentModelVariableNames as en, connectEntrypointTemplate as er, getOrCreateSourceFile as et, generateTypesAndZodSchemasFromGraphql as f, documentModelGenControllerFileTemplate as fn, appDriveContentsFileTemplate as fr, parseArgs as ft, getCommandHelpInfo as g, documentEditorEditorFileTemplate as gn, subgraphLibFileTemplate as gt, tsMorphGenerateDocumentEditor as h, documentEditorModuleFileTemplate as hn, customSubgraphSchemaTemplate as ht, createOrUpdateManifest as i, getActionInputName as in, appEditorFileTemplate as ir, getAppMetadata as it, tsMorphGenerateApp as j, externalDependencies as jn, upgradeManifestTemplate as jt, writeModuleFiles as k, packageJsonTemplate as kn, documentModelUtilsTemplate as kt, operationHasInput as l, documentModelDocumentTypeTemplate as ln, appFilesFileTemplate as lr, getDocumentTypeMetadata as lt, scalarsValidation as m, documentModelRootActionsFileTemplate as mn, customSubgraphResolversTemplate as mt, tsMorphGenerateSubgraph as n, getLatestDocumentModelSpec as nn, claudeSettingsLocalTemplate as nr, getSubgraphMetadata as nt, makeModulesIndexFile as o, getActionType as on, driveExplorerNavigationBreadcrumbsFileTemplate as or, formatSafe as ot, scalars as p, documentModelGenActionsFileTemplate as pn, createDocumentFileTemplate as pr, parseConfig as pt, getStringPropertyValue as q, editorsTemplate as qn, documentModelOperationsModuleOperationsFileTemplate as qt, tsMorphGenerateProcessor as r, getLatestDocumentModelSpecVersionNumber as rn, agentsTemplate as rr, getProcessorMetadata as rt, operationHasAttachment as s, getActionTypeName as sn, folderTreeFileTemplate as sr, formatSourceFileWithPrettier as st, makeSubgraphsIndexFile as t, getEditorVariableNames as tn, cursorMcpTemplate as tr, getPreviousVersionSourceFile as tt, tsMorphGenerateDocumentModel as u, documentModelDocumentSchemaFileTemplate as un, emptyStateFileTemplate as ur, documentModelDocumentTypeMetadata as ut, makeCliDocsFromHelp as v, vitestConfigTemplate as vn, relationalDbSchemaTemplate as vt, writeGeneratedDocumentModelsFiles as w, ManifestTemplate as wn, processorsFactoryTemplate as wt, writeAiConfigFiles as x, subgraphsIndexTemplate as xn, relationalDbIndexTemplate as xt, writeCliDocsMarkdownFile as y, tsConfigTemplate as yn, relationalDbProcessorTemplate as yt, getDefaultProjectOptions as z, indexTsTemplate as zn, documentModelModuleFileTemplate as zt };
8839
+ export { getOrCreateDirectory as $, nginxConfTemplate as $n, getDocumentModelSpecByVersionNumber as $t, writeProjectRootFiles as A, packageJsonTemplate as An, upgradeTransitionTemplate as At, getAllImportModuleSpecifiers as B, indexTsTemplate as Bn, documentModelIndexTemplate as Bt, writeCIFiles as C, readmeTemplate as Cn, processorsIndexTemplate as Ct, writeGeneratedProjectRootFiles as D, packageJsonScriptsTemplate as Dn, analyticsIndexTemplate as Dt, writeGeneratedProcessorsFiles as E, packageJsonExportsTemplate as En, analyticsProcessorTemplate as Et, validateDocumentModelState as F, packageScripts as Fn, makeTestCaseForOperation as Ft, getProperyAssignmentByName as G, geminiSettingsTemplate as Gn, documentModelGenReducerFileTemplate as Gt, getBooleanPropertyValue as H, indexHtmlTemplate as Hn, documentModelGenUtilsTemplate as Ht, getInitialStates as I, npmrcTemplate as In, documentModelTestFileTemplate as It, getVariableDeclarationByTypeName as J, editorsTemplate as Jn, documentModelOperationsModuleErrorFileTemplate as Jt, getStringArrayPropertyElements as K, eslintConfigTemplate as Kn, documentModelPhFactoriesFileTemplate as Kt, DEFAULT_PROJECT_OPTIONS as L, mcpTemplate as Ln, documentModelSrcUtilsTemplate as Lt, makeEditorModuleFile as M, externalDependencies as Mn, documentModelOperationsModuleTestFileTemplate as Mt, makeEditorsFile as N, externalDevDependencies as Nn, makeOperationImportNames as Nt, writeGeneratedSubgraphsFiles as O, pnpmWorkspaceTemplate as On, analyticsFactoryTemplate as Ot, makeEditorsIndexFile as P, packageJsonExports as Pn, makeOperationsImports as Pt, ensureDirectoriesExist as Q, switchboardEntrypointTemplate as Qn, getDocumentModelDirName as Qt, buildTsMorphProject as R, mainTsxTemplate as Rn, documentModelSrcIndexFileTemplate as Rt, writeAllGeneratedProjectFiles as S, styleTemplate as Sn, relationalDbFactoryTemplate as St, writeGeneratedEditorsFiles as T, buildPowerhouseConfigTemplate as Tn, factoryBuildersTemplate as Tt, getObjectLiteral as U, gitIgnoreTemplate as Un, documentModelGenTypesTemplate as Ut, getAllImportNames as V, legacyIndexHtmlTemplate as Vn, documentModelHooksFileTemplate as Vt, getObjectProperty as W, syncAndPublishWorkflowTemplate as Wn, documentModelSchemaIndexTemplate as Wt, buildObjectLiteral as X, documentModelsIndexTemplate as Xn, documentModelOperationModuleActionsFileTemplate as Xt, loadDocumentModelInDir as Y, upgradeManifestsTemplate as Yn, documentModelOperationsModuleCreatorsFileTemplate as Yt, buildStringLiteral as Z, documentModelsTemplate as Zn, getModuleExportType as Zt, getCommandsHelpInfo as _, docsFromCliHelpTemplate as _n, subgraphIndexFileTemplate as _t, getOrCreateManifestFile as a, getActionInputTypeNames as an, appEditorFileTemplate as ar, getEditorMetadata as at, buildBoilerplatePackageJson as b, tsconfigPathsTemplate as bn, relationalDbMigrationsTemplate as bt, operationHasEmptyInput as c, documentModelGenIndexFileTemplate as cn, folderTreeFileTemplate as cr, runPrettier as ct, generateDocumentModelZodSchemas as d, documentModelGenCreatorsFileTemplate as dn, emptyStateFileTemplate as dr, configSpec as dt, getDocumentModelVariableNames as en, dockerfileTemplate as er, getOrCreateSourceFile as et, generateTypesAndZodSchemasFromGraphql as f, documentModelGenControllerFileTemplate as fn, driveExplorerFileTemplate as fr, parseArgs as ft, getCommandHelpInfo as g, documentEditorEditorFileTemplate as gn, subgraphLibFileTemplate as gt, tsMorphGenerateDocumentEditor as h, documentEditorModuleFileTemplate as hn, customSubgraphSchemaTemplate as ht, createOrUpdateManifest as i, getActionInputName as in, agentsTemplate as ir, getAppMetadata as it, tsMorphGenerateApp as j, defaultManifest as jn, upgradeManifestTemplate as jt, writeModuleFiles as k, exportsTemplate as kn, documentModelUtilsTemplate as kt, operationHasInput as l, documentModelDocumentTypeTemplate as ln, appFoldersFileTemplate as lr, getDocumentTypeMetadata as lt, scalarsValidation as m, documentModelRootActionsFileTemplate as mn, createDocumentFileTemplate as mr, customSubgraphResolversTemplate as mt, tsMorphGenerateSubgraph as n, getLatestDocumentModelSpec as nn, cursorMcpTemplate as nr, getSubgraphMetadata as nt, makeModulesIndexFile as o, getActionType as on, appConfigFileTemplate as or, formatSafe as ot, scalars as p, documentModelGenActionsFileTemplate as pn, appDriveContentsFileTemplate as pr, parseConfig as pt, getStringPropertyValue as q, editorsIndexTemplate as qn, documentModelOperationsModuleOperationsFileTemplate as qt, tsMorphGenerateProcessor as r, getLatestDocumentModelSpecVersionNumber as rn, claudeSettingsLocalTemplate as rr, getProcessorMetadata as rt, operationHasAttachment as s, getActionTypeName as sn, driveExplorerNavigationBreadcrumbsFileTemplate as sr, formatSourceFileWithPrettier as st, makeSubgraphsIndexFile as t, getEditorVariableNames as tn, connectEntrypointTemplate as tr, getPreviousVersionSourceFile as tt, tsMorphGenerateDocumentModel as u, documentModelDocumentSchemaFileTemplate as un, appFilesFileTemplate as ur, documentModelDocumentTypeMetadata as ut, makeCliDocsFromHelp as v, vitestConfigTemplate as vn, relationalDbSchemaTemplate as vt, writeGeneratedDocumentModelsFiles as w, ManifestTemplate as wn, processorsFactoryTemplate as wt, writeAiConfigFiles as x, subgraphsIndexTemplate as xn, relationalDbIndexTemplate as xt, writeCliDocsMarkdownFile as y, tsConfigTemplate as yn, relationalDbProcessorTemplate as yt, getDefaultProjectOptions as z, licenseTemplate as zn, documentModelModuleFileTemplate as zt };
8364
8840
 
8365
- //# sourceMappingURL=file-builders-BraThjto.mjs.map
8841
+ //# sourceMappingURL=file-builders-KGdRKyyn.mjs.map