@decantr/cli 1.5.3 → 1.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +2 -2
- package/dist/{chunk-QZVA3PFR.js → chunk-D3W3MYKT.js} +48 -91
- package/dist/{chunk-B5OX2EXL.js → chunk-T7CQSJGV.js} +114 -134
- package/dist/{heal-54MKDDSQ.js → heal-VYEGIUAS.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{upgrade-LTLUPBZQ.js → upgrade-TXVD2WIN.js} +1 -1
- package/package.json +1 -1
- package/src/bundled/blueprints/default.json +1 -2
- package/src/templates/DECANTR.md.template +8 -9
- package/src/templates/essence-summary.md.template +1 -1
- package/src/templates/project.json.template +1 -2
- package/src/templates/task-add-page.md.template +7 -8
- package/src/templates/task-modify.md.template +8 -9
- package/src/templates/task-scaffold.md.template +1 -2
package/dist/bin.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
3
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-D3W3MYKT.js";
|
|
3
|
+
import "./chunk-T7CQSJGV.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
scaffoldMinimal,
|
|
10
10
|
scaffoldProject,
|
|
11
11
|
syncRegistry
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-T7CQSJGV.js";
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
15
|
import { readFileSync as readFileSync15, existsSync as existsSync23, readdirSync as readdirSync6 } from "fs";
|
|
@@ -284,7 +284,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes) {
|
|
|
284
284
|
"Guard enforcement level",
|
|
285
285
|
[
|
|
286
286
|
{ value: "creative", label: "creative", description: "Advisory only (new projects)" },
|
|
287
|
-
{ value: "guided", label: "guided", description: "Style, structure,
|
|
287
|
+
{ value: "guided", label: "guided", description: "Style, structure, density enforced" },
|
|
288
288
|
{ value: "strict", label: "strict", description: "All 5 rules enforced exactly" }
|
|
289
289
|
],
|
|
290
290
|
detected.existingEssence ? 1 : 2
|
|
@@ -649,7 +649,6 @@ import { join as join4 } from "path";
|
|
|
649
649
|
import { RegistryAPIClient } from "@decantr/registry";
|
|
650
650
|
var PLURAL_TO_SINGULAR = {
|
|
651
651
|
patterns: "pattern",
|
|
652
|
-
recipes: "recipe",
|
|
653
652
|
themes: "theme",
|
|
654
653
|
blueprints: "blueprint",
|
|
655
654
|
archetypes: "archetype",
|
|
@@ -657,7 +656,6 @@ var PLURAL_TO_SINGULAR = {
|
|
|
657
656
|
};
|
|
658
657
|
var SINGULAR_TO_PLURAL = {
|
|
659
658
|
pattern: "patterns",
|
|
660
|
-
recipe: "recipes",
|
|
661
659
|
theme: "themes",
|
|
662
660
|
blueprint: "blueprints",
|
|
663
661
|
archetype: "archetypes",
|
|
@@ -710,10 +708,9 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
|
|
|
710
708
|
// src/commands/create.ts
|
|
711
709
|
import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
712
710
|
import { join as join5 } from "path";
|
|
713
|
-
var CONTENT_TYPES = ["pattern", "
|
|
711
|
+
var CONTENT_TYPES = ["pattern", "theme", "blueprint", "archetype", "shell"];
|
|
714
712
|
var PLURAL = {
|
|
715
713
|
pattern: "patterns",
|
|
716
|
-
recipe: "recipes",
|
|
717
714
|
theme: "themes",
|
|
718
715
|
blueprint: "blueprints",
|
|
719
716
|
archetype: "archetypes",
|
|
@@ -730,8 +727,6 @@ function getSkeleton(type, id, name) {
|
|
|
730
727
|
switch (type) {
|
|
731
728
|
case "pattern":
|
|
732
729
|
return { ...base, components: [], presets: {}, layout: {} };
|
|
733
|
-
case "recipe":
|
|
734
|
-
return { ...base, shell: {}, spatial: {}, effects: {} };
|
|
735
730
|
case "theme":
|
|
736
731
|
return { ...base, seed: { primary: "#6500C6", secondary: "#0AF3EB", accent: "#F58882", background: "#0D0D1A" }, modes: ["dark"], shapes: ["rounded"] };
|
|
737
732
|
case "blueprint":
|
|
@@ -1339,7 +1334,7 @@ var DIM7 = "\x1B[2m";
|
|
|
1339
1334
|
var RESET7 = "\x1B[0m";
|
|
1340
1335
|
async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
1341
1336
|
if (!themeName) {
|
|
1342
|
-
console.error(`${RED6}Usage: decantr theme switch <themeName> [--
|
|
1337
|
+
console.error(`${RED6}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET7}`);
|
|
1343
1338
|
process.exitCode = 1;
|
|
1344
1339
|
return;
|
|
1345
1340
|
}
|
|
@@ -1363,16 +1358,11 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
1363
1358
|
return;
|
|
1364
1359
|
}
|
|
1365
1360
|
const essence = migrateV30ToV313(parsed);
|
|
1366
|
-
let recipe;
|
|
1367
1361
|
let shape;
|
|
1368
1362
|
let mode;
|
|
1369
1363
|
for (let i = 0; i < args.length; i++) {
|
|
1370
1364
|
const arg = args[i];
|
|
1371
|
-
if (arg.startsWith("--
|
|
1372
|
-
recipe = arg.split("=")[1];
|
|
1373
|
-
} else if (arg === "--recipe" && args[i + 1] && !args[i + 1].startsWith("-")) {
|
|
1374
|
-
recipe = args[++i];
|
|
1375
|
-
} else if (arg.startsWith("--shape=")) {
|
|
1365
|
+
if (arg.startsWith("--shape=")) {
|
|
1376
1366
|
shape = arg.split("=")[1];
|
|
1377
1367
|
} else if (arg === "--shape" && args[i + 1] && !args[i + 1].startsWith("-")) {
|
|
1378
1368
|
shape = args[++i];
|
|
@@ -1382,13 +1372,10 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
1382
1372
|
mode = args[++i];
|
|
1383
1373
|
}
|
|
1384
1374
|
}
|
|
1385
|
-
const
|
|
1386
|
-
essence.dna.theme.
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
} else {
|
|
1390
|
-
essence.dna.theme.recipe = themeName;
|
|
1391
|
-
}
|
|
1375
|
+
const oldThemeId = essence.dna.theme.id || essence.dna.theme.style;
|
|
1376
|
+
essence.dna.theme.id = themeName;
|
|
1377
|
+
delete essence.dna.theme.style;
|
|
1378
|
+
delete essence.dna.theme.recipe;
|
|
1392
1379
|
if (shape) {
|
|
1393
1380
|
essence.dna.theme.shape = shape;
|
|
1394
1381
|
}
|
|
@@ -1398,29 +1385,27 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
1398
1385
|
const registryClient = new RegistryClient({
|
|
1399
1386
|
cacheDir: join11(projectRoot, ".decantr", "cache")
|
|
1400
1387
|
});
|
|
1401
|
-
const recipeName = essence.dna.theme.recipe;
|
|
1402
1388
|
try {
|
|
1403
|
-
const
|
|
1404
|
-
if (
|
|
1405
|
-
const raw =
|
|
1389
|
+
const themeResult = await registryClient.fetchTheme(themeName);
|
|
1390
|
+
if (themeResult?.data) {
|
|
1391
|
+
const raw = themeResult.data;
|
|
1406
1392
|
const inner = raw.data ?? raw;
|
|
1407
|
-
if (inner.
|
|
1393
|
+
if (inner.radius) {
|
|
1408
1394
|
essence.dna.radius = {
|
|
1409
1395
|
...essence.dna.radius,
|
|
1410
|
-
philosophy: inner.
|
|
1411
|
-
base: inner.
|
|
1396
|
+
philosophy: inner.radius.philosophy || essence.dna.radius.philosophy,
|
|
1397
|
+
base: inner.radius.base ?? essence.dna.radius.base
|
|
1412
1398
|
};
|
|
1413
1399
|
}
|
|
1414
1400
|
}
|
|
1415
1401
|
} catch {
|
|
1416
1402
|
}
|
|
1417
1403
|
writeFileSync8(essencePath, JSON.stringify(essence, null, 2) + "\n");
|
|
1418
|
-
console.log(`${GREEN7}Switched theme: ${
|
|
1419
|
-
if (recipe) console.log(` ${DIM7}Recipe: ${recipe}${RESET7}`);
|
|
1404
|
+
console.log(`${GREEN7}Switched theme: ${oldThemeId} \u2192 ${themeName}${RESET7}`);
|
|
1420
1405
|
if (shape) console.log(` ${DIM7}Shape: ${shape}${RESET7}`);
|
|
1421
1406
|
if (mode) console.log(` ${DIM7}Mode: ${mode}${RESET7}`);
|
|
1422
1407
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
1423
|
-
console.log(`${GREEN7}Derived files refreshed (tokens.css,
|
|
1408
|
+
console.log(`${GREEN7}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET7}`);
|
|
1424
1409
|
console.log(`${YELLOW4}Guard will flag code using old tokens. Run \`decantr check\`.${RESET7}`);
|
|
1425
1410
|
}
|
|
1426
1411
|
|
|
@@ -2467,7 +2452,7 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
2467
2452
|
existing: false
|
|
2468
2453
|
};
|
|
2469
2454
|
if (blueprintData) {
|
|
2470
|
-
if (blueprintData.theme?.style) initOptions.theme = blueprintData.theme.style;
|
|
2455
|
+
if (blueprintData.theme?.id || blueprintData.theme?.style) initOptions.theme = blueprintData.theme.id || blueprintData.theme.style;
|
|
2471
2456
|
if (blueprintData.theme?.mode) initOptions.mode = blueprintData.theme.mode;
|
|
2472
2457
|
if (blueprintData.theme?.shape) initOptions.shape = blueprintData.theme.shape;
|
|
2473
2458
|
if (blueprintData.personality) {
|
|
@@ -2499,8 +2484,6 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
2499
2484
|
let patternSpecs;
|
|
2500
2485
|
let topologyMarkdown = "";
|
|
2501
2486
|
let themeData;
|
|
2502
|
-
let recipeData;
|
|
2503
|
-
let blueprintRecipeName;
|
|
2504
2487
|
let registrySource = apiAvailable ? "api" : "cache";
|
|
2505
2488
|
if (blueprintData?.compose && blueprintData.compose.length > 0) {
|
|
2506
2489
|
const entries = blueprintData.compose;
|
|
@@ -2604,7 +2587,6 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
2604
2587
|
initOptions.personality
|
|
2605
2588
|
);
|
|
2606
2589
|
}
|
|
2607
|
-
blueprintRecipeName = blueprintData.theme?.recipe;
|
|
2608
2590
|
console.log(`${BOLD4} Composition:${RESET9}`);
|
|
2609
2591
|
console.log(` Sections: ${composedSections.sections.length} (${composedSections.sections.map((s) => s.id).join(", ")})`);
|
|
2610
2592
|
const totalRoutes = Object.keys(routeMap).length;
|
|
@@ -2630,23 +2612,16 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
2630
2612
|
palette: theme.palette,
|
|
2631
2613
|
tokens: theme.tokens,
|
|
2632
2614
|
cvd_support: theme.cvd_support,
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
const rawRecipe = recipeResult.data;
|
|
2644
|
-
const recipe = rawRecipe.data ?? rawRecipe;
|
|
2645
|
-
recipeData = {
|
|
2646
|
-
decorators: recipe.decorators || recipeData?.decorators,
|
|
2647
|
-
spatial_hints: recipe.spatial_hints,
|
|
2648
|
-
radius_hints: recipe.radius_hints,
|
|
2649
|
-
treatment_overrides: recipe.treatment_overrides
|
|
2615
|
+
typography: theme.typography,
|
|
2616
|
+
motion: theme.motion,
|
|
2617
|
+
decorators: theme.decorators,
|
|
2618
|
+
treatments: theme.treatments,
|
|
2619
|
+
spatial: theme.spatial,
|
|
2620
|
+
radius: theme.radius,
|
|
2621
|
+
shell: theme.shell,
|
|
2622
|
+
effects: theme.effects,
|
|
2623
|
+
compositions: theme.compositions,
|
|
2624
|
+
pattern_preferences: theme.pattern_preferences
|
|
2650
2625
|
};
|
|
2651
2626
|
}
|
|
2652
2627
|
}
|
|
@@ -2659,7 +2634,6 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
2659
2634
|
archetypeData,
|
|
2660
2635
|
registrySource,
|
|
2661
2636
|
themeData,
|
|
2662
|
-
recipeData,
|
|
2663
2637
|
topologyMarkdown,
|
|
2664
2638
|
composedSections,
|
|
2665
2639
|
routeMap,
|
|
@@ -2916,7 +2890,6 @@ var ALL_CONTENT_TYPES = [
|
|
|
2916
2890
|
"patterns",
|
|
2917
2891
|
"archetypes",
|
|
2918
2892
|
"themes",
|
|
2919
|
-
"recipes",
|
|
2920
2893
|
"blueprints",
|
|
2921
2894
|
"shells"
|
|
2922
2895
|
];
|
|
@@ -3359,7 +3332,7 @@ async function cmdSuggest(query, type) {
|
|
|
3359
3332
|
}
|
|
3360
3333
|
}
|
|
3361
3334
|
async function cmdGet(type, id) {
|
|
3362
|
-
const validTypes = ["pattern", "archetype", "
|
|
3335
|
+
const validTypes = ["pattern", "archetype", "theme", "blueprint", "shell"];
|
|
3363
3336
|
if (!validTypes.includes(type)) {
|
|
3364
3337
|
console.error(error3(`Invalid type "${type}". Must be one of: ${validTypes.join(", ")}`));
|
|
3365
3338
|
process.exitCode = 1;
|
|
@@ -3368,7 +3341,6 @@ async function cmdGet(type, id) {
|
|
|
3368
3341
|
const typeMap = {
|
|
3369
3342
|
pattern: "patterns",
|
|
3370
3343
|
archetype: "archetypes",
|
|
3371
|
-
recipe: "recipes",
|
|
3372
3344
|
theme: "themes",
|
|
3373
3345
|
blueprint: "blueprints",
|
|
3374
3346
|
shell: "shells"
|
|
@@ -3497,7 +3469,7 @@ async function cmdValidate(path) {
|
|
|
3497
3469
|
}
|
|
3498
3470
|
}
|
|
3499
3471
|
async function cmdList(type) {
|
|
3500
|
-
const validTypes = ["patterns", "archetypes", "
|
|
3472
|
+
const validTypes = ["patterns", "archetypes", "themes", "blueprints", "shells"];
|
|
3501
3473
|
if (!validTypes.includes(type)) {
|
|
3502
3474
|
console.error(error3(`Invalid type "${type}". Must be one of: ${validTypes.join(", ")}`));
|
|
3503
3475
|
process.exitCode = 1;
|
|
@@ -3611,7 +3583,6 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
3611
3583
|
} else {
|
|
3612
3584
|
options = await runInteractivePrompts(detected, archetypes, blueprints, themes);
|
|
3613
3585
|
}
|
|
3614
|
-
let blueprintRecipeName;
|
|
3615
3586
|
let topologyMarkdown = "";
|
|
3616
3587
|
let archetypeData;
|
|
3617
3588
|
let composedSections;
|
|
@@ -3624,8 +3595,8 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
3624
3595
|
const rawBlueprint = blueprintResult.data;
|
|
3625
3596
|
const blueprint = rawBlueprint.data ?? rawBlueprint;
|
|
3626
3597
|
if (blueprint.theme) {
|
|
3627
|
-
if (blueprint.theme.style && options.theme === "luminarum") {
|
|
3628
|
-
options.theme = blueprint.theme.style;
|
|
3598
|
+
if ((blueprint.theme.id || blueprint.theme.style) && options.theme === "luminarum") {
|
|
3599
|
+
options.theme = blueprint.theme.id || blueprint.theme.style;
|
|
3629
3600
|
}
|
|
3630
3601
|
if (blueprint.theme.mode && options.mode === "dark") {
|
|
3631
3602
|
options.mode = blueprint.theme.mode;
|
|
@@ -3637,7 +3608,6 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
3637
3608
|
if (blueprint.personality && (!options.personality || options.personality.length === 0 || options.personality.length === 1 && options.personality[0] === "professional")) {
|
|
3638
3609
|
options.personality = typeof blueprint.personality === "string" ? [blueprint.personality] : blueprint.personality;
|
|
3639
3610
|
}
|
|
3640
|
-
blueprintRecipeName = blueprint.theme?.recipe;
|
|
3641
3611
|
if (blueprint.compose && blueprint.compose.length > 0) {
|
|
3642
3612
|
const entries = blueprint.compose;
|
|
3643
3613
|
const results = [];
|
|
@@ -3754,7 +3724,6 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
3754
3724
|
}
|
|
3755
3725
|
}
|
|
3756
3726
|
let themeData;
|
|
3757
|
-
let recipeData;
|
|
3758
3727
|
if (options.theme) {
|
|
3759
3728
|
const themeResult = await registryClient.fetchTheme(options.theme);
|
|
3760
3729
|
if (themeResult) {
|
|
@@ -3765,31 +3734,20 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
3765
3734
|
palette: theme.palette,
|
|
3766
3735
|
tokens: theme.tokens,
|
|
3767
3736
|
cvd_support: theme.cvd_support,
|
|
3768
|
-
|
|
3769
|
-
|
|
3737
|
+
typography: theme.typography,
|
|
3738
|
+
motion: theme.motion,
|
|
3739
|
+
decorators: theme.decorators,
|
|
3740
|
+
treatments: theme.treatments,
|
|
3741
|
+
spatial: theme.spatial,
|
|
3742
|
+
radius: theme.radius,
|
|
3743
|
+
shell: theme.shell,
|
|
3744
|
+
effects: theme.effects,
|
|
3745
|
+
compositions: theme.compositions,
|
|
3746
|
+
pattern_preferences: theme.pattern_preferences
|
|
3770
3747
|
};
|
|
3771
|
-
if (theme.decorators) {
|
|
3772
|
-
recipeData = { decorators: theme.decorators };
|
|
3773
|
-
}
|
|
3774
3748
|
} else {
|
|
3775
3749
|
console.log(`${YELLOW9} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET13}`);
|
|
3776
3750
|
}
|
|
3777
|
-
const recipeName = blueprintRecipeName || options.theme;
|
|
3778
|
-
const recipeResult = await registryClient.fetchRecipe(recipeName);
|
|
3779
|
-
if (process.env.DECANTR_DEBUG && recipeResult) {
|
|
3780
|
-
const dbg = recipeResult.data;
|
|
3781
|
-
console.error(` [debug] recipe source: ${recipeResult.source.type}, keys: ${Object.keys(dbg).join(",")}, has .data: ${"data" in dbg}, has .decorators: ${"decorators" in dbg}, inner.decorators: ${!!dbg.data?.decorators}`);
|
|
3782
|
-
}
|
|
3783
|
-
if (recipeResult) {
|
|
3784
|
-
const rawRecipe = recipeResult.data;
|
|
3785
|
-
const recipe = rawRecipe.data ?? rawRecipe;
|
|
3786
|
-
recipeData = {
|
|
3787
|
-
decorators: recipe.decorators || recipeData?.decorators,
|
|
3788
|
-
spatial_hints: recipe.spatial_hints,
|
|
3789
|
-
radius_hints: recipe.radius_hints,
|
|
3790
|
-
treatment_overrides: recipe.treatment_overrides
|
|
3791
|
-
};
|
|
3792
|
-
}
|
|
3793
3751
|
}
|
|
3794
3752
|
console.log(heading2("Scaffolding project..."));
|
|
3795
3753
|
const result = await scaffoldProject(
|
|
@@ -3800,7 +3758,6 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
3800
3758
|
archetypeData,
|
|
3801
3759
|
registrySource,
|
|
3802
3760
|
themeData,
|
|
3803
|
-
recipeData,
|
|
3804
3761
|
topologyMarkdown,
|
|
3805
3762
|
// V3.1 composition data:
|
|
3806
3763
|
composedSections,
|
|
@@ -4130,7 +4087,7 @@ ${BOLD6}Examples:${RESET13}
|
|
|
4130
4087
|
case "switch": {
|
|
4131
4088
|
const name = args[1];
|
|
4132
4089
|
if (!name) {
|
|
4133
|
-
console.error(error3("Usage: decantr theme switch <themeName> [--
|
|
4090
|
+
console.error(error3("Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]"));
|
|
4134
4091
|
process.exitCode = 1;
|
|
4135
4092
|
return;
|
|
4136
4093
|
}
|
|
@@ -4199,7 +4156,7 @@ ${BOLD6}Commands:${RESET13}
|
|
|
4199
4156
|
${cyan3("list")} List items by type
|
|
4200
4157
|
${cyan3("validate")} Validate essence file (v2 and v3)
|
|
4201
4158
|
${cyan3("theme")} Manage custom themes (create, list, validate, delete, import)
|
|
4202
|
-
${cyan3("create")} Create a custom content item (pattern,
|
|
4159
|
+
${cyan3("create")} Create a custom content item (pattern, theme, blueprint, etc.)
|
|
4203
4160
|
${cyan3("publish")} Publish a custom content item to the community registry
|
|
4204
4161
|
${cyan3("login")} Authenticate with the Decantr registry
|
|
4205
4162
|
${cyan3("logout")} Remove stored credentials
|
|
@@ -4299,7 +4256,7 @@ async function main() {
|
|
|
4299
4256
|
break;
|
|
4300
4257
|
}
|
|
4301
4258
|
case "upgrade": {
|
|
4302
|
-
const { cmdUpgrade } = await import("./upgrade-
|
|
4259
|
+
const { cmdUpgrade } = await import("./upgrade-TXVD2WIN.js");
|
|
4303
4260
|
const applyFlag = args.includes("--apply");
|
|
4304
4261
|
await cmdUpgrade(process.cwd(), { apply: applyFlag });
|
|
4305
4262
|
break;
|
|
@@ -4309,7 +4266,7 @@ async function main() {
|
|
|
4309
4266
|
if (command === "heal") {
|
|
4310
4267
|
console.log(`${YELLOW9}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET13}`);
|
|
4311
4268
|
}
|
|
4312
|
-
const { cmdHeal } = await import("./heal-
|
|
4269
|
+
const { cmdHeal } = await import("./heal-VYEGIUAS.js");
|
|
4313
4270
|
const telemetryFlag = args.includes("--telemetry");
|
|
4314
4271
|
await cmdHeal(process.cwd(), { telemetry: telemetryFlag });
|
|
4315
4272
|
break;
|
|
@@ -4432,7 +4389,7 @@ async function main() {
|
|
|
4432
4389
|
const name = args[2];
|
|
4433
4390
|
if (!type || !name) {
|
|
4434
4391
|
console.error(error3("Usage: decantr create <type> <name>"));
|
|
4435
|
-
console.error(dim3("Types: pattern,
|
|
4392
|
+
console.error(dim3("Types: pattern, theme, blueprint, archetype, shell"));
|
|
4436
4393
|
process.exitCode = 1;
|
|
4437
4394
|
break;
|
|
4438
4395
|
}
|
|
@@ -4444,7 +4401,7 @@ async function main() {
|
|
|
4444
4401
|
const name = args[2];
|
|
4445
4402
|
if (!type || !name) {
|
|
4446
4403
|
console.error(error3("Usage: decantr publish <type> <name>"));
|
|
4447
|
-
console.error(dim3("Types: pattern,
|
|
4404
|
+
console.error(dim3("Types: pattern, theme, blueprint, archetype, shell"));
|
|
4448
4405
|
process.exitCode = 1;
|
|
4449
4406
|
break;
|
|
4450
4407
|
}
|
|
@@ -5,7 +5,7 @@ import { fileURLToPath } from "url";
|
|
|
5
5
|
import { computeSpatialTokens } from "@decantr/essence-spec";
|
|
6
6
|
|
|
7
7
|
// src/treatments.ts
|
|
8
|
-
function generateTreatmentCSS(spatialTokens, treatmentOverrides,
|
|
8
|
+
function generateTreatmentCSS(spatialTokens, treatmentOverrides, themeDecorators, themeName) {
|
|
9
9
|
const lines = [];
|
|
10
10
|
lines.push("/* Generated by @decantr/cli \u2014 Visual Treatment System */");
|
|
11
11
|
lines.push("");
|
|
@@ -185,11 +185,11 @@ function generateTreatmentCSS(spatialTokens, treatmentOverrides, recipeDecorator
|
|
|
185
185
|
["background", "color-mix(in srgb, var(--d-info) 15%, transparent)"],
|
|
186
186
|
["color", "var(--d-info)"]
|
|
187
187
|
]);
|
|
188
|
-
if (
|
|
189
|
-
const label =
|
|
190
|
-
lines.push(`/* \u2500\u2500 Layer 3:
|
|
188
|
+
if (themeDecorators && Object.keys(themeDecorators).length > 0) {
|
|
189
|
+
const label = themeName ? ` (${themeName})` : "";
|
|
190
|
+
lines.push(`/* \u2500\u2500 Layer 3: Theme Decorators${label} \u2500\u2500 */`);
|
|
191
191
|
lines.push("");
|
|
192
|
-
for (const [name, description] of Object.entries(
|
|
192
|
+
for (const [name, description] of Object.entries(themeDecorators)) {
|
|
193
193
|
const rule = generateDecoratorRule(name, description);
|
|
194
194
|
lines.push(rule);
|
|
195
195
|
lines.push("");
|
|
@@ -520,6 +520,21 @@ function generateTokensCSS(themeData, mode, spatialTokens) {
|
|
|
520
520
|
};
|
|
521
521
|
}
|
|
522
522
|
const tokens = buildTokens(resolvedMode);
|
|
523
|
+
if (themeData?.typography?.mono) {
|
|
524
|
+
tokens["--d-font-mono"] = themeData.typography.mono;
|
|
525
|
+
}
|
|
526
|
+
if (themeData?.palette?.["accent-glow"]?.[resolvedMode]) {
|
|
527
|
+
tokens["--d-accent-glow"] = themeData.palette["accent-glow"][resolvedMode];
|
|
528
|
+
}
|
|
529
|
+
if (themeData?.motion?.durations?.hover) {
|
|
530
|
+
tokens["--d-duration-hover"] = themeData.motion.durations.hover;
|
|
531
|
+
}
|
|
532
|
+
if (themeData?.motion?.durations?.entrance) {
|
|
533
|
+
tokens["--d-duration-entrance"] = themeData.motion.durations.entrance;
|
|
534
|
+
}
|
|
535
|
+
if (themeData?.motion?.timing) {
|
|
536
|
+
tokens["--d-easing"] = themeData.motion.timing;
|
|
537
|
+
}
|
|
523
538
|
const lines = Object.entries(tokens).map(([key, value]) => ` ${key}: ${value};`).join("\n");
|
|
524
539
|
const spatialLines = spatialTokens ? "\n" + Object.entries(spatialTokens).map(([k, v]) => ` ${k}: ${v};`).join("\n") : "";
|
|
525
540
|
let css = `/* Generated by @decantr/cli */
|
|
@@ -612,20 +627,20 @@ input, button, textarea, select {
|
|
|
612
627
|
}
|
|
613
628
|
`;
|
|
614
629
|
}
|
|
615
|
-
function generateTreatmentsContext(
|
|
630
|
+
function generateTreatmentsContext(themeData, themeName) {
|
|
616
631
|
const lines = [];
|
|
617
|
-
lines.push(`# Visual Treatments: ${
|
|
632
|
+
lines.push(`# Visual Treatments: ${themeName}`);
|
|
618
633
|
lines.push("");
|
|
619
634
|
lines.push("## Base Treatments");
|
|
620
635
|
lines.push("");
|
|
621
636
|
lines.push("d-interactive, d-surface, d-data, d-control, d-section, d-annotation \u2014 see DECANTR.md for usage.");
|
|
622
637
|
lines.push("");
|
|
623
|
-
if (
|
|
624
|
-
lines.push(`##
|
|
638
|
+
if (themeData?.decorators && Object.keys(themeData.decorators).length > 0) {
|
|
639
|
+
lines.push(`## Theme Decorators (${themeName}-specific)`);
|
|
625
640
|
lines.push("");
|
|
626
641
|
lines.push("| Class | Use for |");
|
|
627
642
|
lines.push("|-------|---------|");
|
|
628
|
-
for (const [name, description] of Object.entries(
|
|
643
|
+
for (const [name, description] of Object.entries(themeData.decorators)) {
|
|
629
644
|
const useFor = description.split(".")[0].trim();
|
|
630
645
|
lines.push(`| ${name} | ${useFor} |`);
|
|
631
646
|
}
|
|
@@ -633,12 +648,12 @@ function generateTreatmentsContext(recipeData, recipeName) {
|
|
|
633
648
|
}
|
|
634
649
|
lines.push("## Composition");
|
|
635
650
|
lines.push("");
|
|
636
|
-
lines.push("Atoms + treatment +
|
|
651
|
+
lines.push("Atoms + treatment + theme decorator:");
|
|
637
652
|
lines.push("```tsx");
|
|
638
653
|
lines.push(`css('_flex _col _gap4') + ' d-surface'`);
|
|
639
654
|
lines.push("```");
|
|
640
655
|
lines.push("");
|
|
641
|
-
lines.push("Atoms use `css()` function. Treatments and
|
|
656
|
+
lines.push("Atoms use `css()` function. Treatments and theme decorators are plain class strings.");
|
|
642
657
|
return lines.join("\n");
|
|
643
658
|
}
|
|
644
659
|
function generateDecoratorRule(name, description) {
|
|
@@ -876,7 +891,7 @@ function buildEssence(options, archetypeData) {
|
|
|
876
891
|
style: options.theme,
|
|
877
892
|
mode: options.mode,
|
|
878
893
|
recipe: options.theme,
|
|
879
|
-
//
|
|
894
|
+
// Legacy v2 field — kept for backward compatibility
|
|
880
895
|
shape: options.shape
|
|
881
896
|
},
|
|
882
897
|
personality: options.personality,
|
|
@@ -889,6 +904,7 @@ function buildEssence(options, archetypeData) {
|
|
|
889
904
|
guard: {
|
|
890
905
|
enforce_style: true,
|
|
891
906
|
enforce_recipe: true,
|
|
907
|
+
// Legacy v2 field — kept for backward compatibility
|
|
892
908
|
mode: options.guard
|
|
893
909
|
},
|
|
894
910
|
density: {
|
|
@@ -902,7 +918,7 @@ function buildEssence(options, archetypeData) {
|
|
|
902
918
|
}
|
|
903
919
|
return essence;
|
|
904
920
|
}
|
|
905
|
-
function buildEssenceV3(options, archetypeData, themeHints
|
|
921
|
+
function buildEssenceV3(options, archetypeData, themeHints) {
|
|
906
922
|
let pages = [
|
|
907
923
|
{ id: "home", layout: ["hero"] }
|
|
908
924
|
];
|
|
@@ -939,9 +955,8 @@ function buildEssenceV3(options, archetypeData, themeHints, recipeHints) {
|
|
|
939
955
|
};
|
|
940
956
|
const dna = {
|
|
941
957
|
theme: {
|
|
942
|
-
|
|
958
|
+
id: options.theme,
|
|
943
959
|
mode: options.mode,
|
|
944
|
-
recipe: options.theme,
|
|
945
960
|
shape: options.shape
|
|
946
961
|
},
|
|
947
962
|
spacing: {
|
|
@@ -951,9 +966,9 @@ function buildEssenceV3(options, archetypeData, themeHints, recipeHints) {
|
|
|
951
966
|
content_gap: densityLevelMap[options.density] || "_gap4"
|
|
952
967
|
},
|
|
953
968
|
typography: {
|
|
954
|
-
scale: themeHints?.
|
|
955
|
-
heading_weight: themeHints?.
|
|
956
|
-
body_weight: themeHints?.
|
|
969
|
+
scale: themeHints?.typography?.scale || "modular",
|
|
970
|
+
heading_weight: themeHints?.typography?.heading_weight || 600,
|
|
971
|
+
body_weight: themeHints?.typography?.body_weight || 400
|
|
957
972
|
},
|
|
958
973
|
color: {
|
|
959
974
|
palette: "semantic",
|
|
@@ -961,17 +976,17 @@ function buildEssenceV3(options, archetypeData, themeHints, recipeHints) {
|
|
|
961
976
|
cvd_preference: options.accessibility?.cvd_preference || "auto"
|
|
962
977
|
},
|
|
963
978
|
radius: {
|
|
964
|
-
philosophy:
|
|
965
|
-
base:
|
|
979
|
+
philosophy: themeHints?.radius?.philosophy || options.shape,
|
|
980
|
+
base: themeHints?.radius?.base || shapeRadiusMap[options.shape] || 8
|
|
966
981
|
},
|
|
967
982
|
elevation: {
|
|
968
983
|
system: "layered",
|
|
969
984
|
max_levels: 3
|
|
970
985
|
},
|
|
971
986
|
motion: {
|
|
972
|
-
preference:
|
|
987
|
+
preference: themeHints?.motion?.preference || "subtle",
|
|
973
988
|
duration_scale: 1,
|
|
974
|
-
reduce_motion: themeHints?.
|
|
989
|
+
reduce_motion: themeHints?.motion?.reduce_motion ?? true
|
|
975
990
|
},
|
|
976
991
|
accessibility: {
|
|
977
992
|
wcag_level: options.accessibility?.wcag_level || "AA",
|
|
@@ -1003,21 +1018,21 @@ function buildEssenceV3(options, archetypeData, themeHints, recipeHints) {
|
|
|
1003
1018
|
}
|
|
1004
1019
|
var CSS_APPROACH_CONTENT = `## CSS Implementation
|
|
1005
1020
|
|
|
1006
|
-
This project uses **@decantr/css** for layout atoms, **visual treatments** for semantic styling, and **
|
|
1021
|
+
This project uses **@decantr/css** for layout atoms, **visual treatments** for semantic styling, and **theme decorators** for theme-specific decoration.
|
|
1007
1022
|
|
|
1008
1023
|
### Three File Setup
|
|
1009
1024
|
|
|
1010
1025
|
\`\`\`
|
|
1011
1026
|
src/styles/
|
|
1012
1027
|
tokens.css # Design tokens: --d-primary, --d-surface, --d-bg, etc.
|
|
1013
|
-
treatments.css # Visual treatments (d-interactive, d-surface, ...) +
|
|
1028
|
+
treatments.css # Visual treatments (d-interactive, d-surface, ...) + theme decorators
|
|
1014
1029
|
global.css # Resets, base typography, sr-only
|
|
1015
1030
|
\`\`\`
|
|
1016
1031
|
|
|
1017
1032
|
\`\`\`javascript
|
|
1018
1033
|
import { css } from '@decantr/css'; // Atoms runtime
|
|
1019
1034
|
import './styles/tokens.css'; // Theme tokens
|
|
1020
|
-
import './styles/treatments.css'; // Treatments +
|
|
1035
|
+
import './styles/treatments.css'; // Treatments + theme decorators
|
|
1021
1036
|
import './styles/global.css'; // Resets
|
|
1022
1037
|
\`\`\`
|
|
1023
1038
|
|
|
@@ -1036,7 +1051,7 @@ Six base treatment classes provide semantic styling. Combine with atoms for layo
|
|
|
1036
1051
|
|
|
1037
1052
|
### Composition
|
|
1038
1053
|
|
|
1039
|
-
Atoms + treatment +
|
|
1054
|
+
Atoms + treatment + theme decorator:
|
|
1040
1055
|
|
|
1041
1056
|
\`\`\`tsx
|
|
1042
1057
|
<button className={css('_px4 _py2') + ' d-interactive'} data-variant="primary">Deploy</button>
|
|
@@ -1046,7 +1061,7 @@ Atoms + treatment + recipe decorator:
|
|
|
1046
1061
|
|
|
1047
1062
|
- **Atoms:** \`css('_flex _col _gap4')\` \u2014 processed by @decantr/css runtime
|
|
1048
1063
|
- **Treatments:** \`d-interactive\`, \`d-surface\` \u2014 semantic base styles from treatments.css
|
|
1049
|
-
- **
|
|
1064
|
+
- **Theme decorators:** \`carbon-glass\`, \`carbon-code\` \u2014 theme-specific decoration from treatments.css
|
|
1050
1065
|
- **Combined:** \`css('_flex _col') + ' d-surface carbon-card'\`
|
|
1051
1066
|
|
|
1052
1067
|
### Atoms Quick Reference
|
|
@@ -1067,16 +1082,20 @@ Scale: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24. Example: \`_gap4\` = \`gap:1r
|
|
|
1067
1082
|
|
|
1068
1083
|
### Design Tokens
|
|
1069
1084
|
|
|
1070
|
-
| Token | Purpose |
|
|
1071
|
-
|
|
1072
|
-
| \`--d-primary\` | Primary brand color |
|
|
1073
|
-
| \`--d-surface\`, \`--d-surface-raised\` | Surface backgrounds |
|
|
1074
|
-
| \`--d-bg\` | Page background |
|
|
1075
|
-
| \`--d-border\` | Border color |
|
|
1076
|
-
| \`--d-text\`, \`--d-text-muted\` | Text colors |
|
|
1077
|
-
| \`--d-success\`, \`--d-error\`, \`--d-warning\`, \`--d-info\` | Status colors |
|
|
1078
|
-
| \`--d-shadow\`, \`--d-shadow-lg\` | Elevation shadows |
|
|
1079
|
-
| \`--d-radius\`, \`--d-radius-lg\` | Border radii |
|
|
1085
|
+
| Token | Purpose | Use for |
|
|
1086
|
+
|-------|---------|---------|
|
|
1087
|
+
| \`--d-primary\` | Primary brand color | Buttons, links, focus rings |
|
|
1088
|
+
| \`--d-surface\`, \`--d-surface-raised\` | Surface backgrounds | Cards, panels |
|
|
1089
|
+
| \`--d-bg\` | Page background | Body, main container |
|
|
1090
|
+
| \`--d-border\` | Border color | Dividers, card borders |
|
|
1091
|
+
| \`--d-text\`, \`--d-text-muted\` | Text colors | Body text, secondary text |
|
|
1092
|
+
| \`--d-success\`, \`--d-error\`, \`--d-warning\`, \`--d-info\` | Status colors | Alerts, badges, toasts |
|
|
1093
|
+
| \`--d-shadow\`, \`--d-shadow-lg\` | Elevation shadows | Cards, overlays |
|
|
1094
|
+
| \`--d-radius\`, \`--d-radius-lg\` | Border radii | Buttons, cards |
|
|
1095
|
+
| \`--d-font-mono\` | Monospace font stack | Code, metrics, data |
|
|
1096
|
+
| \`--d-duration-hover\` | Hover transition | Interactive elements |
|
|
1097
|
+
| \`--d-easing\` | Animation easing | All transitions |
|
|
1098
|
+
| \`--d-accent-glow\` | Glow color | Hover effects, focus rings |
|
|
1080
1099
|
|
|
1081
1100
|
### Routing
|
|
1082
1101
|
|
|
@@ -1113,8 +1132,7 @@ function generateProjectJson(detected, options, registrySource) {
|
|
|
1113
1132
|
cachedContent: {
|
|
1114
1133
|
archetypes: [],
|
|
1115
1134
|
patterns: [],
|
|
1116
|
-
themes: []
|
|
1117
|
-
recipes: []
|
|
1135
|
+
themes: []
|
|
1118
1136
|
}
|
|
1119
1137
|
},
|
|
1120
1138
|
initialized: {
|
|
@@ -1147,7 +1165,7 @@ function generateTaskContext(templateName, essence) {
|
|
|
1147
1165
|
TARGET: essence.target,
|
|
1148
1166
|
THEME_STYLE: essence.theme.style,
|
|
1149
1167
|
THEME_MODE: essence.theme.mode,
|
|
1150
|
-
THEME_RECIPE: essence.theme.
|
|
1168
|
+
THEME_RECIPE: essence.theme.style,
|
|
1151
1169
|
DEFAULT_SHELL: defaultShell,
|
|
1152
1170
|
GUARD_MODE: essence.guard.mode,
|
|
1153
1171
|
LAYOUT: layout,
|
|
@@ -1171,9 +1189,9 @@ function generateTaskContextV3(templateName, essence) {
|
|
|
1171
1189
|
const contentGap = essence.dna.spacing?.content_gap || "_gap4";
|
|
1172
1190
|
const vars = {
|
|
1173
1191
|
TARGET: essence.meta.target || "react",
|
|
1174
|
-
THEME_STYLE: essence.dna.theme.style,
|
|
1192
|
+
THEME_STYLE: essence.dna.theme.id || essence.dna.theme.style || "",
|
|
1175
1193
|
THEME_MODE: essence.dna.theme.mode,
|
|
1176
|
-
THEME_RECIPE: essence.dna.theme.
|
|
1194
|
+
THEME_RECIPE: essence.dna.theme.id || essence.dna.theme.style || "",
|
|
1177
1195
|
DEFAULT_SHELL: defaultShell,
|
|
1178
1196
|
GUARD_MODE: essence.meta.guard.mode,
|
|
1179
1197
|
LAYOUT: layout,
|
|
@@ -1210,9 +1228,9 @@ ${rows.join("\n")}`;
|
|
|
1210
1228
|
BLUEPRINT: "",
|
|
1211
1229
|
PERSONALITY: (essence.dna.personality || []).join(", "),
|
|
1212
1230
|
TARGET: essence.meta.target ?? "",
|
|
1213
|
-
THEME_STYLE: essence.dna.theme.style,
|
|
1231
|
+
THEME_STYLE: essence.dna.theme.id ?? essence.dna.theme.style ?? "",
|
|
1214
1232
|
THEME_MODE: essence.dna.theme.mode,
|
|
1215
|
-
THEME_RECIPE: essence.dna.theme.
|
|
1233
|
+
THEME_RECIPE: essence.dna.theme.id ?? essence.dna.theme.style ?? "",
|
|
1216
1234
|
SHAPE: essence.dna.theme.shape ?? "",
|
|
1217
1235
|
PAGES_TABLE: pagesTable,
|
|
1218
1236
|
FEATURES_LIST: featuresList,
|
|
@@ -1247,8 +1265,8 @@ ${cacheEntry}
|
|
|
1247
1265
|
return true;
|
|
1248
1266
|
}
|
|
1249
1267
|
}
|
|
1250
|
-
async function scaffoldProject(projectRoot, options, detected, registry, archetypeData, registrySource = "cache", themeData,
|
|
1251
|
-
const essenceV3 = buildEssenceV3(options, archetypeData, themeData
|
|
1268
|
+
async function scaffoldProject(projectRoot, options, detected, registry, archetypeData, registrySource = "cache", themeData, topologyMarkdown, composedSections, routeMap, patternSpecs, blueprintData) {
|
|
1269
|
+
const essenceV3 = buildEssenceV3(options, archetypeData, themeData);
|
|
1252
1270
|
const essence = buildEssence(options, archetypeData);
|
|
1253
1271
|
const decantrDir = join(projectRoot, ".decantr");
|
|
1254
1272
|
const contextDir = join(decantrDir, "context");
|
|
@@ -1284,7 +1302,7 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
|
|
|
1284
1302
|
}
|
|
1285
1303
|
writeFileSync(essencePath, JSON.stringify(essenceV3, null, 2) + "\n");
|
|
1286
1304
|
}
|
|
1287
|
-
const refreshResult = await refreshDerivedFiles(projectRoot, essenceV3, registry, themeData,
|
|
1305
|
+
const refreshResult = await refreshDerivedFiles(projectRoot, essenceV3, registry, themeData, { isInitialScaffold: true });
|
|
1288
1306
|
contextFiles.push(...refreshResult.contextFiles);
|
|
1289
1307
|
const gitignoreUpdated = updateGitignore(projectRoot);
|
|
1290
1308
|
return {
|
|
@@ -1299,7 +1317,7 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
|
|
|
1299
1317
|
function scaffoldMinimal(projectRoot) {
|
|
1300
1318
|
const decantrDir = join(projectRoot, ".decantr");
|
|
1301
1319
|
const customDir = join(decantrDir, "custom");
|
|
1302
|
-
const contentTypes = ["patterns", "
|
|
1320
|
+
const contentTypes = ["patterns", "themes", "blueprints", "archetypes", "shells"];
|
|
1303
1321
|
for (const type of contentTypes) {
|
|
1304
1322
|
mkdirSync(join(customDir, type), { recursive: true });
|
|
1305
1323
|
}
|
|
@@ -1307,9 +1325,8 @@ function scaffoldMinimal(projectRoot) {
|
|
|
1307
1325
|
version: "3.0.0",
|
|
1308
1326
|
dna: {
|
|
1309
1327
|
theme: {
|
|
1310
|
-
|
|
1328
|
+
id: "default",
|
|
1311
1329
|
mode: "dark",
|
|
1312
|
-
recipe: "default",
|
|
1313
1330
|
shape: "rounded"
|
|
1314
1331
|
},
|
|
1315
1332
|
spacing: {
|
|
@@ -1391,8 +1408,7 @@ function scaffoldMinimal(projectRoot) {
|
|
|
1391
1408
|
cachedContent: {
|
|
1392
1409
|
archetypes: [],
|
|
1393
1410
|
patterns: [],
|
|
1394
|
-
themes: []
|
|
1395
|
-
recipes: []
|
|
1411
|
+
themes: []
|
|
1396
1412
|
}
|
|
1397
1413
|
},
|
|
1398
1414
|
initialized: {
|
|
@@ -1486,12 +1502,11 @@ When available, use these tools:
|
|
|
1486
1502
|
gitignoreUpdated
|
|
1487
1503
|
};
|
|
1488
1504
|
}
|
|
1489
|
-
async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThemeData,
|
|
1505
|
+
async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThemeData, options) {
|
|
1490
1506
|
const decantrDir = join(projectRoot, ".decantr");
|
|
1491
1507
|
const contextDir = join(decantrDir, "context");
|
|
1492
1508
|
mkdirSync(contextDir, { recursive: true });
|
|
1493
|
-
const themeName = essence.dna.theme.style;
|
|
1494
|
-
const recipeName = essence.dna.theme.recipe ?? themeName;
|
|
1509
|
+
const themeName = essence.dna.theme.id || essence.dna.theme.style || "default";
|
|
1495
1510
|
const mode = essence.dna.theme.mode;
|
|
1496
1511
|
const guardMode = essence.meta.guard.mode;
|
|
1497
1512
|
const guardConfig = {
|
|
@@ -1501,7 +1516,6 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1501
1516
|
};
|
|
1502
1517
|
const personality = essence.dna.personality || [];
|
|
1503
1518
|
let themeData = prefetchedThemeData;
|
|
1504
|
-
let recipeData = prefetchedRecipeData;
|
|
1505
1519
|
if (!themeData) try {
|
|
1506
1520
|
const themeResult = await registry.fetchTheme(themeName);
|
|
1507
1521
|
if (themeResult?.data) {
|
|
@@ -1512,53 +1526,20 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1512
1526
|
palette: t.palette,
|
|
1513
1527
|
cvd_support: t.cvd_support,
|
|
1514
1528
|
tokens: t.tokens,
|
|
1515
|
-
|
|
1516
|
-
|
|
1529
|
+
typography: t.typography,
|
|
1530
|
+
motion: t.motion,
|
|
1531
|
+
decorators: t.decorators,
|
|
1532
|
+
treatments: t.treatments,
|
|
1533
|
+
spatial: t.spatial,
|
|
1534
|
+
radius: t.radius,
|
|
1535
|
+
shell: t.shell,
|
|
1536
|
+
effects: t.effects,
|
|
1537
|
+
compositions: t.compositions,
|
|
1538
|
+
pattern_preferences: t.pattern_preferences
|
|
1517
1539
|
};
|
|
1518
1540
|
}
|
|
1519
1541
|
} catch {
|
|
1520
1542
|
}
|
|
1521
|
-
if (!recipeData) try {
|
|
1522
|
-
const recipeResult = await registry.fetchRecipe(recipeName);
|
|
1523
|
-
if (recipeResult?.data) {
|
|
1524
|
-
const raw = recipeResult.data;
|
|
1525
|
-
const r = raw.data ?? raw;
|
|
1526
|
-
recipeData = {
|
|
1527
|
-
decorators: r.decorators,
|
|
1528
|
-
spatial_hints: r.spatial_hints,
|
|
1529
|
-
radius_hints: r.radius_hints,
|
|
1530
|
-
treatment_overrides: r.treatment_overrides
|
|
1531
|
-
};
|
|
1532
|
-
if (!recipeData.decorators && raw.data) {
|
|
1533
|
-
const inner = raw.data;
|
|
1534
|
-
if (inner.decorators) {
|
|
1535
|
-
recipeData.decorators = inner.decorators;
|
|
1536
|
-
recipeData.spatial_hints = inner.spatial_hints;
|
|
1537
|
-
recipeData.radius_hints = inner.radius_hints;
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
} catch {
|
|
1542
|
-
}
|
|
1543
|
-
if (!recipeData?.decorators || Object.keys(recipeData.decorators).length === 0) {
|
|
1544
|
-
try {
|
|
1545
|
-
const apiUrl = registry.apiUrl || "https://api.decantr.ai/v1";
|
|
1546
|
-
const resp = await fetch(`${apiUrl}/recipes/@official/${recipeName}`);
|
|
1547
|
-
if (resp.ok) {
|
|
1548
|
-
const apiData = await resp.json();
|
|
1549
|
-
const inner = apiData.data ?? apiData;
|
|
1550
|
-
if (inner.decorators && Object.keys(inner.decorators).length > 0) {
|
|
1551
|
-
recipeData = {
|
|
1552
|
-
decorators: inner.decorators,
|
|
1553
|
-
spatial_hints: inner.spatial_hints,
|
|
1554
|
-
radius_hints: inner.radius_hints,
|
|
1555
|
-
treatment_overrides: inner.treatment_overrides
|
|
1556
|
-
};
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
} catch {
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
1543
|
if (!themeData?.seed?.primary) {
|
|
1563
1544
|
try {
|
|
1564
1545
|
const apiUrl = registry.apiUrl || "https://api.decantr.ai/v1";
|
|
@@ -1572,8 +1553,16 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1572
1553
|
palette: inner.palette,
|
|
1573
1554
|
cvd_support: inner.cvd_support,
|
|
1574
1555
|
tokens: inner.tokens,
|
|
1575
|
-
|
|
1576
|
-
|
|
1556
|
+
typography: inner.typography,
|
|
1557
|
+
motion: inner.motion,
|
|
1558
|
+
decorators: inner.decorators,
|
|
1559
|
+
treatments: inner.treatments,
|
|
1560
|
+
spatial: inner.spatial,
|
|
1561
|
+
radius: inner.radius,
|
|
1562
|
+
shell: inner.shell,
|
|
1563
|
+
effects: inner.effects,
|
|
1564
|
+
compositions: inner.compositions,
|
|
1565
|
+
pattern_preferences: inner.pattern_preferences
|
|
1577
1566
|
};
|
|
1578
1567
|
}
|
|
1579
1568
|
}
|
|
@@ -1583,10 +1572,10 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1583
1572
|
const stylesDir = join(projectRoot, "src", "styles");
|
|
1584
1573
|
mkdirSync(stylesDir, { recursive: true });
|
|
1585
1574
|
const densityLevel = options.density || "comfortable";
|
|
1586
|
-
const spatialTokens = computeSpatialTokens(densityLevel,
|
|
1587
|
-
section_padding:
|
|
1588
|
-
density_bias: typeof
|
|
1589
|
-
content_gap_shift:
|
|
1575
|
+
const spatialTokens = computeSpatialTokens(densityLevel, themeData?.spatial ? {
|
|
1576
|
+
section_padding: themeData.spatial.section_padding ?? void 0,
|
|
1577
|
+
density_bias: typeof themeData.spatial.density_bias === "number" ? themeData.spatial.density_bias : void 0,
|
|
1578
|
+
content_gap_shift: themeData.spatial.content_gap_shift
|
|
1590
1579
|
} : void 0);
|
|
1591
1580
|
const tokensPath = join(stylesDir, "tokens.css");
|
|
1592
1581
|
const hasRealThemeData = themeData?.seed?.primary || themeData?.palette?.background;
|
|
@@ -1596,8 +1585,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1596
1585
|
const treatmentsPath = join(stylesDir, "treatments.css");
|
|
1597
1586
|
writeFileSync(treatmentsPath, generateTreatmentCSS(
|
|
1598
1587
|
spatialTokens,
|
|
1599
|
-
|
|
1600
|
-
|
|
1588
|
+
themeData?.treatments,
|
|
1589
|
+
themeData?.decorators,
|
|
1601
1590
|
themeName
|
|
1602
1591
|
));
|
|
1603
1592
|
const globalPath = join(stylesDir, "global.css");
|
|
@@ -1606,7 +1595,7 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1606
1595
|
}
|
|
1607
1596
|
const cssFiles = [tokensPath, treatmentsPath, globalPath];
|
|
1608
1597
|
const treatmentsMdPath = join(contextDir, "treatments.md");
|
|
1609
|
-
writeFileSync(treatmentsMdPath, generateTreatmentsContext(
|
|
1598
|
+
writeFileSync(treatmentsMdPath, generateTreatmentsContext(themeData, themeName));
|
|
1610
1599
|
const decantrMdPath = join(projectRoot, "DECANTR.md");
|
|
1611
1600
|
writeFileSync(decantrMdPath, generateDecantrMdV31(guardMode, CSS_APPROACH_CONTENT));
|
|
1612
1601
|
const hasSections = essence.blueprint.sections && essence.blueprint.sections.length > 0;
|
|
@@ -1708,8 +1697,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1708
1697
|
const topologyMarkdown = generateTopologySection(topologyData, personality);
|
|
1709
1698
|
const themeTokensCss = existsSync(tokensPath) ? readFileSync(tokensPath, "utf-8") : "";
|
|
1710
1699
|
const decoratorList = [];
|
|
1711
|
-
if (
|
|
1712
|
-
for (const [name, desc] of Object.entries(
|
|
1700
|
+
if (themeData?.decorators) {
|
|
1701
|
+
for (const [name, desc] of Object.entries(themeData.decorators)) {
|
|
1713
1702
|
decoratorList.push({ name, description: desc });
|
|
1714
1703
|
}
|
|
1715
1704
|
} else if (existsSync(decoratorsPath)) {
|
|
@@ -1777,7 +1766,6 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1777
1766
|
guardConfig,
|
|
1778
1767
|
personality,
|
|
1779
1768
|
themeName,
|
|
1780
|
-
recipeName,
|
|
1781
1769
|
zoneContext,
|
|
1782
1770
|
patternSpecs: sectionPatterns,
|
|
1783
1771
|
constraints: essence.dna.constraints,
|
|
@@ -1792,7 +1780,6 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1792
1780
|
appName: essence.meta.archetype || "Application",
|
|
1793
1781
|
blueprintId: "",
|
|
1794
1782
|
themeName,
|
|
1795
|
-
recipeName,
|
|
1796
1783
|
personality,
|
|
1797
1784
|
topologyMarkdown,
|
|
1798
1785
|
sections,
|
|
@@ -1867,8 +1854,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1867
1854
|
}
|
|
1868
1855
|
const themeTokensCss = existsSync(tokensPath) ? readFileSync(tokensPath, "utf-8") : "";
|
|
1869
1856
|
const decoratorList = [];
|
|
1870
|
-
if (
|
|
1871
|
-
for (const [name, desc] of Object.entries(
|
|
1857
|
+
if (themeData?.decorators) {
|
|
1858
|
+
for (const [name, desc] of Object.entries(themeData.decorators)) {
|
|
1872
1859
|
decoratorList.push({ name, description: desc });
|
|
1873
1860
|
}
|
|
1874
1861
|
} else if (existsSync(decoratorsPath)) {
|
|
@@ -1906,7 +1893,6 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1906
1893
|
guardConfig,
|
|
1907
1894
|
personality,
|
|
1908
1895
|
themeName,
|
|
1909
|
-
recipeName,
|
|
1910
1896
|
zoneContext: `This is the primary section (${shell} shell).`,
|
|
1911
1897
|
patternSpecs,
|
|
1912
1898
|
constraints: essence.dna.constraints,
|
|
@@ -2010,7 +1996,7 @@ function generateSyntheticComponents(patternId, description) {
|
|
|
2010
1996
|
return [...new Set(syntheticComponents)];
|
|
2011
1997
|
}
|
|
2012
1998
|
function generateSectionContext(input) {
|
|
2013
|
-
const { section, decorators, guardConfig, personality, themeName,
|
|
1999
|
+
const { section, decorators, guardConfig, personality, themeName, zoneContext, patternSpecs, themeHints, constraints, shellInfo } = input;
|
|
2014
2000
|
const lines = [];
|
|
2015
2001
|
lines.push(`# Section: ${section.id}`);
|
|
2016
2002
|
lines.push("");
|
|
@@ -2038,18 +2024,18 @@ function generateSectionContext(input) {
|
|
|
2038
2024
|
lines.push("**Visual Treatments:** All 6 base treatments available (see DECANTR.md for usage).");
|
|
2039
2025
|
if (decorators.length > 0) {
|
|
2040
2026
|
const names = decorators.map((d) => d.name).join(", ");
|
|
2041
|
-
lines.push(`**
|
|
2027
|
+
lines.push(`**Theme decorators:** ${names}`);
|
|
2042
2028
|
}
|
|
2043
2029
|
lines.push("");
|
|
2044
|
-
if (
|
|
2045
|
-
if (
|
|
2046
|
-
lines.push(`**Preferred:** ${
|
|
2030
|
+
if (themeHints) {
|
|
2031
|
+
if (themeHints.preferred && themeHints.preferred.length > 0) {
|
|
2032
|
+
lines.push(`**Preferred:** ${themeHints.preferred.join(", ")}`);
|
|
2047
2033
|
}
|
|
2048
|
-
if (
|
|
2049
|
-
lines.push(`**Compositions:** ${
|
|
2034
|
+
if (themeHints.compositions) {
|
|
2035
|
+
lines.push(`**Compositions:** ${themeHints.compositions}`);
|
|
2050
2036
|
}
|
|
2051
|
-
if (
|
|
2052
|
-
lines.push(`**Spatial hints:** ${
|
|
2037
|
+
if (themeHints.spatialHints) {
|
|
2038
|
+
lines.push(`**Spatial hints:** ${themeHints.spatialHints}`);
|
|
2053
2039
|
}
|
|
2054
2040
|
lines.push("");
|
|
2055
2041
|
}
|
|
@@ -2134,12 +2120,12 @@ function generateSectionContext(input) {
|
|
|
2134
2120
|
return lines.join("\n");
|
|
2135
2121
|
}
|
|
2136
2122
|
function generateScaffoldContext(input) {
|
|
2137
|
-
const { appName, blueprintId, themeName,
|
|
2123
|
+
const { appName, blueprintId, themeName, personality, topologyMarkdown, sections, routes, constraints, seo, navigation } = input;
|
|
2138
2124
|
const lines = [];
|
|
2139
2125
|
lines.push(`# Scaffold: ${appName}`);
|
|
2140
2126
|
lines.push("");
|
|
2141
2127
|
lines.push(`**Blueprint:** ${blueprintId}`);
|
|
2142
|
-
lines.push(`**Theme:** ${themeName}
|
|
2128
|
+
lines.push(`**Theme:** ${themeName}`);
|
|
2143
2129
|
lines.push(`**Personality:** ${personality.join(", ")}`);
|
|
2144
2130
|
lines.push("**Guard mode:** creative (no enforcement during initial scaffolding)");
|
|
2145
2131
|
lines.push("");
|
|
@@ -2234,7 +2220,7 @@ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as rea
|
|
|
2234
2220
|
import { join as join2 } from "path";
|
|
2235
2221
|
import { RegistryAPIClient } from "@decantr/registry";
|
|
2236
2222
|
var DEFAULT_API_URL = "https://api.decantr.ai/v1";
|
|
2237
|
-
var ALL_CONTENT_TYPES = ["themes", "patterns", "
|
|
2223
|
+
var ALL_CONTENT_TYPES = ["themes", "patterns", "blueprints", "archetypes", "shells"];
|
|
2238
2224
|
function loadFromCache(cacheDir, contentType, id, namespace) {
|
|
2239
2225
|
const nsDir = namespace ? join2(cacheDir, namespace) : cacheDir;
|
|
2240
2226
|
const cachePath = id ? join2(nsDir, contentType, `${id}.json`) : join2(nsDir, contentType, "index.json");
|
|
@@ -2398,12 +2384,6 @@ var RegistryClient = class {
|
|
|
2398
2384
|
async fetchShell(id) {
|
|
2399
2385
|
return this.fetchContentItem("shells", id);
|
|
2400
2386
|
}
|
|
2401
|
-
async fetchRecipes() {
|
|
2402
|
-
return this.fetchContentList("recipes");
|
|
2403
|
-
}
|
|
2404
|
-
async fetchRecipe(id) {
|
|
2405
|
-
return this.fetchContentItem("recipes", id);
|
|
2406
|
-
}
|
|
2407
2387
|
/**
|
|
2408
2388
|
* Check if API is available.
|
|
2409
2389
|
*/
|
|
@@ -8,7 +8,7 @@ import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
|
8
8
|
import { join } from "path";
|
|
9
9
|
var TELEMETRY_ENDPOINT = "https://api.decantr.ai/v1/telemetry/guard";
|
|
10
10
|
var TELEMETRY_TIMEOUT_MS = 3e3;
|
|
11
|
-
var DNA_RULES = /* @__PURE__ */ new Set(["style", "
|
|
11
|
+
var DNA_RULES = /* @__PURE__ */ new Set(["style", "density", "accessibility", "theme-mode"]);
|
|
12
12
|
async function sendGuardMetrics(metrics) {
|
|
13
13
|
try {
|
|
14
14
|
const controller = new AbortController();
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-D3W3MYKT.js";
|
|
2
|
+
import "./chunk-T7CQSJGV.js";
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@ Decantr is a design intelligence layer that sits between you (the AI code genera
|
|
|
18
18
|
|
|
19
19
|
DNA defines the foundational design rules. **DNA violations are errors** -- they must never happen without updating the essence first.
|
|
20
20
|
|
|
21
|
-
DNA axioms include: Theme (
|
|
21
|
+
DNA axioms include: Theme (id, mode, shape), Spacing (density, content gap), Typography (scale, weights), Color (palette, accent count), Radius (philosophy, base), Elevation (system, levels), Motion (preference, reduce-motion), Accessibility (WCAG level, focus-visible), and Personality traits.
|
|
22
22
|
|
|
23
23
|
### Blueprint (Structural Layout)
|
|
24
24
|
|
|
@@ -33,13 +33,12 @@ Blueprint includes: Sections (grouped by archetype with role, shell, and scoped
|
|
|
33
33
|
| # | Rule | Layer | What It Checks |
|
|
34
34
|
|---|------|-------|----------------|
|
|
35
35
|
| 1 | Style | DNA (error) | Code uses the theme specified in DNA |
|
|
36
|
-
| 2 |
|
|
37
|
-
| 3 |
|
|
38
|
-
| 4 |
|
|
39
|
-
| 5 |
|
|
40
|
-
| 6 |
|
|
41
|
-
| 7 |
|
|
42
|
-
| 8 | Pattern existence | Blueprint (warn) | Patterns referenced exist in the registry |
|
|
36
|
+
| 2 | Density | DNA (error) | Spacing follows the density profile |
|
|
37
|
+
| 3 | Accessibility | DNA (error) | Code meets the WCAG level |
|
|
38
|
+
| 4 | Theme-mode | DNA (error) | Theme/mode combination is valid |
|
|
39
|
+
| 5 | Structure | Blueprint (warn) | Pages exist in the blueprint sections |
|
|
40
|
+
| 6 | Layout | Blueprint (warn) | Pattern order matches the layout spec |
|
|
41
|
+
| 7 | Pattern existence | Blueprint (warn) | Patterns referenced exist in the registry |
|
|
43
42
|
|
|
44
43
|
### Enforcement Tiers
|
|
45
44
|
|
|
@@ -96,7 +95,7 @@ Run `decantr check` to validate code against the spec.
|
|
|
96
95
|
decantr status # Project health
|
|
97
96
|
decantr check # Detect drift violations
|
|
98
97
|
decantr get pattern X # Fetch a pattern spec from registry
|
|
99
|
-
decantr get
|
|
98
|
+
decantr get theme X # Fetch theme details and decorators
|
|
100
99
|
decantr search <query> # Search the registry
|
|
101
100
|
```
|
|
102
101
|
|
|
@@ -11,12 +11,11 @@ You are adding new pages or features to an existing Decantr project. Guided mode
|
|
|
11
11
|
| # | Layer | Rule | Enforcement | What It Means |
|
|
12
12
|
|---|-------|------|-------------|---------------|
|
|
13
13
|
| 1 | DNA | **Style** | ENFORCED | You MUST use theme `{{THEME_STYLE}}` |
|
|
14
|
-
| 2 | DNA | **
|
|
15
|
-
| 3 | DNA | **
|
|
16
|
-
| 4 | DNA | **
|
|
17
|
-
| 5 |
|
|
18
|
-
| 6 | Blueprint |
|
|
19
|
-
| 7 | Blueprint | Layout | advisory | Pattern order is flexible |
|
|
14
|
+
| 2 | DNA | **Density** | ENFORCED | You MUST follow density `{{DENSITY}}` |
|
|
15
|
+
| 3 | DNA | **Accessibility** | ENFORCED | You MUST meet WCAG level from essence |
|
|
16
|
+
| 4 | DNA | **Theme-mode** | ENFORCED | Theme/mode combination must be compatible |
|
|
17
|
+
| 5 | Blueprint | **Structure** | ENFORCED | Page MUST exist in essence before generating code |
|
|
18
|
+
| 6 | Blueprint | Layout | advisory | Pattern order is flexible |
|
|
20
19
|
| 8 | Blueprint | **Pattern-exists** | ENFORCED | All patterns must exist in the registry |
|
|
21
20
|
|
|
22
21
|
## Before You Start
|
|
@@ -64,7 +63,7 @@ Before adding a page:
|
|
|
64
63
|
During code generation:
|
|
65
64
|
|
|
66
65
|
- [ ] Use theme `{{THEME_STYLE}}` for all styling
|
|
67
|
-
- [ ] Use
|
|
66
|
+
- [ ] Use theme `{{THEME_RECIPE}}` decorators for decoration
|
|
68
67
|
- [ ] Follow the shell structure ({{DEFAULT_SHELL}})
|
|
69
68
|
- [ ] Include patterns from the layout array
|
|
70
69
|
|
|
@@ -72,7 +71,7 @@ After generation:
|
|
|
72
71
|
|
|
73
72
|
- [ ] Run `npx @decantr/cli validate`
|
|
74
73
|
- [ ] Verify the page matches the theme
|
|
75
|
-
- [ ] Check that the
|
|
74
|
+
- [ ] Check that the theme decorator styles are applied
|
|
76
75
|
|
|
77
76
|
## Violation Response
|
|
78
77
|
|
|
@@ -11,12 +11,11 @@ You are modifying existing code in a Decantr project. ALL 8 guard rules are enfo
|
|
|
11
11
|
| # | Layer | Rule | Enforcement | Consequence of Violation |
|
|
12
12
|
|---|-------|------|-------------|--------------------------|
|
|
13
13
|
| 1 | DNA | **Style** | STRICT | ERROR — Code rejected |
|
|
14
|
-
| 2 | DNA | **
|
|
15
|
-
| 3 | DNA | **
|
|
16
|
-
| 4 | DNA | **
|
|
17
|
-
| 5 |
|
|
18
|
-
| 6 | Blueprint | **
|
|
19
|
-
| 7 | Blueprint | **Layout** | STRICT | ERROR — Pattern order must match exactly |
|
|
14
|
+
| 2 | DNA | **Density** | STRICT | WARNING — Flagged for review |
|
|
15
|
+
| 3 | DNA | **Accessibility** | STRICT | ERROR — Code rejected |
|
|
16
|
+
| 4 | DNA | **Theme-mode** | STRICT | ERROR — Code rejected |
|
|
17
|
+
| 5 | Blueprint | **Structure** | STRICT | ERROR — Code rejected |
|
|
18
|
+
| 6 | Blueprint | **Layout** | STRICT | ERROR — Pattern order must match exactly |
|
|
20
19
|
| 8 | Blueprint | **Pattern-exists** | STRICT | ERROR — Code rejected |
|
|
21
20
|
|
|
22
21
|
## Violation Response Protocol
|
|
@@ -75,7 +74,7 @@ For the page you're modifying, verify:
|
|
|
75
74
|
- Shell matches the page's `shell` property
|
|
76
75
|
- Patterns match the page's `layout[]` in order
|
|
77
76
|
- Theme matches `theme.style`
|
|
78
|
-
-
|
|
77
|
+
- Theme decorators match `theme.id`
|
|
79
78
|
|
|
80
79
|
### 3. Plan Changes
|
|
81
80
|
|
|
@@ -93,7 +92,7 @@ Before modifying:
|
|
|
93
92
|
- [ ] Page exists in essence structure
|
|
94
93
|
- [ ] I know the exact layout order: `{{LAYOUT}}`
|
|
95
94
|
- [ ] I will use theme: `{{THEME_STYLE}}`
|
|
96
|
-
- [ ] I will use
|
|
95
|
+
- [ ] I will use theme: `{{THEME_RECIPE}}`
|
|
97
96
|
- [ ] I will follow density: `{{DENSITY}}`
|
|
98
97
|
|
|
99
98
|
During modification:
|
|
@@ -144,7 +143,7 @@ Swapping `chart-grid` and `data-table` is a Layout guard violation.
|
|
|
144
143
|
| "Theme mismatch" | Used different theme | Revert to `{{THEME_STYLE}}` |
|
|
145
144
|
| "Page undefined" | Edited undeclared page | Add page to essence first |
|
|
146
145
|
| "Layout order wrong" | Patterns out of order | Match `layout[]` exactly |
|
|
147
|
-
| "
|
|
146
|
+
| "Theme mismatch" | Wrong decoration style | Use `{{THEME_RECIPE}}` |
|
|
148
147
|
| "Density drift" | Wrong spacing values | Use `{{CONTENT_GAP}}` tokens |
|
|
149
148
|
|
|
150
149
|
## Proposing Essence Changes
|
|
@@ -17,8 +17,7 @@ During scaffolding, the following rules are recommendations, not requirements:
|
|
|
17
17
|
| # | Layer | Rule | Status | Guidance |
|
|
18
18
|
|---|-------|------|--------|----------|
|
|
19
19
|
| 1 | DNA | Style | Advisory | Use the theme from essence, but creative variations are acceptable |
|
|
20
|
-
| 2 | DNA |
|
|
21
|
-
| 3 | DNA | Density | Advisory | Follow spacing guidelines loosely |
|
|
20
|
+
| 2 | DNA | Density | Advisory | Follow spacing guidelines loosely |
|
|
22
21
|
| 4 | DNA | Accessibility | Advisory | Meet WCAG level from essence where possible |
|
|
23
22
|
| 5 | DNA | Theme-mode | Advisory | Use the specified theme/mode combination |
|
|
24
23
|
| 6 | Blueprint | Structure | Advisory | Follow the page structure, add placeholder content |
|