@decantr/core 1.0.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ npm install @decantr/core
15
15
 
16
16
  ## Stability
17
17
 
18
- `@decantr/core` is published for advanced package consumers that need low-level execution-pack primitives. It is stable in the `1.x` line for the documented exports in this package, but it is still not the recommended first integration surface for most Decantr adopters.
18
+ `@decantr/core` is published for advanced package consumers that need low-level execution-pack primitives. It is stable in the `2.x` line for the documented exports in this package, but it is still not the recommended first integration surface for most Decantr adopters.
19
19
 
20
20
  ## What It Exports
21
21
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { StructurePage, EssenceFile, EssenceV3 } from '@decantr/essence-spec';
1
+ import { StructurePage, EssenceFile, EssenceV4 } from '@decantr/essence-spec';
2
2
  import { Pattern, ResolvedPreset, Theme, ContentResolver } from '@decantr/registry';
3
3
 
4
4
  type IRNodeType = 'app' | 'shell' | 'page' | 'pattern' | 'grid' | 'nav' | 'store';
@@ -42,7 +42,7 @@ interface IRPatternMeta {
42
42
  */
43
43
  presetDescription?: string;
44
44
  /**
45
- * v2.1 Tier C1. Declared runtime interactions from the pattern JSON.
45
+ * Declared runtime interactions from the pattern JSON.
46
46
  * Page-pack renderer surfaces these as a checkbox checklist.
47
47
  */
48
48
  interactions?: string[];
@@ -92,7 +92,7 @@ interface IRRoute {
92
92
  shell: string;
93
93
  sectionId?: string;
94
94
  }
95
- /** Which v3 essence layer sourced this node */
95
+ /** Which Essence v4 layer sourced this node */
96
96
  type IRLayer = 'dna' | 'blueprint' | 'meta';
97
97
  interface IRNode {
98
98
  type: IRNodeType;
@@ -100,7 +100,7 @@ interface IRNode {
100
100
  children: IRNode[];
101
101
  spatial?: IRSpatial;
102
102
  meta?: Record<string, unknown>;
103
- /** When built from a v3 essence, indicates the originating layer */
103
+ /** When built from an Essence v4 document, indicates the originating layer */
104
104
  layer?: IRLayer;
105
105
  }
106
106
  interface IRAppNode extends IRNode {
@@ -407,7 +407,7 @@ interface PagePackPattern {
407
407
  */
408
408
  presetDescription?: string;
409
409
  /**
410
- * v2.1 Tier C1. Declared interactions from the pattern JSON. Rendered
410
+ * Declared interactions from the pattern JSON. Rendered
411
411
  * as a checkbox checklist so cold LLMs in generation mode see a
412
412
  * hard-edged list they can't categorize as "philosophy". Enforced by
413
413
  * decantr check --strict (C5 guard rule).
@@ -544,8 +544,8 @@ interface CompileExecutionPackBundleOptions {
544
544
  }
545
545
  declare function renderExecutionPackMarkdown(pack: ExecutionPackBase<unknown>): string;
546
546
  declare function resolvePackAdapter(target: string | undefined, platformType: string | undefined): string;
547
- declare function listPackSections(essence: EssenceV3): SectionPackInput[];
548
- declare function listPackPages(essence: EssenceV3): PagePackInput[];
547
+ declare function listPackSections(essence: EssenceV4): SectionPackInput[];
548
+ declare function listPackPages(essence: EssenceV4): PagePackInput[];
549
549
  declare function buildScaffoldPack(appNode: IRAppNode, options?: ScaffoldPackBuilderOptions): ScaffoldExecutionPack;
550
550
  declare function buildSectionPack(appNode: IRAppNode, input: SectionPackInput, options?: SectionPackBuilderOptions): SectionExecutionPack;
551
551
  declare function buildPagePack(appNode: IRAppNode, input: PagePackInput, options?: PagePackBuilderOptions): PageExecutionPack;
@@ -585,6 +585,44 @@ interface PipelineResult {
585
585
  */
586
586
  declare function runPipeline(essence: EssenceFile, options: PipelineOptions): Promise<PipelineResult>;
587
587
 
588
+ type RealizationAdapter = 'react-vite' | 'next-app' | 'generic-web' | string;
589
+ interface RealizationRoute {
590
+ path: string;
591
+ sectionId: string;
592
+ sectionRole: string;
593
+ pageId: string;
594
+ shell: string;
595
+ patterns: string[];
596
+ states: Array<'empty' | 'loading' | 'error'>;
597
+ }
598
+ interface RealizationMockDataSeed {
599
+ id: string;
600
+ source: 'feature' | 'route';
601
+ shape: Record<string, unknown>;
602
+ }
603
+ interface RealizationInteractionPlaceholder {
604
+ id: string;
605
+ kind: 'command-palette' | 'hotkey' | 'auth-mock' | 'route-action';
606
+ route?: string;
607
+ label: string;
608
+ }
609
+ interface RealizationPlan {
610
+ version: '1.0.0';
611
+ sourceEssenceVersion: '4.0.0';
612
+ adapter: RealizationAdapter;
613
+ canRealizeFrameworkCode: boolean;
614
+ routes: RealizationRoute[];
615
+ shell: {
616
+ id: string;
617
+ theme: string;
618
+ mode: string;
619
+ };
620
+ mockData: RealizationMockDataSeed[];
621
+ interactions: RealizationInteractionPlaceholder[];
622
+ unsupportedReason?: string;
623
+ }
624
+ declare function compileRealizationPlan(essence: EssenceV4): RealizationPlan;
625
+
588
626
  interface ResolvedPage {
589
627
  page: ResolvedStructurePage;
590
628
  patterns: Map<string, {
@@ -609,8 +647,8 @@ interface ResolvedEssence {
609
647
  shell: IRShellConfig;
610
648
  routes: IRRoute[];
611
649
  features: string[];
612
- /** True when the source essence was v3 (DNA/Blueprint/Meta) */
613
- isV3Source: boolean;
650
+ /** True when the source essence uses the active DNA/Blueprint/Meta contract. */
651
+ isBlueprintSource: boolean;
614
652
  }
615
653
  declare function resolveVisualEffects(theme: Theme, pattern: Pattern, _slot?: string): IRVisualEffect | null;
616
654
  /** Resolve all external references in an Essence file */
@@ -619,4 +657,4 @@ declare function resolveEssence(essence: EssenceFile, resolver: ContentResolver)
619
657
  /** Convert a kebab-case or snake_case string to PascalCase */
620
658
  declare function pascalCase(str: string): string;
621
659
 
622
- export { type CompileExecutionPackBundleOptions, EXECUTION_PACK_BUNDLE_SCHEMA_URL, EXECUTION_PACK_SCHEMA_URLS, type ExecutionPackAntiPattern, type ExecutionPackBase, type ExecutionPackBundle, type ExecutionPackExample, type ExecutionPackManifest, type ExecutionPackScope, type ExecutionPackSelector, type ExecutionPackSuccessCheck, type ExecutionPackTarget, type ExecutionPackTokenBudget, type ExecutionPackType, type IRAppNode, type IRBreakpointEntry, type IRCardWrapping, type IRGridNode, type IRHookType, type IRLayer, type IRNavItem, type IRNode, type IRNodeType, type IRPageNode, type IRPatternMeta, type IRPatternNode, type IRRoute, type IRShellConfig, type IRShellNode, type IRSpatial, type IRStoreNode, type IRTheme, type IRThemeDecoration, type IRVisualEffect, type IRWiring, type IRWiringSignal, type MutationExecutionPack, type MutationPackBuilderOptions, type MutationPackData, type MutationPackKind, PACK_MANIFEST_SCHEMA_URL, type PackManifestEntry, type PackManifestMutationEntry, type PackManifestPageEntry, type PackManifestSectionEntry, type PageExecutionPack, type PagePackBuilderOptions, type PagePackData, type PagePackInput, type PagePackPattern, type PipelineOptions, type PipelineResult, type ResolvedEssence, type ResolvedPage, type ReviewExecutionPack, type ReviewPackBuilderOptions, type ReviewPackData, type ReviewPackKind, SELECTED_EXECUTION_PACK_SCHEMA_URL, type ScaffoldExecutionPack, type ScaffoldPackBuilderOptions, type ScaffoldPackData, type ScaffoldPackRoute, type SectionExecutionPack, type SectionPackBuilderOptions, type SectionPackData, type SectionPackInput, type SectionPackRoute, type SelectedExecutionPack, type SelectedExecutionPackResponse, buildMutationPack, buildPageIR, buildPagePack, buildReviewPack, buildScaffoldPack, buildSectionPack, compileExecutionPackBundle, compileSelectedExecutionPack, countPatterns, findNodes, listPackPages, listPackSections, pascalCase, renderExecutionPackMarkdown, resolveEssence, resolvePackAdapter, resolveVisualEffects, runPipeline, selectExecutionPackFromBundle, validateIR, walkIR };
660
+ export { type CompileExecutionPackBundleOptions, EXECUTION_PACK_BUNDLE_SCHEMA_URL, EXECUTION_PACK_SCHEMA_URLS, type ExecutionPackAntiPattern, type ExecutionPackBase, type ExecutionPackBundle, type ExecutionPackExample, type ExecutionPackManifest, type ExecutionPackScope, type ExecutionPackSelector, type ExecutionPackSuccessCheck, type ExecutionPackTarget, type ExecutionPackTokenBudget, type ExecutionPackType, type IRAppNode, type IRBreakpointEntry, type IRCardWrapping, type IRGridNode, type IRHookType, type IRLayer, type IRNavItem, type IRNode, type IRNodeType, type IRPageNode, type IRPatternMeta, type IRPatternNode, type IRRoute, type IRShellConfig, type IRShellNode, type IRSpatial, type IRStoreNode, type IRTheme, type IRThemeDecoration, type IRVisualEffect, type IRWiring, type IRWiringSignal, type MutationExecutionPack, type MutationPackBuilderOptions, type MutationPackData, type MutationPackKind, PACK_MANIFEST_SCHEMA_URL, type PackManifestEntry, type PackManifestMutationEntry, type PackManifestPageEntry, type PackManifestSectionEntry, type PageExecutionPack, type PagePackBuilderOptions, type PagePackData, type PagePackInput, type PagePackPattern, type PipelineOptions, type PipelineResult, type RealizationAdapter, type RealizationInteractionPlaceholder, type RealizationMockDataSeed, type RealizationPlan, type RealizationRoute, type ResolvedEssence, type ResolvedPage, type ReviewExecutionPack, type ReviewPackBuilderOptions, type ReviewPackData, type ReviewPackKind, SELECTED_EXECUTION_PACK_SCHEMA_URL, type ScaffoldExecutionPack, type ScaffoldPackBuilderOptions, type ScaffoldPackData, type ScaffoldPackRoute, type SectionExecutionPack, type SectionPackBuilderOptions, type SectionPackData, type SectionPackInput, type SectionPackRoute, type SelectedExecutionPack, type SelectedExecutionPackResponse, buildMutationPack, buildPageIR, buildPagePack, buildReviewPack, buildScaffoldPack, buildSectionPack, compileExecutionPackBundle, compileRealizationPlan, compileSelectedExecutionPack, countPatterns, findNodes, listPackPages, listPackSections, pascalCase, renderExecutionPackMarkdown, resolveEssence, resolvePackAdapter, resolveVisualEffects, runPipeline, selectExecutionPackFromBundle, validateIR, walkIR };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/resolve.ts
2
- import { computeDensity, isSectioned, isSimple, isV3 } from "@decantr/essence-spec";
2
+ import { computeDensity, isV4 } from "@decantr/essence-spec";
3
3
  import { detectWirings, resolvePatternPreset } from "@decantr/registry";
4
4
 
5
5
  // src/utils.ts
@@ -115,15 +115,7 @@ function buildThemeDecoration(theme) {
115
115
  dimensions: shell.dimensions || null
116
116
  };
117
117
  }
118
- function buildTheme(essence, isAddon) {
119
- return {
120
- id: essence.theme.id,
121
- mode: essence.theme.mode,
122
- shape: essence.theme.shape || null,
123
- isAddon
124
- };
125
- }
126
- function buildThemeFromV3(essence, isAddon) {
118
+ function buildThemeFromV4(essence, isAddon) {
127
119
  const dna = essence.dna;
128
120
  return {
129
121
  id: dna.theme.id,
@@ -145,7 +137,7 @@ function blueprintPageToStructurePage(page, defaultShell, sectionId) {
145
137
  function routeIdentity(pageId, sectionId) {
146
138
  return sectionId ? `${sectionId}:${pageId}` : pageId;
147
139
  }
148
- function buildV3Routes(essence, structurePages) {
140
+ function buildV4Routes(essence, structurePages) {
149
141
  const explicitRoutes = /* @__PURE__ */ new Map();
150
142
  for (const [path, entry] of Object.entries(essence.blueprint.routes ?? {})) {
151
143
  if (!entry?.page) continue;
@@ -230,81 +222,14 @@ function resolveVisualEffects(theme, pattern, _slot) {
230
222
  };
231
223
  }
232
224
  async function resolveEssence(essence, resolver) {
233
- if (isV3(essence)) {
234
- return resolveV3Essence(essence, resolver);
235
- }
236
- let simpleEssence;
237
- if (isSimple(essence)) {
238
- simpleEssence = essence;
239
- } else if (isSectioned(essence)) {
240
- const sectioned = essence;
241
- if (sectioned.sections.length > 1) {
242
- throw new Error(
243
- `Sectioned essences with ${sectioned.sections.length} sections are not yet supported. Only single-section sectioned essences can be processed. Consider migrating to v3 format using migrateV2ToV3().`
244
- );
245
- }
246
- const firstSection = sectioned.sections[0];
247
- simpleEssence = {
248
- version: sectioned.version,
249
- archetype: firstSection.archetype,
250
- theme: firstSection.theme,
251
- personality: sectioned.personality,
252
- platform: sectioned.platform,
253
- structure: firstSection.structure,
254
- features: firstSection.features || [],
255
- density: sectioned.density,
256
- guard: sectioned.guard,
257
- target: sectioned.target
258
- };
259
- } else {
260
- throw new Error("Invalid essence format");
261
- }
262
- let registryTheme = null;
263
- const themeResult = await resolver.resolve("theme", simpleEssence.theme.id);
264
- if (themeResult) {
265
- registryTheme = themeResult.item;
225
+ if (!isV4(essence)) {
226
+ throw new Error(
227
+ "Active Decantr V2 workflows require Essence v4.0.0. Run `decantr migrate --to v4` for older essence files."
228
+ );
266
229
  }
267
- const themeSpatial = registryTheme?.spatial;
268
- const density = computeDensity(
269
- simpleEssence.personality,
270
- themeSpatial ? {
271
- density_bias: themeSpatial.density_bias,
272
- content_gap_shift: themeSpatial.content_gap_shift
273
- } : void 0
274
- );
275
- const themeId = simpleEssence.theme.id;
276
- const isAddon = themeId.startsWith("custom:") || !CORE_STYLES.has(themeId);
277
- const theme = buildTheme(simpleEssence, isAddon);
278
- const resolvedPages = await resolvePages(simpleEssence.structure, resolver, registryTheme);
279
- const shellType = simpleEssence.structure[0]?.shell || "sidebar-main";
280
- const brand = pascalCase(simpleEssence.archetype);
281
- const nav = buildNavItems(simpleEssence.structure);
282
- const decoration = registryTheme ? buildThemeDecoration(registryTheme) : null;
283
- const shell = {
284
- type: shellType,
285
- brand,
286
- nav,
287
- inset: false,
288
- decoration
289
- };
290
- const routes = simpleEssence.structure.map((page, i) => ({
291
- path: routePath(page.id, i),
292
- pageId: page.id,
293
- shell: page.shell
294
- }));
295
- return {
296
- essence,
297
- pages: resolvedPages,
298
- registryTheme,
299
- density: { gap: density.content_gap, level: density.level },
300
- theme,
301
- shell,
302
- routes,
303
- features: simpleEssence.features ?? [],
304
- isV3Source: false
305
- };
230
+ return resolveV4Essence(essence, resolver);
306
231
  }
307
- async function resolveV3Essence(essence, resolver) {
232
+ async function resolveV4Essence(essence, resolver) {
308
233
  const { dna, blueprint, meta } = essence;
309
234
  let registryTheme = null;
310
235
  const themeResult = await resolver.resolve("theme", dna.theme.id);
@@ -325,22 +250,17 @@ async function resolveV3Essence(essence, resolver) {
325
250
  };
326
251
  const themeId = dna.theme.id;
327
252
  const isAddon = themeId.startsWith("custom:") || !CORE_STYLES.has(themeId);
328
- const theme = buildThemeFromV3(essence, isAddon);
329
- const defaultShell = blueprint.shell ?? blueprint.sections?.[0]?.shell ?? "sidebar-main";
330
- const structurePages = blueprint.pages ? blueprint.pages.map((page) => blueprintPageToStructurePage(page, defaultShell)) : blueprint.sections ? blueprint.sections.flatMap(
253
+ const theme = buildThemeFromV4(essence, isAddon);
254
+ const defaultShell = blueprint.shell ?? blueprint.sections[0]?.shell ?? "sidebar-main";
255
+ const structurePages = blueprint.sections.flatMap(
331
256
  (section) => section.pages.map(
332
257
  (page) => blueprintPageToStructurePage(page, section.shell ?? defaultShell, section.id)
333
258
  )
334
- ) : [
335
- blueprintPageToStructurePage(
336
- { id: "home", layout: ["hero"] },
337
- defaultShell
338
- )
339
- ];
259
+ );
340
260
  const resolvedPages = await resolvePages(structurePages, resolver, registryTheme);
341
261
  const shellType = defaultShell;
342
262
  const brand = pascalCase(meta.archetype);
343
- const routes = buildV3Routes(essence, structurePages);
263
+ const routes = buildV4Routes(essence, structurePages);
344
264
  const nav = buildNavItems(structurePages, routes);
345
265
  const decoration = registryTheme ? buildThemeDecoration(registryTheme) : null;
346
266
  const shell = {
@@ -359,7 +279,7 @@ async function resolveV3Essence(essence, resolver) {
359
279
  shell,
360
280
  routes,
361
281
  features: blueprint.features ?? [],
362
- isV3Source: true
282
+ isBlueprintSource: true
363
283
  };
364
284
  }
365
285
  async function resolvePages(pages, resolver, registryTheme) {
@@ -558,23 +478,19 @@ function validateIR(root) {
558
478
  }
559
479
 
560
480
  // src/packs.ts
561
- import { isV3 as isV33, migrateV2ToV3 as migrateV2ToV32 } from "@decantr/essence-spec";
481
+ import { isV4 as isV42 } from "@decantr/essence-spec";
562
482
 
563
483
  // src/pipeline.ts
564
- import { isV3 as isV32, migrateV2ToV3, validateEssence } from "@decantr/essence-spec";
484
+ import { validateEssence } from "@decantr/essence-spec";
565
485
  import { createResolver } from "@decantr/registry";
566
486
  function extractRouting(essence) {
567
- if (isV32(essence)) {
568
- return essence.meta.platform.routing || "history";
569
- }
570
- return essence.platform?.routing || "history";
487
+ return essence.meta.platform.routing || "history";
571
488
  }
572
489
  async function runPipeline(essence, options) {
573
490
  const validation = validateEssence(essence);
574
491
  if (!validation.valid) {
575
492
  throw new Error(`Invalid essence: ${validation.errors.join(", ")}`);
576
493
  }
577
- const effectiveEssence = isV32(essence) ? essence : migrateV2ToV3(essence);
578
494
  const resolver = options.resolver ?? (() => {
579
495
  if (!options.contentRoot) {
580
496
  throw new Error("Pipeline options must include either a contentRoot or a resolver.");
@@ -584,8 +500,8 @@ async function runPipeline(essence, options) {
584
500
  overridePaths: options.overridePaths
585
501
  });
586
502
  })();
587
- const resolved = await resolveEssence(effectiveEssence, resolver);
588
- const layer = resolved.isV3Source ? "blueprint" : void 0;
503
+ const resolved = await resolveEssence(essence, resolver);
504
+ const layer = "blueprint";
589
505
  const pageNodes = [];
590
506
  for (const rp of resolved.pages) {
591
507
  const pageIR = buildPageIR(
@@ -779,13 +695,13 @@ var DEFAULT_REVIEW_ANTI_PATTERNS = [
779
695
  }
780
696
  ];
781
697
  function collectPatternIds(page) {
782
- const patternIds = [];
698
+ const patternIds2 = [];
783
699
  walkIR(page, (node) => {
784
700
  if (node.type !== "pattern") return;
785
701
  const patternNode = node;
786
- patternIds.push(patternNode.pattern.patternId);
702
+ patternIds2.push(patternNode.pattern.patternId);
787
703
  });
788
- return [...new Set(patternIds)];
704
+ return [...new Set(patternIds2)];
789
705
  }
790
706
  function pageIdentity(pageId, sectionId) {
791
707
  return sectionId ? `${sectionId}/${pageId}` : pageId;
@@ -882,6 +798,16 @@ function routingImplementationHint(routing) {
882
798
  }
883
799
  function renderExecutionPackMarkdown(pack) {
884
800
  const lines = [];
801
+ const escapeMarkdownCell = (value) => {
802
+ let escaped = "";
803
+ for (const char of value) {
804
+ if (char === "\\") escaped += "\\\\";
805
+ else if (char === "|") escaped += "\\|";
806
+ else if (char === "\n" || char === "\r") escaped += "<br>";
807
+ else escaped += char;
808
+ }
809
+ return escaped;
810
+ };
885
811
  lines.push(`# ${pack.packType.charAt(0).toUpperCase()}${pack.packType.slice(1)} Pack`);
886
812
  lines.push("");
887
813
  lines.push(`**Objective:** ${pack.objective}`);
@@ -960,7 +886,6 @@ function renderExecutionPackMarkdown(pack) {
960
886
  }
961
887
  lines.push("");
962
888
  if (scaffoldPack.data.themeDecorators && scaffoldPack.data.themeDecorators.length > 0) {
963
- const escScaffoldCell = (s) => s.replace(/\|/g, "\\|");
964
889
  lines.push(`## Required Theme Decorators (${scaffoldPack.data.theme.id})`);
965
890
  lines.push("");
966
891
  lines.push(
@@ -971,7 +896,7 @@ function renderExecutionPackMarkdown(pack) {
971
896
  lines.push("|-------|--------|----------|");
972
897
  for (const entry of scaffoldPack.data.themeDecorators) {
973
898
  lines.push(
974
- `| \`.${entry.class}\` | ${escScaffoldCell(entry.intent)} | ${escScaffoldCell(entry.applyTo)} |`
899
+ `| \`.${entry.class}\` | ${escapeMarkdownCell(entry.intent)} | ${escapeMarkdownCell(entry.applyTo)} |`
975
900
  );
976
901
  }
977
902
  lines.push("");
@@ -1029,7 +954,6 @@ function renderExecutionPackMarkdown(pack) {
1029
954
  lines.push("");
1030
955
  }
1031
956
  if (sectionPack.data.themeDecorators && sectionPack.data.themeDecorators.length > 0) {
1032
- const escCell = (s) => s.replace(/\|/g, "\\|");
1033
957
  lines.push(`## Required Theme Decorators (${sectionPack.data.theme.id})`);
1034
958
  lines.push("");
1035
959
  lines.push(
@@ -1040,7 +964,7 @@ function renderExecutionPackMarkdown(pack) {
1040
964
  lines.push("|-------|--------|----------|");
1041
965
  for (const entry of sectionPack.data.themeDecorators) {
1042
966
  lines.push(
1043
- `| \`.${entry.class}\` | ${escCell(entry.intent)} | ${escCell(entry.applyTo)} |`
967
+ `| \`.${entry.class}\` | ${escapeMarkdownCell(entry.intent)} | ${escapeMarkdownCell(entry.applyTo)} |`
1044
968
  );
1045
969
  }
1046
970
  lines.push("");
@@ -1080,7 +1004,9 @@ function renderExecutionPackMarkdown(pack) {
1080
1004
  lines.push(` > ${pattern.presetDescription}`);
1081
1005
  }
1082
1006
  if (pattern.interactions && pattern.interactions.length > 0) {
1083
- lines.push(` **Interactions (MUST implement each \u2014 see DECANTR.md "Interaction Requirements"):**`);
1007
+ lines.push(
1008
+ ` **Interactions (MUST implement each \u2014 see DECANTR.md "Interaction Requirements"):**`
1009
+ );
1084
1010
  for (const interaction of pattern.interactions) {
1085
1011
  lines.push(` - [ ] ${interaction}`);
1086
1012
  }
@@ -1225,70 +1151,42 @@ function resolvePackAdapter(target, platformType) {
1225
1151
  }
1226
1152
  function listPackSections(essence) {
1227
1153
  const declaredSections = essence.blueprint.sections;
1228
- if (declaredSections && declaredSections.length > 0) {
1229
- const routedSectionPages = new Set(
1230
- Object.values(essence.blueprint.routes ?? {}).map(
1231
- (entry) => `${entry.section}:${entry.page}`
1232
- )
1233
- );
1234
- return declaredSections.map((section) => {
1235
- const pageIds = section.pages.filter(
1236
- (page) => routedSectionPages.size === 0 || routedSectionPages.has(`${section.id}:${page.id}`)
1237
- ).map((page) => page.id);
1238
- return {
1239
- id: section.id,
1240
- role: section.role,
1241
- shell: section.shell,
1242
- description: section.description,
1243
- features: section.features,
1244
- pageIds,
1245
- ...Array.isArray(section.navigation_items) && section.navigation_items.length > 0 ? { navigationItems: section.navigation_items } : {},
1246
- ...Array.isArray(section.directives) && section.directives.length > 0 ? { directives: section.directives } : {}
1247
- };
1248
- }).filter((section) => section.pageIds.length > 0);
1249
- }
1250
- const pages = essence.blueprint.pages ?? [{ id: "home", layout: ["hero"] }];
1251
- return [
1252
- {
1253
- id: essence.meta.archetype || "default",
1254
- role: "primary",
1255
- shell: essence.blueprint.shell ?? "sidebar-main",
1256
- description: `${essence.meta.archetype || "Application"} section`,
1257
- features: essence.blueprint.features || [],
1258
- pageIds: pages.map((page) => page.id)
1259
- }
1260
- ];
1154
+ const routedSectionPages = new Set(
1155
+ Object.values(essence.blueprint.routes ?? {}).map((entry) => `${entry.section}:${entry.page}`)
1156
+ );
1157
+ return declaredSections.map((section) => {
1158
+ const pageIds = section.pages.filter(
1159
+ (page) => routedSectionPages.size === 0 || routedSectionPages.has(`${section.id}:${page.id}`)
1160
+ ).map((page) => page.id);
1161
+ return {
1162
+ id: section.id,
1163
+ role: section.role,
1164
+ shell: section.shell,
1165
+ description: section.description,
1166
+ features: section.features,
1167
+ pageIds,
1168
+ ...Array.isArray(section.navigation_items) && section.navigation_items.length > 0 ? { navigationItems: section.navigation_items } : {},
1169
+ ...Array.isArray(section.directives) && section.directives.length > 0 ? { directives: section.directives } : {}
1170
+ };
1171
+ }).filter((section) => section.pageIds.length > 0);
1261
1172
  }
1262
1173
  function listPackPages(essence) {
1263
1174
  const declaredSections = essence.blueprint.sections;
1264
- if (declaredSections && declaredSections.length > 0) {
1265
- const routedSectionPages = new Set(
1266
- Object.values(essence.blueprint.routes ?? {}).map(
1267
- (entry) => `${entry.section}:${entry.page}`
1268
- )
1269
- );
1270
- return declaredSections.flatMap(
1271
- (section) => section.pages.map((page) => ({
1272
- pageId: page.id,
1273
- shell: page.shell_override ?? section.shell,
1274
- sectionId: section.id,
1275
- sectionRole: section.role,
1276
- features: section.features,
1277
- ...Array.isArray(page.directives) && page.directives.length > 0 ? { directives: page.directives } : {}
1278
- })).filter(
1279
- (page) => routedSectionPages.size === 0 || routedSectionPages.has(`${page.sectionId}:${page.pageId}`)
1280
- )
1281
- );
1282
- }
1283
- const pages = essence.blueprint.pages ?? [{ id: "home", layout: ["hero"] }];
1284
- const defaultShell = essence.blueprint.shell ?? "sidebar-main";
1285
- return pages.map((page) => ({
1286
- pageId: page.id,
1287
- shell: page.shell_override ?? defaultShell,
1288
- sectionId: essence.meta.archetype || "default",
1289
- sectionRole: "primary",
1290
- features: essence.blueprint.features || []
1291
- }));
1175
+ const routedSectionPages = new Set(
1176
+ Object.values(essence.blueprint.routes ?? {}).map((entry) => `${entry.section}:${entry.page}`)
1177
+ );
1178
+ return declaredSections.flatMap(
1179
+ (section) => section.pages.map((page) => ({
1180
+ pageId: page.id,
1181
+ shell: page.shell_override ?? section.shell,
1182
+ sectionId: section.id,
1183
+ sectionRole: section.role,
1184
+ features: section.features,
1185
+ ...Array.isArray(page.directives) && page.directives.length > 0 ? { directives: page.directives } : {}
1186
+ })).filter(
1187
+ (page) => routedSectionPages.size === 0 || routedSectionPages.has(`${page.sectionId}:${page.pageId}`)
1188
+ )
1189
+ );
1292
1190
  }
1293
1191
  function buildPageManifestEntries(pages) {
1294
1192
  const counts = /* @__PURE__ */ new Map();
@@ -1618,19 +1516,23 @@ function buildReviewPack(appNode, options = {}) {
1618
1516
  return pack;
1619
1517
  }
1620
1518
  async function compileExecutionPackBundle(essence, options = {}) {
1621
- const effectiveEssence = isV33(essence) ? essence : migrateV2ToV32(essence);
1519
+ if (!isV42(essence)) {
1520
+ throw new Error(
1521
+ "Active Decantr V2 workflows require Essence v4.0.0. Run `decantr migrate --to v4` for older essence files."
1522
+ );
1523
+ }
1622
1524
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
1623
1525
  const sharedTarget = {
1624
- framework: effectiveEssence.meta.target || null,
1625
- runtime: effectiveEssence.meta.platform.type || null,
1626
- adapter: resolvePackAdapter(effectiveEssence.meta.target, effectiveEssence.meta.platform.type)
1526
+ framework: essence.meta.target || null,
1527
+ runtime: essence.meta.platform.type || null,
1528
+ adapter: resolvePackAdapter(essence.meta.target, essence.meta.platform.type)
1627
1529
  };
1628
1530
  const pipeline = await runPipeline(essence, {
1629
1531
  contentRoot: options.contentRoot,
1630
1532
  overridePaths: options.overridePaths,
1631
1533
  resolver: options.resolver
1632
1534
  });
1633
- const navMeta = effectiveEssence.meta.navigation;
1535
+ const navMeta = essence.meta.navigation;
1634
1536
  const commandPaletteValue = typeof navMeta?.command_palette === "object" && navMeta.command_palette !== null ? navMeta.command_palette : Boolean(navMeta?.command_palette);
1635
1537
  const themeDecorators = (() => {
1636
1538
  const defs = pipeline.registryTheme?.decorator_definitions;
@@ -1665,8 +1567,8 @@ async function compileExecutionPackBundle(essence, options = {}) {
1665
1567
  const review = buildReviewPack(pipeline.ir, {
1666
1568
  target: sharedTarget
1667
1569
  });
1668
- const sectionInputs = listPackSections(effectiveEssence);
1669
- const pageInputs = listPackPages(effectiveEssence);
1570
+ const sectionInputs = listPackSections(essence);
1571
+ const pageInputs = listPackPages(essence);
1670
1572
  const sections = sectionInputs.map(
1671
1573
  (section) => buildSectionPack(pipeline.ir, section, {
1672
1574
  target: sharedTarget
@@ -1773,6 +1675,106 @@ async function compileSelectedExecutionPack(essence, selector, options = {}) {
1773
1675
  const bundle = await compileExecutionPackBundle(essence, options);
1774
1676
  return selectExecutionPackFromBundle(bundle, selector);
1775
1677
  }
1678
+
1679
+ // src/realization.ts
1680
+ import { isV4 as isV43 } from "@decantr/essence-spec";
1681
+ var CERTIFIED_REALIZATION_ADAPTERS = /* @__PURE__ */ new Set(["react-vite", "next-app"]);
1682
+ function routePath2(page, fallbackIndex) {
1683
+ if (page.route) return page.route;
1684
+ if (page.id === "home" || fallbackIndex === 0) return "/";
1685
+ return `/${page.id}`;
1686
+ }
1687
+ function patternIds(layout) {
1688
+ const ids = /* @__PURE__ */ new Set();
1689
+ for (const item of layout) {
1690
+ if (typeof item === "string") {
1691
+ ids.add(item);
1692
+ } else if ("pattern" in item) {
1693
+ ids.add(item.pattern);
1694
+ } else if ("cols" in item) {
1695
+ for (const col of item.cols) {
1696
+ ids.add(typeof col === "string" ? col : col.pattern);
1697
+ }
1698
+ }
1699
+ }
1700
+ return [...ids];
1701
+ }
1702
+ function compileRealizationPlan(essence) {
1703
+ if (!isV43(essence)) {
1704
+ throw new Error(
1705
+ "Active Decantr V2 workflows require Essence v4.0.0. Run `decantr migrate --to v4` for older essence files."
1706
+ );
1707
+ }
1708
+ const packAdapter = resolvePackAdapter(essence.meta.target, essence.meta.platform.type);
1709
+ const adapter = essence.meta.target === "nextjs" ? "next-app" : packAdapter;
1710
+ const canRealizeFrameworkCode = CERTIFIED_REALIZATION_ADAPTERS.has(adapter);
1711
+ const routes = [];
1712
+ for (const section of essence.blueprint.sections) {
1713
+ section.pages.forEach((page, pageIndex) => {
1714
+ routes.push({
1715
+ path: routePath2(page, routes.length + pageIndex),
1716
+ sectionId: section.id,
1717
+ sectionRole: section.role,
1718
+ pageId: page.id,
1719
+ shell: page.shell_override ?? section.shell,
1720
+ patterns: patternIds(page.layout),
1721
+ states: ["empty", "loading", "error"]
1722
+ });
1723
+ });
1724
+ }
1725
+ const mockData = [
1726
+ ...essence.blueprint.features.map((feature) => ({
1727
+ id: feature,
1728
+ source: "feature",
1729
+ shape: { enabled: true, status: "mocked" }
1730
+ })),
1731
+ ...routes.map((route) => ({
1732
+ id: route.pageId,
1733
+ source: "route",
1734
+ shape: { title: route.pageId, items: [] }
1735
+ }))
1736
+ ];
1737
+ const navigation = essence.meta.navigation;
1738
+ const interactions = [
1739
+ {
1740
+ id: "auth-mock",
1741
+ kind: "auth-mock",
1742
+ label: "Authenticated user/session placeholder"
1743
+ }
1744
+ ];
1745
+ if (navigation?.command_palette) {
1746
+ interactions.push({
1747
+ id: "command-palette",
1748
+ kind: "command-palette",
1749
+ label: "Command palette placeholder"
1750
+ });
1751
+ }
1752
+ for (const hotkey of navigation?.hotkeys ?? []) {
1753
+ interactions.push({
1754
+ id: `hotkey-${hotkey.key}`,
1755
+ kind: "hotkey",
1756
+ route: hotkey.route,
1757
+ label: hotkey.label
1758
+ });
1759
+ }
1760
+ return {
1761
+ version: "1.0.0",
1762
+ sourceEssenceVersion: "4.0.0",
1763
+ adapter,
1764
+ canRealizeFrameworkCode,
1765
+ routes,
1766
+ shell: {
1767
+ id: essence.blueprint.shell ?? essence.blueprint.sections[0]?.shell ?? "sidebar-main",
1768
+ theme: essence.dna.theme.id,
1769
+ mode: essence.dna.theme.mode
1770
+ },
1771
+ mockData,
1772
+ interactions,
1773
+ ...canRealizeFrameworkCode ? {} : {
1774
+ unsupportedReason: "No certified realization adapter is available for this target yet. Use the V4 contract, execution packs, prompts, and Project Health without generated framework code."
1775
+ }
1776
+ };
1777
+ }
1776
1778
  export {
1777
1779
  EXECUTION_PACK_BUNDLE_SCHEMA_URL,
1778
1780
  EXECUTION_PACK_SCHEMA_URLS,
@@ -1785,6 +1787,7 @@ export {
1785
1787
  buildScaffoldPack,
1786
1788
  buildSectionPack,
1787
1789
  compileExecutionPackBundle,
1790
+ compileRealizationPlan,
1788
1791
  compileSelectedExecutionPack,
1789
1792
  countPatterns,
1790
1793
  findNodes,