@decantr/cli 1.7.4 → 1.7.6

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.
@@ -1,22 +1,38 @@
1
1
  import {
2
2
  RegistryClient,
3
+ collectPatternIdsFromItems,
3
4
  composeArchetypes,
4
5
  composeSections,
5
6
  deriveTransitions,
6
7
  deriveZones,
7
8
  generateTopologySection,
9
+ mapRegistryArchetypeToArchetypeData,
10
+ mapRegistryPatternToPatternSpecSummary,
11
+ mapRegistryThemeToThemeData,
8
12
  refreshDerivedFiles,
9
13
  scaffoldMinimal,
10
14
  scaffoldProject,
11
- syncRegistry
12
- } from "./chunk-XKXUVNUQ.js";
15
+ syncRegistry,
16
+ writeExecutionPackBundleArtifacts
17
+ } from "./chunk-H4H3IQJK.js";
18
+ import {
19
+ buildGuardRegistryContext
20
+ } from "./chunk-KUDAVJOR.js";
13
21
 
14
22
  // src/index.ts
15
- import { readFileSync as readFileSync15, existsSync as existsSync23, readdirSync as readdirSync6 } from "fs";
16
- import { join as join23, dirname as dirname2 } from "path";
17
- import { fileURLToPath } from "url";
23
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync13, existsSync as existsSync24, readdirSync as readdirSync6 } from "fs";
24
+ import { basename, join as join24, dirname as dirname2, isAbsolute, resolve as resolve3 } from "path";
25
+ import { fileURLToPath as fileURLToPath2 } from "url";
18
26
  import { validateEssence as validateEssence2, evaluateGuard, isV3 as isV36 } from "@decantr/essence-spec";
19
- import { RegistryAPIClient as RegistryAPIClient3 } from "@decantr/registry";
27
+ import {
28
+ RegistryAPIClient as RegistryAPIClient3,
29
+ CONTENT_TYPES as GET_CONTENT_TYPES,
30
+ API_CONTENT_TYPES as LIST_CONTENT_TYPES,
31
+ CONTENT_TYPE_TO_API_CONTENT_TYPE as CONTENT_TYPE_TO_API_CONTENT_TYPE3,
32
+ isContentType as isGetContentType,
33
+ isApiContentType,
34
+ isContentIntelligenceSource
35
+ } from "@decantr/registry";
20
36
 
21
37
  // src/detect.ts
22
38
  import { existsSync, readFileSync } from "fs";
