@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.
@@ -0,0 +1,46 @@
1
+ // src/guard-context.ts
2
+ import { existsSync, readdirSync, readFileSync } from "fs";
3
+ import { join } from "path";
4
+ function loadJsonEntries(dir) {
5
+ if (!existsSync(dir)) return [];
6
+ try {
7
+ return readdirSync(dir).filter((file) => file.endsWith(".json") && file !== "index.json").map((file) => JSON.parse(readFileSync(join(dir, file), "utf-8")));
8
+ } catch {
9
+ return [];
10
+ }
11
+ }
12
+ function buildGuardRegistryContext(projectRoot = process.cwd()) {
13
+ const themeRegistry = /* @__PURE__ */ new Map();
14
+ const patternRegistry = /* @__PURE__ */ new Map();
15
+ const cacheDir = join(projectRoot, ".decantr", "cache");
16
+ const customDir = join(projectRoot, ".decantr", "custom");
17
+ for (const data of loadJsonEntries(join(cacheDir, "@official", "themes"))) {
18
+ if (typeof data.id === "string" && !themeRegistry.has(data.id)) {
19
+ themeRegistry.set(data.id, {
20
+ modes: Array.isArray(data.modes) ? data.modes.filter((mode) => typeof mode === "string") : ["light", "dark"]
21
+ });
22
+ }
23
+ }
24
+ for (const data of loadJsonEntries(join(customDir, "themes"))) {
25
+ if (typeof data.id === "string") {
26
+ themeRegistry.set(`custom:${data.id}`, {
27
+ modes: Array.isArray(data.modes) ? data.modes.filter((mode) => typeof mode === "string") : ["light", "dark"]
28
+ });
29
+ }
30
+ }
31
+ for (const data of loadJsonEntries(join(cacheDir, "@official", "patterns"))) {
32
+ if (typeof data.id === "string" && !patternRegistry.has(data.id)) {
33
+ patternRegistry.set(data.id, data);
34
+ }
35
+ }
36
+ for (const data of loadJsonEntries(join(customDir, "patterns"))) {
37
+ if (typeof data.id === "string") {
38
+ patternRegistry.set(data.id, data);
39
+ }
40
+ }
41
+ return { themeRegistry, patternRegistry };
42
+ }
43
+
44
+ export {
45
+ buildGuardRegistryContext
46
+ };
@@ -1,3 +1,7 @@
1
+ import {
2
+ buildGuardRegistryContext
3
+ } from "./chunk-KUDAVJOR.js";
4
+
1
5
  // src/commands/heal.ts
2
6
  import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
3
7
  import { join as join2 } from "path";
@@ -8,7 +12,7 @@ import { readFileSync, writeFileSync, existsSync } from "fs";
8
12
  import { join } from "path";
9
13
  var TELEMETRY_ENDPOINT = "https://api.decantr.ai/v1/telemetry/guard";
10
14
  var TELEMETRY_TIMEOUT_MS = 3e3;
11
- var DNA_RULES = /* @__PURE__ */ new Set(["style", "density", "accessibility", "theme-mode"]);
15
+ var DNA_RULES = /* @__PURE__ */ new Set(["theme", "style", "density", "accessibility", "theme-mode"]);
12
16
  async function sendGuardMetrics(metrics) {
13
17
  try {
14
18
  const controller = new AbortController();
@@ -77,7 +81,7 @@ function collectMetrics(essence, issues) {
77
81
  resolution_rate: 0,
78
82
  sections_count: sections.length,
79
83
  routes_count: Object.keys(routes).length,
80
- theme: theme.style ?? "unknown"
84
+ theme: theme.id ?? "unknown"
81
85
  };
82
86
  }
83
87
 
@@ -109,7 +113,7 @@ async function cmdHeal(projectRoot = process.cwd(), options = {}) {
109
113
  }
110
114
  }
