@getcoherent/cli 0.6.49 → 0.6.50

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.
Files changed (3) hide show
  1. package/README.md +6 -1
  2. package/dist/index.js +470 -428
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -101,7 +101,7 @@ import { CLI_VERSION as CLI_VERSION6 } from "@getcoherent/core";
101
101
  import chalk3 from "chalk";
102
102
  import ora from "ora";
103
103
  import prompts2 from "prompts";
104
- import { existsSync as existsSync4, readFileSync as readFileSync2, mkdirSync as mkdirSync3, rmSync, writeFileSync as writeFileSync4 } from "fs";
104
+ import { existsSync as existsSync3, readFileSync as readFileSync2, mkdirSync as mkdirSync3, rmSync, writeFileSync as writeFileSync4 } from "fs";
105
105
  import { basename, join as join3 } from "path";
106
106
  import { execSync } from "child_process";
107
107
  import { ProjectScaffolder, ComponentGenerator } from "@getcoherent/core";
@@ -839,123 +839,14 @@ function hasApiKey() {
839
839
  return !!(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY);
840
840
  }
841
841
 
842
- // src/utils/cursor-rules.ts
843
- import { writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
842
+ // src/utils/harness-context.ts
843
+ import { writeFileSync as writeFileSync3, existsSync as existsSync2 } from "fs";
844
844
  import { join as join2 } from "path";
845
- import { loadManifest as loadManifest2 } from "@getcoherent/core";
846
- import { DesignSystemManager as DesignSystemManager2 } from "@getcoherent/core";
845
+ import { loadManifest, DesignSystemManager } from "@getcoherent/core";
847
846
 
848
847
  // src/utils/claude-code.ts
849
- import { writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
848
+ import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
850
849
  import { join } from "path";
851
- import { loadManifest } from "@getcoherent/core";
852
- import { DesignSystemManager } from "@getcoherent/core";
853
- function buildSharedComponentsListForClaude(manifest) {
854
- if (!manifest.shared || manifest.shared.length === 0) {
855
- return "No shared components yet. Register with: coherent components shared add <name> --type layout|navigation|data-display|form|feedback|section|widget";
856
- }
857
- const order = {
858
- layout: 0,
859
- navigation: 1,
860
- "data-display": 2,
861
- form: 3,
862
- feedback: 4,
863
- section: 5,
864
- widget: 6
865
- };
866
- const sorted = [...manifest.shared].sort(
867
- (a, b) => (order[a.type] ?? 9) - (order[b.type] ?? 9) || a.name.localeCompare(b.name)
868
- );
869
- return sorted.map((e) => {
870
- const used = e.usedIn.length === 0 ? "\u2014" : e.usedIn.length === 1 && e.usedIn[0] === "app/layout.tsx" ? "layout" : e.usedIn.length + " files";
871
- return `- ${e.id} ${e.name} (${e.type}) \u2014 ${e.file} \u2014 ${used}`;
872
- }).join("\n");
873
- }
874
- function buildClaudeMdContent(manifest, _config) {
875
- const sharedList = buildSharedComponentsListForClaude(manifest);
876
- return `# Coherent Design Method Project
877
-
878
- This is a Coherent Design Method project \u2014 AI-powered multi-page UI prototype with shared component system.
879
-
880
- ## Architecture
881
-
882
- - app/ \u2014 Next.js App Router pages
883
- - components/ui/ \u2014 base shadcn/ui components (Button, Card, Input, etc.)
884
- - components/shared/ \u2014 shared reusable blocks with unique IDs (CID-XXX)
885
- - app/design-system/ \u2014 platform overlay (DO NOT MODIFY)
886
- - coherent.components.json \u2014 shared component manifest
887
- - design-system.config.ts \u2014 design tokens and page definitions
888
-
889
- ## Shared Components (MUST REUSE)
890
-
891
- ${sharedList}
892
-
893
- Before creating ANY UI block, check if a shared component exists above. If yes \u2014 IMPORT it. NEVER recreate inline.
894
-
895
- ## Rules
896
-
897
- - ONLY use @/components/ui/* \u2014 never native <button>, <select>, <input type="checkbox">, <table>
898
- - Icons: lucide-react only
899
- - Forms: Label above Input, Switch for toggles, Select for 3+ options
900
- - Colors: semantic tokens only (bg-background, text-foreground, bg-primary) \u2014 never hardcoded
901
- - Links: text-sm text-muted-foreground underline underline-offset-4 hover:text-foreground transition-colors (ALL links same style per page)
902
- - ALL interactive elements MUST have hover: and focus-visible: states \u2014 no exceptions
903
- - Identical components must look identical everywhere
904
- - Badge: default=success, secondary=neutral, outline=warning, destructive=error (same status = same variant everywhere)
905
- - Avatar: size-8 in lists, size-10 in profiles, always rounded-full
906
- - Dialog: max-w-sm for confirms, max-w-md for forms. Footer: cancel left, action right
907
- - Tabs: shadcn Tabs. TabsContent space-y-4. TabsList w-full md:w-auto
908
- - Alert: <Alert> for info, variant="destructive" for errors. Never for success (use toast)
909
- - Sections: h2 text-lg font-semibold. Separator between sections, border-b between list items
910
- - Nav active: sidebar=bg-accent font-medium, top nav=text-foreground font-medium
911
- - Toast: use shadcn toast, not browser alert(). Success=description only 3-5s, error=variant="destructive" persistent
912
- - Table rows: hover:bg-muted/50, actions via DropdownMenu (MoreHorizontal), wrap in overflow-x-auto
913
- - Button order: secondary first, primary LAST. Icon+text: icon mr-2 size-4 before text
914
- - Skeleton: h-4 animate-pulse rounded-md bg-muted (match content shape). Button loading: Loader2 animate-spin
915
- - Sheet for filters/mobile nav/previews. Dialog for confirmations/blocking. Sheet default side: right
916
- - Breadcrumb on pages 2+ levels deep. Current page=text-foreground, parents=muted-foreground
917
- - Code blocks: inline=rounded bg-muted px-1.5 py-0.5 font-mono text-sm. Block=rounded-md bg-muted px-4 py-3
918
- - Pagination: shadcn Pagination, centered below list. Feeds: "Load more" button instead
919
- - Card actions: DropdownMenu in CardHeader top-right OR actions in CardFooter, never both
920
- - Search: relative + Search icon absolute left-3, Input pl-9, debounce 300ms
921
- - Accordion: shadcn, type="single" for FAQ, "multiple" for settings
922
- - Popover=small forms, DropdownMenu=action lists, Dialog=complex/blocking
923
- - ScrollArea=fixed containers, native overflow-y-auto=dynamic content
924
- - Empty states: centered icon (size-12) + title + description + CTA. Search/filter variants
925
- - Stat cards: CardTitle text-sm font-medium, metric text-2xl font-bold, trend text-emerald-600/text-destructive
926
- - Error pages: centered 404/500 + "Go home" CTA. Never dead-end the user
927
- - Confirmation: title=action-specific, description=consequences, Cancel(outline)+Destructive
928
- - Multi-step: numbered circles (bg-primary active, bg-muted upcoming), Back/Next buttons
929
- - Form validation: text-sm text-destructive below input, border-destructive on input. NEVER toast
930
- - File upload: border-2 border-dashed + Upload icon + "Drag and drop or browse"
931
- - RadioGroup: 2-3 options=Radio, 4+=Select. Vertical default
932
- - Notification dot: absolute -top-1 -right-1 size-2 bg-destructive. Count: max "9+"
933
- - Progress: shadcn Progress h-2. For uploads/quotas. NEVER for page loads
934
- - Data format: dates=relative recent, absolute older. Numbers=toLocaleString. Currency=$1,234.56
935
- - Status dots: size-2 rounded-full (emerald=active, destructive=error, yellow=warning)
936
- - Timeline: vertical dot+line+event. Avatar group: flex -space-x-2 ring-2 ring-background
937
- - Sidebar: w-64 desktop, Sheet from left mobile. Settings: two-col nav+cards
938
- - Pricing: grid md:grid-cols-3, highlighted=ring-2 ring-primary, Popular badge
939
- - Hero: centered py-16 md:py-24, h1 text-3xl md:text-5xl, CTA size="lg"
940
- - Command palette: shadcn Command, \u2318K trigger. Toggle/ToggleGroup for view switchers
941
- - Copy: ghost sm button, swap Copy\u2192Check icon 2s. Z-index: content=0, dropdown=50, toast=100
942
- - Animation: transition-colors for hovers, 150ms. NEVER page load animations
943
- - Accessibility: WCAG 2.2 AA, contrast \u2265 4.5:1, touch targets \u2265 44px, focus-visible on all interactive
944
- - Auth pages (login, signup, etc.) go in app/(auth)/ route group \u2014 no Header/Footer
945
-
946
- ## After Making Changes
947
-
948
- Run after changes:
949
- - coherent check \u2014 show all quality and consistency issues (read-only)
950
- - coherent fix \u2014 auto-fix cache, deps, syntax, and style issues
951
-
952
- ## Do NOT modify
953
-
954
- - app/design-system/* \u2014 platform overlay
955
- - app/api/design-system/* \u2014 platform API routes
956
- - coherent.components.json \u2014 managed by platform
957
- `;
958
- }
959
850
  function ensureDir(dir) {
960
851
  try {
961
852
  mkdirSync2(dir, { recursive: true });
@@ -1290,11 +1181,6 @@ var SETTINGS_JSON = `{
1290
1181
  }
1291
1182
  }
1292
1183
  `;
1293
- function writeClaudeMd(projectRoot, manifest, config2) {
1294
- const content = buildClaudeMdContent(manifest, config2);
1295
- const outPath = join(projectRoot, "CLAUDE.md");
1296
- writeFileSync2(outPath, content, "utf-8");
1297
- }
1298
1184
  function writeClaudeCommands(projectRoot) {
1299
1185
  const dir = join(projectRoot, ".claude", "commands");
1300
1186
  ensureDir(dir);
@@ -1315,34 +1201,8 @@ function writeClaudeSettings(projectRoot) {
1315
1201
  ensureDir(dir);
1316
1202
  writeFileSync2(join(dir, "settings.json"), SETTINGS_JSON.trim(), "utf-8");
1317
1203
  }
1318
- async function loadManifestAndConfig(projectRoot) {
1319
- let manifest;
1320
- try {
1321
- manifest = await loadManifest(projectRoot);
1322
- } catch {
1323
- manifest = { shared: [], nextId: 1 };
1324
- }
1325
- let config2 = null;
1326
- const configPath = join(projectRoot, "design-system.config.ts");
1327
- if (existsSync2(configPath)) {
1328
- try {
1329
- const dsm = new DesignSystemManager(configPath);
1330
- await dsm.load();
1331
- config2 = dsm.getConfig();
1332
- } catch {
1333
- }
1334
- }
1335
- return { manifest, config: config2 };
1336
- }
1337
- async function generateClaudeCodeFiles(projectRoot) {
1338
- const { manifest, config: config2 } = await loadManifestAndConfig(projectRoot);
1339
- writeClaudeMd(projectRoot, manifest, config2);
1340
- writeClaudeCommands(projectRoot);
1341
- writeClaudeSkills(projectRoot);
1342
- writeClaudeSettings(projectRoot);
1343
- }
1344
1204
 
1345
- // src/utils/cursor-rules.ts
1205
+ // src/utils/harness-context.ts
1346
1206
  function buildSharedComponentsList(manifest) {
1347
1207
  if (!manifest.shared || manifest.shared.length === 0) {
1348
1208
  return `No shared components registered yet.
@@ -1377,6 +1237,27 @@ register them: coherent components shared add <Name> --type layout|navigation|da
1377
1237
 
1378
1238
  ${lines.join("\n\n")}`;
1379
1239
  }
1240
+ function buildSharedComponentsListCompact(manifest) {
1241
+ if (!manifest.shared || manifest.shared.length === 0) {
1242
+ return "No shared components yet. Register with: coherent components shared add <name> --type layout|navigation|data-display|form|feedback|section|widget";
1243
+ }
1244
+ const order = {
1245
+ layout: 0,
1246
+ navigation: 1,
1247
+ "data-display": 2,
1248
+ form: 3,
1249
+ feedback: 4,
1250
+ section: 5,
1251
+ widget: 6
1252
+ };
1253
+ const sorted = [...manifest.shared].sort(
1254
+ (a, b) => (order[a.type] ?? 9) - (order[b.type] ?? 9) || a.name.localeCompare(b.name)
1255
+ );
1256
+ return sorted.map((e) => {
1257
+ const used = e.usedIn.length === 0 ? "\u2014" : e.usedIn.length === 1 && e.usedIn[0] === "app/layout.tsx" ? "layout" : e.usedIn.length + " files";
1258
+ return `- ${e.id} ${e.name} (${e.type}) \u2014 ${e.file} \u2014 ${used}`;
1259
+ }).join("\n");
1260
+ }
1380
1261
  function buildDesignTokensSummary(config2) {
1381
1262
  if (!config2?.tokens) {
1382
1263
  return `Design tokens are defined in design-system.config.ts and globals.css.
@@ -1403,14 +1284,7 @@ Use semantic classes: bg-background, text-foreground, bg-primary, text-muted-for
1403
1284
  return `Current design tokens:
1404
1285
  ${lines.join("\n")}`;
1405
1286
  }
1406
- function buildCursorRules(manifest, config2) {
1407
- const sharedList = buildSharedComponentsList(manifest);
1408
- const tokensSummary = buildDesignTokensSummary(config2);
1409
- return `# Coherent Design Method \u2014 Project Rules
1410
- # Auto-generated. Updated when shared components or config change.
1411
- # Do NOT edit manually \u2014 run \`coherent rules\` to regenerate.
1412
-
1413
- ## Project Architecture
1287
+ var ARCHITECTURE_DETAILED = `## Project Architecture
1414
1288
 
1415
1289
  This is a Coherent Design Method project. It uses Next.js + Tailwind + a built-in component library.
1416
1290
 
@@ -1424,21 +1298,16 @@ This is a Coherent Design Method project. It uses Next.js + Tailwind + a built-i
1424
1298
  ### Config files
1425
1299
  - design-system.config.ts \u2014 design tokens, pages, navigation
1426
1300
  - coherent.components.json \u2014 shared component manifest
1427
- - globals.css \u2014 CSS variables (colors, typography, spacing)
1428
-
1429
- ## Shared Components (MUST REUSE)
1430
-
1431
- Before creating ANY UI block, check if a matching shared component exists below.
1432
- If it does \u2014 IMPORT and USE it. NEVER recreate inline.
1433
-
1434
- ${sharedList}
1301
+ - globals.css \u2014 CSS variables (colors, typography, spacing)`;
1302
+ var ARCHITECTURE_COMPACT = `## Architecture
1435
1303
 
1436
- When using a shared component:
1437
- - Import from @/components/shared/{filename}
1438
- - If you need it with different props, use its props interface
1439
- - If the component doesn't accept the prop you need, add the prop to the shared component and update all existing usages
1440
-
1441
- ## Component Rules (MANDATORY)
1304
+ - app/ \u2014 Next.js App Router pages
1305
+ - components/ui/ \u2014 base shadcn/ui components (Button, Card, Input, etc.)
1306
+ - components/shared/ \u2014 shared reusable blocks with unique IDs (CID-XXX)
1307
+ - app/design-system/ \u2014 platform overlay (DO NOT MODIFY)
1308
+ - coherent.components.json \u2014 shared component manifest
1309
+ - design-system.config.ts \u2014 design tokens and page definitions`;
1310
+ var RULES_DETAILED = `## Component Rules (MANDATORY)
1442
1311
 
1443
1312
  - ONLY use components from @/components/ui/* \u2014 never native HTML elements
1444
1313
  - NEVER use native <button> \u2014 use: import { Button } from "@/components/ui/button"
@@ -1634,9 +1503,58 @@ When using a shared component:
1634
1503
  - Content: z-0. Sticky: z-10. Dropdowns: z-50. Toast: z-[100]. Never arbitrary above z-50.
1635
1504
 
1636
1505
  ### Animation
1637
- - transition-colors for hovers. 150ms default. NEVER animate on page load or decorative.
1506
+ - transition-colors for hovers. 150ms default. NEVER animate on page load or decorative.`;
1507
+ var RULES_COMPACT = `## Rules
1638
1508
 
1639
- ## Design Quality Standards
1509
+ - ONLY use @/components/ui/* \u2014 never native <button>, <select>, <input type="checkbox">, <table>
1510
+ - Icons: lucide-react only
1511
+ - Forms: Label above Input, Switch for toggles, Select for 3+ options
1512
+ - Colors: semantic tokens only (bg-background, text-foreground, bg-primary) \u2014 never hardcoded
1513
+ - Links: text-sm text-muted-foreground underline underline-offset-4 hover:text-foreground transition-colors (ALL links same style per page)
1514
+ - ALL interactive elements MUST have hover: and focus-visible: states \u2014 no exceptions
1515
+ - Identical components must look identical everywhere
1516
+ - Badge: default=success, secondary=neutral, outline=warning, destructive=error (same status = same variant everywhere)
1517
+ - Avatar: size-8 in lists, size-10 in profiles, always rounded-full
1518
+ - Dialog: max-w-sm for confirms, max-w-md for forms. Footer: cancel left, action right
1519
+ - Tabs: shadcn Tabs. TabsContent space-y-4. TabsList w-full md:w-auto
1520
+ - Alert: <Alert> for info, variant="destructive" for errors. Never for success (use toast)
1521
+ - Sections: h2 text-lg font-semibold. Separator between sections, border-b between list items
1522
+ - Nav active: sidebar=bg-accent font-medium, top nav=text-foreground font-medium
1523
+ - Toast: use shadcn toast, not browser alert(). Success=description only 3-5s, error=variant="destructive" persistent
1524
+ - Table rows: hover:bg-muted/50, actions via DropdownMenu (MoreHorizontal), wrap in overflow-x-auto
1525
+ - Button order: secondary first, primary LAST. Icon+text: icon mr-2 size-4 before text
1526
+ - Skeleton: h-4 animate-pulse rounded-md bg-muted (match content shape). Button loading: Loader2 animate-spin
1527
+ - Sheet for filters/mobile nav/previews. Dialog for confirmations/blocking. Sheet default side: right
1528
+ - Breadcrumb on pages 2+ levels deep. Current page=text-foreground, parents=muted-foreground
1529
+ - Code blocks: inline=rounded bg-muted px-1.5 py-0.5 font-mono text-sm. Block=rounded-md bg-muted px-4 py-3
1530
+ - Pagination: shadcn Pagination, centered below list. Feeds: "Load more" button instead
1531
+ - Card actions: DropdownMenu in CardHeader top-right OR actions in CardFooter, never both
1532
+ - Search: relative + Search icon absolute left-3, Input pl-9, debounce 300ms
1533
+ - Accordion: shadcn, type="single" for FAQ, "multiple" for settings
1534
+ - Popover=small forms, DropdownMenu=action lists, Dialog=complex/blocking
1535
+ - ScrollArea=fixed containers, native overflow-y-auto=dynamic content
1536
+ - Empty states: centered icon (size-12) + title + description + CTA. Search/filter variants
1537
+ - Stat cards: CardTitle text-sm font-medium, metric text-2xl font-bold, trend text-emerald-600/text-destructive
1538
+ - Error pages: centered 404/500 + "Go home" CTA. Never dead-end the user
1539
+ - Confirmation: title=action-specific, description=consequences, Cancel(outline)+Destructive
1540
+ - Multi-step: numbered circles (bg-primary active, bg-muted upcoming), Back/Next buttons
1541
+ - Form validation: text-sm text-destructive below input, border-destructive on input. NEVER toast
1542
+ - File upload: border-2 border-dashed + Upload icon + "Drag and drop or browse"
1543
+ - RadioGroup: 2-3 options=Radio, 4+=Select. Vertical default
1544
+ - Notification dot: absolute -top-1 -right-1 size-2 bg-destructive. Count: max "9+"
1545
+ - Progress: shadcn Progress h-2. For uploads/quotas. NEVER for page loads
1546
+ - Data format: dates=relative recent, absolute older. Numbers=toLocaleString. Currency=$1,234.56
1547
+ - Status dots: size-2 rounded-full (emerald=active, destructive=error, yellow=warning)
1548
+ - Timeline: vertical dot+line+event. Avatar group: flex -space-x-2 ring-2 ring-background
1549
+ - Sidebar: w-64 desktop, Sheet from left mobile. Settings: two-col nav+cards
1550
+ - Pricing: grid md:grid-cols-3, highlighted=ring-2 ring-primary, Popular badge
1551
+ - Hero: centered py-16 md:py-24, h1 text-3xl md:text-5xl, CTA size="lg"
1552
+ - Command palette: shadcn Command, \u2318K trigger. Toggle/ToggleGroup for view switchers
1553
+ - Copy: ghost sm button, swap Copy\u2192Check icon 2s. Z-index: content=0, dropdown=50, toast=100
1554
+ - Animation: transition-colors for hovers, 150ms. NEVER page load animations
1555
+ - Accessibility: WCAG 2.2 AA, contrast \u2265 4.5:1, touch targets \u2265 44px, focus-visible on all interactive
1556
+ - Auth pages (login, signup, etc.) go in app/(auth)/ route group \u2014 no Header/Footer`;
1557
+ var DESIGN_QUALITY2 = `## Design Quality Standards
1640
1558
 
1641
1559
  - Headlines: text-4xl+ font-bold tracking-tight for page titles, text-5xl+ for heroes, text-2xl+ for sections
1642
1560
  - Cards: rounded-xl with border-border/15, ALWAYS hover state: hover:border-border/30 transition-colors
@@ -1646,45 +1564,33 @@ When using a shared component:
1646
1564
  - One accent color per page \u2014 never mix blue + purple + emerald
1647
1565
  - Hero: min-h-[80vh] centered, gradient text on key phrase (from-white to-zinc-500 bg-clip-text text-transparent)
1648
1566
  - Comparison sections: red-400 X for negative, emerald-400 Check for positive
1649
- - Footer: minimal, border-t border-border/10, py-10, text-sm text-muted-foreground
1650
-
1651
- ## Design Tokens
1652
-
1653
- ${tokensSummary}
1654
-
1655
- Use semantic token classes (bg-background, text-foreground, bg-primary, etc.).
1656
- NEVER hardcode colors. NEVER use arbitrary Tailwind values like bg-[#123456].
1657
-
1658
- ## Form Layout Rules
1567
+ - Footer: minimal, border-t border-border/10, py-10, text-sm text-muted-foreground`;
1568
+ var FORMS = `## Form Layout Rules
1659
1569
 
1660
1570
  - Label above Input (never beside on mobile)
1661
1571
  - space-y-2 within field group (label + input + description)
1662
1572
  - space-y-6 between field groups
1663
1573
  - Switch for boolean toggles, not Checkbox
1664
1574
  - Select for 3+ options, Radio for 2-3 options
1665
- - CardFooter for form actions (Save, Cancel)
1666
-
1667
- ## Accessibility (WCAG 2.2 AA)
1575
+ - CardFooter for form actions (Save, Cancel)`;
1576
+ var ACCESSIBILITY = `## Accessibility (WCAG 2.2 AA)
1668
1577
 
1669
1578
  - Text contrast \u2265 4.5:1, UI component contrast \u2265 3:1
1670
1579
  - Touch targets \u2265 44\xD744px (min-h-11 min-w-11)
1671
1580
  - Focus visible on ALL interactive elements (focus-visible:ring-2)
1672
1581
  - Color never the only indicator
1673
1582
  - Every form input must have a Label with htmlFor
1674
- - Heading hierarchy: one h1 per page, no skipped levels
1675
-
1676
- ## Auth Pages
1583
+ - Heading hierarchy: one h1 per page, no skipped levels`;
1584
+ var AUTH = `## Auth Pages
1677
1585
 
1678
1586
  Login, signup, register, forgot-password \u2192 placed in app/(auth)/ route group.
1679
- These pages do NOT show Header/Footer.
1680
-
1681
- ## After Making Changes
1587
+ These pages do NOT show Header/Footer.`;
1588
+ var COMMANDS_SECTION = `## After Making Changes
1682
1589
 
1683
1590
  Run in terminal:
1684
1591
  - coherent check \u2014 show all quality and consistency issues (read-only)
1685
- - coherent fix \u2014 auto-fix cache, deps, syntax, and style issues
1686
-
1687
- ## Platform Overlay (DO NOT TOUCH)
1592
+ - coherent fix \u2014 auto-fix cache, deps, syntax, and style issues`;
1593
+ var PLATFORM = `## Platform Overlay (DO NOT TOUCH)
1688
1594
 
1689
1595
  The following are dev-only platform features, excluded from production export:
1690
1596
  - Floating Design System button (in shared Header component)
@@ -1692,30 +1598,166 @@ The following are dev-only platform features, excluded from production export:
1692
1598
  - /api/design-system/* routes
1693
1599
  - coherent.components.json
1694
1600
 
1695
- DO NOT modify or delete these. They are managed by the platform.
1601
+ DO NOT modify or delete these. They are managed by the platform.`;
1602
+ var COMMANDS_COMPACT = `## After Making Changes
1603
+
1604
+ Run after changes:
1605
+ - coherent check \u2014 show all quality and consistency issues (read-only)
1606
+ - coherent fix \u2014 auto-fix cache, deps, syntax, and style issues`;
1607
+ var PLATFORM_COMPACT = `## Do NOT modify
1608
+
1609
+ - app/design-system/* \u2014 platform overlay
1610
+ - app/api/design-system/* \u2014 platform API routes
1611
+ - coherent.components.json \u2014 managed by platform`;
1612
+ function buildProjectContext(manifest, config2) {
1613
+ return {
1614
+ sharedComponents: buildSharedComponentsList(manifest),
1615
+ sharedComponentsCompact: buildSharedComponentsListCompact(manifest),
1616
+ designTokens: buildDesignTokensSummary(config2),
1617
+ architectureDetailed: ARCHITECTURE_DETAILED,
1618
+ architectureCompact: ARCHITECTURE_COMPACT,
1619
+ rulesDetailed: RULES_DETAILED,
1620
+ rulesCompact: RULES_COMPACT,
1621
+ designQuality: DESIGN_QUALITY2,
1622
+ forms: FORMS,
1623
+ accessibility: ACCESSIBILITY,
1624
+ auth: AUTH,
1625
+ commands: COMMANDS_SECTION,
1626
+ platform: PLATFORM
1627
+ };
1628
+ }
1629
+ function formatForCursor(ctx) {
1630
+ return `# Coherent Design Method \u2014 Project Rules
1631
+ # Auto-generated. Updated when shared components or config change.
1632
+ # Do NOT edit manually \u2014 run \`coherent rules\` to regenerate.
1633
+
1634
+ ${ctx.architectureDetailed}
1635
+
1636
+ ## Shared Components (MUST REUSE)
1637
+
1638
+ Before creating ANY UI block, check if a matching shared component exists below.
1639
+ If it does \u2014 IMPORT and USE it. NEVER recreate inline.
1640
+
1641
+ ${ctx.sharedComponents}
1642
+
1643
+ When using a shared component:
1644
+ - Import from @/components/shared/{filename}
1645
+ - If you need it with different props, use its props interface
1646
+ - If the component doesn't accept the prop you need, add the prop to the shared component and update all existing usages
1647
+
1648
+ ${ctx.rulesDetailed}
1649
+
1650
+ ${ctx.designQuality}
1651
+
1652
+ ## Design Tokens
1653
+
1654
+ ${ctx.designTokens}
1655
+
1656
+ Use semantic token classes (bg-background, text-foreground, bg-primary, etc.).
1657
+ NEVER hardcode colors. NEVER use arbitrary Tailwind values like bg-[#123456].
1658
+
1659
+ ${ctx.forms}
1660
+
1661
+ ${ctx.accessibility}
1662
+
1663
+ ${ctx.auth}
1664
+
1665
+ ${ctx.commands}
1666
+
1667
+ ${ctx.platform}
1668
+ `;
1669
+ }
1670
+ function formatForClaude(ctx) {
1671
+ return `# Coherent Design Method Project
1672
+
1673
+ This is a Coherent Design Method project \u2014 AI-powered multi-page UI prototype with shared component system.
1674
+
1675
+ ${ctx.architectureCompact}
1676
+
1677
+ ## Shared Components (MUST REUSE)
1678
+
1679
+ ${ctx.sharedComponentsCompact}
1680
+
1681
+ Before creating ANY UI block, check if a shared component exists above. If yes \u2014 IMPORT it. NEVER recreate inline.
1682
+
1683
+ ${ctx.rulesCompact}
1684
+
1685
+ ## Design Tokens
1686
+
1687
+ ${ctx.designTokens}
1688
+
1689
+ Use semantic token classes (bg-background, text-foreground, bg-primary, etc.).
1690
+ NEVER hardcode colors. NEVER use arbitrary Tailwind values like bg-[#123456].
1691
+
1692
+ ${COMMANDS_COMPACT}
1693
+
1694
+ ${PLATFORM_COMPACT}
1696
1695
  `;
1697
1696
  }
1698
- async function writeCursorRules(projectRoot) {
1697
+ function formatForAgents(ctx) {
1698
+ return `# Project Conventions
1699
+ # Auto-generated by Coherent. Run \`coherent rules\` to regenerate.
1700
+
1701
+ ${ctx.architectureDetailed}
1702
+
1703
+ ## Shared Components (MUST REUSE)
1704
+
1705
+ Before creating ANY UI block, check if a matching shared component exists below.
1706
+ If it does \u2014 IMPORT and USE it. NEVER recreate inline.
1707
+
1708
+ ${ctx.sharedComponents}
1709
+
1710
+ When using a shared component:
1711
+ - Import from @/components/shared/{filename}
1712
+ - If you need it with different props, use its props interface
1713
+ - If the component doesn't accept the prop you need, add the prop to the shared component and update all existing usages
1714
+
1715
+ ${ctx.rulesDetailed}
1716
+
1717
+ ${ctx.designQuality}
1718
+
1719
+ ## Design Tokens
1720
+
1721
+ ${ctx.designTokens}
1722
+
1723
+ Use semantic token classes (bg-background, text-foreground, bg-primary, etc.).
1724
+ NEVER hardcode colors. NEVER use arbitrary Tailwind values like bg-[#123456].
1725
+
1726
+ ${ctx.forms}
1727
+
1728
+ ${ctx.accessibility}
1729
+
1730
+ ${ctx.auth}
1731
+
1732
+ ${ctx.commands}
1733
+
1734
+ ${ctx.platform}
1735
+ `;
1736
+ }
1737
+ async function writeAllHarnessFiles(projectRoot) {
1699
1738
  let manifest;
1700
1739
  try {
1701
- manifest = await loadManifest2(projectRoot);
1740
+ manifest = await loadManifest(projectRoot);
1702
1741
  } catch {
1703
1742
  manifest = { shared: [], nextId: 1 };
1704
1743
  }
1705
1744
  let config2 = null;
1706
1745
  const configPath = join2(projectRoot, "design-system.config.ts");
1707
- if (existsSync3(configPath)) {
1746
+ if (existsSync2(configPath)) {
1708
1747
  try {
1709
- const dsm = new DesignSystemManager2(configPath);
1748
+ const dsm = new DesignSystemManager(configPath);
1710
1749
  await dsm.load();
1711
1750
  config2 = dsm.getConfig();
1712
1751
  } catch {
1713
1752
  }
1714
1753
  }
1715
- const content = buildCursorRules(manifest, config2);
1716
- const outPath = join2(projectRoot, ".cursorrules");
1717
- writeFileSync3(outPath, content, "utf-8");
1718
- writeClaudeMd(projectRoot, manifest, config2);
1754
+ const ctx = buildProjectContext(manifest, config2);
1755
+ writeFileSync3(join2(projectRoot, ".cursorrules"), formatForCursor(ctx), "utf-8");
1756
+ writeFileSync3(join2(projectRoot, "CLAUDE.md"), formatForClaude(ctx), "utf-8");
1757
+ writeFileSync3(join2(projectRoot, "AGENTS.md"), formatForAgents(ctx), "utf-8");
1758
+ writeClaudeCommands(projectRoot);
1759
+ writeClaudeSkills(projectRoot);
1760
+ writeClaudeSettings(projectRoot);
1719
1761
  const tokenKeys = config2?.tokens ? [
1720
1762
  ...Object.keys(config2.tokens.colors?.light ?? {}),
1721
1763
  ...Object.keys(config2.tokens.colors?.dark ?? {}),
@@ -1728,19 +1770,19 @@ async function writeCursorRules(projectRoot) {
1728
1770
  tokenKeys: tokenKeys || void 0
1729
1771
  };
1730
1772
  }
1731
- async function regenerateCursorRules() {
1773
+ async function regenerateAllHarnessFiles() {
1732
1774
  const project = findConfig();
1733
1775
  if (!project) {
1734
1776
  return { written: false };
1735
1777
  }
1736
- return writeCursorRules(project.root);
1778
+ return writeAllHarnessFiles(project.root);
1737
1779
  }
1738
1780
 
1739
1781
  // src/commands/init.ts
1740
1782
  import { cwd } from "process";
1741
1783
  function hasNextInPackageJson(projectPath) {
1742
1784
  const pkgPath = join3(projectPath, "package.json");
1743
- if (!existsSync4(pkgPath)) return false;
1785
+ if (!existsSync3(pkgPath)) return false;
1744
1786
  try {
1745
1787
  const json = JSON.parse(readFileSync2(pkgPath, "utf-8"));
1746
1788
  const deps = { ...json.dependencies, ...json.devDependencies };
@@ -1753,7 +1795,7 @@ function cleanConflictingFiles(projectPath) {
1753
1795
  const conflicts = [".next", ".coherent", ".cursorrules", ".eslintrc.json", "CLAUDE.md", ".claude", ".vscode"];
1754
1796
  for (const name of conflicts) {
1755
1797
  const fullPath = join3(projectPath, name);
1756
- if (existsSync4(fullPath)) {
1798
+ if (existsSync3(fullPath)) {
1757
1799
  rmSync(fullPath, { recursive: true, force: true });
1758
1800
  }
1759
1801
  }
@@ -1761,12 +1803,12 @@ function cleanConflictingFiles(projectPath) {
1761
1803
  function runCreateNextApp(projectPath) {
1762
1804
  cleanConflictingFiles(projectPath);
1763
1805
  const envPath = join3(projectPath, ".env");
1764
- const envBackup = existsSync4(envPath) ? readFileSync2(envPath, "utf-8") : null;
1806
+ const envBackup = existsSync3(envPath) ? readFileSync2(envPath, "utf-8") : null;
1765
1807
  if (envBackup !== null) rmSync(envPath, { force: true });
1766
1808
  const cmd = "npx --yes create-next-app@15.2.4 . --typescript --tailwind --eslint --app --no-src-dir --no-turbopack --yes";
1767
1809
  execSync(cmd, { cwd: projectPath, stdio: "inherit" });
1768
1810
  if (envBackup !== null) {
1769
- const existing = existsSync4(envPath) ? readFileSync2(envPath, "utf-8") : "";
1811
+ const existing = existsSync3(envPath) ? readFileSync2(envPath, "utf-8") : "";
1770
1812
  writeFileSync4(envPath, existing ? existing + "\n" + envBackup : envBackup, "utf-8");
1771
1813
  }
1772
1814
  }
@@ -1774,8 +1816,8 @@ async function ensureCoherentPrerequisites(projectPath) {
1774
1816
  const libPath = join3(projectPath, "lib");
1775
1817
  const utilsPath = join3(projectPath, "lib", "utils.ts");
1776
1818
  const componentsUiPath = join3(projectPath, "components", "ui");
1777
- if (!existsSync4(utilsPath)) {
1778
- if (!existsSync4(libPath)) mkdirSync3(libPath, { recursive: true });
1819
+ if (!existsSync3(utilsPath)) {
1820
+ if (!existsSync3(libPath)) mkdirSync3(libPath, { recursive: true });
1779
1821
  const cnContent = `import { type ClassValue, clsx } from 'clsx'
1780
1822
  import { twMerge } from 'tailwind-merge'
1781
1823
 
@@ -1785,7 +1827,7 @@ export function cn(...inputs: ClassValue[]) {
1785
1827
  `;
1786
1828
  await writeFile(utilsPath, cnContent);
1787
1829
  }
1788
- if (!existsSync4(componentsUiPath)) mkdirSync3(componentsUiPath, { recursive: true });
1830
+ if (!existsSync3(componentsUiPath)) mkdirSync3(componentsUiPath, { recursive: true });
1789
1831
  }
1790
1832
  async function ensureRegistryComponents(config2, projectPath) {
1791
1833
  const provider = getComponentProvider();
@@ -1793,12 +1835,12 @@ async function ensureRegistryComponents(config2, projectPath) {
1793
1835
  await provider.installBatch(baseComponents, projectPath);
1794
1836
  const generator = new ComponentGenerator(config2);
1795
1837
  const uiDir = join3(projectPath, "components", "ui");
1796
- if (!existsSync4(uiDir)) mkdirSync3(uiDir, { recursive: true });
1838
+ if (!existsSync3(uiDir)) mkdirSync3(uiDir, { recursive: true });
1797
1839
  for (const comp of config2.components) {
1798
1840
  if (comp.source === "shadcn") continue;
1799
1841
  const fileName = toKebabCase(comp.name) + ".tsx";
1800
1842
  const filePath = join3(uiDir, fileName);
1801
- if (existsSync4(filePath)) continue;
1843
+ if (existsSync3(filePath)) continue;
1802
1844
  const code = await generator.generate(comp);
1803
1845
  await writeFile(filePath, code);
1804
1846
  }
@@ -1827,7 +1869,7 @@ async function initCommand(name) {
1827
1869
  process.exit(1);
1828
1870
  }
1829
1871
  const targetDir = join3(cwd(), name);
1830
- if (!existsSync4(targetDir)) {
1872
+ if (!existsSync3(targetDir)) {
1831
1873
  mkdirSync3(targetDir, { recursive: true });
1832
1874
  }
1833
1875
  process.chdir(targetDir);
@@ -1835,7 +1877,7 @@ async function initCommand(name) {
1835
1877
  let projectPath;
1836
1878
  try {
1837
1879
  projectPath = cwd();
1838
- if (!existsSync4(projectPath)) {
1880
+ if (!existsSync3(projectPath)) {
1839
1881
  throw new Error("ENOENT");
1840
1882
  }
1841
1883
  } catch (err) {
@@ -1901,7 +1943,7 @@ async function initCommand(name) {
1901
1943
  } else {
1902
1944
  try {
1903
1945
  const pkgPath = join3(projectPath, "package.json");
1904
- if (existsSync4(pkgPath)) {
1946
+ if (existsSync3(pkgPath)) {
1905
1947
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
1906
1948
  if (typeof pkg.name === "string" && pkg.name) {
1907
1949
  appName = toTitleCase(pkg.name);
@@ -1996,8 +2038,7 @@ export default config
1996
2038
  { type: "init", description: "Project initialized", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
1997
2039
  ]);
1998
2040
  try {
1999
- await writeCursorRules(projectPath);
2000
- await generateClaudeCodeFiles(projectPath);
2041
+ await writeAllHarnessFiles(projectPath);
2001
2042
  } catch (e) {
2002
2043
  if (process.env.COHERENT_DEBUG === "1") console.error(chalk3.dim("Could not write .cursorrules / CLAUDE.md:"), e);
2003
2044
  }
@@ -2013,9 +2054,9 @@ async function configureNextImages(projectPath) {
2013
2054
  const jsPath = join3(projectPath, "next.config.js");
2014
2055
  const mjsPath = join3(projectPath, "next.config.mjs");
2015
2056
  let configPath = "";
2016
- if (existsSync4(tsPath)) configPath = tsPath;
2017
- else if (existsSync4(mjsPath)) configPath = mjsPath;
2018
- else if (existsSync4(jsPath)) configPath = jsPath;
2057
+ if (existsSync3(tsPath)) configPath = tsPath;
2058
+ else if (existsSync3(mjsPath)) configPath = mjsPath;
2059
+ else if (existsSync3(jsPath)) configPath = jsPath;
2019
2060
  else return;
2020
2061
  const content = `import type { NextConfig } from "next";
2021
2062
 
@@ -2055,14 +2096,14 @@ async function createAppRouteGroupLayout(projectPath) {
2055
2096
  import chalk10 from "chalk";
2056
2097
  import ora2 from "ora";
2057
2098
  import { resolve as resolve5, relative as relative2, join as join6 } from "path";
2058
- import { existsSync as existsSync9, readFileSync as readFileSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
2099
+ import { existsSync as existsSync8, readFileSync as readFileSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
2059
2100
  import {
2060
- DesignSystemManager as DesignSystemManager5,
2101
+ DesignSystemManager as DesignSystemManager4,
2061
2102
  ComponentManager as ComponentManager4,
2062
2103
  PageManager as PageManager2,
2063
2104
  CLI_VERSION as CLI_VERSION2,
2064
2105
  getTemplateForPageType as getTemplateForPageType2,
2065
- loadManifest as loadManifest7,
2106
+ loadManifest as loadManifest6,
2066
2107
  saveManifest as saveManifest3,
2067
2108
  updateEntry
2068
2109
  } from "@getcoherent/core";
@@ -2555,8 +2596,8 @@ function extractComponentSpec(changes) {
2555
2596
  // src/utils/dark-mode.ts
2556
2597
  import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
2557
2598
  import { join as join4 } from "path";
2558
- import { existsSync as existsSync5 } from "fs";
2559
- import { generateSharedComponent, loadManifest as loadManifest3, integrateSharedLayoutIntoRootLayout } from "@getcoherent/core";
2599
+ import { existsSync as existsSync4 } from "fs";
2600
+ import { generateSharedComponent, loadManifest as loadManifest2, integrateSharedLayoutIntoRootLayout } from "@getcoherent/core";
2560
2601
  var THEME_TOGGLE_CODE = `'use client'
2561
2602
 
2562
2603
  import { Moon, Sun } from 'lucide-react'
@@ -2582,7 +2623,7 @@ export function ThemeToggle() {
2582
2623
  `;
2583
2624
  async function setDefaultDarkTheme(projectRoot) {
2584
2625
  const layoutPath = join4(projectRoot, "app", "layout.tsx");
2585
- if (!existsSync5(layoutPath)) return false;
2626
+ if (!existsSync4(layoutPath)) return false;
2586
2627
  let content = await readFile2(layoutPath, "utf-8");
2587
2628
  if (content.includes('<html className="dark"') || content.includes("<html className='dark'")) return true;
2588
2629
  content = content.replace(/<html(\s|>)/, '<html className="dark"$1');
@@ -2590,7 +2631,7 @@ async function setDefaultDarkTheme(projectRoot) {
2590
2631
  return true;
2591
2632
  }
2592
2633
  async function ensureThemeToggle(projectRoot) {
2593
- const manifest = await loadManifest3(projectRoot);
2634
+ const manifest = await loadManifest2(projectRoot);
2594
2635
  const existing = manifest.shared.find((e) => e.name === "ThemeToggle" || e.name.toLowerCase().includes("themetoggle"));
2595
2636
  if (existing) {
2596
2637
  await integrateSharedLayoutIntoRootLayout(projectRoot);
@@ -2610,7 +2651,7 @@ async function ensureThemeToggle(projectRoot) {
2610
2651
  import { appendFile } from "fs/promises";
2611
2652
 
2612
2653
  // src/utils/backup.ts
2613
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync5, readdirSync, rmSync as rmSync2, statSync } from "fs";
2654
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync5, readdirSync, rmSync as rmSync2, statSync } from "fs";
2614
2655
  import { join as join5, relative, dirname as dirname2 } from "path";
2615
2656
  import chalk5 from "chalk";
2616
2657
  var DEBUG = process.env.COHERENT_DEBUG === "1";
@@ -2633,7 +2674,7 @@ function createBackup(projectRoot) {
2633
2674
  let fileCount = 0;
2634
2675
  for (const file of CRITICAL_FILES) {
2635
2676
  const src = join5(projectRoot, file);
2636
- if (existsSync6(src)) {
2677
+ if (existsSync5(src)) {
2637
2678
  const dest = join5(backupPath, file);
2638
2679
  mkdirSync4(dirname2(dest), { recursive: true });
2639
2680
  writeFileSync5(dest, readFileSync3(src));
@@ -2642,7 +2683,7 @@ function createBackup(projectRoot) {
2642
2683
  }
2643
2684
  for (const dir of CRITICAL_DIRS) {
2644
2685
  const srcDir = join5(projectRoot, dir);
2645
- if (!existsSync6(srcDir)) continue;
2686
+ if (!existsSync5(srcDir)) continue;
2646
2687
  backupDirectory(srcDir, projectRoot, backupPath);
2647
2688
  fileCount += countFiles(srcDir);
2648
2689
  }
@@ -2710,12 +2751,12 @@ function pruneOldBackups(backupBase) {
2710
2751
  }
2711
2752
  function listBackups(projectRoot) {
2712
2753
  const backupBase = join5(projectRoot, BACKUP_DIR);
2713
- if (!existsSync6(backupBase)) return [];
2754
+ if (!existsSync5(backupBase)) return [];
2714
2755
  try {
2715
2756
  return readdirSync(backupBase).filter((e) => !e.startsWith(".")).map((name) => {
2716
2757
  const metaPath = join5(backupBase, name, ".backup-meta.json");
2717
2758
  let meta = { timestamp: name, files: 0 };
2718
- if (existsSync6(metaPath)) {
2759
+ if (existsSync5(metaPath)) {
2719
2760
  try {
2720
2761
  meta = JSON.parse(readFileSync3(metaPath, "utf-8"));
2721
2762
  } catch (e) {
@@ -2731,7 +2772,7 @@ function listBackups(projectRoot) {
2731
2772
  }
2732
2773
  function restoreBackup(projectRoot, backupName) {
2733
2774
  const backupPath = join5(projectRoot, BACKUP_DIR, backupName);
2734
- if (!existsSync6(backupPath)) return false;
2775
+ if (!existsSync5(backupPath)) return false;
2735
2776
  try {
2736
2777
  restoreDirectory(backupPath, backupPath, projectRoot);
2737
2778
  return true;
@@ -3209,12 +3250,12 @@ function applyDefaults(request) {
3209
3250
  }
3210
3251
 
3211
3252
  // src/commands/chat/split-generator.ts
3212
- import { existsSync as existsSync7, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
3253
+ import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
3213
3254
  import { resolve as resolve2 } from "path";
3214
3255
  import { z } from "zod";
3215
3256
  import {
3216
3257
  SharedComponentTypeSchema,
3217
- loadManifest as loadManifest4,
3258
+ loadManifest as loadManifest3,
3218
3259
  saveManifest,
3219
3260
  generateSharedComponent as generateSharedComponent2
3220
3261
  } from "@getcoherent/core";
@@ -3660,7 +3701,7 @@ function readExistingAppPageForReference(projectRoot, plan) {
3660
3701
  for (const group of ["(app)", "(admin)", "(dashboard)"]) {
3661
3702
  const filePath = resolve2(projectRoot, "app", group, key, "page.tsx");
3662
3703
  try {
3663
- if (existsSync7(filePath)) {
3704
+ if (existsSync6(filePath)) {
3664
3705
  const code = readFileSync4(filePath, "utf-8");
3665
3706
  const lines = code.split("\n");
3666
3707
  return lines.slice(0, 60).join("\n");
@@ -3672,7 +3713,7 @@ function readExistingAppPageForReference(projectRoot, plan) {
3672
3713
  }
3673
3714
  }
3674
3715
  const appDir = resolve2(projectRoot, "app");
3675
- if (!existsSync7(appDir)) return null;
3716
+ if (!existsSync6(appDir)) return null;
3676
3717
  try {
3677
3718
  const entries = readdirSync2(appDir);
3678
3719
  for (const entry of entries) {
@@ -3682,7 +3723,7 @@ function readExistingAppPageForReference(projectRoot, plan) {
3682
3723
  const subDirs = readdirSync2(groupDir);
3683
3724
  for (const sub of subDirs) {
3684
3725
  const pagePath = resolve2(groupDir, sub, "page.tsx");
3685
- if (existsSync7(pagePath)) {
3726
+ if (existsSync6(pagePath)) {
3686
3727
  const code = readFileSync4(pagePath, "utf-8");
3687
3728
  const lines = code.split("\n");
3688
3729
  return lines.slice(0, 60).join("\n");
@@ -3728,7 +3769,7 @@ var manifestLock = Promise.resolve();
3728
3769
  async function updateManifestSafe(projectRoot, fn) {
3729
3770
  const timeoutMs = 5e3;
3730
3771
  const update = manifestLock.then(async () => {
3731
- const m = await loadManifest4(projectRoot);
3772
+ const m = await loadManifest3(projectRoot);
3732
3773
  const updated = fn(m);
3733
3774
  await saveManifest(projectRoot, updated);
3734
3775
  });
@@ -3908,7 +3949,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
3908
3949
  await createAIProvider(provider ?? "auto")
3909
3950
  );
3910
3951
  if (generated.length > 0) {
3911
- const updatedManifest = await loadManifest4(projectRoot);
3952
+ const updatedManifest = await loadManifest3(projectRoot);
3912
3953
  parseOpts.sharedComponentsSummary = buildSharedComponentsSummary(updatedManifest);
3913
3954
  const names = generated.map((c) => c.name).join(", ");
3914
3955
  spinner.succeed(`Phase 4.5/6 \u2014 Generated ${generated.length} shared components (${names})`);
@@ -3919,7 +3960,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
3919
3960
  spinner.warn("Phase 4.5/6 \u2014 Could not generate shared components (continuing without)");
3920
3961
  }
3921
3962
  } else if (homePageCode) {
3922
- const manifest = await loadManifest4(projectRoot);
3963
+ const manifest = await loadManifest3(projectRoot);
3923
3964
  const shouldSkip = reusedExistingAnchor && manifest.shared.some((e) => e.type !== "layout");
3924
3965
  if (!shouldSkip) {
3925
3966
  spinner.start("Phase 4.5/6 \u2014 Extracting shared components (legacy)...");
@@ -3943,7 +3984,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
3943
3984
  }
3944
3985
  spinner.start(`Phase 5/6 \u2014 Generating ${remainingPages.length} pages in parallel...`);
3945
3986
  const sharedComponentsNote = buildSharedComponentsNote(parseOpts.sharedComponentsSummary);
3946
- const currentManifest = projectRoot ? await loadManifest4(projectRoot) : null;
3987
+ const currentManifest = projectRoot ? await loadManifest3(projectRoot) : null;
3947
3988
  const routeNote = `EXISTING ROUTES in this project: ${allRoutes}. All internal links MUST point to one of these routes. If a target doesn't exist, use href="#".`;
3948
3989
  const alignmentNote = 'CRITICAL LAYOUT RULE: Every <section> must wrap its content in a container div matching the header width. Use the EXACT same container classes as shown in the style context (e.g. className="container max-w-6xl px-4" or className="max-w-6xl mx-auto px-4"). Inner content can use narrower max-w for text centering, but the outer section container MUST match.';
3949
3990
  const existingAppPageCode = readExistingAppPageForReference(parseOpts?.projectRoot ?? null, plan);
@@ -3957,7 +3998,7 @@ ${existingAppPageCode}
3957
3998
  const existingPageCode = {};
3958
3999
  if (projectRoot) {
3959
4000
  const appDir = resolve2(projectRoot, "app");
3960
- if (existsSync7(appDir)) {
4001
+ if (existsSync6(appDir)) {
3961
4002
  const pageFiles = readdirSync2(appDir, { recursive: true }).filter(
3962
4003
  (f) => typeof f === "string" && f.endsWith("page.tsx")
3963
4004
  );
@@ -4144,7 +4185,7 @@ var SharedExtractionResponseSchema = z.object({
4144
4185
  components: z.array(SharedExtractionItemSchema).max(5).default([])
4145
4186
  });
4146
4187
  async function extractSharedComponents(homePageCode, projectRoot, aiProvider) {
4147
- const manifest = await loadManifest4(projectRoot);
4188
+ const manifest = await loadManifest3(projectRoot);
4148
4189
  let ai;
4149
4190
  try {
4150
4191
  ai = await createAIProvider(aiProvider);
@@ -4199,7 +4240,7 @@ async function extractSharedComponents(homePageCode, projectRoot, aiProvider) {
4199
4240
  } catch {
4200
4241
  }
4201
4242
  }
4202
- const updatedManifest = await loadManifest4(projectRoot);
4243
+ const updatedManifest = await loadManifest3(projectRoot);
4203
4244
  return { components: results, summary: buildSharedComponentsSummary(updatedManifest) };
4204
4245
  }
4205
4246
  function extractAppNameFromPrompt(prompt) {
@@ -4249,7 +4290,7 @@ import { dirname as dirname3 } from "path";
4249
4290
  import chalk8 from "chalk";
4250
4291
  import {
4251
4292
  getTemplateForPageType,
4252
- loadManifest as loadManifest5,
4293
+ loadManifest as loadManifest4,
4253
4294
  saveManifest as saveManifest2,
4254
4295
  updateUsedIn,
4255
4296
  findSharedComponentByIdOrName,
@@ -4664,7 +4705,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
4664
4705
  postFixes: fixes
4665
4706
  });
4666
4707
  try {
4667
- await writeCursorRules(projectRoot);
4708
+ await writeAllHarnessFiles(projectRoot);
4668
4709
  } catch {
4669
4710
  }
4670
4711
  return {
@@ -4731,7 +4772,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
4731
4772
  fixes.forEach((f) => console.log(chalk8.dim(` ${f}`)));
4732
4773
  }
4733
4774
  await writeFile(pageFilePath, fixedCode);
4734
- const manifest = await loadManifest5(projectRoot);
4775
+ const manifest = await loadManifest4(projectRoot);
4735
4776
  const usedIn = manifest.shared.find((e) => e.id === resolved.id)?.usedIn ?? [];
4736
4777
  const filePathRel = routeToRelPath(route, readPlan || isAuthRoute(route));
4737
4778
  if (!usedIn.includes(filePathRel)) {
@@ -4746,7 +4787,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
4746
4787
  postFixes: fixes
4747
4788
  });
4748
4789
  try {
4749
- await writeCursorRules(projectRoot);
4790
+ await writeAllHarnessFiles(projectRoot);
4750
4791
  } catch {
4751
4792
  }
4752
4793
  return {
@@ -4833,7 +4874,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
4833
4874
  await writeFile(fullPath, fixedCode);
4834
4875
  usedInFiles.push(relPath);
4835
4876
  }
4836
- const manifest = await loadManifest5(projectRoot);
4877
+ const manifest = await loadManifest4(projectRoot);
4837
4878
  const nextManifest = updateUsedIn(manifest, created.id, usedInFiles);
4838
4879
  await saveManifest2(projectRoot, nextManifest);
4839
4880
  printPromoteAndLinkReport({
@@ -4843,7 +4884,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
4843
4884
  usedInFiles
4844
4885
  });
4845
4886
  try {
4846
- await writeCursorRules(projectRoot);
4887
+ await writeAllHarnessFiles(projectRoot);
4847
4888
  } catch {
4848
4889
  }
4849
4890
  return {
@@ -5089,7 +5130,7 @@ Keep all existing functionality intact.`,
5089
5130
  cm.updateConfig(cfg);
5090
5131
  pm.updateConfig(cfg);
5091
5132
  }
5092
- const manifestForAudit = await loadManifest5(projectRoot);
5133
+ const manifestForAudit = await loadManifest4(projectRoot);
5093
5134
  const planForAudit = loadPlan(projectRoot);
5094
5135
  await warnInlineDuplicates(
5095
5136
  projectRoot,
@@ -5320,7 +5361,7 @@ ${pagesCtx}`
5320
5361
  cm.updateConfig(cfg);
5321
5362
  pm.updateConfig(cfg);
5322
5363
  }
5323
- const manifestForAudit = await loadManifest5(projectRoot);
5364
+ const manifestForAudit = await loadManifest4(projectRoot);
5324
5365
  const planForAudit2 = loadPlan(projectRoot);
5325
5366
  await warnInlineDuplicates(
5326
5367
  projectRoot,
@@ -5419,7 +5460,7 @@ Rules:
5419
5460
  fixes.forEach((f) => console.log(chalk8.dim(` ${f}`)));
5420
5461
  }
5421
5462
  const relFilePath = routeToRelPath(route, isAuth);
5422
- const manifest = await loadManifest5(projectRoot);
5463
+ const manifest = await loadManifest4(projectRoot);
5423
5464
  printPostGenerationReport({
5424
5465
  action: "updated",
5425
5466
  pageTitle: pageDef.name || pageDef.id || "Page",
@@ -5563,8 +5604,8 @@ function hasNavChanged(before, after) {
5563
5604
  // src/commands/chat/interactive.ts
5564
5605
  import chalk9 from "chalk";
5565
5606
  import { resolve as resolve4 } from "path";
5566
- import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5 } from "fs";
5567
- import { DesignSystemManager as DesignSystemManager4, ComponentManager as ComponentManager3, loadManifest as loadManifest6 } from "@getcoherent/core";
5607
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5 } from "fs";
5608
+ import { DesignSystemManager as DesignSystemManager3, ComponentManager as ComponentManager3, loadManifest as loadManifest5 } from "@getcoherent/core";
5568
5609
  var DEBUG3 = process.env.COHERENT_DEBUG === "1";
5569
5610
  async function interactiveChat(options, chatCommandFn) {
5570
5611
  const { createInterface } = await import("readline");
@@ -5573,7 +5614,7 @@ async function interactiveChat(options, chatCommandFn) {
5573
5614
  const projectRoot = project.root;
5574
5615
  const configPath = project.configPath;
5575
5616
  const config2 = await loadConfig(configPath);
5576
- const dsm = new DesignSystemManager4(configPath);
5617
+ const dsm = new DesignSystemManager3(configPath);
5577
5618
  await dsm.load();
5578
5619
  const cm = new ComponentManager3(config2);
5579
5620
  const validProviders = ["claude", "openai", "auto"];
@@ -5588,7 +5629,7 @@ async function interactiveChat(options, chatCommandFn) {
5588
5629
  let history = [];
5589
5630
  try {
5590
5631
  mkdirSync5(historyDir, { recursive: true });
5591
- if (existsSync8(historyFile)) {
5632
+ if (existsSync7(historyFile)) {
5592
5633
  history = readFileSync5(historyFile, "utf-8").split("\n").filter(Boolean).slice(-200);
5593
5634
  }
5594
5635
  } catch (e) {
@@ -5634,7 +5675,7 @@ async function interactiveChat(options, chatCommandFn) {
5634
5675
  return;
5635
5676
  }
5636
5677
  if (lower === "components" || lower === "list components" || lower.includes("what components")) {
5637
- const manifest = await loadManifest6(projectRoot);
5678
+ const manifest = await loadManifest5(projectRoot);
5638
5679
  if (manifest.shared.length === 0) {
5639
5680
  console.log(chalk9.gray("\n No shared components yet.\n"));
5640
5681
  } else {
@@ -5676,7 +5717,7 @@ async function interactiveChat(options, chatCommandFn) {
5676
5717
  }
5677
5718
  if (lower === "status") {
5678
5719
  const currentConfig = dsm.getConfig();
5679
- const manifest = await loadManifest6(projectRoot);
5720
+ const manifest = await loadManifest5(projectRoot);
5680
5721
  console.log(chalk9.bold(`
5681
5722
  ${currentConfig.name || "Coherent Project"}`));
5682
5723
  console.log(
@@ -5768,7 +5809,7 @@ async function chatCommand(message, options) {
5768
5809
  const projectRoot = project.root;
5769
5810
  const configPath = project.configPath;
5770
5811
  const migrationGuard = join6(projectRoot, ".coherent", "migration-in-progress");
5771
- if (existsSync9(migrationGuard)) {
5812
+ if (existsSync8(migrationGuard)) {
5772
5813
  spinner.fail("Migration in progress");
5773
5814
  console.error(chalk10.red("\n\u274C A migration is in progress. Run `coherent migrate --rollback` to undo first."));
5774
5815
  bail("Migration in progress");
@@ -5807,7 +5848,7 @@ async function chatCommand(message, options) {
5807
5848
  spinner.text = "Loading design system configuration...";
5808
5849
  }
5809
5850
  const storedHashes = await loadHashes(projectRoot);
5810
- const dsm = new DesignSystemManager5(configPath);
5851
+ const dsm = new DesignSystemManager4(configPath);
5811
5852
  await dsm.load();
5812
5853
  const cm = new ComponentManager4(config2);
5813
5854
  const pm = new PageManager2(config2, cm);
@@ -5857,7 +5898,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
5857
5898
  async (p) => JSON.stringify(await aiProvider.generateJSON("You are a component classifier.", p))
5858
5899
  );
5859
5900
  if (classifications.length > 0) {
5860
- let manifest2 = await loadManifest7(projectRoot);
5901
+ let manifest2 = await loadManifest6(projectRoot);
5861
5902
  manifest2 = updateEntry(manifest2, genResult.id, {
5862
5903
  type: classifications[0].type,
5863
5904
  description: classifications[0].description || message
@@ -5923,10 +5964,10 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
5923
5964
  }
5924
5965
  }
5925
5966
  spinner.start("Parsing your request...");
5926
- let manifest = await loadManifest7(project.root);
5967
+ let manifest = await loadManifest6(project.root);
5927
5968
  const validShared = manifest.shared.filter((s) => {
5928
5969
  const fp = resolve5(project.root, s.file);
5929
- return existsSync9(fp);
5970
+ return existsSync8(fp);
5930
5971
  });
5931
5972
  if (validShared.length !== manifest.shared.length) {
5932
5973
  const cleaned = manifest.shared.length - validShared.length;
@@ -5995,7 +6036,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
5995
6036
  } else {
5996
6037
  let reusePlanDirective;
5997
6038
  try {
5998
- const singlePageManifest = await loadManifest7(projectRoot);
6039
+ const singlePageManifest = await loadManifest6(projectRoot);
5999
6040
  if (singlePageManifest.shared.length > 0) {
6000
6041
  const reusePlan = buildReusePlan({
6001
6042
  pageName: "page",
@@ -6147,7 +6188,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6147
6188
  for (const entry of manifest.shared) {
6148
6189
  try {
6149
6190
  const sharedPath = resolve5(projectRoot, entry.file);
6150
- if (existsSync9(sharedPath)) {
6191
+ if (existsSync8(sharedPath)) {
6151
6192
  const sharedCode = readFileSync6(sharedPath, "utf-8");
6152
6193
  const sharedImports = sharedCode.matchAll(/@\/components\/ui\/([a-z0-9-]+)/g);
6153
6194
  for (const m of sharedImports) {
@@ -6169,7 +6210,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6169
6210
  for (const componentId of allNeededComponentIds) {
6170
6211
  const isRegistered = !!cm.read(componentId);
6171
6212
  const filePath = join6(projectRoot, "components", "ui", `${componentId}.tsx`);
6172
- const fileExists = existsSync9(filePath);
6213
+ const fileExists = existsSync8(filePath);
6173
6214
  if (DEBUG4) console.log(chalk10.gray(` Checking ${componentId}: registered=${isRegistered} file=${fileExists}`));
6174
6215
  if (!isRegistered || !fileExists) {
6175
6216
  missingComponents.push(componentId);
@@ -6288,7 +6329,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6288
6329
  try {
6289
6330
  const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
6290
6331
  const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-HGNEY3W3.js");
6291
- const manifest2 = await loadManifest7(projectRoot);
6332
+ const manifest2 = await loadManifest6(projectRoot);
6292
6333
  const reuseplan = projectRoot ? loadPlan(projectRoot) : null;
6293
6334
  if (manifest2.shared.length > 0) {
6294
6335
  for (const request of normalizedRequests) {
@@ -6318,7 +6359,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6318
6359
  const route = page.route || `/${page.id || "page"}`;
6319
6360
  const pageFilePath = routeToFsPath(projectRoot, route, false);
6320
6361
  let pageCode = "";
6321
- if (existsSync9(pageFilePath)) {
6362
+ if (existsSync8(pageFilePath)) {
6322
6363
  try {
6323
6364
  pageCode = readFileSync6(pageFilePath, "utf-8");
6324
6365
  } catch {
@@ -6340,8 +6381,8 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6340
6381
  }
6341
6382
  const missingRoutes = [...allLinkedRoutes].filter((route) => {
6342
6383
  if (expandedExisting.has(route)) return false;
6343
- if (existsSync9(routeToFsPath(projectRoot, route, false))) return false;
6344
- if (existsSync9(routeToFsPath(projectRoot, route, true))) return false;
6384
+ if (existsSync8(routeToFsPath(projectRoot, route, false))) return false;
6385
+ if (existsSync8(routeToFsPath(projectRoot, route, true))) return false;
6345
6386
  return true;
6346
6387
  });
6347
6388
  const SCAFFOLD_AI_LIMIT = 10;
@@ -6406,7 +6447,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6406
6447
  const filePath = routeToFsPath(projectRoot, linkedRoute, isAuth);
6407
6448
  if (isAuth) await ensureAuthRouteGroup(projectRoot);
6408
6449
  const dir = resolve5(filePath, "..");
6409
- if (!existsSync9(dir)) {
6450
+ if (!existsSync8(dir)) {
6410
6451
  mkdirSync6(dir, { recursive: true });
6411
6452
  }
6412
6453
  const placeholderCode = `export default function ${pageName.replace(/\s/g, "")}Page() {
@@ -6523,13 +6564,13 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6523
6564
  const sharedDir = resolve5(projectRoot, "components", "shared");
6524
6565
  const layoutFile = resolve5(projectRoot, "app", "layout.tsx");
6525
6566
  const filesToHash = [layoutFile];
6526
- if (existsSync9(sharedDir)) {
6567
+ if (existsSync8(sharedDir)) {
6527
6568
  for (const f of readdirSync3(sharedDir)) {
6528
6569
  if (f.endsWith(".tsx")) filesToHash.push(resolve5(sharedDir, f));
6529
6570
  }
6530
6571
  }
6531
6572
  for (const filePath of filesToHash) {
6532
- if (existsSync9(filePath)) {
6573
+ if (existsSync8(filePath)) {
6533
6574
  const rel = relative2(projectRoot, filePath);
6534
6575
  updatedHashes[rel] = await computeFileHash(filePath);
6535
6576
  }
@@ -6540,11 +6581,11 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6540
6581
  }
6541
6582
  try {
6542
6583
  const { extractPropsInterface, extractDependencies, extractUsageExample } = await import("./component-extractor-VYJLT5NR.js");
6543
- let currentManifest = await loadManifest7(projectRoot);
6584
+ let currentManifest = await loadManifest6(projectRoot);
6544
6585
  let manifestChanged = false;
6545
6586
  for (const entry of currentManifest.shared) {
6546
6587
  const fullPath = resolve5(projectRoot, entry.file);
6547
- if (!existsSync9(fullPath)) continue;
6588
+ if (!existsSync8(fullPath)) continue;
6548
6589
  const code = readFileSync6(fullPath, "utf-8");
6549
6590
  const props = extractPropsInterface(code);
6550
6591
  const deps = extractDependencies(code);
@@ -6559,7 +6600,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6559
6600
  const pageFiles = Array.from(allModified).filter((f) => f.startsWith("app/") && f.endsWith("page.tsx"));
6560
6601
  for (const pageFile of pageFiles) {
6561
6602
  const fullPath = resolve5(projectRoot, pageFile);
6562
- if (!existsSync9(fullPath)) continue;
6603
+ if (!existsSync8(fullPath)) continue;
6563
6604
  const pageCode = readFileSync6(fullPath, "utf-8");
6564
6605
  for (const entry of currentManifest.shared) {
6565
6606
  const isUsed = pageCode.includes(`from '@/components/shared/`) && (pageCode.includes(`{ ${entry.name} }`) || pageCode.includes(`{ ${entry.name},`));
@@ -6617,7 +6658,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6617
6658
  ${uxRecommendations}
6618
6659
  `;
6619
6660
  try {
6620
- if (!existsSync9(recPath)) {
6661
+ if (!existsSync8(recPath)) {
6621
6662
  await writeFile(
6622
6663
  recPath,
6623
6664
  "# UX/UI Recommendations\n\nRecommendations are added here when you use `coherent chat` and the AI suggests improvements.\n"
@@ -6691,7 +6732,7 @@ ${uxRecommendations}
6691
6732
  import chalk11 from "chalk";
6692
6733
  import ora3 from "ora";
6693
6734
  import { spawn } from "child_process";
6694
- import { existsSync as existsSync12, rmSync as rmSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync8, readdirSync as readdirSync5 } from "fs";
6735
+ import { existsSync as existsSync11, rmSync as rmSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync8, readdirSync as readdirSync5 } from "fs";
6695
6736
  import { resolve as resolve6, join as join9 } from "path";
6696
6737
  import { readdir } from "fs/promises";
6697
6738
 
@@ -6744,15 +6785,15 @@ function validateV4GlobalsCss(css) {
6744
6785
  }
6745
6786
 
6746
6787
  // src/commands/preview.ts
6747
- import { DesignSystemManager as DesignSystemManager6, ComponentGenerator as ComponentGenerator2 } from "@getcoherent/core";
6788
+ import { DesignSystemManager as DesignSystemManager5, ComponentGenerator as ComponentGenerator2 } from "@getcoherent/core";
6748
6789
 
6749
6790
  // src/utils/file-watcher.ts
6750
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync11 } from "fs";
6791
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync10 } from "fs";
6751
6792
  import { relative as relative4, join as join8 } from "path";
6752
- import { loadManifest as loadManifest8, saveManifest as saveManifest4 } from "@getcoherent/core";
6793
+ import { loadManifest as loadManifest7, saveManifest as saveManifest4 } from "@getcoherent/core";
6753
6794
 
6754
6795
  // src/utils/component-integrity.ts
6755
- import { existsSync as existsSync10, readFileSync as readFileSync7, readdirSync as readdirSync4 } from "fs";
6796
+ import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync4 } from "fs";
6756
6797
  import { join as join7, relative as relative3 } from "path";
6757
6798
  function extractExportedComponentNames(code) {
6758
6799
  const names = [];
@@ -6786,7 +6827,7 @@ function arraysEqual(a, b) {
6786
6827
  function findPagesImporting(projectRoot, componentName, componentFile) {
6787
6828
  const results = [];
6788
6829
  const appDir = join7(projectRoot, "app");
6789
- if (!existsSync10(appDir)) return results;
6830
+ if (!existsSync9(appDir)) return results;
6790
6831
  const pageFiles = collectFiles(appDir, (name) => name === "page.tsx" || name === "page.jsx");
6791
6832
  const componentImportPath = componentFile.replace(/\.tsx$/, "").replace(/\.jsx$/, "");
6792
6833
  for (const absPath of pageFiles) {
@@ -6807,7 +6848,7 @@ function findPagesImporting(projectRoot, componentName, componentFile) {
6807
6848
  function isUsedInLayout(projectRoot, componentName) {
6808
6849
  const appDir = join7(projectRoot, "app");
6809
6850
  const layoutPaths = [join7(appDir, "layout.tsx")];
6810
- if (existsSync10(appDir)) {
6851
+ if (existsSync9(appDir)) {
6811
6852
  try {
6812
6853
  for (const entry of readdirSync4(appDir, { withFileTypes: true })) {
6813
6854
  if (entry.isDirectory() && entry.name.startsWith("(") && entry.name.endsWith(")")) {
@@ -6831,7 +6872,7 @@ function isUsedInLayout(projectRoot, componentName) {
6831
6872
  function findUnregisteredComponents(projectRoot, manifest) {
6832
6873
  const results = [];
6833
6874
  const componentsDir = join7(projectRoot, "components");
6834
- if (!existsSync10(componentsDir)) return results;
6875
+ if (!existsSync9(componentsDir)) return results;
6835
6876
  const registeredFiles = new Set(manifest.shared.map((s) => s.file));
6836
6877
  const registeredNames = new Set(manifest.shared.map((s) => s.name));
6837
6878
  const files = collectFiles(
@@ -6859,7 +6900,7 @@ function findUnregisteredComponents(projectRoot, manifest) {
6859
6900
  function findInlineDuplicates(projectRoot, manifest) {
6860
6901
  const results = [];
6861
6902
  const appDir = join7(projectRoot, "app");
6862
- if (!existsSync10(appDir)) return results;
6903
+ if (!existsSync9(appDir)) return results;
6863
6904
  const pageFiles = collectFiles(appDir, (name) => name === "page.tsx" || name === "page.jsx");
6864
6905
  for (const absPath of pageFiles) {
6865
6906
  if (absPath.includes("design-system")) continue;
@@ -6889,7 +6930,7 @@ function findInlineDuplicates(projectRoot, manifest) {
6889
6930
  }
6890
6931
  function findComponentFileByExportName(projectRoot, componentName) {
6891
6932
  const componentsDir = join7(projectRoot, "components");
6892
- if (!existsSync10(componentsDir)) return null;
6933
+ if (!existsSync9(componentsDir)) return null;
6893
6934
  const files = collectFiles(
6894
6935
  componentsDir,
6895
6936
  (name) => (name.endsWith(".tsx") || name.endsWith(".jsx")) && !name.startsWith("."),
@@ -6911,7 +6952,7 @@ function removeOrphanedEntries(projectRoot, manifest) {
6911
6952
  const removed = [];
6912
6953
  const valid = manifest.shared.filter((entry) => {
6913
6954
  const filePath = join7(projectRoot, entry.file);
6914
- if (existsSync10(filePath)) return true;
6955
+ if (existsSync9(filePath)) return true;
6915
6956
  removed.push({ id: entry.id, name: entry.name });
6916
6957
  return false;
6917
6958
  });
@@ -6930,7 +6971,7 @@ function reconcileComponents(projectRoot, manifest) {
6930
6971
  const m = { ...manifest, shared: [...manifest.shared], nextId: manifest.nextId };
6931
6972
  m.shared = m.shared.filter((entry) => {
6932
6973
  const filePath = join7(projectRoot, entry.file);
6933
- if (!existsSync10(filePath)) {
6974
+ if (!existsSync9(filePath)) {
6934
6975
  const newPath = findComponentFileByExportName(projectRoot, entry.name);
6935
6976
  if (newPath) {
6936
6977
  result.updated.push({ id: entry.id, field: "file", from: entry.file, to: newPath });
@@ -7066,7 +7107,7 @@ function findInlineDuplicatesOfShared(content, manifest) {
7066
7107
  function getWatcherConfig(projectRoot) {
7067
7108
  try {
7068
7109
  const pkgPath = join8(projectRoot, "package.json");
7069
- if (!existsSync11(pkgPath)) return defaultWatcherConfig();
7110
+ if (!existsSync10(pkgPath)) return defaultWatcherConfig();
7070
7111
  const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
7071
7112
  const c = pkg?.coherent?.watcher ?? {};
7072
7113
  return {
@@ -7125,7 +7166,7 @@ async function handleFileChange(projectRoot, filePath) {
7125
7166
  if (config2.warnSharedReuse) {
7126
7167
  let manifest;
7127
7168
  try {
7128
- manifest = await loadManifest8(projectRoot);
7169
+ manifest = await loadManifest7(projectRoot);
7129
7170
  } catch {
7130
7171
  manifest = { shared: [], nextId: 1 };
7131
7172
  }
@@ -7144,7 +7185,7 @@ async function handleFileDelete(projectRoot, filePath) {
7144
7185
  if (!relativePath.startsWith("components/") || relativePath.startsWith("components/ui/")) return;
7145
7186
  try {
7146
7187
  const chalk30 = (await import("chalk")).default;
7147
- const manifest = await loadManifest8(projectRoot);
7188
+ const manifest = await loadManifest7(projectRoot);
7148
7189
  const orphaned = manifest.shared.find((s) => s.file === relativePath);
7149
7190
  if (orphaned) {
7150
7191
  const cleaned = {
@@ -7154,7 +7195,7 @@ async function handleFileDelete(projectRoot, filePath) {
7154
7195
  await saveManifest4(projectRoot, cleaned);
7155
7196
  console.log(chalk30.cyan(`
7156
7197
  \u{1F5D1} Auto-removed ${orphaned.id} (${orphaned.name}) \u2014 file deleted`));
7157
- await writeCursorRules(projectRoot);
7198
+ await writeAllHarnessFiles(projectRoot);
7158
7199
  }
7159
7200
  } catch {
7160
7201
  }
@@ -7165,7 +7206,7 @@ async function detectNewComponent(projectRoot, filePath) {
7165
7206
  if (!relativePath.endsWith(".tsx") && !relativePath.endsWith(".jsx")) return;
7166
7207
  try {
7167
7208
  const chalk30 = (await import("chalk")).default;
7168
- const manifest = await loadManifest8(projectRoot);
7209
+ const manifest = await loadManifest7(projectRoot);
7169
7210
  const alreadyRegistered = manifest.shared.some((s) => s.file === relativePath);
7170
7211
  if (alreadyRegistered) return;
7171
7212
  const code = readFileSync8(filePath, "utf-8");
@@ -7183,7 +7224,7 @@ async function detectNewComponent(projectRoot, filePath) {
7183
7224
  }
7184
7225
  async function handleManifestChange(projectRoot) {
7185
7226
  try {
7186
- await writeCursorRules(projectRoot);
7227
+ await writeAllHarnessFiles(projectRoot);
7187
7228
  } catch {
7188
7229
  }
7189
7230
  }
@@ -7208,7 +7249,7 @@ function startFileWatcher(projectRoot) {
7208
7249
  watcher.on("unlink", (fp) => handleFileDelete(projectRoot, fp));
7209
7250
  });
7210
7251
  const manifestPath = join8(projectRoot, "coherent.components.json");
7211
- if (existsSync11(manifestPath)) {
7252
+ if (existsSync10(manifestPath)) {
7212
7253
  import("chokidar").then((chokidar) => {
7213
7254
  manifestWatcher = chokidar.default.watch(manifestPath, { ignoreInitial: true });
7214
7255
  manifestWatcher.on("change", () => handleManifestChange(projectRoot));
@@ -7222,7 +7263,7 @@ function startFileWatcher(projectRoot) {
7222
7263
 
7223
7264
  // src/commands/preview.ts
7224
7265
  function getPackageManager(projectRoot) {
7225
- const hasPnpm = existsSync12(resolve6(projectRoot, "pnpm-lock.yaml"));
7266
+ const hasPnpm = existsSync11(resolve6(projectRoot, "pnpm-lock.yaml"));
7226
7267
  return hasPnpm ? "pnpm" : "npm";
7227
7268
  }
7228
7269
  function runInstall(projectRoot) {
@@ -7246,21 +7287,21 @@ function runInstall(projectRoot) {
7246
7287
  function checkProjectInitialized(projectRoot) {
7247
7288
  const configPath = resolve6(projectRoot, "design-system.config.ts");
7248
7289
  const packageJsonPath = resolve6(projectRoot, "package.json");
7249
- if (!existsSync12(configPath)) {
7290
+ if (!existsSync11(configPath)) {
7250
7291
  return false;
7251
7292
  }
7252
- if (!existsSync12(packageJsonPath)) {
7293
+ if (!existsSync11(packageJsonPath)) {
7253
7294
  return false;
7254
7295
  }
7255
7296
  return true;
7256
7297
  }
7257
7298
  function checkDependenciesInstalled(projectRoot) {
7258
7299
  const nodeModulesPath = resolve6(projectRoot, "node_modules");
7259
- return existsSync12(nodeModulesPath);
7300
+ return existsSync11(nodeModulesPath);
7260
7301
  }
7261
7302
  function clearStaleCache(projectRoot) {
7262
7303
  const nextDir = join9(projectRoot, ".next");
7263
- if (existsSync12(nextDir)) {
7304
+ if (existsSync11(nextDir)) {
7264
7305
  rmSync3(nextDir, { recursive: true, force: true });
7265
7306
  console.log(chalk11.dim(" \u2714 Cleared stale build cache"));
7266
7307
  }
@@ -7276,7 +7317,7 @@ async function preflightDependencyCheck(projectRoot) {
7276
7317
  }
7277
7318
  async function listPageFiles(appDir) {
7278
7319
  const out = [];
7279
- if (!existsSync12(appDir)) return out;
7320
+ if (!existsSync11(appDir)) return out;
7280
7321
  async function walk(dir) {
7281
7322
  const entries = await readdir(dir, { withFileTypes: true });
7282
7323
  for (const e of entries) {
@@ -7303,10 +7344,10 @@ async function validateSyntax(projectRoot) {
7303
7344
  async function fixMissingComponentExports(projectRoot) {
7304
7345
  const appDir = join9(projectRoot, "app");
7305
7346
  const uiDir = join9(projectRoot, "components", "ui");
7306
- if (!existsSync12(appDir) || !existsSync12(uiDir)) return;
7347
+ if (!existsSync11(appDir) || !existsSync11(uiDir)) return;
7307
7348
  const pages = await listPageFiles(appDir);
7308
7349
  const sharedDir = join9(projectRoot, "components", "shared");
7309
- if (existsSync12(sharedDir)) {
7350
+ if (existsSync11(sharedDir)) {
7310
7351
  const sharedFiles = readdirSync5(sharedDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => join9(sharedDir, f));
7311
7352
  pages.push(...sharedFiles);
7312
7353
  }
@@ -7325,7 +7366,7 @@ async function fixMissingComponentExports(projectRoot) {
7325
7366
  const configPath = join9(projectRoot, "design-system.config.ts");
7326
7367
  let config2 = null;
7327
7368
  try {
7328
- const mgr = new DesignSystemManager6(configPath);
7369
+ const mgr = new DesignSystemManager5(configPath);
7329
7370
  config2 = mgr.getConfig();
7330
7371
  } catch {
7331
7372
  }
@@ -7333,7 +7374,7 @@ async function fixMissingComponentExports(projectRoot) {
7333
7374
  const provider = getComponentProvider();
7334
7375
  for (const [componentId, needed] of neededExports) {
7335
7376
  const componentFile = join9(uiDir, `${componentId}.tsx`);
7336
- if (!existsSync12(componentFile)) {
7377
+ if (!existsSync11(componentFile)) {
7337
7378
  if (provider.has(componentId)) {
7338
7379
  try {
7339
7380
  const result = await provider.installComponent(componentId, projectRoot);
@@ -7402,7 +7443,7 @@ async function fixMissingComponentExports(projectRoot) {
7402
7443
  }
7403
7444
  for (const [componentId, needed] of neededSharedExports) {
7404
7445
  const componentFile = join9(sharedDir, `${componentId}.tsx`);
7405
- if (!existsSync12(componentFile)) continue;
7446
+ if (!existsSync11(componentFile)) continue;
7406
7447
  let content = readFileSync9(componentFile, "utf-8");
7407
7448
  const exportRe = /export\s+(?:const|function|class)\s+(\w+)|export\s*\{([^}]+)\}/g;
7408
7449
  const existingExports = /* @__PURE__ */ new Set();
@@ -7426,9 +7467,9 @@ async function fixMissingComponentExports(projectRoot) {
7426
7467
  }
7427
7468
  async function backfillPageAnalysis(projectRoot) {
7428
7469
  const configPath = join9(projectRoot, "design-system.config.ts");
7429
- if (!existsSync12(configPath)) return;
7470
+ if (!existsSync11(configPath)) return;
7430
7471
  try {
7431
- const mgr = new DesignSystemManager6(configPath);
7472
+ const mgr = new DesignSystemManager5(configPath);
7432
7473
  const config2 = mgr.getConfig();
7433
7474
  let changed = false;
7434
7475
  for (const page of config2.pages) {
@@ -7443,7 +7484,7 @@ async function backfillPageAnalysis(projectRoot) {
7443
7484
  } else {
7444
7485
  filePath = join9(projectRoot, "app", route.slice(1), "page.tsx");
7445
7486
  }
7446
- if (!existsSync12(filePath)) continue;
7487
+ if (!existsSync11(filePath)) continue;
7447
7488
  const code = readFileSync9(filePath, "utf-8");
7448
7489
  if (code.length < 50) continue;
7449
7490
  page.pageAnalysis = analyzePageCode(code);
@@ -7595,11 +7636,11 @@ async function openBrowser(url) {
7595
7636
  }
7596
7637
  function startDevServer(projectRoot) {
7597
7638
  const packageJsonPath = resolve6(projectRoot, "package.json");
7598
- if (!existsSync12(packageJsonPath)) {
7639
+ if (!existsSync11(packageJsonPath)) {
7599
7640
  throw new Error('package.json not found. Run "coherent init" first.');
7600
7641
  }
7601
- const hasPnpm = existsSync12(resolve6(projectRoot, "pnpm-lock.yaml"));
7602
- const hasNpm = existsSync12(resolve6(projectRoot, "package-lock.json"));
7642
+ const hasPnpm = existsSync11(resolve6(projectRoot, "pnpm-lock.yaml"));
7643
+ const hasNpm = existsSync11(resolve6(projectRoot, "package-lock.json"));
7603
7644
  const command = hasPnpm ? "pnpm" : hasNpm ? "npm" : "npx";
7604
7645
  const args = hasPnpm ? ["dev", "--turbo"] : hasNpm ? ["run", "dev", "--", "--turbo"] : ["next", "dev", "--turbo"];
7605
7646
  const child = spawn(command, args, {
@@ -7646,7 +7687,7 @@ async function previewCommand() {
7646
7687
  if (needsGlobalsFix(projectRoot)) {
7647
7688
  spinner.text = "Fixing globals.css...";
7648
7689
  try {
7649
- const dsm = new DesignSystemManager6(resolve6(projectRoot, "design-system.config.ts"));
7690
+ const dsm = new DesignSystemManager5(resolve6(projectRoot, "design-system.config.ts"));
7650
7691
  await dsm.load();
7651
7692
  const config2 = dsm.getConfig();
7652
7693
  fixGlobalsCss(projectRoot, config2);
@@ -7657,7 +7698,7 @@ async function previewCommand() {
7657
7698
  }
7658
7699
  if (isTailwindV4(projectRoot)) {
7659
7700
  const globalsPath = resolve6(projectRoot, "app", "globals.css");
7660
- if (existsSync12(globalsPath)) {
7701
+ if (existsSync11(globalsPath)) {
7661
7702
  const globalsContent = readFileSync9(globalsPath, "utf-8");
7662
7703
  const cssIssues = validateV4GlobalsCss(globalsContent);
7663
7704
  if (cssIssues.length > 0) {
@@ -7699,7 +7740,7 @@ async function previewCommand() {
7699
7740
  import chalk12 from "chalk";
7700
7741
  import ora4 from "ora";
7701
7742
  import { spawn as spawn2 } from "child_process";
7702
- import { existsSync as existsSync13, rmSync as rmSync4, readdirSync as readdirSync6 } from "fs";
7743
+ import { existsSync as existsSync12, rmSync as rmSync4, readdirSync as readdirSync6 } from "fs";
7703
7744
  import { resolve as resolve7, join as join10, dirname as dirname4 } from "path";
7704
7745
  import { readdir as readdir2, readFile as readFile3, writeFile as writeFile3, mkdir as mkdir2, copyFile } from "fs/promises";
7705
7746
  var COPY_EXCLUDE = /* @__PURE__ */ new Set([
@@ -7710,6 +7751,7 @@ var COPY_EXCLUDE = /* @__PURE__ */ new Set([
7710
7751
  ".tmp-e2e",
7711
7752
  ".cursorrules",
7712
7753
  "CLAUDE.md",
7754
+ "AGENTS.md",
7713
7755
  ".claude",
7714
7756
  ".coherent",
7715
7757
  "design-system.config.ts",
@@ -7734,17 +7776,17 @@ async function copyDir(src, dest) {
7734
7776
  }
7735
7777
  }
7736
7778
  function checkProjectInitialized2(projectRoot) {
7737
- return existsSync13(resolve7(projectRoot, "design-system.config.ts")) && existsSync13(resolve7(projectRoot, "package.json"));
7779
+ return existsSync12(resolve7(projectRoot, "design-system.config.ts")) && existsSync12(resolve7(projectRoot, "package.json"));
7738
7780
  }
7739
7781
  function getPackageManager2(projectRoot) {
7740
- if (existsSync13(resolve7(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
7741
- if (existsSync13(resolve7(projectRoot, "package-lock.json"))) return "npm";
7782
+ if (existsSync12(resolve7(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
7783
+ if (existsSync12(resolve7(projectRoot, "package-lock.json"))) return "npm";
7742
7784
  return "npx";
7743
7785
  }
7744
7786
  async function patchNextConfigForExport(outRoot) {
7745
7787
  for (const name of ["next.config.ts", "next.config.mjs", "next.config.js"]) {
7746
7788
  const p = join10(outRoot, name);
7747
- if (!existsSync13(p)) continue;
7789
+ if (!existsSync12(p)) continue;
7748
7790
  let content = await readFile3(p, "utf-8");
7749
7791
  if (content.includes("ignoreDuringBuilds")) return;
7750
7792
  content = content.replace(
@@ -7786,7 +7828,7 @@ EXPOSE 3000
7786
7828
  `;
7787
7829
  async function ensureReadmeDeploySection(outRoot) {
7788
7830
  const readmePath = join10(outRoot, "README.md");
7789
- if (!existsSync13(readmePath)) return;
7831
+ if (!existsSync12(readmePath)) return;
7790
7832
  try {
7791
7833
  let content = await readFile3(readmePath, "utf-8");
7792
7834
  if (/##\s+Deploy\b/m.test(content)) return;
@@ -7811,14 +7853,14 @@ async function countPages(outRoot) {
7811
7853
  }
7812
7854
  }
7813
7855
  const appDir = join10(outRoot, "app");
7814
- if (existsSync13(appDir)) await walk(appDir);
7856
+ if (existsSync12(appDir)) await walk(appDir);
7815
7857
  return n;
7816
7858
  }
7817
7859
  function countComponents(outRoot) {
7818
7860
  let n = 0;
7819
7861
  for (const sub of ["ui", "shared"]) {
7820
7862
  const dir = join10(outRoot, "components", sub);
7821
- if (!existsSync13(dir)) continue;
7863
+ if (!existsSync12(dir)) continue;
7822
7864
  try {
7823
7865
  n += readdirSync6(dir).filter((f) => f.endsWith(".tsx") || f.endsWith(".jsx")).length;
7824
7866
  } catch {
@@ -7829,7 +7871,7 @@ function countComponents(outRoot) {
7829
7871
  var IMPORT_FROM_REGEX = /from\s+['"]([^'"]+)['"]/g;
7830
7872
  async function collectImportedPackages(dir, extensions) {
7831
7873
  const packages = /* @__PURE__ */ new Set();
7832
- if (!existsSync13(dir)) return packages;
7874
+ if (!existsSync12(dir)) return packages;
7833
7875
  async function walk(d) {
7834
7876
  const entries = await readdir2(d, { withFileTypes: true });
7835
7877
  for (const e of entries) {
@@ -7857,7 +7899,7 @@ async function collectImportedPackages(dir, extensions) {
7857
7899
  }
7858
7900
  async function findMissingDepsInExport(outRoot) {
7859
7901
  const pkgPath = join10(outRoot, "package.json");
7860
- if (!existsSync13(pkgPath)) return [];
7902
+ if (!existsSync12(pkgPath)) return [];
7861
7903
  let pkg;
7862
7904
  try {
7863
7905
  pkg = JSON.parse(await readFile3(pkgPath, "utf-8"));
@@ -7878,32 +7920,32 @@ async function stripCoherentArtifacts(outputDir) {
7878
7920
  const removed = [];
7879
7921
  for (const p of ["app/design-system", "app/api/design-system"]) {
7880
7922
  const full = join10(outputDir, p);
7881
- if (existsSync13(full)) {
7923
+ if (existsSync12(full)) {
7882
7924
  rmSync4(full, { recursive: true, force: true });
7883
7925
  removed.push(p);
7884
7926
  }
7885
7927
  }
7886
7928
  const appNavPath = join10(outputDir, "app", "AppNav.tsx");
7887
- if (existsSync13(appNavPath)) {
7929
+ if (existsSync12(appNavPath)) {
7888
7930
  rmSync4(appNavPath, { force: true });
7889
7931
  removed.push("app/AppNav.tsx");
7890
7932
  }
7891
7933
  const layoutPath = join10(outputDir, "app", "layout.tsx");
7892
- if (existsSync13(layoutPath)) {
7934
+ if (existsSync12(layoutPath)) {
7893
7935
  let layout = await readFile3(layoutPath, "utf-8");
7894
7936
  layout = layout.replace(/import\s*\{?\s*AppNav\s*\}?\s*from\s*['"][^'"]+['"]\s*\n?/g, "");
7895
7937
  layout = layout.replace(/\s*<AppNav\s*\/?\s*>\s*/g, "\n");
7896
7938
  await writeFile3(layoutPath, layout, "utf-8");
7897
7939
  }
7898
7940
  const sharedHeaderPath = join10(outputDir, "components", "shared", "header.tsx");
7899
- if (existsSync13(sharedHeaderPath)) {
7941
+ if (existsSync12(sharedHeaderPath)) {
7900
7942
  let header = await readFile3(sharedHeaderPath, "utf-8");
7901
7943
  header = header.replace(/<Link\s[^>]*href="\/design-system"[^>]*>[\s\S]*?<\/Link>/g, "");
7902
7944
  header = header.replace(/\n\s*<>\s*\n/, "\n");
7903
7945
  header = header.replace(/\n\s*<\/>\s*\n/, "\n");
7904
7946
  await writeFile3(sharedHeaderPath, header, "utf-8");
7905
7947
  }
7906
- if (existsSync13(layoutPath)) {
7948
+ if (existsSync12(layoutPath)) {
7907
7949
  let rootLayout = await readFile3(layoutPath, "utf-8");
7908
7950
  const before = rootLayout;
7909
7951
  rootLayout = rootLayout.replace(/<Link\s[^>]*href="\/design-system"[^>]*>[\s\S]*?<\/Link>/g, "");
@@ -7912,7 +7954,7 @@ async function stripCoherentArtifacts(outputDir) {
7912
7954
  }
7913
7955
  }
7914
7956
  const guardPath2 = join10(outputDir, "app", "ShowWhenNotAuthRoute.tsx");
7915
- if (existsSync13(guardPath2)) {
7957
+ if (existsSync12(guardPath2)) {
7916
7958
  let guard = await readFile3(guardPath2, "utf-8");
7917
7959
  guard = guard.replace(/['"],?\s*'\/design-system['"],?\s*/g, "");
7918
7960
  const pathsMatch = guard.match(/HIDDEN_PATHS\s*=\s*\[([^\]]*)\]/);
@@ -7920,7 +7962,7 @@ async function stripCoherentArtifacts(outputDir) {
7920
7962
  if (remaining.length === 0) {
7921
7963
  rmSync4(guardPath2, { force: true });
7922
7964
  removed.push("app/ShowWhenNotAuthRoute.tsx");
7923
- if (existsSync13(layoutPath)) {
7965
+ if (existsSync12(layoutPath)) {
7924
7966
  let layout = await readFile3(layoutPath, "utf-8");
7925
7967
  layout = layout.replace(/import\s+\w+\s+from\s*['"]\.\/ShowWhenNotAuthRoute['"]\s*\n?/g, "");
7926
7968
  layout = layout.replace(/\s*<ShowWhenNotAuthRoute>\s*\n?/g, "\n");
@@ -7936,19 +7978,20 @@ async function stripCoherentArtifacts(outputDir) {
7936
7978
  "design-system.config.ts",
7937
7979
  ".cursorrules",
7938
7980
  "CLAUDE.md",
7981
+ "AGENTS.md",
7939
7982
  ".env",
7940
7983
  ".env.local",
7941
7984
  "recommendations.md"
7942
7985
  ]) {
7943
7986
  const full = join10(outputDir, name);
7944
- if (existsSync13(full)) {
7987
+ if (existsSync12(full)) {
7945
7988
  rmSync4(full, { force: true });
7946
7989
  removed.push(name);
7947
7990
  }
7948
7991
  }
7949
7992
  for (const dir of [".claude", ".coherent"]) {
7950
7993
  const full = join10(outputDir, dir);
7951
- if (existsSync13(full)) {
7994
+ if (existsSync12(full)) {
7952
7995
  rmSync4(full, { recursive: true, force: true });
7953
7996
  removed.push(dir + "/");
7954
7997
  }
@@ -7972,7 +8015,7 @@ async function exportCommand(options = {}) {
7972
8015
  process.exit(1);
7973
8016
  }
7974
8017
  spinner.text = "Copying project...";
7975
- if (existsSync13(outputDir)) rmSync4(outputDir, { recursive: true, force: true });
8018
+ if (existsSync12(outputDir)) rmSync4(outputDir, { recursive: true, force: true });
7976
8019
  await copyDir(projectRoot, outputDir);
7977
8020
  spinner.succeed("Project copied");
7978
8021
  if (!keepDs) {
@@ -8035,7 +8078,7 @@ async function exportCommand(options = {}) {
8035
8078
  // src/commands/status.ts
8036
8079
  import chalk13 from "chalk";
8037
8080
  import { basename as basename2 } from "path";
8038
- import { DesignSystemManager as DesignSystemManager7 } from "@getcoherent/core";
8081
+ import { DesignSystemManager as DesignSystemManager6 } from "@getcoherent/core";
8039
8082
  function countTokens(tokens) {
8040
8083
  let count = 0;
8041
8084
  function countObj(obj) {
@@ -8067,7 +8110,7 @@ async function statusCommand() {
8067
8110
  console.log(chalk13.gray("\u{1F4C4} Config: ") + chalk13.white(basename2(project.configPath)));
8068
8111
  console.log("");
8069
8112
  try {
8070
- const manager = new DesignSystemManager7(project.configPath);
8113
+ const manager = new DesignSystemManager6(project.configPath);
8071
8114
  await manager.load();
8072
8115
  const config2 = manager.getConfig();
8073
8116
  console.log(chalk13.cyan("\u{1F4CA} Statistics:\n"));
@@ -8110,7 +8153,7 @@ async function statusCommand() {
8110
8153
  // src/commands/regenerate-docs.ts
8111
8154
  import chalk14 from "chalk";
8112
8155
  import ora5 from "ora";
8113
- import { DesignSystemManager as DesignSystemManager8 } from "@getcoherent/core";
8156
+ import { DesignSystemManager as DesignSystemManager7 } from "@getcoherent/core";
8114
8157
  import { ProjectScaffolder as ProjectScaffolder2 } from "@getcoherent/core";
8115
8158
  async function regenerateDocsCommand() {
8116
8159
  try {
@@ -8123,7 +8166,7 @@ async function regenerateDocsCommand() {
8123
8166
  }
8124
8167
  const spinner = ora5("Regenerating documentation pages...").start();
8125
8168
  try {
8126
- const manager = new DesignSystemManager8(project.configPath);
8169
+ const manager = new DesignSystemManager7(project.configPath);
8127
8170
  await manager.load();
8128
8171
  const config2 = manager.getConfig();
8129
8172
  const scaffolder = new ProjectScaffolder2(config2, project.root);
@@ -8147,14 +8190,14 @@ async function regenerateDocsCommand() {
8147
8190
 
8148
8191
  // src/commands/fix.ts
8149
8192
  import chalk15 from "chalk";
8150
- import { readdirSync as readdirSync7, readFileSync as readFileSync10, existsSync as existsSync14, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
8193
+ import { readdirSync as readdirSync7, readFileSync as readFileSync10, existsSync as existsSync13, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
8151
8194
  import { resolve as resolve8, join as join11, relative as relative5, basename as basename3 } from "path";
8152
8195
  import {
8153
- DesignSystemManager as DesignSystemManager9,
8196
+ DesignSystemManager as DesignSystemManager8,
8154
8197
  ComponentManager as ComponentManager5,
8155
8198
  PageManager as PageManager3,
8156
8199
  ComponentGenerator as ComponentGenerator3,
8157
- loadManifest as loadManifest9,
8200
+ loadManifest as loadManifest8,
8158
8201
  saveManifest as saveManifest5
8159
8202
  } from "@getcoherent/core";
8160
8203
  function extractComponentIdsFromCode2(code) {
@@ -8206,7 +8249,7 @@ async function fixCommand(opts = {}) {
8206
8249
  }
8207
8250
  if (!skipCache) {
8208
8251
  const nextDir = join11(projectRoot, ".next");
8209
- if (existsSync14(nextDir)) {
8252
+ if (existsSync13(nextDir)) {
8210
8253
  if (!dryRun) rmSync5(nextDir, { recursive: true, force: true });
8211
8254
  fixes.push("Cleared build cache");
8212
8255
  console.log(chalk15.green(" \u2714 Cleared build cache"));
@@ -8240,7 +8283,7 @@ async function fixCommand(opts = {}) {
8240
8283
  let cm = null;
8241
8284
  let pm = null;
8242
8285
  if (allComponentIds.size > 0) {
8243
- dsm = new DesignSystemManager9(project.configPath);
8286
+ dsm = new DesignSystemManager8(project.configPath);
8244
8287
  await dsm.load();
8245
8288
  const config2 = dsm.getConfig();
8246
8289
  cm = new ComponentManager5(config2);
@@ -8253,7 +8296,7 @@ async function fixCommand(opts = {}) {
8253
8296
  } else {
8254
8297
  const fileName = toKebabCase(id) + ".tsx";
8255
8298
  const filePath = resolve8(projectRoot, "components", "ui", fileName);
8256
- if (!existsSync14(filePath)) missingFiles.push(id);
8299
+ if (!existsSync13(filePath)) missingFiles.push(id);
8257
8300
  }
8258
8301
  }
8259
8302
  const provider = getComponentProvider();
@@ -8302,8 +8345,8 @@ async function fixCommand(opts = {}) {
8302
8345
  }
8303
8346
  }
8304
8347
  }
8305
- if (!dsm && existsSync14(project.configPath)) {
8306
- dsm = new DesignSystemManager9(project.configPath);
8348
+ if (!dsm && existsSync13(project.configPath)) {
8349
+ dsm = new DesignSystemManager8(project.configPath);
8307
8350
  await dsm.load();
8308
8351
  }
8309
8352
  if (dsm && dsm.getConfig().name === "My App") {
@@ -8311,7 +8354,7 @@ async function fixCommand(opts = {}) {
8311
8354
  let derivedName = null;
8312
8355
  try {
8313
8356
  const pkgPath = resolve8(projectRoot, "package.json");
8314
- if (existsSync14(pkgPath)) {
8357
+ if (existsSync13(pkgPath)) {
8315
8358
  const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
8316
8359
  if (typeof pkg.name === "string" && pkg.name) {
8317
8360
  derivedName = toTitleCase2(pkg.name);
@@ -8349,7 +8392,7 @@ async function fixCommand(opts = {}) {
8349
8392
  const configName = dsm.getConfig().name;
8350
8393
  if (configName && configName !== "My App") {
8351
8394
  const appLayoutPath = resolve8(projectRoot, "app", "(app)", "layout.tsx");
8352
- if (existsSync14(appLayoutPath)) {
8395
+ if (existsSync13(appLayoutPath)) {
8353
8396
  let appLayoutCode = readFileSync10(appLayoutPath, "utf-8");
8354
8397
  if (appLayoutCode.includes("My App")) {
8355
8398
  appLayoutCode = appLayoutCode.replace(/My App/g, configName);
@@ -8368,7 +8411,7 @@ async function fixCommand(opts = {}) {
8368
8411
  }
8369
8412
  }
8370
8413
  const sharedDir = resolve8(projectRoot, "components", "shared");
8371
- if (existsSync14(sharedDir)) {
8414
+ if (existsSync13(sharedDir)) {
8372
8415
  try {
8373
8416
  for (const f of readdirSync7(sharedDir).filter((n) => n.endsWith(".tsx"))) {
8374
8417
  const sharedPath = join11(sharedDir, f);
@@ -8430,7 +8473,7 @@ async function fixCommand(opts = {}) {
8430
8473
  const plan = loadPlan2(projectRoot);
8431
8474
  if (plan) {
8432
8475
  if (!dsm) {
8433
- dsm = new DesignSystemManager9(project.configPath);
8476
+ dsm = new DesignSystemManager8(project.configPath);
8434
8477
  await dsm.load();
8435
8478
  }
8436
8479
  await ensurePlanGroupLayouts2(projectRoot, plan, {}, dsm.getConfig());
@@ -8439,9 +8482,9 @@ async function fixCommand(opts = {}) {
8439
8482
  console.log(chalk15.green(` \u2714 Verified group layouts: ${layoutTypes}`));
8440
8483
  const hasSidebar = plan.groups.some((g) => g.layout === "sidebar" || g.layout === "both");
8441
8484
  const sidebarPath = resolve8(projectRoot, "components", "shared", "sidebar.tsx");
8442
- if (hasSidebar && !existsSync14(sidebarPath) && !dryRun) {
8485
+ if (hasSidebar && !existsSync13(sidebarPath) && !dryRun) {
8443
8486
  if (!dsm) {
8444
- dsm = new DesignSystemManager9(project.configPath);
8487
+ dsm = new DesignSystemManager8(project.configPath);
8445
8488
  await dsm.load();
8446
8489
  }
8447
8490
  const { PageGenerator } = await import("@getcoherent/core");
@@ -8458,7 +8501,7 @@ async function fixCommand(opts = {}) {
8458
8501
  }
8459
8502
  if (hasSidebar && !dryRun) {
8460
8503
  const rootLayoutPath = resolve8(projectRoot, "app", "layout.tsx");
8461
- if (existsSync14(rootLayoutPath)) {
8504
+ if (existsSync13(rootLayoutPath)) {
8462
8505
  let rootCode = readFileSync10(rootLayoutPath, "utf-8");
8463
8506
  if (rootCode.includes("<Header")) {
8464
8507
  rootCode = rootCode.replace(/import\s*\{[^}]*Header[^}]*\}[^;\n]*[;\n]?\s*/g, "").replace(/import\s*\{[^}]*Footer[^}]*\}[^;\n]*[;\n]?\s*/g, "").replace(/import\s+ShowWhenNotAuthRoute[^;\n]*[;\n]?\s*/g, "").replace(/<ShowWhenNotAuthRoute>[\s\S]*?<\/ShowWhenNotAuthRoute>/g, (match) => {
@@ -8477,7 +8520,7 @@ async function fixCommand(opts = {}) {
8477
8520
  }
8478
8521
  }
8479
8522
  const publicLayoutPath = resolve8(projectRoot, "app", "(public)", "layout.tsx");
8480
- const publicExists = existsSync14(publicLayoutPath);
8523
+ const publicExists = existsSync13(publicLayoutPath);
8481
8524
  const needsPublicLayout = !publicExists || !readFileSync10(publicLayoutPath, "utf-8").includes("<Header");
8482
8525
  if (needsPublicLayout) {
8483
8526
  const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-YSGVHVNN.js");
@@ -8491,7 +8534,7 @@ async function fixCommand(opts = {}) {
8491
8534
  }
8492
8535
  }
8493
8536
  const sidebarComponentPath2 = resolve8(projectRoot, "components", "shared", "sidebar.tsx");
8494
- if (existsSync14(sidebarComponentPath2)) {
8537
+ if (existsSync13(sidebarComponentPath2)) {
8495
8538
  const existingSidebarCode = readFileSync10(sidebarComponentPath2, "utf-8");
8496
8539
  const sidebarConfigName = dsm?.getConfig().name ?? "";
8497
8540
  const hasWrongName = existingSidebarCode.includes("My App") && sidebarConfigName !== "My App";
@@ -8499,7 +8542,7 @@ async function fixCommand(opts = {}) {
8499
8542
  const isBroken = !isValidTsx(existingSidebarCode, projectRoot);
8500
8543
  if (hasWrongName || hasTrigger || isBroken) {
8501
8544
  if (!dsm) {
8502
- dsm = new DesignSystemManager9(project.configPath);
8545
+ dsm = new DesignSystemManager8(project.configPath);
8503
8546
  await dsm.load();
8504
8547
  }
8505
8548
  const { PageGenerator } = await import("@getcoherent/core");
@@ -8520,7 +8563,7 @@ async function fixCommand(opts = {}) {
8520
8563
  }
8521
8564
  const rootPagePath = resolve8(projectRoot, "app", "page.tsx");
8522
8565
  const publicPagePath = resolve8(projectRoot, "app", "(public)", "page.tsx");
8523
- if (existsSync14(rootPagePath) && !existsSync14(publicPagePath)) {
8566
+ if (existsSync13(rootPagePath) && !existsSync13(publicPagePath)) {
8524
8567
  const { renameSync } = await import("fs");
8525
8568
  mkdirSync7(resolve8(projectRoot, "app", "(public)"), { recursive: true });
8526
8569
  renameSync(rootPagePath, publicPagePath);
@@ -8528,7 +8571,7 @@ async function fixCommand(opts = {}) {
8528
8571
  console.log(chalk15.green(" \u2714 Moved app/page.tsx \u2192 app/(public)/page.tsx (gets Header/Footer)"));
8529
8572
  }
8530
8573
  const themeTogglePath = resolve8(projectRoot, "components", "shared", "theme-toggle.tsx");
8531
- if (!existsSync14(themeTogglePath)) {
8574
+ if (!existsSync13(themeTogglePath)) {
8532
8575
  const { generateThemeToggleCode } = await import("./code-generator-YSGVHVNN.js");
8533
8576
  mkdirSync7(resolve8(projectRoot, "components", "shared"), { recursive: true });
8534
8577
  const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
@@ -8545,7 +8588,7 @@ async function fixCommand(opts = {}) {
8545
8588
  console.log(chalk15.yellow(` \u26A0 Layout repair skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8546
8589
  }
8547
8590
  const appLayoutRepairPath = resolve8(projectRoot, "app", "(app)", "layout.tsx");
8548
- if (existsSync14(appLayoutRepairPath) && dsm) {
8591
+ if (existsSync13(appLayoutRepairPath) && dsm) {
8549
8592
  const appLayoutCode = readFileSync10(appLayoutRepairPath, "utf-8");
8550
8593
  const isMinimal = appLayoutCode.length < 500 && !appLayoutCode.includes("Header") && !appLayoutCode.includes("Footer") && !appLayoutCode.includes("Sidebar") && !appLayoutCode.includes("SidebarProvider") && !appLayoutCode.includes("SidebarTrigger") && !appLayoutCode.includes("Sheet");
8551
8594
  const navType = dsm.getConfig().navigation?.type || "header";
@@ -8683,7 +8726,7 @@ async function fixCommand(opts = {}) {
8683
8726
  }
8684
8727
  }
8685
8728
  try {
8686
- let manifest = await loadManifest9(project.root);
8729
+ let manifest = await loadManifest8(project.root);
8687
8730
  let manifestModified = false;
8688
8731
  const { manifest: cleaned, removed: orphaned } = removeOrphanedEntries(project.root, manifest);
8689
8732
  if (orphaned.length > 0) {
@@ -8763,7 +8806,7 @@ async function fixCommand(opts = {}) {
8763
8806
  }
8764
8807
  try {
8765
8808
  const tsconfigPath = resolve8(projectRoot, "tsconfig.json");
8766
- if (existsSync14(tsconfigPath)) {
8809
+ if (existsSync13(tsconfigPath)) {
8767
8810
  const { runTscCheck, applyDeterministicFixes } = await import("./tsc-autofix-S5PKMFSC.js");
8768
8811
  const { applyAiFixes } = await import("./tsc-ai-fix-O3EMRWV2.js");
8769
8812
  const tscErrors = runTscCheck(projectRoot);
@@ -8851,8 +8894,8 @@ async function fixCommand(opts = {}) {
8851
8894
  // src/commands/check.ts
8852
8895
  import chalk16 from "chalk";
8853
8896
  import { resolve as resolve9 } from "path";
8854
- import { readdirSync as readdirSync8, readFileSync as readFileSync11, statSync as statSync3, existsSync as existsSync15 } from "fs";
8855
- import { loadManifest as loadManifest10 } from "@getcoherent/core";
8897
+ import { readdirSync as readdirSync8, readFileSync as readFileSync11, statSync as statSync3, existsSync as existsSync14 } from "fs";
8898
+ import { loadManifest as loadManifest9 } from "@getcoherent/core";
8856
8899
  var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", "design-system"]);
8857
8900
  function findTsxFiles(dir) {
8858
8901
  const results = [];
@@ -8887,8 +8930,8 @@ async function checkCommand(opts = {}) {
8887
8930
  };
8888
8931
  let validRoutes = [];
8889
8932
  try {
8890
- const { DesignSystemManager: DesignSystemManager15 } = await import("@getcoherent/core");
8891
- const dsm = new DesignSystemManager15(project.configPath);
8933
+ const { DesignSystemManager: DesignSystemManager14 } = await import("@getcoherent/core");
8934
+ const dsm = new DesignSystemManager14(project.configPath);
8892
8935
  await dsm.load();
8893
8936
  validRoutes = dsm.getConfig().pages.map((p) => p.route).filter(Boolean);
8894
8937
  } catch {
@@ -8979,11 +9022,11 @@ async function checkCommand(opts = {}) {
8979
9022
  \u{1F517} Internal Links`) + chalk16.dim(` \u2014 all ${result.links.total} links resolve \u2713`));
8980
9023
  }
8981
9024
  try {
8982
- const manifest = await loadManifest10(project.root);
9025
+ const manifest = await loadManifest9(project.root);
8983
9026
  if (manifest.shared.length > 0) {
8984
9027
  for (const entry of manifest.shared) {
8985
9028
  const fullPath = resolve9(project.root, entry.file);
8986
- if (!existsSync15(fullPath)) {
9029
+ if (!existsSync14(fullPath)) {
8987
9030
  result.pages.withErrors++;
8988
9031
  if (!opts.json) console.log(chalk16.red(`
8989
9032
  \u2717 Missing shared component file: ${entry.id} (${entry.file})`));
@@ -8995,7 +9038,7 @@ async function checkCommand(opts = {}) {
8995
9038
  }
8996
9039
  if (!skipShared) {
8997
9040
  try {
8998
- const manifest = await loadManifest10(projectRoot);
9041
+ const manifest = await loadManifest9(projectRoot);
8999
9042
  if (!opts.json && manifest.shared.length > 0) {
9000
9043
  console.log(chalk16.cyan(`
9001
9044
  \u{1F9E9} Shared Components`) + chalk16.dim(` (${manifest.shared.length} registered)
@@ -9008,7 +9051,7 @@ async function checkCommand(opts = {}) {
9008
9051
  let _nameMismatch = 0;
9009
9052
  for (const entry of manifest.shared) {
9010
9053
  const filePath = resolve9(projectRoot, entry.file);
9011
- const fileExists = existsSync15(filePath);
9054
+ const fileExists = existsSync14(filePath);
9012
9055
  if (!fileExists) {
9013
9056
  _orphaned++;
9014
9057
  if (!opts.json) {
@@ -9086,7 +9129,7 @@ async function checkCommand(opts = {}) {
9086
9129
  id: e.id,
9087
9130
  name: e.name,
9088
9131
  type: e.type,
9089
- status: existsSync15(resolve9(projectRoot, e.file)) ? "ok" : "unused",
9132
+ status: existsSync14(resolve9(projectRoot, e.file)) ? "ok" : "unused",
9090
9133
  message: "",
9091
9134
  suggestions: void 0
9092
9135
  }))
@@ -9098,9 +9141,9 @@ async function checkCommand(opts = {}) {
9098
9141
  try {
9099
9142
  const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
9100
9143
  const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-HGNEY3W3.js");
9101
- const manifest = await loadManifest10(projectRoot);
9144
+ const manifest = await loadManifest9(projectRoot);
9102
9145
  const appDir = resolve9(projectRoot, "app");
9103
- const pageFiles = existsSync15(appDir) ? findTsxFiles(appDir) : [];
9146
+ const pageFiles = existsSync14(appDir) ? findTsxFiles(appDir) : [];
9104
9147
  if (manifest.shared.length > 0 && pageFiles.length > 0) {
9105
9148
  const reuseWarnings = [];
9106
9149
  for (const file of pageFiles) {
@@ -9175,7 +9218,7 @@ async function doctorCommand() {
9175
9218
  import chalk19 from "chalk";
9176
9219
  async function rulesCommand() {
9177
9220
  try {
9178
- const result = await regenerateCursorRules();
9221
+ const result = await regenerateAllHarnessFiles();
9179
9222
  if (!result.written) {
9180
9223
  exitNotCoherent();
9181
9224
  }
@@ -9183,7 +9226,7 @@ async function rulesCommand() {
9183
9226
  if (result.sharedCount !== void 0) parts.push(`${result.sharedCount} shared components`);
9184
9227
  if (result.tokenKeys !== void 0) parts.push(`${result.tokenKeys} design token keys`);
9185
9228
  const summary = parts.length > 0 ? ` (${parts.join(", ")})` : "";
9186
- console.log(chalk19.green(`\u2714 Updated .cursorrules and CLAUDE.md${summary}
9229
+ console.log(chalk19.green(`\u2714 Updated .cursorrules, CLAUDE.md, and AGENTS.md${summary}
9187
9230
  `));
9188
9231
  } catch (error) {
9189
9232
  console.error(chalk19.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
@@ -9209,13 +9252,13 @@ async function auditCommand(options) {
9209
9252
  import { Command } from "commander";
9210
9253
  import chalk22 from "chalk";
9211
9254
  import {
9212
- DesignSystemManager as DesignSystemManager10,
9255
+ DesignSystemManager as DesignSystemManager9,
9213
9256
  ComponentManager as ComponentManager6,
9214
- loadManifest as loadManifest11,
9257
+ loadManifest as loadManifest10,
9215
9258
  generateSharedComponent as generateSharedComponent4,
9216
9259
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2
9217
9260
  } from "@getcoherent/core";
9218
- import { existsSync as existsSync16 } from "fs";
9261
+ import { existsSync as existsSync15 } from "fs";
9219
9262
  import { resolve as resolve10 } from "path";
9220
9263
 
9221
9264
  // src/utils/ds-files.ts
@@ -9248,11 +9291,11 @@ function createComponentsCommand() {
9248
9291
  cmd.command("list").description("List all components (shared + UI)").option("--json", "Machine-readable JSON output").action(async (opts) => {
9249
9292
  const project = findConfig();
9250
9293
  if (!project) exitNotCoherent();
9251
- const dsm = new DesignSystemManager10(project.configPath);
9294
+ const dsm = new DesignSystemManager9(project.configPath);
9252
9295
  await dsm.load();
9253
9296
  const config2 = dsm.getConfig();
9254
9297
  const cm = new ComponentManager6(config2);
9255
- const manifest = await loadManifest11(project.root);
9298
+ const manifest = await loadManifest10(project.root);
9256
9299
  if (opts.json) {
9257
9300
  const installed2 = cm.getAllComponents();
9258
9301
  console.log(JSON.stringify({ shared: manifest.shared, ui: installed2 }, null, 2));
@@ -9312,7 +9355,7 @@ function createComponentsCommand() {
9312
9355
  sharedCmd.option("--json", "Machine-readable JSON output").option("--verbose", "Show file paths and usage details").action(async (opts) => {
9313
9356
  const project = findConfig();
9314
9357
  if (!project) exitNotCoherent();
9315
- const manifest = await loadManifest11(project.root);
9358
+ const manifest = await loadManifest10(project.root);
9316
9359
  if (opts.json) {
9317
9360
  console.log(JSON.stringify(manifest, null, 2));
9318
9361
  return;
@@ -9370,9 +9413,9 @@ function createComponentsCommand() {
9370
9413
  if (updated) console.log(chalk22.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
9371
9414
  }
9372
9415
  const sharedPagePath = resolve10(project.root, "app/design-system/shared/page.tsx");
9373
- if (!existsSync16(sharedPagePath)) {
9416
+ if (!existsSync15(sharedPagePath)) {
9374
9417
  try {
9375
- const dsm = new DesignSystemManager10(project.configPath);
9418
+ const dsm = new DesignSystemManager9(project.configPath);
9376
9419
  await dsm.load();
9377
9420
  const config2 = dsm.getConfig();
9378
9421
  const written = await writeDesignSystemFiles(project.root, config2, { sharedOnly: true });
@@ -9384,7 +9427,7 @@ function createComponentsCommand() {
9384
9427
  }
9385
9428
  }
9386
9429
  try {
9387
- await writeCursorRules(project.root);
9430
+ await writeAllHarnessFiles(project.root);
9388
9431
  } catch (e) {
9389
9432
  if (process.env.COHERENT_DEBUG === "1") console.error(chalk22.dim("Could not update .cursorrules:"), e);
9390
9433
  }
@@ -9397,7 +9440,7 @@ import chalk23 from "chalk";
9397
9440
  import ora6 from "ora";
9398
9441
  import { writeFile as writeFile5, mkdir as mkdir4 } from "fs/promises";
9399
9442
  import { resolve as resolve11, join as join13, dirname as dirname6 } from "path";
9400
- import { existsSync as existsSync17 } from "fs";
9443
+ import { existsSync as existsSync16 } from "fs";
9401
9444
  import {
9402
9445
  FigmaClient,
9403
9446
  parseFigmaFileResponse,
@@ -9410,7 +9453,7 @@ import {
9410
9453
  generateSharedComponent as generateSharedComponent5,
9411
9454
  generatePagesFromFigma,
9412
9455
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout3,
9413
- DesignSystemManager as DesignSystemManager11,
9456
+ DesignSystemManager as DesignSystemManager10,
9414
9457
  validateConfig,
9415
9458
  FRAMEWORK_VERSIONS as FRAMEWORK_VERSIONS2,
9416
9459
  CLI_VERSION as CLI_VERSION3
@@ -9645,8 +9688,8 @@ async function importFigmaAction(urlOrKey, opts) {
9645
9688
  if (!dryRun) {
9646
9689
  spinner.start("Updating design-system.config.ts...");
9647
9690
  const configPath = resolve11(projectRoot, DESIGN_SYSTEM_CONFIG_PATH);
9648
- const dsm = new DesignSystemManager11(configPath);
9649
- if (existsSync17(configPath)) {
9691
+ const dsm = new DesignSystemManager10(configPath);
9692
+ if (existsSync16(configPath)) {
9650
9693
  await dsm.load();
9651
9694
  const existing = dsm.getConfig();
9652
9695
  dsm.updateConfig({
@@ -9676,7 +9719,7 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
9676
9719
  spinner.succeed("design-system.config.ts updated");
9677
9720
  spinner.start("Ensuring root layout...");
9678
9721
  const layoutPath = join13(projectRoot, "app/layout.tsx");
9679
- if (!existsSync17(layoutPath)) {
9722
+ if (!existsSync16(layoutPath)) {
9680
9723
  await mkdir4(dirname6(layoutPath), { recursive: true });
9681
9724
  await writeFile5(layoutPath, MINIMAL_ROOT_LAYOUT, "utf-8");
9682
9725
  stats.filesWritten.push("app/layout.tsx");
@@ -9691,7 +9734,7 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
9691
9734
  stats.dsFilesWritten = dsFiles.length;
9692
9735
  spinner.succeed(`DS viewer: ${dsFiles.length} files`);
9693
9736
  try {
9694
- await writeCursorRules(projectRoot);
9737
+ await writeAllHarnessFiles(projectRoot);
9695
9738
  } catch (e) {
9696
9739
  if (process.env.COHERENT_DEBUG === "1") console.error(chalk23.dim("Could not update .cursorrules:"), e);
9697
9740
  }
@@ -9742,7 +9785,7 @@ function printReport(stats, opts) {
9742
9785
  // src/commands/ds.ts
9743
9786
  import chalk24 from "chalk";
9744
9787
  import ora7 from "ora";
9745
- import { DesignSystemManager as DesignSystemManager12 } from "@getcoherent/core";
9788
+ import { DesignSystemManager as DesignSystemManager11 } from "@getcoherent/core";
9746
9789
  async function dsRegenerateCommand() {
9747
9790
  try {
9748
9791
  const project = findConfig();
@@ -9750,7 +9793,7 @@ async function dsRegenerateCommand() {
9750
9793
  exitNotCoherent();
9751
9794
  }
9752
9795
  const spinner = ora7("Loading config and regenerating Design System pages...").start();
9753
- const dsm = new DesignSystemManager12(project.configPath);
9796
+ const dsm = new DesignSystemManager11(project.configPath);
9754
9797
  await dsm.load();
9755
9798
  const config2 = dsm.getConfig();
9756
9799
  const written = await writeDesignSystemFiles(project.root, config2);
@@ -9766,9 +9809,9 @@ async function dsRegenerateCommand() {
9766
9809
  // src/commands/update.ts
9767
9810
  import chalk25 from "chalk";
9768
9811
  import ora8 from "ora";
9769
- import { readFileSync as readFileSync12, existsSync as existsSync18 } from "fs";
9812
+ import { readFileSync as readFileSync12, existsSync as existsSync17 } from "fs";
9770
9813
  import { join as join14 } from "path";
9771
- import { DesignSystemManager as DesignSystemManager13, CLI_VERSION as CLI_VERSION4 } from "@getcoherent/core";
9814
+ import { DesignSystemManager as DesignSystemManager12, CLI_VERSION as CLI_VERSION4 } from "@getcoherent/core";
9772
9815
 
9773
9816
  // src/utils/migrations.ts
9774
9817
  var MIGRATIONS = [
@@ -9810,7 +9853,7 @@ async function updateCommand(opts) {
9810
9853
  }
9811
9854
  const spinner = ora8("Loading project configuration...").start();
9812
9855
  try {
9813
- const dsm = new DesignSystemManager13(project.configPath);
9856
+ const dsm = new DesignSystemManager12(project.configPath);
9814
9857
  await dsm.load();
9815
9858
  const config2 = dsm.getConfig();
9816
9859
  const projectVersion = config2.coherentVersion || "0.0.0";
@@ -9850,7 +9893,7 @@ async function updateCommand(opts) {
9850
9893
  const overlayFiles = await writeDesignSystemFiles(project.root, config2);
9851
9894
  report.overlayFiles = overlayFiles.length;
9852
9895
  spinner.text = "Updating .cursorrules and CLAUDE.md...";
9853
- const rulesResult = await writeCursorRules(project.root);
9896
+ const rulesResult = await writeAllHarnessFiles(project.root);
9854
9897
  report.rulesUpdated = rulesResult.written;
9855
9898
  spinner.text = "Checking globals.css...";
9856
9899
  report.missingCssVars = checkMissingCssVars(project.root);
@@ -9937,7 +9980,7 @@ var EXPECTED_CSS_VARS = [
9937
9980
  ];
9938
9981
  function checkMissingCssVars(projectRoot) {
9939
9982
  const globalsPath = join14(projectRoot, "app", "globals.css");
9940
- if (!existsSync18(globalsPath)) return [];
9983
+ if (!existsSync17(globalsPath)) return [];
9941
9984
  try {
9942
9985
  const content = readFileSync12(globalsPath, "utf-8");
9943
9986
  return EXPECTED_CSS_VARS.filter((v) => !content.includes(v));
@@ -9947,7 +9990,7 @@ function checkMissingCssVars(projectRoot) {
9947
9990
  }
9948
9991
  function patchGlobalsCss(projectRoot, missingVars) {
9949
9992
  const globalsPath = join14(projectRoot, "app", "globals.css");
9950
- if (!existsSync18(globalsPath) || missingVars.length === 0) return;
9993
+ if (!existsSync17(globalsPath) || missingVars.length === 0) return;
9951
9994
  const { writeFileSync: writeFileSync11 } = __require("fs");
9952
9995
  let content = readFileSync12(globalsPath, "utf-8");
9953
9996
  const defaultValues = {
@@ -10027,16 +10070,16 @@ async function undoCommand(options) {
10027
10070
  // src/commands/sync.ts
10028
10071
  import chalk27 from "chalk";
10029
10072
  import ora9 from "ora";
10030
- import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
10073
+ import { existsSync as existsSync18, readFileSync as readFileSync13 } from "fs";
10031
10074
  import { join as join15, relative as relative6, dirname as dirname7 } from "path";
10032
10075
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
10033
- import { DesignSystemManager as DesignSystemManager14 } from "@getcoherent/core";
10034
- import { loadManifest as loadManifest12, saveManifest as saveManifest6, findSharedComponent } from "@getcoherent/core";
10076
+ import { DesignSystemManager as DesignSystemManager13 } from "@getcoherent/core";
10077
+ import { loadManifest as loadManifest11, saveManifest as saveManifest6, findSharedComponent } from "@getcoherent/core";
10035
10078
  function extractTokensFromProject(projectRoot) {
10036
10079
  const lightColors = {};
10037
10080
  const darkColors = {};
10038
10081
  const globalsPath = join15(projectRoot, "app", "globals.css");
10039
- if (existsSync19(globalsPath)) {
10082
+ if (existsSync18(globalsPath)) {
10040
10083
  const css = readFileSync13(globalsPath, "utf-8");
10041
10084
  const rootMatch = css.match(/:root\s*\{([^}]+)\}/s);
10042
10085
  if (rootMatch) parseVarsInto(rootMatch[1], lightColors);
@@ -10045,7 +10088,7 @@ function extractTokensFromProject(projectRoot) {
10045
10088
  }
10046
10089
  const layoutPath = join15(projectRoot, "app", "layout.tsx");
10047
10090
  let layoutCode = "";
10048
- if (existsSync19(layoutPath)) {
10091
+ if (existsSync18(layoutPath)) {
10049
10092
  layoutCode = readFileSync13(layoutPath, "utf-8");
10050
10093
  const rootInline = layoutCode.match(/:root\s*\{([^}]+)\}/s);
10051
10094
  if (rootInline && Object.keys(lightColors).length === 0) {
@@ -10064,7 +10107,7 @@ function extractTokensFromProject(projectRoot) {
10064
10107
  defaultMode = "dark";
10065
10108
  }
10066
10109
  let radius;
10067
- const allCss = [existsSync19(globalsPath) ? readFileSync13(globalsPath, "utf-8") : "", layoutCode].join("\n");
10110
+ const allCss = [existsSync18(globalsPath) ? readFileSync13(globalsPath, "utf-8") : "", layoutCode].join("\n");
10068
10111
  const radiusMatch = allCss.match(/--radius:\s*([^;]+);/);
10069
10112
  if (radiusMatch) radius = radiusMatch[1].trim();
10070
10113
  return {
@@ -10088,7 +10131,7 @@ function parseVarsInto(block, target) {
10088
10131
  async function detectCustomComponents(projectRoot, allPageCode) {
10089
10132
  const results = [];
10090
10133
  const componentsDir = join15(projectRoot, "components");
10091
- if (!existsSync19(componentsDir)) return results;
10134
+ if (!existsSync18(componentsDir)) return results;
10092
10135
  const files = [];
10093
10136
  await walkForTsx(componentsDir, files, ["ui"]);
10094
10137
  const fileResults = await Promise.all(
@@ -10279,11 +10322,11 @@ async function syncCommand(options = {}) {
10279
10322
  const spinner = ora9("Scanning project files...").start();
10280
10323
  try {
10281
10324
  const appDir = join15(project.root, "app");
10282
- if (!existsSync19(appDir)) {
10325
+ if (!existsSync18(appDir)) {
10283
10326
  spinner.fail("No app/ directory found");
10284
10327
  process.exit(1);
10285
10328
  }
10286
- const dsm = new DesignSystemManager14(project.configPath);
10329
+ const dsm = new DesignSystemManager13(project.configPath);
10287
10330
  await dsm.load();
10288
10331
  const config2 = dsm.getConfig();
10289
10332
  const discoveredPages = await discoverPages(appDir);
@@ -10323,7 +10366,7 @@ async function syncCommand(options = {}) {
10323
10366
  let reconcileResult = null;
10324
10367
  if (doComponents) {
10325
10368
  spinner.start("Reconciling shared components...");
10326
- const manifest = await loadManifest12(project.root);
10369
+ const manifest = await loadManifest11(project.root);
10327
10370
  const { manifest: reconciledManifest, result: rr } = reconcileComponents(project.root, manifest);
10328
10371
  reconcileResult = rr;
10329
10372
  if (!dryRun) {
@@ -10411,9 +10454,8 @@ async function syncCommand(options = {}) {
10411
10454
  const written = await writeDesignSystemFiles(project.root, config2);
10412
10455
  spinner.succeed(`Regenerated ${written.length} Design System file(s)`);
10413
10456
  spinner.start("Updating AI context files...");
10414
- await writeCursorRules(project.root);
10415
- await generateClaudeCodeFiles(project.root);
10416
- spinner.succeed("Updated .cursorrules and CLAUDE.md");
10457
+ await writeAllHarnessFiles(project.root);
10458
+ spinner.succeed("Updated .cursorrules, CLAUDE.md, and AGENTS.md");
10417
10459
  }
10418
10460
  console.log("");
10419
10461
  console.log(chalk27.green(`\u2705 Design System ${dryRun ? "analyzed" : "synced"} with actual code
@@ -10509,7 +10551,7 @@ async function syncCommand(options = {}) {
10509
10551
  // src/commands/migrate.ts
10510
10552
  import chalk28 from "chalk";
10511
10553
  import ora10 from "ora";
10512
- import { existsSync as existsSync20, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync9, readFileSync as readFileSync14, readdirSync as readdirSync9 } from "fs";
10554
+ import { existsSync as existsSync19, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync9, readFileSync as readFileSync14, readdirSync as readdirSync9 } from "fs";
10513
10555
  import { join as join16 } from "path";
10514
10556
  function backupDir(projectRoot) {
10515
10557
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
@@ -10522,11 +10564,11 @@ function createBackup2(projectRoot) {
10522
10564
  const uiDir = join16(projectRoot, "components", "ui");
10523
10565
  const dest = backupDir(projectRoot);
10524
10566
  mkdirSync8(dest, { recursive: true });
10525
- if (existsSync20(uiDir)) {
10567
+ if (existsSync19(uiDir)) {
10526
10568
  cpSync(uiDir, join16(dest, "components-ui"), { recursive: true });
10527
10569
  }
10528
10570
  const configPath = join16(projectRoot, "design-system.config.ts");
10529
- if (existsSync20(configPath)) {
10571
+ if (existsSync19(configPath)) {
10530
10572
  cpSync(configPath, join16(dest, "design-system.config.ts"));
10531
10573
  }
10532
10574
  return dest;
@@ -10538,24 +10580,24 @@ function setGuard(projectRoot, backupPath) {
10538
10580
  }
10539
10581
  function clearGuard(projectRoot) {
10540
10582
  const guard = guardPath(projectRoot);
10541
- if (existsSync20(guard)) rmSync6(guard);
10583
+ if (existsSync19(guard)) rmSync6(guard);
10542
10584
  }
10543
10585
  function rollback(projectRoot) {
10544
10586
  const guard = guardPath(projectRoot);
10545
- if (!existsSync20(guard)) return false;
10587
+ if (!existsSync19(guard)) return false;
10546
10588
  try {
10547
10589
  const data = JSON.parse(readFileSync14(guard, "utf-8"));
10548
10590
  const backup = data.backup;
10549
- if (!existsSync20(backup)) return false;
10591
+ if (!existsSync19(backup)) return false;
10550
10592
  const uiBackup = join16(backup, "components-ui");
10551
10593
  const uiDir = join16(projectRoot, "components", "ui");
10552
- if (existsSync20(uiBackup)) {
10553
- if (existsSync20(uiDir)) rmSync6(uiDir, { recursive: true });
10594
+ if (existsSync19(uiBackup)) {
10595
+ if (existsSync19(uiDir)) rmSync6(uiDir, { recursive: true });
10554
10596
  cpSync(uiBackup, uiDir, { recursive: true });
10555
10597
  }
10556
10598
  const configBackup = join16(backup, "design-system.config.ts");
10557
10599
  const configDest = join16(projectRoot, "design-system.config.ts");
10558
- if (existsSync20(configBackup)) {
10600
+ if (existsSync19(configBackup)) {
10559
10601
  cpSync(configBackup, configDest);
10560
10602
  }
10561
10603
  clearGuard(projectRoot);
@@ -10583,13 +10625,13 @@ async function migrateAction(options) {
10583
10625
  return;
10584
10626
  }
10585
10627
  const guard = guardPath(projectRoot);
10586
- if (existsSync20(guard)) {
10628
+ if (existsSync19(guard)) {
10587
10629
  console.log(chalk28.yellow("A migration is already in progress."));
10588
10630
  console.log(chalk28.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
10589
10631
  return;
10590
10632
  }
10591
10633
  const uiDir = join16(projectRoot, "components", "ui");
10592
- if (!existsSync20(uiDir)) {
10634
+ if (!existsSync19(uiDir)) {
10593
10635
  console.log(chalk28.yellow("No components/ui directory found. Nothing to migrate."));
10594
10636
  return;
10595
10637
  }
@@ -10616,7 +10658,7 @@ Found ${migratable.length} component(s) to migrate:`));
10616
10658
  try {
10617
10659
  for (const id of migratable) {
10618
10660
  const filePath = join16(uiDir, `${id}.tsx`);
10619
- if (existsSync20(filePath)) rmSync6(filePath);
10661
+ if (existsSync19(filePath)) rmSync6(filePath);
10620
10662
  }
10621
10663
  const results = await provider.installBatch(migratable, projectRoot, { force: true });
10622
10664
  let migrated = 0;
@@ -10638,7 +10680,7 @@ Found ${migratable.length} component(s) to migrate:`));
10638
10680
  }
10639
10681
 
10640
10682
  // src/utils/update-notifier.ts
10641
- import { existsSync as existsSync21, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "fs";
10683
+ import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "fs";
10642
10684
  import { join as join17 } from "path";
10643
10685
  import { homedir } from "os";
10644
10686
  import chalk29 from "chalk";
@@ -10650,7 +10692,7 @@ var CACHE_FILE = join17(CACHE_DIR, "update-check.json");
10650
10692
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10651
10693
  function readCache() {
10652
10694
  try {
10653
- if (!existsSync21(CACHE_FILE)) return null;
10695
+ if (!existsSync20(CACHE_FILE)) return null;
10654
10696
  const raw = readFileSync15(CACHE_FILE, "utf-8");
10655
10697
  return JSON.parse(raw);
10656
10698
  } catch (e) {
@@ -10660,7 +10702,7 @@ function readCache() {
10660
10702
  }
10661
10703
  function writeCache(data) {
10662
10704
  try {
10663
- if (!existsSync21(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10705
+ if (!existsSync20(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10664
10706
  writeFileSync10(CACHE_FILE, JSON.stringify(data), "utf-8");
10665
10707
  } catch (e) {
10666
10708
  if (DEBUG5) console.error("Failed to write update cache:", e);