@decantr/cli 1.7.5 → 1.7.7
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/LICENSE +21 -0
- package/README.md +51 -3
- package/dist/bin.js +2 -2
- package/dist/{chunk-H4H3IQJK.js → chunk-4D5V6GQU.js} +75 -10
- package/dist/{chunk-KAEQTVAM.js → chunk-OHQXL7EJ.js} +468 -330
- package/dist/index.js +2 -2
- package/dist/{upgrade-XNUAON3G.js → upgrade-WE7Y7ZOE.js} +1 -1
- package/package.json +10 -8
- package/src/templates/DECANTR.md.template +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Decantr AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -14,12 +14,22 @@ npm install -D @decantr/cli
|
|
|
14
14
|
Or run it without installing:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npx @decantr/cli
|
|
17
|
+
npx @decantr/cli new my-app --blueprint=agent-marketplace
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
Use `decantr new` for a greenfield workspace in a fresh directory.
|
|
21
|
+
Use `decantr analyze` first when you already have an app and want Decantr governance without adopting a blueprint.
|
|
22
|
+
Use `decantr init` to attach Decantr contract/context files to an existing project or to create a contract-only workspace.
|
|
23
|
+
|
|
24
|
+
Current starter adapter availability:
|
|
25
|
+
|
|
26
|
+
- `react-vite` is the runnable bootstrap adapter in this wave
|
|
27
|
+
- other contract targets remain valid Decantr targets, but `decantr new` will keep them in contract-only mode until their adapters land
|
|
28
|
+
|
|
20
29
|
## What It Does
|
|
21
30
|
|
|
22
31
|
- scaffolds Decantr projects from blueprints, archetypes, or prompts
|
|
32
|
+
- supports three workflow lanes: greenfield blueprint, brownfield adoption, and hybrid composition
|
|
23
33
|
- generates execution-pack context files for AI coding assistants
|
|
24
34
|
- audits projects against Decantr contracts
|
|
25
35
|
- searches the registry and showcase benchmark corpus
|
|
@@ -28,7 +38,10 @@ npx @decantr/cli init --blueprint=agent-marketplace --yes
|
|
|
28
38
|
## Common Commands
|
|
29
39
|
|
|
30
40
|
```bash
|
|
31
|
-
decantr
|
|
41
|
+
decantr new my-app --blueprint=agent-marketplace
|
|
42
|
+
decantr analyze
|
|
43
|
+
decantr init --existing --yes
|
|
44
|
+
decantr init --existing --blueprint=agent-marketplace
|
|
32
45
|
decantr magic "AI-native analytics workspace"
|
|
33
46
|
decantr audit
|
|
34
47
|
decantr check
|
|
@@ -36,14 +49,49 @@ decantr registry summary --namespace @official --json
|
|
|
36
49
|
decantr showcase verification --json
|
|
37
50
|
```
|
|
38
51
|
|
|
52
|
+
## Greenfield Certification
|
|
53
|
+
|
|
54
|
+
Use the built-in certification harness before releases when you want to prove that representative blueprints still scaffold into runnable starter projects:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm --filter @decantr/cli certify:blueprints
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
By default it certifies `portfolio`, `producer-studio`, and `agent-marketplace` by:
|
|
61
|
+
|
|
62
|
+
- running `decantr new` in fresh temp directories
|
|
63
|
+
- seeding offline content from `DECANTR_CONTENT_DIR` or a sibling `decantr-content` checkout
|
|
64
|
+
- verifying the starter runtime files and router mode match the generated essence
|
|
65
|
+
- running `npm run build` in each scaffolded project
|
|
66
|
+
|
|
67
|
+
Override the matrix or emit JSON when needed:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm --filter @decantr/cli certify:blueprints -- --blueprints=portfolio,legal-research --json
|
|
71
|
+
```
|
|
72
|
+
|
|
39
73
|
Offline blueprint scaffolding expects a real local content source:
|
|
40
74
|
|
|
41
75
|
```bash
|
|
42
|
-
DECANTR_CONTENT_DIR=/path/to/decantr-content decantr
|
|
76
|
+
DECANTR_CONTENT_DIR=/path/to/decantr-content decantr new my-app --blueprint=agent-marketplace --offline
|
|
43
77
|
```
|
|
44
78
|
|
|
45
79
|
If a requested offline blueprint, archetype, or theme cannot be resolved from local cache/custom content or `DECANTR_CONTENT_DIR`, the CLI now stops explicitly instead of silently falling back to the default scaffold.
|
|
46
80
|
|
|
81
|
+
## Workflow Certification
|
|
82
|
+
|
|
83
|
+
The broader workflow matrix now has its own certification entrypoint:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pnpm --filter @decantr/cli certify:workflows
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
It covers:
|
|
90
|
+
|
|
91
|
+
- greenfield blueprint bootstrap
|
|
92
|
+
- brownfield `analyze -> init --existing`
|
|
93
|
+
- hybrid follow-up composition via Decantr mutation commands
|
|
94
|
+
|
|
47
95
|
## Generated Context
|
|
48
96
|
|
|
49
97
|
Scaffolded projects include compiled execution packs under `.decantr/context/`, including:
|
package/dist/bin.js
CHANGED
|
@@ -6,8 +6,9 @@ import { computeSpatialTokens } from "@decantr/essence-spec";
|
|
|
6
6
|
import { compileExecutionPackBundle } from "@decantr/core";
|
|
7
7
|
|
|
8
8
|
// src/treatments.ts
|
|
9
|
-
function generateTreatmentCSS(spatialTokens, treatmentOverrides, themeDecorators, themeName) {
|
|
9
|
+
function generateTreatmentCSS(spatialTokens, treatmentOverrides, themeDecorators, themeName, themeDecoratorDefinitions) {
|
|
10
10
|
const lines = [];
|
|
11
|
+
const decoratorAnimationNames = /* @__PURE__ */ new Set();
|
|
11
12
|
lines.push("/* Generated by @decantr/cli \u2014 Visual Treatment System */");
|
|
12
13
|
lines.push("");
|
|
13
14
|
lines.push("@layer treatments {");
|
|
@@ -195,9 +196,9 @@ ${themeBody}
|
|
|
195
196
|
["font-size", "0.75rem"],
|
|
196
197
|
["font-weight", "500"],
|
|
197
198
|
["padding", "0.125rem 0.5rem"],
|
|
198
|
-
["margin-top", "calc(var(--d-annotation-mt) * var(--d-density-scale, 1))"],
|
|
199
199
|
["border-radius", "var(--d-radius-full)"],
|
|
200
|
-
["background", "var(--d-surface)"],
|
|
200
|
+
["background", "color-mix(in srgb, var(--d-surface-raised) 88%, transparent)"],
|
|
201
|
+
["border", "1px solid color-mix(in srgb, var(--d-border) 72%, transparent)"],
|
|
201
202
|
["color", "var(--d-text-muted)"],
|
|
202
203
|
["white-space", "nowrap"]
|
|
203
204
|
]);
|
|
@@ -247,10 +248,47 @@ ${themeBody}
|
|
|
247
248
|
lines.push("}");
|
|
248
249
|
lines.push("");
|
|
249
250
|
lines.push("} /* end @layer treatments */");
|
|
251
|
+
const decoratorRules = [];
|
|
252
|
+
if (themeDecoratorDefinitions) {
|
|
253
|
+
for (const [className, definition] of Object.entries(themeDecoratorDefinitions)) {
|
|
254
|
+
const props = definition?.suggested_properties ?? {};
|
|
255
|
+
const entries = Object.entries(props);
|
|
256
|
+
if (entries.length === 0) continue;
|
|
257
|
+
decoratorRules.push(`.${className} {`);
|
|
258
|
+
for (const [prop, value] of entries) {
|
|
259
|
+
decoratorRules.push(` ${prop}: ${value};`);
|
|
260
|
+
if (prop === "animation") {
|
|
261
|
+
const animationName = value.split(/\s+/)[0]?.trim();
|
|
262
|
+
if (animationName) decoratorAnimationNames.add(animationName);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
decoratorRules.push("}");
|
|
266
|
+
decoratorRules.push("");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const decoratorKeyframes = [];
|
|
270
|
+
if (decoratorAnimationNames.has("carbon-fade-slide")) {
|
|
271
|
+
decoratorKeyframes.push("@keyframes carbon-fade-slide {");
|
|
272
|
+
decoratorKeyframes.push(" from { opacity: 0; transform: translateY(12px); }");
|
|
273
|
+
decoratorKeyframes.push(" to { opacity: 1; transform: translateY(0); }");
|
|
274
|
+
decoratorKeyframes.push("}");
|
|
275
|
+
decoratorKeyframes.push("");
|
|
276
|
+
}
|
|
277
|
+
if (decoratorAnimationNames.has("pulse")) {
|
|
278
|
+
decoratorKeyframes.push("@keyframes pulse {");
|
|
279
|
+
decoratorKeyframes.push(" 0%, 100% { opacity: 1; }");
|
|
280
|
+
decoratorKeyframes.push(" 50% { opacity: 0.5; }");
|
|
281
|
+
decoratorKeyframes.push("}");
|
|
282
|
+
decoratorKeyframes.push("");
|
|
283
|
+
}
|
|
284
|
+
const decoratorComments = themeDecorators ? Object.entries(themeDecorators).map(([name, description]) => ` /* .${name}: ${description} */`).join("\n") : " /* No theme decorators available. */";
|
|
285
|
+
const decoratorBody = decoratorRules.length > 0 ? `${decoratorRules.join("\n")}${decoratorKeyframes.length > 0 ? `
|
|
286
|
+
${decoratorKeyframes.join("\n")}` : ""}${decoratorComments ? `
|
|
287
|
+
${decoratorComments}` : ""}` : `${decoratorComments}
|
|
288
|
+
/* Canonical decorator CSS should be derived from theme decorator definitions when available. */`;
|
|
250
289
|
const decoratorBlock = `
|
|
251
290
|
@layer decorators {
|
|
252
|
-
|
|
253
|
-
/* See .decantr/context/section-*.md for intent, suggested properties, and usage guidance. */
|
|
291
|
+
${decoratorBody}
|
|
254
292
|
}
|
|
255
293
|
`;
|
|
256
294
|
lines.push(decoratorBlock);
|
|
@@ -598,6 +636,7 @@ function mapRegistryThemeToThemeData(theme) {
|
|
|
598
636
|
typography: theme.typography,
|
|
599
637
|
motion: theme.motion,
|
|
600
638
|
decorators: theme.decorators,
|
|
639
|
+
decorator_definitions: theme.decorator_definitions,
|
|
601
640
|
treatments: theme.treatments,
|
|
602
641
|
spatial: theme.spatial,
|
|
603
642
|
radius: theme.radius,
|
|
@@ -777,11 +816,15 @@ body {
|
|
|
777
816
|
transform: translateY(0);
|
|
778
817
|
}
|
|
779
818
|
|
|
780
|
-
img, picture, video, canvas
|
|
819
|
+
img, picture, video, canvas {
|
|
781
820
|
display: block;
|
|
782
821
|
max-width: 100%;
|
|
783
822
|
}
|
|
784
823
|
|
|
824
|
+
svg {
|
|
825
|
+
max-width: 100%;
|
|
826
|
+
}
|
|
827
|
+
|
|
785
828
|
input, button, textarea, select {
|
|
786
829
|
font: inherit;
|
|
787
830
|
color: inherit;
|
|
@@ -1009,10 +1052,14 @@ import './styles/global.css'; // Resets
|
|
|
1009
1052
|
### Runtime Rules
|
|
1010
1053
|
|
|
1011
1054
|
- Use the real \`@decantr/css\` runtime for atoms. If \`package.json\` does not already depend on \`@decantr/css\`, add it before building.
|
|
1055
|
+
- If \`package.json\`, app entry files, or router/runtime files are absent, create them explicitly for the declared target instead of assuming a hidden starter already exists.
|
|
1012
1056
|
- 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.
|
|
1013
1057
|
- Keep atoms in \`css(...)\`, treatments as semantic classes, and theme decorators as additive classes. Do not blur those roles together.
|
|
1058
|
+
- Do **not** use inline visual style values or component-scoped \`<style>\` tags as the primary styling path. Colors, spacing, borders, shadows, gradients, and transitions should come from atoms, treatments, decorators, or CSS variables. Inline styles are only acceptable for truly dynamic geometry that cannot be expressed through the contract.
|
|
1014
1059
|
- Use \`d-control\` as the default semantic treatment for inputs, selects, and textareas. Theme decorators such as \`carbon-input\` are additive and should only layer on when the section or theme contract explicitly calls for them.
|
|
1015
1060
|
- Use loading decorators such as \`carbon-skeleton\` as optional enhancement on top of a structurally correct loading state \u2014 they do not replace the need for a real loading/skeleton branch.
|
|
1061
|
+
- Shells own spacing, centering, and scroll containers. Pages should not duplicate shell responsibilities with extra full-height wrappers, max-width wrappers, or page-local padding unless the route contract explicitly requires it.
|
|
1062
|
+
- If a required decorator class is referenced in the generated contract but missing from generated CSS, report that contract gap instead of inventing a parallel visual system.
|
|
1016
1063
|
|
|
1017
1064
|
### Visual Treatments
|
|
1018
1065
|
|
|
@@ -1044,12 +1091,19 @@ Atoms + treatment + theme decorator:
|
|
|
1044
1091
|
|
|
1045
1092
|
\`\`\`tsx
|
|
1046
1093
|
// Responsive prefix \u2014 applies at breakpoint and above:
|
|
1047
|
-
css('_col
|
|
1094
|
+
css('_col _sm:row')
|
|
1048
1095
|
|
|
1049
1096
|
// Pseudo prefix:
|
|
1050
|
-
css('
|
|
1097
|
+
css('_bgprimary _h:bgprimary/80')
|
|
1051
1098
|
\`\`\`
|
|
1052
1099
|
|
|
1100
|
+
### Prefix and Arbitrary Value Syntax
|
|
1101
|
+
|
|
1102
|
+
- Responsive prefixes are part of the atom token itself: \`_sm:gc2\`, \`_md:flex\`, \`_lg:row\`.
|
|
1103
|
+
- Pseudo prefixes are also token-prefixed: \`_h:bgprimary/80\`, \`_f:borderprimary\`, \`_fv:shadowmd\`.
|
|
1104
|
+
- Arbitrary values use square brackets when the standard scale is not enough: \`_w[512px]\`, \`_h[100vh]\`, \`_p[clamp(1rem,3vw,2rem)]\`, \`_z[40]\`.
|
|
1105
|
+
- When you see bracket atoms in shell or page contracts, treat them as first-class Decantr syntax, not as an error or a cue to fall back to inline styles.
|
|
1106
|
+
|
|
1053
1107
|
### Atom Reference
|
|
1054
1108
|
|
|
1055
1109
|
#### Display
|
|
@@ -1226,7 +1280,7 @@ css('hover:_opacity80')
|
|
|
1226
1280
|
| \`_trans\` | \`transition:all 0.15s ease\` |
|
|
1227
1281
|
| \`_visible\`, \`_invisible\` | visibility |
|
|
1228
1282
|
|
|
1229
|
-
Responsive prefixes: \`_sm:\`, \`_md:\`, \`_lg:\` (e.g. \`
|
|
1283
|
+
Responsive prefixes: \`_sm:\`, \`_md:\`, \`_lg:\`, \`_xl:\` (e.g. \`_sm:gc2\`, \`_md:flex\`, \`_lg:row\`).
|
|
1230
1284
|
|
|
1231
1285
|
### Section Labels
|
|
1232
1286
|
|
|
@@ -1245,6 +1299,7 @@ If the theme provides motion tokens, apply the \`entrance-fade\` class to page c
|
|
|
1245
1299
|
### Navigation Shortcuts
|
|
1246
1300
|
|
|
1247
1301
|
If the essence defines hotkeys or command_palette, implement as keyboard event listeners (useEffect + keydown) \u2014 not as visible UI text.
|
|
1302
|
+
Missing declared navigation features are contract drift, not optional polish.
|
|
1248
1303
|
|
|
1249
1304
|
### Design Tokens
|
|
1250
1305
|
|
|
@@ -2141,7 +2196,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
2141
2196
|
spatialTokens,
|
|
2142
2197
|
themeData?.treatments,
|
|
2143
2198
|
themeData?.decorators,
|
|
2144
|
-
themeName
|
|
2199
|
+
themeName,
|
|
2200
|
+
themeData?.decorator_definitions
|
|
2145
2201
|
);
|
|
2146
2202
|
const personalityCSS = generatePersonalityCSS(personality || [], themeData || {});
|
|
2147
2203
|
treatmentCSS += personalityCSS;
|
|
@@ -3112,9 +3168,18 @@ function generateScaffoldContext(input) {
|
|
|
3112
3168
|
lines.push("");
|
|
3113
3169
|
if (navigation.command_palette) {
|
|
3114
3170
|
lines.push("- Command palette: enabled");
|
|
3171
|
+
lines.push("- Requirement: implement a real keyboard-triggered command palette, not just placeholder UI text.");
|
|
3115
3172
|
}
|
|
3116
3173
|
if (navigation.hotkeys && navigation.hotkeys.length > 0) {
|
|
3117
3174
|
lines.push(`- Hotkeys: ${navigation.hotkeys.length} configured`);
|
|
3175
|
+
for (const hotkey of navigation.hotkeys) {
|
|
3176
|
+
if (typeof hotkey === "object" && hotkey !== null && typeof hotkey.key === "string") {
|
|
3177
|
+
const target = [hotkey.label, hotkey.route || hotkey.action].filter(Boolean).join(" \u2014 ");
|
|
3178
|
+
lines.push(` - \`${hotkey.key}\`${target ? `: ${target}` : ""}`);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
lines.push("- Requirement: implement these bindings as real keyboard shortcuts, not as decorative text.");
|
|
3182
|
+
lines.push("- Presentation rule: do not append hotkey text to persistent nav labels, breadcrumbs, or page titles unless the shell or route contract explicitly requests visible shortcut hints.");
|
|
3118
3183
|
}
|
|
3119
3184
|
lines.push("");
|
|
3120
3185
|
}
|