@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.
- package/README.md +84 -0
- package/dist/bin.js +3 -2
- package/dist/{chunk-XKXUVNUQ.js → chunk-H4H3IQJK.js} +561 -122
- package/dist/{chunk-Y5C2O7Z7.js → chunk-KAEQTVAM.js} +1249 -360
- package/dist/chunk-KUDAVJOR.js +46 -0
- package/dist/{heal-VYEGIUAS.js → heal-MURR3RVQ.js} +7 -3
- package/dist/index.js +3 -2
- package/dist/{upgrade-GTUGOUSD.js → upgrade-XNUAON3G.js} +9 -13
- package/package.json +12 -6
- package/src/templates/DECANTR.md.template +31 -3
- package/src/templates/essence-summary.md.template +1 -2
- package/src/templates/task-add-page.md.template +3 -3
- package/src/templates/task-modify.md.template +7 -7
|
@@ -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.
|
|
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,
|
|
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-
|
|
2
|
-
import "./chunk-
|
|
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-
|
|
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
|
|
30
|
-
if (
|
|
31
|
-
const theme = await client.fetchTheme(
|
|
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
|
|
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:
|
|
39
|
+
id: themeId,
|
|
42
40
|
currentVersion: current,
|
|
43
41
|
latestVersion,
|
|
44
|
-
data:
|
|
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
|
|
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:
|
|
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
|
-
"description": "Decantr CLI —
|
|
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": "
|
|
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/
|
|
27
|
-
"@decantr/
|
|
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
|
-
|
|
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
|
|
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
|
|
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 | {{
|
|
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 | **
|
|
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 `{{
|
|
71
|
-
- [ ] Use theme `{{
|
|
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 | **
|
|
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
|
-
"{{
|
|
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 "{{
|
|
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.
|
|
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: `{{
|
|
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 `{{
|
|
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
|
|
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
|