@decantr/cli 2.7.0 → 2.8.1
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 +22 -11
- package/dist/bin.js +2 -1
- package/dist/{chunk-ICSLIYSX.js → chunk-FV6DGYD7.js} +49 -8
- package/dist/{chunk-ZYHR3BGT.js → chunk-RKZMHS2K.js} +836 -257
- package/dist/chunk-VE6N3XWG.js +78 -0
- package/dist/index.js +2 -1
- package/dist/{studio-MKLBUC3A.js → studio-G3YOU5YF.js} +2 -1
- package/dist/{workspace-KSFWRZEX.js → workspace-U7J3CJY3.js} +4 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npx @decantr/cli new my-app --blueprint=esports-hq
|
|
|
20
20
|
Use `decantr setup` when you are unsure which path applies. It detects whether the repo is empty, already attached, or a Brownfield app and recommends the next command.
|
|
21
21
|
Use `decantr new` for a greenfield workspace in a fresh directory. With a blueprint/archetype it uses the runnable adapter and Decantr CSS; without registry content it creates a contract-only workspace unless you explicitly pass `--adoption=decantr-css`.
|
|
22
22
|
Use `decantr adopt` when you already have an app and want Decantr governance without adopting a blueprint. Brownfield attach is proposal-driven: Decantr inventories the app, writes an observed essence proposal, and only applies it when you explicitly accept or merge it.
|
|
23
|
-
Use `decantr task` before asking an LLM to modify a route, and `decantr verify` after the edit. Use `decantr codify` when you want project-owned UI patterns such as
|
|
23
|
+
Use `decantr task` before asking an LLM to modify a route, and `decantr verify` after the edit. Use `decantr codify --from-audit` when you want project-owned UI patterns and local rules such as button/card/shell/theme standards to appear in future task context and verification.
|
|
24
24
|
Use `decantr init`, `decantr analyze`, `decantr check`, and `decantr health` as advanced primitives when you need direct control over one step.
|
|
25
25
|
|
|
26
26
|
Current starter adapter availability:
|
|
@@ -38,11 +38,11 @@ Explicit workflow/adoption flags:
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
decantr setup
|
|
41
|
-
decantr adopt --
|
|
42
|
-
decantr
|
|
43
|
-
decantr verify --brownfield
|
|
44
|
-
decantr codify
|
|
41
|
+
decantr adopt --yes
|
|
42
|
+
decantr codify --from-audit
|
|
45
43
|
decantr codify --accept
|
|
44
|
+
decantr task /feed "add saved recipe actions"
|
|
45
|
+
decantr verify --brownfield --local-patterns
|
|
46
46
|
decantr init --workflow=greenfield --adoption=contract-only
|
|
47
47
|
decantr analyze
|
|
48
48
|
decantr init --existing --accept-proposal
|
|
@@ -61,11 +61,18 @@ Adoption modes:
|
|
|
61
61
|
- `style-bridge` writes bridge tokens/files that map Decantr intent onto an existing style system without requiring `@decantr/css`.
|
|
62
62
|
- `decantr-css` writes the full Decantr CSS files and runtime guidance.
|
|
63
63
|
|
|
64
|
-
Monorepos store both `workspaceRoot` and `appRoot`.
|
|
64
|
+
Monorepos store both `workspaceRoot` and `appRoot`. Install Decantr at the workspace root if that is where dependencies are managed, but attach Decantr to an app root with `--project=<path>`.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pnpm add -D -w @decantr/cli
|
|
68
|
+
pnpm exec decantr setup
|
|
69
|
+
pnpm exec decantr workspace list
|
|
70
|
+
pnpm exec decantr adopt --project apps/web --yes
|
|
71
|
+
```
|
|
65
72
|
|
|
66
73
|
Assistant rule integration is preview-first: `--assistant-bridge=preview` writes `.decantr/context/assistant-bridge.md`, `decantr rules preview` prints the bridge, and `--assistant-bridge=apply` or `decantr rules apply` mutates supported rule files with idempotent marked blocks.
|
|
67
74
|
|
|
68
|
-
Brownfield analysis also writes `.decantr/doctrine-map.json`, a ranked source-precedence map across security/data, architecture, design-system, workflow/CI, feature/business, assistant-specific, stale, and unsafe-to-cite evidence. It also writes `.decantr/brownfield-intelligence.json`, `.decantr/theme-inventory.json`, and `.decantr/enrichment-backlog.md`. The proposal groups routes into observed semantic domains such as auth, RBAC, billing, reporting, facilities, settings, and public surfaces across Next App/Pages Router, React Router, Angular Router, SvelteKit, Vue Router, and Nuxt file routes. Existing styling systems such as Tailwind, Bootstrap, MUI, Chakra, plain CSS, and Decantr CSS are observed as evidence instead of replaced. Theme variants are observed in the theme inventory without changing Essence V4. `decantr verify --brownfield` uses the Brownfield guard layer to flag actionable missing doctrine coverage, unsafe context, missing assistant bridges, style drift, and unsafe defaults without treating current database migrations as stale docs.
|
|
75
|
+
Brownfield analysis also writes `.decantr/doctrine-map.json`, a ranked source-precedence map across security/data, architecture, design-system, workflow/CI, feature/business, assistant-specific, stale, and unsafe-to-cite evidence. It also writes `.decantr/brownfield-intelligence.json`, `.decantr/theme-inventory.json`, and `.decantr/enrichment-backlog.md`. The proposal groups routes into observed semantic domains such as auth, RBAC, billing, reporting, facilities, settings, and public surfaces across Next App/Pages Router, React Router, Angular Router, SvelteKit, Vue Router, and Nuxt file routes. Existing styling systems such as Tailwind, Bootstrap, MUI, Chakra, plain CSS, and Decantr CSS are observed as evidence instead of replaced. Theme variants are observed in the theme inventory without changing Essence V4. `decantr codify --from-audit` proposes `.decantr/local-patterns.proposal.json` and `.decantr/rules.proposal.json`; after review, `decantr codify --accept` promotes `.decantr/local-patterns.json` and `.decantr/rules.json`. `decantr verify --brownfield --local-patterns` uses the Brownfield guard layer plus accepted local law to flag actionable missing doctrine coverage, unsafe context, missing assistant bridges, style drift, raw local-rule violations, and unsafe defaults without treating current database migrations as stale docs.
|
|
69
76
|
|
|
70
77
|
## What It Does
|
|
71
78
|
|
|
@@ -86,10 +93,13 @@ Brownfield analysis also writes `.decantr/doctrine-map.json`, a ranked source-pr
|
|
|
86
93
|
```bash
|
|
87
94
|
decantr setup
|
|
88
95
|
decantr new my-app --blueprint=esports-hq
|
|
89
|
-
decantr adopt --
|
|
96
|
+
decantr adopt --yes
|
|
97
|
+
decantr adopt --project apps/web --yes
|
|
98
|
+
decantr codify --from-audit
|
|
99
|
+
decantr codify --accept
|
|
90
100
|
decantr task /feed "add saved recipe actions"
|
|
91
101
|
decantr verify --brownfield --local-patterns
|
|
92
|
-
decantr
|
|
102
|
+
decantr verify --base-url http://localhost:3000 --evidence
|
|
93
103
|
decantr init --existing --blueprint=esports-hq
|
|
94
104
|
decantr init --workflow=greenfield --adoption=contract-only
|
|
95
105
|
decantr rules preview
|
|
@@ -114,13 +124,14 @@ decantr showcase verification --json
|
|
|
114
124
|
|
|
115
125
|
## Project Health And Studio
|
|
116
126
|
|
|
117
|
-
`decantr verify` is the workflow command most users should run locally and in CI. It delegates to Project Health, can add Brownfield guard validation with `--brownfield`, requires an accepted local pattern pack with `--local-patterns`, supports workspace mode, and writes evidence to `.decantr/evidence/latest.json` by default when `--evidence` is used.
|
|
127
|
+
`decantr verify` is the workflow command most users should run locally and in CI. It delegates to Project Health, can add Brownfield guard validation with `--brownfield`, requires an accepted local pattern pack with `--local-patterns`, scans `.decantr/rules.json` when present, supports workspace mode, and writes evidence to `.decantr/evidence/latest.json` by default when `--evidence` is used.
|
|
118
128
|
|
|
119
129
|
`decantr health` remains the advanced project observability primitive. It composes the existing verifier audit, guard checks, brownfield route drift checks, runtime evidence, and execution-pack files into a `ProjectHealthReport` with a status, score, route summary, pack summary, findings, and AI-ready remediation prompts.
|
|
120
130
|
|
|
121
131
|
```bash
|
|
122
132
|
decantr verify
|
|
123
133
|
decantr verify --brownfield --local-patterns
|
|
134
|
+
decantr verify --brownfield --local-patterns --fail-on warn
|
|
124
135
|
decantr verify --base-url http://localhost:3000 --evidence
|
|
125
136
|
decantr verify --since-baseline
|
|
126
137
|
decantr verify init-ci --project apps/registry
|
|
@@ -149,7 +160,7 @@ Use `--json` for machines and schema validation, `--markdown` for CI summaries,
|
|
|
149
160
|
|
|
150
161
|
`decantr verify init-ci` installs `.github/workflows/decantr-health.yml` for GitHub Actions. The generated workflow installs project dependencies, writes JSON/markdown health artifacts, gates with the Project Health CI command, appends the markdown report to the GitHub step summary, and uploads both files as artifacts. Use `--force` to replace an existing workflow, `--fail-on warn` for stricter repositories, or `--cli-version <version|latest>` to pin the package used by CI. In monorepos, add `--project <path>` from the repository root; dependency install stays at the root while health runs inside the app contract and uploads artifacts from that project path. Use `--workspace` to generate an aggregate gate that runs `decantr workspace health` from the repository root and uploads `.decantr/workspace-health.json` plus `.decantr/workspace-health.md`.
|
|
151
162
|
|
|
152
|
-
`decantr workspace` is the monorepo reliability namespace.
|
|
163
|
+
`decantr workspace` is the monorepo reliability namespace. Before attach, `workspace list` shows app candidates. After attach, it also discovers Decantr projects from `.decantr/workspace.json` or by finding `decantr.essence.json` files. Workspace health runs projects with deterministic ordering, concurrency, per-project timeout, failure isolation, and aggregate JSON, and can limit a run to changed projects:
|
|
153
164
|
|
|
154
165
|
```bash
|
|
155
166
|
decantr workspace list
|
package/dist/bin.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listWorkspaceAppCandidates
|
|
3
|
+
} from "./chunk-VE6N3XWG.js";
|
|
1
4
|
import {
|
|
2
5
|
createProjectHealthReport
|
|
3
6
|
} from "./chunk-PAF4PBD3.js";
|
|
@@ -93,6 +96,14 @@ function listWorkspaceProjects(root = process.cwd()) {
|
|
|
93
96
|
}
|
|
94
97
|
return [...byPath.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
95
98
|
}
|
|
99
|
+
function listWorkspaceCandidates(root = process.cwd(), projects = listWorkspaceProjects(root)) {
|
|
100
|
+
const attached = new Set(projects.map((project) => project.path));
|
|
101
|
+
return listWorkspaceAppCandidates(root).map((path) => ({
|
|
102
|
+
path,
|
|
103
|
+
attached: attached.has(path),
|
|
104
|
+
suggestedAdoptCommand: `decantr adopt --project ${path} --yes`
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
96
107
|
function changedPaths(root, since) {
|
|
97
108
|
try {
|
|
98
109
|
const output = execFileSync("git", ["diff", "--name-only", since, "--"], {
|
|
@@ -100,7 +111,9 @@ function changedPaths(root, since) {
|
|
|
100
111
|
encoding: "utf-8",
|
|
101
112
|
stdio: ["ignore", "pipe", "ignore"]
|
|
102
113
|
});
|
|
103
|
-
return new Set(
|
|
114
|
+
return new Set(
|
|
115
|
+
output.split("\n").map((line) => line.trim()).filter(Boolean)
|
|
116
|
+
);
|
|
104
117
|
} catch {
|
|
105
118
|
return /* @__PURE__ */ new Set();
|
|
106
119
|
}
|
|
@@ -116,7 +129,10 @@ function projectChanged(project, changed) {
|
|
|
116
129
|
async function withTimeout(promise, timeoutMs, label) {
|
|
117
130
|
let timeout;
|
|
118
131
|
const timer = new Promise((_, reject) => {
|
|
119
|
-
timeout = setTimeout(
|
|
132
|
+
timeout = setTimeout(
|
|
133
|
+
() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),
|
|
134
|
+
timeoutMs
|
|
135
|
+
);
|
|
120
136
|
});
|
|
121
137
|
try {
|
|
122
138
|
return await Promise.race([promise, timer]);
|
|
@@ -265,9 +281,11 @@ function parseWorkspaceArgs(args) {
|
|
|
265
281
|
else if (arg.startsWith("--since=")) options.since = arg.split("=")[1];
|
|
266
282
|
else if (arg === "--output" && args[index + 1]) options.output = args[++index];
|
|
267
283
|
else if (arg.startsWith("--output=")) options.output = arg.split("=")[1];
|
|
268
|
-
else if (arg === "--fail-on" && args[index + 1])
|
|
284
|
+
else if (arg === "--fail-on" && args[index + 1])
|
|
285
|
+
options.failOn = parseHealthFailOn(args[++index]);
|
|
269
286
|
else if (arg.startsWith("--fail-on=")) options.failOn = parseHealthFailOn(arg.split("=")[1]);
|
|
270
|
-
else if (arg === "--concurrency" && args[index + 1])
|
|
287
|
+
else if (arg === "--concurrency" && args[index + 1])
|
|
288
|
+
options.concurrency = Number(args[++index]);
|
|
271
289
|
else if (arg.startsWith("--concurrency=")) options.concurrency = Number(arg.split("=")[1]);
|
|
272
290
|
else if (arg === "--timeout-ms" && args[index + 1]) options.timeoutMs = Number(args[++index]);
|
|
273
291
|
else if (arg.startsWith("--timeout-ms=")) options.timeoutMs = Number(arg.split("=")[1]);
|
|
@@ -278,15 +296,36 @@ async function cmdWorkspace(workspaceRoot = process.cwd(), args = ["workspace"])
|
|
|
278
296
|
const options = parseWorkspaceArgs(args);
|
|
279
297
|
if (options.subcommand === "list") {
|
|
280
298
|
const projects = listWorkspaceProjects(workspaceRoot);
|
|
281
|
-
const
|
|
299
|
+
const candidates = listWorkspaceCandidates(workspaceRoot, projects);
|
|
300
|
+
const unattachedCandidates = candidates.filter((candidate) => !candidate.attached);
|
|
301
|
+
const payload2 = `${JSON.stringify({ projects, candidates }, null, 2)}
|
|
282
302
|
`;
|
|
283
303
|
if (options.json) {
|
|
284
304
|
process.stdout.write(payload2);
|
|
285
305
|
return;
|
|
286
306
|
}
|
|
287
307
|
console.log(`${BOLD}Decantr workspace projects${RESET}`);
|
|
288
|
-
|
|
289
|
-
|
|
308
|
+
console.log("");
|
|
309
|
+
console.log("Attached Decantr projects:");
|
|
310
|
+
if (projects.length === 0) {
|
|
311
|
+
console.log(` ${DIM}(none yet)${RESET}`);
|
|
312
|
+
} else {
|
|
313
|
+
for (const project of projects) {
|
|
314
|
+
console.log(` ${project.path} ${DIM}${project.source}${RESET}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (candidates.length > 0) {
|
|
318
|
+
console.log("");
|
|
319
|
+
console.log("App candidates:");
|
|
320
|
+
for (const candidate of candidates) {
|
|
321
|
+
const status = candidate.attached ? `${GREEN}attached${RESET}` : `${YELLOW}unattached${RESET}`;
|
|
322
|
+
console.log(` ${candidate.path} ${DIM}${status}${RESET}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (unattachedCandidates.length > 0) {
|
|
326
|
+
console.log("");
|
|
327
|
+
console.log("Start by attaching one app:");
|
|
328
|
+
console.log(` ${unattachedCandidates[0].suggestedAdoptCommand}`);
|
|
290
329
|
}
|
|
291
330
|
return;
|
|
292
331
|
}
|
|
@@ -296,7 +335,8 @@ async function cmdWorkspace(workspaceRoot = process.cwd(), args = ["workspace"])
|
|
|
296
335
|
if (options.output) {
|
|
297
336
|
mkdirSync(dirname(resolve(workspaceRoot, options.output)), { recursive: true });
|
|
298
337
|
writeFileSync(resolve(workspaceRoot, options.output), payload, "utf-8");
|
|
299
|
-
if (!options.ci)
|
|
338
|
+
if (!options.ci)
|
|
339
|
+
console.log(`${GREEN}Wrote Decantr workspace health:${RESET} ${options.output}`);
|
|
300
340
|
} else {
|
|
301
341
|
process.stdout.write(payload);
|
|
302
342
|
}
|
|
@@ -307,6 +347,7 @@ async function cmdWorkspace(workspaceRoot = process.cwd(), args = ["workspace"])
|
|
|
307
347
|
|
|
308
348
|
export {
|
|
309
349
|
listWorkspaceProjects,
|
|
350
|
+
listWorkspaceCandidates,
|
|
310
351
|
createWorkspaceHealthReport,
|
|
311
352
|
formatWorkspaceHealthText,
|
|
312
353
|
formatWorkspaceHealthMarkdown,
|