@getcoherent/cli 0.5.15 → 0.6.1

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.
package/dist/index.js CHANGED
@@ -1,3 +1,11 @@
1
+ import {
2
+ generateArchitecturePlan,
3
+ getPageGroup,
4
+ getPageType,
5
+ loadPlan,
6
+ routeToKey,
7
+ savePlan
8
+ } from "./chunk-INW3BQSX.js";
1
9
  import {
2
10
  __require
3
11
  } from "./chunk-3RG5ZIWI.js";
@@ -1984,8 +1992,8 @@ function fixEscapedClosingQuotes(code) {
1984
1992
  }
1985
1993
  function fixUnescapedLtInJsx(code) {
1986
1994
  let out = code;
1987
- out = out.replace(/>([^<]*)<(\d)/g, ">$1&lt;$2");
1988
- out = out.replace(/>([^<]*)<([^/a-zA-Z!{>])/g, ">$1&lt;$2");
1995
+ out = out.replace(/>([^<\n]*)<(\d)/g, ">$1&lt;$2");
1996
+ out = out.replace(/>([^<\n]*)<([^/a-zA-Z!{>\n])/g, ">$1&lt;$2");
1989
1997
  return out;
1990
1998
  }
1991
1999
 
@@ -3745,7 +3753,7 @@ async function createAppRouteGroupLayout(projectPath) {
3745
3753
  }
3746
3754
 
3747
3755
  // src/commands/chat.ts
3748
- import chalk13 from "chalk";
3756
+ import chalk14 from "chalk";
3749
3757
  import ora2 from "ora";
3750
3758
  import { resolve as resolve9, relative as relative2, join as join11 } from "path";
3751
3759
  import { existsSync as existsSync16, readFileSync as readFileSync11, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
@@ -3832,7 +3840,7 @@ Please set ${envVar} in your environment or .env file.`);
3832
3840
  }
3833
3841
  if (preferredProvider === "openai") {
3834
3842
  try {
3835
- const { OpenAIClient } = await import("./openai-provider-FSXSVEYD.js");
3843
+ const { OpenAIClient } = await import("./openai-provider-XUI7ZHUR.js");
3836
3844
  return await OpenAIClient.create(apiKey2, config2?.model);
3837
3845
  } catch (error) {
3838
3846
  if (error.message?.includes("not installed")) {
@@ -3846,7 +3854,7 @@ Error: ${error.message}`
3846
3854
  );
3847
3855
  }
3848
3856
  } else {
3849
- const { ClaudeClient } = await import("./claude-RFHVT7RC.js");
3857
+ const { ClaudeClient } = await import("./claude-BZ3HSBD3.js");
3850
3858
  return ClaudeClient.create(apiKey2, config2?.model);
3851
3859
  }
3852
3860
  }
@@ -3859,7 +3867,7 @@ Error: ${error.message}`
3859
3867
  switch (provider) {
3860
3868
  case "openai":
3861
3869
  try {
3862
- const { OpenAIClient } = await import("./openai-provider-FSXSVEYD.js");
3870
+ const { OpenAIClient } = await import("./openai-provider-XUI7ZHUR.js");
3863
3871
  return await OpenAIClient.create(apiKey, config2?.model);
3864
3872
  } catch (error) {
3865
3873
  if (error.message?.includes("not installed")) {
@@ -3873,7 +3881,7 @@ Error: ${error.message}`
3873
3881
  );
3874
3882
  }
3875
3883
  case "claude":
3876
- const { ClaudeClient } = await import("./claude-RFHVT7RC.js");
3884
+ const { ClaudeClient } = await import("./claude-BZ3HSBD3.js");
3877
3885
  return ClaudeClient.create(apiKey, config2?.model);
3878
3886
  default:
3879
3887
  throw new Error(`Unsupported AI provider: ${provider}`);