@@ -165,10 +181,10 @@ var CYAN = "\x1B[36m";
165
181
  function ask(question, defaultValue) {
166
182
  const rl = createInterface({ input: process.stdin, output: process.stdout });
167
183
  const prompt = defaultValue ? `${question} ${DIM}(${defaultValue})${RESET}: ` : `${question}: `;
168
- return new Promise((resolve2) => {
184
+ return new Promise((resolve4) => {
169
185
  rl.question(prompt, (answer) => {
170
186
  rl.close();
171
- resolve2(answer.trim() || defaultValue || "");
187
+ resolve4(answer.trim() || defaultValue || "");
172
188
  });
173
189
  });
174
190
  }
@@ -361,7 +377,7 @@ function mergeWithDefaults(flags, detected) {
361
377
  }
362
378
  async function runSimplifiedInit(blueprints) {
363
379
  const rl = createInterface({ input: process.stdin, output: process.stdout });
364
- const question = (q) => new Promise((resolve2) => rl.question(q, resolve2));
380
+ const question = (q) => new Promise((resolve4) => rl.question(q, resolve4));
365
381
  console.log("\n? What blueprint would you like to scaffold?\n");
366
382
  console.log(" 1. Decantr default (recommended)");
367
383
  console.log(" 2. Search registry...\n");
@@ -399,11 +415,12 @@ import { join as join2 } from "path";
399
415
  // src/theme-templates.ts
400
416
  function getThemeSkeleton(id, name) {
401
417
  return {
402
- $schema: "https://decantr.ai/schemas/style-metadata.v1.json",
418
+ $schema: "https://decantr.ai/schemas/theme.v1.json",
403
419
  id,
404
420
  name,
405
- description: "",
421
+ description: `Custom theme starter for ${name}. Replace the seed palette, personality, and treatments before publishing.`,
406
422
  tags: [],
423
+ personality: "",
407
424
  seed: {
408
425
  primary: "#6366F1",
409
426
  secondary: "#8B5CF6",
@@ -432,10 +449,12 @@ decantr theme create mytheme
432
449
 
433
450
  | Field | Required | Description |
434
451
  |-------|----------|-------------|
452
+ | $schema | Yes | Must be \`https://decantr.ai/schemas/theme.v1.json\` |
435
453
  | id | Yes | Unique identifier (matches filename) |
436
454
  | name | Yes | Display name |
437
- | description | No | Brief description |
455
+ | description | Yes | Brief description for humans and LLMs |
438
456
  | tags | No | Searchable tags |
457
+ | personality | No | Short visual summary for LLMs |
439
458
  | seed | Yes | Core colors: primary, secondary, accent, background |
440
459
  | palette | No | Extended color palette |
441
460
  | modes | Yes | Supported modes: ["light"], ["dark"], or both |
@@ -450,7 +469,7 @@ In \`decantr.essence.json\`:
450
469
  \`\`\`json
451
470
  {
452
471
  "theme": {
453
- "style": "custom:mytheme",
472
+ "id": "custom:mytheme",
454
473
  "mode": "dark"
455
474
  }
456
475
  }
@@ -473,10 +492,11 @@ decantr get theme auradecantism
473
492
  }
474
493
 
475
494
  // src/theme-commands.ts
476
- var REQUIRED_FIELDS = ["id", "name", "seed", "modes", "shapes", "decantr_compat", "source"];
495
+ var REQUIRED_FIELDS = ["$schema", "id", "name", "description", "seed", "modes", "shapes", "decantr_compat", "source"];
477
496
  var REQUIRED_SEED = ["primary", "secondary", "accent", "background"];
478
497
  var VALID_MODES = ["light", "dark"];
479
498
  var VALID_SHAPES = ["sharp", "rounded", "pill"];
499
+ var THEME_SCHEMA_URL = "https://decantr.ai/schemas/theme.v1.json";
480
500
  function validateCustomTheme(theme) {
481
501
  const errors = [];
482
502
  for (const field of REQUIRED_FIELDS) {
@@ -484,6 +504,15 @@ function validateCustomTheme(theme) {
484
504
  errors.push(`Missing required field: ${field}`);
485
505
  }
486
506
  }
507
+ for (const field of ["id", "name", "description"]) {
508
+ const value = theme[field];
509
+ if (value !== void 0 && (typeof value !== "string" || value.trim().length === 0)) {
510
+ errors.push(`Field "${field}" must be a non-empty string`);
511
+ }
512
+ }
513
+ if ("$schema" in theme && theme.$schema !== THEME_SCHEMA_URL) {
514
+ errors.push(`Invalid $schema "${String(theme.$schema)}" - must be "${THEME_SCHEMA_URL}"`);
515
+ }
487
516
  if (theme.seed && typeof theme.seed === "object") {
488
517
  const seed = theme.seed;
489
518
  for (const color of REQUIRED_SEED) {
@@ -643,24 +672,21 @@ function getApiKeyOrToken() {
643
672
  return creds.api_key || creds.access_token || null;
644
673
  }
645
674
 
675
+ // src/index.ts
676
+ import {
677
+ auditProject,
678
+ critiqueFile as critiqueProjectFile
679
+ } from "@decantr/verifier";
680
+
646
681
  // src/commands/publish.ts
647
682
  import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
648
683
  import { join as join4 } from "path";
649
- import { RegistryAPIClient } from "@decantr/registry";
650
- var PLURAL_TO_SINGULAR = {
651
- patterns: "pattern",
652
- themes: "theme",
653
- blueprints: "blueprint",
654
- archetypes: "archetype",
655
- shells: "shell"
656
- };
657
- var SINGULAR_TO_PLURAL = {
658
- pattern: "patterns",
659
- theme: "themes",
660
- blueprint: "blueprints",
661
- archetype: "archetypes",
662
- shell: "shells"
663
- };
684
+ import {
685
+ RegistryAPIClient,
686
+ RegistryAPIError,
687
+ API_CONTENT_TYPE_TO_CONTENT_TYPE,
688
+ CONTENT_TYPE_TO_API_CONTENT_TYPE
689
+ } from "@decantr/registry";
664
690
  async function cmdPublish(type, name, projectRoot = process.cwd()) {
665
691
  const token = getApiKeyOrToken();
666
692
  if (!token) {
@@ -668,8 +694,8 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
668
694
  process.exitCode = 1;
669
695
  return;
670
696
  }
671
- const singularType = PLURAL_TO_SINGULAR[type] || type;
672
- const pluralType = SINGULAR_TO_PLURAL[type] || SINGULAR_TO_PLURAL[singularType] || `${type}s`;
697
+ const singularType = API_CONTENT_TYPE_TO_CONTENT_TYPE[type] || type;
698
+ const pluralType = CONTENT_TYPE_TO_API_CONTENT_TYPE[type] || CONTENT_TYPE_TO_API_CONTENT_TYPE[singularType] || `${type}s`;
673
699
  const customPath = join4(projectRoot, ".decantr", "custom", pluralType, `${name}.json`);
674
700
  if (!existsSync4(customPath)) {
675
701
  console.error(`Custom ${singularType} "${name}" not found at ${customPath}`);
@@ -700,7 +726,18 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
700
726
  console.log(`Published ${singularType}/${name} to @community`);
701
727
  console.log(`Status: ${result.status}`);
702
728
  } catch (err) {
703
- console.error(`Failed to publish: ${err.message}`);
729
+ if (err instanceof RegistryAPIError) {
730
+ console.error(`Failed to publish: ${err.message}`);
731
+ const details = err.details;
732
+ if (Array.isArray(details?.validationErrors) && details.validationErrors.length > 0) {
733
+ console.error("Validation errors:");
734
+ for (const validationError of details.validationErrors) {
735
+ console.error(` - ${String(validationError)}`);
736
+ }
737
+ }
738
+ } else {
739
+ console.error(`Failed to publish: ${err.message}`);
740
+ }
704
741
  process.exitCode = 1;
705
742
  }
706
743
  }
@@ -708,33 +745,110 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
708
745
  // src/commands/create.ts
709
746
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
710
747
  import { join as join5 } from "path";
711
- var CONTENT_TYPES = ["pattern", "theme", "blueprint", "archetype", "shell"];
712
- var PLURAL = {
713
- pattern: "patterns",
714
- theme: "themes",
715
- blueprint: "blueprints",
716
- archetype: "archetypes",
717
- shell: "shells"
748
+ import {
749
+ CONTENT_TYPES,
750
+ CONTENT_TYPE_TO_API_CONTENT_TYPE as CONTENT_TYPE_TO_API_CONTENT_TYPE2
751
+ } from "@decantr/registry";
752
+ var PLURAL = CONTENT_TYPE_TO_API_CONTENT_TYPE2;
753
+ var SCHEMA_URLS = {
754
+ pattern: "https://decantr.ai/schemas/pattern.v2.json",
755
+ theme: "https://decantr.ai/schemas/theme.v1.json",
756
+ blueprint: "https://decantr.ai/schemas/blueprint.v1.json",
757
+ archetype: "https://decantr.ai/schemas/archetype.v2.json",
758
+ shell: "https://decantr.ai/schemas/shell.v1.json"
718
759
  };
760
+ function humanizeId(id) {
761
+ return id.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
762
+ }
719
763
  function getSkeleton(type, id, name) {
720
764
  const base = {
765
+ $schema: SCHEMA_URLS[type],
721
766
  id,
722
767
  name,
723
- description: "",
724
- version: "1.0.0",
725
- source: "custom"
768
+ version: "1.0.0"
726
769
  };
727
770
  switch (type) {
728
771
  case "pattern":
729
- return { ...base, components: [], presets: {}, layout: {} };
772
+ return {
773
+ ...base,
774
+ description: `Starter pattern for ${name}. Replace the preset layout, slots, and code examples before publishing.`,
775
+ tags: [],
776
+ components: [],
777
+ default_preset: "standard",
778
+ presets: {
779
+ standard: {
780
+ description: "Default starter preset. Replace the layout atoms and slots with the real structure for this pattern.",
781
+ layout: {
782
+ layout: "stack",
783
+ atoms: "_flex _col _gap4"
784
+ }
785
+ }
786
+ }
787
+ };
730
788
  case "theme":
731
- return { ...base, seed: { primary: "#6500C6", secondary: "#0AF3EB", accent: "#F58882", background: "#0D0D1A" }, modes: ["dark"], shapes: ["rounded"] };
789
+ return getThemeSkeleton(id, name);
732
790
  case "blueprint":
733
- return { ...base, compose: [], theme: {}, personality: [] };
791
+ return {
792
+ ...base,
793
+ description: `Starter blueprint for ${name}. Replace the theme, routes, and composed archetypes before publishing.`,
794
+ tags: [],
795
+ compose: ["starter-home"],
796
+ theme: {
797
+ id: "carbon",
798
+ mode: "dark",
799
+ shape: "rounded"
800
+ },
801
+ personality: "Calm, production-ready starter blueprint. Tailor the voice, routes, and composed archetypes to your product.",
802
+ routes: {
803
+ "/": {
804
+ page: "home",
805
+ shell: "top-nav-main",
806
+ archetype: "starter-home"
807
+ }
808
+ },
809
+ overrides: {
810
+ features_add: [],
811
+ features_remove: [],
812
+ pages: {},
813
+ pages_remove: []
814
+ }
815
+ };
734
816
  case "archetype":
735
- return { ...base, pages: [], features: [], suggested_theme: "" };
817
+ return {
818
+ ...base,
819
+ role: "primary",
820
+ description: `Starter archetype for ${name}. Replace the sample page, pattern layout, and features before publishing.`,
821
+ tags: ["starter"],
822
+ pages: [
823
+ {
824
+ id: "home",
825
+ description: "Starter page for your primary flow.",
826
+ shell: "top-nav-main",
827
+ patterns: [],
828
+ default_layout: []
829
+ }
830
+ ],
831
+ features: [],
832
+ suggested_theme: {
833
+ ids: ["carbon"],
834
+ modes: ["dark"],
835
+ shapes: ["rounded"]
836
+ }
837
+ };
736
838
  case "shell":
737
- return { ...base, regions: [], layout: "sidebar-main" };
839
+ return {
840
+ ...base,
841
+ description: `Starter shell for ${name}. Replace the regions, layout guidance, and internal structure before publishing.`,
842
+ layout: "stack",
843
+ atoms: "_flex _col _h[100vh]",
844
+ config: {
845
+ regions: ["header", "body"]
846
+ },
847
+ guidance: {
848
+ section_label_treatment: "d-label",
849
+ section_density: "comfortable"
850
+ }
851
+ };
738
852
  }
739
853
  }
740
854
  function cmdCreate(type, name, projectRoot = process.cwd()) {
@@ -743,7 +857,8 @@ function cmdCreate(type, name, projectRoot = process.cwd()) {
743
857
  process.exitCode = 1;
744
858
  return;
745
859
  }
746
- const plural = PLURAL[type];
860
+ const contentType = type;
861
+ const plural = PLURAL[contentType];
747
862
  const customDir = join5(projectRoot, ".decantr", "custom", plural);
748
863
  const filePath = join5(customDir, `${name}.json`);
749
864
  if (existsSync5(filePath)) {
@@ -752,7 +867,7 @@ function cmdCreate(type, name, projectRoot = process.cwd()) {
752
867
  return;
753
868
  }
754
869
  mkdirSync3(customDir, { recursive: true });
755
- const skeleton = getSkeleton(type, name, name.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
870
+ const skeleton = getSkeleton(contentType, name, humanizeId(name));
756
871
  writeFileSync3(filePath, JSON.stringify(skeleton, null, 2));
757
872
  console.log(`Created ${type} "${name}" at ${filePath}`);
758
873
  console.log(`Edit it, then publish with: decantr publish ${type} ${name}`);
@@ -1059,15 +1174,14 @@ async function cmdAddSection(archetypeId, args, projectRoot = process.cwd()) {
1059
1174
  process.exitCode = 1;
1060
1175
  return;
1061
1176
  }
1062
- const raw = result.data;
1063
- const inner = raw.data ?? raw;
1177
+ const archetype = result.data;
1064
1178
  const newSection = {
1065
- id: inner.id || archetypeId,
1066
- role: inner.role || "auxiliary",
1067
- shell: inner.pages?.[0]?.shell || essence.blueprint.shell || "top-nav-main",
1068
- features: inner.features || [],
1069
- description: inner.description || "",
1070
- pages: (inner.pages || []).map((p) => ({
1179
+ id: archetype.id || archetypeId,
1180
+ role: archetype.role || "auxiliary",
1181
+ shell: archetype.pages?.[0]?.shell || essence.blueprint.shell || "top-nav-main",
1182
+ features: archetype.features || [],
1183
+ description: archetype.description || "",
1184
+ pages: (archetype.pages || []).map((p) => ({
1071
1185
  id: p.id,
1072
1186
  layout: p.default_layout?.length ? p.default_layout : ["hero"]
1073
1187
  }))
@@ -1332,6 +1446,8 @@ var RED6 = "\x1B[31m";
1332
1446
  var YELLOW4 = "\x1B[33m";
1333
1447
  var DIM7 = "\x1B[2m";
1334
1448
  var RESET7 = "\x1B[0m";
1449
+ var VALID_THEME_SHAPES = ["sharp", "rounded", "pill"];
1450
+ var VALID_THEME_MODES = ["light", "dark", "auto"];
1335
1451
  async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
1336
1452
  if (!themeName) {
1337
1453
  console.error(`${RED6}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET7}`);
@@ -1372,10 +1488,18 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
1372
1488
  mode = args[++i];
1373
1489
  }
1374
1490
  }
1375
- const oldThemeId = essence.dna.theme.id || essence.dna.theme.style;
1491
+ if (shape && !VALID_THEME_SHAPES.includes(shape)) {
1492
+ console.error(`${RED6}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET7}`);
1493
+ process.exitCode = 1;
1494
+ return;
1495
+ }
1496
+ if (mode && !VALID_THEME_MODES.includes(mode)) {
1497
+ console.error(`${RED6}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET7}`);
1498
+ process.exitCode = 1;
1499
+ return;
1500
+ }
1501
+ const oldThemeId = essence.dna.theme.id;
1376
1502
  essence.dna.theme.id = themeName;
1377
- delete essence.dna.theme.style;
1378
- delete essence.dna.theme.recipe;
1379
1503
  if (shape) {
1380
1504
  essence.dna.theme.shape = shape;
1381
1505
  }
@@ -1388,13 +1512,11 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
1388
1512
  try {
1389
1513
  const themeResult = await registryClient.fetchTheme(themeName);
1390
1514
  if (themeResult?.data) {
1391
- const raw = themeResult.data;
1392
- const inner = raw.data ?? raw;
1393
- if (inner.radius) {
1515
+ if (themeResult.data.radius) {
1394
1516
  essence.dna.radius = {
1395
1517
  ...essence.dna.radius,
1396
- philosophy: inner.radius.philosophy || essence.dna.radius.philosophy,
1397
- base: inner.radius.base ?? essence.dna.radius.base
1518
+ philosophy: themeResult.data.radius.philosophy || essence.dna.radius.philosophy,
1519
+ base: themeResult.data.radius.base ?? essence.dna.radius.base
1398
1520
  };
1399
1521
  }
1400
1522
  }
@@ -2357,7 +2479,7 @@ async function resolveTheme(intent, registryClient) {
2357
2479
  }).sort((a, b) => b.score - a.score);
2358
2480
  if (scored[0] && scored[0].score > 0) {
2359
2481
  const mode2 = intent.themeHints.includes("light") ? "light" : intent.themeHints.includes("dark") ? "dark" : scored[0].modes?.includes("dark") ? "dark" : "light";
2360
- return { style: scored[0].id, mode: mode2 };
2482
+ return { id: scored[0].id, mode: mode2 };
2361
2483
  }
2362
2484
  }
2363
2485
  } catch {
@@ -2365,14 +2487,14 @@ async function resolveTheme(intent, registryClient) {
2365
2487
  }
2366
2488
  let mode = "dark";
2367
2489
  if (hints.includes("light")) mode = "light";
2368
- if (hints.includes("neon") || hints.includes("glass")) return { style: "obsidianite", mode };
2369
- if (hints.includes("warm") || hints.includes("elegant")) return { style: "aurealis", mode };
2370
- if (hints.includes("cool") || hints.includes("minimal")) return { style: "glacialis", mode };
2371
- if (hints.includes("brutalist")) return { style: "ferrocrete", mode };
2372
- if (hints.includes("corporate")) return { style: "luminarum", mode };
2373
- if (hints.includes("playful")) return { style: "solstice", mode };
2374
- if (hints.includes("retro")) return { style: "oxidian", mode };
2375
- return { style: "luminarum", mode };
2490
+ if (hints.includes("neon") || hints.includes("glass")) return { id: "obsidianite", mode };
2491
+ if (hints.includes("warm") || hints.includes("elegant")) return { id: "aurealis", mode };
2492
+ if (hints.includes("cool") || hints.includes("minimal")) return { id: "glacialis", mode };
2493
+ if (hints.includes("brutalist")) return { id: "ferrocrete", mode };
2494
+ if (hints.includes("corporate")) return { id: "luminarum", mode };
2495
+ if (hints.includes("playful")) return { id: "solstice", mode };
2496
+ if (hints.includes("retro")) return { id: "oxidian", mode };
2497
+ return { id: "luminarum", mode };
2376
2498
  }
2377
2499
  function buildPersonality(intent) {
2378
2500
  if (intent.personalityHints.length > 0) {
@@ -2464,8 +2586,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2464
2586
  }
2465
2587
  const bpResult = await registryClient.fetchBlueprint(best.id);
2466
2588
  if (bpResult) {
2467
- const rawBp = bpResult.data;
2468
- blueprintData = rawBp.data ?? rawBp;
2589
+ blueprintData = bpResult.data;
2469
2590
  }
2470
2591
  } else {
2471
2592
  console.log(dim(" No strong blueprint match found. Using archetype-based scaffold."));
@@ -2478,7 +2599,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2478
2599
  const initOptions = {
2479
2600
  blueprint: matchedBlueprint,
2480
2601
  archetype: intent.archetype || blueprintData?.compose?.[0]?.archetype || blueprintData?.compose?.[0] || "dashboard-analytics",
2481
- theme: themeResolved.style,
2602
+ theme: themeResolved.id,
2482
2603
  mode: themeResolved.mode,
2483
2604
  shape: "rounded",
2484
2605
  target: "react",
@@ -2490,7 +2611,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2490
2611
  existing: false
2491
2612
  };
2492
2613
  if (blueprintData) {
2493
- if (blueprintData.theme?.id || blueprintData.theme?.style) initOptions.theme = blueprintData.theme.id || blueprintData.theme.style;
2614
+ if (blueprintData.theme?.id) initOptions.theme = blueprintData.theme.id;
2494
2615
  if (blueprintData.theme?.mode) initOptions.mode = blueprintData.theme.mode;
2495
2616
  if (blueprintData.theme?.shape) initOptions.shape = blueprintData.theme.shape;
2496
2617
  if (blueprintData.personality) {
@@ -2541,8 +2662,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2541
2662
  const id = typeof entry === "string" ? entry : entry.archetype;
2542
2663
  const result2 = await registryClient.fetchArchetype(id);
2543
2664
  if (result2) {
2544
- const raw = result2.data;
2545
- archetypeMap.set(id, raw.data ?? raw);
2665
+ archetypeMap.set(id, mapRegistryArchetypeToArchetypeData(result2.data));
2546
2666
  } else {
2547
2667
  archetypeMap.set(id, null);
2548
2668
  }
@@ -2582,9 +2702,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2582
2702
  if (page.patterns) {
2583
2703
  for (const ref of page.patterns) allPatternIds.add(ref.pattern);
2584
2704
  }
2585
- for (const item of page.layout) {
2586
- if (typeof item === "string") allPatternIds.add(item);
2587
- }
2705
+ for (const patternId of collectPatternIdsFromItems(page.layout)) allPatternIds.add(patternId);
2588
2706
  }
2589
2707
  }
2590
2708
  patternSpecs = {};
@@ -2592,15 +2710,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2592
2710
  try {
2593
2711
  const result2 = await registryClient.fetchPattern(pid);
2594
2712
  if (result2) {
2595
- const raw = result2.data;
2596
- const inner = raw.data ?? raw;
2597
- const defaultPreset = inner.default_preset || "standard";
2598
- const preset = inner.presets?.[defaultPreset];
2599
- patternSpecs[pid] = {
2600
- description: inner.description || "",
2601
- components: inner.components || [],
2602
- slots: preset?.layout?.slots || {}
2603
- };
2713
+ patternSpecs[pid] = mapRegistryPatternToPatternSpecSummary(result2.data, void 0, false);
2604
2714
  }
2605
2715
  } catch {
2606
2716
  }
@@ -2610,7 +2720,7 @@ async function cmdMagic(prompt, projectRoot, options) {
2610
2720
  const arcId = typeof entry === "string" ? entry : entry.archetype;
2611
2721
  const archData = archetypeMap.get(arcId);
2612
2722
  if (archData) {
2613
- const explicitRole = typeof entry === "object" && "role" in entry ? entry.role : void 0;
2723
+ const explicitRole = typeof entry === "string" ? void 0 : entry.role;
2614
2724
  zoneInputs.push({
2615
2725
  archetypeId: arcId,
2616
2726
  role: explicitRole || archData.role || "auxiliary",
@@ -2647,31 +2757,13 @@ async function cmdMagic(prompt, projectRoot, options) {
2647
2757
  } else if (intent.archetype && apiAvailable) {
2648
2758
  const archResult = await registryClient.fetchArchetype(initOptions.archetype);
2649
2759
  if (archResult) {
2650
- const raw = archResult.data;
2651
- archetypeData = raw.data ?? raw;
2760
+ archetypeData = mapRegistryArchetypeToArchetypeData(archResult.data);
2652
2761
  }
2653
2762
  }
2654
2763
  if (apiAvailable && initOptions.theme) {
2655
2764
  const themeResult = await registryClient.fetchTheme(initOptions.theme);
2656
2765
  if (themeResult) {
2657
- const rawTheme = themeResult.data;
2658
- const theme = rawTheme.data ?? rawTheme;
2659
- themeData = {
2660
- seed: theme.seed,
2661
- palette: theme.palette,
2662
- tokens: theme.tokens,
2663
- cvd_support: theme.cvd_support,
2664
- typography: theme.typography,
2665
- motion: theme.motion,
2666
- decorators: theme.decorators,
2667
- treatments: theme.treatments,
2668
- spatial: theme.spatial,
2669
- radius: theme.radius,
2670
- shell: theme.shell,
2671
- effects: theme.effects,
2672
- compositions: theme.compositions,
2673
- pattern_preferences: theme.pattern_preferences
2674
- };
2766
+ themeData = mapRegistryThemeToThemeData(themeResult.data);
2675
2767
  }
2676
2768
  }
2677
2769
  const richPersonality = buildRichPersonality(intent, blueprintData, themeData);
@@ -2733,14 +2825,18 @@ async function cmdMagic(prompt, projectRoot, options) {
2733
2825
  }
2734
2826
  console.log(`
2735
2827
  ${GREEN9}${BOLD4}Quality summary:${RESET9}`);
2736
- console.log(` Context files: ${sectionCount} sections + scaffold.md + DECANTR.md`);
2828
+ console.log(` Context files: ${sectionCount} sections + page packs + section packs + scaffold-pack.md + scaffold.md + DECANTR.md`);
2737
2829
  console.log(` CSS: tokens.css + treatments.css + global.css`);
2738
2830
  console.log(` @layer cascade: ${hasLayers ? GREEN9 + "yes" + RESET9 : YELLOW6 + "missing" + RESET9}`);
2739
2831
  console.log("");
2740
2832
  console.log(`${BOLD4} Ready!${RESET9} Next steps:`);
2741
- console.log(` 1. Read ${cyan("DECANTR.md")} to understand the design system`);
2742
- console.log(` 2. Read ${cyan(".decantr/context/scaffold.md")} for the full app overview`);
2743
- console.log(` 3. Start building pages from the route map`);
2833
+ console.log(` 1. Read ${cyan("DECANTR.md")} for guard rules, CSS approach, and workflow`);
2834
+ console.log(` 2. Read ${cyan(".decantr/context/scaffold-pack.md")} first as the primary compiled contract`);
2835
+ console.log(` 3. Read ${cyan(".decantr/context/scaffold.md")} second for broader topology and voice guidance`);
2836
+ console.log(` 4. Read the matching ${cyan(".decantr/context/section-*-pack.md")} and ${cyan(".decantr/context/section-*.md")} files before section work`);
2837
+ console.log(` 5. Read the matching ${cyan(".decantr/context/page-*-pack.md")} file before route work`);
2838
+ console.log(` 6. Build the shell and route structure first, then implement each page`);
2839
+ console.log(` 7. Run ${cyan("decantr check")} and ${cyan("decantr audit")} before you ship`);
2744
2840
  console.log("");
2745
2841
  }
2746
2842
 
@@ -2951,20 +3047,14 @@ function ensureDir(filePath) {
2951
3047
  // src/commands/registry-mirror.ts
2952
3048
  import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync11 } from "fs";
2953
3049
  import { join as join21 } from "path";
2954
- import { RegistryAPIClient as RegistryAPIClient2 } from "@decantr/registry";
3050
+ import { RegistryAPIClient as RegistryAPIClient2, API_CONTENT_TYPES } from "@decantr/registry";
2955
3051
  var GREEN11 = "\x1B[32m";
2956
3052
  var RED9 = "\x1B[31m";
2957
3053
  var DIM11 = "\x1B[2m";
2958
3054
  var CYAN5 = "\x1B[36m";
2959
3055
  var YELLOW7 = "\x1B[33m";
2960
3056
  var RESET11 = "\x1B[0m";
2961
- var ALL_CONTENT_TYPES = [
2962
- "patterns",
2963
- "archetypes",
2964
- "themes",
2965
- "blueprints",
2966
- "shells"
2967
- ];
3057
+ var ALL_CONTENT_TYPES = [...API_CONTENT_TYPES];
2968
3058
  async function cmdRegistryMirror(projectRoot, options = {}) {
2969
3059
  const apiUrl = process.env.DECANTR_API_URL || "https://api.decantr.ai/v1";
2970
3060
  const apiClient = new RegistryAPIClient2({
@@ -3035,9 +3125,58 @@ Mirroring registry content to ${DIM11}.decantr/cache/${RESET11}
3035
3125
  }
3036
3126
 
3037
3127
  // src/commands/new-project.ts
3038
- import { existsSync as existsSync22, mkdirSync as mkdirSync7, writeFileSync as writeFileSync12 } from "fs";
3039
- import { join as join22, resolve } from "path";
3128
+ import { existsSync as existsSync23, mkdirSync as mkdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "fs";
3129
+ import { join as join23, resolve as resolve2 } from "path";
3040
3130
  import { execSync } from "child_process";
3131
+ import { fileURLToPath } from "url";
3132
+
3133
+ // src/offline-content.ts
3134
+ import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync7 } from "fs";
3135
+ import { join as join22, resolve } from "path";
3136
+ var CONTENT_TYPES2 = ["archetypes", "blueprints", "patterns", "themes", "shells"];
3137
+ function copyIfExists(source, target) {
3138
+ if (!existsSync22(source)) return false;
3139
+ if (resolve(source) === resolve(target)) return true;
3140
+ cpSync(source, target, { recursive: true });
3141
+ return true;
3142
+ }
3143
+ function hydrateContentRoot(projectDir, contentRoot) {
3144
+ if (!existsSync22(contentRoot)) return false;
3145
+ const customRoot = join22(projectDir, ".decantr", "custom");
3146
+ const cacheRoot = join22(projectDir, ".decantr", "cache", "@official");
3147
+ mkdirSync7(customRoot, { recursive: true });
3148
+ mkdirSync7(cacheRoot, { recursive: true });
3149
+ let copiedAny = false;
3150
+ for (const type of CONTENT_TYPES2) {
3151
+ const sourceDir = join22(contentRoot, type);
3152
+ if (!existsSync22(sourceDir)) continue;
3153
+ cpSync(sourceDir, join22(customRoot, type), { recursive: true });
3154
+ cpSync(sourceDir, join22(cacheRoot, type), { recursive: true });
3155
+ copiedAny = true;
3156
+ }
3157
+ return copiedAny;
3158
+ }
3159
+ function seedOfflineRegistry(projectDir, workspaceRoot) {
3160
+ const projectDecantrRoot = join22(projectDir, ".decantr");
3161
+ mkdirSync7(projectDecantrRoot, { recursive: true });
3162
+ const copiedCache = copyIfExists(join22(workspaceRoot, ".decantr", "cache"), join22(projectDecantrRoot, "cache"));
3163
+ const copiedCustom = copyIfExists(join22(workspaceRoot, ".decantr", "custom"), join22(projectDecantrRoot, "custom"));
3164
+ if (copiedCache || copiedCustom) {
3165
+ return { seeded: true, strategy: "workspace-cache" };
3166
+ }
3167
+ const configuredContentRoot = process.env.DECANTR_CONTENT_DIR ? resolve(process.env.DECANTR_CONTENT_DIR) : null;
3168
+ const siblingContentRoot = resolve(workspaceRoot, "..", "decantr-content");
3169
+ const contentRoot = configuredContentRoot && existsSync22(configuredContentRoot) ? configuredContentRoot : siblingContentRoot;
3170
+ if (hydrateContentRoot(projectDir, contentRoot)) {
3171
+ return {
3172
+ seeded: true,
3173
+ strategy: configuredContentRoot && existsSync22(configuredContentRoot) ? "configured-content-root" : "sibling-content-root"
3174
+ };
3175
+ }
3176
+ return { seeded: false, strategy: null };
3177
+ }
3178
+
3179
+ // src/commands/new-project.ts
3041
3180
  var BOLD5 = "\x1B[1m";
3042
3181
  var DIM12 = "\x1B[2m";
3043
3182
  var RESET12 = "\x1B[0m";
@@ -3062,20 +3201,92 @@ function dim2(text) {
3062
3201
  function cyan2(text) {
3063
3202
  return `${CYAN6}${text}${RESET12}`;
3064
3203
  }
3204
+ function detectRoutingMode(projectDir) {
3205
+ try {
3206
+ const essence = JSON.parse(readFileSync15(join23(projectDir, "decantr.essence.json"), "utf-8"));
3207
+ const routing = essence.meta?.platform?.routing;
3208
+ if (routing === "history" || routing === "pathname") {
3209
+ return routing;
3210
+ }
3211
+ return "hash";
3212
+ } catch {
3213
+ return "hash";
3214
+ }
3215
+ }
3216
+ function writeStarterRuntimeFiles(projectDir, title, routingMode) {
3217
+ const srcDir = join23(projectDir, "src");
3218
+ const routerImport = routingMode === "hash" ? "HashRouter" : "BrowserRouter";
3219
+ const mainTsx = `import { StrictMode } from 'react';
3220
+ import { createRoot } from 'react-dom/client';
3221
+ import { ${routerImport} } from 'react-router-dom';
3222
+ import { App } from './App';
3223
+ import './styles/global.css';
3224
+ import './styles/tokens.css';
3225
+ import './styles/treatments.css';
3226
+
3227
+ createRoot(document.getElementById('root')!).render(
3228
+ <StrictMode>
3229
+ <${routerImport}>
3230
+ <App />
3231
+ </${routerImport}>
3232
+ </StrictMode>,
3233
+ );
3234
+ `;
3235
+ writeFileSync12(join23(srcDir, "main.tsx"), mainTsx);
3236
+ const appTsx = `import { css } from '@decantr/css';
3237
+ import { Routes, Route } from 'react-router-dom';
3238
+
3239
+ function WelcomePage() {
3240
+ return (
3241
+ <>
3242
+ <a href="#main-content" className="skip-link">Skip to content</a>
3243
+ <main id="main-content" className={css('_minh[100vh] _flex _col _aic _jcc _p6 _gap4')}>
3244
+ <section className={css('_wfull _mw[42rem]') + ' d-section'} data-density="comfortable">
3245
+ <div className={css('_flex _col _aic _gap4 _textc') + ' d-surface'} data-elevation="raised">
3246
+ <p className="d-label" data-anchor>Decantr starter</p>
3247
+ <h1 className={css('_heading2')}>${title}</h1>
3248
+ <p className={css('_textsm _fgmuted _mw[32rem]')}>
3249
+ Scaffolded with Decantr. Read DECANTR.md and the compiled packs in .decantr/context before building routes.
3250
+ </p>
3251
+ <div className={css('_flex _gap3 _wrap _jcc')}>
3252
+ <span className="d-annotation" data-status="info">Runtime: @decantr/css</span>
3253
+ <span className="d-annotation" data-status="success">Routing: ${routingMode}</span>
3254
+ </div>
3255
+ </div>
3256
+ </section>
3257
+ </main>
3258
+ </>
3259
+ );
3260
+ }
3261
+
3262
+ export function App() {
3263
+ return (
3264
+ <Routes>
3265
+ <Route path="/" element={<WelcomePage />} />
3266
+ </Routes>
3267
+ );
3268
+ }
3269
+ `;
3270
+ writeFileSync12(join23(srcDir, "App.tsx"), appTsx);
3271
+ }
3272
+ function getTargetRoutingMode(target) {
3273
+ return (target || "react").toLowerCase() === "nextjs" ? "pathname" : "hash";
3274
+ }
3065
3275
  async function cmdNewProject(projectName, options) {
3066
- const projectDir = resolve(process.cwd(), projectName);
3276
+ const workspaceRoot = process.cwd();
3277
+ const projectDir = resolve2(workspaceRoot, projectName);
3067
3278
  if (!/^[a-z0-9][a-z0-9._-]*$/i.test(projectName)) {
3068
3279
  console.error(error2("Invalid project name. Use alphanumeric characters, hyphens, dots, or underscores."));
3069
3280
  process.exitCode = 1;
3070
3281
  return;
3071
3282
  }
3072
- if (existsSync22(projectDir)) {
3283
+ if (existsSync23(projectDir)) {
3073
3284
  console.error(error2(`Directory "${projectName}" already exists.`));
3074
3285
  process.exitCode = 1;
3075
3286
  return;
3076
3287
  }
3077
3288
  console.log(heading(`Creating ${projectName}...`));
3078
- mkdirSync7(projectDir, { recursive: true });
3289
+ mkdirSync8(projectDir, { recursive: true });
3079
3290
  console.log(dim2(` Created ${projectName}/`));
3080
3291
  const packageJson = {
3081
3292
  name: projectName,
@@ -3101,7 +3312,7 @@ async function cmdNewProject(projectName, options) {
3101
3312
  "vite": "^6.0.0"
3102
3313
  }
3103
3314
  };
3104
- writeFileSync12(join22(projectDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
3315
+ writeFileSync12(join23(projectDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
3105
3316
  console.log(dim2(" Created package.json"));
3106
3317
  const viteConfig = `import { defineConfig } from 'vite';
3107
3318
  import react from '@vitejs/plugin-react';
@@ -3110,7 +3321,7 @@ export default defineConfig({
3110
3321
  plugins: [react()],
3111
3322
  });
3112
3323
  `;
3113
- writeFileSync12(join22(projectDir, "vite.config.ts"), viteConfig);
3324
+ writeFileSync12(join23(projectDir, "vite.config.ts"), viteConfig);
3114
3325
  console.log(dim2(" Created vite.config.ts"));
3115
3326
  const tsconfig = {
3116
3327
  compilerOptions: {
@@ -3133,7 +3344,7 @@ export default defineConfig({
3133
3344
  },
3134
3345
  include: ["src"]
3135
3346
  };
3136
- writeFileSync12(join22(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
3347
+ writeFileSync12(join23(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
3137
3348
  const tsconfigApp = {
3138
3349
  compilerOptions: {
3139
3350
  tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
@@ -3156,7 +3367,7 @@ export default defineConfig({
3156
3367
  },
3157
3368
  include: ["src"]
3158
3369
  };
3159
- writeFileSync12(join22(projectDir, "tsconfig.app.json"), JSON.stringify(tsconfigApp, null, 2) + "\n");
3370
+ writeFileSync12(join23(projectDir, "tsconfig.app.json"), JSON.stringify(tsconfigApp, null, 2) + "\n");
3160
3371
  console.log(dim2(" Created tsconfig.json"));
3161
3372
  const title = projectName.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
3162
3373
  const indexHtml = `<!doctype html>
@@ -3172,49 +3383,13 @@ export default defineConfig({
3172
3383
  </body>
3173
3384
  </html>
3174
3385
  `;
3175
- writeFileSync12(join22(projectDir, "index.html"), indexHtml);
3386
+ writeFileSync12(join23(projectDir, "index.html"), indexHtml);
3176
3387
  console.log(dim2(" Created index.html"));
3177
- const srcDir = join22(projectDir, "src");
3178
- mkdirSync7(srcDir, { recursive: true });
3179
- const mainTsx = `import { StrictMode } from 'react';
3180
- import { createRoot } from 'react-dom/client';
3181
- import { BrowserRouter } from 'react-router-dom';
3182
- import { App } from './App';
3183
- import './styles/tokens.css';
3184
- import './styles/treatments.css';
3185
- import './styles/global.css';
3186
-
3187
- createRoot(document.getElementById('root')!).render(
3188
- <StrictMode>
3189
- <BrowserRouter>
3190
- <App />
3191
- </BrowserRouter>
3192
- </StrictMode>,
3193
- );
3194
- `;
3195
- writeFileSync12(join22(srcDir, "main.tsx"), mainTsx);
3196
- const appTsx = `import { Routes, Route } from 'react-router-dom';
3197
-
3198
- function WelcomePage() {
3199
- return (
3200
- <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', gap: '1rem' }}>
3201
- <h1>${title}</h1>
3202
- <p style={{ opacity: 0.6 }}>Scaffolded with Decantr. Run <code>decantr status</code> to check project health.</p>
3203
- </div>
3204
- );
3205
- }
3206
-
3207
- export function App() {
3208
- return (
3209
- <Routes>
3210
- <Route path="/" element={<WelcomePage />} />
3211
- </Routes>
3212
- );
3213
- }
3214
- `;
3215
- writeFileSync12(join22(srcDir, "App.tsx"), appTsx);
3216
- writeFileSync12(join22(srcDir, "vite-env.d.ts"), '/// <reference types="vite/client" />\n');
3217
- mkdirSync7(join22(srcDir, "styles"), { recursive: true });
3388
+ const srcDir = join23(projectDir, "src");
3389
+ mkdirSync8(srcDir, { recursive: true });
3390
+ writeStarterRuntimeFiles(projectDir, title, getTargetRoutingMode(options.target));
3391
+ writeFileSync12(join23(srcDir, "vite-env.d.ts"), '/// <reference types="vite/client" />\n');
3392
+ mkdirSync8(join23(srcDir, "styles"), { recursive: true });
3218
3393
  console.log(dim2(" Created src/"));
3219
3394
  console.log(heading("Installing dependencies..."));
3220
3395
  const packageManager = detectPackageManager();
@@ -3224,6 +3399,24 @@ export function App() {
3224
3399
  console.log(`
3225
3400
  ${YELLOW8}Dependency install failed. Run \`${packageManager} install\` manually.${RESET12}`);
3226
3401
  }
3402
+ const requiresOfflineContent = Boolean(options.offline && (options.blueprint || options.archetype));
3403
+ const seeded = options.offline ? seedOfflineRegistry(projectDir, workspaceRoot) : { seeded: false, strategy: null };
3404
+ if (seeded.seeded) {
3405
+ console.log(dim2(` Seeded offline registry content from ${seeded.strategy}.`));
3406
+ } else if (requiresOfflineContent) {
3407
+ console.log(`${YELLOW8} Offline blueprint/archetype resolution requires local registry content.${RESET12}`);
3408
+ console.log(dim2(" No parent workspace cache/custom content or configured decantr-content source was found."));
3409
+ console.log("");
3410
+ console.log(success2(`
3411
+ \u2713 Project "${projectName}" created!
3412
+ `));
3413
+ console.log(` ${cyan2("cd " + projectName)}`);
3414
+ console.log(` ${cyan2(packageManager + " run dev")}`);
3415
+ console.log(` ${cyan2("decantr sync")} ${dim2("# when online, then rerun decantr init")}`);
3416
+ console.log(` ${cyan2("DECANTR_CONTENT_DIR=/path/to/decantr-content decantr init --existing --offline")} ${dim2("# or seed a local content source")}`);
3417
+ console.log("");
3418
+ return;
3419
+ }
3227
3420
  console.log(heading("Initializing Decantr..."));
3228
3421
  const initFlags = ["--yes", "--existing"];
3229
3422
  if (options.blueprint) initFlags.push(`--blueprint=${options.blueprint}`);
@@ -3231,12 +3424,15 @@ ${YELLOW8}Dependency install failed. Run \`${packageManager} install\` manually.
3231
3424
  if (options.theme) initFlags.push(`--theme=${options.theme}`);
3232
3425
  if (options.mode) initFlags.push(`--mode=${options.mode}`);
3233
3426
  if (options.shape) initFlags.push(`--shape=${options.shape}`);
3427
+ if (options.target) initFlags.push(`--target=${options.target}`);
3234
3428
  if (options.offline) initFlags.push("--offline");
3235
3429
  if (options.registry) initFlags.push(`--registry=${options.registry}`);
3236
3430
  try {
3237
- const cliBin = join22(__dirname, "..", "bin", "decantr.js");
3238
- const cliPath = existsSync22(cliBin) ? `node ${cliBin}` : "npx decantr";
3431
+ const bundledCliEntrypoint = fileURLToPath(new URL("./bin.js", import.meta.url));
3432
+ const cliEntrypoint = existsSync23(bundledCliEntrypoint) ? bundledCliEntrypoint : process.argv[1] && existsSync23(process.argv[1]) ? process.argv[1] : null;
3433
+ const cliPath = cliEntrypoint ? `"${process.execPath}" "${cliEntrypoint}"` : "npx decantr";
3239
3434
  execSync(`${cliPath} init ${initFlags.join(" ")}`, { cwd: projectDir, stdio: "inherit" });
3435
+ writeStarterRuntimeFiles(projectDir, title, detectRoutingMode(projectDir));
3240
3436
  } catch {
3241
3437
  console.log(`
3242
3438
  ${YELLOW8}Decantr init encountered issues. Run \`decantr init\` manually inside ${projectName}/.${RESET12}`);
@@ -3249,13 +3445,13 @@ ${YELLOW8}Decantr init encountered issues. Run \`decantr init\` manually inside
3249
3445
  console.log("");
3250
3446
  }
3251
3447
  function detectPackageManager() {
3252
- if (existsSync22(join22(process.cwd(), "pnpm-lock.yaml")) || existsSync22(join22(process.cwd(), "pnpm-workspace.yaml"))) {
3448
+ if (existsSync23(join23(process.cwd(), "pnpm-lock.yaml")) || existsSync23(join23(process.cwd(), "pnpm-workspace.yaml"))) {
3253
3449
  return "pnpm";
3254
3450
  }
3255
- if (existsSync22(join22(process.cwd(), "yarn.lock"))) {
3451
+ if (existsSync23(join23(process.cwd(), "yarn.lock"))) {
3256
3452
  return "yarn";
3257
3453
  }
3258
- if (existsSync22(join22(process.cwd(), "bun.lockb")) || existsSync22(join22(process.cwd(), "bun.lock"))) {
3454
+ if (existsSync23(join23(process.cwd(), "bun.lockb")) || existsSync23(join23(process.cwd(), "bun.lock"))) {
3259
3455
  return "bun";
3260
3456
  }
3261
3457
  return "npm";
@@ -3286,6 +3482,64 @@ function dim3(text) {
3286
3482
  function cyan3(text) {
3287
3483
  return `${CYAN7}${text}${RESET13}`;
3288
3484
  }
3485
+ function formatIntelligenceSummary(intelligence) {
3486
+ if (!intelligence) {
3487
+ return null;
3488
+ }
3489
+ const parts = [];
3490
+ const recommendationReasons = intelligence.recommendation_reasons ?? [];
3491
+ const recommendationBlockers = intelligence.recommendation_blockers ?? [];
3492
+ if (intelligence.recommended) {
3493
+ parts.push("recommended");
3494
+ }
3495
+ switch (intelligence.source) {
3496
+ case "authored":
3497
+ parts.push("authored intelligence");
3498
+ break;
3499
+ case "hybrid":
3500
+ parts.push("hybrid intelligence");
3501
+ break;
3502
+ case "benchmark":
3503
+ parts.push("benchmark-backed");
3504
+ break;
3505
+ default:
3506
+ break;
3507
+ }
3508
+ switch (intelligence.verification_status) {
3509
+ case "smoke-green":
3510
+ parts.push("smoke verified");
3511
+ break;
3512
+ case "build-green":
3513
+ parts.push("build verified");
3514
+ break;
3515
+ case "smoke-red":
3516
+ parts.push("smoke failed");
3517
+ break;
3518
+ case "build-red":
3519
+ parts.push("build failed");
3520
+ break;
3521
+ default:
3522
+ break;
3523
+ }
3524
+ if (intelligence.confidence_tier === "verified") {
3525
+ parts.push("verified confidence");
3526
+ } else if (intelligence.confidence_tier === "high") {
3527
+ parts.push("high confidence");
3528
+ } else if (intelligence.confidence_tier === "medium") {
3529
+ parts.push("medium confidence");
3530
+ } else if (intelligence.benchmark_confidence !== "none") {
3531
+ parts.push(`${intelligence.benchmark_confidence} confidence`);
3532
+ }
3533
+ if (intelligence.quality_score != null) {
3534
+ parts.push(`quality ${intelligence.quality_score}`);
3535
+ }
3536
+ if (intelligence.recommended && recommendationReasons.length > 0) {
3537
+ parts.push(`because ${recommendationReasons[0]}`);
3538
+ } else if (!intelligence.recommended && recommendationBlockers.length > 0) {
3539
+ parts.push(`held back by ${recommendationBlockers[0]}`);
3540
+ }
3541
+ return parts.length > 0 ? parts.join(" | ") : null;
3542
+ }
3289
3543
  function extractPatternName(item) {
3290
3544
  if (typeof item === "string") return item;
3291
3545
  if (typeof item === "object" && item !== null) {
@@ -3301,12 +3555,30 @@ function generateCuratedPrompt(ctx) {
3301
3555
  const lines = [];
3302
3556
  lines.push("Build this application using the Decantr design system.");
3303
3557
  lines.push("");
3304
- lines.push("Read DECANTR.md for the design spec, CSS approach, and guard rules.");
3305
- lines.push("Read .decantr/context/scaffold.md for the app overview, topology, routes, and voice guidance.");
3306
- lines.push("Read each .decantr/context/section-*.md file before building that section's pages.");
3307
- lines.push("Import src/styles/global.css, src/styles/tokens.css, and src/styles/treatments.css.");
3558
+ lines.push("Treat the compiled execution-pack files as the primary source of truth.");
3559
+ lines.push("Use narrative docs only as secondary explanation when the compiled packs are not enough.");
3560
+ lines.push("Use only files present in this workspace as the source of truth. If local scaffold files disagree, stop and report the mismatch instead of relying on external Decantr assumptions or prior examples.");
3561
+ lines.push("");
3562
+ lines.push("Read in this order:");
3563
+ lines.push("1. DECANTR.md for the design spec, CSS approach, and guard rules.");
3564
+ lines.push("2. .decantr/context/scaffold-pack.md for the compact compiled shell, theme, feature, and route contract.");
3565
+ lines.push("3. .decantr/context/scaffold.md for the broader app overview, topology, route map, and voice guidance.");
3566
+ lines.push("4. Before working on any section, read its matching .decantr/context/section-*-pack.md and then .decantr/context/section-*.md files.");
3567
+ lines.push("5. Before working on any route/page, read its matching .decantr/context/page-*-pack.md file.");
3308
3568
  lines.push("");
3309
- lines.push("Start with the shell layouts, then build each section's pages.");
3569
+ lines.push("Implementation rules:");
3570
+ lines.push("- Do not invent routes, sections, shells, themes, or features that are not present in the compiled packs.");
3571
+ lines.push("- Prefer scaffold-pack, section-pack, and page-pack guidance over broader narrative docs when they differ.");
3572
+ lines.push("- Start with the shell layouts and route structure first, then build section pages route by route.");
3573
+ lines.push("- Import src/styles/global.css, src/styles/tokens.css, and src/styles/treatments.css.");
3574
+ lines.push("- Use the existing Decantr tokens, treatments, and decorators instead of inventing a new visual system.");
3575
+ lines.push("- Do not modify generated context files unless the task is explicitly to regenerate or refresh Decantr context.");
3576
+ lines.push("");
3577
+ lines.push("Execution flow:");
3578
+ lines.push("- Build the shell and shared layout first.");
3579
+ lines.push("- Then implement each section's pages using the matching section and page packs.");
3580
+ lines.push("- After implementation, run decantr check and decantr audit and fix any contract or drift issues.");
3581
+ lines.push("- If a required context file is missing or inconsistent, stop and report exactly which file is missing before continuing.");
3310
3582
  return lines.join("\n");
3311
3583
  }
3312
3584
  function getAPIClient() {
@@ -3315,10 +3587,448 @@ function getAPIClient() {
3315
3587
  apiKey: process.env.DECANTR_API_KEY || void 0
3316
3588
  });
3317
3589
  }
3318
- async function cmdSearch(query, type) {
3590
+ function getPublicAPIClient() {
3591
+ return new RegistryAPIClient3({
3592
+ baseUrl: process.env.DECANTR_API_URL || void 0
3593
+ });
3594
+ }
3595
+ function resolveUserPath(inputPath, cwd = process.cwd()) {
3596
+ return isAbsolute(inputPath) ? inputPath : resolve3(cwd, inputPath);
3597
+ }
3598
+ function extractHostedAssetPaths(indexHtml) {
3599
+ const assetPaths = /* @__PURE__ */ new Set();
3600
+ for (const match of indexHtml.matchAll(/<(?:script|link)[^>]+(?:src|href)="([^"]+)"/g)) {
3601
+ const assetPath = match[1];
3602
+ const assetsIndex = assetPath.indexOf("/assets/");
3603
+ if (assetsIndex === -1) continue;
3604
+ assetPaths.add(assetPath.slice(assetsIndex));
3605
+ }
3606
+ return [...assetPaths];
3607
+ }
3608
+ function readHostedDistSnapshot(distPath) {
3609
+ const resolvedDistPath = distPath ? resolveUserPath(distPath) : join24(process.cwd(), "dist");
3610
+ const indexPath = join24(resolvedDistPath, "index.html");
3611
+ if (!existsSync24(indexPath)) {
3612
+ return void 0;
3613
+ }
3614
+ const indexHtml = readFileSync16(indexPath, "utf-8");
3615
+ const assetPaths = extractHostedAssetPaths(indexHtml);
3616
+ const assets = {};
3617
+ for (const assetPath of assetPaths) {
3618
+ const assetFilePath = join24(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
3619
+ if (existsSync24(assetFilePath)) {
3620
+ assets[assetPath] = readFileSync16(assetFilePath, "utf-8");
3621
+ }
3622
+ }
3623
+ return {
3624
+ indexHtml,
3625
+ assets
3626
+ };
3627
+ }
3628
+ function isHostedSourceSnapshotFile(path) {
3629
+ if (/\.d\.ts$/i.test(path)) return false;
3630
+ return /\.(?:[cm]?[jt]sx?)$/i.test(path);
3631
+ }
3632
+ function readHostedSourceSnapshot(sourcePath) {
3633
+ if (!sourcePath) return void 0;
3634
+ const resolvedSourcePath = resolveUserPath(sourcePath);
3635
+ if (!existsSync24(resolvedSourcePath)) {
3636
+ return void 0;
3637
+ }
3638
+ const files = {};
3639
+ const ignoredDirNames = /* @__PURE__ */ new Set(["node_modules", ".git", ".decantr", "dist", "build", "coverage"]);
3640
+ const rootPrefix = basename(resolvedSourcePath);
3641
+ const walk = (absoluteDir, relativeDir) => {
3642
+ for (const entry of readdirSync6(absoluteDir, { withFileTypes: true })) {
3643
+ if (ignoredDirNames.has(entry.name)) continue;
3644
+ const absolutePath = join24(absoluteDir, entry.name);
3645
+ const relativePath = join24(relativeDir, entry.name).replace(/\\/g, "/");
3646
+ if (entry.isDirectory()) {
3647
+ walk(absolutePath, relativePath);
3648
+ continue;
3649
+ }
3650
+ if (!entry.isFile()) continue;
3651
+ if (!isHostedSourceSnapshotFile(relativePath)) continue;
3652
+ files[relativePath] = readFileSync16(absolutePath, "utf-8");
3653
+ }
3654
+ };
3655
+ walk(resolvedSourcePath, rootPrefix);
3656
+ return Object.keys(files).length > 0 ? { files } : void 0;
3657
+ }
3658
+ async function getShowcaseBenchmarkView(view = "shortlist") {
3659
+ const client = getPublicAPIClient();
3660
+ if (view === "manifest") {
3661
+ return client.getShowcaseManifest();
3662
+ }
3663
+ if (view === "verification") {
3664
+ return client.getShowcaseShortlistVerification();
3665
+ }
3666
+ return client.getShowcaseShortlist();
3667
+ }
3668
+ async function printShowcaseBenchmarks(view, jsonOutput) {
3669
+ const fmtBytes = (bytes) => bytes >= 1e6 ? `${(bytes / 1e6).toFixed(2)} MB` : `${Math.round(bytes / 1e3)} KB`;
3670
+ const data = await getShowcaseBenchmarkView(view);
3671
+ if (jsonOutput) {
3672
+ console.log(JSON.stringify(data, null, 2));
3673
+ return;
3674
+ }
3675
+ if (view === "manifest") {
3676
+ const manifest = data;
3677
+ console.log(heading2("Showcase Corpus"));
3678
+ console.log(` Active apps: ${manifest.total}`);
3679
+ console.log(` Shortlisted apps: ${manifest.shortlisted}`);
3680
+ console.log("");
3681
+ for (const entry of manifest.apps) {
3682
+ const verification = entry.verification;
3683
+ const verificationSummary = verification ? ` | ${verification.verificationStatus} | drift ${verification.drift.signal}` : "";
3684
+ console.log(` ${cyan3(entry.slug)} class ${entry.classification}${verificationSummary}`);
3685
+ }
3686
+ return;
3687
+ }
3688
+ if (view === "verification") {
3689
+ const report = data;
3690
+ console.log(heading2("Showcase Verification"));
3691
+ if (report.generatedAt) {
3692
+ console.log(` Generated: ${report.generatedAt}`);
3693
+ }
3694
+ if (report.summary) {
3695
+ console.log(` Passed builds: ${report.summary.passedBuilds}/${report.summary.appCount}`);
3696
+ console.log(` Avg build: ${report.summary.averageDurationMs} ms`);
3697
+ console.log(` Passed smokes: ${report.summary.passedSmokes}/${report.summary.appCount}`);
3698
+ console.log(` Avg smoke: ${report.summary.averageSmokeDurationMs} ms`);
3699
+ console.log(` Title checks: ${report.summary.appsWithTitleOkCount}/${report.summary.appCount}`);
3700
+ console.log(` Lang checks: ${report.summary.appsWithLangOkCount}/${report.summary.appCount}`);
3701
+ console.log(` Viewport checks: ${report.summary.appsWithViewportOkCount}/${report.summary.appCount}`);
3702
+ console.log(` Charset checks: ${report.summary.appsWithCharsetOkCount}/${report.summary.appCount}`);
3703
+ console.log(` No inline scripts: ${report.summary.appsWithoutInlineScriptsCount}/${report.summary.appCount}`);
3704
+ console.log(` CSP signals: ${report.summary.appsWithCspSignalCount}/${report.summary.appCount}`);
3705
+ console.log(` External script integrity ok: ${report.summary.appsWithExternalScriptIntegrityCount}/${report.summary.appCount}`);
3706
+ console.log(` External stylesheet integrity ok: ${report.summary.appsWithExternalStylesheetIntegrityCount}/${report.summary.appCount}`);
3707
+ console.log(` Route coverage: ${report.summary.appsWithRouteCoverageCount}/${report.summary.appCount}`);
3708
+ console.log(` Full route coverage: ${report.summary.appsWithFullRouteCoverageCount}/${report.summary.appCount}`);
3709
+ console.log(` Avg assets: total ${fmtBytes(report.summary.averageTotalAssetBytes)} | js ${fmtBytes(report.summary.averageJsAssetBytes)} | css ${fmtBytes(report.summary.averageCssAssetBytes)}`);
3710
+ console.log(` Drift: lower ${report.summary.lowerDriftCount}, moderate ${report.summary.moderateDriftCount}, elevated ${report.summary.elevatedDriftCount}`);
3711
+ console.log(` Pack manifests: ${report.summary.withPackManifestCount}/${report.summary.appCount}`);
3712
+ console.log("");
3713
+ }
3714
+ for (const entry of report.results) {
3715
+ console.log(` ${cyan3(entry.slug)} ${entry.verificationStatus} | smoke ${entry.smoke.passed ? "green" : entry.build.passed ? "red" : "pending"} | routes ${entry.smoke.routeDocumentsPassed}/${entry.smoke.routeDocumentsChecked}${entry.smoke.fullRouteCoverageOk ? " full" : " partial"} | js ${fmtBytes(entry.smoke.jsAssetBytes)} | drift ${entry.drift.signal} | build ${entry.build.durationMs} ms | smoke ${entry.smoke.durationMs} ms`);
3716
+ }
3717
+ return;
3718
+ }
3719
+ const shortlist = data;
3720
+ console.log(heading2("Showcase Shortlist"));
3721
+ if (shortlist.generatedAt) {
3722
+ console.log(` Generated: ${shortlist.generatedAt}`);
3723
+ }
3724
+ if (shortlist.summary) {
3725
+ console.log(` Passed builds: ${shortlist.summary.passedBuilds}/${shortlist.summary.appCount}`);
3726
+ console.log(` Passed smokes: ${shortlist.summary.passedSmokes}/${shortlist.summary.appCount}`);
3727
+ console.log(` Route coverage: ${shortlist.summary.appsWithRouteCoverageCount}/${shortlist.summary.appCount}`);
3728
+ console.log(` Full route coverage: ${shortlist.summary.appsWithFullRouteCoverageCount}/${shortlist.summary.appCount}`);
3729
+ console.log(` Drift mix: lower ${shortlist.summary.lowerDriftCount}, moderate ${shortlist.summary.moderateDriftCount}, elevated ${shortlist.summary.elevatedDriftCount}`);
3730
+ console.log("");
3731
+ }
3732
+ for (const entry of shortlist.apps) {
3733
+ const verification = entry.verification;
3734
+ const verificationSummary = verification ? `${verification.verificationStatus} | smoke ${verification.smoke.passed ? "green" : verification.build.passed ? "red" : "pending"} | drift ${verification.drift.signal}` : "verification pending";
3735
+ console.log(` ${cyan3(entry.slug)} class ${entry.classification} | ${verificationSummary}`);
3736
+ }
3737
+ }
3738
+ async function printRegistryIntelligenceSummary(namespace, jsonOutput = false) {
3739
+ const client = getPublicAPIClient();
3740
+ const summary = await client.getRegistryIntelligenceSummary(
3741
+ namespace ? { namespace } : void 0
3742
+ );
3743
+ if (jsonOutput) {
3744
+ console.log(JSON.stringify(summary, null, 2));
3745
+ return;
3746
+ }
3747
+ const typedSummary = summary;
3748
+ console.log(heading2("Registry Intelligence Summary"));
3749
+ console.log(` Namespace: ${typedSummary.namespace ?? "all public content"}`);
3750
+ console.log(` Generated: ${typedSummary.generated_at}`);
3751
+ console.log(` Public items: ${typedSummary.totals.total_public_items}`);
3752
+ console.log(` With intelligence: ${typedSummary.totals.with_intelligence}`);
3753
+ console.log(` Recommended: ${typedSummary.totals.recommended}`);
3754
+ console.log(
3755
+ ` Sources: authored ${typedSummary.totals.authored}, benchmark ${typedSummary.totals.benchmark}, hybrid ${typedSummary.totals.hybrid}, missing ${typedSummary.totals.missing_source}`
3756
+ );
3757
+ console.log(
3758
+ ` Verification: smoke green ${typedSummary.totals.smoke_green}, build green ${typedSummary.totals.build_green}, high confidence ${typedSummary.totals.high_confidence}, verified ${typedSummary.totals.verified_confidence}`
3759
+ );
3760
+ console.log("");
3761
+ for (const [type, bucket] of Object.entries(typedSummary.by_type)) {
3762
+ console.log(
3763
+ ` ${cyan3(type.padEnd(10))} total ${bucket.total_public_items} | intelligence ${bucket.with_intelligence} | recommended ${bucket.recommended} | authored ${bucket.authored} | benchmark ${bucket.benchmark} | hybrid ${bucket.hybrid}`
3764
+ );
3765
+ }
3766
+ }
3767
+ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput = false, writeContext = false) {
3768
+ const client = getPublicAPIClient();
3769
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join24(process.cwd(), "decantr.essence.json");
3770
+ if (!existsSync24(resolvedPath)) {
3771
+ throw new Error(`Essence file not found at ${resolvedPath}`);
3772
+ }
3773
+ const essence = JSON.parse(readFileSync16(resolvedPath, "utf-8"));
3774
+ const bundle = await client.compileExecutionPacks(
3775
+ essence,
3776
+ namespace ? { namespace } : void 0
3777
+ );
3778
+ let writtenContextPaths = [];
3779
+ if (writeContext) {
3780
+ const contextDir = join24(process.cwd(), ".decantr", "context");
3781
+ mkdirSync9(contextDir, { recursive: true });
3782
+ const written = writeExecutionPackBundleArtifacts(
3783
+ contextDir,
3784
+ bundle
3785
+ );
3786
+ writtenContextPaths = written.paths;
3787
+ }
3788
+ if (jsonOutput) {
3789
+ console.log(JSON.stringify(bundle, null, 2));
3790
+ return;
3791
+ }
3792
+ const typedBundle = bundle;
3793
+ console.log(heading2("Hosted Execution Packs"));
3794
+ console.log(` Source essence: ${resolvedPath}`);
3795
+ console.log(` Essence version: ${typedBundle.sourceEssenceVersion}`);
3796
+ console.log(` Generated: ${typedBundle.generatedAt}`);
3797
+ console.log(` Adapter: ${typedBundle.scaffold.target.adapter}`);
3798
+ console.log(` Shell: ${typedBundle.scaffold.data.shell}`);
3799
+ console.log(` Theme: ${typedBundle.scaffold.data.theme.id} (${typedBundle.scaffold.data.theme.mode})`);
3800
+ console.log(` Pages: ${typedBundle.pages.length}`);
3801
+ console.log(` Sections: ${typedBundle.sections.length}`);
3802
+ console.log(` Mutations: ${typedBundle.mutations.length}`);
3803
+ if (writeContext) {
3804
+ console.log(` Context bundle: ${join24(process.cwd(), ".decantr", "context")}`);
3805
+ console.log(` Files written: ${writtenContextPaths.length}`);
3806
+ }
3807
+ console.log("");
3808
+ console.log(`${BOLD6}Route Plan:${RESET13}`);
3809
+ for (const route of typedBundle.scaffold.data.routes) {
3810
+ const patterns = route.patternIds.length > 0 ? route.patternIds.join(", ") : "none";
3811
+ console.log(` ${cyan3(route.path)} -> ${route.pageId} [${patterns}]`);
3812
+ }
3813
+ }
3814
+ async function printHostedSelectedExecutionPack(packType, id, essencePath, namespace, jsonOutput = false, writeContext = false) {
3815
+ const client = getPublicAPIClient();
3816
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join24(process.cwd(), "decantr.essence.json");
3817
+ if (!existsSync24(resolvedPath)) {
3818
+ throw new Error(`Essence file not found at ${resolvedPath}`);
3819
+ }
3820
+ if ((packType === "section" || packType === "page" || packType === "mutation") && !id) {
3821
+ throw new Error(`Pack type "${packType}" requires an id.`);
3822
+ }
3823
+ const essence = JSON.parse(readFileSync16(resolvedPath, "utf-8"));
3824
+ const selected = await client.selectExecutionPack(
3825
+ {
3826
+ essence,
3827
+ pack_type: packType,
3828
+ ...id ? { id } : {}
3829
+ },
3830
+ namespace ? { namespace } : void 0
3831
+ );
3832
+ let writtenContextDir = null;
3833
+ if (writeContext) {
3834
+ const contextDir = join24(process.cwd(), ".decantr", "context");
3835
+ mkdirSync9(contextDir, { recursive: true });
3836
+ writeFileSync13(join24(contextDir, "pack-manifest.json"), JSON.stringify(selected.manifest, null, 2) + "\n");
3837
+ const manifestEntry = selected.selector.packType === "scaffold" ? selected.manifest.scaffold : selected.selector.packType === "review" ? selected.manifest.review : selected.selector.packType === "section" ? selected.manifest.sections.find((entry) => entry.id === selected.selector.id) : selected.selector.packType === "page" ? selected.manifest.pages.find((entry) => entry.id === selected.selector.id) : selected.manifest.mutations.find((entry) => entry.id === selected.selector.id);
3838
+ const markdownFile = manifestEntry?.markdown ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.md`;
3839
+ const jsonFile = manifestEntry?.json ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.json`;
3840
+ writeFileSync13(join24(contextDir, markdownFile), selected.pack.renderedMarkdown);
3841
+ writeFileSync13(join24(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
3842
+ writtenContextDir = contextDir;
3843
+ }
3844
+ if (jsonOutput) {
3845
+ console.log(JSON.stringify(selected, null, 2));
3846
+ return;
3847
+ }
3848
+ const typedSelected = selected;
3849
+ console.log(heading2("Hosted Execution Pack"));
3850
+ console.log(` Source essence: ${resolvedPath}`);
3851
+ console.log(` Generated: ${typedSelected.generatedAt}`);
3852
+ console.log(` Pack type: ${typedSelected.selector.packType}`);
3853
+ if (typedSelected.selector.id) {
3854
+ console.log(` Pack id: ${typedSelected.selector.id}`);
3855
+ }
3856
+ console.log(` Adapter: ${typedSelected.pack.target.adapter}`);
3857
+ console.log(` Objective: ${typedSelected.pack.objective}`);
3858
+ if (writtenContextDir) {
3859
+ console.log(` Context artifact: ${writtenContextDir}`);
3860
+ }
3861
+ console.log("");
3862
+ process.stdout.write(typedSelected.pack.renderedMarkdown);
3863
+ }
3864
+ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutput = false, writeContext = false) {
3865
+ const client = getPublicAPIClient();
3866
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join24(process.cwd(), "decantr.essence.json");
3867
+ if (!existsSync24(resolvedPath)) {
3868
+ throw new Error(`Essence file not found at ${resolvedPath}`);
3869
+ }
3870
+ const essence = JSON.parse(readFileSync16(resolvedPath, "utf-8"));
3871
+ const manifest = await client.getExecutionPackManifest(
3872
+ essence,
3873
+ namespace ? { namespace } : void 0
3874
+ );
3875
+ let writtenContextDir = null;
3876
+ if (writeContext) {
3877
+ const contextDir = join24(process.cwd(), ".decantr", "context");
3878
+ mkdirSync9(contextDir, { recursive: true });
3879
+ writeFileSync13(join24(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
3880
+ writtenContextDir = contextDir;
3881
+ }
3882
+ if (jsonOutput) {
3883
+ console.log(JSON.stringify(manifest, null, 2));
3884
+ return;
3885
+ }
3886
+ console.log(heading2("Hosted Pack Manifest"));
3887
+ console.log(` Source essence: ${resolvedPath}`);
3888
+ console.log(` Generated: ${manifest.generatedAt}`);
3889
+ console.log(` Version: ${manifest.version}`);
3890
+ console.log(` Scaffold: ${manifest.scaffold ? "present" : "missing"}`);
3891
+ console.log(` Review: ${manifest.review ? "present" : "missing"}`);
3892
+ console.log(` Sections: ${manifest.sections.length}`);
3893
+ console.log(` Pages: ${manifest.pages.length}`);
3894
+ console.log(` Mutations: ${manifest.mutations.length}`);
3895
+ if (writtenContextDir) {
3896
+ console.log(` Context artifact: ${writtenContextDir}`);
3897
+ }
3898
+ }
3899
+ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@official") {
3900
+ const contextDir = join24(projectRoot, ".decantr", "context");
3901
+ const reviewPackPath = join24(contextDir, "review-pack.json");
3902
+ const manifestPath = join24(contextDir, "pack-manifest.json");
3903
+ if (existsSync24(reviewPackPath) && existsSync24(manifestPath)) {
3904
+ return { attempted: false, hydrated: false };
3905
+ }
3906
+ const essencePath = join24(projectRoot, "decantr.essence.json");
3907
+ if (!existsSync24(essencePath)) {
3908
+ return { attempted: false, hydrated: false };
3909
+ }
3910
+ const reviewHydration = await hydrateHostedReviewPackIfMissing(projectRoot, namespace);
3911
+ if (reviewHydration.hydrated || !reviewHydration.attempted) {
3912
+ return reviewHydration;
3913
+ }
3914
+ try {
3915
+ const client = getPublicAPIClient();
3916
+ const essence = JSON.parse(readFileSync16(essencePath, "utf-8"));
3917
+ const bundle = await client.compileExecutionPacks(essence, { namespace });
3918
+ mkdirSync9(contextDir, { recursive: true });
3919
+ writeExecutionPackBundleArtifacts(
3920
+ contextDir,
3921
+ bundle
3922
+ );
3923
+ return { attempted: true, hydrated: true, scope: "bundle" };
3924
+ } catch {
3925
+ return { attempted: true, hydrated: false };
3926
+ }
3927
+ }
3928
+ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@official") {
3929
+ const contextDir = join24(projectRoot, ".decantr", "context");
3930
+ const reviewPackPath = join24(contextDir, "review-pack.json");
3931
+ const manifestPath = join24(contextDir, "pack-manifest.json");
3932
+ if (existsSync24(reviewPackPath) && existsSync24(manifestPath)) {
3933
+ return { attempted: false, hydrated: false };
3934
+ }
3935
+ const essencePath = join24(projectRoot, "decantr.essence.json");
3936
+ if (!existsSync24(essencePath)) {
3937
+ return { attempted: false, hydrated: false };
3938
+ }
3939
+ try {
3940
+ const client = getPublicAPIClient();
3941
+ const essence = JSON.parse(readFileSync16(essencePath, "utf-8"));
3942
+ const selected = await client.selectExecutionPack(
3943
+ {
3944
+ essence,
3945
+ pack_type: "review"
3946
+ },
3947
+ { namespace }
3948
+ );
3949
+ mkdirSync9(contextDir, { recursive: true });
3950
+ writeFileSync13(join24(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
3951
+ writeFileSync13(join24(contextDir, "review-pack.json"), JSON.stringify(selected.pack, null, 2) + "\n");
3952
+ if (!existsSync24(manifestPath)) {
3953
+ writeFileSync13(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
3954
+ }
3955
+ return { attempted: true, hydrated: true, scope: "review" };
3956
+ } catch {
3957
+ return { attempted: true, hydrated: false };
3958
+ }
3959
+ }
3960
+ async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false, essencePath, treatmentsPath) {
3961
+ const client = getPublicAPIClient();
3962
+ const resolvedSourcePath = resolveUserPath(sourcePath);
3963
+ const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join24(process.cwd(), "decantr.essence.json");
3964
+ const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join24(process.cwd(), "src", "styles", "treatments.css");
3965
+ if (!existsSync24(resolvedSourcePath)) {
3966
+ throw new Error(`Source file not found at ${resolvedSourcePath}`);
3967
+ }
3968
+ if (!existsSync24(resolvedEssencePath)) {
3969
+ throw new Error(`Essence file not found at ${resolvedEssencePath}`);
3970
+ }
3971
+ const code = readFileSync16(resolvedSourcePath, "utf-8");
3972
+ const essence = JSON.parse(readFileSync16(resolvedEssencePath, "utf-8"));
3973
+ const treatmentsCss = existsSync24(resolvedTreatmentsPath) ? readFileSync16(resolvedTreatmentsPath, "utf-8") : void 0;
3974
+ const report = await client.critiqueFile(
3975
+ {
3976
+ essence,
3977
+ filePath: sourcePath,
3978
+ code,
3979
+ treatmentsCss
3980
+ },
3981
+ namespace ? { namespace } : void 0
3982
+ );
3983
+ if (jsonOutput) {
3984
+ console.log(JSON.stringify(report, null, 2));
3985
+ return;
3986
+ }
3987
+ console.log(heading2("Hosted File Critique"));
3988
+ console.log(` Source file: ${resolvedSourcePath}`);
3989
+ console.log(` Essence: ${resolvedEssencePath}`);
3990
+ if (treatmentsCss) {
3991
+ console.log(` Treatments: ${resolvedTreatmentsPath}`);
3992
+ }
3993
+ printFileCritiqueReport(report);
3994
+ }
3995
+ async function printHostedProjectAudit(namespace, jsonOutput = false, essencePath, distPath, sourcesPath) {
3996
+ const client = getPublicAPIClient();
3997
+ const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join24(process.cwd(), "decantr.essence.json");
3998
+ if (!existsSync24(resolvedEssencePath)) {
3999
+ throw new Error(`Essence file not found at ${resolvedEssencePath}`);
4000
+ }
4001
+ const essence = JSON.parse(readFileSync16(resolvedEssencePath, "utf-8"));
4002
+ const dist = readHostedDistSnapshot(distPath);
4003
+ const sources = readHostedSourceSnapshot(sourcesPath);
4004
+ const report = await client.auditProject(
4005
+ {
4006
+ essence,
4007
+ dist,
4008
+ sources
4009
+ },
4010
+ namespace ? { namespace } : void 0
4011
+ );
4012
+ if (jsonOutput) {
4013
+ console.log(JSON.stringify(report, null, 2));
4014
+ return;
4015
+ }
4016
+ console.log(heading2("Hosted Project Audit"));
4017
+ console.log(` Essence: ${resolvedEssencePath}`);
4018
+ console.log(` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join24(process.cwd(), "dist") : "none"}`);
4019
+ console.log(` Source snapshot: ${sources && sourcesPath ? resolveUserPath(sourcesPath) : "none"}`);
4020
+ printProjectAuditReport(report);
4021
+ }
4022
+ async function cmdSearch(query, type, sort, recommended, intelligenceSource) {
3319
4023
  const apiClient = getAPIClient();
3320
4024
  try {
3321
- const response = await apiClient.search({ q: query, type });
4025
+ const response = await apiClient.search({
4026
+ q: query,
4027
+ type,
4028
+ sort,
4029
+ recommended,
4030
+ intelligenceSource
4031
+ });
3322
4032
  const results = response.results;
3323
4033
  if (results.length === 0) {
3324
4034
  console.log(dim3(`No results for "${query}"`));
@@ -3328,6 +4038,10 @@ async function cmdSearch(query, type) {
3328
4038
  for (const r of results) {
3329
4039
  console.log(` ${cyan3(r.type.padEnd(12))} ${BOLD6}${r.slug}${RESET13}`);
3330
4040
  console.log(` ${dim3(r.description || "")}`);
4041
+ const intelligenceSummary = formatIntelligenceSummary(r.intelligence);
4042
+ if (intelligenceSummary) {
4043
+ console.log(` ${dim3(intelligenceSummary)}`);
4044
+ }
3331
4045
  console.log("");
3332
4046
  }
3333
4047
  } catch {
@@ -3372,40 +4086,32 @@ async function cmdSuggest(query, type) {
3372
4086
  }
3373
4087
  }
3374
4088
  async function cmdGet(type, id) {
3375
- const validTypes = ["pattern", "archetype", "theme", "blueprint", "shell"];
3376
- if (!validTypes.includes(type)) {
3377
- console.error(error3(`Invalid type "${type}". Must be one of: ${validTypes.join(", ")}`));
4089
+ if (!isGetContentType(type)) {
4090
+ console.error(error3(`Invalid type "${type}". Must be one of: ${GET_CONTENT_TYPES.join(", ")}`));
3378
4091
  process.exitCode = 1;
3379
4092
  return;
3380
4093
  }
3381
- const typeMap = {
3382
- pattern: "patterns",
3383
- archetype: "archetypes",
3384
- theme: "themes",
3385
- blueprint: "blueprints",
3386
- shell: "shells"
3387
- };
3388
- const apiType = typeMap[type];
4094
+ const apiType = CONTENT_TYPE_TO_API_CONTENT_TYPE3[type];
3389
4095
  const registryClient = new RegistryClient({
3390
- cacheDir: join23(process.cwd(), ".decantr", "cache")
4096
+ cacheDir: join24(process.cwd(), ".decantr", "cache")
3391
4097
  });
3392
4098
  const result = await registryClient.fetchContentItem(apiType, id);
3393
4099
  if (result) {
3394
4100
  console.log(JSON.stringify(result.data, null, 2));
3395
4101
  return;
3396
4102
  }
3397
- const currentDir = dirname2(fileURLToPath(import.meta.url));
4103
+ const currentDir = dirname2(fileURLToPath2(import.meta.url));
3398
4104
  const bundledCandidates = [
3399
- join23(currentDir, "bundled", apiType, `${id}.json`),
4105
+ join24(currentDir, "bundled", apiType, `${id}.json`),
3400
4106
  // Running from src/
3401
- join23(currentDir, "..", "src", "bundled", apiType, `${id}.json`),
4107
+ join24(currentDir, "..", "src", "bundled", apiType, `${id}.json`),
3402
4108
  // Running from dist/
3403
- join23(currentDir, "..", "bundled", apiType, `${id}.json`)
4109
+ join24(currentDir, "..", "bundled", apiType, `${id}.json`)
3404
4110
  // Alternative dist layout
3405
4111
  ];
3406
- const bundledPath = bundledCandidates.find((p) => existsSync23(p)) || null;
4112
+ const bundledPath = bundledCandidates.find((p) => existsSync24(p)) || null;
3407
4113
  if (bundledPath) {
3408
- const data = JSON.parse(readFileSync15(bundledPath, "utf-8"));
4114
+ const data = JSON.parse(readFileSync16(bundledPath, "utf-8"));
3409
4115
  console.log(JSON.stringify(data, null, 2));
3410
4116
  return;
3411
4117
  }
@@ -3413,55 +4119,11 @@ async function cmdGet(type, id) {
3413
4119
  process.exitCode = 1;
3414
4120
  return;
3415
4121
  }
3416
- function buildRegistryContext() {
3417
- const themeRegistry = /* @__PURE__ */ new Map();
3418
- const patternRegistry = /* @__PURE__ */ new Map();
3419
- const projectRoot = process.cwd();
3420
- const cacheDir = join23(projectRoot, ".decantr", "cache");
3421
- const customDir = join23(projectRoot, ".decantr", "custom");
3422
- const cachedThemesDir = join23(cacheDir, "@official", "themes");
3423
- try {
3424
- if (existsSync23(cachedThemesDir)) {
3425
- for (const f of readdirSync6(cachedThemesDir).filter((f2) => f2.endsWith(".json") && f2 !== "index.json")) {
3426
- const data = JSON.parse(readFileSync15(join23(cachedThemesDir, f), "utf-8"));
3427
- if (data.id && !themeRegistry.has(data.id)) {
3428
- themeRegistry.set(data.id, { modes: data.modes || ["light", "dark"] });
3429
- }
3430
- }
3431
- }
3432
- } catch {
3433
- }
3434
- const customThemesDir = join23(customDir, "themes");
3435
- try {
3436
- if (existsSync23(customThemesDir)) {
3437
- for (const f of readdirSync6(customThemesDir).filter((f2) => f2.endsWith(".json"))) {
3438
- const data = JSON.parse(readFileSync15(join23(customThemesDir, f), "utf-8"));
3439
- if (data.id) {
3440
- themeRegistry.set(`custom:${data.id}`, { modes: data.modes || ["light", "dark"] });
3441
- }
3442
- }
3443
- }
3444
- } catch {
3445
- }
3446
- const cachedPatternsDir = join23(cacheDir, "@official", "patterns");
3447
- try {
3448
- if (existsSync23(cachedPatternsDir)) {
3449
- for (const f of readdirSync6(cachedPatternsDir).filter((f2) => f2.endsWith(".json") && f2 !== "index.json")) {
3450
- const data = JSON.parse(readFileSync15(join23(cachedPatternsDir, f), "utf-8"));
3451
- if (data.id && !patternRegistry.has(data.id)) {
3452
- patternRegistry.set(data.id, data);
3453
- }
3454
- }
3455
- }
3456
- } catch {
3457
- }
3458
- return { themeRegistry, patternRegistry };
3459
- }
3460
4122
  async function cmdValidate(path) {
3461
- const essencePath = path || join23(process.cwd(), "decantr.essence.json");
4123
+ const essencePath = path || join24(process.cwd(), "decantr.essence.json");
3462
4124
  let raw;
3463
4125
  try {
3464
- raw = readFileSync15(essencePath, "utf-8");
4126
+ raw = readFileSync16(essencePath, "utf-8");
3465
4127
  } catch {
3466
4128
  console.error(error3(`Could not read ${essencePath}`));
3467
4129
  process.exitCode = 1;
@@ -3491,7 +4153,7 @@ async function cmdValidate(path) {
3491
4153
  console.log(`${YELLOW9}Tip: Run \`decantr migrate\` to upgrade to v3 format.${RESET13}`);