111
115
  try {
112
- const violations = evaluateGuard(essence, { themeRegistry: /* @__PURE__ */ new Map(), patternRegistry: /* @__PURE__ */ new Map() });
116
+ const violations = evaluateGuard(essence, buildGuardRegistryContext(projectRoot));
113
117
  for (const v of violations) {
114
118
  issues.push({
115
119
  type: v.severity === "error" ? "error" : "warning",
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
- import "./chunk-Y5C2O7Z7.js";
2
- import "./chunk-XKXUVNUQ.js";
1
+ import "./chunk-KAEQTVAM.js";
2
+ import "./chunk-H4H3IQJK.js";
3
+ import "./chunk-KUDAVJOR.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RegistryClient,
3
3
  refreshDerivedFiles
4
- } from "./chunk-XKXUVNUQ.js";
4
+ } from "./chunk-H4H3IQJK.js";
5
5
 
6
6
  // src/commands/upgrade.ts
7
7
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -26,22 +26,20 @@ async function cmdUpgrade(projectRoot = process.cwd(), options = {}) {
26
26
  });
27
27
  console.log("Checking for updates...\n");
28
28
  const upgrades = [];
29
- const themeStyle = essence.dna?.theme?.style || essence.theme?.style;
30
- if (themeStyle) {
31
- const theme = await client.fetchTheme(themeStyle);
29
+ const themeId = essence.dna?.theme?.id || essence.theme?.id;
30
+ if (themeId) {
31
+ const theme = await client.fetchTheme(themeId);
32
32
  if (theme) {
33
- const themeData = theme.data;
34
- const inner = themeData.data ?? themeData;
35
- const latestVersion = inner.version || themeData.version;
33
+ const latestVersion = theme.data.version;
36
34
  if (latestVersion) {
37
35
  const current = essence.dna?.theme?.version || essence.theme?.version || "0.0.0";
38
36
  if (latestVersion !== current) {
39
37
  upgrades.push({
40
38
  type: "theme",
41
- id: themeStyle,
39
+ id: themeId,
42
40
  currentVersion: current,
43
41
  latestVersion,
44
- data: themeData
42
+ data: theme.data
45
43
  });
46
44
  }
47
45
  }
@@ -50,9 +48,7 @@ async function cmdUpgrade(projectRoot = process.cwd(), options = {}) {
50
48
  if (essence.blueprint && typeof essence.blueprint === "string") {
51
49
  const blueprint = await client.fetchBlueprint(essence.blueprint);
52
50
  if (blueprint) {
53
- const bpData = blueprint.data;
54
- const inner = bpData.data ?? bpData;
55
- const latestVersion = inner.version || bpData.version;
51
+ const latestVersion = blueprint.data.version;
56
52
  if (latestVersion) {
57
53
  const current = essence.blueprintVersion || "0.0.0";
58
54
  if (latestVersion !== current) {
@@ -61,7 +57,7 @@ async function cmdUpgrade(projectRoot = process.cwd(), options = {}) {
61
57
  id: essence.blueprint,
62
58
  currentVersion: current,
63
59
  latestVersion,
64
- data: bpData
60
+ data: blueprint.data
65
61
  });
66
62
  }
67
63
  }
package/package.json CHANGED
@@ -1,17 +1,21 @@
1
1
  {
2
2
  "name": "@decantr/cli",
3
- "version": "1.7.4",
4
- "description": "Decantr CLI — search the registry, validate essence files, and access design intelligence from the terminal",
3
+ "version": "1.7.6",
4
+ "description": "Decantr CLI — scaffold, audit, and maintain Decantr projects from the terminal",
5
+ "author": "Decantr AI",
5
6
  "license": "MIT",
7
+ "bugs": {
8
+ "url": "https://github.com/decantr-ai/decantr/issues"
9
+ },
6
10
  "repository": {
7
11
  "type": "git",
8
- "url": "https://github.com/decantr-ai/decantr.git",
12
+ "url": "git+https://github.com/decantr-ai/decantr.git",
9
13
  "directory": "packages/cli"
10
14
  },
11
15
  "homepage": "https://decantr.ai",
12
16
  "type": "module",
13
17
  "bin": {
14
- "decantr": "./dist/bin.js"
18
+ "decantr": "dist/bin.js"
15
19
  },
16
20
  "main": "dist/index.js",
17
21
  "files": [
@@ -23,8 +27,10 @@
23
27
  "access": "public"
24
28
  },
25
29
  "dependencies": {
26
- "@decantr/essence-spec": "1.0.0-beta.11",
27
- "@decantr/registry": "1.0.0-beta.12"
30
+ "@decantr/core": "1.0.0",
31
+ "@decantr/essence-spec": "1.0.0",
32
+ "@decantr/registry": "1.0.1",
33
+ "@decantr/verifier": "1.0.1"
28
34
  },
29
35
  "scripts": {
30
36
  "build": "tsup",
@@ -68,6 +68,11 @@ When a user request would violate guard rules:
68
68
  - `decantr_check_drift` -- Check if planned changes violate rules
69
69
  - `decantr_accept_drift` -- Accept a detected drift as intentional
70
70
  - `decantr_update_essence` -- Update the essence spec to match desired changes
71
+ - `decantr_audit_project` -- Audit the current project against the essence contract and compiled packs
72
+ - `decantr_get_scaffold_context` -- Read the top-level scaffold task, scaffold overview, compiled scaffold pack, and review pack together
73
+ - `decantr_get_page_context` -- Read a route-local page pack together with its parent section context when available
74
+ - `decantr_get_execution_pack` -- Read compiled scaffold, review, mutation, section, and page packs
75
+ - `decantr_get_section_context` -- Read the richer section context with compiled pack data when available
71
76
 
72
77
  ---
73
78
 
@@ -79,15 +84,38 @@ When a user request would violate guard rules:
79
84
 
80
85
  ### Initial scaffolding
81
86
 
82
- Read `.decantr/context/scaffold.md` for the full app overview, topology, and route map.
87
+ Treat the compiled execution-pack files as the primary source of truth.
88
+ Use narrative docs only as secondary explanation when the compiled packs are not enough.
89
+ 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.
90
+
91
+ Read `.decantr/context/scaffold-pack.md` first for the compact compiled shell, theme, feature, and route contract.
92
+ Then read `.decantr/context/scaffold.md` for the fuller app overview, topology, route map, and voice guidance.
93
+ Start implementation from the shell layouts and shared route structure before filling in section pages.
83
94
 
84
95
  ### Working on a section
85
96
 
86
- Read `.decantr/context/section-{name}.md` for that section's complete context. Each section file contains guard rules, theme tokens, decorator classes, pattern specs with code examples, zone context, and routes. **Everything you need is in that one file.**
97
+ Read `.decantr/context/section-{name}-pack.md` for the compact compiled section contract.
98
+ Then read `.decantr/context/section-{name}.md` for the fuller context. Prefer the compiled section pack if the two sources differ, and do not invent section features, shells, or themes that are not present in the compiled contract.
99
+
100
+ ### Working on a route
101
+
102
+ Read `.decantr/context/page-{name}-pack.md` for the most local compiled route contract before editing a specific page. Route-local packs should win over broader narrative docs when there is any mismatch.
103
+
104
+ ### Editing rules
105
+
106
+ - Use the real `@decantr/css` runtime for atoms. If `package.json` does not already include `@decantr/css`, add it before implementation.
107
+ - If a local `package.json` is present, trust its declared Decantr dependencies over external assumptions about package availability.
108
+ - Do **not** create local atom-runtime substitutes such as `src/lib/css.js`, `src/lib/css.ts`, or hand-written `src/styles/atoms.css` files unless the task explicitly asks for a fallback runtime.
109
+ - Import `src/styles/global.css`, `src/styles/tokens.css`, and `src/styles/treatments.css`.
110
+ - Reuse the existing Decantr tokens, treatments, and decorators instead of inventing a new visual system.
111
+ - If `dna.accessibility.skip_nav = true`, add a visible-on-focus skip link and a matching main landmark target such as `<main id="main-content">`.
112
+ - If `dna.motion.reduce_motion = true`, add an explicit `prefers-reduced-motion: reduce` path in project CSS.
113
+ - Do not modify generated context files unless you are explicitly regenerating or refreshing Decantr context.
114
+ - If a required context file is missing or inconsistent, stop and report which file is missing before continuing.
87
115
 
88
116
  ### Validation
89
117
 
90
- Run `decantr check` to validate code against the spec.
118
+ Run `decantr check` to detect drift violations while editing and `decantr audit` to audit the whole project contract after implementation.
91
119
 
92
120
  ### Quick Commands
93
121
 
@@ -17,9 +17,8 @@ Auto-generated summary of `decantr.essence.json`.
17
17
 
18
18
  | Property | Value |
19
19
  |----------|-------|
20
- | Theme | {{THEME_STYLE}} |
20
+ | Theme ID | {{THEME_ID}} |
21
21
  | Mode | {{THEME_MODE}} |
22
- | Theme ID | {{THEME_RECIPE}} |
23
22
  | Shape | {{SHAPE}} |
24
23
 
25
24
  ## Structure
@@ -10,7 +10,7 @@ You are adding new pages or features to an existing Decantr project. Guided mode
10
10
 
11
11
  | # | Layer | Rule | Enforcement | What It Means |
12
12
  |---|-------|------|-------------|---------------|
13
- | 1 | DNA | **Style** | ENFORCED | You MUST use theme `{{THEME_STYLE}}` |
13
+ | 1 | DNA | **Theme** | ENFORCED | You MUST use theme `{{THEME_ID}}` |
14
14
  | 2 | DNA | **Density** | ENFORCED | You MUST follow density `{{DENSITY}}` |
15
15
  | 3 | DNA | **Accessibility** | ENFORCED | You MUST meet WCAG level from essence |
16
16
  | 4 | DNA | **Theme-mode** | ENFORCED | Theme/mode combination must be compatible |
@@ -67,8 +67,8 @@ Before adding a page:
67
67
 
68
68
  During code generation:
69
69
 
70
- - [ ] Use theme `{{THEME_STYLE}}` for all styling
71
- - [ ] Use theme `{{THEME_RECIPE}}` decorators for decoration
70
+ - [ ] Use theme `{{THEME_ID}}` for all styling
71
+ - [ ] Use theme `{{THEME_ID}}` treatments and decorators for visual identity
72
72
  - [ ] Follow the shell structure for the target section (see section context file for shell notes)
73
73
  - [ ] Include patterns from the layout array
74
74
 
@@ -10,7 +10,7 @@ You are modifying existing code in a Decantr project. ALL 7 guard rules are enfo
10
10
 
11
11
  | # | Layer | Rule | Enforcement | Consequence of Violation |
12
12
  |---|-------|------|-------------|--------------------------|
13
- | 1 | DNA | **Style** | STRICT | ERROR — Code rejected |
13
+ | 1 | DNA | **Theme** | STRICT | ERROR — Code rejected |
14
14
  | 2 | DNA | **Density** | STRICT | WARNING — Flagged for review |
15
15
  | 3 | DNA | **Accessibility** | STRICT | ERROR — Code rejected |
16
16
  | 4 | DNA | **Theme-mode** | STRICT | ERROR — Code rejected |
@@ -34,11 +34,11 @@ When ANY rule would be violated:
34
34
  **Theme violation:**
35
35
  ```
36
36
  STOP: I cannot use theme "glassmorphism" because the essence specifies
37
- "{{THEME_STYLE}}". This would violate the Style guard rule.
37
+ "{{THEME_ID}}". This would violate the Theme guard rule.
38
38
 
39
39
  Would you like me to:
40
40
  1. Update the essence to use "glassmorphism" instead?
41
- 2. Keep the current theme "{{THEME_STYLE}}"?
41
+ 2. Keep the current theme "{{THEME_ID}}"?
42
42
  ```
43
43
 
44
44
  **Layout violation:**
@@ -73,7 +73,7 @@ For the page you're modifying, verify:
73
73
  - Page ID exists in `blueprint.sections[].pages[]`
74
74
  - Shell matches the page's `shell` property
75
75
  - Patterns match the page's `layout[]` in order
76
- - Theme matches `theme.style`
76
+ - Theme matches `theme.id`
77
77
  - Theme decorators match `theme.id`
78
78
 
79
79
  ### 3. Plan Changes
@@ -91,7 +91,7 @@ Before modifying:
91
91
 
92
92
  - [ ] Page exists in essence structure
93
93
  - [ ] I know the layout order for the target page (check `blueprint.sections[].pages[]`)
94
- - [ ] I will use theme: `{{THEME_STYLE}}`
94
+ - [ ] I will use theme: `{{THEME_ID}}`
95
95
  - [ ] I will follow density: `{{DENSITY}}`
96
96
 
97
97
  During modification:
@@ -139,10 +139,10 @@ Swapping `chart-grid` and `data-table` is a Layout guard violation.
139
139
 
140
140
  | Violation | What Happened | Fix |
141
141
  |-----------|---------------|-----|
142
- | "Theme mismatch" | Used different theme | Revert to `{{THEME_STYLE}}` |
142
+ | "Theme mismatch" | Used different theme | Revert to `{{THEME_ID}}` |
143
143
  | "Page undefined" | Edited undeclared page | Add page to essence first |
144
144
  | "Layout order wrong" | Patterns out of order | Match `layout[]` exactly |
145
- | "Theme mismatch" | Wrong decoration style | Use `{{THEME_RECIPE}}` |
145
+ | "Theme mismatch" | Wrong treatments or decorators | Use `{{THEME_ID}}` theme styling |
146
146
  | "Density drift" | Wrong spacing values | Use `{{CONTENT_GAP}}` tokens |
147
147
 
148
148
  ## Proposing Essence Changes