@@ -3894,7 +3902,7 @@ var PAGE_TEMPLATES = {
3894
3902
  login: {
3895
3903
  description: "Login page with centered card form",
3896
3904
  sections: [
3897
- 'Centered layout: outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10". Inner div className="w-full max-w-sm".',
3905
+ 'Centered layout: outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10". Inner div className="w-full max-w-md".',
3898
3906
  'Card with CardHeader: CardTitle "Sign in" (text-2xl font-bold), CardDescription "Enter your credentials to access your account" (text-sm text-muted-foreground).',
3899
3907
  'CardContent with form: email Input (type="email", placeholder="you@example.com"), password Input (type="password"), a "Forgot password?" link (text-sm text-muted-foreground hover:text-foreground), and a Button "Sign in" (w-full).',
3900
3908
  `CardFooter: text "Don't have an account?" with a Sign up link. All text is text-sm text-muted-foreground.`,
@@ -3915,7 +3923,7 @@ var PAGE_TEMPLATES = {
3915
3923
  register: {
3916
3924
  description: "Registration page with centered card form",
3917
3925
  sections: [
3918
- 'Centered layout: outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10". Inner div className="w-full max-w-sm".',
3926
+ 'Centered layout: outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10". Inner div className="w-full max-w-md".',
3919
3927
  'Card with CardHeader: CardTitle "Create an account" (text-2xl font-bold), CardDescription "Enter your details to get started" (text-sm text-muted-foreground).',
3920
3928
  'CardContent with form: name Input, email Input (type="email"), password Input (type="password"), confirm password Input (type="password"), and a Button "Create account" (w-full).',
3921
3929
  'CardFooter: text "Already have an account?" with a Sign in link. All text is text-sm text-muted-foreground.',
@@ -4089,7 +4097,7 @@ var PAGE_TEMPLATES = {
4089
4097
  "reset-password": {
4090
4098
  description: "Reset password page with centered card form",
4091
4099
  sections: [
4092
- 'Centered layout: outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10". Inner div className="w-full max-w-sm".',
4100
+ 'Centered layout: outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10". Inner div className="w-full max-w-md".',
4093
4101
  'Card with CardHeader: CardTitle "Reset Password" (text-xl), CardDescription.',
4094
4102
  'CardContent with form: new password Input (type="password"), confirm password Input (type="password"), Button "Reset password" (w-full).',
4095
4103
  'Footer text: "Remember your password?" with Sign in link.',
@@ -4101,6 +4109,7 @@ var PAGE_TEMPLATES = {
4101
4109
  var AUTH_ROUTE_SEGMENTS = /* @__PURE__ */ new Set([
4102
4110
  "login",
4103
4111
  "signin",
4112
+ "sign-in",
4104
4113
  "sign-up",
4105
4114
  "signup",
4106
4115
  "register",
@@ -4197,7 +4206,7 @@ LAYOUT PATTERNS:
4197
4206
  - Stats/KPI grid: grid gap-4 md:grid-cols-2 lg:grid-cols-4
4198
4207
  - Card grid (3 col): grid gap-4 md:grid-cols-3
4199
4208
  - Full-height page: min-h-svh (not min-h-screen)
4200
- - Centered form (login/signup): flex min-h-svh flex-col items-center justify-center p-6 md:p-10 \u2192 div w-full max-w-sm
4209
+ - Centered form (login/signup): flex min-h-svh flex-col items-center justify-center p-6 md:p-10 \u2192 div w-full max-w-md
4201
4210
  - Page content wrapper: flex flex-1 flex-col gap-4 p-4 lg:p-6
4202
4211
  - Responsive: primary md: and lg:. Use sm:/xl: only when genuinely needed. Avoid 2xl:. NEVER arbitrary like min-[800px].
4203
4212
 
@@ -4249,12 +4258,11 @@ CONTENT (zero placeholders):
4249
4258
  - NEVER: "Lorem ipsum", "Card content", "Description here"
4250
4259
  - ALWAYS: Real, contextual content. Realistic metric names, values, dates.
4251
4260
  `;
4252
- var DESIGN_QUALITY = `
4253
- ## DESIGN QUALITY (apply to EVERY page)
4261
+ var DESIGN_QUALITY_COMMON = `
4262
+ ## DESIGN QUALITY \u2014 COMMON
4254
4263
 
4255
4264
  ### Typography Hierarchy
4256
4265
  - Page headline (h1): text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight leading-[1.1]
4257
- - Landing/marketing hero headline: text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight leading-[1.05]
4258
4266
  - Section titles (h2): text-2xl md:text-3xl font-bold
4259
4267
  - Card titles (h3): text-sm font-semibold (never text-base or text-lg)
4260
4268
  - Body text: text-sm text-muted-foreground leading-relaxed
@@ -4267,6 +4275,29 @@ var DESIGN_QUALITY = `
4267
4275
  - Sections alternate between bg-background and bg-muted/5 for rhythm
4268
4276
  - Section dividers: border-t border-border/10 (subtle, not heavy)
4269
4277
 
4278
+ ### Buttons with Icons
4279
+ - Buttons containing text + icon: ALWAYS use inline-flex items-center gap-2 whitespace-nowrap
4280
+ - Icon inside button: h-4 w-4 (never larger), placed AFTER text for arrows, BEFORE text for action icons
4281
+ - NEVER let button content wrap to multiple lines \u2014 use whitespace-nowrap on the Button component
4282
+ - CTA buttons: use the Button component, NEVER raw <button> or <a> styled as button
4283
+
4284
+ ### Accent Color Discipline
4285
+ - ONE accent color per page (primary or emerald-400)
4286
+ - Use for: CTAs, terminal text, check icons, feature icon backgrounds, active states
4287
+ - NEVER mix blue + purple + emerald on same page
4288
+ - Badge: outline style (border-border/30 bg-transparent) not filled color
4289
+ - Status icons: text-emerald-400 for positive, text-red-400 for negative
4290
+
4291
+ ### Dark Theme Implementation
4292
+ - html element: className="dark"
4293
+ - Background: use CSS variables from globals.css dark section
4294
+ - Text: text-foreground for primary, text-muted-foreground for secondary
4295
+ - NEVER hardcode dark colors (bg-gray-900) \u2014 always use semantic tokens
4296
+ - Cards and elevated elements: slightly lighter than background (bg-card or bg-zinc-900/50)
4297
+ `;
4298
+ var DESIGN_QUALITY_MARKETING = `
4299
+ ## DESIGN QUALITY \u2014 MARKETING PAGES
4300
+
4270
4301
  ### Spacing Rhythm (3 distinct levels)
4271
4302
  - Between sections: py-20 md:py-28 (generous)
4272
4303
  - Within sections (title to content): mb-12 md:mb-16
@@ -4274,11 +4305,8 @@ var DESIGN_QUALITY = `
4274
4305
  - Between cards in grid: gap-5 (tight)
4275
4306
  - NEVER uniform spacing everywhere \u2014 contrast creates rhythm
4276
4307
 
4277
- ### Buttons with Icons
4278
- - Buttons containing text + icon: ALWAYS use inline-flex items-center gap-2 whitespace-nowrap
4279
- - Icon inside button: h-4 w-4 (never larger), placed AFTER text for arrows, BEFORE text for action icons
4280
- - NEVER let button content wrap to multiple lines \u2014 use whitespace-nowrap on the Button component
4281
- - CTA buttons: use the Button component, NEVER raw <button> or <a> styled as button
4308
+ ### Hero headline
4309
+ - Landing/marketing hero headline: text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight leading-[1.05]
4282
4310
 
4283
4311
  ### Icons in Feature Cards
4284
4312
  - Wrap in colored container: bg-primary/10 rounded-lg p-2.5
@@ -4294,14 +4322,7 @@ var DESIGN_QUALITY = `
4294
4322
  - Title bar (optional): flex with 3 dots (bg-zinc-700 rounded-full w-2.5 h-2.5) + title text-zinc-500 text-[11px]
4295
4323
  - Copy button: text-zinc-500 hover:text-zinc-300
4296
4324
 
4297
- ### Accent Color Discipline
4298
- - ONE accent color per page (primary or emerald-400)
4299
- - Use for: CTAs, terminal text, check icons, feature icon backgrounds, active states
4300
- - NEVER mix blue + purple + emerald on same page
4301
- - Badge: outline style (border-border/30 bg-transparent) not filled color
4302
- - Status icons: text-emerald-400 for positive, text-red-400 for negative
4303
-
4304
- ### Hero Section (landing/marketing pages)
4325
+ ### Hero Section
4305
4326
  - Minimum height: min-h-[80vh] flex items-center justify-center
4306
4327
  - Content: centered, max-w-3xl, flex flex-col items-center text-center gap-8
4307
4328
  - Badge above headline: small, outline, text-xs tracking-wide
@@ -4318,8 +4339,6 @@ var DESIGN_QUALITY = `
4318
4339
  ### Step/Process Sections
4319
4340
  - Numbered steps: circle with border, number inside (w-10 h-10 rounded-full border border-border/30 text-sm)
4320
4341
  - Label above: text-xs font-semibold tracking-widest uppercase text-muted-foreground
4321
- - Each step has a code block showing the command
4322
- - Description below: text-sm text-muted-foreground
4323
4342
 
4324
4343
  ### Footer
4325
4344
  - Minimal: border-t border-border/10, py-10
@@ -4327,13 +4346,80 @@ var DESIGN_QUALITY = `
4327
4346
  - Links: hover:text-foreground transition-colors
4328
4347
  - Layout: flex justify-between on desktop, stack on mobile
4329
4348
 
4330
- ### Dark Theme Implementation
4331
- - html element: className="dark"
4332
- - Background: use CSS variables from globals.css dark section
4333
- - Text: text-foreground for primary, text-muted-foreground for secondary
4334
- - NEVER hardcode dark colors (bg-gray-900) \u2014 always use semantic tokens
4335
- - Cards and elevated elements: slightly lighter than background (bg-card or bg-zinc-900/50)
4349
+ NEVER include app-style elements (sidebar widgets, data tables, filters) on marketing pages.
4350
+ `;
4351
+ var DESIGN_QUALITY_APP = `
4352
+ ## DESIGN QUALITY \u2014 APP PAGES
4353
+
4354
+ ### Spacing
4355
+ - gap-4 md:gap-6 between sections
4356
+ - p-4 lg:p-6 content padding
4357
+ - Within cards: p-4 to p-6 (compact)
4358
+ - Between cards in grid: gap-4 (tight)
4359
+
4360
+ ### Layout
4361
+ - Data tables, card grids, filters, stat rows
4362
+ - Page wrapper: flex flex-1 flex-col gap-4 p-4 lg:p-6
4363
+ - Stats grid: grid gap-4 md:grid-cols-2 lg:grid-cols-4
4364
+ - Content: functional, scannable, data-dense
4365
+
4366
+ ### Toolbars & Filters
4367
+ - Filter row: flex flex-wrap items-center gap-2
4368
+ - Search input: MUST use flex-1 to fill remaining horizontal space
4369
+ - Filters/selects: fixed width (w-[180px] or auto), do NOT flex-grow
4370
+ - On mobile (sm:): search full width, filters wrap to next line
4371
+
4372
+ NEVER include marketing sections (hero, pricing, testimonials) on app pages.
4373
+ `;
4374
+ var DESIGN_QUALITY_AUTH = `
4375
+ ## DESIGN QUALITY \u2014 AUTH PAGES
4376
+
4377
+ ### Layout
4378
+ - Centered card: flex min-h-svh items-center justify-center p-6 md:p-10
4379
+ - Card width: w-full max-w-md
4380
+ - No navigation, no section containers, no sidebar
4381
+ - Single focused form with clear CTA
4382
+ - Card \u2192 CardHeader (title + description) \u2192 CardContent (form) \u2192 CardFooter (link to other auth page)
4383
+
4384
+ NEVER include navigation bars, sidebars, or multi-section layouts on auth pages.
4385
+ `;
4386
+ var DESIGN_QUALITY_CRITICAL = `
4387
+ ## CRITICAL CODE RULES (violations will be auto-corrected)
4388
+ - Every lucide-react icon MUST have className="... shrink-0" to prevent flex squishing
4389
+ - Button with asChild wrapping Link: the inner element MUST have className="inline-flex items-center gap-2"
4390
+ - NEVER use raw Tailwind colors (bg-blue-500, text-gray-600). ONLY semantic tokens: bg-primary, text-muted-foreground, etc.
4391
+ - <Link> and <a> MUST always have an href attribute. Never omit href.
4392
+ - CardTitle: NEVER add text-xl, text-2xl, text-lg. CardTitle is text-sm font-medium by default.
4336
4393
  `;
4394
+ function getDesignQualityForType(type) {
4395
+ switch (type) {
4396
+ case "marketing":
4397
+ return DESIGN_QUALITY_MARKETING + DESIGN_QUALITY_CRITICAL;
4398
+ case "app":
4399
+ return DESIGN_QUALITY_APP + DESIGN_QUALITY_CRITICAL;
4400
+ case "auth":
4401
+ return DESIGN_QUALITY_AUTH + DESIGN_QUALITY_CRITICAL;
4402
+ }
4403
+ }
4404
+ function inferPageTypeFromRoute(route) {
4405
+ const slug = route.replace(/^\//, "").split("/")[0] || "";
4406
+ const authSlugs = /* @__PURE__ */ new Set([
4407
+ "login",
4408
+ "register",
4409
+ "sign-up",
4410
+ "signup",
4411
+ "sign-in",
4412
+ "signin",
4413
+ "forgot-password",
4414
+ "reset-password"
4415
+ ]);
4416
+ const marketingSlugs = /* @__PURE__ */ new Set(["pricing", "features", "about", "blog", "contact", "terms", "privacy"]);
4417
+ if (authSlugs.has(slug)) return "auth";
4418
+ if (marketingSlugs.has(slug) || slug === "") return "marketing";
4419
+ return "app";
4420
+ }
4421
+ var DESIGN_QUALITY = `${DESIGN_QUALITY_COMMON}
4422
+ ${DESIGN_QUALITY_MARKETING}`;
4337
4423
  var VISUAL_DEPTH = `
4338
4424
  ## VISUAL DEPTH TECHNIQUES (pick 1-3 per page based on context)
4339
4425
 
@@ -5210,7 +5296,7 @@ pageCode rules (shadcn/ui blocks quality):
5210
5296
  - Full Next.js App Router page. Imports from '@/components/ui/...' for registry components.
5211
5297
  - Follow ALL design constraints above: text-sm base, semantic colors only, restricted spacing, weight-based hierarchy.
5212
5298
  - Stat card pattern: Card > CardHeader(flex flex-row items-center justify-between space-y-0 pb-2) > CardTitle(text-sm font-medium) + Icon(size-4 text-muted-foreground) ; CardContent > metric(text-2xl font-bold) + change(text-xs text-muted-foreground).
5213
- - Login/form pattern: outer div(flex min-h-svh flex-col items-center justify-center p-6 md:p-10) > inner div(w-full max-w-sm) > Card with form.
5299
+ - Login/form pattern: outer div(flex min-h-svh flex-col items-center justify-center p-6 md:p-10) > inner div(w-full max-w-md) > Card with form.
5214
5300
  - Dashboard pattern: div(space-y-6) > page header(h1 text-2xl font-bold tracking-tight + p text-sm text-muted-foreground) > stats grid(grid gap-4 md:grid-cols-2 lg:grid-cols-4) > content cards. No <main> wrapper \u2014 the layout provides it.
5215
5301
  - No placeholders: real contextual copy only. Use the EXACT text, language, and content from the user's request.
5216
5302
  - IMAGES: For avatar/profile photos, use https://i.pravatar.cc/150?u=<unique-seed> (e.g. ?u=sarah.johnson). For hero/product images, use https://picsum.photos/800/400?random=N. Use standard <img> tags with className, NOT Next.js <Image>. Always provide alt text.
@@ -5335,11 +5421,14 @@ Return valid JSON only, no markdown code fence. Use this shape:
5335
5421
  { "requests": [ ... array of ModificationRequest ... ], "uxRecommendations": "optional markdown or omit key" }
5336
5422
  Legacy: returning only a JSON array of requests is still accepted.`;
5337
5423
  }
5338
- function buildLightweightPagePrompt(pageName, route, styleContext, sharedComponentsSummary) {
5424
+ function buildLightweightPagePrompt(pageName, route, styleContext, sharedComponentsSummary, pageType) {
5425
+ const designConstraints = pageType ? getDesignQualityForType(pageType) : "";
5339
5426
  return [
5340
5427
  `Generate complete pageCode for a page called "${pageName}" at route "${route}".`,
5341
5428
  `Output valid TSX with a default export React component.`,
5342
5429
  `Use shadcn/ui components (import from @/components/ui/*). Use Tailwind CSS semantic tokens only.`,
5430
+ pageType ? `PAGE TYPE: ${pageType}` : "",
5431
+ designConstraints,
5343
5432
  styleContext ? `Follow this style context:
5344
5433
  ${styleContext}` : "",
5345
5434
  sharedComponentsSummary ? `Available shared components:
@@ -5989,7 +6078,7 @@ function checkLines(code, pattern, type, message, severity, skipCommentsAndStrin
5989
6078
  }
5990
6079
  return issues;
5991
6080
  }
5992
- function validatePageQuality(code, validRoutes) {
6081
+ function validatePageQuality(code, validRoutes, pageType) {
5993
6082
  const issues = [];
5994
6083
  const allLines = code.split("\n");
5995
6084
  const isTerminalContext = (lineNum) => {
@@ -6159,21 +6248,23 @@ function validatePageQuality(code, validRoutes) {
6159
6248
  "warning"
6160
6249
  )
6161
6250
  );
6162
- const h1Matches = code.match(/<h1[\s>]/g);
6163
- if (!h1Matches || h1Matches.length === 0) {
6164
- issues.push({
6165
- line: 0,
6166
- type: "NO_H1",
6167
- message: "Page has no <h1> \u2014 every page should have exactly one h1 heading",
6168
- severity: "warning"
6169
- });
6170
- } else if (h1Matches.length > 1) {
6171
- issues.push({
6172
- line: 0,
6173
- type: "MULTIPLE_H1",
6174
- message: `Page has ${h1Matches.length} <h1> elements \u2014 use exactly one per page`,
6175
- severity: "warning"
6176
- });
6251
+ if (pageType !== "auth") {
6252
+ const h1Matches = code.match(/<h1[\s>]/g);
6253
+ if (!h1Matches || h1Matches.length === 0) {
6254
+ issues.push({
6255
+ line: 0,
6256
+ type: "NO_H1",
6257
+ message: "Page has no <h1> \u2014 every page should have exactly one h1 heading",
6258
+ severity: "warning"
6259
+ });
6260
+ } else if (h1Matches.length > 1) {
6261
+ issues.push({
6262
+ line: 0,
6263
+ type: "MULTIPLE_H1",
6264
+ message: `Page has ${h1Matches.length} <h1> elements \u2014 use exactly one per page`,
6265
+ severity: "warning"
6266
+ });
6267
+ }
6177
6268
  }
6178
6269
  const headingLevels = [...code.matchAll(/<h([1-6])[\s>]/g)].map((m) => parseInt(m[1]));
6179
6270
  const hasCardContext = /\bCard\b|\bCardTitle\b|\bCardHeader\b/.test(code);
@@ -6347,6 +6438,24 @@ function validatePageQuality(code, validRoutes) {
6347
6438
  issues.push(...detectComponentIssues(code));
6348
6439
  return issues;
6349
6440
  }
6441
+ function resolveHref(linkText, context) {
6442
+ if (!context) return "/";
6443
+ const text = linkText.trim().toLowerCase();
6444
+ if (context.linkMap) {
6445
+ for (const [label, route] of Object.entries(context.linkMap)) {
6446
+ if (label.toLowerCase() === text) return route;
6447
+ }
6448
+ }
6449
+ if (context.knownRoutes) {
6450
+ const cleaned = text.replace(/^(back\s+to|go\s+to|view\s+all|see\s+all|return\s+to)\s+/i, "").trim();
6451
+ for (const route of context.knownRoutes) {
6452
+ const slug = route.split("/").filter(Boolean).pop() || "";
6453
+ const routeName = slug.replace(/[-_]/g, " ");
6454
+ if (routeName && cleaned === routeName) return route;
6455
+ }
6456
+ }
6457
+ return "/";
6458
+ }
6350
6459
  function replaceRawColors(classes, colorMap) {
6351
6460
  let changed = false;
6352
6461
  let result = classes;
@@ -6439,7 +6548,7 @@ function replaceRawColors(classes, colorMap) {
6439
6548
  });
6440
6549
  return { result, changed };
6441
6550
  }
6442
- async function autoFixCode(code) {
6551
+ async function autoFixCode(code, context) {
6443
6552
  const fixes = [];
6444
6553
  let fixed = code;
6445
6554
  const beforeQuoteFix = fixed;
@@ -6449,11 +6558,36 @@ async function autoFixCode(code) {
6449
6558
  fixes.push("fixed escaped closing quotes in strings");
6450
6559
  }
6451
6560
  const beforeEntityFix = fixed;
6452
- fixed = fixed.replace(/&lt;=/g, "<=");
6453
- fixed = fixed.replace(/&gt;=/g, ">=");
6454
- fixed = fixed.replace(/&amp;&amp;/g, "&&");
6455
- fixed = fixed.replace(/([\w)\]])\s*&lt;\s*([\w(])/g, "$1 < $2");
6456
- fixed = fixed.replace(/([\w)\]])\s*&gt;\s*([\w(])/g, "$1 > $2");
6561
+ const isInsideAttrValue = (line, idx) => {
6562
+ let inQuote = false;
6563
+ let inAttr = false;
6564
+ for (let i = 0; i < idx; i++) {
6565
+ if (line[i] === "=" && line[i + 1] === '"') {
6566
+ inAttr = true;
6567
+ inQuote = true;
6568
+ i++;
6569
+ } else if (inAttr && line[i] === '"') {
6570
+ inAttr = false;
6571
+ inQuote = false;
6572
+ }
6573
+ }
6574
+ return inQuote;
6575
+ };
6576
+ fixed = fixed.split("\n").map((line) => {
6577
+ let l = line;
6578
+ l = l.replace(/&lt;=/g, (m, offset) => isInsideAttrValue(line, offset) ? m : "<=");
6579
+ l = l.replace(/&gt;=/g, (m, offset) => isInsideAttrValue(line, offset) ? m : ">=");
6580
+ l = l.replace(/&amp;&amp;/g, (m, offset) => isInsideAttrValue(line, offset) ? m : "&&");
6581
+ l = l.replace(
6582
+ /([\w)\]])\s*&lt;\s*([\w(])/g,
6583
+ (m, p1, p2, offset) => isInsideAttrValue(line, offset) ? m : `${p1} < ${p2}`
6584
+ );
6585
+ l = l.replace(
6586
+ /([\w)\]])\s*&gt;\s*([\w(])/g,
6587
+ (m, p1, p2, offset) => isInsideAttrValue(line, offset) ? m : `${p1} > ${p2}`
6588
+ );
6589
+ return l;
6590
+ }).join("\n");
6457
6591
  if (fixed !== beforeEntityFix) {
6458
6592
  fixes.push("Fixed syntax issues");
6459
6593
  }
@@ -6801,9 +6935,14 @@ ${selectImport}`
6801
6935
  fixes.push("added inline-flex to Button asChild children (base-ui compat)");
6802
6936
  }
6803
6937
  const beforeLinkHrefFix = fixed;
6804
- fixed = fixed.replace(/<(Link|a)\b(?![^>]*\bhref\s*=)([^>]*)>/g, '<$1 href="/"$2>');
6938
+ fixed = fixed.replace(/<(Link|a)\b(?![^>]*\bhref\s*=)([^>]*)>([\s\S]*?)<\/\1>/g, (_match, tag, attrs, children) => {
6939
+ const textContent = children.replace(/<[^>]*>/g, "").trim();
6940
+ const href = resolveHref(textContent, context);
6941
+ return `<${tag} href="${href}"${attrs}>${children}</${tag}>`;
6942
+ });
6943
+ fixed = fixed.replace(/<(Link|a)\b(?![^>]*\bhref\s*=)([^>]*)\/?>/g, '<$1 href="/"$2>');
6805
6944
  if (fixed !== beforeLinkHrefFix) {
6806
- fixes.push('added href="/" to <Link>/<a> missing href');
6945
+ fixes.push("added href to <Link>/<a> missing href");
6807
6946
  }
6808
6947
  const { code: fixedByRules, fixes: ruleFixes } = applyComponentRules(fixed);
6809
6948
  if (ruleFixes.length > 0) {
@@ -6928,7 +7067,16 @@ import { DesignSystemManager as DesignSystemManager3, loadManifest as loadManife
6928
7067
  import chalk8 from "chalk";
6929
7068
  var MARKETING_ROUTES = /* @__PURE__ */ new Set(["", "landing", "pricing", "about", "contact", "blog", "features"]);
6930
7069
  var MIN_ANCHOR_PAGE_CODE_CHARS = 120;
6931
- var AUTH_ROUTE_SLUGS = /* @__PURE__ */ new Set(["login", "register", "forgot-password", "reset-password", "sign-up"]);
7070
+ var AUTH_ROUTE_SLUGS = /* @__PURE__ */ new Set([
7071
+ "login",
7072
+ "signin",
7073
+ "sign-in",
7074
+ "register",
7075
+ "sign-up",
7076
+ "signup",
7077
+ "forgot-password",
7078
+ "reset-password"
7079
+ ]);
6932
7080
  function inferRouteUsesAuthSegment(route) {
6933
7081
  const slug = route.replace(/^\//, "").split("/")[0] || "";
6934
7082
  return AUTH_ROUTE_SLUGS.has(slug);
@@ -6950,34 +7098,42 @@ function isMarketingRoute(route) {
6950
7098
  const slug = route.replace(/^\//, "").split("/")[0] || "";
6951
7099
  return MARKETING_ROUTES.has(slug);
6952
7100
  }
6953
- function routeToFsPath(projectRoot, route, isAuth) {
7101
+ function routeToFsPath(projectRoot, route, isAuthOrPlan) {
7102
+ const plan = typeof isAuthOrPlan === "object" ? isAuthOrPlan : void 0;
7103
+ const isAuth = typeof isAuthOrPlan === "boolean" ? isAuthOrPlan : false;
6954
7104
  const slug = route.replace(/^\//, "");
6955
- if (isAuth) {
6956
- return resolve5(projectRoot, "app", "(auth)", slug || "login", "page.tsx");
6957
- }
6958
- if (!slug) {
6959
- return resolve5(projectRoot, "app", "page.tsx");
6960
- }
6961
- if (isMarketingRoute(route)) {
6962
- return resolve5(projectRoot, "app", slug, "page.tsx");
7105
+ if (!slug) return resolve5(projectRoot, "app", "page.tsx");
7106
+ if (plan) {
7107
+ const group = getPageGroup(route, plan);
7108
+ if (group) return resolve5(projectRoot, "app", `(${group.id})`, slug, "page.tsx");
6963
7109
  }
7110
+ if (isAuth) return resolve5(projectRoot, "app", "(auth)", slug || "login", "page.tsx");
7111
+ if (isMarketingRoute(route)) return resolve5(projectRoot, "app", slug, "page.tsx");
6964
7112
  return resolve5(projectRoot, "app", "(app)", slug, "page.tsx");
6965
7113
  }
6966
- function routeToRelPath(route, isAuth) {
7114
+ function routeToRelPath(route, isAuthOrPlan) {
7115
+ const plan = typeof isAuthOrPlan === "object" ? isAuthOrPlan : void 0;
7116
+ const isAuth = typeof isAuthOrPlan === "boolean" ? isAuthOrPlan : false;
6967
7117
  const slug = route.replace(/^\//, "");
6968
- if (isAuth) {
6969
- return `app/(auth)/${slug || "login"}/page.tsx`;
6970
- }
6971
- if (!slug) {
6972
- return "app/page.tsx";
6973
- }
6974
- if (isMarketingRoute(route)) {
6975
- return `app/${slug}/page.tsx`;
7118
+ if (!slug) return "app/page.tsx";
7119
+ if (plan) {
7120
+ const group = getPageGroup(route, plan);
7121
+ if (group) return `app/(${group.id})/${slug}/page.tsx`;
6976
7122
  }
7123
+ if (isAuth) return `app/(auth)/${slug || "login"}/page.tsx`;
7124
+ if (isMarketingRoute(route)) return `app/${slug}/page.tsx`;
6977
7125
  return `app/(app)/${slug}/page.tsx`;
6978
7126
  }
7127
+ var AUTH_SYNONYMS = {
7128
+ "/register": "/signup",
7129
+ "/registration": "/signup",
7130
+ "/sign-up": "/signup",
7131
+ "/signin": "/login",
7132
+ "/sign-in": "/login"
7133
+ };
6979
7134
  function deduplicatePages(pages) {
6980
- const normalize = (route) => route.replace(/\/$/, "").replace(/s$/, "").replace(/ue$/, "");
7135
+ const canonicalize = (route) => AUTH_SYNONYMS[route] || route;
7136
+ const normalize = (route) => canonicalize(route).replace(/\/$/, "").replace(/s$/, "").replace(/ue$/, "");
6981
7137
  const seen = /* @__PURE__ */ new Map();
6982
7138
  return pages.filter((page, idx) => {
6983
7139
  const norm = normalize(page.route);
@@ -6998,13 +7154,24 @@ function extractComponentIdsFromCode(code) {
6998
7154
  }
6999
7155
  return ids;
7000
7156
  }
7001
- async function warnInlineDuplicates(projectRoot, pageName, pageCode, manifest) {
7157
+ async function warnInlineDuplicates(projectRoot, pageName, route, pageCode, manifest, plan) {
7002
7158
  const sectionOrWidget = manifest.shared.filter((e) => e.type === "section" || e.type === "widget");
7003
7159
  if (sectionOrWidget.length === 0) return;
7160
+ const plannedForPage = plan ? new Set(plan.sharedComponents.filter((c) => c.usedBy.includes(route)).map((c) => c.name)) : null;
7004
7161
  for (const e of sectionOrWidget) {
7162
+ if (plannedForPage && !plannedForPage.has(e.name)) continue;
7005
7163
  const kebab = e.file.replace(/^components\/shared\//, "").replace(/\.tsx$/, "");
7006
7164
  const hasImport = pageCode.includes(`@/components/shared/${kebab}`);
7007
7165
  if (hasImport) continue;
7166
+ if (plannedForPage) {
7167
+ console.log(
7168
+ chalk8.yellow(
7169
+ `
7170
+ \u26A0 Page "${pageName}" should use shared component ${e.name} (per architecture plan) but it's not imported. Import from @/components/shared/${kebab}`
7171
+ )
7172
+ );
7173
+ continue;
7174
+ }
7008
7175
  const sameNameAsTag = new RegExp(`<\\/?${e.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s>]`).test(pageCode);
7009
7176
  if (sameNameAsTag) {
7010
7177
  console.log(
@@ -7115,8 +7282,8 @@ ${currentCode}
7115
7282
 
7116
7283
  // src/commands/chat/request-parser.ts
7117
7284
  var AUTH_FLOW_PATTERNS = {
7118
- "/login": ["/register", "/forgot-password"],
7119
- "/signin": ["/register", "/forgot-password"],
7285
+ "/login": ["/signup", "/forgot-password"],
7286
+ "/signin": ["/signup", "/forgot-password"],
7120
7287
  "/signup": ["/login"],
7121
7288
  "/register": ["/login"],
7122
7289
  "/forgot-password": ["/login", "/reset-password"],
@@ -7159,14 +7326,19 @@ function extractInternalLinks(code) {
7159
7326
  function inferRelatedPages(plannedPages) {
7160
7327
  const plannedRoutes = new Set(plannedPages.map((p) => p.route));
7161
7328
  const inferred = [];
7162
- for (const { route } of plannedPages) {
7329
+ const queue = [...plannedPages];
7330
+ let i = 0;
7331
+ while (i < queue.length) {
7332
+ const { route } = queue[i++];
7163
7333
  const authRelated = AUTH_FLOW_PATTERNS[route];
7164
7334
  if (authRelated) {
7165
7335
  for (const rel of authRelated) {
7166
7336
  if (!plannedRoutes.has(rel)) {
7167
7337
  const slug = rel.slice(1);
7168
7338
  const name = slug.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
7169
- inferred.push({ id: slug, name, route: rel });
7339
+ const page = { id: slug, name, route: rel };
7340
+ inferred.push(page);
7341
+ queue.push(page);
7170
7342
  plannedRoutes.add(rel);
7171
7343
  }
7172
7344
  }
@@ -7176,6 +7348,7 @@ function inferRelatedPages(plannedPages) {
7176
7348
  for (const rel of rule.related) {
7177
7349
  if (!plannedRoutes.has(rel.route)) {
7178
7350
  inferred.push(rel);
7351
+ queue.push(rel);
7179
7352
  plannedRoutes.add(rel.route);
7180
7353
  }
7181
7354
  }
@@ -7203,7 +7376,7 @@ function extractPageNamesFromMessage(message) {
7203
7376
  settings: "/settings",
7204
7377
  account: "/account",
7205
7378
  "personal account": "/account",
7206
- registration: "/registration",
7379
+ registration: "/signup",
7207
7380
  signup: "/signup",
7208
7381
  "sign up": "/signup",
7209
7382
  login: "/login",
@@ -7616,6 +7789,7 @@ async function pMap(items, fn, concurrency = 3) {
7616
7789
  }
7617
7790
 
7618
7791
  // src/commands/chat/split-generator.ts
7792
+ import chalk9 from "chalk";
7619
7793
  function buildExistingPagesContext(config2) {
7620
7794
  const pages = config2.pages || [];
7621
7795
  const analyzed = pages.filter((p) => p.pageAnalysis);
@@ -7712,6 +7886,21 @@ Before implementing any section, check this list. Import and use matching compon
7712
7886
 
7713
7887
  ${sharedComponentsSummary}`;
7714
7888
  }
7889
+ function formatPlanSummary(plan) {
7890
+ if (plan.groups.length === 0) return "";
7891
+ const groupLines = plan.groups.map((g) => ` Group "${g.id}" (layout: ${g.layout}): ${g.pages.join(", ")}`);
7892
+ const compLines = plan.sharedComponents.map(
7893
+ (c) => ` ${c.name} (${c.type}) \u2014 ${c.description}; usedBy: ${c.usedBy.join(", ")}`
7894
+ );
7895
+ const parts = [`ARCHITECTURE PLAN:
7896
+ Groups:
7897
+ ${groupLines.join("\n")}`];
7898
+ if (compLines.length > 0) {
7899
+ parts.push(`Shared Components:
7900
+ ${compLines.join("\n")}`);
7901
+ }
7902
+ return parts.join("\n");
7903
+ }
7715
7904
  async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts) {
7716
7905
  let pageNames = [];
7717
7906
  spinner.start("Phase 1/5 \u2014 Planning pages...");
@@ -7745,7 +7934,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
7745
7934
  }
7746
7935
  if (pageNames.length === 0) {
7747
7936
  spinner.fail("Could not determine pages to create");
7748
- return [];
7937
+ return { requests: [], plan: null };
7749
7938
  }
7750
7939
  pageNames = deduplicatePages(pageNames);
7751
7940
  const hasHomePage = pageNames.some((p) => p.route === "/");
@@ -7767,7 +7956,41 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
7767
7956
  const allRoutes = pageNames.map((p) => p.route).join(", ");
7768
7957
  const allPagesList = pageNames.map((p) => `${p.name} (${p.route})`).join(", ");
7769
7958
  const inferredNote = inferred.length > 0 ? ` (${inferred.length} auto-inferred)` : "";
7770
- spinner.succeed(`Phase 1/5 \u2014 Found ${pageNames.length} pages${inferredNote}: ${allPagesList}`);
7959
+ spinner.succeed(`Phase 1/6 \u2014 Found ${pageNames.length} pages${inferredNote}: ${allPagesList}`);
7960
+ let plan = null;
7961
+ if (parseOpts.projectRoot) {
7962
+ spinner.start("Phase 2/6 \u2014 Generating architecture plan...");
7963
+ try {
7964
+ const ai = await createAIProvider(provider ?? "auto");
7965
+ const layoutHint = modCtx.config.navigation?.type || null;
7966
+ plan = await generateArchitecturePlan(pageNames, message, ai, layoutHint);
7967
+ if (plan) {
7968
+ const groupsSummary = plan.groups.map((g) => `${g.id} (${g.layout}, ${g.pages.length} pages)`).join(", ");
7969
+ const sharedSummary = plan.sharedComponents.length > 0 ? plan.sharedComponents.map((c) => `${c.name} \u2192 ${c.usedBy.join(", ")}`).join(" | ") : "";
7970
+ const totalPages = plan.groups.reduce((sum, g) => sum + g.pages.length, 0);
7971
+ spinner.succeed(`Phase 2/6 \u2014 Architecture plan created`);
7972
+ console.log(chalk9.dim(` Groups: ${groupsSummary}`));
7973
+ if (sharedSummary) console.log(chalk9.dim(` Shared: ${sharedSummary}`));
7974
+ console.log(chalk9.dim(` Total: ${totalPages} pages, ${plan.sharedComponents.length} shared components`));
7975
+ if (plan.sharedComponents.length > 0 && parseOpts.projectRoot) {
7976
+ const allDeps = new Set(plan.sharedComponents.flatMap((c) => c.shadcnDeps));
7977
+ if (allDeps.size > 0) {
7978
+ const componentProvider = getComponentProvider();
7979
+ for (const dep of allDeps) {
7980
+ try {
7981
+ await componentProvider.installComponent(dep, parseOpts.projectRoot);
7982
+ } catch {
7983
+ }
7984
+ }
7985
+ }
7986
+ }
7987
+ } else {
7988
+ spinner.warn("Phase 2/6 \u2014 Plan generation failed (continuing without plan)");
7989
+ }
7990
+ } catch {
7991
+ spinner.warn("Phase 2/6 \u2014 Plan generation failed (continuing without plan)");
7992
+ }
7993
+ }
7771
7994
  const homeIdx = pageNames.findIndex((p) => p.route === "/");
7772
7995
  const homePage = homeIdx !== -1 ? pageNames[homeIdx] : pageNames[0];
7773
7996
  const remainingPages = pageNames.filter((_, i) => i !== (homeIdx !== -1 ? homeIdx : 0));
@@ -7781,12 +8004,12 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
7781
8004
  if (existingCode) {
7782
8005
  reusedExistingAnchor = true;
7783
8006
  homePageCode = existingCode;
7784
- spinner.start(`Phase 2/5 \u2014 Loading ${homePage.name} from disk (style anchor)...`);
7785
- spinner.succeed(`Phase 2/5 \u2014 Reused existing ${homePage.name} page (skipped AI regeneration)`);
8007
+ spinner.start(`Phase 3/6 \u2014 Loading ${homePage.name} from disk (style anchor)...`);
8008
+ spinner.succeed(`Phase 3/6 \u2014 Reused existing ${homePage.name} page (skipped AI regeneration)`);
7786
8009
  }
7787
8010
  }
7788
8011
  if (!reusedExistingAnchor) {
7789
- spinner.start(`Phase 2/5 \u2014 Generating ${homePage.name} page (sets design direction)...`);
8012
+ spinner.start(`Phase 3/6 \u2014 Generating ${homePage.name} page (sets design direction)...`);
7790
8013
  try {
7791
8014
  const homeResult = await parseModification(
7792
8015
  `Create ONE page called "${homePage.name}" at route "${homePage.route}". Context: ${message}. This REPLACES the default placeholder page \u2014 generate a complete, content-rich landing page for the project described above. Generate complete pageCode. Include a branded site-wide <header> with navigation links to ALL these pages: ${allPagesList}. Use these EXACT routes in navigation: ${allRoutes}. Include a <footer> at the bottom. Make it visually polished \u2014 this page sets the design direction for the entire site. Do not generate other pages.`,
@@ -7808,73 +8031,102 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
7808
8031
  changes: { id: homePage.id, name: homePage.name, route: homePage.route }
7809
8032
  };
7810
8033
  }
7811
- spinner.succeed(`Phase 2/5 \u2014 ${homePage.name} page generated`);
8034
+ spinner.succeed(`Phase 3/6 \u2014 ${homePage.name} page generated`);
7812
8035
  }
7813
- spinner.start("Phase 3/5 \u2014 Extracting design patterns...");
8036
+ spinner.start("Phase 4/6 \u2014 Extracting design patterns...");
7814
8037
  const styleContext = homePageCode ? extractStyleContext(homePageCode) : "";
7815
8038
  if (styleContext) {
7816
8039
  const lineCount = styleContext.split("\n").length - 1;
7817
8040
  const source = reusedExistingAnchor ? `${homePage.name} (existing file)` : homePage.name;
7818
- spinner.succeed(`Phase 3/5 \u2014 Extracted ${lineCount} style patterns from ${source}`);
8041
+ spinner.succeed(`Phase 4/6 \u2014 Extracted ${lineCount} style patterns from ${source}`);
7819
8042
  } else {
7820
- spinner.succeed("Phase 3/5 \u2014 No style patterns extracted (anchor page had no code)");
8043
+ spinner.succeed("Phase 4/6 \u2014 No style patterns extracted (anchor page had no code)");
7821
8044
  }
7822
- if (remainingPages.length >= 2 && homePageCode && projectRoot) {
7823
- const manifest = await loadManifest5(projectRoot);
7824
- const shouldSkip = reusedExistingAnchor && manifest.shared.some((e) => e.type !== "layout");
7825
- if (!shouldSkip) {
7826
- spinner.start("Phase 3.5/5 \u2014 Extracting shared components...");
8045
+ if (remainingPages.length >= 2 && projectRoot) {
8046
+ if (plan && plan.sharedComponents.length > 0) {
8047
+ spinner.start(`Phase 4.5/6 \u2014 Generating ${plan.sharedComponents.length} shared components from plan...`);
7827
8048
  try {
7828
- const extraction = await extractSharedComponents(homePageCode, projectRoot, provider ?? "auto");
7829
- parseOpts.sharedComponentsSummary = extraction.summary;
7830
- if (extraction.components.length > 0) {
7831
- const names = extraction.components.map((c) => c.name).join(", ");
7832
- spinner.succeed(`Phase 3.5/5 \u2014 Extracted ${extraction.components.length} shared components (${names})`);
8049
+ const { generateSharedComponentsFromPlan } = await import("./plan-generator-IS3YDZUW.js");
8050
+ const generated = await generateSharedComponentsFromPlan(
8051
+ plan,
8052
+ styleContext,
8053
+ projectRoot,
8054
+ await createAIProvider(provider ?? "auto")
8055
+ );
8056
+ if (generated.length > 0) {
8057
+ const updatedManifest = await loadManifest5(projectRoot);
8058
+ parseOpts.sharedComponentsSummary = buildSharedComponentsSummary(updatedManifest);
8059
+ const names = generated.map((c) => c.name).join(", ");
8060
+ spinner.succeed(`Phase 4.5/6 \u2014 Generated ${generated.length} shared components (${names})`);
7833
8061
  } else {
7834
- spinner.succeed("Phase 3.5/5 \u2014 No shared components extracted");
8062
+ spinner.succeed("Phase 4.5/6 \u2014 No shared components generated");
7835
8063
  }
7836
8064
  } catch {
7837
- spinner.warn("Phase 3.5/5 \u2014 Could not extract shared components (continuing without)");
8065
+ spinner.warn("Phase 4.5/6 \u2014 Could not generate shared components (continuing without)");
8066
+ }
8067
+ } else if (homePageCode) {
8068
+ const manifest = await loadManifest5(projectRoot);
8069
+ const shouldSkip = reusedExistingAnchor && manifest.shared.some((e) => e.type !== "layout");
8070
+ if (!shouldSkip) {
8071
+ spinner.start("Phase 4.5/6 \u2014 Extracting shared components (legacy)...");
8072
+ try {
8073
+ const extraction = await extractSharedComponents(homePageCode, projectRoot, provider ?? "auto");
8074
+ parseOpts.sharedComponentsSummary = extraction.summary;
8075
+ if (extraction.components.length > 0) {
8076
+ const names = extraction.components.map((c) => c.name).join(", ");
8077
+ spinner.succeed(`Phase 4.5/6 \u2014 Extracted ${extraction.components.length} shared components (${names})`);
8078
+ } else {
8079
+ spinner.succeed("Phase 4.5/6 \u2014 No shared components extracted");
8080
+ }
8081
+ } catch {
8082
+ spinner.warn("Phase 4.5/6 \u2014 Could not extract shared components (continuing without)");
8083
+ }
7838
8084
  }
7839
8085
  }
7840
8086
  }
7841
8087
  if (remainingPages.length === 0) {
7842
- return homeRequest ? [homeRequest] : [];
8088
+ return { requests: homeRequest ? [homeRequest] : [], plan };
7843
8089
  }
7844
- spinner.start(`Phase 4/5 \u2014 Generating ${remainingPages.length} pages in parallel...`);
8090
+ spinner.start(`Phase 5/6 \u2014 Generating ${remainingPages.length} pages in parallel...`);
7845
8091
  const sharedLayoutNote = "Header and Footer are shared components rendered by the root layout. Do NOT include any site-wide <header>, <nav>, or <footer> in this page. Start with the main content directly.";
7846
8092
  const sharedComponentsNote = buildSharedComponentsNote(parseOpts.sharedComponentsSummary);
7847
8093
  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="#".`;
7848
8094
  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.';
8095
+ const planSummaryNote = plan ? formatPlanSummary(plan) : "";
7849
8096
  const existingPagesContext = buildExistingPagesContext(modCtx.config);
7850
8097
  const AI_CONCURRENCY = 3;
7851
- let phase4Done = 0;
8098
+ let phase5Done = 0;
7852
8099
  const remainingRequests = await pMap(
7853
8100
  remainingPages,
7854
8101
  async ({ name, id, route }) => {
7855
8102
  const isAuth = isAuthRoute(route) || isAuthRoute(name);
7856
- const authNote = isAuth ? 'For this auth page: use centered card layout with outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10" and inner div className="w-full max-w-sm". Do NOT use section containers or full-width wrappers. The auth layout provides centering \u2014 just output the card content.' : void 0;
8103
+ const pageType = plan ? getPageType(route, plan) : inferPageTypeFromRoute(route);
8104
+ const designConstraints = getDesignQualityForType(pageType);
8105
+ const authNote = isAuth ? 'For this auth page: use centered card layout with outer div className="flex min-h-svh flex-col items-center justify-center p-6 md:p-10" and inner div className="w-full max-w-md". Do NOT use section containers or full-width wrappers. The auth layout provides centering \u2014 just output the card content.' : void 0;
7857
8106
  const prompt = [
7858
8107
  `Create ONE page called "${name}" at route "${route}".`,
7859
8108
  `Context: ${message}.`,
7860
8109
  `Generate complete pageCode for this single page only. Do not generate other pages.`,
8110
+ `PAGE TYPE: ${pageType}`,
8111
+ designConstraints,
7861
8112
  sharedLayoutNote,
7862
8113
  sharedComponentsNote,
7863
8114
  routeNote,
7864
8115
  alignmentNote,
7865
8116
  authNote,
8117
+ planSummaryNote,
7866
8118
  existingPagesContext,
7867
8119
  styleContext
7868
8120
  ].filter(Boolean).join("\n\n");
7869
8121
  try {
7870
8122
  const result = await parseModification(prompt, modCtx, provider, parseOpts);
7871
- phase4Done++;
7872
- spinner.text = `Phase 4/5 \u2014 ${phase4Done}/${remainingPages.length} pages generated...`;
8123
+ phase5Done++;
8124
+ spinner.text = `Phase 5/6 \u2014 ${phase5Done}/${remainingPages.length} pages generated...`;
7873
8125
  const codePage = result.requests.find((r) => r.type === "add-page");
7874
8126
  return codePage || { type: "add-page", target: "new", changes: { id, name, route } };
7875
8127
  } catch {
7876
- phase4Done++;
7877
- spinner.text = `Phase 4/5 \u2014 ${phase4Done}/${remainingPages.length} pages generated...`;
8128
+ phase5Done++;
8129
+ spinner.text = `Phase 5/6 \u2014 ${phase5Done}/${remainingPages.length} pages generated...`;
7878
8130
  return { type: "add-page", target: "new", changes: { id, name, route } };
7879
8131
  }
7880
8132
  },
@@ -7889,18 +8141,18 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
7889
8141
  const pageName = page.name || page.id || "page";
7890
8142
  const pageRoute = page.route || `/${pageName.toLowerCase()}`;
7891
8143
  try {
8144
+ const retryPageType = plan ? getPageType(pageRoute, plan) : inferPageTypeFromRoute(pageRoute);
7892
8145
  const lightweightPrompt = buildLightweightPagePrompt(
7893
8146
  pageName,
7894
8147
  pageRoute,
7895
8148
  styleContext || "",
7896
- parseOpts.sharedComponentsSummary
7897
- );
7898
- const retryResult = await parseModification(
7899
- lightweightPrompt,
7900
- modCtx,
7901
- provider,
7902
- { ...parseOpts, lightweight: true }
8149
+ parseOpts.sharedComponentsSummary,
8150
+ retryPageType
7903
8151
  );
8152
+ const retryResult = await parseModification(lightweightPrompt, modCtx, provider, {
8153
+ ...parseOpts,
8154
+ lightweight: true
8155
+ });
7904
8156
  const codePage = retryResult.requests.find((r) => r.type === "add-page");
7905
8157
  if (codePage && codePage.changes?.pageCode) {
7906
8158
  const idx = allRequests.indexOf(req);
@@ -7911,8 +8163,8 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
7911
8163
  }
7912
8164
  }
7913
8165
  const withCode = allRequests.filter((r) => r.changes?.pageCode).length;
7914
- spinner.succeed(`Phase 4/5 \u2014 Generated ${allRequests.length} pages (${withCode} with full code)`);
7915
- return allRequests;
8166
+ spinner.succeed(`Phase 5/6 \u2014 Generated ${allRequests.length} pages (${withCode} with full code)`);
8167
+ return { requests: allRequests, plan };
7916
8168
  }
7917
8169
  var SharedExtractionItemSchema = z.object({
7918
8170
  name: z.string().min(2).max(50),
@@ -8026,7 +8278,7 @@ function extractAppNameFromPrompt(prompt) {
8026
8278
  import { resolve as resolve7 } from "path";
8027
8279
  import { mkdir as mkdir4 } from "fs/promises";
8028
8280
  import { dirname as dirname6 } from "path";
8029
- import chalk11 from "chalk";
8281
+ import chalk12 from "chalk";
8030
8282
  import {
8031
8283
  getTemplateForPageType,
8032
8284
  loadManifest as loadManifest6,
@@ -8047,7 +8299,7 @@ import {
8047
8299
  TailwindConfigGenerator
8048
8300
  } from "@getcoherent/core";
8049
8301
  import { integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2, generateSharedComponent as generateSharedComponent3 } from "@getcoherent/core";
8050
- import chalk9 from "chalk";
8302
+ import chalk10 from "chalk";
8051
8303
 
8052
8304
  // src/utils/file-hashes.ts
8053
8305
  import { createHash } from "crypto";
@@ -8151,7 +8403,7 @@ async function canOverwriteShared(projectRoot, componentFile, storedHashes) {
8151
8403
  if (!storedHash) return true;
8152
8404
  const edited = await isManuallyEdited(filePath, storedHash);
8153
8405
  if (edited) {
8154
- console.log(chalk9.yellow(` \u26A0 Skipping ${componentFile} \u2014 manually edited since last generation`));
8406
+ console.log(chalk10.yellow(` \u26A0 Skipping ${componentFile} \u2014 manually edited since last generation`));
8155
8407
  }
8156
8408
  return !edited;
8157
8409
  }
@@ -8214,7 +8466,7 @@ async function regenerateLayout(config2, projectRoot, options = { navChanged: fa
8214
8466
  await ensureAppRouteGroupLayout(projectRoot, config2.navigation?.type, options.navChanged);
8215
8467
  } catch (err) {
8216
8468
  if (process.env.COHERENT_DEBUG === "1") {
8217
- console.log(chalk9.dim("Layout integration warning:", err));
8469
+ console.log(chalk10.dim("Layout integration warning:", err));
8218
8470
  }
8219
8471
  }
8220
8472
  }
@@ -8282,6 +8534,59 @@ export default function AppLayout({
8282
8534
  }
8283
8535
  `;
8284
8536
  }
8537
+ function buildGroupLayoutCode(layout, _pages) {
8538
+ if (layout === "sidebar" || layout === "both") {
8539
+ return `import { Sidebar } from '@/components/shared/sidebar'
8540
+
8541
+ export default function GroupLayout({
8542
+ children,
8543
+ }: {
8544
+ children: React.ReactNode
8545
+ }) {
8546
+ return (
8547
+ <div className="flex min-h-[calc(100vh-3.5rem)]">
8548
+ <Sidebar />
8549
+ <main className="flex-1 px-4 sm:px-6 lg:px-8 py-6">
8550
+ {children}
8551
+ </main>
8552
+ </div>
8553
+ )
8554
+ }
8555
+ `;
8556
+ }
8557
+ if (layout === "none") {
8558
+ return `export default function GroupLayout({
8559
+ children,
8560
+ }: {
8561
+ children: React.ReactNode
8562
+ }) {
8563
+ return <>{children}</>
8564
+ }
8565
+ `;
8566
+ }
8567
+ return `export default function GroupLayout({
8568
+ children,
8569
+ }: {
8570
+ children: React.ReactNode
8571
+ }) {
8572
+ return (
8573
+ <main className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
8574
+ {children}
8575
+ </main>
8576
+ )
8577
+ }
8578
+ `;
8579
+ }
8580
+ async function ensurePlanGroupLayouts(projectRoot, plan) {
8581
+ const { mkdir: mkdirAsync } = await import("fs/promises");
8582
+ for (const group of plan.groups) {
8583
+ const groupDir = resolve6(projectRoot, "app", `(${group.id})`);
8584
+ await mkdirAsync(groupDir, { recursive: true });
8585
+ const layoutPath = resolve6(groupDir, "layout.tsx");
8586
+ const code = buildGroupLayoutCode(group.layout, group.pages);
8587
+ await writeFile(layoutPath, code);
8588
+ }
8589
+ }
8285
8590
  async function regenerateFiles(modified, config2, projectRoot, options = { navChanged: false }) {
8286
8591
  const componentIds = /* @__PURE__ */ new Set();
8287
8592
  const pageIds = /* @__PURE__ */ new Set();
@@ -8299,7 +8604,7 @@ async function regenerateFiles(modified, config2, projectRoot, options = { navCh
8299
8604
  });
8300
8605
  const sharedInstalled = await scanAndInstallSharedDeps(projectRoot);
8301
8606
  if (sharedInstalled.length > 0 && process.env.COHERENT_DEBUG === "1") {
8302
- console.log(chalk9.dim(` Auto-installed shared deps: ${sharedInstalled.join(", ")}`));
8607
+ console.log(chalk10.dim(` Auto-installed shared deps: ${sharedInstalled.join(", ")}`));
8303
8608
  }
8304
8609
  }
8305
8610
  if (componentIds.size > 0) {
@@ -8356,7 +8661,7 @@ function extractBalancedTag(source, tagName) {
8356
8661
  }
8357
8662
 
8358
8663
  // src/commands/chat/reporting.ts
8359
- import chalk10 from "chalk";
8664
+ import chalk11 from "chalk";
8360
8665
  function extractImportsFrom(code, fromPath) {
8361
8666
  const escaped = fromPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8362
8667
  const regex = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*['"\`]${escaped}[^'"\`]*['"\`]`, "g");
@@ -8378,27 +8683,27 @@ function printPostGenerationReport(opts) {
8378
8683
  const iconCount = extractImportsFrom(code, "lucide-react").length;
8379
8684
  const hasInstalled = postFixes.some((f) => f.startsWith("Installed:"));
8380
8685
  const syntaxStatus = postFixes.length > 0 ? postFixes.some((f) => f.includes("metadata")) ? "fixed (escaped metadata quotes) \u2714" : "fixed \u2714" : "valid \u2714";
8381
- console.log(chalk10.green(`
8686
+ console.log(chalk11.green(`
8382
8687
  \u2705 Page "${pageTitle}" ${action} at ${filePath}
8383
8688
  `));
8384
8689
  if (uiComponents.length > 0) {
8385
- console.log(chalk10.dim(` Components: ${uiComponents.join(", ")} (from @/components/ui)`));
8690
+ console.log(chalk11.dim(` Components: ${uiComponents.join(", ")} (from @/components/ui)`));
8386
8691
  }
8387
8692
  if (inCodeShared.length > 0) {
8388
- console.log(chalk10.dim(` Shared: ${inCodeShared.map((s) => `${s.id} (${s.name})`).join(", ")}`));
8693
+ console.log(chalk11.dim(` Shared: ${inCodeShared.map((s) => `${s.id} (${s.name})`).join(", ")}`));
8389
8694
  }
8390
8695
  if (layoutShared.length > 0) {
8391
- console.log(chalk10.dim(` Layout: ${layoutShared.map((l) => `${l.id} (${l.name})`).join(", ")} via layout.tsx`));
8696
+ console.log(chalk11.dim(` Layout: ${layoutShared.map((l) => `${l.id} (${l.name})`).join(", ")} via layout.tsx`));
8392
8697
  }
8393
8698
  if (iconCount > 0) {
8394
- console.log(chalk10.dim(` Icons: ${iconCount} from lucide-react`));
8699
+ console.log(chalk11.dim(` Icons: ${iconCount} from lucide-react`));
8395
8700
  }
8396
8701
  if (hasInstalled) {
8397
- console.log(chalk10.dim(" Dependencies: installed \u2714"));
8702
+ console.log(chalk11.dim(" Dependencies: installed \u2714"));
8398
8703
  }
8399
- console.log(chalk10.dim(` Syntax: ${syntaxStatus}`));
8704
+ console.log(chalk11.dim(` Syntax: ${syntaxStatus}`));
8400
8705
  if (route) {
8401
- console.log(chalk10.cyan(`
8706
+ console.log(chalk11.cyan(`
8402
8707
  Preview: http://localhost:3000${route}`));
8403
8708
  }
8404
8709
  console.log("");
@@ -8406,35 +8711,35 @@ function printPostGenerationReport(opts) {
8406
8711
  function printSharedComponentReport(opts) {
8407
8712
  const { id, name, file, instruction, postFixes = [] } = opts;
8408
8713
  const syntaxStatus = postFixes.length > 0 ? "fixed \u2714" : "valid \u2714";
8409
- console.log(chalk10.green(`
8714
+ console.log(chalk11.green(`
8410
8715
  \u2705 Updated ${id} (${name}) at ${file}
8411
8716
  `));
8412
8717
  if (instruction) {
8413
8718
  const snippet = instruction.length > 60 ? instruction.slice(0, 57) + "..." : instruction;
8414
- console.log(chalk10.dim(` Changed: ${snippet}`));
8719
+ console.log(chalk11.dim(` Changed: ${snippet}`));
8415
8720
  }
8416
- console.log(chalk10.dim(" Affects: all pages via layout.tsx"));
8417
- console.log(chalk10.dim(` Syntax: ${syntaxStatus}`));
8721
+ console.log(chalk11.dim(" Affects: all pages via layout.tsx"));
8722
+ console.log(chalk11.dim(` Syntax: ${syntaxStatus}`));
8418
8723
  console.log("");
8419
8724
  }
8420
8725
  function printLinkSharedReport(opts) {
8421
8726
  const { sharedId, sharedName, pageTarget, route, postFixes = [] } = opts;
8422
8727
  const syntaxStatus = postFixes.length > 0 ? "fixed \u2714" : "valid \u2714";
8423
- console.log(chalk10.green(`
8728
+ console.log(chalk11.green(`
8424
8729
  \u2705 Linked ${sharedId} (${sharedName}) to page "${pageTarget}"
8425
8730
  `));
8426
- console.log(chalk10.dim(` Syntax: ${syntaxStatus}`));
8427
- console.log(chalk10.cyan(` Preview: http://localhost:3000${route}`));
8731
+ console.log(chalk11.dim(` Syntax: ${syntaxStatus}`));
8732
+ console.log(chalk11.cyan(` Preview: http://localhost:3000${route}`));
8428
8733
  console.log("");
8429
8734
  }
8430
8735
  function printPromoteAndLinkReport(opts) {
8431
8736
  const { id, name, file, usedInFiles, postFixes = [] } = opts;
8432
8737
  const syntaxStatus = postFixes.length > 0 ? "fixed \u2714" : "valid \u2714";
8433
- console.log(chalk10.green(`
8738
+ console.log(chalk11.green(`
8434
8739
  \u2705 Created ${id} (${name}) at ${file}
8435
8740
  `));
8436
- console.log(chalk10.dim(` Linked to: ${usedInFiles.length} page(s)`));
8437
- console.log(chalk10.dim(` Syntax: ${syntaxStatus}`));
8741
+ console.log(chalk11.dim(` Linked to: ${usedInFiles.length} page(s)`));
8742
+ console.log(chalk11.dim(` Syntax: ${syntaxStatus}`));
8438
8743
  console.log("");
8439
8744
  }
8440
8745
  function showPreview(requests, results, config2, preflightInstalledNames) {
@@ -8452,23 +8757,23 @@ function showPreview(requests, results, config2, preflightInstalledNames) {
8452
8757
  const modifiedSharedComponents = successfulPairs.filter(({ request }) => request.type === "modify-layout-block");
8453
8758
  const modifiedPages = successfulPairs.filter(({ request }) => request.type === "update-page");
8454
8759
  const tokenChanges = successfulPairs.filter(({ request }) => request.type === "update-token");
8455
- console.log(chalk10.bold.cyan("\n\u{1F4CB} Changes Applied:\n"));
8760
+ console.log(chalk11.bold.cyan("\n\u{1F4CB} Changes Applied:\n"));
8456
8761
  if (preflightInstalledNames && preflightInstalledNames.length > 0) {
8457
- console.log(chalk10.cyan("\u{1F50D} Pre-flight check: Installed missing components:"));
8762
+ console.log(chalk11.cyan("\u{1F50D} Pre-flight check: Installed missing components:"));
8458
8763
  preflightInstalledNames.forEach((name) => {
8459
- console.log(chalk10.green(` \u2728 Auto-installed ${name}`));
8764
+ console.log(chalk11.green(` \u2728 Auto-installed ${name}`));
8460
8765
  });
8461
8766
  console.log("");
8462
8767
  }
8463
8768
  if (addedComponents.length > 0) {
8464
8769
  const names = addedComponents.map(({ request }) => request.changes.name).filter(Boolean);
8465
- console.log(chalk10.green("\u{1F4E6} Components:"));
8466
- console.log(chalk10.white(` \u2728 Auto-installed: ${names.join(", ")}`));
8770
+ console.log(chalk11.green("\u{1F4E6} Components:"));
8771
+ console.log(chalk11.white(` \u2728 Auto-installed: ${names.join(", ")}`));
8467
8772
  }
8468
8773
  if (customComponents.length > 0) {
8469
8774
  const names = customComponents.map(({ request }) => request.changes.name).filter(Boolean);
8470
- if (addedComponents.length === 0) console.log(chalk10.green("\u{1F4E6} Components:"));
8471
- console.log(chalk10.white(` \u2728 Created: ${names.join(", ")}`));
8775
+ if (addedComponents.length === 0) console.log(chalk11.green("\u{1F4E6} Components:"));
8776
+ console.log(chalk11.white(` \u2728 Created: ${names.join(", ")}`));
8472
8777
  }
8473
8778
  const usedComponentIds = /* @__PURE__ */ new Set();
8474
8779
  addedPages.forEach(({ request }) => {
@@ -8483,71 +8788,73 @@ function showPreview(requests, results, config2, preflightInstalledNames) {
8483
8788
  ]);
8484
8789
  const reusedIds = [...usedComponentIds].filter((id) => !newComponentIds.has(id));
8485
8790
  if (reusedIds.length > 0) {
8486
- if (addedComponents.length === 0 && customComponents.length === 0) console.log(chalk10.green("\u{1F4E6} Components:"));
8487
- console.log(chalk10.white(` \u{1F504} Reused: ${reusedIds.join(", ")}`));
8791
+ if (addedComponents.length === 0 && customComponents.length === 0) console.log(chalk11.green("\u{1F4E6} Components:"));
8792
+ console.log(chalk11.white(` \u{1F504} Reused: ${reusedIds.join(", ")}`));
8488
8793
  }
8489
8794
  if (addedComponents.length > 0 || customComponents.length > 0 || reusedIds.length > 0) {
8490
8795
  console.log("");
8491
8796
  }
8492
8797
  if (addedPages.length > 0) {
8493
- console.log(chalk10.green("\u{1F4C4} Pages Created:"));
8798
+ console.log(chalk11.green("\u{1F4C4} Pages Created:"));
8494
8799
  addedPages.forEach(({ request }) => {
8495
8800
  const page = request.changes;
8496
8801
  const route = page.route || "/";
8497
- console.log(chalk10.white(` \u2728 ${page.name || "Page"}`));
8498
- console.log(chalk10.gray(` Route: ${route}`));
8499
- console.log(chalk10.gray(` Sections: ${page.sections?.length ?? 0}`));
8802
+ console.log(chalk11.white(` \u2728 ${page.name || "Page"}`));
8803
+ console.log(chalk11.gray(` Route: ${route}`));
8804
+ const configPage = config2.pages?.find((p) => p.id === page.id || p.route === (page.route || "/"));
8805
+ const sectionCount = configPage?.pageAnalysis?.sections?.length ?? page.sections?.length ?? 0;
8806
+ console.log(chalk11.gray(` Sections: ${sectionCount}`));
8500
8807
  });
8501
8808
  console.log("");
8502
8809
  }
8503
8810
  if (modifiedComponents.length > 0 || modifiedSharedComponents.length > 0 || modifiedPages.length > 0 || tokenChanges.length > 0) {
8504
- console.log(chalk10.yellow("\u{1F527} Modified:"));
8811
+ console.log(chalk11.yellow("\u{1F527} Modified:"));
8505
8812
  modifiedComponents.forEach(({ result }) => {
8506
- console.log(chalk10.white(` \u2022 ${result.message}`));
8813
+ console.log(chalk11.white(` \u2022 ${result.message}`));
8507
8814
  });
8508
8815
  modifiedSharedComponents.forEach(({ result }) => {
8509
- console.log(chalk10.white(` \u2022 ${result.message}`));
8816
+ console.log(chalk11.white(` \u2022 ${result.message}`));
8510
8817
  });
8511
8818
  modifiedPages.forEach(({ result }) => {
8512
- console.log(chalk10.white(` \u2022 ${result.message}`));
8819
+ console.log(chalk11.white(` \u2022 ${result.message}`));
8513
8820
  });
8514
8821
  tokenChanges.forEach(({ result }) => {
8515
- console.log(chalk10.white(` \u2022 ${result.message}`));
8822
+ console.log(chalk11.white(` \u2022 ${result.message}`));
8516
8823
  });
8517
8824
  console.log("");
8518
8825
  }
8519
8826
  if (failedPairs.length > 0) {
8520
- console.log(chalk10.red("\u274C Failed modifications:"));
8827
+ console.log(chalk11.red("\u274C Failed modifications:"));
8521
8828
  failedPairs.forEach(({ result }) => {
8522
- console.log(chalk10.gray(` \u2716 ${result.message}`));
8829
+ console.log(chalk11.gray(` \u2716 ${result.message}`));
8523
8830
  });
8524
8831
  console.log("");
8525
8832
  }
8526
8833
  const successCount = successfulPairs.length;
8527
8834
  const totalCount = results.length;
8528
8835
  if (successCount === totalCount) {
8529
- console.log(chalk10.green.bold(`\u2705 Success! ${successCount} modification(s) applied
8836
+ console.log(chalk11.green.bold(`\u2705 Success! ${successCount} modification(s) applied
8530
8837
  `));
8531
8838
  } else {
8532
- console.log(chalk10.yellow.bold(`\u26A0\uFE0F Partial success: ${successCount}/${totalCount} modification(s) applied
8839
+ console.log(chalk11.yellow.bold(`\u26A0\uFE0F Partial success: ${successCount}/${totalCount} modification(s) applied
8533
8840
  `));
8534
8841
  }
8535
8842
  if (addedPages.length > 0) {
8536
8843
  const firstPage = addedPages[0].request.changes;
8537
8844
  const route = firstPage?.route || "/";
8538
- console.log(chalk10.cyan("\u{1F680} What's next:\n"));
8539
- console.log(chalk10.white(" \u{1F4FA} View in browser:"));
8540
- console.log(chalk10.cyan(" coherent preview"));
8541
- console.log(chalk10.gray(` \u2192 Opens http://localhost:3000${route}
8845
+ console.log(chalk11.cyan("\u{1F680} What's next:\n"));
8846
+ console.log(chalk11.white(" \u{1F4FA} View in browser:"));
8847
+ console.log(chalk11.cyan(" coherent preview"));
8848
+ console.log(chalk11.gray(` \u2192 Opens http://localhost:3000${route}
8542
8849
  `));
8543
- console.log(chalk10.white(" \u{1F3A8} Customize:"));
8544
- console.log(chalk10.cyan(' coherent chat "make buttons rounded"'));
8545
- console.log(chalk10.cyan(` coherent chat "add hero section to ${firstPage?.name ?? "page"}"`));
8850
+ console.log(chalk11.white(" \u{1F3A8} Customize:"));
8851
+ console.log(chalk11.cyan(' coherent chat "make buttons rounded"'));
8852
+ console.log(chalk11.cyan(` coherent chat "add hero section to ${firstPage?.name ?? "page"}"`));
8546
8853
  console.log("");
8547
8854
  } else if (successCount > 0) {
8548
- console.log(chalk10.cyan("\u{1F680} What's next:\n"));
8549
- console.log(chalk10.white(" \u{1F4FA} Preview changes:"));
8550
- console.log(chalk10.cyan(" coherent preview\n"));
8855
+ console.log(chalk11.cyan("\u{1F680} What's next:\n"));
8856
+ console.log(chalk11.white(" \u{1F4FA} Preview changes:"));
8857
+ console.log(chalk11.cyan(" coherent preview\n"));
8551
8858
  }
8552
8859
  }
8553
8860
  function getChangeDescription(request, config2) {
@@ -8696,8 +9003,8 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
8696
9003
  const newCode = await ai.editSharedComponentCode(currentCode, instruction, resolved.name);
8697
9004
  const { fixedCode, fixes } = await validateAndFixGeneratedCode(projectRoot, newCode, { isPage: false });
8698
9005
  if (fixes.length > 0) {
8699
- console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
8700
- fixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
9006
+ console.log(chalk12.dim(" \u{1F527} Post-generation fixes:"));
9007
+ fixes.forEach((f) => console.log(chalk12.dim(` ${f}`)));
8701
9008
  }
8702
9009
  await writeFile(fullPath, fixedCode);
8703
9010
  printSharedComponentReport({
@@ -8770,8 +9077,8 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
8770
9077
  const newPageCode = await ai.replaceInlineWithShared(pageCode, sharedCode, resolved.name, changes?.blockHint);
8771
9078
  const { fixedCode, fixes } = await validateAndFixGeneratedCode(projectRoot, newPageCode, { isPage: true });
8772
9079
  if (fixes.length > 0) {
8773
- console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
8774
- fixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
9080
+ console.log(chalk12.dim(" \u{1F527} Post-generation fixes:"));
9081
+ fixes.forEach((f) => console.log(chalk12.dim(` ${f}`)));
8775
9082
  }
8776
9083
  await writeFile(pageFilePath, fixedCode);
8777
9084
  const manifest = await loadManifest6(projectRoot);
@@ -8873,8 +9180,8 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
8873
9180
  const newCode = await ai.replaceInlineWithShared(linkPageCode, sharedCode, created.name, blockHint);
8874
9181
  const { fixedCode, fixes } = await validateAndFixGeneratedCode(projectRoot, newCode, { isPage: true });
8875
9182
  if (fixes.length > 0) {
8876
- console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
8877
- fixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
9183
+ console.log(chalk12.dim(" \u{1F527} Post-generation fixes:"));
9184
+ fixes.forEach((f) => console.log(chalk12.dim(` ${f}`)));
8878
9185
  }
8879
9186
  await writeFile(fullPath, fixedCode);
8880
9187
  usedInFiles.push(relPath);
@@ -8965,7 +9272,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
8965
9272
  const aiPageCode = typeof page.pageCode === "string" && page.pageCode.trim() !== "" ? page.pageCode : void 0;
8966
9273
  if (aiPageCode) {
8967
9274
  finalPageCode = aiPageCode;
8968
- if (DEBUG2) console.log(chalk11.dim(` [pageCode] Using AI-generated pageCode (user content priority)`));
9275
+ if (DEBUG2) console.log(chalk12.dim(` [pageCode] Using AI-generated pageCode (user content priority)`));
8969
9276
  } else {
8970
9277
  const inferredType = page.pageType || inferPageType(page.route || "", page.name || "");
8971
9278
  if (inferredType) {
@@ -8980,19 +9287,19 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
8980
9287
  const content = page.structuredContent || getDefaultContent(inferredType, page.name || pageName);
8981
9288
  finalPageCode = templateFn(content, opts);
8982
9289
  if (DEBUG2)
8983
- console.log(chalk11.dim(` [template] Used "${inferredType}" template (inferred from route/name)`));
9290
+ console.log(chalk12.dim(` [template] Used "${inferredType}" template (inferred from route/name)`));
8984
9291
  } catch {
8985
- if (DEBUG2) console.log(chalk11.dim(` [template] Failed for "${inferredType}"`));
9292
+ if (DEBUG2) console.log(chalk12.dim(` [template] Failed for "${inferredType}"`));
8986
9293
  }
8987
9294
  }
8988
9295
  }
8989
9296
  }
8990
9297
  if (!finalPageCode) {
8991
- console.log(chalk11.yellow(`
9298
+ console.log(chalk12.yellow(`
8992
9299
  \u26A0\uFE0F Page "${page.name || page.id}" has no generated code \u2014 it will appear empty.`));
8993
- console.log(chalk11.dim(" This usually means the AI did not produce pageCode for this page."));
9300
+ console.log(chalk12.dim(" This usually means the AI did not produce pageCode for this page."));
8994
9301
  console.log(
8995
- chalk11.dim(
9302
+ chalk12.dim(
8996
9303
  ' Try running: coherent chat "regenerate the ' + (page.name || page.id) + ' page with full content"'
8997
9304
  )
8998
9305
  );
@@ -9034,7 +9341,13 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
9034
9341
  isPage: true
9035
9342
  });
9036
9343
  let codeToWrite = fixedCode;
9037
- const { code: autoFixed, fixes: autoFixes } = await autoFixCode(codeToWrite);
9344
+ const currentPlan = projectRoot ? loadPlan(projectRoot) : null;
9345
+ const autoFixCtx = route ? {
9346
+ currentRoute: route,
9347
+ knownRoutes: dsm.getConfig().pages.map((p) => p.route).filter(Boolean),
9348
+ linkMap: currentPlan?.pageNotes[routeToKey(route)]?.links
9349
+ } : void 0;
9350
+ const { code: autoFixed, fixes: autoFixes } = await autoFixCode(codeToWrite, autoFixCtx);
9038
9351
  codeToWrite = autoFixed;
9039
9352
  const hasDashboardPage = dsm.getConfig().pages.some((p) => p.route === "/dashboard");
9040
9353
  if (!hasDashboardPage) {
@@ -9046,7 +9359,9 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
9046
9359
  }
9047
9360
  const { code: layoutStripped, stripped } = stripInlineLayoutElements(codeToWrite);
9048
9361
  codeToWrite = layoutStripped;
9049
- if (!isMarketingRoute(route) && !isAuthRoute(route)) {
9362
+ const qualityPageType = currentPlan ? getPageType(route, currentPlan) : inferPageTypeFromRoute(route);
9363
+ const pageType = currentPlan ? getPageType(route, currentPlan) : isMarketingRoute(route) ? "marketing" : isAuth ? "auth" : "app";
9364
+ if (pageType === "app") {
9050
9365
  const { code: normalized, fixed: wrapperFixed } = normalizePageWrapper(codeToWrite);
9051
9366
  if (wrapperFixed) {
9052
9367
  codeToWrite = normalized;
@@ -9056,8 +9371,8 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
9056
9371
  const allFixes = [...postFixes, ...autoFixes];
9057
9372
  if (stripped.length > 0) allFixes.push(`stripped inline ${stripped.join(", ")} (layout owns these)`);
9058
9373
  if (allFixes.length > 0) {
9059
- console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
9060
- allFixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
9374
+ console.log(chalk12.dim(" \u{1F527} Post-generation fixes:"));
9375
+ allFixes.forEach((f) => console.log(chalk12.dim(` ${f}`)));
9061
9376
  }
9062
9377
  await writeFile(filePath, codeToWrite);
9063
9378
  const pageIdx = dsm.getConfig().pages.findIndex((p) => p.id === page.id);
@@ -9069,7 +9384,15 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
9069
9384
  pm.updateConfig(cfg);
9070
9385
  }
9071
9386
  const manifestForAudit = await loadManifest6(projectRoot);
9072
- await warnInlineDuplicates(projectRoot, page.name || page.id || route.slice(1), codeToWrite, manifestForAudit);
9387
+ const planForAudit = loadPlan(projectRoot);
9388
+ await warnInlineDuplicates(
9389
+ projectRoot,
9390
+ page.name || page.id || route.slice(1),
9391
+ route,
9392
+ codeToWrite,
9393
+ manifestForAudit,
9394
+ planForAudit ?? void 0
9395
+ );
9073
9396
  const relFilePath = routeToRelPath(route, isAuth);
9074
9397
  printPostGenerationReport({
9075
9398
  action: "created",
@@ -9082,11 +9405,11 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
9082
9405
  layoutShared: manifestForAudit.shared.filter((c) => c.type === "layout"),
9083
9406
  allShared: manifestForAudit.shared
9084
9407
  });
9085
- let issues = validatePageQuality(codeToWrite);
9408
+ let issues = validatePageQuality(codeToWrite, void 0, qualityPageType);
9086
9409
  const errors = issues.filter((i) => i.severity === "error");
9087
9410
  if (errors.length >= 2 && aiProvider) {
9088
9411
  console.log(
9089
- chalk11.yellow(`
9412
+ chalk12.yellow(`
9090
9413
  \u{1F504} ${errors.length} quality errors \u2014 attempting AI fix for ${page.name || page.id}...`)
9091
9414
  );
9092
9415
  try {
@@ -9103,19 +9426,19 @@ Rules:
9103
9426
  - Keep all existing functionality and layout intact`;
9104
9427
  const fixedCode2 = await ai.editPageCode(codeToWrite, instruction, page.name || page.id || "Page");
9105
9428
  if (fixedCode2 && fixedCode2.length > 100 && /export\s+default/.test(fixedCode2)) {
9106
- const recheck = validatePageQuality(fixedCode2);
9429
+ const recheck = validatePageQuality(fixedCode2, void 0, qualityPageType);
9107
9430
  const recheckErrors = recheck.filter((i) => i.severity === "error");
9108
9431
  if (recheckErrors.length < errors.length) {
9109
9432
  codeToWrite = fixedCode2;
9110
- const { code: reFixed, fixes: reFixes } = await autoFixCode(codeToWrite);
9433
+ const { code: reFixed, fixes: reFixes } = await autoFixCode(codeToWrite, autoFixCtx);
9111
9434
  if (reFixes.length > 0) {
9112
9435
  codeToWrite = reFixed;
9113
9436
  postFixes.push(...reFixes);
9114
9437
  }
9115
9438
  await writeFile(filePath, codeToWrite);
9116
- issues = validatePageQuality(codeToWrite);
9439
+ issues = validatePageQuality(codeToWrite, void 0, qualityPageType);
9117
9440
  const finalErrors = issues.filter((i) => i.severity === "error").length;
9118
- console.log(chalk11.green(` \u2714 Quality fix: ${errors.length} \u2192 ${finalErrors} errors`));
9441
+ console.log(chalk12.green(` \u2714 Quality fix: ${errors.length} \u2192 ${finalErrors} errors`));
9119
9442
  }
9120
9443
  }
9121
9444
  }
@@ -9124,15 +9447,15 @@ Rules:
9124
9447
  }
9125
9448
  const report = formatIssues(issues);
9126
9449
  if (report) {
9127
- console.log(chalk11.yellow(`
9450
+ console.log(chalk12.yellow(`
9128
9451
  \u{1F50D} Quality check for ${page.name || page.id}:`));
9129
- console.log(chalk11.dim(report));
9452
+ console.log(chalk12.dim(report));
9130
9453
  }
9131
9454
  const consistency = checkDesignConsistency(codeToWrite);
9132
9455
  if (consistency.length > 0) {
9133
- console.log(chalk11.yellow(`
9456
+ console.log(chalk12.yellow(`
9134
9457
  \u{1F3A8} Design consistency for ${page.name || page.id}:`));
9135
- consistency.forEach((w) => console.log(chalk11.dim(` \u26A0 [${w.type}] ${w.message}`)));
9458
+ consistency.forEach((w) => console.log(chalk12.dim(` \u26A0 [${w.type}] ${w.message}`)));
9136
9459
  }
9137
9460
  }
9138
9461
  }
@@ -9147,9 +9470,9 @@ Rules:
9147
9470
  const changes = request.changes;
9148
9471
  const instruction = originalMessage || (typeof changes?.instruction === "string" ? changes.instruction : void 0);
9149
9472
  let resolvedPageCode = typeof changes?.pageCode === "string" && changes.pageCode.trim() !== "" ? changes.pageCode : void 0;
9150
- if (DEBUG2 && instruction) console.log(chalk11.dim(` [update-page] instruction: ${instruction.slice(0, 120)}...`));
9473
+ if (DEBUG2 && instruction) console.log(chalk12.dim(` [update-page] instruction: ${instruction.slice(0, 120)}...`));
9151
9474
  if (DEBUG2 && resolvedPageCode)
9152
- console.log(chalk11.dim(` [update-page] has pageCode (${resolvedPageCode.length} chars)`));
9475
+ console.log(chalk12.dim(` [update-page] has pageCode (${resolvedPageCode.length} chars)`));
9153
9476
  const configChanges = { ...changes };
9154
9477
  delete configChanges.pageCode;
9155
9478
  delete configChanges.pageType;
@@ -9173,12 +9496,12 @@ Rules:
9173
9496
  try {
9174
9497
  currentCode = await readFile(absPath);
9175
9498
  } catch {
9176
- if (DEBUG2) console.log(chalk11.dim(` [update-page] Could not read current file at ${absPath}`));
9499
+ if (DEBUG2) console.log(chalk12.dim(` [update-page] Could not read current file at ${absPath}`));
9177
9500
  }
9178
9501
  if (currentCode) {
9179
9502
  const ai = await createAIProvider(aiProvider ?? "auto");
9180
9503
  if (ai.editPageCode) {
9181
- console.log(chalk11.dim(" \u270F\uFE0F Applying changes to existing page..."));
9504
+ console.log(chalk12.dim(" \u270F\uFE0F Applying changes to existing page..."));
9182
9505
  const coreRules = CORE_CONSTRAINTS;
9183
9506
  const qualityRules = DESIGN_QUALITY;
9184
9507
  const contextualRules = selectContextualRules(instruction);
@@ -9198,15 +9521,15 @@ ${contextualRules}
9198
9521
  ${routeRules}
9199
9522
  ${pagesCtx}`
9200
9523
  );
9201
- if (DEBUG2) console.log(chalk11.dim(` [update-page] AI returned ${resolvedPageCode.length} chars`));
9524
+ if (DEBUG2) console.log(chalk12.dim(` [update-page] AI returned ${resolvedPageCode.length} chars`));
9202
9525
  const editIssues = verifyIncrementalEdit(currentCode, resolvedPageCode);
9203
9526
  if (editIssues.length > 0) {
9204
- console.log(chalk11.yellow(`
9527
+ console.log(chalk12.yellow(`
9205
9528
  \u26A0 Incremental edit issues for ${pageDef.name || pageDef.id}:`));
9206
- editIssues.forEach((issue) => console.log(chalk11.dim(` [${issue.type}] ${issue.message}`)));
9529
+ editIssues.forEach((issue) => console.log(chalk12.dim(` [${issue.type}] ${issue.message}`)));
9207
9530
  }
9208
9531
  } else {
9209
- console.log(chalk11.yellow(" \u26A0 AI provider does not support editPageCode"));
9532
+ console.log(chalk12.yellow(" \u26A0 AI provider does not support editPageCode"));
9210
9533
  }
9211
9534
  }
9212
9535
  }
@@ -9234,7 +9557,13 @@ ${pagesCtx}`
9234
9557
  isPage: true
9235
9558
  });
9236
9559
  let codeToWrite = fixedCode;
9237
- const { code: autoFixed, fixes: autoFixes } = await autoFixCode(codeToWrite);
9560
+ const currentPlan2 = projectRoot ? loadPlan(projectRoot) : null;
9561
+ const autoFixCtx2 = route ? {
9562
+ currentRoute: route,
9563
+ knownRoutes: dsm.getConfig().pages.map((p) => p.route).filter(Boolean),
9564
+ linkMap: currentPlan2?.pageNotes[routeToKey(route)]?.links
9565
+ } : void 0;
9566
+ const { code: autoFixed, fixes: autoFixes } = await autoFixCode(codeToWrite, autoFixCtx2);
9238
9567
  codeToWrite = autoFixed;
9239
9568
  const hasDashboardPage = dsm.getConfig().pages.some((p) => p.route === "/dashboard");
9240
9569
  if (!hasDashboardPage) {
@@ -9246,7 +9575,9 @@ ${pagesCtx}`
9246
9575
  }
9247
9576
  const { code: layoutStripped, stripped } = stripInlineLayoutElements(codeToWrite);
9248
9577
  codeToWrite = layoutStripped;
9249
- if (!isMarketingRoute(route) && !isAuthRoute(route)) {
9578
+ const qualityPageType2 = currentPlan2 ? getPageType(route, currentPlan2) : inferPageTypeFromRoute(route);
9579
+ const pageType2 = currentPlan2 ? getPageType(route, currentPlan2) : isMarketingRoute(route) ? "marketing" : isAuth ? "auth" : "app";
9580
+ if (pageType2 === "app") {
9250
9581
  const { code: normalized, fixed: wrapperFixed } = normalizePageWrapper(codeToWrite);
9251
9582
  if (wrapperFixed) {
9252
9583
  codeToWrite = normalized;
@@ -9256,8 +9587,8 @@ ${pagesCtx}`
9256
9587
  const allFixes = [...postFixes, ...autoFixes];
9257
9588
  if (stripped.length > 0) allFixes.push(`stripped inline ${stripped.join(", ")} (layout owns these)`);
9258
9589
  if (allFixes.length > 0) {
9259
- console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
9260
- allFixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
9590
+ console.log(chalk12.dim(" \u{1F527} Post-generation fixes:"));
9591
+ allFixes.forEach((f) => console.log(chalk12.dim(` ${f}`)));
9261
9592
  }
9262
9593
  await writeFile(absPath, codeToWrite);
9263
9594
  const updatePageIdx = dsm.getConfig().pages.findIndex((p) => p.id === pageDef.id);
@@ -9269,11 +9600,14 @@ ${pagesCtx}`
9269
9600
  pm.updateConfig(cfg);
9270
9601
  }
9271
9602
  const manifestForAudit = await loadManifest6(projectRoot);
9603
+ const planForAudit2 = loadPlan(projectRoot);
9272
9604
  await warnInlineDuplicates(
9273
9605
  projectRoot,
9274
9606
  pageDef.name || pageDef.id || route.slice(1),
9607
+ route,
9275
9608
  codeToWrite,
9276
- manifestForAudit
9609
+ manifestForAudit,
9610
+ planForAudit2 ?? void 0
9277
9611
  );
9278
9612
  const relFilePath = routeToRelPath(route, isAuth);
9279
9613
  printPostGenerationReport({
@@ -9287,28 +9621,34 @@ ${pagesCtx}`
9287
9621
  allShared: manifestForAudit.shared,
9288
9622
  layoutShared: manifestForAudit.shared.filter((c) => c.type === "layout")
9289
9623
  });
9290
- const issues = validatePageQuality(codeToWrite);
9624
+ const issues = validatePageQuality(codeToWrite, void 0, qualityPageType2);
9291
9625
  const report = formatIssues(issues);
9292
9626
  if (report) {
9293
- console.log(chalk11.yellow(`
9627
+ console.log(chalk12.yellow(`
9294
9628
  \u{1F50D} Quality check for ${pageDef.name || pageDef.id}:`));
9295
- console.log(chalk11.dim(report));
9629
+ console.log(chalk12.dim(report));
9296
9630
  }
9297
9631
  const consistency = checkDesignConsistency(codeToWrite);
9298
9632
  if (consistency.length > 0) {
9299
- console.log(chalk11.yellow(`
9633
+ console.log(chalk12.yellow(`
9300
9634
  \u{1F3A8} Design consistency for ${pageDef.name || pageDef.id}:`));
9301
- consistency.forEach((w) => console.log(chalk11.dim(` \u26A0 [${w.type}] ${w.message}`)));
9635
+ consistency.forEach((w) => console.log(chalk12.dim(` \u26A0 [${w.type}] ${w.message}`)));
9302
9636
  }
9303
9637
  } else {
9304
9638
  try {
9305
9639
  let code = await readFile(absPath);
9306
- const { code: fixed, fixes } = await autoFixCode(code);
9640
+ const currentPlanForElse = projectRoot ? loadPlan(projectRoot) : null;
9641
+ const autoFixCtxElse = route ? {
9642
+ currentRoute: route,
9643
+ knownRoutes: dsm.getConfig().pages.map((p) => p.route).filter(Boolean),
9644
+ linkMap: currentPlanForElse?.pageNotes[routeToKey(route)]?.links
9645
+ } : void 0;
9646
+ const { code: fixed, fixes } = await autoFixCode(code, autoFixCtxElse);
9307
9647
  if (fixes.length > 0) {
9308
9648
  code = fixed;
9309
9649
  await writeFile(absPath, code);
9310
- console.log(chalk11.dim(" \u{1F527} Auto-fixes applied:"));
9311
- fixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
9650
+ console.log(chalk12.dim(" \u{1F527} Auto-fixes applied:"));
9651
+ fixes.forEach((f) => console.log(chalk12.dim(` ${f}`)));
9312
9652
  }
9313
9653
  const relFilePath = routeToRelPath(route, isAuth);
9314
9654
  const manifest = await loadManifest6(projectRoot);
@@ -9322,12 +9662,14 @@ ${pagesCtx}`
9322
9662
  allShared: manifest.shared,
9323
9663
  layoutShared: manifest.shared.filter((c) => c.type === "layout")
9324
9664
  });
9325
- const issues = validatePageQuality(code);
9665
+ const currentPlanForQuality = currentPlanForElse;
9666
+ const pageTypeForQuality = currentPlanForQuality ? getPageType(route, currentPlanForQuality) : inferPageTypeFromRoute(route);
9667
+ const issues = validatePageQuality(code, void 0, pageTypeForQuality);
9326
9668
  const report = formatIssues(issues);
9327
9669
  if (report) {
9328
- console.log(chalk11.yellow(`
9670
+ console.log(chalk12.yellow(`
9329
9671
  \u{1F50D} Quality check for ${pageDef.name || pageDef.id}:`));
9330
- console.log(chalk11.dim(report));
9672
+ console.log(chalk12.dim(report));
9331
9673
  }
9332
9674
  } catch {
9333
9675
  }
@@ -9450,7 +9792,7 @@ function hasNavChanged(before, after) {
9450
9792
  }
9451
9793
 
9452
9794
  // src/commands/chat/interactive.ts
9453
- import chalk12 from "chalk";
9795
+ import chalk13 from "chalk";
9454
9796
  import { resolve as resolve8 } from "path";
9455
9797
  import { existsSync as existsSync15, readFileSync as readFileSync10, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
9456
9798
  import { DesignSystemManager as DesignSystemManager6, ComponentManager as ComponentManager4, loadManifest as loadManifest7 } from "@getcoherent/core";
@@ -9468,7 +9810,7 @@ async function interactiveChat(options, chatCommandFn) {
9468
9810
  const validProviders = ["claude", "openai", "auto"];
9469
9811
  const provider = (options.provider || "auto").toLowerCase();
9470
9812
  if (!validProviders.includes(provider)) {
9471
- console.error(chalk12.red(`
9813
+ console.error(chalk13.red(`
9472
9814
  \u274C Invalid provider: ${options.provider}`));
9473
9815
  process.exit(1);
9474
9816
  }
@@ -9483,13 +9825,13 @@ async function interactiveChat(options, chatCommandFn) {
9483
9825
  } catch (e) {
9484
9826
  if (DEBUG3) console.error("Failed to load REPL history:", e);
9485
9827
  }
9486
- console.log(chalk12.cyan("\n\u{1F3A8} Coherent Interactive Mode"));
9487
- console.log(chalk12.dim(" Type your requests, or use built-in commands."));
9488
- console.log(chalk12.dim(' Type "help" for available commands, "exit" to quit.\n'));
9828
+ console.log(chalk13.cyan("\n\u{1F3A8} Coherent Interactive Mode"));
9829
+ console.log(chalk13.dim(" Type your requests, or use built-in commands."));
9830
+ console.log(chalk13.dim(' Type "help" for available commands, "exit" to quit.\n'));
9489
9831
  const rl = createInterface({
9490
9832
  input: process.stdin,
9491
9833
  output: process.stdout,
9492
- prompt: chalk12.cyan("Coherent> "),
9834
+ prompt: chalk13.cyan("Coherent> "),
9493
9835
  history,
9494
9836
  historySize: 200
9495
9837
  });
@@ -9503,37 +9845,37 @@ async function interactiveChat(options, chatCommandFn) {
9503
9845
  const lower = input.toLowerCase();
9504
9846
  if (lower === "exit" || lower === "quit" || lower === "q") {
9505
9847
  saveHistory();
9506
- console.log(chalk12.dim("\nBye!\n"));
9848
+ console.log(chalk13.dim("\nBye!\n"));
9507
9849
  rl.close();
9508
9850
  process.exit(0);
9509
9851
  }
9510
9852
  if (lower === "help") {
9511
- console.log(chalk12.bold("\n Built-in commands:"));
9512
- console.log(chalk12.white(" components") + chalk12.dim(" \u2014 list shared and UI components"));
9513
- console.log(chalk12.white(" pages") + chalk12.dim(" \u2014 list all pages"));
9514
- console.log(chalk12.white(" tokens") + chalk12.dim(" \u2014 show design tokens"));
9515
- console.log(chalk12.white(" status") + chalk12.dim(" \u2014 project summary"));
9516
- console.log(chalk12.white(" help") + chalk12.dim(" \u2014 this help"));
9517
- console.log(chalk12.white(" exit") + chalk12.dim(" \u2014 quit interactive mode"));
9518
- console.log(chalk12.bold("\n Target shortcuts:"));
9519
- console.log(chalk12.white(" @ComponentName <msg>") + chalk12.dim(" \u2014 target a shared component"));
9520
- console.log(chalk12.white(" @/route <msg>") + chalk12.dim(" \u2014 target a page by route"));
9521
- console.log(chalk12.dim("\n Anything else is sent to AI as a modification request.\n"));
9853
+ console.log(chalk13.bold("\n Built-in commands:"));
9854
+ console.log(chalk13.white(" components") + chalk13.dim(" \u2014 list shared and UI components"));
9855
+ console.log(chalk13.white(" pages") + chalk13.dim(" \u2014 list all pages"));
9856
+ console.log(chalk13.white(" tokens") + chalk13.dim(" \u2014 show design tokens"));
9857
+ console.log(chalk13.white(" status") + chalk13.dim(" \u2014 project summary"));
9858
+ console.log(chalk13.white(" help") + chalk13.dim(" \u2014 this help"));
9859
+ console.log(chalk13.white(" exit") + chalk13.dim(" \u2014 quit interactive mode"));
9860
+ console.log(chalk13.bold("\n Target shortcuts:"));
9861
+ console.log(chalk13.white(" @ComponentName <msg>") + chalk13.dim(" \u2014 target a shared component"));
9862
+ console.log(chalk13.white(" @/route <msg>") + chalk13.dim(" \u2014 target a page by route"));
9863
+ console.log(chalk13.dim("\n Anything else is sent to AI as a modification request.\n"));
9522
9864
  rl.prompt();
9523
9865
  return;
9524
9866
  }
9525
9867
  if (lower === "components" || lower === "list components" || lower.includes("what components")) {
9526
9868
  const manifest = await loadManifest7(projectRoot);
9527
9869
  if (manifest.shared.length === 0) {
9528
- console.log(chalk12.gray("\n No shared components yet.\n"));
9870
+ console.log(chalk13.gray("\n No shared components yet.\n"));
9529
9871
  } else {
9530
9872
  console.log("");
9531
9873
  const order = { layout: 0, section: 1, widget: 2 };
9532
9874
  const sorted = [...manifest.shared].sort((a, b) => (order[a.type] ?? 9) - (order[b.type] ?? 9));
9533
9875
  sorted.forEach((entry) => {
9534
- const usage = entry.usedIn.includes("app/layout.tsx") ? chalk12.green("all pages") : entry.usedIn.length > 0 ? chalk12.gray(entry.usedIn.join(", ")) : chalk12.gray("unused");
9876
+ const usage = entry.usedIn.includes("app/layout.tsx") ? chalk13.green("all pages") : entry.usedIn.length > 0 ? chalk13.gray(entry.usedIn.join(", ")) : chalk13.gray("unused");
9535
9877
  console.log(
9536
- ` ${chalk12.cyan(entry.id.padEnd(8))} ${chalk12.white(entry.name.padEnd(18))} ${chalk12.gray(entry.type.padEnd(9))} ${usage}`
9878
+ ` ${chalk13.cyan(entry.id.padEnd(8))} ${chalk13.white(entry.name.padEnd(18))} ${chalk13.gray(entry.type.padEnd(9))} ${usage}`
9537
9879
  );
9538
9880
  });
9539
9881
  console.log("");
@@ -9544,11 +9886,11 @@ async function interactiveChat(options, chatCommandFn) {
9544
9886
  if (lower === "pages" || lower === "list pages" || lower.includes("what pages")) {
9545
9887
  const currentConfig = dsm.getConfig();
9546
9888
  if (currentConfig.pages.length === 0) {
9547
- console.log(chalk12.gray("\n No pages yet.\n"));
9889
+ console.log(chalk13.gray("\n No pages yet.\n"));
9548
9890
  } else {
9549
9891
  console.log("");
9550
9892
  currentConfig.pages.forEach((p) => {
9551
- console.log(` ${chalk12.white(p.name.padEnd(22))} ${chalk12.gray(p.route)}`);
9893
+ console.log(` ${chalk13.white(p.name.padEnd(22))} ${chalk13.gray(p.route)}`);
9552
9894
  });
9553
9895
  console.log("");
9554
9896
  }
@@ -9558,10 +9900,10 @@ async function interactiveChat(options, chatCommandFn) {
9558
9900
  if (lower === "status") {
9559
9901
  const currentConfig = dsm.getConfig();
9560
9902
  const manifest = await loadManifest7(projectRoot);
9561
- console.log(chalk12.bold(`
9903
+ console.log(chalk13.bold(`
9562
9904
  ${currentConfig.name || "Coherent Project"}`));
9563
9905
  console.log(
9564
- chalk12.dim(
9906
+ chalk13.dim(
9565
9907
  ` Pages: ${currentConfig.pages.length} | Shared components: ${manifest.shared.length} | UI components: ${cm.getAllComponents().length}
9566
9908
  `
9567
9909
  )
@@ -9572,21 +9914,21 @@ async function interactiveChat(options, chatCommandFn) {
9572
9914
  if (lower === "tokens" || lower === "show tokens" || lower === "design tokens") {
9573
9915
  const currentConfig = dsm.getConfig();
9574
9916
  const t = currentConfig.tokens;
9575
- console.log(chalk12.bold("\n Design Tokens\n"));
9576
- console.log(chalk12.cyan(" Colors (light)"));
9917
+ console.log(chalk13.bold("\n Design Tokens\n"));
9918
+ console.log(chalk13.cyan(" Colors (light)"));
9577
9919
  for (const [k, v] of Object.entries(t.colors.light)) {
9578
- console.log(` ${chalk12.white(k.padEnd(14))} ${chalk12.gray(v)}`);
9920
+ console.log(` ${chalk13.white(k.padEnd(14))} ${chalk13.gray(v)}`);
9579
9921
  }
9580
- console.log(chalk12.cyan("\n Typography"));
9581
- console.log(` ${chalk12.white("sans".padEnd(14))} ${chalk12.gray(t.typography.fontFamily.sans)}`);
9582
- console.log(` ${chalk12.white("mono".padEnd(14))} ${chalk12.gray(t.typography.fontFamily.mono)}`);
9583
- console.log(chalk12.cyan("\n Spacing"));
9922
+ console.log(chalk13.cyan("\n Typography"));
9923
+ console.log(` ${chalk13.white("sans".padEnd(14))} ${chalk13.gray(t.typography.fontFamily.sans)}`);
9924
+ console.log(` ${chalk13.white("mono".padEnd(14))} ${chalk13.gray(t.typography.fontFamily.mono)}`);
9925
+ console.log(chalk13.cyan("\n Spacing"));
9584
9926
  for (const [k, v] of Object.entries(t.spacing)) {
9585
- console.log(` ${chalk12.white(k.padEnd(14))} ${chalk12.gray(v)}`);
9927
+ console.log(` ${chalk13.white(k.padEnd(14))} ${chalk13.gray(v)}`);
9586
9928
  }
9587
- console.log(chalk12.cyan("\n Radius"));
9929
+ console.log(chalk13.cyan("\n Radius"));
9588
9930
  for (const [k, v] of Object.entries(t.radius)) {
9589
- console.log(` ${chalk12.white(k.padEnd(14))} ${chalk12.gray(v)}`);
9931
+ console.log(` ${chalk13.white(k.padEnd(14))} ${chalk13.gray(v)}`);
9590
9932
  }
9591
9933
  console.log("");
9592
9934
  rl.prompt();
@@ -9608,7 +9950,7 @@ async function interactiveChat(options, chatCommandFn) {
9608
9950
  await dsm.load();
9609
9951
  } catch (err) {
9610
9952
  if (!err._printed) {
9611
- console.error(chalk12.red(`
9953
+ console.error(chalk13.red(`
9612
9954
  Error: ${err.message}
9613
9955
  `));
9614
9956
  }
@@ -9640,8 +9982,8 @@ async function chatCommand(message, options) {
9640
9982
  process.exit(1);
9641
9983
  };
9642
9984
  if (!message) {
9643
- console.error(chalk13.red('\n\u274C No message provided. Use: coherent chat "your request"\n'));
9644
- console.log(chalk13.dim(" Or use interactive mode: coherent chat -i\n"));
9985
+ console.error(chalk14.red('\n\u274C No message provided. Use: coherent chat "your request"\n'));
9986
+ console.log(chalk14.dim(" Or use interactive mode: coherent chat -i\n"));
9645
9987
  bail("No message provided");
9646
9988
  }
9647
9989
  const spinner = ora2("Processing your request...").start();
@@ -9651,7 +9993,7 @@ async function chatCommand(message, options) {
9651
9993
  const migrationGuard = join11(projectRoot, ".coherent", "migration-in-progress");
9652
9994
  if (existsSync16(migrationGuard)) {
9653
9995
  spinner.fail("Migration in progress");
9654
- console.error(chalk13.red("\n\u274C A migration is in progress. Run `coherent migrate --rollback` to undo first."));
9996
+ console.error(chalk14.red("\n\u274C A migration is in progress. Run `coherent migrate --rollback` to undo first."));
9655
9997
  bail("Migration in progress");
9656
9998
  }
9657
9999
  const validProviders = ["claude", "openai", "auto"];
@@ -9661,20 +10003,20 @@ async function chatCommand(message, options) {
9661
10003
  releaseLock = await acquireProjectLock(projectRoot);
9662
10004
  if (!validProviders.includes(provider)) {
9663
10005
  spinner.fail("Invalid provider");
9664
- console.error(chalk13.red(`
10006
+ console.error(chalk14.red(`
9665
10007
  \u274C Invalid provider: ${options.provider}`));
9666
- console.log(chalk13.dim(`Valid options: ${validProviders.join(", ")}`));
10008
+ console.log(chalk14.dim(`Valid options: ${validProviders.join(", ")}`));
9667
10009
  bail(`Invalid provider: ${options.provider}`);
9668
10010
  }
9669
10011
  spinner.text = "Loading design system configuration...";
9670
10012
  const config2 = await loadConfig(configPath);
9671
10013
  if (config2.coherentVersion && config2.coherentVersion !== CLI_VERSION2) {
9672
10014
  spinner.stop();
9673
- console.log(chalk13.yellow("\n\u26A0\uFE0F Version mismatch detected\n"));
9674
- console.log(chalk13.gray(" Project created with: ") + chalk13.white(`v${config2.coherentVersion}`));
9675
- console.log(chalk13.gray(" Current CLI version: ") + chalk13.white(`v${CLI_VERSION2}`));
9676
- console.log(chalk13.cyan("\n \u{1F4A1} Run `coherent update` to apply latest changes to your project.\n"));
9677
- console.log(chalk13.dim(" Continuing anyway...\n"));
10015
+ console.log(chalk14.yellow("\n\u26A0\uFE0F Version mismatch detected\n"));
10016
+ console.log(chalk14.gray(" Project created with: ") + chalk14.white(`v${config2.coherentVersion}`));
10017
+ console.log(chalk14.gray(" Current CLI version: ") + chalk14.white(`v${CLI_VERSION2}`));
10018
+ console.log(chalk14.cyan("\n \u{1F4A1} Run `coherent update` to apply latest changes to your project.\n"));
10019
+ console.log(chalk14.dim(" Continuing anyway...\n"));
9678
10020
  spinner.start("Loading design system configuration...");
9679
10021
  }
9680
10022
  if (needsGlobalsFix(projectRoot)) {
@@ -9701,9 +10043,9 @@ async function chatCommand(message, options) {
9701
10043
  const done = await setDefaultDarkTheme(projectRoot);
9702
10044
  spinner.stop();
9703
10045
  if (done) {
9704
- console.log(chalk13.green("\n\u2705 Default theme set to dark. Reload the app to see changes.\n"));
10046
+ console.log(chalk14.green("\n\u2705 Default theme set to dark. Reload the app to see changes.\n"));
9705
10047
  } else {
9706
- console.log(chalk13.yellow("\n\u26A0\uFE0F Could not update layout (app/layout.tsx not found).\n"));
10048
+ console.log(chalk14.yellow("\n\u26A0\uFE0F Could not update layout (app/layout.tsx not found).\n"));
9707
10049
  }
9708
10050
  return;
9709
10051
  }
@@ -9719,10 +10061,10 @@ async function chatCommand(message, options) {
9719
10061
  dsm.updateConfig(cfg);
9720
10062
  dsm.save();
9721
10063
  spinner.stop();
9722
- console.log(chalk13.green("\n\u2705 Default theme set to light. Reload the app to see changes.\n"));
10064
+ console.log(chalk14.green("\n\u2705 Default theme set to light. Reload the app to see changes.\n"));
9723
10065
  } catch {
9724
10066
  spinner.stop();
9725
- console.log(chalk13.yellow("\n\u26A0\uFE0F Could not update layout (app/layout.tsx not found).\n"));
10067
+ console.log(chalk14.yellow("\n\u26A0\uFE0F Could not update layout (app/layout.tsx not found).\n"));
9726
10068
  }
9727
10069
  return;
9728
10070
  }
@@ -9732,7 +10074,7 @@ async function chatCommand(message, options) {
9732
10074
  const { created, id } = await ensureThemeToggle(projectRoot);
9733
10075
  spinner.stop();
9734
10076
  console.log(
9735
- chalk13.green(
10077
+ chalk14.green(
9736
10078
  `
9737
10079
  \u2705 ${created ? `Created ${id} (ThemeToggle) and added to layout` : "ThemeToggle already present; layout updated"}.
9738
10080
  `
@@ -9740,7 +10082,7 @@ async function chatCommand(message, options) {
9740
10082
  );
9741
10083
  } catch (e) {
9742
10084
  spinner.fail("Failed to add theme toggle");
9743
- if (e instanceof Error) console.error(chalk13.red("\n\u274C " + e.message + "\n"));
10085
+ if (e instanceof Error) console.error(chalk14.red("\n\u274C " + e.message + "\n"));
9744
10086
  }
9745
10087
  return;
9746
10088
  }
@@ -9756,12 +10098,12 @@ async function chatCommand(message, options) {
9756
10098
  manifest = { ...manifest, shared: validShared };
9757
10099
  await saveManifest2(project.root, manifest);
9758
10100
  if (DEBUG4) {
9759
- console.log(chalk13.dim(`[pre-gen] Cleaned ${cleaned} orphaned component(s) from manifest`));
10101
+ console.log(chalk14.dim(`[pre-gen] Cleaned ${cleaned} orphaned component(s) from manifest`));
9760
10102
  }
9761
10103
  }
9762
10104
  const sharedComponentsSummary = buildSharedComponentsSummary(manifest);
9763
10105
  if (DEBUG4 && sharedComponentsSummary) {
9764
- console.log(chalk13.dim("[add-page] sharedComponentsSummary in prompt:\n" + sharedComponentsSummary));
10106
+ console.log(chalk14.dim("[add-page] sharedComponentsSummary in prompt:\n" + sharedComponentsSummary));
9765
10107
  }
9766
10108
  let requests;
9767
10109
  let uxRecommendations;
@@ -9773,7 +10115,12 @@ async function chatCommand(message, options) {
9773
10115
  ) || []).length >= SPLIT_THRESHOLD;
9774
10116
  if (multiPageHint) {
9775
10117
  try {
9776
- requests = await splitGeneratePages(spinner, message, modCtx, provider, parseOpts);
10118
+ const splitResult = await splitGeneratePages(spinner, message, modCtx, provider, parseOpts);
10119
+ requests = splitResult.requests;
10120
+ if (splitResult.plan && projectRoot) {
10121
+ savePlan(projectRoot, splitResult.plan);
10122
+ await ensurePlanGroupLayouts(projectRoot, splitResult.plan);
10123
+ }
9777
10124
  uxRecommendations = void 0;
9778
10125
  } catch {
9779
10126
  spinner.warn("Split generation encountered an issue \u2014 trying page-by-page...");
@@ -9846,7 +10193,12 @@ async function chatCommand(message, options) {
9846
10193
  if (isTruncated || isJsonError) {
9847
10194
  spinner.warn("Response too large \u2014 splitting into smaller requests...");
9848
10195
  try {
9849
- requests = await splitGeneratePages(spinner, message, modCtx, provider, parseOpts);
10196
+ const splitResult = await splitGeneratePages(spinner, message, modCtx, provider, parseOpts);
10197
+ requests = splitResult.requests;
10198
+ if (splitResult.plan && projectRoot) {
10199
+ savePlan(projectRoot, splitResult.plan);
10200
+ await ensurePlanGroupLayouts(projectRoot, splitResult.plan);
10201
+ }
9850
10202
  uxRecommendations = void 0;
9851
10203
  } catch {
9852
10204
  throw firstError;
@@ -9858,10 +10210,10 @@ async function chatCommand(message, options) {
9858
10210
  }
9859
10211
  if (requests.length === 0) {
9860
10212
  spinner.fail("No modifications found in your request");
9861
- console.log(chalk13.yellow("\n\u{1F4A1} Try being more specific, e.g.:"));
9862
- console.log(chalk13.dim(' - "make buttons blue"'));
9863
- console.log(chalk13.dim(' - "add a pricing page"'));
9864
- console.log(chalk13.dim(' - "change primary color to green"'));
10213
+ console.log(chalk14.yellow("\n\u{1F4A1} Try being more specific, e.g.:"));
10214
+ console.log(chalk14.dim(' - "make buttons blue"'));
10215
+ console.log(chalk14.dim(' - "add a pricing page"'));
10216
+ console.log(chalk14.dim(' - "change primary color to green"'));
9865
10217
  return;
9866
10218
  }
9867
10219
  spinner.succeed(`Parsed ${requests.length} modification(s)`);
@@ -9869,11 +10221,11 @@ async function chatCommand(message, options) {
9869
10221
  normalizedRequests = normalizedRequests.map((req) => {
9870
10222
  const result = normalizeRequest(req, dsm.getConfig());
9871
10223
  if ("error" in result) {
9872
- console.log(chalk13.yellow(` \u26A0 Skipped: ${result.error}`));
10224
+ console.log(chalk14.yellow(` \u26A0 Skipped: ${result.error}`));
9873
10225
  return null;
9874
10226
  }
9875
10227
  if (result.type !== req.type) {
9876
- console.log(chalk13.dim(` \u2139 Adjusted: ${req.type} \u2192 ${result.type} (target: ${req.target})`));
10228
+ console.log(chalk14.dim(` \u2139 Adjusted: ${req.type} \u2192 ${result.type} (target: ${req.target})`));
9877
10229
  }
9878
10230
  return result;
9879
10231
  }).filter((r) => r !== null);
@@ -9929,13 +10281,13 @@ async function chatCommand(message, options) {
9929
10281
  }
9930
10282
  }
9931
10283
  if (DEBUG4) {
9932
- console.log(chalk13.gray(`
10284
+ console.log(chalk14.gray(`
9933
10285
  [DEBUG] Pre-flight analysis for page "${page.name || page.route}": `));
9934
- console.log(chalk13.gray(` Page sections: ${page.sections?.length || 0}`));
10286
+ console.log(chalk14.gray(` Page sections: ${page.sections?.length || 0}`));
9935
10287
  if (page.sections?.[0]?.props?.fields) {
9936
- console.log(chalk13.gray(` First section has ${page.sections[0].props.fields.length} fields`));
10288
+ console.log(chalk14.gray(` First section has ${page.sections[0].props.fields.length} fields`));
9937
10289
  page.sections[0].props.fields.forEach((f, i) => {
9938
- console.log(chalk13.gray(` Field ${i}: component=${f.component}`));
10290
+ console.log(chalk14.gray(` Field ${i}: component=${f.component}`));
9939
10291
  });
9940
10292
  }
9941
10293
  }
@@ -9958,8 +10310,8 @@ async function chatCommand(message, options) {
9958
10310
  const INVALID_COMPONENT_IDS = /* @__PURE__ */ new Set(["ui", "shared", "lib", "utils", "hooks", "app", "components"]);
9959
10311
  for (const id of INVALID_COMPONENT_IDS) allNeededComponentIds.delete(id);
9960
10312
  if (DEBUG4) {
9961
- console.log(chalk13.gray("\n[DEBUG] Pre-flight analysis (consolidated):"));
9962
- console.log(chalk13.gray(` All needed components: ${Array.from(allNeededComponentIds).join(", ")}`));
10313
+ console.log(chalk14.gray("\n[DEBUG] Pre-flight analysis (consolidated):"));
10314
+ console.log(chalk14.gray(` All needed components: ${Array.from(allNeededComponentIds).join(", ")}`));
9963
10315
  console.log("");
9964
10316
  }
9965
10317
  const missingComponents = [];
@@ -9967,59 +10319,59 @@ async function chatCommand(message, options) {
9967
10319
  const isRegistered = !!cm.read(componentId);
9968
10320
  const filePath = join11(projectRoot, "components", "ui", `${componentId}.tsx`);
9969
10321
  const fileExists = existsSync16(filePath);
9970
- if (DEBUG4) console.log(chalk13.gray(` Checking ${componentId}: registered=${isRegistered} file=${fileExists}`));
10322
+ if (DEBUG4) console.log(chalk14.gray(` Checking ${componentId}: registered=${isRegistered} file=${fileExists}`));
9971
10323
  if (!isRegistered || !fileExists) {
9972
10324
  missingComponents.push(componentId);
9973
10325
  }
9974
10326
  }
9975
10327
  if (missingComponents.length > 0) {
9976
10328
  spinner.stop();
9977
- console.log(chalk13.cyan("\n\u{1F50D} Pre-flight check: Installing missing components...\n"));
10329
+ console.log(chalk14.cyan("\n\u{1F50D} Pre-flight check: Installing missing components...\n"));
9978
10330
  const provider2 = getComponentProvider();
9979
10331
  for (const componentId of missingComponents) {
9980
10332
  if (DEBUG4) {
9981
- console.log(chalk13.gray(` [DEBUG] Trying to install: ${componentId}`));
9982
- console.log(chalk13.gray(` [DEBUG] provider.has(${componentId}): ${provider2.has(componentId)}`));
10333
+ console.log(chalk14.gray(` [DEBUG] Trying to install: ${componentId}`));
10334
+ console.log(chalk14.gray(` [DEBUG] provider.has(${componentId}): ${provider2.has(componentId)}`));
9983
10335
  }
9984
10336
  if (provider2.has(componentId)) {
9985
10337
  try {
9986
10338
  const result = await provider2.installComponent(componentId, projectRoot);
9987
- if (DEBUG4) console.log(chalk13.gray(` [DEBUG] installComponent result: ${result.success}`));
10339
+ if (DEBUG4) console.log(chalk14.gray(` [DEBUG] installComponent result: ${result.success}`));
9988
10340
  if (result.success && result.componentDef) {
9989
10341
  if (!cm.read(componentId)) {
9990
10342
  if (DEBUG4)
9991
10343
  console.log(
9992
- chalk13.gray(` [DEBUG] Registering ${result.componentDef.id} (${result.componentDef.name})`)
10344
+ chalk14.gray(` [DEBUG] Registering ${result.componentDef.id} (${result.componentDef.name})`)
9993
10345
  );
9994
10346
  const regResult = await cm.register(result.componentDef);
9995
10347
  if (DEBUG4) {
9996
10348
  console.log(
9997
- chalk13.gray(
10349
+ chalk14.gray(
9998
10350
  ` [DEBUG] Register result: ${regResult.success ? "SUCCESS" : "FAILED"}${!regResult.success && regResult.message ? ` - ${regResult.message}` : ""}`
9999
10351
  )
10000
10352
  );
10001
10353
  }
10002
10354
  if (regResult.success) {
10003
10355
  preflightInstalledIds.push(result.componentDef.id);
10004
- console.log(chalk13.green(` \u2728 Auto-installed ${result.componentDef.name} component`));
10356
+ console.log(chalk14.green(` \u2728 Auto-installed ${result.componentDef.name} component`));
10005
10357
  dsm.updateConfig(regResult.config);
10006
10358
  cm.updateConfig(regResult.config);
10007
10359
  pm.updateConfig(regResult.config);
10008
10360
  }
10009
10361
  } else {
10010
10362
  preflightInstalledIds.push(result.componentDef.id);
10011
- console.log(chalk13.green(` \u2728 Re-installed ${result.componentDef.name} component (file was missing)`));
10363
+ console.log(chalk14.green(` \u2728 Re-installed ${result.componentDef.name} component (file was missing)`));
10012
10364
  }
10013
10365
  }
10014
10366
  } catch (error) {
10015
- console.log(chalk13.red(` \u274C Failed to install ${componentId}:`));
10016
- console.log(chalk13.red(` ${error instanceof Error ? error.message : error}`));
10367
+ console.log(chalk14.red(` \u274C Failed to install ${componentId}:`));
10368
+ console.log(chalk14.red(` ${error instanceof Error ? error.message : error}`));
10017
10369
  if (error instanceof Error && error.stack) {
10018
- console.log(chalk13.gray(` ${error.stack.split("\n")[1]}`));
10370
+ console.log(chalk14.gray(` ${error.stack.split("\n")[1]}`));
10019
10371
  }
10020
10372
  }
10021
10373
  } else {
10022
- console.log(chalk13.yellow(` \u26A0\uFE0F Component ${componentId} not available`));
10374
+ console.log(chalk14.yellow(` \u26A0\uFE0F Component ${componentId} not available`));
10023
10375
  }
10024
10376
  }
10025
10377
  console.log("");
@@ -10030,11 +10382,11 @@ async function chatCommand(message, options) {
10030
10382
  const toInstallNpm = [...neededPkgs].filter((p) => !installedPkgs.has(p));
10031
10383
  if (toInstallNpm.length > 0) {
10032
10384
  spinner.stop();
10033
- console.log(chalk13.cyan(`
10385
+ console.log(chalk14.cyan(`
10034
10386
  \u{1F4E6} Auto-installing missing dependencies: ${toInstallNpm.join(", ")}
10035
10387
  `));
10036
10388
  const ok = await installPackages(projectRoot, toInstallNpm);
10037
- if (!ok) console.log(chalk13.yellow(` Run manually: npm install ${toInstallNpm.join(" ")}
10389
+ if (!ok) console.log(chalk14.yellow(` Run manually: npm install ${toInstallNpm.join(" ")}
10038
10390
  `));
10039
10391
  spinner.start("Applying modifications...");
10040
10392
  }
@@ -10045,7 +10397,7 @@ async function chatCommand(message, options) {
10045
10397
  if (componentId && preflightComponentIds.has(componentId)) {
10046
10398
  if (DEBUG4) {
10047
10399
  console.log(
10048
- chalk13.gray(`[DEBUG] Filtered duplicate add-component: ${componentId} (already installed in pre-flight)`)
10400
+ chalk14.gray(`[DEBUG] Filtered duplicate add-component: ${componentId} (already installed in pre-flight)`)
10049
10401
  );
10050
10402
  }
10051
10403
  return false;
@@ -10054,11 +10406,11 @@ async function chatCommand(message, options) {
10054
10406
  return true;
10055
10407
  });
10056
10408
  if (DEBUG4 && preflightComponentIds.size > 0) {
10057
- console.log(chalk13.gray(`[DEBUG] Remaining requests after filtering: ${normalizedRequests.length}`));
10409
+ console.log(chalk14.gray(`[DEBUG] Remaining requests after filtering: ${normalizedRequests.length}`));
10058
10410
  }
10059
10411
  try {
10060
10412
  createBackup(projectRoot);
10061
- if (DEBUG4) console.log(chalk13.dim("[backup] Created snapshot"));
10413
+ if (DEBUG4) console.log(chalk14.dim("[backup] Created snapshot"));
10062
10414
  } catch {
10063
10415
  }
10064
10416
  const navBefore = takeNavSnapshot(
@@ -10113,10 +10465,10 @@ async function chatCommand(message, options) {
10113
10465
  const SCAFFOLD_AI_LIMIT = 10;
10114
10466
  if (missingRoutes.length > 0 && missingRoutes.length <= SCAFFOLD_AI_LIMIT) {
10115
10467
  spinner.stop();
10116
- console.log(chalk13.cyan(`
10468
+ console.log(chalk14.cyan(`
10117
10469
  \u{1F517} Auto-scaffolding ${missingRoutes.length} linked page(s)...`));
10118
10470
  console.log(
10119
- chalk13.dim(
10471
+ chalk14.dim(
10120
10472
  ` (${missingRoutes.length} additional AI call(s) \u2014 disable with settings.autoScaffold: false in config)
10121
10473
  `
10122
10474
  )
@@ -10153,7 +10505,7 @@ async function chatCommand(message, options) {
10153
10505
  }
10154
10506
  } catch (err) {
10155
10507
  scaffoldSpinner.warn(` Could not scaffold "${pageName}" (${linkedRoute}) \u2014 skipped`);
10156
- if (DEBUG4) console.log(chalk13.dim(` ${err instanceof Error ? err.message : "unknown error"}`));
10508
+ if (DEBUG4) console.log(chalk14.dim(` ${err instanceof Error ? err.message : "unknown error"}`));
10157
10509
  }
10158
10510
  }
10159
10511
  console.log("");
@@ -10161,7 +10513,7 @@ async function chatCommand(message, options) {
10161
10513
  } else if (missingRoutes.length > SCAFFOLD_AI_LIMIT) {
10162
10514
  spinner.stop();
10163
10515
  console.log(
10164
- chalk13.yellow(
10516
+ chalk14.yellow(
10165
10517
  `
10166
10518
  \u26A0 Found ${missingRoutes.length} linked pages \u2014 creating placeholder pages (too many for AI generation).`
10167
10519
  )
@@ -10190,7 +10542,7 @@ async function chatCommand(message, options) {
10190
10542
  scaffoldedPages.push({ route: linkedRoute, name: `${pageName} (placeholder)` });
10191
10543
  }
10192
10544
  console.log(
10193
- chalk13.cyan(` Created ${missingRoutes.length} placeholder pages. Use \`coherent chat\` to fill them.
10545
+ chalk14.cyan(` Created ${missingRoutes.length} placeholder pages. Use \`coherent chat\` to fill them.
10194
10546
  `)
10195
10547
  );
10196
10548
  spinner.start("Finalizing...");
@@ -10218,9 +10570,9 @@ async function chatCommand(message, options) {
10218
10570
  }
10219
10571
  }
10220
10572
  if (linkIssues.length > 0) {
10221
- console.log(chalk13.yellow("\n\u{1F517} Broken internal links:"));
10573
+ console.log(chalk14.yellow("\n\u{1F517} Broken internal links:"));
10222
10574
  for (const { page, message: message2 } of linkIssues) {
10223
- console.log(chalk13.dim(` ${page}: ${message2}`));
10575
+ console.log(chalk14.dim(` ${page}: ${message2}`));
10224
10576
  }
10225
10577
  }
10226
10578
  }
@@ -10233,7 +10585,7 @@ async function chatCommand(message, options) {
10233
10585
  if (latestConfig.theme.defaultMode !== targetMode) {
10234
10586
  latestConfig.theme.defaultMode = targetMode;
10235
10587
  dsm.updateConfig(latestConfig);
10236
- if (DEBUG4) console.log(chalk13.dim(` [theme] Set defaultMode to "${targetMode}"`));
10588
+ if (DEBUG4) console.log(chalk14.dim(` [theme] Set defaultMode to "${targetMode}"`));
10237
10589
  }
10238
10590
  const layoutPath = resolve9(projectRoot, "app", "layout.tsx");
10239
10591
  try {
@@ -10241,11 +10593,11 @@ async function chatCommand(message, options) {
10241
10593
  if (targetMode === "dark" && !layoutCode.includes('className="dark"')) {
10242
10594
  layoutCode = layoutCode.replace(/<html\s+lang="en"/, '<html lang="en" className="dark"');
10243
10595
  await writeFile(layoutPath, layoutCode);
10244
- console.log(chalk13.dim(` \u{1F319} Applied dark theme to layout`));
10596
+ console.log(chalk14.dim(` \u{1F319} Applied dark theme to layout`));
10245
10597
  } else if (targetMode === "light" && layoutCode.includes('className="dark"')) {
10246
10598
  layoutCode = layoutCode.replace(' className="dark"', "");
10247
10599
  await writeFile(layoutPath, layoutCode);
10248
- console.log(chalk13.dim(` \u2600\uFE0F Applied light theme to layout`));
10600
+ console.log(chalk14.dim(` \u2600\uFE0F Applied light theme to layout`));
10249
10601
  }
10250
10602
  } catch {
10251
10603
  }
@@ -10277,7 +10629,7 @@ async function chatCommand(message, options) {
10277
10629
  }
10278
10630
  const finalDeps = await scanAndInstallSharedDeps(projectRoot);
10279
10631
  if (finalDeps.length > 0) {
10280
- console.log(chalk13.dim(` Auto-installed shared deps: ${finalDeps.join(", ")}`));
10632
+ console.log(chalk14.dim(` Auto-installed shared deps: ${finalDeps.join(", ")}`));
10281
10633
  }
10282
10634
  try {
10283
10635
  fixGlobalsCss(projectRoot, updatedConfig);
@@ -10301,7 +10653,7 @@ async function chatCommand(message, options) {
10301
10653
  }
10302
10654
  await saveHashes(projectRoot, updatedHashes);
10303
10655
  } catch {
10304
- if (DEBUG4) console.log(chalk13.dim("[hashes] Could not save file hashes"));
10656
+ if (DEBUG4) console.log(chalk14.dim("[hashes] Could not save file hashes"));
10305
10657
  }
10306
10658
  const successfulPairs = normalizedRequests.map((request, index) => ({ request, result: results[index] })).filter(({ result }) => result.success);
10307
10659
  if (successfulPairs.length > 0) {
@@ -10318,9 +10670,9 @@ async function chatCommand(message, options) {
10318
10670
  const preflightNames = preflightInstalledIds.map((id) => updatedConfig.components.find((c) => c.id === id)?.name).filter(Boolean);
10319
10671
  showPreview(normalizedRequests, results, updatedConfig, preflightNames);
10320
10672
  if (scaffoldedPages.length > 0) {
10321
- console.log(chalk13.cyan("\u{1F517} Auto-scaffolded linked pages:"));
10673
+ console.log(chalk14.cyan("\u{1F517} Auto-scaffolded linked pages:"));
10322
10674
  scaffoldedPages.forEach(({ route, name }) => {
10323
- console.log(chalk13.white(` \u2728 ${name} \u2192 ${route}`));
10675
+ console.log(chalk14.white(` \u2728 ${name} \u2192 ${route}`));
10324
10676
  });
10325
10677
  console.log("");
10326
10678
  }
@@ -10342,58 +10694,58 @@ ${uxRecommendations}
10342
10694
  );
10343
10695
  }
10344
10696
  await appendFile(recPath, section);
10345
- console.log(chalk13.cyan("\n\u{1F4CB} UX Recommendations:"));
10697
+ console.log(chalk14.cyan("\n\u{1F4CB} UX Recommendations:"));
10346
10698
  for (const line of uxRecommendations.split("\n").filter(Boolean)) {
10347
- console.log(chalk13.dim(` ${line}`));
10699
+ console.log(chalk14.dim(` ${line}`));
10348
10700
  }
10349
- console.log(chalk13.dim(" \u2192 Saved to /design-system/docs/recommendations"));
10701
+ console.log(chalk14.dim(" \u2192 Saved to /design-system/docs/recommendations"));
10350
10702
  } catch (e) {
10351
10703
  console.log(
10352
- chalk13.yellow("\n\u26A0\uFE0F Could not write recommendations.md: " + (e instanceof Error ? e.message : String(e)))
10704
+ chalk14.yellow("\n\u26A0\uFE0F Could not write recommendations.md: " + (e instanceof Error ? e.message : String(e)))
10353
10705
  );
10354
- console.log(chalk13.dim("Recommendations:\n") + uxRecommendations);
10706
+ console.log(chalk14.dim("Recommendations:\n") + uxRecommendations);
10355
10707
  }
10356
10708
  }
10357
10709
  } catch (error) {
10358
10710
  spinner.fail("Chat command failed");
10359
- console.error(chalk13.red("\n\u2716 Chat command failed"));
10711
+ console.error(chalk14.red("\n\u2716 Chat command failed"));
10360
10712
  const zodError = error;
10361
10713
  const issues = zodError.issues || error.errors;
10362
10714
  if (issues && Array.isArray(issues)) {
10363
- console.log(chalk13.yellow("\n\u26A0\uFE0F AI generated incomplete data. Missing or invalid fields:"));
10715
+ console.log(chalk14.yellow("\n\u26A0\uFE0F AI generated incomplete data. Missing or invalid fields:"));
10364
10716
  issues.forEach((err) => {
10365
- console.log(chalk13.gray(` \u2022 ${err.path.join(".")}: ${err.message}`));
10717
+ console.log(chalk14.gray(` \u2022 ${err.path.join(".")}: ${err.message}`));
10366
10718
  });
10367
- console.log(chalk13.cyan("\n\u{1F4A1} Try being more specific, e.g.:"));
10368
- console.log(chalk13.white(' coherent chat "add a dashboard page with hero section using Button component"'));
10369
- console.log(chalk13.white(' coherent chat "add pricing page"'));
10719
+ console.log(chalk14.cyan("\n\u{1F4A1} Try being more specific, e.g.:"));
10720
+ console.log(chalk14.white(' coherent chat "add a dashboard page with hero section using Button component"'));
10721
+ console.log(chalk14.white(' coherent chat "add pricing page"'));
10370
10722
  } else if (error instanceof Error) {
10371
- console.error(chalk13.red(error.message));
10723
+ console.error(chalk14.red(error.message));
10372
10724
  if (error.message.includes("Unterminated string") || error.message.includes("Unexpected end of JSON") || error.message.includes("Failed to parse modification") && error.message.includes("JSON")) {
10373
10725
  console.log(
10374
- chalk13.yellow("\n\u{1F4A1} The AI response was too large or contained invalid JSON. Try splitting your request:")
10726
+ chalk14.yellow("\n\u{1F4A1} The AI response was too large or contained invalid JSON. Try splitting your request:")
10375
10727
  );
10376
- console.log(chalk13.white(' coherent chat "add dashboard page with stats and recent activity"'));
10377
- console.log(chalk13.white(' coherent chat "add account page"'));
10378
- console.log(chalk13.white(' coherent chat "add settings page"'));
10728
+ console.log(chalk14.white(' coherent chat "add dashboard page with stats and recent activity"'));
10729
+ console.log(chalk14.white(' coherent chat "add account page"'));
10730
+ console.log(chalk14.white(' coherent chat "add settings page"'));
10379
10731
  } else if (error.message.includes("API key not found") || error.message.includes("ANTHROPIC_API_KEY") || error.message.includes("OPENAI_API_KEY")) {
10380
10732
  const isOpenAI = error.message.includes("OpenAI") || typeof provider !== "undefined" && provider === "openai";
10381
10733
  const providerName = isOpenAI ? "OpenAI" : "Anthropic Claude";
10382
10734
  const envVar = isOpenAI ? "OPENAI_API_KEY" : "ANTHROPIC_API_KEY";
10383
10735
  const url = isOpenAI ? "https://platform.openai.com" : "https://console.anthropic.com";
10384
- console.log(chalk13.yellow("\n\u{1F4A1} Setup Instructions:"));
10385
- console.log(chalk13.dim(` 1. Get your ${providerName} API key from: ${url}`));
10386
- console.log(chalk13.dim(" 2. Create a .env file in the current directory:"));
10387
- console.log(chalk13.cyan(` echo "${envVar}=your_key_here" > .env`));
10388
- console.log(chalk13.dim(" 3. Or export it in your shell:"));
10389
- console.log(chalk13.cyan(` export ${envVar}=your_key_here`));
10736
+ console.log(chalk14.yellow("\n\u{1F4A1} Setup Instructions:"));
10737
+ console.log(chalk14.dim(` 1. Get your ${providerName} API key from: ${url}`));
10738
+ console.log(chalk14.dim(" 2. Create a .env file in the current directory:"));
10739
+ console.log(chalk14.cyan(` echo "${envVar}=your_key_here" > .env`));
10740
+ console.log(chalk14.dim(" 3. Or export it in your shell:"));
10741
+ console.log(chalk14.cyan(` export ${envVar}=your_key_here`));
10390
10742
  if (isOpenAI) {
10391
- console.log(chalk13.dim('\n Also ensure "openai" package is installed:'));
10392
- console.log(chalk13.cyan(" npm install openai"));
10743
+ console.log(chalk14.dim('\n Also ensure "openai" package is installed:'));
10744
+ console.log(chalk14.cyan(" npm install openai"));
10393
10745
  }
10394
10746
  }
10395
10747
  } else {
10396
- console.error(chalk13.red("Unknown error occurred"));
10748
+ console.error(chalk14.red("Unknown error occurred"));
10397
10749
  }
10398
10750
  console.log("");
10399
10751
  if (options._throwOnError) {
@@ -10406,7 +10758,7 @@ ${uxRecommendations}
10406
10758
  }
10407
10759
 
10408
10760
  // src/commands/preview.ts
10409
- import chalk14 from "chalk";
10761
+ import chalk15 from "chalk";
10410
10762
  import ora3 from "ora";
10411
10763
  import { spawn } from "child_process";
10412
10764
  import { existsSync as existsSync19, rmSync as rmSync3, readFileSync as readFileSync14, writeFileSync as writeFileSync10, readdirSync as readdirSync5 } from "fs";
@@ -10746,13 +11098,13 @@ async function handleFileChange(projectRoot, filePath) {
10746
11098
  return;
10747
11099
  }
10748
11100
  const config2 = getWatcherConfig(projectRoot);
10749
- const chalk33 = (await import("chalk")).default;
11101
+ const chalk34 = (await import("chalk")).default;
10750
11102
  if (config2.autoInstall) {
10751
11103
  const missing = findMissingPackagesInCode(content, projectRoot);
10752
11104
  if (missing.length > 0) {
10753
11105
  const ok = await installPackages(projectRoot, missing);
10754
11106
  if (ok) {
10755
- console.log(chalk33.cyan(`
11107
+ console.log(chalk34.cyan(`
10756
11108
  \u{1F527} Auto-installed: ${missing.join(", ")} (needed by ${relativePath})`));
10757
11109
  }
10758
11110
  }
@@ -10761,12 +11113,12 @@ async function handleFileChange(projectRoot, filePath) {
10761
11113
  const fixed = sanitizeMetadataStrings(ensureUseClientIfNeeded(content));
10762
11114
  if (fixed !== content) {
10763
11115
  writeFileSync9(filePath, fixed, "utf-8");
10764
- console.log(chalk33.cyan(` \u{1F527} Auto-fixed syntax in ${relativePath}`));
11116
+ console.log(chalk34.cyan(` \u{1F527} Auto-fixed syntax in ${relativePath}`));
10765
11117
  }
10766
11118
  }
10767
11119
  if (config2.warnNativeElements && hasNativeElements(content)) {
10768
- console.log(chalk33.yellow(` \u26A0 ${relativePath}: uses native HTML elements (<button>, <select>, etc.)`));
10769
- console.log(chalk33.dim(" Use components from @/components/ui/ instead"));
11120
+ console.log(chalk34.yellow(` \u26A0 ${relativePath}: uses native HTML elements (<button>, <select>, etc.)`));
11121
+ console.log(chalk34.dim(" Use components from @/components/ui/ instead"));
10770
11122
  }
10771
11123
  if (config2.warnSharedReuse) {
10772
11124
  let manifest;
@@ -10779,8 +11131,8 @@ async function handleFileChange(projectRoot, filePath) {
10779
11131
  const dupes = findInlineDuplicatesOfShared(content, manifest);
10780
11132
  for (const d of dupes) {
10781
11133
  const importPath = d.file.replace(/\.tsx$/, "").replace(/^components\/shared\//, "");
10782
- console.log(chalk33.yellow(` \u26A0 ${relativePath}: has inline code similar to ${d.cid} (${d.name})`));
10783
- console.log(chalk33.dim(` Consider: import { ${d.name} } from "@/components/shared/${importPath}"`));
11134
+ console.log(chalk34.yellow(` \u26A0 ${relativePath}: has inline code similar to ${d.cid} (${d.name})`));
11135
+ console.log(chalk34.dim(` Consider: import { ${d.name} } from "@/components/shared/${importPath}"`));
10784
11136
  }
10785
11137
  }
10786
11138
  }
@@ -10789,7 +11141,7 @@ async function handleFileDelete(projectRoot, filePath) {
10789
11141
  const relativePath = relative4(projectRoot, filePath).replace(/\\/g, "/");
10790
11142
  if (!relativePath.startsWith("components/") || relativePath.startsWith("components/ui/")) return;
10791
11143
  try {
10792
- const chalk33 = (await import("chalk")).default;
11144
+ const chalk34 = (await import("chalk")).default;
10793
11145
  const manifest = await loadManifest9(projectRoot);
10794
11146
  const orphaned = manifest.shared.find((s) => s.file === relativePath);
10795
11147
  if (orphaned) {
@@ -10798,7 +11150,7 @@ async function handleFileDelete(projectRoot, filePath) {
10798
11150
  shared: manifest.shared.filter((s) => s.id !== orphaned.id)
10799
11151
  };
10800
11152
  await saveManifest3(projectRoot, cleaned);
10801
- console.log(chalk33.cyan(`
11153
+ console.log(chalk34.cyan(`
10802
11154
  \u{1F5D1} Auto-removed ${orphaned.id} (${orphaned.name}) \u2014 file deleted`));
10803
11155
  await writeCursorRules(projectRoot);
10804
11156
  }
@@ -10810,7 +11162,7 @@ async function detectNewComponent(projectRoot, filePath) {
10810
11162
  if (!relativePath.startsWith("components/") || relativePath.startsWith("components/ui/")) return;
10811
11163
  if (!relativePath.endsWith(".tsx") && !relativePath.endsWith(".jsx")) return;
10812
11164
  try {
10813
- const chalk33 = (await import("chalk")).default;
11165
+ const chalk34 = (await import("chalk")).default;
10814
11166
  const manifest = await loadManifest9(projectRoot);
10815
11167
  const alreadyRegistered = manifest.shared.some((s) => s.file === relativePath);
10816
11168
  if (alreadyRegistered) return;
@@ -10819,9 +11171,9 @@ async function detectNewComponent(projectRoot, filePath) {
10819
11171
  if (exports.length > 0) {
10820
11172
  const alreadyByName = exports.every((n) => manifest.shared.some((s) => s.name === n));
10821
11173
  if (!alreadyByName) {
10822
- console.log(chalk33.cyan(`
11174
+ console.log(chalk34.cyan(`
10823
11175
  \u2139 New component detected: ${exports[0]} in ${relativePath}`));
10824
- console.log(chalk33.dim(" Register with: coherent sync"));
11176
+ console.log(chalk34.dim(" Register with: coherent sync"));
10825
11177
  }
10826
11178
  }
10827
11179
  } catch {
@@ -10908,17 +11260,17 @@ function clearStaleCache(projectRoot) {
10908
11260
  const nextDir = join14(projectRoot, ".next");
10909
11261
  if (existsSync19(nextDir)) {
10910
11262
  rmSync3(nextDir, { recursive: true, force: true });
10911
- console.log(chalk14.dim(" \u2714 Cleared stale build cache"));
11263
+ console.log(chalk15.dim(" \u2714 Cleared stale build cache"));
10912
11264
  }
10913
11265
  }
10914
11266
  async function preflightDependencyCheck(projectRoot) {
10915
11267
  const missing = await findMissingPackages(projectRoot);
10916
11268
  if (missing.length === 0) return;
10917
- console.log(chalk14.cyan(`
11269
+ console.log(chalk15.cyan(`
10918
11270
  Auto-installing missing dependencies: ${missing.join(", ")}`));
10919
11271
  const ok = await installPackages(projectRoot, missing);
10920
- if (ok) console.log(chalk14.dim(" \u2714 Installed"));
10921
- else console.log(chalk14.yellow(` Run manually: npm install ${missing.join(" ")}`));
11272
+ if (ok) console.log(chalk15.dim(" \u2714 Installed"));
11273
+ else console.log(chalk15.yellow(` Run manually: npm install ${missing.join(" ")}`));
10922
11274
  }
10923
11275
  async function listPageFiles(appDir) {
10924
11276
  const out = [];
@@ -10942,7 +11294,7 @@ async function validateSyntax(projectRoot) {
10942
11294
  const fixed = fixUnescapedLtInJsx(sanitizeMetadataStrings(ensureUseClientIfNeeded(content)));
10943
11295
  if (fixed !== content) {
10944
11296
  writeFileSync10(file, fixed, "utf-8");
10945
- console.log(chalk14.dim(` \u2714 Auto-fixed syntax: ${file.replace(projectRoot, ".").replace(/^\.[/\\]/, "")}`));
11297
+ console.log(chalk15.dim(` \u2714 Auto-fixed syntax: ${file.replace(projectRoot, ".").replace(/^\.[/\\]/, "")}`));
10946
11298
  }
10947
11299
  }
10948
11300
  }
@@ -10984,7 +11336,7 @@ async function fixMissingComponentExports(projectRoot) {
10984
11336
  try {
10985
11337
  const result = await provider.installComponent(componentId, projectRoot);
10986
11338
  if (result.success) {
10987
- console.log(chalk14.dim(` \u2714 Installed missing ${componentId}.tsx`));
11339
+ console.log(chalk15.dim(` \u2714 Installed missing ${componentId}.tsx`));
10988
11340
  }
10989
11341
  } catch {
10990
11342
  }
@@ -10996,7 +11348,7 @@ async function fixMissingComponentExports(projectRoot) {
10996
11348
  mkdirSync10(uiDir, { recursive: true });
10997
11349
  const newContent = await generator.generate(def);
10998
11350
  writeFileSync10(componentFile, newContent, "utf-8");
10999
- console.log(chalk14.dim(` \u2714 Created missing ${componentId}.tsx`));
11351
+ console.log(chalk15.dim(` \u2714 Created missing ${componentId}.tsx`));
11000
11352
  } catch {
11001
11353
  }
11002
11354
  }
@@ -11019,7 +11371,7 @@ async function fixMissingComponentExports(projectRoot) {
11019
11371
  try {
11020
11372
  const result = await provider.installComponent(componentId, projectRoot, { force: true });
11021
11373
  if (result.success) {
11022
- console.log(chalk14.dim(` \u2714 Reinstalled ${componentId}.tsx (added missing exports: ${missing.join(", ")})`));
11374
+ console.log(chalk15.dim(` \u2714 Reinstalled ${componentId}.tsx (added missing exports: ${missing.join(", ")})`));
11023
11375
  }
11024
11376
  } catch {
11025
11377
  }
@@ -11029,7 +11381,7 @@ async function fixMissingComponentExports(projectRoot) {
11029
11381
  try {
11030
11382
  const newContent = await generator.generate(def);
11031
11383
  writeFileSync10(componentFile, newContent, "utf-8");
11032
- console.log(chalk14.dim(` \u2714 Regenerated ${componentId}.tsx (added missing exports: ${missing.join(", ")})`));
11384
+ console.log(chalk15.dim(` \u2714 Regenerated ${componentId}.tsx (added missing exports: ${missing.join(", ")})`));
11033
11385
  } catch {
11034
11386
  }
11035
11387
  }
@@ -11088,14 +11440,14 @@ async function healthCheck(port) {
11088
11440
  try {
11089
11441
  const res = await fetch(`http://localhost:${port}`);
11090
11442
  if (res.status === 200) {
11091
- console.log(chalk14.green(`
11443
+ console.log(chalk15.green(`
11092
11444
  \u2705 Preview healthy at http://localhost:${port}`));
11093
11445
  } else {
11094
- console.log(chalk14.yellow(`
11446
+ console.log(chalk15.yellow(`
11095
11447
  \u26A0 Preview returned ${res.status}. Run: coherent fix`));
11096
11448
  }
11097
11449
  } catch {
11098
- console.log(chalk14.yellow(`
11450
+ console.log(chalk15.yellow(`
11099
11451
  \u26A0 Preview not responding. Run: coherent fix`));
11100
11452
  }
11101
11453
  }
@@ -11134,29 +11486,29 @@ function launchWithMonitoring(projectRoot, restarts) {
11134
11486
  const shadcnId = extractShadcnComponentFromModuleNotFound(msg);
11135
11487
  if (shadcnId && !installingSet.has(shadcnId)) {
11136
11488
  installingSet.add(shadcnId);
11137
- console.log(chalk14.yellow(`
11489
+ console.log(chalk15.yellow(`
11138
11490
  \u26A0 Missing component detected: ${shadcnId}`));
11139
- console.log(chalk14.cyan(" Auto-installing..."));
11491
+ console.log(chalk15.cyan(" Auto-installing..."));
11140
11492
  autoInstallShadcnComponent(shadcnId, projectRoot).then((ok) => {
11141
11493
  if (ok) {
11142
- console.log(chalk14.green(` \u2714 Installed ${shadcnId}.tsx. Restarting...`));
11494
+ console.log(chalk15.green(` \u2714 Installed ${shadcnId}.tsx. Restarting...`));
11143
11495
  intentionalRestart = true;
11144
11496
  server.kill("SIGTERM");
11145
11497
  launchWithMonitoring(projectRoot, restarts + 1).then(resolvePromise).catch(rejectPromise);
11146
11498
  } else {
11147
- console.log(chalk14.red(` \u2716 Could not install ${shadcnId}. Run: npx shadcn@latest add ${shadcnId}`));
11499
+ console.log(chalk15.red(` \u2716 Could not install ${shadcnId}. Run: npx shadcn@latest add ${shadcnId}`));
11148
11500
  }
11149
11501
  });
11150
11502
  } else if (!shadcnId) {
11151
11503
  const pkg = extractPackageFromModuleNotFound(msg);
11152
11504
  if (pkg && !installingSet.has(pkg)) {
11153
11505
  installingSet.add(pkg);
11154
- console.log(chalk14.yellow(`
11506
+ console.log(chalk15.yellow(`
11155
11507
  \u26A0 Missing package detected: ${pkg}`));
11156
- console.log(chalk14.cyan(" Auto-installing..."));
11508
+ console.log(chalk15.cyan(" Auto-installing..."));
11157
11509
  installPackages(projectRoot, [pkg]).then((ok) => {
11158
11510
  if (ok) {
11159
- console.log(chalk14.green(` \u2714 Installed ${pkg}. Restarting...`));
11511
+ console.log(chalk15.green(` \u2714 Installed ${pkg}. Restarting...`));
11160
11512
  intentionalRestart = true;
11161
11513
  server.kill("SIGTERM");
11162
11514
  launchWithMonitoring(projectRoot, restarts + 1).then(resolvePromise).catch(rejectPromise);
@@ -11166,19 +11518,19 @@ function launchWithMonitoring(projectRoot, restarts) {
11166
11518
  }
11167
11519
  }
11168
11520
  if (msg.includes("Failed to compile")) {
11169
- console.log(chalk14.yellow("\n\u26A0 Compilation error detected."));
11170
- console.log(chalk14.dim(' Hint: run "coherent fix" in another terminal to auto-fix'));
11171
- console.log(chalk14.dim(' Or: coherent chat "fix the broken page"'));
11521
+ console.log(chalk15.yellow("\n\u26A0 Compilation error detected."));
11522
+ console.log(chalk15.dim(' Hint: run "coherent fix" in another terminal to auto-fix'));
11523
+ console.log(chalk15.dim(' Or: coherent chat "fix the broken page"'));
11172
11524
  }
11173
11525
  });
11174
11526
  server.on("exit", (code) => {
11175
11527
  if (intentionalRestart) return;
11176
11528
  if (code !== 0 && code !== null) {
11177
- console.log(chalk14.red(`
11529
+ console.log(chalk15.red(`
11178
11530
  \u274C Dev server exited with code ${code}`));
11179
- console.log(chalk14.dim(' Check the output above. Fix and run "coherent preview" again.\n'));
11531
+ console.log(chalk15.dim(' Check the output above. Fix and run "coherent preview" again.\n'));
11180
11532
  } else {
11181
- console.log(chalk14.dim("\n\u{1F44B} Dev server stopped"));
11533
+ console.log(chalk15.dim("\n\u{1F44B} Dev server stopped"));
11182
11534
  }
11183
11535
  process.exit(code ?? 0);
11184
11536
  });
@@ -11187,7 +11539,7 @@ function launchWithMonitoring(projectRoot, restarts) {
11187
11539
  });
11188
11540
  const shutdown = () => {
11189
11541
  closeWatcher();
11190
- console.log(chalk14.dim("\n\n\u{1F6D1} Stopping dev server..."));
11542
+ console.log(chalk15.dim("\n\n\u{1F6D1} Stopping dev server..."));
11191
11543
  server.kill("SIGTERM");
11192
11544
  };
11193
11545
  process.on("SIGINT", shutdown);
@@ -11199,9 +11551,9 @@ async function openBrowser(url) {
11199
11551
  const open = await import("open");
11200
11552
  await open.default(url);
11201
11553
  } catch (error) {
11202
- console.log(chalk14.yellow(`
11554
+ console.log(chalk15.yellow(`
11203
11555
  \u26A0\uFE0F Could not open browser automatically`));
11204
- console.log(chalk14.dim(` Please open ${url} manually`));
11556
+ console.log(chalk15.dim(` Please open ${url} manually`));
11205
11557
  }
11206
11558
  }
11207
11559
  function startDevServer(projectRoot) {
@@ -11232,8 +11584,8 @@ async function previewCommand() {
11232
11584
  try {
11233
11585
  if (!checkProjectInitialized(projectRoot)) {
11234
11586
  spinner.fail("Project not initialized");
11235
- console.log(chalk14.red("\n\u274C Project not found"));
11236
- console.log(chalk14.dim('Run "coherent init" first to create a project.'));
11587
+ console.log(chalk15.red("\n\u274C Project not found"));
11588
+ console.log(chalk15.dim('Run "coherent init" first to create a project.'));
11237
11589
  process.exit(1);
11238
11590
  }
11239
11591
  spinner.text = "Checking dependencies...";
@@ -11241,16 +11593,16 @@ async function previewCommand() {
11241
11593
  spinner.warn("Dependencies not installed");
11242
11594
  const pm = getPackageManager(projectRoot);
11243
11595
  const installCommand = pm === "pnpm" ? "pnpm install" : "npm install";
11244
- console.log(chalk14.yellow("\n\u26A0\uFE0F Dependencies not installed"));
11245
- console.log(chalk14.cyan(`
11596
+ console.log(chalk15.yellow("\n\u26A0\uFE0F Dependencies not installed"));
11597
+ console.log(chalk15.cyan(`
11246
11598
  Running ${installCommand}...
11247
11599
  `));
11248
11600
  const ok = await runInstall(projectRoot);
11249
11601
  if (!ok) {
11250
- console.error(chalk14.red('\n\u274C Install failed. Fix errors above and run "coherent preview" again.\n'));
11602
+ console.error(chalk15.red('\n\u274C Install failed. Fix errors above and run "coherent preview" again.\n'));
11251
11603
  process.exit(1);
11252
11604
  }
11253
- console.log(chalk14.green("\n\u2705 Dependencies installed\n"));
11605
+ console.log(chalk15.green("\n\u2705 Dependencies installed\n"));
11254
11606
  } else {
11255
11607
  spinner.succeed("Project ready");
11256
11608
  }
@@ -11273,27 +11625,27 @@ async function previewCommand() {
11273
11625
  await fixMissingComponentExports(projectRoot);
11274
11626
  await backfillPageAnalysis(projectRoot);
11275
11627
  spinner.succeed("Project ready");
11276
- console.log(chalk14.dim(" \u{1F4A1} Edited files manually? Run `coherent sync` to update the Design System.\n"));
11277
- console.log(chalk14.blue("\n\u{1F680} Starting Next.js dev server...\n"));
11628
+ console.log(chalk15.dim(" \u{1F4A1} Edited files manually? Run `coherent sync` to update the Design System.\n"));
11629
+ console.log(chalk15.blue("\n\u{1F680} Starting Next.js dev server...\n"));
11278
11630
  await launchWithMonitoring(projectRoot, 0);
11279
11631
  } catch (error) {
11280
11632
  spinner.fail("Failed to start dev server");
11281
11633
  if (error instanceof Error) {
11282
- console.error(chalk14.red(`
11634
+ console.error(chalk15.red(`
11283
11635
  \u274C ${error.message}`));
11284
11636
  if (error.message.includes("package.json")) {
11285
- console.log(chalk14.yellow("\n\u{1F4A1} Tip: Make sure you're in a Coherent project directory."));
11286
- console.log(chalk14.dim(' Run "coherent init" to create a new project.'));
11637
+ console.log(chalk15.yellow("\n\u{1F4A1} Tip: Make sure you're in a Coherent project directory."));
11638
+ console.log(chalk15.dim(' Run "coherent init" to create a new project.'));
11287
11639
  }
11288
11640
  } else {
11289
- console.error(chalk14.red("Unknown error occurred"));
11641
+ console.error(chalk15.red("Unknown error occurred"));
11290
11642
  }
11291
11643
  process.exit(1);
11292
11644
  }
11293
11645
  }
11294
11646
 
11295
11647
  // src/commands/export.ts
11296
- import chalk15 from "chalk";
11648
+ import chalk16 from "chalk";
11297
11649
  import ora4 from "ora";
11298
11650
  import { spawn as spawn2 } from "child_process";
11299
11651
  import { existsSync as existsSync20, rmSync as rmSync4, readdirSync as readdirSync6 } from "fs";
@@ -11572,7 +11924,7 @@ async function exportCommand(options = {}) {
11572
11924
  const missingDeps = await findMissingDepsInExport(outputDir);
11573
11925
  if (missingDeps.length > 0) {
11574
11926
  console.log(
11575
- chalk15.yellow(
11927
+ chalk16.yellow(
11576
11928
  "\n\u26A0\uFE0F Warning: exported code imports packages not in package.json: " + missingDeps.join(", ") + "\n Add them to dependencies and run npm install in the export dir.\n"
11577
11929
  )
11578
11930
  );
@@ -11588,7 +11940,7 @@ async function exportCommand(options = {}) {
11588
11940
  spinner.succeed("Dependencies installed");
11589
11941
  await ensureReadmeDeploySection(outputDir);
11590
11942
  await patchNextConfigForExport(outputDir);
11591
- console.log(chalk15.dim("\n Tip: run `coherent check` before export to catch quality issues.\n"));
11943
+ console.log(chalk16.dim("\n Tip: run `coherent check` before export to catch quality issues.\n"));
11592
11944
  let buildOk = false;
11593
11945
  if (doBuild) {
11594
11946
  spinner.start("Running next build...");
@@ -11598,7 +11950,7 @@ async function exportCommand(options = {}) {
11598
11950
  spinner.succeed("Build: success");
11599
11951
  } catch (e) {
11600
11952
  spinner.fail("Build failed");
11601
- if (e instanceof Error) console.error(chalk15.red(e.message));
11953
+ if (e instanceof Error) console.error(chalk16.red(e.message));
11602
11954
  }
11603
11955
  } else {
11604
11956
  buildOk = true;
@@ -11606,23 +11958,23 @@ async function exportCommand(options = {}) {
11606
11958
  const pageCount = await countPages(outputDir);
11607
11959
  const componentCount = countComponents(outputDir);
11608
11960
  spinner.stop();
11609
- console.log(chalk15.green("\n\u2705 Exported to " + outputDir + "\n"));
11610
- console.log(chalk15.blue(" Pages: " + pageCount));
11611
- console.log(chalk15.blue(" Components: " + componentCount + " (base + shared)"));
11612
- console.log(chalk15.blue(" Build: " + (doBuild ? buildOk ? "success" : "failed" : "skipped (--no-build)")));
11961
+ console.log(chalk16.green("\n\u2705 Exported to " + outputDir + "\n"));
11962
+ console.log(chalk16.blue(" Pages: " + pageCount));
11963
+ console.log(chalk16.blue(" Components: " + componentCount + " (base + shared)"));
11964
+ console.log(chalk16.blue(" Build: " + (doBuild ? buildOk ? "success" : "failed" : "skipped (--no-build)")));
11613
11965
  console.log("");
11614
- console.log(chalk15.dim(" Deploy: npx vercel " + outputDir));
11615
- console.log(chalk15.dim(" or: npx netlify deploy --dir " + outputDir + "/.next"));
11966
+ console.log(chalk16.dim(" Deploy: npx vercel " + outputDir));
11967
+ console.log(chalk16.dim(" or: npx netlify deploy --dir " + outputDir + "/.next"));
11616
11968
  console.log("");
11617
11969
  } catch (error) {
11618
11970
  spinner.fail("Export failed");
11619
- if (error instanceof Error) console.error(chalk15.red("\n\u274C " + error.message));
11971
+ if (error instanceof Error) console.error(chalk16.red("\n\u274C " + error.message));
11620
11972
  process.exit(1);
11621
11973
  }
11622
11974
  }
11623
11975
 
11624
11976
  // src/commands/status.ts
11625
- import chalk16 from "chalk";
11977
+ import chalk17 from "chalk";
11626
11978
  import { basename } from "path";
11627
11979
  import { DesignSystemManager as DesignSystemManager9 } from "@getcoherent/core";
11628
11980
  function countTokens(tokens) {
@@ -11646,58 +11998,58 @@ async function statusCommand() {
11646
11998
  try {
11647
11999
  const project = findConfig();
11648
12000
  if (!project) {
11649
- console.log(chalk16.yellow("\u26A0\uFE0F Not in a Coherent project\n"));
12001
+ console.log(chalk17.yellow("\u26A0\uFE0F Not in a Coherent project\n"));
11650
12002
  console.log("Initialize a project:");
11651
- console.log(chalk16.white(" $ coherent init\n"));
12003
+ console.log(chalk17.white(" $ coherent init\n"));
11652
12004
  return;
11653
12005
  }
11654
- console.log(chalk16.cyan("\n\u2728 Current Project\n"));
11655
- console.log(chalk16.gray("\u{1F4C1} Location: ") + chalk16.white(project.root));
11656
- console.log(chalk16.gray("\u{1F4C4} Config: ") + chalk16.white(basename(project.configPath)));
12006
+ console.log(chalk17.cyan("\n\u2728 Current Project\n"));
12007
+ console.log(chalk17.gray("\u{1F4C1} Location: ") + chalk17.white(project.root));
12008
+ console.log(chalk17.gray("\u{1F4C4} Config: ") + chalk17.white(basename(project.configPath)));
11657
12009
  console.log("");
11658
12010
  try {
11659
12011
  const manager = new DesignSystemManager9(project.configPath);
11660
12012
  await manager.load();
11661
12013
  const config2 = manager.getConfig();
11662
- console.log(chalk16.cyan("\u{1F4CA} Statistics:\n"));
12014
+ console.log(chalk17.cyan("\u{1F4CA} Statistics:\n"));
11663
12015
  const pageCount = Array.isArray(config2.pages) ? config2.pages.length : Object.keys(config2.pages || {}).length;
11664
- console.log(chalk16.gray(" Pages: ") + chalk16.white(String(pageCount)));
12016
+ console.log(chalk17.gray(" Pages: ") + chalk17.white(String(pageCount)));
11665
12017
  const componentCount = Array.isArray(config2.components) ? config2.components.length : Object.keys(config2.components || {}).length;
11666
- console.log(chalk16.gray(" Components: ") + chalk16.white(String(componentCount)));
12018
+ console.log(chalk17.gray(" Components: ") + chalk17.white(String(componentCount)));
11667
12019
  const tokenCount = countTokens(config2.tokens);
11668
- console.log(chalk16.gray(" Design tokens: ") + chalk16.white(String(tokenCount)));
12020
+ console.log(chalk17.gray(" Design tokens: ") + chalk17.white(String(tokenCount)));
11669
12021
  console.log("");
11670
12022
  const recent = readRecentChanges(project.root);
11671
12023
  if (recent.length > 0) {
11672
- console.log(chalk16.cyan("\u{1F4DD} Recent changes:\n"));
12024
+ console.log(chalk17.cyan("\u{1F4DD} Recent changes:\n"));
11673
12025
  recent.slice(0, 5).forEach((change) => {
11674
12026
  const ago = formatTimeAgo(change.timestamp);
11675
- console.log(chalk16.gray(" \u2022 ") + chalk16.white(change.description) + chalk16.gray(` (${ago})`));
12027
+ console.log(chalk17.gray(" \u2022 ") + chalk17.white(change.description) + chalk17.gray(` (${ago})`));
11676
12028
  });
11677
12029
  console.log("");
11678
12030
  }
11679
- console.log(chalk16.cyan("\u{1F680} Quick actions:\n"));
11680
- console.log(chalk16.white(' $ coherent chat "add new page"'));
11681
- console.log(chalk16.white(" $ coherent preview"));
11682
- console.log(chalk16.white(" $ coherent export"));
12031
+ console.log(chalk17.cyan("\u{1F680} Quick actions:\n"));
12032
+ console.log(chalk17.white(' $ coherent chat "add new page"'));
12033
+ console.log(chalk17.white(" $ coherent preview"));
12034
+ console.log(chalk17.white(" $ coherent export"));
11683
12035
  console.log("");
11684
12036
  } catch (error) {
11685
- console.error(chalk16.red("Error loading config:"));
12037
+ console.error(chalk17.red("Error loading config:"));
11686
12038
  if (error instanceof Error) {
11687
- console.error(chalk16.red(` ${error.message}`));
12039
+ console.error(chalk17.red(` ${error.message}`));
11688
12040
  } else {
11689
- console.error(chalk16.red(" Unknown error"));
12041
+ console.error(chalk17.red(" Unknown error"));
11690
12042
  }
11691
12043
  console.log("");
11692
12044
  }
11693
12045
  } catch (error) {
11694
- console.error(chalk16.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
12046
+ console.error(chalk17.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
11695
12047
  process.exit(1);
11696
12048
  }
11697
12049
  }
11698
12050
 
11699
12051
  // src/commands/regenerate-docs.ts
11700
- import chalk17 from "chalk";
12052
+ import chalk18 from "chalk";
11701
12053
  import ora5 from "ora";
11702
12054
  import { DesignSystemManager as DesignSystemManager10 } from "@getcoherent/core";
11703
12055
  import { ProjectScaffolder as ProjectScaffolder2 } from "@getcoherent/core";
@@ -11705,9 +12057,9 @@ async function regenerateDocsCommand() {
11705
12057
  try {
11706
12058
  const project = findConfig();
11707
12059
  if (!project) {
11708
- console.log(chalk17.yellow("\u26A0\uFE0F Not in a Coherent project\n"));
12060
+ console.log(chalk18.yellow("\u26A0\uFE0F Not in a Coherent project\n"));
11709
12061
  console.log("Run this command from a project root that has design-system.config.ts");
11710
- console.log(chalk17.white(" $ coherent init # in an empty folder first\n"));
12062
+ console.log(chalk18.white(" $ coherent init # in an empty folder first\n"));
11711
12063
  process.exit(1);
11712
12064
  }
11713
12065
  const spinner = ora5("Regenerating documentation pages...").start();
@@ -11719,23 +12071,23 @@ async function regenerateDocsCommand() {
11719
12071
  await scaffolder.generateDocsPages();
11720
12072
  spinner.succeed("Documentation pages updated");
11721
12073
  console.log(
11722
- chalk17.gray(
12074
+ chalk18.gray(
11723
12075
  "\nUpdated: app/design-system/docs/ (layout, page, components, tokens, for-designers, recommendations)\n"
11724
12076
  )
11725
12077
  );
11726
12078
  } catch (err) {
11727
12079
  spinner.fail("Failed to regenerate docs");
11728
- console.error(chalk17.red(err instanceof Error ? err.message : String(err)));
12080
+ console.error(chalk18.red(err instanceof Error ? err.message : String(err)));
11729
12081
  process.exit(1);
11730
12082
  }
11731
12083
  } catch (error) {
11732
- console.error(chalk17.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
12084
+ console.error(chalk18.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
11733
12085
  process.exit(1);
11734
12086
  }
11735
12087
  }
11736
12088
 
11737
12089
  // src/commands/fix.ts
11738
- import chalk18 from "chalk";
12090
+ import chalk19 from "chalk";
11739
12091
  import { readdirSync as readdirSync7, readFileSync as readFileSync15, existsSync as existsSync21, writeFileSync as writeFileSync11, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
11740
12092
  import { resolve as resolve12, join as join16 } from "path";
11741
12093
  import {
@@ -11787,31 +12139,31 @@ async function fixCommand(opts = {}) {
11787
12139
  const fixes = [];
11788
12140
  const remaining = [];
11789
12141
  if (dryRun) {
11790
- console.log(chalk18.cyan("\ncoherent fix --dry-run\n"));
12142
+ console.log(chalk19.cyan("\ncoherent fix --dry-run\n"));
11791
12143
  } else {
11792
- console.log(chalk18.cyan("\ncoherent fix\n"));
12144
+ console.log(chalk19.cyan("\ncoherent fix\n"));
11793
12145
  }
11794
12146
  if (!skipCache) {
11795
12147
  const nextDir = join16(projectRoot, ".next");
11796
12148
  if (existsSync21(nextDir)) {
11797
12149
  if (!dryRun) rmSync5(nextDir, { recursive: true, force: true });
11798
12150
  fixes.push("Cleared build cache");
11799
- console.log(chalk18.green(" \u2714 Cleared build cache"));
12151
+ console.log(chalk19.green(" \u2714 Cleared build cache"));
11800
12152
  }
11801
12153
  }
11802
12154
  const missingPkgs = await findMissingPackages(projectRoot);
11803
12155
  if (missingPkgs.length > 0) {
11804
12156
  if (dryRun) {
11805
12157
  fixes.push(`Would install packages: ${missingPkgs.join(", ")}`);
11806
- console.log(chalk18.green(` \u2714 Would install packages: ${missingPkgs.join(", ")}`));
12158
+ console.log(chalk19.green(` \u2714 Would install packages: ${missingPkgs.join(", ")}`));
11807
12159
  } else {
11808
12160
  const ok = await installPackages(projectRoot, missingPkgs);
11809
12161
  if (ok) {
11810
12162
  fixes.push(`Installed missing packages: ${missingPkgs.join(", ")}`);
11811
- console.log(chalk18.green(` \u2714 Installed missing packages: ${missingPkgs.join(", ")}`));
12163
+ console.log(chalk19.green(` \u2714 Installed missing packages: ${missingPkgs.join(", ")}`));
11812
12164
  } else {
11813
12165
  remaining.push(`Failed to install: ${missingPkgs.join(", ")}. Run: npm install ${missingPkgs.join(" ")}`);
11814
- console.log(chalk18.yellow(` \u26A0 Could not install: ${missingPkgs.join(", ")}`));
12166
+ console.log(chalk19.yellow(` \u26A0 Could not install: ${missingPkgs.join(", ")}`));
11815
12167
  }
11816
12168
  }
11817
12169
  }
@@ -11848,7 +12200,7 @@ async function fixCommand(opts = {}) {
11848
12200
  if (toInstall.length > 0) {
11849
12201
  if (dryRun) {
11850
12202
  fixes.push(`Would install components: ${toInstall.join(", ")}`);
11851
- console.log(chalk18.green(` \u2714 Would install components: ${toInstall.join(", ")}`));
12203
+ console.log(chalk19.green(` \u2714 Would install components: ${toInstall.join(", ")}`));
11852
12204
  } else {
11853
12205
  let installed = 0;
11854
12206
  for (const componentId of toInstall) {
@@ -11877,14 +12229,14 @@ async function fixCommand(opts = {}) {
11877
12229
  installed++;
11878
12230
  } catch (err) {
11879
12231
  console.log(
11880
- chalk18.yellow(` \u26A0 Failed to install ${componentId}: ${err instanceof Error ? err.message : "unknown"}`)
12232
+ chalk19.yellow(` \u26A0 Failed to install ${componentId}: ${err instanceof Error ? err.message : "unknown"}`)
11881
12233
  );
11882
12234
  }
11883
12235
  }
11884
12236
  if (installed > 0) {
11885
12237
  await dsm.save();
11886
12238
  fixes.push(`Installed missing components: ${toInstall.join(", ")}`);
11887
- console.log(chalk18.green(` \u2714 Installed missing components: ${toInstall.join(", ")}`));
12239
+ console.log(chalk19.green(` \u2714 Installed missing components: ${toInstall.join(", ")}`));
11888
12240
  }
11889
12241
  }
11890
12242
  }
@@ -11904,7 +12256,7 @@ async function fixCommand(opts = {}) {
11904
12256
  if (syntaxFixed > 0) {
11905
12257
  const verb = dryRun ? "Would fix" : "Fixed";
11906
12258
  fixes.push(`${verb} syntax in ${syntaxFixed} file(s)`);
11907
- console.log(chalk18.green(` \u2714 ${verb} syntax: ${syntaxFixed} file(s) (use client, metadata, quotes)`));
12259
+ console.log(chalk19.green(` \u2714 ${verb} syntax: ${syntaxFixed} file(s) (use client, metadata, quotes)`));
11908
12260
  }
11909
12261
  if (!skipQuality) {
11910
12262
  let qualityFixCount = 0;
@@ -11922,7 +12274,7 @@ async function fixCommand(opts = {}) {
11922
12274
  const uniqueFixes = [...new Set(qualityFixDetails)];
11923
12275
  const verb = dryRun ? "Would fix" : "Fixed";
11924
12276
  fixes.push(`${verb} quality in ${qualityFixCount} file(s)`);
11925
- console.log(chalk18.green(` \u2714 ${verb} ${uniqueFixes.length} quality issue type(s): ${uniqueFixes.join(", ")}`));
12277
+ console.log(chalk19.green(` \u2714 ${verb} ${uniqueFixes.length} quality issue type(s): ${uniqueFixes.join(", ")}`));
11926
12278
  }
11927
12279
  }
11928
12280
  let totalErrors = 0;
@@ -11967,13 +12319,13 @@ async function fixCommand(opts = {}) {
11967
12319
  if (dryRun) {
11968
12320
  fixes.push(`Would update ${o.id} path to ${newPath}`);
11969
12321
  } else {
11970
- console.log(chalk18.green(` \u2714 Updated ${o.id} (${o.name}) path \u2192 ${newPath}`));
12322
+ console.log(chalk19.green(` \u2714 Updated ${o.id} (${o.name}) path \u2192 ${newPath}`));
11971
12323
  }
11972
12324
  } else {
11973
12325
  if (dryRun) {
11974
12326
  fixes.push(`Would remove orphaned ${o.id} (${o.name})`);
11975
12327
  } else {
11976
- console.log(chalk18.green(` \u2714 Removed orphaned ${o.id} (${o.name}) \u2014 file missing`));
12328
+ console.log(chalk19.green(` \u2714 Removed orphaned ${o.id} (${o.name}) \u2014 file missing`));
11977
12329
  }
11978
12330
  }
11979
12331
  }
@@ -11986,7 +12338,7 @@ async function fixCommand(opts = {}) {
11986
12338
  entry.usedIn = fullActual;
11987
12339
  manifestModified = true;
11988
12340
  if (!dryRun) {
11989
- console.log(chalk18.green(` \u2714 Updated ${entry.id} usedIn: ${fullActual.join(", ") || "none"}`));
12341
+ console.log(chalk19.green(` \u2714 Updated ${entry.id} usedIn: ${fullActual.join(", ") || "none"}`));
11990
12342
  }
11991
12343
  }
11992
12344
  }
@@ -12004,7 +12356,7 @@ async function fixCommand(opts = {}) {
12004
12356
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
12005
12357
  });
12006
12358
  manifest.nextId++;
12007
- console.log(chalk18.green(` \u2714 Registered ${id} (${comp.name}) from ${comp.file}`));
12359
+ console.log(chalk19.green(` \u2714 Registered ${id} (${comp.name}) from ${comp.file}`));
12008
12360
  } else {
12009
12361
  fixes.push(`Would register ${comp.name} from ${comp.file}`);
12010
12362
  }
@@ -12024,33 +12376,33 @@ async function fixCommand(opts = {}) {
12024
12376
  } catch {
12025
12377
  }
12026
12378
  if (fixes.length === 0 && totalErrors === 0 && totalWarnings === 0 && remaining.length === 0) {
12027
- console.log(chalk18.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
12028
- console.log(chalk18.cyan(" Run: coherent preview\n"));
12379
+ console.log(chalk19.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
12380
+ console.log(chalk19.cyan(" Run: coherent preview\n"));
12029
12381
  return;
12030
12382
  }
12031
12383
  if (fixes.length > 0) console.log("");
12032
12384
  if (totalErrors > 0 || totalWarnings > 0 || remaining.length > 0) {
12033
- console.log(chalk18.dim(" \u2500".repeat(25)));
12034
- console.log(chalk18.yellow(`
12385
+ console.log(chalk19.dim(" \u2500".repeat(25)));
12386
+ console.log(chalk19.yellow(`
12035
12387
  Remaining (need manual fix or AI):`));
12036
12388
  for (const { path: path4, report } of fileIssues) {
12037
- console.log(chalk18.dim(` \u{1F4C4} ${path4}`));
12389
+ console.log(chalk19.dim(` \u{1F4C4} ${path4}`));
12038
12390
  console.log(report);
12039
12391
  }
12040
12392
  for (const r of remaining) {
12041
- console.log(chalk18.yellow(` \u26A0 ${r}`));
12393
+ console.log(chalk19.yellow(` \u26A0 ${r}`));
12042
12394
  }
12043
12395
  console.log("");
12044
12396
  const parts = [];
12045
- if (totalErrors > 0) parts.push(chalk18.red(`\u274C ${totalErrors} error(s)`));
12046
- if (totalWarnings > 0) parts.push(chalk18.yellow(`\u26A0 ${totalWarnings} warning(s)`));
12397
+ if (totalErrors > 0) parts.push(chalk19.red(`\u274C ${totalErrors} error(s)`));
12398
+ if (totalWarnings > 0) parts.push(chalk19.yellow(`\u26A0 ${totalWarnings} warning(s)`));
12047
12399
  if (parts.length > 0) console.log(` ${parts.join(" ")}`);
12048
12400
  }
12049
- console.log(chalk18.cyan("\n Run: coherent preview\n"));
12401
+ console.log(chalk19.cyan("\n Run: coherent preview\n"));
12050
12402
  }
12051
12403
 
12052
12404
  // src/commands/check.ts
12053
- import chalk19 from "chalk";
12405
+ import chalk20 from "chalk";
12054
12406
  import { resolve as resolve13 } from "path";
12055
12407
  import { readdirSync as readdirSync8, readFileSync as readFileSync16, statSync as statSync2, existsSync as existsSync22 } from "fs";
12056
12408
  import { loadManifest as loadManifest11 } from "@getcoherent/core";
@@ -12098,7 +12450,7 @@ async function checkCommand(opts = {}) {
12098
12450
  const appDir = resolve13(projectRoot, "app");
12099
12451
  const files = findTsxFiles(appDir);
12100
12452
  result.pages.total = files.length;
12101
- if (!opts.json) console.log(chalk19.cyan("\n \u{1F4C4} Pages") + chalk19.dim(` (${files.length} scanned)
12453
+ if (!opts.json) console.log(chalk20.cyan("\n \u{1F4C4} Pages") + chalk20.dim(` (${files.length} scanned)
12102
12454
  `));
12103
12455
  const autoFixableTypes = /* @__PURE__ */ new Set([
12104
12456
  "RAW_COLOR",
@@ -12128,7 +12480,7 @@ async function checkCommand(opts = {}) {
12128
12480
  result.autoFixable += fileAutoFixable;
12129
12481
  if (filteredIssues.length === 0) {
12130
12482
  result.pages.clean++;
12131
- if (!opts.json) console.log(chalk19.green(` \u2714 ${relativePath}`) + chalk19.dim(" \u2014 clean"));
12483
+ if (!opts.json) console.log(chalk20.green(` \u2714 ${relativePath}`) + chalk20.dim(" \u2014 clean"));
12132
12484
  continue;
12133
12485
  }
12134
12486
  if (errors > 0) result.pages.withErrors++;
@@ -12141,9 +12493,9 @@ async function checkCommand(opts = {}) {
12141
12493
  });
12142
12494
  if (!opts.json) {
12143
12495
  const parts = [];
12144
- if (errors > 0) parts.push(chalk19.red(`${errors} error(s)`));
12145
- if (warnings > 0) parts.push(chalk19.yellow(`${warnings} warning(s)`));
12146
- console.log(chalk19.yellow(` \u26A0 ${relativePath}`) + chalk19.dim(` \u2014 ${parts.join(", ")}`));
12496
+ if (errors > 0) parts.push(chalk20.red(`${errors} error(s)`));
12497
+ if (warnings > 0) parts.push(chalk20.yellow(`${warnings} warning(s)`));
12498
+ console.log(chalk20.yellow(` \u26A0 ${relativePath}`) + chalk20.dim(` \u2014 ${parts.join(", ")}`));
12147
12499
  console.log(formatIssues(filteredIssues));
12148
12500
  }
12149
12501
  }
@@ -12169,15 +12521,15 @@ async function checkCommand(opts = {}) {
12169
12521
  }
12170
12522
  }
12171
12523
  if (!opts.json && result.links.broken.length > 0) {
12172
- console.log(chalk19.yellow(`
12173
- \u{1F517} Internal Links`) + chalk19.dim(` (${result.links.total} scanned)
12524
+ console.log(chalk20.yellow(`
12525
+ \u{1F517} Internal Links`) + chalk20.dim(` (${result.links.total} scanned)
12174
12526
  `));
12175
12527
  for (const b of result.links.broken) {
12176
- console.log(chalk19.red(` \u2717 ${b.file}:${b.line}`) + chalk19.dim(` \u2192 ${b.href} (route does not exist)`));
12528
+ console.log(chalk20.red(` \u2717 ${b.file}:${b.line}`) + chalk20.dim(` \u2192 ${b.href} (route does not exist)`));
12177
12529
  }
12178
12530
  } else if (!opts.json && result.links.total > 0) {
12179
- console.log(chalk19.green(`
12180
- \u{1F517} Internal Links`) + chalk19.dim(` \u2014 all ${result.links.total} links resolve \u2713`));
12531
+ console.log(chalk20.green(`
12532
+ \u{1F517} Internal Links`) + chalk20.dim(` \u2014 all ${result.links.total} links resolve \u2713`));
12181
12533
  }
12182
12534
  try {
12183
12535
  const manifest = await loadManifest11(project.root);
@@ -12186,7 +12538,7 @@ async function checkCommand(opts = {}) {
12186
12538
  const fullPath = resolve13(project.root, entry.file);
12187
12539
  if (!existsSync22(fullPath)) {
12188
12540
  result.pages.withErrors++;
12189
- if (!opts.json) console.log(chalk19.red(`
12541
+ if (!opts.json) console.log(chalk20.red(`
12190
12542
  \u2717 Missing shared component file: ${entry.id} (${entry.file})`));
12191
12543
  }
12192
12544
  }
@@ -12198,8 +12550,8 @@ async function checkCommand(opts = {}) {
12198
12550
  try {
12199
12551
  const manifest = await loadManifest11(projectRoot);
12200
12552
  if (!opts.json && manifest.shared.length > 0) {
12201
- console.log(chalk19.cyan(`
12202
- \u{1F9E9} Shared Components`) + chalk19.dim(` (${manifest.shared.length} registered)
12553
+ console.log(chalk20.cyan(`
12554
+ \u{1F9E9} Shared Components`) + chalk20.dim(` (${manifest.shared.length} registered)
12203
12555
  `));
12204
12556
  }
12205
12557
  let consistent = 0;
@@ -12213,8 +12565,8 @@ async function checkCommand(opts = {}) {
12213
12565
  if (!fileExists) {
12214
12566
  _orphaned++;
12215
12567
  if (!opts.json) {
12216
- console.log(chalk19.red(` \u274C ${entry.id} (${entry.name}) \u2014 file missing: ${entry.file}`));
12217
- console.log(chalk19.dim(` Fix: coherent fix or coherent sync`));
12568
+ console.log(chalk20.red(` \u274C ${entry.id} (${entry.name}) \u2014 file missing: ${entry.file}`));
12569
+ console.log(chalk20.dim(` Fix: coherent fix or coherent sync`));
12218
12570
  }
12219
12571
  continue;
12220
12572
  }
@@ -12225,11 +12577,11 @@ async function checkCommand(opts = {}) {
12225
12577
  _nameMismatch++;
12226
12578
  if (!opts.json) {
12227
12579
  console.log(
12228
- chalk19.yellow(
12580
+ chalk20.yellow(
12229
12581
  ` \u26A0 ${entry.id} \u2014 manifest name "${entry.name}" doesn't match export "${actualExports[0]}"`
12230
12582
  )
12231
12583
  );
12232
- console.log(chalk19.dim(` Fix: coherent sync`));
12584
+ console.log(chalk20.dim(` Fix: coherent sync`));
12233
12585
  }
12234
12586
  }
12235
12587
  } catch {
@@ -12244,35 +12596,35 @@ async function checkCommand(opts = {}) {
12244
12596
  if (totalUsage === 0) {
12245
12597
  unused++;
12246
12598
  if (!opts.json) {
12247
- console.log(chalk19.blue(` \u2139 ${entry.id} (${entry.name}) \u2014 registered but not used anywhere`));
12248
- console.log(chalk19.dim(` Remove: coherent components shared remove ${entry.id}`));
12599
+ console.log(chalk20.blue(` \u2139 ${entry.id} (${entry.name}) \u2014 registered but not used anywhere`));
12600
+ console.log(chalk20.dim(` Remove: coherent components shared remove ${entry.id}`));
12249
12601
  }
12250
12602
  } else {
12251
12603
  consistent++;
12252
12604
  const usageDesc = inLayout ? `layout + ${actualUsedIn.length} page(s)` : `${actualUsedIn.length} page(s)`;
12253
12605
  if (!opts.json) {
12254
- const staleNote = isStale ? chalk19.yellow(" [usedIn stale]") : "";
12255
- console.log(chalk19.green(` \u2714 ${entry.id} (${entry.name})`) + chalk19.dim(` \u2014 ${usageDesc}`) + staleNote);
12606
+ const staleNote = isStale ? chalk20.yellow(" [usedIn stale]") : "";
12607
+ console.log(chalk20.green(` \u2714 ${entry.id} (${entry.name})`) + chalk20.dim(` \u2014 ${usageDesc}`) + staleNote);
12256
12608
  }
12257
12609
  }
12258
12610
  }
12259
12611
  const unregistered = findUnregisteredComponents(projectRoot, manifest);
12260
12612
  if (unregistered.length > 0 && !opts.json) {
12261
- console.log(chalk19.cyan(`
12613
+ console.log(chalk20.cyan(`
12262
12614
  \u{1F4E6} Unregistered components found:`));
12263
12615
  for (const comp of unregistered) {
12264
- console.log(chalk19.blue(` \u2139 ${comp.name}`) + chalk19.dim(` \u2014 ${comp.file} (not in manifest)`));
12265
- console.log(chalk19.dim(` Register: coherent sync`));
12616
+ console.log(chalk20.blue(` \u2139 ${comp.name}`) + chalk20.dim(` \u2014 ${comp.file} (not in manifest)`));
12617
+ console.log(chalk20.dim(` Register: coherent sync`));
12266
12618
  }
12267
12619
  }
12268
12620
  const inlineDupes = findInlineDuplicates(projectRoot, manifest);
12269
12621
  if (inlineDupes.length > 0 && !opts.json) {
12270
- console.log(chalk19.cyan(`
12622
+ console.log(chalk20.cyan(`
12271
12623
  \u{1F50D} Inline duplicates:`));
12272
12624
  for (const dup of inlineDupes) {
12273
- console.log(chalk19.yellow(` \u26A0 ${dup.pageFile}`) + chalk19.dim(` has inline ${dup.componentName}`));
12625
+ console.log(chalk20.yellow(` \u26A0 ${dup.pageFile}`) + chalk20.dim(` has inline ${dup.componentName}`));
12274
12626
  console.log(
12275
- chalk19.dim(
12627
+ chalk20.dim(
12276
12628
  ` Use shared: import { ${dup.componentName} } from "@/${dup.sharedFile.replace(".tsx", "")}"`
12277
12629
  )
12278
12630
  );
@@ -12299,24 +12651,24 @@ async function checkCommand(opts = {}) {
12299
12651
  console.log(JSON.stringify(result, null, 2));
12300
12652
  return;
12301
12653
  }
12302
- console.log(chalk19.dim("\n " + "\u2500".repeat(50)));
12654
+ console.log(chalk20.dim("\n " + "\u2500".repeat(50)));
12303
12655
  const summaryParts = [];
12304
12656
  if (!skipPages) {
12305
- summaryParts.push(`${chalk19.green(`${result.pages.clean} clean`)} pages`);
12306
- if (result.pages.withErrors > 0) summaryParts.push(chalk19.red(`${result.pages.withErrors} with errors`));
12307
- if (result.pages.withWarnings > 0) summaryParts.push(chalk19.yellow(`${result.pages.withWarnings} with warnings`));
12657
+ summaryParts.push(`${chalk20.green(`${result.pages.clean} clean`)} pages`);
12658
+ if (result.pages.withErrors > 0) summaryParts.push(chalk20.red(`${result.pages.withErrors} with errors`));
12659
+ if (result.pages.withWarnings > 0) summaryParts.push(chalk20.yellow(`${result.pages.withWarnings} with warnings`));
12308
12660
  }
12309
12661
  if (!skipShared && result.shared.total > 0) {
12310
12662
  summaryParts.push(`${result.shared.consistent} healthy shared`);
12311
12663
  if (result.shared.unused > 0) summaryParts.push(`${result.shared.unused} unused`);
12312
12664
  }
12313
12665
  if (result.links.broken.length > 0) {
12314
- summaryParts.push(chalk19.red(`${result.links.broken.length} broken link(s)`));
12666
+ summaryParts.push(chalk20.red(`${result.links.broken.length} broken link(s)`));
12315
12667
  }
12316
12668
  console.log(`
12317
12669
  ${summaryParts.join(" | ")}`);
12318
12670
  if (result.autoFixable > 0) {
12319
- console.log(chalk19.cyan(`
12671
+ console.log(chalk20.cyan(`
12320
12672
  Auto-fixable: ${result.autoFixable} issues. Run: coherent fix`));
12321
12673
  }
12322
12674
  console.log("");
@@ -12325,21 +12677,21 @@ async function checkCommand(opts = {}) {
12325
12677
  }
12326
12678
 
12327
12679
  // src/commands/repair.ts
12328
- import chalk20 from "chalk";
12680
+ import chalk21 from "chalk";
12329
12681
  async function repairCommand() {
12330
- console.log(chalk20.dim(" \u2139\uFE0F `coherent repair` is deprecated \u2014 use `coherent fix` instead\n"));
12682
+ console.log(chalk21.dim(" \u2139\uFE0F `coherent repair` is deprecated \u2014 use `coherent fix` instead\n"));
12331
12683
  await fixCommand();
12332
12684
  }
12333
12685
 
12334
12686
  // src/commands/doctor.ts
12335
- import chalk21 from "chalk";
12687
+ import chalk22 from "chalk";
12336
12688
  async function doctorCommand() {
12337
- console.log(chalk21.dim(" \u2139\uFE0F `coherent doctor` is deprecated \u2014 use `coherent fix` instead\n"));
12689
+ console.log(chalk22.dim(" \u2139\uFE0F `coherent doctor` is deprecated \u2014 use `coherent fix` instead\n"));
12338
12690
  await fixCommand();
12339
12691
  }
12340
12692
 
12341
12693
  // src/commands/rules.ts
12342
- import chalk22 from "chalk";
12694
+ import chalk23 from "chalk";
12343
12695
  async function rulesCommand() {
12344
12696
  try {
12345
12697
  const result = await regenerateCursorRules();
@@ -12350,31 +12702,31 @@ async function rulesCommand() {
12350
12702
  if (result.sharedCount !== void 0) parts.push(`${result.sharedCount} shared components`);
12351
12703
  if (result.tokenKeys !== void 0) parts.push(`${result.tokenKeys} design token keys`);
12352
12704
  const summary = parts.length > 0 ? ` (${parts.join(", ")})` : "";
12353
- console.log(chalk22.green(`\u2714 Updated .cursorrules and CLAUDE.md${summary}
12705
+ console.log(chalk23.green(`\u2714 Updated .cursorrules and CLAUDE.md${summary}
12354
12706
  `));
12355
12707
  } catch (error) {
12356
- console.error(chalk22.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
12708
+ console.error(chalk23.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
12357
12709
  process.exit(1);
12358
12710
  }
12359
12711
  }
12360
12712
 
12361
12713
  // src/commands/validate.ts
12362
- import chalk23 from "chalk";
12714
+ import chalk24 from "chalk";
12363
12715
  async function validateCommand() {
12364
- console.log(chalk23.dim(" \u2139\uFE0F `coherent validate` is deprecated \u2014 use `coherent check` instead\n"));
12716
+ console.log(chalk24.dim(" \u2139\uFE0F `coherent validate` is deprecated \u2014 use `coherent check` instead\n"));
12365
12717
  await checkCommand({ pages: true });
12366
12718
  }
12367
12719
 
12368
12720
  // src/commands/audit.ts
12369
- import chalk24 from "chalk";
12721
+ import chalk25 from "chalk";
12370
12722
  async function auditCommand(options) {
12371
- console.log(chalk24.dim(" \u2139\uFE0F `coherent audit` is deprecated \u2014 use `coherent check` instead\n"));
12723
+ console.log(chalk25.dim(" \u2139\uFE0F `coherent audit` is deprecated \u2014 use `coherent check` instead\n"));
12372
12724
  await checkCommand({ shared: true, json: options.json });
12373
12725
  }
12374
12726
 
12375
12727
  // src/commands/components.ts
12376
12728
  import { Command } from "commander";
12377
- import chalk25 from "chalk";
12729
+ import chalk26 from "chalk";
12378
12730
  import {
12379
12731
  DesignSystemManager as DesignSystemManager12,
12380
12732
  ComponentManager as ComponentManager7,
@@ -12425,9 +12777,9 @@ function createComponentsCommand() {
12425
12777
  console.log(JSON.stringify({ shared: manifest.shared, ui: installed2 }, null, 2));
12426
12778
  return;
12427
12779
  }
12428
- console.log(chalk25.bold("\n\u{1F4E6} Shared Components"));
12780
+ console.log(chalk26.bold("\n\u{1F4E6} Shared Components"));
12429
12781
  if (manifest.shared.length === 0) {
12430
- console.log(chalk25.gray(" None yet. Generate pages with header/footer to create them.\n"));
12782
+ console.log(chalk26.gray(" None yet. Generate pages with header/footer to create them.\n"));
12431
12783
  } else {
12432
12784
  const order = { layout: 0, section: 1, widget: 2 };
12433
12785
  const sorted = [...manifest.shared].sort(
@@ -12435,9 +12787,9 @@ function createComponentsCommand() {
12435
12787
  );
12436
12788
  console.log("");
12437
12789
  sorted.forEach((entry) => {
12438
- const usage = entry.usedIn.length === 0 ? chalk25.gray("unused") : entry.usedIn.includes("app/layout.tsx") ? chalk25.green("all pages") : chalk25.gray(entry.usedIn.join(", "));
12790
+ const usage = entry.usedIn.length === 0 ? chalk26.gray("unused") : entry.usedIn.includes("app/layout.tsx") ? chalk26.green("all pages") : chalk26.gray(entry.usedIn.join(", "));
12439
12791
  console.log(
12440
- ` ${chalk25.cyan(entry.id.padEnd(8))} ${chalk25.white(entry.name.padEnd(18))} ${chalk25.gray(entry.type.padEnd(9))} ${usage}`
12792
+ ` ${chalk26.cyan(entry.id.padEnd(8))} ${chalk26.white(entry.name.padEnd(18))} ${chalk26.gray(entry.type.padEnd(9))} ${usage}`
12441
12793
  );
12442
12794
  });
12443
12795
  console.log("");
@@ -12446,24 +12798,24 @@ function createComponentsCommand() {
12446
12798
  const availableShadcn = listShadcnComponents();
12447
12799
  const installedIds = new Set(installed.map((c) => c.id));
12448
12800
  const notInstalled = availableShadcn.filter((id) => !installedIds.has(id));
12449
- console.log(chalk25.bold("\u{1F9E9} UI Components (shadcn)"));
12801
+ console.log(chalk26.bold("\u{1F9E9} UI Components (shadcn)"));
12450
12802
  if (installed.length === 0) {
12451
- console.log(chalk25.gray(" None installed yet.\n"));
12803
+ console.log(chalk26.gray(" None installed yet.\n"));
12452
12804
  } else {
12453
12805
  const names = installed.map((c) => c.name).sort();
12454
- console.log(chalk25.green(` Installed (${names.length}): `) + chalk25.white(names.join(", ")));
12806
+ console.log(chalk26.green(` Installed (${names.length}): `) + chalk26.white(names.join(", ")));
12455
12807
  }
12456
12808
  if (notInstalled.length > 0) {
12457
- console.log(chalk25.gray(` Available (${notInstalled.length}): `) + chalk25.gray(notInstalled.join(", ")));
12809
+ console.log(chalk26.gray(` Available (${notInstalled.length}): `) + chalk26.gray(notInstalled.join(", ")));
12458
12810
  }
12459
12811
  console.log("");
12460
- console.log(chalk25.cyan("\u{1F4A1} Commands:"));
12461
- console.log(chalk25.white(' coherent chat "add a testimonial component"'));
12462
- console.log(chalk25.white(' coherent chat --component "Header" "add a search button"'));
12812
+ console.log(chalk26.cyan("\u{1F4A1} Commands:"));
12813
+ console.log(chalk26.white(' coherent chat "add a testimonial component"'));
12814
+ console.log(chalk26.white(' coherent chat --component "Header" "add a search button"'));
12463
12815
  console.log("");
12464
12816
  });
12465
12817
  cmd.command("add <name>").description("Install a specific component").action(async (name) => {
12466
- console.log(chalk25.yellow(`
12818
+ console.log(chalk26.yellow(`
12467
12819
  \u{1F4A1} Use: coherent chat "add ${name} component"
12468
12820
  `));
12469
12821
  });
@@ -12476,25 +12828,25 @@ function createComponentsCommand() {
12476
12828
  console.log(JSON.stringify(manifest, null, 2));
12477
12829
  return;
12478
12830
  }
12479
- console.log(chalk25.bold("\n\u{1F4E6} Shared Components\n"));
12831
+ console.log(chalk26.bold("\n\u{1F4E6} Shared Components\n"));
12480
12832
  if (manifest.shared.length === 0) {
12481
- console.log(chalk25.yellow(" No shared components yet.\n"));
12482
- console.log(chalk25.gray(' Create via chat: coherent chat "add a page with header and footer"\n'));
12833
+ console.log(chalk26.yellow(" No shared components yet.\n"));
12834
+ console.log(chalk26.gray(' Create via chat: coherent chat "add a page with header and footer"\n'));
12483
12835
  return;
12484
12836
  }
12485
12837
  const order = { layout: 0, section: 1, widget: 2 };
12486
12838
  const sorted = [...manifest.shared].sort((a, b) => order[a.type] - order[b.type] || a.name.localeCompare(b.name));
12487
12839
  sorted.forEach((entry) => {
12488
- const usedIn = entry.usedIn.length === 0 ? chalk25.gray("(not used yet)") : entry.usedIn.length === 1 && entry.usedIn[0] === "app/layout.tsx" ? chalk25.gray("layout.tsx (all pages)") : chalk25.gray(`used in: ${entry.usedIn.join(", ")}`);
12489
- console.log(chalk25.cyan(` ${entry.id}`), chalk25.white(entry.name), chalk25.gray(entry.type));
12840
+ const usedIn = entry.usedIn.length === 0 ? chalk26.gray("(not used yet)") : entry.usedIn.length === 1 && entry.usedIn[0] === "app/layout.tsx" ? chalk26.gray("layout.tsx (all pages)") : chalk26.gray(`used in: ${entry.usedIn.join(", ")}`);
12841
+ console.log(chalk26.cyan(` ${entry.id}`), chalk26.white(entry.name), chalk26.gray(entry.type));
12490
12842
  if (opts.verbose) {
12491
- console.log(chalk25.gray(` file: ${entry.file}`));
12492
- if (entry.description) console.log(chalk25.gray(` ${entry.description}`));
12843
+ console.log(chalk26.gray(` file: ${entry.file}`));
12844
+ if (entry.description) console.log(chalk26.gray(` ${entry.description}`));
12493
12845
  }
12494
- console.log(chalk25.gray(` ${usedIn}`));
12846
+ console.log(chalk26.gray(` ${usedIn}`));
12495
12847
  console.log("");
12496
12848
  });
12497
- console.log(chalk25.cyan("\u{1F4A1} Modify by ID:"), chalk25.white('coherent chat "in CID-001 add a search button"\n'));
12849
+ console.log(chalk26.cyan("\u{1F4A1} Modify by ID:"), chalk26.white('coherent chat "in CID-001 add a search button"\n'));
12498
12850
  });
12499
12851
  sharedCmd.command("add <name>").description("Create a shared component (layout/section/widget) and register in manifest").option("-t, --type <type>", "Type: layout | section | widget", "layout").option("-d, --description <desc>", "Description").action(async (name, opts) => {
12500
12852
  const project = findConfig();
@@ -12506,12 +12858,12 @@ function createComponentsCommand() {
12506
12858
  description: opts.description,
12507
12859
  usedIn: type === "layout" ? ["app/layout.tsx"] : []
12508
12860
  });
12509
- console.log(chalk25.green(`
12861
+ console.log(chalk26.green(`
12510
12862
  \u2705 Created ${result.id} (${result.name}) at ${result.file}
12511
12863
  `));
12512
12864
  if (type === "layout") {
12513
12865
  const updated = await integrateSharedLayoutIntoRootLayout3(project.root);
12514
- if (updated) console.log(chalk25.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
12866
+ if (updated) console.log(chalk26.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
12515
12867
  }
12516
12868
  const sharedPagePath = resolve14(project.root, "app/design-system/shared/page.tsx");
12517
12869
  if (!existsSync23(sharedPagePath)) {
@@ -12521,23 +12873,23 @@ function createComponentsCommand() {
12521
12873
  const config2 = dsm.getConfig();
12522
12874
  const written = await writeDesignSystemFiles(project.root, config2, { sharedOnly: true });
12523
12875
  if (written.length > 0) {
12524
- console.log(chalk25.cyan(" Added Design System shared pages: /design-system/shared\n"));
12876
+ console.log(chalk26.cyan(" Added Design System shared pages: /design-system/shared\n"));
12525
12877
  }
12526
12878
  } catch (e) {
12527
- if (process.env.COHERENT_DEBUG === "1") console.error(chalk25.dim("DS shared pages write failed:"), e);
12879
+ if (process.env.COHERENT_DEBUG === "1") console.error(chalk26.dim("DS shared pages write failed:"), e);
12528
12880
  }
12529
12881
  }
12530
12882
  try {
12531
12883
  await writeCursorRules(project.root);
12532
12884
  } catch (e) {
12533
- if (process.env.COHERENT_DEBUG === "1") console.error(chalk25.dim("Could not update .cursorrules:"), e);
12885
+ if (process.env.COHERENT_DEBUG === "1") console.error(chalk26.dim("Could not update .cursorrules:"), e);
12534
12886
  }
12535
12887
  });
12536
12888
  return cmd;
12537
12889
  }
12538
12890
 
12539
12891
  // src/commands/import-cmd.ts
12540
- import chalk26 from "chalk";
12892
+ import chalk27 from "chalk";
12541
12893
  import ora6 from "ora";
12542
12894
  import { writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
12543
12895
  import { resolve as resolve15, join as join18, dirname as dirname9 } from "path";
@@ -12642,25 +12994,25 @@ function createImportCommand() {
12642
12994
  }
12643
12995
  async function importFigmaAction(urlOrKey, opts) {
12644
12996
  if (typeof urlOrKey !== "string" || !urlOrKey.trim()) {
12645
- console.error(chalk26.red("\n\u274C Figma URL or file key is required.\n"));
12646
- console.log(chalk26.dim(" Usage: coherent import figma <url-or-key> --token <your-token>\n"));
12997
+ console.error(chalk27.red("\n\u274C Figma URL or file key is required.\n"));
12998
+ console.log(chalk27.dim(" Usage: coherent import figma <url-or-key> --token <your-token>\n"));
12647
12999
  process.exit(1);
12648
13000
  }
12649
13001
  const token = opts.token ?? process.env.FIGMA_ACCESS_TOKEN ?? process.env.FIGMA_TOKEN;
12650
13002
  if (!token || typeof token !== "string") {
12651
- console.error(chalk26.red("\n\u274C Figma token required.\n"));
12652
- console.log(chalk26.dim(" Use: coherent import figma <url-or-key> --token <your-token>"));
12653
- console.log(chalk26.dim(" Or set FIGMA_ACCESS_TOKEN or FIGMA_TOKEN in your environment.\n"));
12654
- console.log(chalk26.dim(" Get a token: Figma \u2192 Settings \u2192 Personal access tokens.\n"));
13003
+ console.error(chalk27.red("\n\u274C Figma token required.\n"));
13004
+ console.log(chalk27.dim(" Use: coherent import figma <url-or-key> --token <your-token>"));
13005
+ console.log(chalk27.dim(" Or set FIGMA_ACCESS_TOKEN or FIGMA_TOKEN in your environment.\n"));
13006
+ console.log(chalk27.dim(" Get a token: Figma \u2192 Settings \u2192 Personal access tokens.\n"));
12655
13007
  process.exit(1);
12656
13008
  }
12657
13009
  const generatePages = opts.pages !== false;
12658
13010
  const dryRun = Boolean(opts.dryRun);
12659
13011
  const fileKey = FigmaClient.extractFileKey(urlOrKey);
12660
13012
  if (!fileKey) {
12661
- console.error(chalk26.red("\n\u274C Invalid Figma URL or file key.\n"));
12662
- console.log(chalk26.dim(" Use a URL like: https://www.figma.com/file/ABC123/MyDesign"));
12663
- console.log(chalk26.dim(" Or the file key: ABC123\n"));
13013
+ console.error(chalk27.red("\n\u274C Invalid Figma URL or file key.\n"));
13014
+ console.log(chalk27.dim(" Use a URL like: https://www.figma.com/file/ABC123/MyDesign"));
13015
+ console.log(chalk27.dim(" Or the file key: ABC123\n"));
12664
13016
  process.exit(1);
12665
13017
  }
12666
13018
  const project = findConfig();
@@ -12837,7 +13189,7 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
12837
13189
  try {
12838
13190
  await writeCursorRules(projectRoot);
12839
13191
  } catch (e) {
12840
- if (process.env.COHERENT_DEBUG === "1") console.error(chalk26.dim("Could not update .cursorrules:"), e);
13192
+ if (process.env.COHERENT_DEBUG === "1") console.error(chalk27.dim("Could not update .cursorrules:"), e);
12841
13193
  }
12842
13194
  } else {
12843
13195
  stats.filesWritten.push(DESIGN_SYSTEM_CONFIG_PATH);
@@ -12847,7 +13199,7 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
12847
13199
  } catch (err) {
12848
13200
  spinner.fail("Import failed");
12849
13201
  const message = err instanceof Error ? err.message : String(err);
12850
- console.error(chalk26.red("\n\u274C " + message + "\n"));
13202
+ console.error(chalk27.red("\n\u274C " + message + "\n"));
12851
13203
  process.exit(1);
12852
13204
  }
12853
13205
  }
@@ -12855,36 +13207,36 @@ function printReport(stats, opts) {
12855
13207
  const { dryRun, generatePages, fileName } = opts;
12856
13208
  console.log("");
12857
13209
  if (dryRun) {
12858
- console.log(chalk26.yellow("\u2550\u2550\u2550 Dry run (no files written) \u2550\u2550\u2550"));
13210
+ console.log(chalk27.yellow("\u2550\u2550\u2550 Dry run (no files written) \u2550\u2550\u2550"));
12859
13211
  console.log("");
12860
13212
  }
12861
- console.log(chalk26.green("\u2705 Figma import complete"));
13213
+ console.log(chalk27.green("\u2705 Figma import complete"));
12862
13214
  console.log("");
12863
- console.log(chalk26.cyan(" Statistics"));
12864
- console.log(chalk26.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
12865
- console.log(chalk26.blue(` File: ${fileName}`));
12866
- console.log(chalk26.blue(` Color styles: ${stats.colorStyles}`));
12867
- console.log(chalk26.blue(` Text styles: ${stats.textStyles}`));
13215
+ console.log(chalk27.cyan(" Statistics"));
13216
+ console.log(chalk27.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13217
+ console.log(chalk27.blue(` File: ${fileName}`));
13218
+ console.log(chalk27.blue(` Color styles: ${stats.colorStyles}`));
13219
+ console.log(chalk27.blue(` Text styles: ${stats.textStyles}`));
12868
13220
  console.log(
12869
- chalk26.blue(` Components: ${stats.componentsTotal} (${stats.baseCount} \u2192 base, ${stats.sharedCount} \u2192 shared)`)
13221
+ chalk27.blue(` Components: ${stats.componentsTotal} (${stats.baseCount} \u2192 base, ${stats.sharedCount} \u2192 shared)`)
12870
13222
  );
12871
- console.log(chalk26.blue(` Pages: ${stats.pagesGenerated}${!generatePages ? " (skipped by --no-pages)" : ""}`));
12872
- console.log(chalk26.blue(` design-system.config: ${stats.configUpdated ? "updated" : "\u2014"}`));
12873
- console.log(chalk26.blue(` Layout (Header/Footer): ${stats.layoutIntegrated ? "integrated" : "\u2014"}`));
12874
- console.log(chalk26.blue(` DS viewer files: ${stats.dsFilesWritten}`));
13223
+ console.log(chalk27.blue(` Pages: ${stats.pagesGenerated}${!generatePages ? " (skipped by --no-pages)" : ""}`));
13224
+ console.log(chalk27.blue(` design-system.config: ${stats.configUpdated ? "updated" : "\u2014"}`));
13225
+ console.log(chalk27.blue(` Layout (Header/Footer): ${stats.layoutIntegrated ? "integrated" : "\u2014"}`));
13226
+ console.log(chalk27.blue(` DS viewer files: ${stats.dsFilesWritten}`));
12875
13227
  console.log(
12876
- chalk26.blue(` Total files ${dryRun ? "that would be written" : "written"}: ${stats.filesWritten.length}`)
13228
+ chalk27.blue(` Total files ${dryRun ? "that would be written" : "written"}: ${stats.filesWritten.length}`)
12877
13229
  );
12878
13230
  console.log("");
12879
13231
  if (stats.filesWritten.length > 0 && stats.filesWritten.length <= 30) {
12880
- console.log(chalk26.dim(" Files:"));
12881
- stats.filesWritten.forEach((f) => console.log(chalk26.dim(` ${f}`)));
13232
+ console.log(chalk27.dim(" Files:"));
13233
+ stats.filesWritten.forEach((f) => console.log(chalk27.dim(` ${f}`)));
12882
13234
  console.log("");
12883
13235
  }
12884
13236
  }
12885
13237
 
12886
13238
  // src/commands/ds.ts
12887
- import chalk27 from "chalk";
13239
+ import chalk28 from "chalk";
12888
13240
  import ora7 from "ora";
12889
13241
  import { DesignSystemManager as DesignSystemManager14 } from "@getcoherent/core";
12890
13242
  async function dsRegenerateCommand() {
@@ -12899,16 +13251,16 @@ async function dsRegenerateCommand() {
12899
13251
  const config2 = dsm.getConfig();
12900
13252
  const written = await writeDesignSystemFiles(project.root, config2);
12901
13253
  spinner.succeed(`Regenerated ${written.length} Design System file(s)`);
12902
- console.log(chalk27.gray(" app/design-system/* and app/api/design-system/*\n"));
12903
- console.log(chalk27.cyan(" Open /design-system in the app to view.\n"));
13254
+ console.log(chalk28.gray(" app/design-system/* and app/api/design-system/*\n"));
13255
+ console.log(chalk28.cyan(" Open /design-system in the app to view.\n"));
12904
13256
  } catch (error) {
12905
- console.error(chalk27.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
13257
+ console.error(chalk28.red("\u274C Command failed:"), error instanceof Error ? error.message : "Unknown error");
12906
13258
  process.exit(1);
12907
13259
  }
12908
13260
  }
12909
13261
 
12910
13262
  // src/commands/update.ts
12911
- import chalk28 from "chalk";
13263
+ import chalk29 from "chalk";
12912
13264
  import ora8 from "ora";
12913
13265
  import { readFileSync as readFileSync17, existsSync as existsSync25 } from "fs";
12914
13266
  import { join as join19 } from "path";
@@ -12960,14 +13312,14 @@ async function updateCommand(opts) {
12960
13312
  const projectVersion = config2.coherentVersion || "0.0.0";
12961
13313
  if (compareSemver(projectVersion, CLI_VERSION4) === 0) {
12962
13314
  spinner.succeed("Project is already up to date");
12963
- console.log(chalk28.gray(` Version: v${CLI_VERSION4}
13315
+ console.log(chalk29.gray(` Version: v${CLI_VERSION4}
12964
13316
  `));
12965
13317
  return;
12966
13318
  }
12967
13319
  if (compareSemver(projectVersion, CLI_VERSION4) > 0) {
12968
13320
  spinner.warn("Project was created with a newer CLI version");
12969
- console.log(chalk28.yellow(` Project: v${projectVersion} \u2192 CLI: v${CLI_VERSION4}`));
12970
- console.log(chalk28.yellow(" Update your CLI: npm install -g @getcoherent/cli@latest\n"));
13321
+ console.log(chalk29.yellow(` Project: v${projectVersion} \u2192 CLI: v${CLI_VERSION4}`));
13322
+ console.log(chalk29.yellow(" Update your CLI: npm install -g @getcoherent/cli@latest\n"));
12971
13323
  return;
12972
13324
  }
12973
13325
  const report = {
@@ -13013,36 +13365,36 @@ async function updateCommand(opts) {
13013
13365
  }
13014
13366
  function printReport2(report) {
13015
13367
  const from = report.fromVersion ? `v${report.fromVersion}` : "unknown";
13016
- console.log(chalk28.green(`
13368
+ console.log(chalk29.green(`
13017
13369
  \u2714 Project updated: ${from} \u2192 v${report.toVersion}
13018
13370
  `));
13019
13371
  if (report.overlayFiles > 0) {
13020
- console.log(chalk28.white(` \u2714 Regenerated platform overlay (${report.overlayFiles} files)`));
13372
+ console.log(chalk29.white(` \u2714 Regenerated platform overlay (${report.overlayFiles} files)`));
13021
13373
  }
13022
13374
  if (report.migrationsApplied.length > 0) {
13023
13375
  for (const desc of report.migrationsApplied) {
13024
- console.log(chalk28.white(` \u2714 Migrated config: ${desc}`));
13376
+ console.log(chalk29.white(` \u2714 Migrated config: ${desc}`));
13025
13377
  }
13026
13378
  }
13027
13379
  if (report.rulesUpdated) {
13028
- console.log(chalk28.white(" \u2714 Updated .cursorrules and CLAUDE.md"));
13380
+ console.log(chalk29.white(" \u2714 Updated .cursorrules and CLAUDE.md"));
13029
13381
  }
13030
13382
  if (report.missingCssVars.length > 0) {
13031
13383
  console.log("");
13032
- console.log(chalk28.yellow(" \u26A0 New CSS variables available in globals.css:"));
13384
+ console.log(chalk29.yellow(" \u26A0 New CSS variables available in globals.css:"));
13033
13385
  for (const v of report.missingCssVars.slice(0, 10)) {
13034
- console.log(chalk28.gray(` ${v}`));
13386
+ console.log(chalk29.gray(` ${v}`));
13035
13387
  }
13036
13388
  if (report.missingCssVars.length > 10) {
13037
- console.log(chalk28.gray(` ... and ${report.missingCssVars.length - 10} more`));
13389
+ console.log(chalk29.gray(` ... and ${report.missingCssVars.length - 10} more`));
13038
13390
  }
13039
13391
  console.log("");
13040
- console.log(chalk28.cyan(" To add them automatically:"));
13041
- console.log(chalk28.white(" coherent update --patch-globals\n"));
13392
+ console.log(chalk29.cyan(" To add them automatically:"));
13393
+ console.log(chalk29.white(" coherent update --patch-globals\n"));
13042
13394
  }
13043
13395
  console.log("");
13044
- console.log(chalk28.dim(" Your pages and components were NOT modified."));
13045
- console.log(chalk28.dim(" Run `coherent check` to check existing pages against new rules.\n"));
13396
+ console.log(chalk29.dim(" Your pages and components were NOT modified."));
13397
+ console.log(chalk29.dim(" Run `coherent check` to check existing pages against new rules.\n"));
13046
13398
  }
13047
13399
  var EXPECTED_CSS_VARS = [
13048
13400
  "--background",
@@ -13126,7 +13478,7 @@ function patchGlobalsCss(projectRoot, missingVars) {
13126
13478
  }
13127
13479
 
13128
13480
  // src/commands/undo.ts
13129
- import chalk29 from "chalk";
13481
+ import chalk30 from "chalk";
13130
13482
  async function undoCommand(options) {
13131
13483
  try {
13132
13484
  const project = findConfig();
@@ -13135,41 +13487,41 @@ async function undoCommand(options) {
13135
13487
  const backups = listBackups(projectRoot);
13136
13488
  if (options.list) {
13137
13489
  if (backups.length === 0) {
13138
- console.log(chalk29.yellow("No backups found."));
13490
+ console.log(chalk30.yellow("No backups found."));
13139
13491
  return;
13140
13492
  }
13141
- console.log(chalk29.bold("\n\u{1F4E6} Available backups:\n"));
13493
+ console.log(chalk30.bold("\n\u{1F4E6} Available backups:\n"));
13142
13494
  for (const b of backups) {
13143
13495
  const date = new Date(b.timestamp);
13144
13496
  const timeStr = date.toLocaleString();
13145
- console.log(chalk29.white(` ${b.name}`));
13146
- console.log(chalk29.dim(` ${timeStr} \u2014 ${b.files} file(s)`));
13497
+ console.log(chalk30.white(` ${b.name}`));
13498
+ console.log(chalk30.dim(` ${timeStr} \u2014 ${b.files} file(s)`));
13147
13499
  console.log();
13148
13500
  }
13149
13501
  return;
13150
13502
  }
13151
13503
  if (backups.length === 0) {
13152
- console.log(chalk29.yellow("No backups found. Nothing to undo."));
13504
+ console.log(chalk30.yellow("No backups found. Nothing to undo."));
13153
13505
  return;
13154
13506
  }
13155
13507
  const latest = backups[0];
13156
13508
  const ok = restoreBackup(projectRoot, latest.name);
13157
13509
  if (!ok) {
13158
- console.log(chalk29.red("Failed to restore backup."));
13510
+ console.log(chalk30.red("Failed to restore backup."));
13159
13511
  return;
13160
13512
  }
13161
- console.log(chalk29.green("\n\u2705 Restored to previous state:\n"));
13162
- console.log(chalk29.dim(` Snapshot: ${new Date(latest.timestamp).toLocaleString()}`));
13163
- console.log(chalk29.dim(` Files: ${latest.files} restored`));
13164
- console.log(chalk29.cyan("\n Run: coherent preview\n"));
13513
+ console.log(chalk30.green("\n\u2705 Restored to previous state:\n"));
13514
+ console.log(chalk30.dim(` Snapshot: ${new Date(latest.timestamp).toLocaleString()}`));
13515
+ console.log(chalk30.dim(` Files: ${latest.files} restored`));
13516
+ console.log(chalk30.cyan("\n Run: coherent preview\n"));
13165
13517
  } catch (error) {
13166
- console.error(chalk29.red("\u274C Undo failed:"), error instanceof Error ? error.message : "Unknown error");
13518
+ console.error(chalk30.red("\u274C Undo failed:"), error instanceof Error ? error.message : "Unknown error");
13167
13519
  process.exit(1);
13168
13520
  }
13169
13521
  }
13170
13522
 
13171
13523
  // src/commands/sync.ts
13172
- import chalk30 from "chalk";
13524
+ import chalk31 from "chalk";
13173
13525
  import ora9 from "ora";
13174
13526
  import { existsSync as existsSync26, readFileSync as readFileSync18 } from "fs";
13175
13527
  import { join as join20, relative as relative5, dirname as dirname10 } from "path";
@@ -13407,7 +13759,7 @@ async function syncCommand(options = {}) {
13407
13759
  const doTokens = runAll || options.tokens === true;
13408
13760
  const doComponents = runAll || options.components === true;
13409
13761
  const doPatterns = runAll || options.patterns === true;
13410
- if (dryRun) console.log(chalk30.yellow(" [dry-run] No files will be written\n"));
13762
+ if (dryRun) console.log(chalk31.yellow(" [dry-run] No files will be written\n"));
13411
13763
  const spinner = ora9("Scanning project files...").start();
13412
13764
  try {
13413
13765
  const appDir = join20(project.root, "app");
@@ -13548,84 +13900,84 @@ async function syncCommand(options = {}) {
13548
13900
  spinner.succeed("Updated .cursorrules and CLAUDE.md");
13549
13901
  }
13550
13902
  console.log("");
13551
- console.log(chalk30.green(`\u2705 Design System ${dryRun ? "analyzed" : "synced"} with actual code
13903
+ console.log(chalk31.green(`\u2705 Design System ${dryRun ? "analyzed" : "synced"} with actual code
13552
13904
  `));
13553
- console.log(chalk30.blue("\u{1F4C4} Pages:"));
13905
+ console.log(chalk31.blue("\u{1F4C4} Pages:"));
13554
13906
  for (const page of discoveredPages) {
13555
13907
  const a = analyzePageCode(page.code);
13556
13908
  const comps = Object.entries(a.componentUsage || {}).filter(([, c]) => c > 0).map(([n]) => n);
13557
- console.log(chalk30.gray(` ${page.route} \u2014 ${page.name}`));
13558
- if (comps.length > 0) console.log(chalk30.gray(` Components: ${comps.join(", ")}`));
13559
- if (a.sections?.length) console.log(chalk30.gray(` Sections: ${a.sections.map((s) => s.name).join(", ")}`));
13909
+ console.log(chalk31.gray(` ${page.route} \u2014 ${page.name}`));
13910
+ if (comps.length > 0) console.log(chalk31.gray(` Components: ${comps.join(", ")}`));
13911
+ if (a.sections?.length) console.log(chalk31.gray(` Sections: ${a.sections.map((s) => s.name).join(", ")}`));
13560
13912
  }
13561
13913
  if (doTokens && extractedTokens) {
13562
13914
  console.log("");
13563
- console.log(chalk30.blue("\u{1F3A8} Design Tokens (from globals.css):"));
13915
+ console.log(chalk31.blue("\u{1F3A8} Design Tokens (from globals.css):"));
13564
13916
  const lc = Object.keys(extractedTokens.colors.light).length;
13565
13917
  const dc = Object.keys(extractedTokens.colors.dark).length;
13566
- console.log(chalk30.gray(` Light: ${lc} variables | Dark: ${dc} variables`));
13567
- console.log(chalk30.gray(` Default mode: ${extractedTokens.defaultMode}`));
13568
- if (extractedTokens.radius) console.log(chalk30.gray(` Border radius: ${extractedTokens.radius}`));
13918
+ console.log(chalk31.gray(` Light: ${lc} variables | Dark: ${dc} variables`));
13919
+ console.log(chalk31.gray(` Default mode: ${extractedTokens.defaultMode}`));
13920
+ if (extractedTokens.radius) console.log(chalk31.gray(` Border radius: ${extractedTokens.radius}`));
13569
13921
  }
13570
13922
  if (doComponents && reconcileResult) {
13571
13923
  console.log("");
13572
- console.log(chalk30.blue("\u{1F9E9} Shared Components:"));
13924
+ console.log(chalk31.blue("\u{1F9E9} Shared Components:"));
13573
13925
  for (const r of reconcileResult.removed) {
13574
- console.log(chalk30.red(` \u{1F5D1} Removed ${r.id} (${r.name}) \u2014 ${r.reason}`));
13926
+ console.log(chalk31.red(` \u{1F5D1} Removed ${r.id} (${r.name}) \u2014 ${r.reason}`));
13575
13927
  }
13576
13928
  for (const u of reconcileResult.updated) {
13577
- console.log(chalk30.cyan(` \u{1F4DD} Updated ${u.id} ${u.field}: ${u.from} \u2192 ${u.to}`));
13929
+ console.log(chalk31.cyan(` \u{1F4DD} Updated ${u.id} ${u.field}: ${u.from} \u2192 ${u.to}`));
13578
13930
  }
13579
13931
  for (const a of reconcileResult.added) {
13580
- console.log(chalk30.green(` \u2728 Added ${a.id} (${a.name}) \u2014 ${a.file} (${a.type})`));
13932
+ console.log(chalk31.green(` \u2728 Added ${a.id} (${a.name}) \u2014 ${a.file} (${a.type})`));
13581
13933
  }
13582
13934
  for (const w of reconcileResult.warnings) {
13583
- console.log(chalk30.yellow(` \u26A0 ${w.message}`));
13584
- console.log(chalk30.dim(` ${w.suggestion}`));
13935
+ console.log(chalk31.yellow(` \u26A0 ${w.message}`));
13936
+ console.log(chalk31.dim(` ${w.suggestion}`));
13585
13937
  }
13586
13938
  if (reconcileResult.removed.length === 0 && reconcileResult.updated.length === 0 && reconcileResult.added.length === 0 && reconcileResult.warnings.length === 0) {
13587
- console.log(chalk30.gray(" All components consistent \u2713"));
13939
+ console.log(chalk31.gray(" All components consistent \u2713"));
13588
13940
  }
13589
13941
  }
13590
13942
  if (doPatterns && Object.keys(stylePatterns).length > 0) {
13591
13943
  console.log("");
13592
- console.log(chalk30.blue("\u{1F4D0} Style Patterns:"));
13593
- if (stylePatterns.card) console.log(chalk30.gray(` Cards: ${stylePatterns.card.slice(0, 80)}`));
13594
- if (stylePatterns.section) console.log(chalk30.gray(` Sections: ${stylePatterns.section}`));
13595
- if (stylePatterns.terminal) console.log(chalk30.gray(` Terminal: ${stylePatterns.terminal.slice(0, 80)}`));
13596
- if (stylePatterns.iconContainer) console.log(chalk30.gray(` Icons: ${stylePatterns.iconContainer.slice(0, 80)}`));
13944
+ console.log(chalk31.blue("\u{1F4D0} Style Patterns:"));
13945
+ if (stylePatterns.card) console.log(chalk31.gray(` Cards: ${stylePatterns.card.slice(0, 80)}`));
13946
+ if (stylePatterns.section) console.log(chalk31.gray(` Sections: ${stylePatterns.section}`));
13947
+ if (stylePatterns.terminal) console.log(chalk31.gray(` Terminal: ${stylePatterns.terminal.slice(0, 80)}`));
13948
+ if (stylePatterns.iconContainer) console.log(chalk31.gray(` Icons: ${stylePatterns.iconContainer.slice(0, 80)}`));
13597
13949
  if (stylePatterns.heroHeadline)
13598
- console.log(chalk30.gray(` Hero headline: ${stylePatterns.heroHeadline.slice(0, 80)}`));
13950
+ console.log(chalk31.gray(` Hero headline: ${stylePatterns.heroHeadline.slice(0, 80)}`));
13599
13951
  if (stylePatterns.sectionTitle)
13600
- console.log(chalk30.gray(` Section title: ${stylePatterns.sectionTitle.slice(0, 80)}`));
13952
+ console.log(chalk31.gray(` Section title: ${stylePatterns.sectionTitle.slice(0, 80)}`));
13601
13953
  }
13602
13954
  const tokenUsage = extractActualTokenUsage(allPageCode);
13603
13955
  if (tokenUsage.colors.length > 0) {
13604
13956
  console.log("");
13605
- console.log(chalk30.blue("\u{1F3F7}\uFE0F Actual token usage (from classNames):"));
13957
+ console.log(chalk31.blue("\u{1F3F7}\uFE0F Actual token usage (from classNames):"));
13606
13958
  console.log(
13607
- chalk30.gray(
13959
+ chalk31.gray(
13608
13960
  ` Colors: ${tokenUsage.colors.slice(0, 12).join(", ")}${tokenUsage.colors.length > 12 ? ` (+${tokenUsage.colors.length - 12})` : ""}`
13609
13961
  )
13610
13962
  );
13611
13963
  console.log(
13612
- chalk30.gray(
13964
+ chalk31.gray(
13613
13965
  ` Typography: ${tokenUsage.typography.slice(0, 8).join(", ")}${tokenUsage.typography.length > 8 ? ` (+${tokenUsage.typography.length - 8})` : ""}`
13614
13966
  )
13615
13967
  );
13616
- console.log(chalk30.gray(` Radius: ${tokenUsage.borderRadius.join(", ")}`));
13968
+ console.log(chalk31.gray(` Radius: ${tokenUsage.borderRadius.join(", ")}`));
13617
13969
  }
13618
13970
  const reusable = extractReusablePatterns(allPageCode);
13619
13971
  if (reusable.length > 0) {
13620
13972
  console.log("");
13621
- console.log(chalk30.blue(`\u{1F501} Repeating patterns (${reusable.length} \u2014 potential reusable components):`));
13973
+ console.log(chalk31.blue(`\u{1F501} Repeating patterns (${reusable.length} \u2014 potential reusable components):`));
13622
13974
  for (const p of reusable.slice(0, 5)) {
13623
- console.log(chalk30.gray(` \xD7${p.count}: ${p.sample}${p.sample.length < p.pattern.length ? "..." : ""}`));
13975
+ console.log(chalk31.gray(` \xD7${p.count}: ${p.sample}${p.sample.length < p.pattern.length ? "..." : ""}`));
13624
13976
  }
13625
13977
  }
13626
13978
  console.log("");
13627
13979
  if (!dryRun) {
13628
- console.log(chalk30.cyan(" Open /design-system in the app to see the updated view."));
13980
+ console.log(chalk31.cyan(" Open /design-system in the app to see the updated view."));
13629
13981
  }
13630
13982
  console.log("");
13631
13983
  } catch (err) {
@@ -13636,7 +13988,7 @@ async function syncCommand(options = {}) {
13636
13988
  }
13637
13989
 
13638
13990
  // src/commands/migrate.ts
13639
- import chalk31 from "chalk";
13991
+ import chalk32 from "chalk";
13640
13992
  import ora10 from "ora";
13641
13993
  import { existsSync as existsSync27, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync12, readFileSync as readFileSync19, readdirSync as readdirSync9 } from "fs";
13642
13994
  import { join as join21 } from "path";
@@ -13713,13 +14065,13 @@ async function migrateAction(options) {
13713
14065
  }
13714
14066
  const guard = guardPath(projectRoot);
13715
14067
  if (existsSync27(guard)) {
13716
- console.log(chalk31.yellow("A migration is already in progress."));
13717
- console.log(chalk31.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
14068
+ console.log(chalk32.yellow("A migration is already in progress."));
14069
+ console.log(chalk32.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
13718
14070
  return;
13719
14071
  }
13720
14072
  const uiDir = join21(projectRoot, "components", "ui");
13721
14073
  if (!existsSync27(uiDir)) {
13722
- console.log(chalk31.yellow("No components/ui directory found. Nothing to migrate."));
14074
+ console.log(chalk32.yellow("No components/ui directory found. Nothing to migrate."));
13723
14075
  return;
13724
14076
  }
13725
14077
  const provider = getComponentProvider();
@@ -13727,16 +14079,16 @@ async function migrateAction(options) {
13727
14079
  const files = readdirSync9(uiDir).filter((f) => f.endsWith(".tsx"));
13728
14080
  const migratable = files.map((f) => f.replace(".tsx", "")).filter((id) => managedIds.has(id));
13729
14081
  if (migratable.length === 0) {
13730
- console.log(chalk31.green("All components are already up to date."));
14082
+ console.log(chalk32.green("All components are already up to date."));
13731
14083
  return;
13732
14084
  }
13733
- console.log(chalk31.cyan(`
14085
+ console.log(chalk32.cyan(`
13734
14086
  Found ${migratable.length} component(s) to migrate:`));
13735
14087
  for (const id of migratable) {
13736
- console.log(chalk31.dim(` - ${id}`));
14088
+ console.log(chalk32.dim(` - ${id}`));
13737
14089
  }
13738
14090
  if (options.dryRun) {
13739
- console.log(chalk31.yellow("\n[dry-run] No changes applied."));
14091
+ console.log(chalk32.yellow("\n[dry-run] No changes applied."));
13740
14092
  return;
13741
14093
  }
13742
14094
  const spinner = ora10("Migrating components...").start();
@@ -13753,12 +14105,12 @@ Found ${migratable.length} component(s) to migrate:`));
13753
14105
  if (result.success) {
13754
14106
  migrated++;
13755
14107
  } else {
13756
- console.warn(chalk31.yellow(` \u26A0 Failed to migrate ${id}`));
14108
+ console.warn(chalk32.yellow(` \u26A0 Failed to migrate ${id}`));
13757
14109
  }
13758
14110
  }
13759
14111
  clearGuard(projectRoot);
13760
14112
  spinner.succeed(`Migrated ${migrated}/${migratable.length} components to real shadcn/ui`);
13761
- console.log(chalk31.dim(` Backup saved to: ${backup}`));
14113
+ console.log(chalk32.dim(` Backup saved to: ${backup}`));
13762
14114
  } catch (err) {
13763
14115
  spinner.fail("Migration failed \u2014 rolling back");
13764
14116
  rollback(projectRoot);
@@ -13770,7 +14122,7 @@ Found ${migratable.length} component(s) to migrate:`));
13770
14122
  import { existsSync as existsSync28, mkdirSync as mkdirSync9, readFileSync as readFileSync20, writeFileSync as writeFileSync13 } from "fs";
13771
14123
  import { join as join22 } from "path";
13772
14124
  import { homedir } from "os";
13773
- import chalk32 from "chalk";
14125
+ import chalk33 from "chalk";
13774
14126
  import { CLI_VERSION as CLI_VERSION5 } from "@getcoherent/core";
13775
14127
  var DEBUG5 = process.env.COHERENT_DEBUG === "1";
13776
14128
  var PACKAGE_NAME = "@getcoherent/cli";
@@ -13841,8 +14193,8 @@ async function checkForUpdates() {
13841
14193
  }
13842
14194
  function printUpdateNotice(latest) {
13843
14195
  console.log(
13844
- chalk32.yellow(`
13845
- \u2B06 Update available: v${CLI_VERSION5} \u2192 v${latest}`) + chalk32.dim(`
14196
+ chalk33.yellow(`
14197
+ \u2B06 Update available: v${CLI_VERSION5} \u2192 v${latest}`) + chalk33.dim(`
13846
14198
  Run: npm update -g ${PACKAGE_NAME}
13847
14199
  `)
13848
14200
  );