3492
4154
  }
3493
4155
  try {
3494
- const { themeRegistry, patternRegistry } = buildRegistryContext();
4156
+ const { themeRegistry, patternRegistry } = buildGuardRegistryContext(process.cwd());
3495
4157
  const violations = evaluateGuard(essence, { themeRegistry, patternRegistry });
3496
4158
  if (violations.length > 0) {
3497
4159
  console.log(heading2("Guard violations:"));
@@ -3508,17 +4170,22 @@ async function cmdValidate(path) {
3508
4170
  } catch {
3509
4171
  }
3510
4172
  }
3511
- async function cmdList(type) {
3512
- const validTypes = ["patterns", "archetypes", "themes", "blueprints", "shells"];
3513
- if (!validTypes.includes(type)) {
3514
- console.error(error3(`Invalid type "${type}". Must be one of: ${validTypes.join(", ")}`));
4173
+ async function cmdList(type, sort, recommended, intelligenceSource) {
4174
+ if (!isApiContentType(type)) {
4175
+ console.error(error3(`Invalid type "${type}". Must be one of: ${LIST_CONTENT_TYPES.join(", ")}`));
3515
4176
  process.exitCode = 1;
3516
4177
  return;
3517
4178
  }
3518
4179
  const registryClient = new RegistryClient({
3519
- cacheDir: join23(process.cwd(), ".decantr", "cache")
4180
+ cacheDir: join24(process.cwd(), ".decantr", "cache")
3520
4181
  });
3521
- const result = await registryClient.fetchContentList(type);
4182
+ const result = await registryClient.fetchContentList(
4183
+ type,
4184
+ void 0,
4185
+ sort,
4186
+ recommended,
4187
+ intelligenceSource
4188
+ );
3522
4189
  const items = result.data.items;
3523
4190
  if (items.length === 0) {
3524
4191
  console.log(dim3(`No ${type} found.`));
@@ -3547,6 +4214,12 @@ async function cmdList(type) {
3547
4214
  console.log(heading2(`${items.length} ${type} found`));
3548
4215
  for (const item of items) {
3549
4216
  console.log(` ${cyan3(item.id)} ${dim3(item.description || item.name || "")}`);
4217
+ const intelligenceSummary = formatIntelligenceSummary(
4218
+ item.intelligence
4219
+ );
4220
+ if (intelligenceSummary) {
4221
+ console.log(` ${dim3(intelligenceSummary)}`);
4222
+ }
3550
4223
  }
3551
4224
  }
3552
4225
  }
@@ -3562,12 +4235,34 @@ async function cmdInit(args) {
3562
4235
  return;
3563
4236
  }
3564
4237
  }
4238
+ const requestedBlueprint = Boolean(args.blueprint);
4239
+ const requestedArchetype = Boolean(args.archetype);
4240
+ const requestedTheme = Boolean(args.theme);
4241
+ let offlineSeed = { seeded: false, strategy: null };
4242
+ if (args.offline) {
4243
+ offlineSeed = seedOfflineRegistry(projectRoot, projectRoot);
4244
+ if (offlineSeed.seeded) {
4245
+ console.log(dim3(` Seeded offline registry content from ${offlineSeed.strategy}.`));
4246
+ } else if (requestedBlueprint || requestedArchetype) {
4247
+ console.log(error3("\nOffline blueprint/archetype scaffolding requires a local Decantr content source."));
4248
+ console.log(dim3("Set DECANTR_CONTENT_DIR, seed .decantr/cache or .decantr/custom, or run without --offline."));
4249
+ process.exitCode = 1;
4250
+ return;
4251
+ }
4252
+ }
3565
4253
  const registryClient = new RegistryClient({
3566
- cacheDir: join23(projectRoot, ".decantr", "cache"),
4254
+ cacheDir: join24(projectRoot, ".decantr", "cache"),
3567
4255
  apiUrl: args.registry,
3568
4256
  offline: args.offline
3569
4257
  });
3570
4258
  const apiAvailable = await registryClient.checkApiAvailability();
4259
+ if (!apiAvailable && !args.offline && (requestedBlueprint || requestedArchetype)) {
4260
+ const fallbackSeed = seedOfflineRegistry(projectRoot, projectRoot);
4261
+ if (fallbackSeed.seeded) {
4262
+ offlineSeed = fallbackSeed;
4263
+ console.log(dim3(` Seeded local registry fallback from ${fallbackSeed.strategy}.`));
4264
+ }
4265
+ }
3571
4266
  let selectedBlueprint = "default";
3572
4267
  let registrySource = "cache";
3573
4268
  if (args.yes) {
@@ -3589,8 +4284,15 @@ ${YELLOW9}You're offline. Scaffolding minimal Decantr project.${RESET13}`);
3589
4284
  console.log("");
3590
4285
  console.log(" Next steps:");
3591
4286
  console.log(` 1. Run ${cyan3("decantr sync")} when online`);
3592
- console.log(` 2. Use ${cyan3("decantr create <type> <name>")} to create custom content`);
3593
- console.log(` 3. Review DECANTR.md for methodology`);
4287
+ console.log(` 2. Run ${cyan3("decantr refresh")} after syncing to generate scaffold, section, and page packs`);
4288
+ console.log(` 3. Read ${cyan3("DECANTR.md")} and the generated ${cyan3(".decantr/context/*")} files before implementation`);
4289
+ console.log(` 4. Use ${cyan3("decantr create <type> <name>")} to create custom content if needed`);
4290
+ return;
4291
+ }
4292
+ if (requestedBlueprint || requestedArchetype) {
4293
+ console.log(error3("\nThe requested blueprint/archetype could not be resolved from the hosted registry or local cache."));
4294
+ console.log(dim3("Run `decantr sync`, set DECANTR_CONTENT_DIR, or retry when the registry is reachable."));
4295
+ process.exitCode = 1;
3594
4296
  return;
3595
4297
  }
3596
4298
  console.log(`
@@ -3644,8 +4346,8 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3644
4346
  if (blueprintResult) {
3645
4347
  const blueprint = blueprintResult.data;
3646
4348
  if (blueprint.theme) {
3647
- if (!userExplicit.theme && (blueprint.theme.id || blueprint.theme.style)) {
3648
- options.theme = blueprint.theme.id || blueprint.theme.style;
4349
+ if (!userExplicit.theme && blueprint.theme.id) {
4350
+ options.theme = blueprint.theme.id;
3649
4351
  }
3650
4352
  if (!userExplicit.mode && blueprint.theme.mode) {
3651
4353
  options.mode = blueprint.theme.mode;
@@ -3663,9 +4365,9 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3663
4365
  for (const entry of entries) {
3664
4366
  const id = typeof entry === "string" ? entry : entry.archetype;
3665
4367
  const r = await registryClient.fetchArchetype(id);
3666
- results.push([id, r?.data ?? null]);
4368
+ results.push([id, r?.data ? mapRegistryArchetypeToArchetypeData(r.data) : null]);
3667
4369
  }
3668
- const archetypeMap = new Map(results.map(([id, data]) => [id, data || null]));
4370
+ const archetypeMap = new Map(results);
3669
4371
  const composed = composeArchetypes(entries, archetypeMap);
3670
4372
  const primaryId = typeof entries[0] === "string" ? entries[0] : entries[0].archetype;
3671
4373
  archetypeData = {
@@ -3700,9 +4402,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3700
4402
  if (page.patterns) {
3701
4403
  for (const ref of page.patterns) allPatternIds.add(ref.pattern);
3702
4404
  }
3703
- for (const item of page.layout) {
3704
- if (typeof item === "string") allPatternIds.add(item);
3705
- }
4405
+ for (const patternId of collectPatternIdsFromItems(page.layout)) allPatternIds.add(patternId);
3706
4406
  }
3707
4407
  }
3708
4408
  patternSpecs = {};
@@ -3711,14 +4411,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3711
4411
  try {
3712
4412
  const result2 = await registryClient.fetchPattern(pid);
3713
4413
  if (result2) {
3714
- const inner = result2.data;
3715
- const defaultPreset = inner.default_preset || "standard";
3716
- const preset = inner.presets?.[defaultPreset];
3717
- patternSpecs[pid] = {
3718
- description: inner.description || "",
3719
- components: inner.components || [],
3720
- slots: preset?.layout?.slots || {}
3721
- };
4414
+ patternSpecs[pid] = mapRegistryPatternToPatternSpecSummary(result2.data, void 0, false);
3722
4415
  }
3723
4416
  } catch {
3724
4417
  }
@@ -3727,7 +4420,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3727
4420
  const zoneInputs = [];
3728
4421
  for (const entry of entries) {
3729
4422
  const arcId = typeof entry === "string" ? entry : entry.archetype;
3730
- const explicitRole = typeof entry === "object" && "role" in entry ? entry.role : void 0;
4423
+ const explicitRole = typeof entry === "string" ? void 0 : entry.role;
3731
4424
  const archData = archetypeMap.get(arcId);
3732
4425
  if (archData) {
3733
4426
  zoneInputs.push({
@@ -3758,13 +4451,25 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3758
4451
  ) : "";
3759
4452
  }
3760
4453
  } else {
4454
+ if (requestedBlueprint) {
4455
+ console.log(error3(` Error: Could not fetch blueprint "${options.blueprint}".`));
4456
+ console.log(dim3("Resolve local registry content or retry against the hosted registry."));
4457
+ process.exitCode = 1;
4458
+ return;
4459
+ }
3761
4460
  console.log(`${YELLOW9} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET13}`);
3762
4461
  }
3763
4462
  } else if (options.archetype) {
3764
4463
  const archetypeResult = await registryClient.fetchArchetype(options.archetype);
3765
4464
  if (archetypeResult) {
3766
- archetypeData = archetypeResult.data;
4465
+ archetypeData = mapRegistryArchetypeToArchetypeData(archetypeResult.data);
3767
4466
  } else {
4467
+ if (requestedArchetype) {
4468
+ console.log(error3(` Error: Could not fetch archetype "${options.archetype}".`));
4469
+ console.log(dim3("Resolve local registry content or retry against the hosted registry."));
4470
+ process.exitCode = 1;
4471
+ return;
4472
+ }
3768
4473
  console.log(`${YELLOW9} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET13}`);
3769
4474
  }
3770
4475
  }
@@ -3772,24 +4477,14 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3772
4477
  if (options.theme) {
3773
4478
  const themeResult = await registryClient.fetchTheme(options.theme);
3774
4479
  if (themeResult) {
3775
- const theme = themeResult.data;
3776
- themeData = {
3777
- seed: theme.seed,
3778
- palette: theme.palette,
3779
- tokens: theme.tokens,
3780
- cvd_support: theme.cvd_support,
3781
- typography: theme.typography,
3782
- motion: theme.motion,
3783
- decorators: theme.decorators,
3784
- treatments: theme.treatments,
3785
- spatial: theme.spatial,
3786
- radius: theme.radius,
3787
- shell: theme.shell,
3788
- effects: theme.effects,
3789
- compositions: theme.compositions,
3790
- pattern_preferences: theme.pattern_preferences
3791
- };
4480
+ themeData = mapRegistryThemeToThemeData(themeResult.data);
3792
4481
  } else {
4482
+ if (requestedTheme) {
4483
+ console.log(error3(` Error: Could not fetch theme "${options.theme}".`));
4484
+ console.log(dim3("Resolve local registry content or retry against the hosted registry."));
4485
+ process.exitCode = 1;
4486
+ return;
4487
+ }
3793
4488
  console.log(`${YELLOW9} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET13}`);
3794
4489
  }
3795
4490
  }
@@ -3819,8 +4514,12 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3819
4514
  }
3820
4515
  console.log("");
3821
4516
  console.log(" Next steps:");
3822
- console.log(" 1. Review DECANTR.md for methodology");
3823
- console.log(" 2. Explore more at decantr.ai/registry");
4517
+ console.log(" 1. Read DECANTR.md for methodology, CSS approach, and guard rules");
4518
+ console.log(" 2. Read .decantr/context/scaffold-pack.md first, then .decantr/context/scaffold.md");
4519
+ console.log(" 3. Read the matching section and page packs before implementing each route");
4520
+ console.log(" 4. Build the shell and route structure first, then implement the pages");
4521
+ console.log(" 5. Run decantr check and decantr audit after implementation");
4522
+ console.log(" 6. Explore more at decantr.ai/registry");
3824
4523
  console.log("");
3825
4524
  console.log(" Commands:");
3826
4525
  console.log(` ${cyan3("decantr status")} Project health`);
@@ -3830,7 +4529,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
3830
4529
  console.log(` ${cyan3("decantr upgrade")} Update to latest patterns`);
3831
4530
  console.log(` ${cyan3("decantr check")} Detect drift issues`);
3832
4531
  console.log(` ${cyan3("decantr migrate")} Migrate v2 essence to v3`);
3833
- const essenceContent = readFileSync15(result.essencePath, "utf-8");
4532
+ const essenceContent = readFileSync16(result.essencePath, "utf-8");
3834
4533
  const essence = JSON.parse(essenceContent);
3835
4534
  if (essence.version !== "3.1.0") {
3836
4535
  const validation = validateEssence2(essence);
@@ -3877,16 +4576,16 @@ Validation warnings: ${validation.errors.join(", ")}`));
3877
4576
  }
3878
4577
  async function cmdStatus() {
3879
4578
  const projectRoot = process.cwd();
3880
- const essencePath = join23(projectRoot, "decantr.essence.json");
3881
- const projectJsonPath = join23(projectRoot, ".decantr", "project.json");
4579
+ const essencePath = join24(projectRoot, "decantr.essence.json");
4580
+ const projectJsonPath = join24(projectRoot, ".decantr", "project.json");
3882
4581
  console.log(heading2("Decantr Project Status"));
3883
- if (!existsSync23(essencePath)) {
4582
+ if (!existsSync24(essencePath)) {
3884
4583
  console.log(`${RED11}No decantr.essence.json found.${RESET13}`);
3885
4584
  console.log(dim3('Run "decantr init" to create one.'));
3886
4585
  return;
3887
4586
  }
3888
4587
  try {
3889
- const essence = JSON.parse(readFileSync15(essencePath, "utf-8"));
4588
+ const essence = JSON.parse(readFileSync16(essencePath, "utf-8"));
3890
4589
  const validation = validateEssence2(essence);
3891
4590
  const essenceVersion = isV36(essence) ? "v3" : "v2";
3892
4591
  console.log(`${BOLD6}Essence:${RESET13}`);
@@ -3897,8 +4596,12 @@ async function cmdStatus() {
3897
4596
  }
3898
4597
  if (isV36(essence)) {
3899
4598
  const v3 = essence;
4599
+ const sections = v3.blueprint.sections ?? [];
4600
+ const flatPages = sections.length > 0 ? sections.flatMap((section) => section.pages ?? []) : v3.blueprint.pages ?? [];
4601
+ const resolvedShell = sections.find((section) => section.role === "primary")?.shell || sections[0]?.shell || v3.blueprint.shell || "unknown";
4602
+ const resolvedFeatures = v3.blueprint.features ?? [];
3900
4603
  console.log(` ${BOLD6}DNA:${RESET13}`);
3901
- console.log(` Theme: ${v3.dna.theme.style} (${v3.dna.theme.mode})`);
4604
+ console.log(` Theme: ${v3.dna.theme.id} (${v3.dna.theme.mode})`);
3902
4605
  console.log(` Spacing: ${v3.dna.spacing.density} density, ${v3.dna.spacing.content_gap} gap`);
3903
4606
  console.log(` Typography: ${v3.dna.typography.scale} scale`);
3904
4607
  console.log(` Radius: ${v3.dna.radius.philosophy} (base ${v3.dna.radius.base}px)`);
@@ -3906,9 +4609,12 @@ async function cmdStatus() {
3906
4609
  console.log(` Accessibility: WCAG ${v3.dna.accessibility.wcag_level}`);
3907
4610
  console.log(` Personality: ${v3.dna.personality.join(", ")}`);
3908
4611
  console.log(` ${BOLD6}Blueprint:${RESET13}`);
3909
- console.log(` Shell: ${v3.blueprint.shell}`);
3910
- console.log(` Pages: ${v3.blueprint.pages.length}`);
3911
- console.log(` Features: ${v3.blueprint.features.length > 0 ? v3.blueprint.features.join(", ") : "none"}`);
4612
+ console.log(` Shell: ${resolvedShell}`);
4613
+ console.log(` Pages: ${flatPages.length}`);
4614
+ if (sections.length > 0) {
4615
+ console.log(` Sections: ${sections.length}`);
4616
+ }
4617
+ console.log(` Features: ${resolvedFeatures.length > 0 ? resolvedFeatures.join(", ") : "none"}`);
3912
4618
  console.log(` ${BOLD6}Meta:${RESET13}`);
3913
4619
  console.log(` Archetype: ${v3.meta.archetype}`);
3914
4620
  console.log(` Target: ${v3.meta.target}`);
@@ -3918,7 +4624,7 @@ async function cmdStatus() {
3918
4624
  const theme = e.theme;
3919
4625
  const guard = e.guard;
3920
4626
  const structure = e.structure;
3921
- console.log(` Theme: ${theme?.style || "unknown"} (${theme?.mode || "unknown"})`);
4627
+ console.log(` Theme: ${theme?.id || "unknown"} (${theme?.mode || "unknown"})`);
3922
4628
  console.log(` Guard: ${guard?.mode || "unknown"}`);
3923
4629
  console.log(` Pages: ${(structure || []).length}`);
3924
4630
  console.log(` ${YELLOW9}Tip: Run \`decantr migrate\` to upgrade to v3.${RESET13}`);
@@ -3928,9 +4634,9 @@ async function cmdStatus() {
3928
4634
  }
3929
4635
  console.log("");
3930
4636
  console.log(`${BOLD6}Sync Status:${RESET13}`);
3931
- if (existsSync23(projectJsonPath)) {
4637
+ if (existsSync24(projectJsonPath)) {
3932
4638
  try {
3933
- const projectJson = JSON.parse(readFileSync15(projectJsonPath, "utf-8"));
4639
+ const projectJson = JSON.parse(readFileSync16(projectJsonPath, "utf-8"));
3934
4640
  const syncStatus = projectJson.sync?.status || "unknown";
3935
4641
  const lastSync = projectJson.sync?.lastSync || "never";
3936
4642
  const source = projectJson.sync?.registrySource || "unknown";
@@ -3948,7 +4654,7 @@ async function cmdStatus() {
3948
4654
  }
3949
4655
  async function cmdSync() {
3950
4656
  const projectRoot = process.cwd();
3951
- const cacheDir = join23(projectRoot, ".decantr", "cache");
4657
+ const cacheDir = join24(projectRoot, ".decantr", "cache");
3952
4658
  console.log(heading2("Syncing registry content..."));
3953
4659
  const result = await syncRegistry(cacheDir);
3954
4660
  if (result.synced.length > 0) {
@@ -3964,47 +4670,110 @@ async function cmdSync() {
3964
4670
  }
3965
4671
  }
3966
4672
  }
3967
- async function cmdAudit() {
3968
- const projectRoot = process.cwd();
3969
- const essencePath = join23(projectRoot, "decantr.essence.json");
3970
- console.log(heading2("Auditing project..."));
3971
- if (!existsSync23(essencePath)) {
3972
- console.log(`${RED11}No decantr.essence.json found.${RESET13}`);
3973
- process.exitCode = 1;
4673
+ function printVerificationFindings(findings) {
4674
+ if (findings.length === 0) {
4675
+ console.log(success3("No findings."));
3974
4676
  return;
3975
4677
  }
4678
+ for (const finding of findings) {
4679
+ const color = finding.severity === "error" ? RED11 : finding.severity === "warn" ? YELLOW9 : CYAN7;
4680
+ console.log(` ${color}[${finding.severity.toUpperCase()}]${RESET13} ${finding.category}: ${finding.message}`);
4681
+ for (const evidence of finding.evidence) {
4682
+ console.log(` ${DIM13}${evidence}${RESET13}`);
4683
+ }
4684
+ if (finding.suggestedFix) {
4685
+ console.log(` ${DIM13}Fix: ${finding.suggestedFix}${RESET13}`);
4686
+ }
4687
+ }
4688
+ }
4689
+ function printProjectAuditReport(report) {
4690
+ if (report.valid) {
4691
+ console.log(success3("Project contract is valid."));
4692
+ } else {
4693
+ console.log(`${RED11}Project audit found blocking issues.${RESET13}`);
4694
+ }
4695
+ console.log("");
4696
+ console.log(`${BOLD6}Summary:${RESET13}`);
4697
+ console.log(` Essence version: ${report.summary.essenceVersion ?? "missing"}`);
4698
+ console.log(` Pages defined: ${report.summary.pageCount}`);
4699
+ console.log(` Pack manifest: ${report.summary.packManifestPresent ? "present" : "missing"}`);
4700
+ console.log(` Review pack: ${report.summary.reviewPackPresent ? "present" : "missing"}`);
4701
+ const runtimeStatus = report.summary.runtimeAuditChecked ? report.summary.runtimePassed ? "passed" : "failed" : report.runtimeAudit.distPresent ? "incomplete" : "pending (no dist/)";
4702
+ console.log(` Runtime audit: ${runtimeStatus}`);
4703
+ if (report.summary.runtimeAuditChecked && report.runtimeAudit.assetCount > 0) {
4704
+ const fmt = (bytes) => bytes >= 1e6 ? `${(bytes / 1e6).toFixed(2)} MB` : `${Math.round(bytes / 1e3)} KB`;
4705
+ console.log(
4706
+ ` Built assets: total ${fmt(report.runtimeAudit.totalAssetBytes)} | js ${fmt(report.runtimeAudit.jsAssetBytes)} | css ${fmt(report.runtimeAudit.cssAssetBytes)}`
4707
+ );
4708
+ console.log(
4709
+ ` Document hardening: lang ${report.runtimeAudit.langOk ? "ok" : "missing"} | viewport ${report.runtimeAudit.viewportOk ? "ok" : "missing"} | charset ${report.runtimeAudit.charsetOk ? "ok" : "missing"} | csp ${report.runtimeAudit.cspSignalOk ? "present" : "missing"}`
4710
+ );
4711
+ console.log(
4712
+ ` Route document shell: root docs ${report.runtimeAudit.routeDocumentsPassed}/${report.runtimeAudit.routeDocumentsChecked} | hardened docs ${report.runtimeAudit.routeDocumentsHardenedCount}/${report.runtimeAudit.routeDocumentsChecked}`
4713
+ );
4714
+ console.log(
4715
+ ` Script hygiene: inline scripts ${report.runtimeAudit.inlineScriptCount} | inline event handlers ${report.runtimeAudit.inlineEventHandlerCount} | scripts without integrity ${report.runtimeAudit.externalScriptsWithoutIntegrityCount} | scripts missing crossorigin ${report.runtimeAudit.externalScriptsWithIntegrityMissingCrossoriginCount} | stylesheets without integrity ${report.runtimeAudit.externalStylesheetsWithoutIntegrityCount} | stylesheets missing crossorigin ${report.runtimeAudit.externalStylesheetsWithIntegrityMissingCrossoriginCount} | insecure external scripts ${report.runtimeAudit.externalScriptsWithInsecureTransportCount} | insecure external stylesheets ${report.runtimeAudit.externalStylesheetsWithInsecureTransportCount} | insecure external media ${report.runtimeAudit.externalMediaSourcesWithInsecureTransportCount} | external blank links missing rel ${report.runtimeAudit.externalBlankLinksWithoutRelCount} | external iframes missing sandbox ${report.runtimeAudit.externalIframesWithoutSandboxCount} | insecure external iframes ${report.runtimeAudit.externalIframesWithInsecureTransportCount}`
4716
+ );
4717
+ console.log(
4718
+ ` JS risk signals: dynamic code ${report.runtimeAudit.jsEvalSignalCount} | html injection ${report.runtimeAudit.jsHtmlInjectionSignalCount} | insecure/dev transport ${report.runtimeAudit.jsInsecureTransportSignalCount} | secret markers ${report.runtimeAudit.jsSecretSignalCount}`
4719
+ );
4720
+ }
4721
+ console.log(` Findings: ${report.summary.errorCount} error(s), ${report.summary.warnCount} warn(s), ${report.summary.infoCount} info`);
4722
+ console.log("");
4723
+ console.log(`${BOLD6}Findings:${RESET13}`);
4724
+ printVerificationFindings(report.findings);
4725
+ }
4726
+ function printFileCritiqueReport(report) {
4727
+ console.log(success3(`Critiqued ${report.file}`));
4728
+ console.log("");
4729
+ console.log(`${BOLD6}Summary:${RESET13}`);
4730
+ console.log(` Overall score: ${report.overall}/5`);
4731
+ console.log(` Focus areas: ${report.focusAreas.join(", ")}`);
4732
+ console.log(` Review pack: ${report.reviewPack ? "present" : "missing"}`);
4733
+ console.log("");
4734
+ console.log(`${BOLD6}Scores:${RESET13}`);
4735
+ for (const score of report.scores) {
4736
+ console.log(` ${cyan3(score.category.padEnd(20))} ${score.score}/5 ${dim3(score.details)}`);
4737
+ }
4738
+ console.log("");
4739
+ console.log(`${BOLD6}Findings:${RESET13}`);
4740
+ printVerificationFindings(report.findings);
4741
+ }
4742
+ async function cmdAudit(filePath) {
4743
+ const projectRoot = process.cwd();
3976
4744
  try {
3977
- const essence = JSON.parse(readFileSync15(essencePath, "utf-8"));
3978
- const validation = validateEssence2(essence);
3979
- if (!validation.valid) {
3980
- console.log(`${RED11}Essence validation failed:${RESET13}`);
3981
- for (const err of validation.errors) {
3982
- console.log(` ${RED11}${err}${RESET13}`);
4745
+ if (filePath) {
4746
+ const hydration2 = await hydrateHostedReviewPackIfMissing(projectRoot);
4747
+ console.log(heading2(`Critiquing ${filePath}...`));
4748
+ if (hydration2.hydrated) {
4749
+ console.log(dim3("Hydrated missing review pack from hosted registry."));
4750
+ console.log("");
3983
4751
  }
4752
+ const report2 = await critiqueProjectFile(filePath, projectRoot);
4753
+ printFileCritiqueReport(report2);
4754
+ if (report2.findings.some((finding) => finding.severity === "error")) {
4755
+ process.exitCode = 1;
4756
+ }
4757
+ return;
4758
+ }
4759
+ const hydration = await hydrateHostedExecutionPacksIfMissing(projectRoot);
4760
+ console.log(heading2("Auditing project..."));
4761
+ if (hydration.hydrated) {
4762
+ console.log(dim3(
4763
+ hydration.scope === "bundle" ? "Hydrated missing execution packs from hosted registry." : "Hydrated missing review pack and manifest from hosted registry."
4764
+ ));
4765
+ console.log("");
4766
+ }
4767
+ const report = await auditProject(projectRoot);
4768
+ printProjectAuditReport(report);
4769
+ if (!report.valid) {
3984
4770
  process.exitCode = 1;
3985
4771
  return;
3986
4772
  }
3987
- console.log(success3("Essence is valid."));
3988
- const { themeRegistry, patternRegistry } = buildRegistryContext();
3989
- const violations = evaluateGuard(essence, { themeRegistry, patternRegistry });
3990
- if (violations.length > 0) {
4773
+ if (report.findings.length > 0) {
3991
4774
  console.log("");
3992
- console.log(`${YELLOW9}Guard violations:${RESET13}`);
3993
- for (const v of violations) {
3994
- const vr = v;
3995
- console.log(` ${YELLOW9}[${vr.rule}]${RESET13} ${vr.message}`);
3996
- if (vr.suggestion) {
3997
- console.log(` ${DIM13}Suggestion: ${vr.suggestion}${RESET13}`);
3998
- }
3999
- }
4000
- } else {
4001
- console.log(success3("No guard violations."));
4775
+ console.log(dim3("Project audit completed with advisory findings."));
4002
4776
  }
4003
- console.log("");
4004
- console.log(`${BOLD6}Summary:${RESET13}`);
4005
- console.log(` Pages defined: ${essence.structure.length}`);
4006
- console.log(` Guard mode: ${essence.guard.mode}`);
4007
- console.log(` Theme: ${essence.theme.style}`);
4008
4777
  } catch (e) {
4009
4778
  console.log(`${RED11}Error: ${e.message}${RESET13}`);
4010
4779
  process.exitCode = 1;
@@ -4047,7 +4816,7 @@ ${BOLD6}Examples:${RESET13}
4047
4816
  console.log(success3(`Created custom theme "${name}"`));
4048
4817
  console.log(dim3(` Path: ${result.path}`));
4049
4818
  console.log("");
4050
- console.log(`Use in essence: ${cyan3(`"style": "custom:${name}"`)}`);
4819
+ console.log(`Use in essence: ${cyan3(`"id": "custom:${name}"`)}`);
4051
4820
  } else {
4052
4821
  console.error(error3(result.error || "Failed to create theme"));
4053
4822
  process.exitCode = 1;
@@ -4074,14 +4843,14 @@ ${BOLD6}Examples:${RESET13}
4074
4843
  process.exitCode = 1;
4075
4844
  return;
4076
4845
  }
4077
- const themePath = join23(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
4078
- if (!existsSync23(themePath)) {
4846
+ const themePath = join24(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
4847
+ if (!existsSync24(themePath)) {
4079
4848
  console.error(error3(`Theme "${name}" not found at ${themePath}`));
4080
4849
  process.exitCode = 1;
4081
4850
  return;
4082
4851
  }
4083
4852
  try {
4084
- const theme = JSON.parse(readFileSync15(themePath, "utf-8"));
4853
+ const theme = JSON.parse(readFileSync16(themePath, "utf-8"));
4085
4854
  const result = validateCustomTheme(theme);
4086
4855
  if (result.valid) {
4087
4856
  console.log(success3(`Custom theme "${name}" is valid`));
@@ -4159,14 +4928,20 @@ ${BOLD6}Usage:${RESET13}
4159
4928
  decantr init [options]
4160
4929
  decantr status
4161
4930
  decantr sync
4162
- decantr audit
4931
+ decantr audit [file]
4163
4932
  decantr migrate
4164
4933
  decantr check
4165
4934
  decantr sync-drift
4166
- decantr search <query> [--type <type>]
4935
+ decantr search <query> [--type <type>] [--sort <recommended|recent|name>] [--recommended] [--source <authored|benchmark|hybrid>]
4167
4936
  decantr suggest <query> [--type <type>]
4168
4937
  decantr get <type> <id>
4169
- decantr list <type>
4938
+ decantr list <type> [--sort <recommended|recent|name>] [--recommended] [--source <authored|benchmark|hybrid>]
4939
+ decantr showcase [manifest|shortlist|verification] [--json]
4940
+ decantr registry summary [--namespace <namespace>] [--json]
4941
+ decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
4942
+ decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
4943
+ decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]
4944
+ decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]
4170
4945
  decantr validate [path]
4171
4946
  decantr theme <subcommand>
4172
4947
  decantr create <type> <name>
@@ -4196,7 +4971,7 @@ ${BOLD6}Commands:${RESET13}
4196
4971
  ${cyan3("init")} Initialize Decantr in an existing project (v3 essence by default)
4197
4972
  ${cyan3("status")} Show project status, DNA axioms, and blueprint info
4198
4973
  ${cyan3("sync")} Sync registry content from API
4199
- ${cyan3("audit")} Validate essence and check for drift
4974
+ ${cyan3("audit")} Audit the project or critique a specific file against compiled packs
4200
4975
  ${cyan3("migrate")} Migrate v2 essence to v3 format (with .v2.backup.json backup)
4201
4976
  ${cyan3("check")} Detect drift issues (validate + guard rules) [--telemetry]
4202
4977
  ${cyan3("sync-drift")} Review and resolve drift log entries
@@ -4204,6 +4979,7 @@ ${BOLD6}Commands:${RESET13}
4204
4979
  ${cyan3("suggest")} Suggest patterns or alternatives for a query
4205
4980
  ${cyan3("get")} Get full details of a registry item
4206
4981
  ${cyan3("list")} List items by type
4982
+ ${cyan3("showcase")} Inspect audited showcase benchmark metadata
4207
4983
  ${cyan3("validate")} Validate essence file (v2 and v3)
4208
4984
  ${cyan3("theme")} Manage custom themes (create, list, validate, delete, import)
4209
4985
  ${cyan3("create")} Create a custom content item (pattern, theme, blueprint, etc.)
@@ -4212,7 +4988,7 @@ ${BOLD6}Commands:${RESET13}
4212
4988
  ${cyan3("logout")} Remove stored credentials
4213
4989
  ${cyan3("analyze")} Scan existing project and produce analysis report
4214
4990
  ${cyan3("export")} Export design tokens to framework format (shadcn, tailwind, css-vars)
4215
- ${cyan3("registry")} Registry management (mirror)
4991
+ ${cyan3("registry")} Registry management and intelligence summary
4216
4992
  ${cyan3("upgrade")} Check for content updates from registry
4217
4993
  ${cyan3("help")} Show this help
4218
4994
 
@@ -4222,12 +4998,24 @@ ${BOLD6}Examples:${RESET13}
4222
4998
  decantr init
4223
4999
  decantr init --blueprint=saas-dashboard --theme=luminarum --yes
4224
5000
  decantr status
5001
+ decantr audit
5002
+ decantr audit src/pages/HomePage.tsx
4225
5003
  decantr migrate
4226
5004
  decantr check
4227
5005
  decantr sync-drift
4228
5006
  decantr search dashboard
4229
5007
  decantr suggest leaderboard
4230
5008
  decantr list patterns
5009
+ decantr showcase shortlist
5010
+ decantr showcase verification --json
5011
+ decantr registry summary --namespace @official
5012
+ decantr registry compile-packs decantr.essence.json --json
5013
+ decantr registry compile-packs decantr.essence.json --write-context
5014
+ decantr registry get-pack manifest --namespace @official --json
5015
+ decantr registry get-pack review --namespace @official --write-context
5016
+ decantr registry critique-file src/pages/Home.tsx --namespace @official --json
5017
+ decantr registry audit-project --namespace @official --json
5018
+ decantr registry audit-project --namespace @official --dist dist --sources src
4231
5019
  decantr create pattern my-card
4232
5020
  `);
4233
5021
  }
@@ -4266,6 +5054,7 @@ async function main() {
4266
5054
  theme: newOpts.theme,
4267
5055
  mode: newOpts.mode,
4268
5056
  shape: newOpts.shape,
5057
+ target: newOpts.target,
4269
5058
  offline: newOpts.offline === true,
4270
5059
  registry: newOpts.registry
4271
5060
  });
@@ -4306,7 +5095,7 @@ async function main() {
4306
5095
  break;
4307
5096
  }
4308
5097
  case "upgrade": {
4309
- const { cmdUpgrade } = await import("./upgrade-GTUGOUSD.js");
5098
+ const { cmdUpgrade } = await import("./upgrade-XNUAON3G.js");
4310
5099
  const applyFlag = args.includes("--apply");
4311
5100
  await cmdUpgrade(process.cwd(), { apply: applyFlag });
4312
5101
  break;
@@ -4316,7 +5105,7 @@ async function main() {
4316
5105
  if (command === "heal") {
4317
5106
  console.log(`${YELLOW9}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET13}`);
4318
5107
  }
4319
- const { cmdHeal } = await import("./heal-VYEGIUAS.js");
5108
+ const { cmdHeal } = await import("./heal-MURR3RVQ.js");
4320
5109
  const telemetryFlag = args.includes("--telemetry");
4321
5110
  await cmdHeal(process.cwd(), { telemetry: telemetryFlag });
4322
5111
  break;
@@ -4348,19 +5137,29 @@ async function main() {
4348
5137
  break;
4349
5138
  }
4350
5139
  case "audit": {
4351
- await cmdAudit();
5140
+ await cmdAudit(args[1]);
4352
5141
  break;
4353
5142
  }
4354
5143
  case "search": {
4355
5144
  const query = args[1];
4356
5145
  if (!query) {
4357
- console.error(error3("Usage: decantr search <query> [--type <type>]"));
5146
+ console.error(error3("Usage: decantr search <query> [--type <type>] [--sort <recommended|recent|name>] [--source <authored|benchmark|hybrid>]"));
4358
5147
  process.exitCode = 1;
4359
5148
  return;
4360
5149
  }
4361
5150
  const typeIdx = args.indexOf("--type");
4362
5151
  const type = typeIdx !== -1 ? args[typeIdx + 1] : void 0;
4363
- await cmdSearch(query, type);
5152
+ const sortIdx = args.indexOf("--sort");
5153
+ const sort = sortIdx !== -1 ? args[sortIdx + 1] : void 0;
5154
+ const sourceIdx = args.indexOf("--source");
5155
+ const intelligenceSource = sourceIdx !== -1 ? args[sourceIdx + 1] : void 0;
5156
+ if (intelligenceSource && !isContentIntelligenceSource(intelligenceSource)) {
5157
+ console.error(error3(`Invalid source "${intelligenceSource}". Must be one of: authored, benchmark, hybrid.`));
5158
+ process.exitCode = 1;
5159
+ return;
5160
+ }
5161
+ const recommended = args.includes("--recommended");
5162
+ await cmdSearch(query, type, sort, recommended, intelligenceSource);
4364
5163
  break;
4365
5164
  }
4366
5165
  case "suggest": {
@@ -4389,11 +5188,37 @@ async function main() {
4389
5188
  case "list": {
4390
5189
  const type = args[1];
4391
5190
  if (!type) {
4392
- console.error(error3("Usage: decantr list <type>"));
5191
+ console.error(error3("Usage: decantr list <type> [--sort <recommended|recent|name>] [--source <authored|benchmark|hybrid>]"));
4393
5192
  process.exitCode = 1;
4394
5193
  return;
4395
5194
  }
4396
- await cmdList(type);
5195
+ const sortIdx = args.indexOf("--sort");
5196
+ const sort = sortIdx !== -1 ? args[sortIdx + 1] : void 0;
5197
+ const sourceIdx = args.indexOf("--source");
5198
+ const intelligenceSource = sourceIdx !== -1 ? args[sourceIdx + 1] : void 0;
5199
+ if (intelligenceSource && !isContentIntelligenceSource(intelligenceSource)) {
5200
+ console.error(error3(`Invalid source "${intelligenceSource}". Must be one of: authored, benchmark, hybrid.`));
5201
+ process.exitCode = 1;
5202
+ return;
5203
+ }
5204
+ const recommended = args.includes("--recommended");
5205
+ await cmdList(type, sort, recommended, intelligenceSource);
5206
+ break;
5207
+ }
5208
+ case "showcase": {
5209
+ const requestedView = args[1];
5210
+ const view = requestedView === "manifest" || requestedView === "shortlist" || requestedView === "verification" ? requestedView : "shortlist";
5211
+ const jsonOutput = args.includes("--json");
5212
+ if (requestedView && requestedView.startsWith("--")) {
5213
+ await printShowcaseBenchmarks("shortlist", jsonOutput);
5214
+ break;
5215
+ }
5216
+ if (requestedView && !["manifest", "shortlist", "verification"].includes(requestedView)) {
5217
+ console.error(error3("Usage: decantr showcase [manifest|shortlist|verification] [--json]"));
5218
+ process.exitCode = 1;
5219
+ break;
5220
+ }
5221
+ await printShowcaseBenchmarks(view, jsonOutput);
4397
5222
  break;
4398
5223
  }
4399
5224
  case "validate": {
@@ -4469,8 +5294,72 @@ async function main() {
4469
5294
  const typeIdx = args.indexOf("--type");
4470
5295
  const mirrorType = typeIdx !== -1 ? args[typeIdx + 1] : void 0;
4471
5296
  await cmdRegistryMirror(process.cwd(), { type: mirrorType });
5297
+ } else if (subcommand === "summary") {
5298
+ const namespaceIdx = args.indexOf("--namespace");
5299
+ const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
5300
+ const jsonOutput = args.includes("--json");
5301
+ await printRegistryIntelligenceSummary(namespace, jsonOutput);
5302
+ } else if (subcommand === "compile-packs") {
5303
+ const namespaceIdx = args.indexOf("--namespace");
5304
+ const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
5305
+ const jsonOutput = args.includes("--json");
5306
+ const writeContext = args.includes("--write-context");
5307
+ const essencePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
5308
+ await printHostedExecutionPackBundle(essencePath, namespace, jsonOutput, writeContext);
5309
+ } else if (subcommand === "get-pack") {
5310
+ const namespaceIdx = args.indexOf("--namespace");
5311
+ const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
5312
+ const jsonOutput = args.includes("--json");
5313
+ const writeContext = args.includes("--write-context");
5314
+ const essenceIdx = args.indexOf("--essence");
5315
+ const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
5316
+ const packType = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
5317
+ const id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
5318
+ if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
5319
+ console.error(`${RED11}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET13}`);
5320
+ process.exitCode = 1;
5321
+ break;
5322
+ }
5323
+ if (packType === "manifest") {
5324
+ await printHostedExecutionPackManifest(essencePath, namespace, jsonOutput, writeContext);
5325
+ break;
5326
+ }
5327
+ await printHostedSelectedExecutionPack(
5328
+ packType,
5329
+ id,
5330
+ essencePath,
5331
+ namespace,
5332
+ jsonOutput,
5333
+ writeContext
5334
+ );
5335
+ } else if (subcommand === "critique-file") {
5336
+ const namespaceIdx = args.indexOf("--namespace");
5337
+ const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
5338
+ const jsonOutput = args.includes("--json");
5339
+ const essenceIdx = args.indexOf("--essence");
5340
+ const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
5341
+ const treatmentsIdx = args.indexOf("--treatments");
5342
+ const treatmentsPath = treatmentsIdx !== -1 ? args[treatmentsIdx + 1] : void 0;
5343
+ const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
5344
+ if (!sourcePath) {
5345
+ console.error(`${RED11}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET13}`);
5346
+ process.exitCode = 1;
5347
+ break;
5348
+ }
5349
+ await printHostedFileCritique(sourcePath, namespace, jsonOutput, essencePath, treatmentsPath);
5350
+ } else if (subcommand === "audit-project") {
5351
+ const namespaceIdx = args.indexOf("--namespace");
5352
+ const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
5353
+ const jsonOutput = args.includes("--json");
5354
+ const essenceIdx = args.indexOf("--essence");
5355
+ const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
5356
+ const distIdx = args.indexOf("--dist");
5357
+ const distPath = distIdx !== -1 ? args[distIdx + 1] : void 0;
5358
+ const sourcesIdx = args.indexOf("--sources");
5359
+ const sourcesPath = sourcesIdx !== -1 ? args[sourcesIdx + 1] : void 0;
5360
+ await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
4472
5361
  } else {
4473
- console.error(`${RED11}Usage: decantr registry mirror [--type <type>]${RESET13}`);
5362
+ console.error(`${RED11}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${RESET13}`);
4474
5363
  process.exitCode = 1;
4475
5364
  }
4476
5365
  break;