@decantr/cli 2.9.5 → 2.9.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/README.md +5 -1
- package/dist/bin.js +5 -5
- package/dist/{chunk-WONPNSSI.js → chunk-4SZ4SEKT.js} +24 -5
- package/dist/{chunk-3KJ46XY7.js → chunk-66L74ZNJ.js} +163 -94
- package/dist/{chunk-RXF7ZYGK.js → chunk-IQZCIMQJ.js} +28 -1
- package/dist/{chunk-VCUFZB45.js → chunk-QDMXZSVK.js} +1 -1
- package/dist/{chunk-FACL3NXU.js → chunk-WPP3JEMC.js} +1 -1
- package/dist/{heal-ZQHEHBUJ.js → heal-2UCSPRTK.js} +1 -1
- package/dist/{health-R7AV5G4V.js → health-VAYRQVTF.js} +2 -2
- package/dist/index.js +5 -5
- package/dist/{studio-2734P63C.js → studio-WPETOZRW.js} +3 -3
- package/dist/{upgrade-VON7Y3LG.js → upgrade-7ZYWR2GH.js} +1 -1
- package/dist/{workspace-DRHTQ2NG.js → workspace-PBO3BJRL.js} +3 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -136,12 +136,16 @@ decantr list patterns
|
|
|
136
136
|
decantr showcase verification --json
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
`suggest --from-code` uses the selected app's source file to rank both hosted registry patterns and accepted project-owned local patterns, so Brownfield button/card/form law can surface from real code instead of just the text query.
|
|
140
|
+
|
|
139
141
|
## Project Health And Studio
|
|
140
142
|
|
|
141
143
|
`decantr verify` is the workflow command most users should run locally after edits. 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.
|
|
142
144
|
|
|
143
145
|
`decantr doctor` explains project/workspace state, adoption mode, generated artifacts, local law, visual evidence, design authority signals, CI wiring, and the next command to run. It is the command to reach for when an app is in a monorepo, has stale Decantr files, or someone is not sure what Decantr expects next.
|
|
144
146
|
|
|
147
|
+
`decantr setup` is non-mutating orientation. In an attached Brownfield app it reflects whether local law is already accepted, so the recommended verify command includes `--local-patterns` only when the project has that layer.
|
|
148
|
+
|
|
145
149
|
`decantr ci` is the blessed non-mutating automation gate. It runs the Project Health surface with adoption-mode-aware local law checks and emits a schema-backed CI report. `decantr ci init` writes root GitHub workflows or portable generic snippets using the detected package manager and pinned local CLI command instead of `@latest`; if the root manifest has not pinned Decantr yet, it prints the exact install command first.
|
|
146
150
|
|
|
147
151
|
`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.
|
|
@@ -189,7 +193,7 @@ decantr workspace health --json --output .decantr/workspace-health.json
|
|
|
189
193
|
decantr verify --workspace --changed --since origin/main
|
|
190
194
|
```
|
|
191
195
|
|
|
192
|
-
In observed Brownfield projects, common section shorthands are accepted for page additions when they resolve unambiguously. For example, `decantr add page app/settings --route /settings --project apps/web`
|
|
196
|
+
In observed Brownfield projects, common section shorthands are accepted for page and feature additions when they resolve unambiguously. For example, `decantr add page app/settings --route /settings --project apps/web` and `decantr add feature saved-recipes --section app --project apps/web` resolve `app` to the single primary section, such as `observed-primary`, so docs and LLM prompts do not have to guess generated section IDs first.
|
|
193
197
|
|
|
194
198
|
`decantr studio` starts a local-only dashboard powered by the same report. It uses Node built-ins only and serves `GET /`, `GET /api/health`, and `POST /api/refresh`.
|
|
195
199
|
|
package/dist/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
3
|
-
import "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-66L74ZNJ.js";
|
|
3
|
+
import "./chunk-IQZCIMQJ.js";
|
|
4
|
+
import "./chunk-QDMXZSVK.js";
|
|
5
|
+
import "./chunk-WPP3JEMC.js";
|
|
6
|
+
import "./chunk-4SZ4SEKT.js";
|
|
@@ -1971,6 +1971,16 @@ var YELLOW = "\x1B[33m";
|
|
|
1971
1971
|
var CYAN = "\x1B[36m";
|
|
1972
1972
|
var RESET = "\x1B[0m";
|
|
1973
1973
|
var DIM = "\x1B[2m";
|
|
1974
|
+
function isContractOnlyProject(projectRoot) {
|
|
1975
|
+
const metadataPath = join10(projectRoot, ".decantr", "project.json");
|
|
1976
|
+
if (!existsSync10(metadataPath)) return false;
|
|
1977
|
+
try {
|
|
1978
|
+
const metadata = JSON.parse(readFileSync10(metadataPath, "utf-8"));
|
|
1979
|
+
return metadata.initialized?.adoptionMode === "contract-only";
|
|
1980
|
+
} catch {
|
|
1981
|
+
return false;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1974
1984
|
function collectCheckIssues(projectRoot = process.cwd(), options = {}) {
|
|
1975
1985
|
const essencePath = join10(projectRoot, "decantr.essence.json");
|
|
1976
1986
|
if (!existsSync10(essencePath)) {
|
|
@@ -2000,9 +2010,11 @@ function collectCheckIssues(projectRoot = process.cwd(), options = {}) {
|
|
|
2000
2010
|
return { essence, issues, missingEssence: false };
|
|
2001
2011
|
}
|
|
2002
2012
|
let interactionIssues = [];
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2013
|
+
if (!isContractOnlyProject(projectRoot)) {
|
|
2014
|
+
try {
|
|
2015
|
+
interactionIssues = scanProjectInteractions(projectRoot);
|
|
2016
|
+
} catch {
|
|
2017
|
+
}
|
|
2006
2018
|
}
|
|
2007
2019
|
try {
|
|
2008
2020
|
const guardContext = buildGuardRegistryContext(projectRoot);
|
|
@@ -2066,9 +2078,16 @@ async function cmdHeal(projectRoot = process.cwd(), options = {}) {
|
|
|
2066
2078
|
console.log(` ${DIM}Suggestion: ${issue.suggestion}${RESET}`);
|
|
2067
2079
|
}
|
|
2068
2080
|
}
|
|
2069
|
-
console.log(`
|
|
2070
|
-
${YELLOW}Manual fixes required. Review the issues above.${RESET}`);
|
|
2071
2081
|
const hasError = issues.some((i) => i.type === "error");
|
|
2082
|
+
if (hasError) {
|
|
2083
|
+
console.log(`
|
|
2084
|
+
${YELLOW}Manual fixes required. Review the issues above.${RESET}`);
|
|
2085
|
+
} else {
|
|
2086
|
+
console.log(
|
|
2087
|
+
`
|
|
2088
|
+
${YELLOW}Warnings found. Review the issues above or set stricter gates in CI.${RESET}`
|
|
2089
|
+
);
|
|
2090
|
+
}
|
|
2072
2091
|
if (hasError) {
|
|
2073
2092
|
process.exitCode = 1;
|
|
2074
2093
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
scaffoldProject,
|
|
15
15
|
syncRegistry,
|
|
16
16
|
writeExecutionPackBundleArtifacts
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IQZCIMQJ.js";
|
|
18
18
|
import {
|
|
19
19
|
createWorkspaceHealthReport,
|
|
20
20
|
formatWorkspaceHealthMarkdown,
|
|
@@ -22,14 +22,14 @@ import {
|
|
|
22
22
|
listWorkspaceCandidates,
|
|
23
23
|
listWorkspaceProjects,
|
|
24
24
|
shouldFailWorkspaceHealth
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-QDMXZSVK.js";
|
|
26
26
|
import {
|
|
27
27
|
createProjectHealthReport,
|
|
28
28
|
formatProjectHealthMarkdown,
|
|
29
29
|
formatProjectHealthText,
|
|
30
30
|
resolveWorkspaceInfo,
|
|
31
31
|
shouldFailHealth
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-WPP3JEMC.js";
|
|
33
33
|
import {
|
|
34
34
|
buildGuardRegistryContext,
|
|
35
35
|
createDoctrineMap,
|
|
@@ -46,11 +46,11 @@ import {
|
|
|
46
46
|
sendCliCommandTelemetry,
|
|
47
47
|
sendNewProjectCompletedTelemetry,
|
|
48
48
|
writeDoctrineMap
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-4SZ4SEKT.js";
|
|
50
50
|
|
|
51
51
|
// src/index.ts
|
|
52
52
|
import { existsSync as existsSync29, mkdirSync as mkdirSync16, readdirSync as readdirSync9, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "fs";
|
|
53
|
-
import { basename as basename3, dirname as
|
|
53
|
+
import { basename as basename3, dirname as dirname6, isAbsolute as isAbsolute3, join as join31, relative as relative7, resolve as resolve4 } from "path";
|
|
54
54
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
55
55
|
import { evaluateGuard, isV4 as isV49, validateEssence as validateEssence2 } from "@decantr/essence-spec";
|
|
56
56
|
import {
|
|
@@ -1940,16 +1940,23 @@ async function cmdAddFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
1940
1940
|
sectionId = readFlagValue(args, "section");
|
|
1941
1941
|
if (sectionId) {
|
|
1942
1942
|
const sections = essence.blueprint.sections;
|
|
1943
|
-
const
|
|
1944
|
-
if (!
|
|
1945
|
-
|
|
1946
|
-
console.error(`${DIM}Available sections: ${sections.map((s) => s.id).join(", ")}${RESET}`);
|
|
1943
|
+
const resolved = resolveSectionForPage(sections, sectionId);
|
|
1944
|
+
if (!resolved) {
|
|
1945
|
+
printSectionNotFound(sectionId, sections);
|
|
1947
1946
|
process.exitCode = 1;
|
|
1948
1947
|
return;
|
|
1949
1948
|
}
|
|
1949
|
+
const { section } = resolved;
|
|
1950
|
+
const resolvedSectionId = section.id;
|
|
1950
1951
|
if (!section.features.includes(feature)) {
|
|
1951
1952
|
section.features.push(feature);
|
|
1952
1953
|
}
|
|
1954
|
+
if (resolved.resolvedFromAlias) {
|
|
1955
|
+
console.log(
|
|
1956
|
+
`${YELLOW}Resolved section alias "${sectionId}" to "${resolvedSectionId}".${RESET}`
|
|
1957
|
+
);
|
|
1958
|
+
}
|
|
1959
|
+
sectionId = resolvedSectionId;
|
|
1953
1960
|
}
|
|
1954
1961
|
if (!essence.blueprint.features.includes(feature)) {
|
|
1955
1962
|
essence.blueprint.features.push(feature);
|
|
@@ -2747,7 +2754,7 @@ function writeBrownfieldIntelligenceArtifacts(input) {
|
|
|
2747
2754
|
|
|
2748
2755
|
// src/detect.ts
|
|
2749
2756
|
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
2750
|
-
import { join as join12 } from "path";
|
|
2757
|
+
import { dirname as dirname2, join as join12 } from "path";
|
|
2751
2758
|
var RULE_FILES = [
|
|
2752
2759
|
"CLAUDE.md",
|
|
2753
2760
|
".claude/rules",
|
|
@@ -2759,6 +2766,34 @@ var RULE_FILES = [
|
|
|
2759
2766
|
".github/copilot-instructions.md",
|
|
2760
2767
|
".windsurfrules"
|
|
2761
2768
|
];
|
|
2769
|
+
function readPackageJson(dir) {
|
|
2770
|
+
const path = join12(dir, "package.json");
|
|
2771
|
+
if (!existsSync10(path)) return null;
|
|
2772
|
+
try {
|
|
2773
|
+
return JSON.parse(readFileSync9(path, "utf-8"));
|
|
2774
|
+
} catch {
|
|
2775
|
+
return null;
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
function packageManagerFromName(name) {
|
|
2779
|
+
if (name === "pnpm" || name === "yarn" || name === "bun" || name === "npm") return name;
|
|
2780
|
+
return "unknown";
|
|
2781
|
+
}
|
|
2782
|
+
function detectPackageManager(projectRoot) {
|
|
2783
|
+
let current = projectRoot;
|
|
2784
|
+
while (true) {
|
|
2785
|
+
const pkg = readPackageJson(current);
|
|
2786
|
+
const declared = packageManagerFromName(pkg?.packageManager?.split("@")[0]);
|
|
2787
|
+
if (declared !== "unknown") return declared;
|
|
2788
|
+
if (existsSync10(join12(current, "pnpm-lock.yaml"))) return "pnpm";
|
|
2789
|
+
if (existsSync10(join12(current, "yarn.lock"))) return "yarn";
|
|
2790
|
+
if (existsSync10(join12(current, "bun.lockb"))) return "bun";
|
|
2791
|
+
if (existsSync10(join12(current, "package-lock.json"))) return "npm";
|
|
2792
|
+
const parent = dirname2(current);
|
|
2793
|
+
if (parent === current) return "unknown";
|
|
2794
|
+
current = parent;
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2762
2797
|
function detectProject(projectRoot = process.cwd()) {
|
|
2763
2798
|
const result = {
|
|
2764
2799
|
framework: "unknown",
|
|
@@ -2775,15 +2810,7 @@ function detectProject(projectRoot = process.cwd()) {
|
|
|
2775
2810
|
result.existingRuleFiles.push(ruleFile);
|
|
2776
2811
|
}
|
|
2777
2812
|
}
|
|
2778
|
-
|
|
2779
|
-
result.packageManager = "pnpm";
|
|
2780
|
-
} else if (existsSync10(join12(projectRoot, "yarn.lock"))) {
|
|
2781
|
-
result.packageManager = "yarn";
|
|
2782
|
-
} else if (existsSync10(join12(projectRoot, "bun.lockb"))) {
|
|
2783
|
-
result.packageManager = "bun";
|
|
2784
|
-
} else if (existsSync10(join12(projectRoot, "package-lock.json"))) {
|
|
2785
|
-
result.packageManager = "npm";
|
|
2786
|
-
}
|
|
2813
|
+
result.packageManager = detectPackageManager(projectRoot);
|
|
2787
2814
|
result.hasTypeScript = existsSync10(join12(projectRoot, "tsconfig.json"));
|
|
2788
2815
|
result.hasTailwind = existsSync10(join12(projectRoot, "tailwind.config.js")) || existsSync10(join12(projectRoot, "tailwind.config.ts")) || existsSync10(join12(projectRoot, "tailwind.config.mjs")) || existsSync10(join12(projectRoot, "tailwind.config.cjs"));
|
|
2789
2816
|
if (existsSync10(join12(projectRoot, "next.config.js")) || existsSync10(join12(projectRoot, "next.config.ts")) || existsSync10(join12(projectRoot, "next.config.mjs"))) {
|
|
@@ -3188,7 +3215,7 @@ ${YELLOW2}Next step:${RESET2} Review ${BOLD}${reportDisplayPath}${RESET2}, then
|
|
|
3188
3215
|
|
|
3189
3216
|
// src/commands/ci.ts
|
|
3190
3217
|
import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
3191
|
-
import { dirname as
|
|
3218
|
+
import { dirname as dirname3, join as join16, relative as relative4, resolve } from "path";
|
|
3192
3219
|
|
|
3193
3220
|
// src/local-law.ts
|
|
3194
3221
|
import { execFileSync } from "child_process";
|
|
@@ -3725,7 +3752,7 @@ function parseProvider(value) {
|
|
|
3725
3752
|
if (value === "github" || value === "generic") return value;
|
|
3726
3753
|
throw new Error("Invalid --provider value. Use github or generic.");
|
|
3727
3754
|
}
|
|
3728
|
-
function
|
|
3755
|
+
function detectPackageManager2(root) {
|
|
3729
3756
|
const pkg = readJson(join16(root, "package.json"));
|
|
3730
3757
|
const declared = pkg?.packageManager?.split("@")[0];
|
|
3731
3758
|
if (declared === "pnpm" || declared === "npm" || declared === "yarn" || declared === "bun") {
|
|
@@ -3794,7 +3821,7 @@ function projectSlug(projectPath) {
|
|
|
3794
3821
|
}
|
|
3795
3822
|
function writeOutput(root, path, content) {
|
|
3796
3823
|
const absolute = resolve(root, path);
|
|
3797
|
-
mkdirSync9(
|
|
3824
|
+
mkdirSync9(dirname3(absolute), { recursive: true });
|
|
3798
3825
|
writeFileSync10(absolute, content, "utf-8");
|
|
3799
3826
|
}
|
|
3800
3827
|
function summarizeLocalLaw(projectRoot) {
|
|
@@ -3924,7 +3951,7 @@ function writeCiInit(root, options) {
|
|
|
3924
3951
|
}
|
|
3925
3952
|
const outputRoot = workspaceInfo.workspaceRoot;
|
|
3926
3953
|
const projectPath = options.project ?? (options.workspace || workspaceInfo.appRoot === workspaceInfo.workspaceRoot ? void 0 : relative4(workspaceInfo.workspaceRoot, workspaceInfo.appRoot).replace(/\\/g, "/"));
|
|
3927
|
-
const packageManager =
|
|
3954
|
+
const packageManager = detectPackageManager2(outputRoot);
|
|
3928
3955
|
const command = decantrCommand(packageManager);
|
|
3929
3956
|
const failOn = options.failOn ?? "error";
|
|
3930
3957
|
const provider = options.provider ?? "github";
|
|
@@ -4288,7 +4315,7 @@ function cmdCreate(type, name, projectRoot = process.cwd()) {
|
|
|
4288
4315
|
|
|
4289
4316
|
// src/commands/doctor.ts
|
|
4290
4317
|
import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
|
|
4291
|
-
import { dirname as
|
|
4318
|
+
import { dirname as dirname4, join as join18, relative as relative5 } from "path";
|
|
4292
4319
|
import { fileURLToPath } from "url";
|
|
4293
4320
|
import { isV4 as isV44 } from "@decantr/essence-spec";
|
|
4294
4321
|
import { collectMissingPackManifestFiles } from "@decantr/verifier";
|
|
@@ -4312,16 +4339,16 @@ function isContractOnlyProject(projectRoot) {
|
|
|
4312
4339
|
return projectJson?.initialized?.adoptionMode === "contract-only";
|
|
4313
4340
|
}
|
|
4314
4341
|
function readCliPackageVersion() {
|
|
4315
|
-
const packagePath = join18(
|
|
4316
|
-
const srcPackagePath = join18(
|
|
4342
|
+
const packagePath = join18(dirname4(fileURLToPath(import.meta.url)), "..", "..", "package.json");
|
|
4343
|
+
const srcPackagePath = join18(dirname4(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
4317
4344
|
const pkg = readJson2(packagePath) ?? readJson2(srcPackagePath);
|
|
4318
4345
|
return pkg?.version ?? "unknown";
|
|
4319
4346
|
}
|
|
4320
|
-
function
|
|
4347
|
+
function readPackageJson2(dir) {
|
|
4321
4348
|
return readJson2(join18(dir, "package.json"));
|
|
4322
4349
|
}
|
|
4323
|
-
function
|
|
4324
|
-
const pkg =
|
|
4350
|
+
function detectPackageManager3(root) {
|
|
4351
|
+
const pkg = readPackageJson2(root);
|
|
4325
4352
|
const declared = pkg?.packageManager?.split("@")[0];
|
|
4326
4353
|
if (declared === "pnpm" || declared === "npm" || declared === "yarn" || declared === "bun") {
|
|
4327
4354
|
return declared;
|
|
@@ -4333,11 +4360,11 @@ function detectPackageManager2(root) {
|
|
|
4333
4360
|
return "unknown";
|
|
4334
4361
|
}
|
|
4335
4362
|
function localCliDependency(root) {
|
|
4336
|
-
const pkg =
|
|
4363
|
+
const pkg = readPackageJson2(root);
|
|
4337
4364
|
return pkg?.devDependencies?.["@decantr/cli"] ?? pkg?.dependencies?.["@decantr/cli"] ?? null;
|
|
4338
4365
|
}
|
|
4339
4366
|
function hasWorkspaceMarker2(root) {
|
|
4340
|
-
const pkg =
|
|
4367
|
+
const pkg = readPackageJson2(root);
|
|
4341
4368
|
return Boolean(
|
|
4342
4369
|
existsSync16(join18(root, "pnpm-workspace.yaml")) || existsSync16(join18(root, "turbo.json")) || existsSync16(join18(root, "nx.json")) || pkg?.workspaces
|
|
4343
4370
|
);
|
|
@@ -4368,7 +4395,7 @@ function hasAnyFile(dir, names) {
|
|
|
4368
4395
|
return null;
|
|
4369
4396
|
}
|
|
4370
4397
|
function packageHasDependency(dir, names) {
|
|
4371
|
-
const pkg =
|
|
4398
|
+
const pkg = readPackageJson2(dir);
|
|
4372
4399
|
const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
4373
4400
|
return names.some((name) => Boolean(deps[name]));
|
|
4374
4401
|
}
|
|
@@ -4448,7 +4475,7 @@ function buildDoctorReport(root, args) {
|
|
|
4448
4475
|
const appRoot = workspaceMode ? workspaceRoot : workspaceInfo.appRoot;
|
|
4449
4476
|
const projectMissing = Boolean(projectArg && !existsSync16(appRoot));
|
|
4450
4477
|
const projectPath = appRoot === workspaceRoot ? null : rel(workspaceRoot, appRoot);
|
|
4451
|
-
const packageManager =
|
|
4478
|
+
const packageManager = detectPackageManager3(workspaceRoot);
|
|
4452
4479
|
const cliDependency = localCliDependency(workspaceRoot);
|
|
4453
4480
|
const detected = detectProject(appRoot);
|
|
4454
4481
|
const projectJson = readJson2(join18(appRoot, ".decantr", "project.json"));
|
|
@@ -4716,7 +4743,7 @@ async function cmdDoctor(args = ["doctor"], root = process.cwd()) {
|
|
|
4716
4743
|
|
|
4717
4744
|
// src/commands/export.ts
|
|
4718
4745
|
import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
|
|
4719
|
-
import { dirname as
|
|
4746
|
+
import { dirname as dirname5, isAbsolute, join as join19 } from "path";
|
|
4720
4747
|
var GREEN5 = "\x1B[32m";
|
|
4721
4748
|
var RED4 = "\x1B[31m";
|
|
4722
4749
|
var DIM5 = "\x1B[2m";
|
|
@@ -4970,7 +4997,7 @@ async function cmdExport(target, projectRoot, options = {}) {
|
|
|
4970
4997
|
}
|
|
4971
4998
|
}
|
|
4972
4999
|
function ensureDir(filePath) {
|
|
4973
|
-
const dir =
|
|
5000
|
+
const dir = dirname5(filePath);
|
|
4974
5001
|
if (!existsSync17(dir)) {
|
|
4975
5002
|
mkdirSync11(dir, { recursive: true });
|
|
4976
5003
|
}
|
|
@@ -5883,7 +5910,7 @@ async function cmdNewProject(projectName, options) {
|
|
|
5883
5910
|
)
|
|
5884
5911
|
);
|
|
5885
5912
|
}
|
|
5886
|
-
const packageManager =
|
|
5913
|
+
const packageManager = detectPackageManager4();
|
|
5887
5914
|
if (shouldBootstrapRuntime) {
|
|
5888
5915
|
console.log(heading("Installing dependencies..."));
|
|
5889
5916
|
try {
|
|
@@ -5959,7 +5986,7 @@ ${YELLOW6}Decantr init encountered issues. Run \`decantr init\` manually inside
|
|
|
5959
5986
|
});
|
|
5960
5987
|
}
|
|
5961
5988
|
}
|
|
5962
|
-
function
|
|
5989
|
+
function detectPackageManager4() {
|
|
5963
5990
|
if (existsSync21(join23(process.cwd(), "pnpm-lock.yaml")) || existsSync21(join23(process.cwd(), "pnpm-workspace.yaml"))) {
|
|
5964
5991
|
return "pnpm";
|
|
5965
5992
|
}
|
|
@@ -6358,6 +6385,7 @@ import { join as join27 } from "path";
|
|
|
6358
6385
|
import { isV4 as isV47 } from "@decantr/essence-spec";
|
|
6359
6386
|
var GREEN11 = "\x1B[32m";
|
|
6360
6387
|
var RED9 = "\x1B[31m";
|
|
6388
|
+
var YELLOW8 = "\x1B[33m";
|
|
6361
6389
|
var DIM11 = "\x1B[2m";
|
|
6362
6390
|
var RESET11 = "\x1B[0m";
|
|
6363
6391
|
function readV4Essence2(projectRoot) {
|
|
@@ -6396,6 +6424,27 @@ function readFlagValue2(args, name) {
|
|
|
6396
6424
|
}
|
|
6397
6425
|
return void 0;
|
|
6398
6426
|
}
|
|
6427
|
+
function resolveSectionAlias(sections, requestedSectionId) {
|
|
6428
|
+
const exact = sections.find((section) => section.id === requestedSectionId);
|
|
6429
|
+
if (exact) return { section: exact, resolvedFromAlias: false };
|
|
6430
|
+
const roleByAlias = {
|
|
6431
|
+
app: "primary",
|
|
6432
|
+
main: "primary",
|
|
6433
|
+
primary: "primary",
|
|
6434
|
+
public: "public",
|
|
6435
|
+
marketing: "public",
|
|
6436
|
+
auth: "gateway",
|
|
6437
|
+
gateway: "gateway",
|
|
6438
|
+
auxiliary: "auxiliary"
|
|
6439
|
+
};
|
|
6440
|
+
const desiredRole = roleByAlias[requestedSectionId.toLowerCase()];
|
|
6441
|
+
if (!desiredRole) return null;
|
|
6442
|
+
const roleMatches = sections.filter((section) => section.role === desiredRole);
|
|
6443
|
+
if (roleMatches.length === 1) return { section: roleMatches[0], resolvedFromAlias: true };
|
|
6444
|
+
if (roleMatches.length > 1) return null;
|
|
6445
|
+
const observedMatch = sections.find((section) => section.id === `observed-${desiredRole}`);
|
|
6446
|
+
return observedMatch ? { section: observedMatch, resolvedFromAlias: true } : null;
|
|
6447
|
+
}
|
|
6399
6448
|
function recomputeGlobalFeatures(essence) {
|
|
6400
6449
|
const all = /* @__PURE__ */ new Set();
|
|
6401
6450
|
for (const section of essence.blueprint.sections || []) {
|
|
@@ -6460,24 +6509,31 @@ async function cmdRemovePage(path, args, projectRoot = process.cwd()) {
|
|
|
6460
6509
|
if (!loaded) return;
|
|
6461
6510
|
const { essence, essencePath } = loaded;
|
|
6462
6511
|
const sections = essence.blueprint.sections;
|
|
6463
|
-
const
|
|
6464
|
-
if (!
|
|
6512
|
+
const resolved = resolveSectionAlias(sections, sectionId);
|
|
6513
|
+
if (!resolved) {
|
|
6465
6514
|
console.error(`${RED9}Section "${sectionId}" not found.${RESET11}`);
|
|
6466
6515
|
console.error(`${DIM11}Available sections: ${sections.map((s) => s.id).join(", ")}${RESET11}`);
|
|
6467
6516
|
process.exitCode = 1;
|
|
6468
6517
|
return;
|
|
6469
6518
|
}
|
|
6519
|
+
const { section } = resolved;
|
|
6520
|
+
const resolvedSectionId = section.id;
|
|
6470
6521
|
const pageIdx = section.pages.findIndex((p) => p.id === pageId);
|
|
6471
6522
|
if (pageIdx === -1) {
|
|
6472
|
-
console.error(`${RED9}Page "${pageId}" not found in section "${
|
|
6523
|
+
console.error(`${RED9}Page "${pageId}" not found in section "${resolvedSectionId}".${RESET11}`);
|
|
6473
6524
|
console.error(`${DIM11}Available pages: ${section.pages.map((p) => p.id).join(", ")}${RESET11}`);
|
|
6474
6525
|
process.exitCode = 1;
|
|
6475
6526
|
return;
|
|
6476
6527
|
}
|
|
6477
6528
|
section.pages.splice(pageIdx, 1);
|
|
6478
|
-
removeRoutes(essence,
|
|
6529
|
+
removeRoutes(essence, resolvedSectionId, pageId);
|
|
6479
6530
|
writeEssence2(essencePath, essence);
|
|
6480
|
-
|
|
6531
|
+
if (resolved.resolvedFromAlias) {
|
|
6532
|
+
console.log(
|
|
6533
|
+
`${YELLOW8}Resolved section alias "${sectionId}" to "${resolvedSectionId}".${RESET11}`
|
|
6534
|
+
);
|
|
6535
|
+
}
|
|
6536
|
+
console.log(`${GREEN11}Removed page "${pageId}" from section "${resolvedSectionId}".${RESET11}`);
|
|
6481
6537
|
const registryClient = new RegistryClient({
|
|
6482
6538
|
cacheDir: join27(projectRoot, ".decantr", "cache")
|
|
6483
6539
|
});
|
|
@@ -6497,13 +6553,18 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
6497
6553
|
sectionId = readFlagValue2(args, "section");
|
|
6498
6554
|
if (sectionId) {
|
|
6499
6555
|
const sections = essence.blueprint.sections;
|
|
6500
|
-
const
|
|
6501
|
-
if (!
|
|
6556
|
+
const resolved = resolveSectionAlias(sections, sectionId);
|
|
6557
|
+
if (!resolved) {
|
|
6502
6558
|
console.error(`${RED9}Section "${sectionId}" not found.${RESET11}`);
|
|
6503
6559
|
console.error(`${DIM11}Available sections: ${sections.map((s) => s.id).join(", ")}${RESET11}`);
|
|
6504
6560
|
process.exitCode = 1;
|
|
6505
6561
|
return;
|
|
6506
6562
|
}
|
|
6563
|
+
const { section } = resolved;
|
|
6564
|
+
if (resolved.resolvedFromAlias) {
|
|
6565
|
+
console.log(`${YELLOW8}Resolved section alias "${sectionId}" to "${section.id}".${RESET11}`);
|
|
6566
|
+
}
|
|
6567
|
+
sectionId = section.id;
|
|
6507
6568
|
const fIdx = section.features.indexOf(feature);
|
|
6508
6569
|
if (fIdx !== -1) {
|
|
6509
6570
|
section.features.splice(fIdx, 1);
|
|
@@ -6528,7 +6589,7 @@ import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSy
|
|
|
6528
6589
|
import { join as join28 } from "path";
|
|
6529
6590
|
var GREEN12 = "\x1B[32m";
|
|
6530
6591
|
var RED10 = "\x1B[31m";
|
|
6531
|
-
var
|
|
6592
|
+
var YELLOW9 = "\x1B[33m";
|
|
6532
6593
|
var RESET12 = "\x1B[0m";
|
|
6533
6594
|
var DIM12 = "\x1B[2m";
|
|
6534
6595
|
var BOLD6 = "\x1B[1m";
|
|
@@ -6569,7 +6630,7 @@ ${BOLD6}Unresolved Drift Entries (${unresolved.length})${RESET12}
|
|
|
6569
6630
|
`);
|
|
6570
6631
|
for (let i = 0; i < unresolved.length; i++) {
|
|
6571
6632
|
const entry = unresolved[i];
|
|
6572
|
-
const severityColor = entry.severity === "error" ? RED10 :
|
|
6633
|
+
const severityColor = entry.severity === "error" ? RED10 : YELLOW9;
|
|
6573
6634
|
const icon = entry.severity === "error" ? "x" : "!";
|
|
6574
6635
|
console.log(
|
|
6575
6636
|
` ${severityColor}${icon}${RESET12} ${BOLD6}#${i + 1}${RESET12} [${entry.rule}] ${entry.message}`
|
|
@@ -6853,7 +6914,7 @@ import { join as join29 } from "path";
|
|
|
6853
6914
|
import { isV4 as isV48 } from "@decantr/essence-spec";
|
|
6854
6915
|
var GREEN14 = "\x1B[32m";
|
|
6855
6916
|
var RED11 = "\x1B[31m";
|
|
6856
|
-
var
|
|
6917
|
+
var YELLOW10 = "\x1B[33m";
|
|
6857
6918
|
var DIM14 = "\x1B[2m";
|
|
6858
6919
|
var RESET14 = "\x1B[0m";
|
|
6859
6920
|
var VALID_THEME_SHAPES = ["sharp", "rounded", "pill"];
|
|
@@ -6948,7 +7009,7 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
6948
7009
|
console.log(
|
|
6949
7010
|
`${GREEN14}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET14}`
|
|
6950
7011
|
);
|
|
6951
|
-
console.log(`${
|
|
7012
|
+
console.log(`${YELLOW10}Guard will flag code using old tokens. Run \`decantr check\`.${RESET14}`);
|
|
6952
7013
|
}
|
|
6953
7014
|
|
|
6954
7015
|
// src/prompts.ts
|
|
@@ -6957,7 +7018,7 @@ var BOLD8 = "\x1B[1m";
|
|
|
6957
7018
|
var DIM15 = "\x1B[2m";
|
|
6958
7019
|
var RESET15 = "\x1B[0m";
|
|
6959
7020
|
var GREEN15 = "\x1B[32m";
|
|
6960
|
-
var
|
|
7021
|
+
var YELLOW11 = "\x1B[33m";
|
|
6961
7022
|
var CYAN8 = "\x1B[36m";
|
|
6962
7023
|
function ask(question, defaultValue) {
|
|
6963
7024
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -6997,7 +7058,7 @@ async function confirm(question, defaultYes = true) {
|
|
|
6997
7058
|
}
|
|
6998
7059
|
function warn(message) {
|
|
6999
7060
|
console.log(`
|
|
7000
|
-
${
|
|
7061
|
+
${YELLOW11} Warning: ${message}${RESET15}`);
|
|
7001
7062
|
}
|
|
7002
7063
|
function showDetection(detected) {
|
|
7003
7064
|
console.log(`
|
|
@@ -7016,7 +7077,7 @@ ${CYAN8}Detected project configuration:${RESET15}`);
|
|
|
7016
7077
|
console.log(` Tailwind CSS: ${GREEN15}yes${RESET15}`);
|
|
7017
7078
|
}
|
|
7018
7079
|
if (detected.existingEssence) {
|
|
7019
|
-
console.log(` Existing essence: ${
|
|
7080
|
+
console.log(` Existing essence: ${YELLOW11}yes${RESET15}`);
|
|
7020
7081
|
}
|
|
7021
7082
|
}
|
|
7022
7083
|
async function runInteractivePrompts(detected, archetypes, blueprints, themes, workflowSeed) {
|
|
@@ -7418,7 +7479,7 @@ var RESET16 = "\x1B[0m";
|
|
|
7418
7479
|
var RED12 = "\x1B[31m";
|
|
7419
7480
|
var GREEN16 = "\x1B[32m";
|
|
7420
7481
|
var CYAN9 = "\x1B[36m";
|
|
7421
|
-
var
|
|
7482
|
+
var YELLOW12 = "\x1B[33m";
|
|
7422
7483
|
function heading2(text) {
|
|
7423
7484
|
return `
|
|
7424
7485
|
${BOLD9}${text}${RESET16}
|
|
@@ -8200,7 +8261,7 @@ async function compileHostedExecutionPackBundle(essencePath, namespace) {
|
|
|
8200
8261
|
}
|
|
8201
8262
|
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8202
8263
|
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
8203
|
-
const contextDir = join31(
|
|
8264
|
+
const contextDir = join31(dirname6(resolvedPath), ".decantr", "context");
|
|
8204
8265
|
return { resolvedPath, bundle, contextDir };
|
|
8205
8266
|
}
|
|
8206
8267
|
function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
|
|
@@ -8244,7 +8305,7 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8244
8305
|
);
|
|
8245
8306
|
let writtenContextDir = null;
|
|
8246
8307
|
if (writeContext) {
|
|
8247
|
-
const contextDir = join31(
|
|
8308
|
+
const contextDir = join31(dirname6(resolvedPath), ".decantr", "context");
|
|
8248
8309
|
mkdirSync16(contextDir, { recursive: true });
|
|
8249
8310
|
writeFileSync19(
|
|
8250
8311
|
join31(contextDir, "pack-manifest.json"),
|
|
@@ -8290,7 +8351,7 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
|
|
|
8290
8351
|
);
|
|
8291
8352
|
let writtenContextDir = null;
|
|
8292
8353
|
if (writeContext) {
|
|
8293
|
-
const contextDir = join31(
|
|
8354
|
+
const contextDir = join31(dirname6(resolvedPath), ".decantr", "context");
|
|
8294
8355
|
mkdirSync16(contextDir, { recursive: true });
|
|
8295
8356
|
writeFileSync19(join31(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
8296
8357
|
writtenContextDir = contextDir;
|
|
@@ -8461,7 +8522,7 @@ function printBlueprintPortfolioNotice(blueprint) {
|
|
|
8461
8522
|
if (!portfolio) return;
|
|
8462
8523
|
if (portfolio.visibility === "hidden" || portfolio.maturity === "fold-candidate") {
|
|
8463
8524
|
console.log(
|
|
8464
|
-
`${
|
|
8525
|
+
`${YELLOW12} Warning:${RESET16} blueprint "${blueprint.id}" is folded out of public browsing.`
|
|
8465
8526
|
);
|
|
8466
8527
|
if (portfolio.recommended_alternative) {
|
|
8467
8528
|
console.log(
|
|
@@ -8474,7 +8535,7 @@ function printBlueprintPortfolioNotice(blueprint) {
|
|
|
8474
8535
|
}
|
|
8475
8536
|
if (portfolio.visibility === "labs") {
|
|
8476
8537
|
console.log(
|
|
8477
|
-
`${
|
|
8538
|
+
`${YELLOW12} Note:${RESET16} blueprint "${blueprint.id}" is a Labs blueprint; direct scaffolding is supported, but it is not a default recommendation yet.`
|
|
8478
8539
|
);
|
|
8479
8540
|
}
|
|
8480
8541
|
}
|
|
@@ -8661,7 +8722,10 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8661
8722
|
`Pattern suggestions for "${query}"${contextBits.length > 0 ? ` (${contextBits.join(", ")})` : ""}`
|
|
8662
8723
|
)
|
|
8663
8724
|
);
|
|
8664
|
-
const localMatches = localPatternMatches(
|
|
8725
|
+
const localMatches = localPatternMatches(
|
|
8726
|
+
options.projectRoot,
|
|
8727
|
+
[query, code].filter(Boolean).join("\n")
|
|
8728
|
+
);
|
|
8665
8729
|
if (localMatches.length > 0) {
|
|
8666
8730
|
console.log(`${BOLD9}Project-owned local law:${RESET16}`);
|
|
8667
8731
|
for (const match of localMatches) {
|
|
@@ -8763,7 +8827,7 @@ async function cmdValidate(path) {
|
|
|
8763
8827
|
console.log(heading2("Guard violations:"));
|
|
8764
8828
|
for (const v of violations) {
|
|
8765
8829
|
const vr = v;
|
|
8766
|
-
console.log(` ${
|
|
8830
|
+
console.log(` ${YELLOW12}[${vr.rule}]${RESET16} ${vr.message}`);
|
|
8767
8831
|
if (vr.suggestion) {
|
|
8768
8832
|
console.log(` ${DIM16}Suggestion: ${vr.suggestion}${RESET16}`);
|
|
8769
8833
|
}
|
|
@@ -8869,7 +8933,7 @@ ${CYAN9}Telemetry enabled.${RESET16} Decantr will send privacy-filtered CLI prod
|
|
|
8869
8933
|
console.log(`${DIM16}Set "telemetry": false in .decantr/project.json to opt out.${RESET16}`);
|
|
8870
8934
|
}
|
|
8871
8935
|
function readCliPackageVersion2() {
|
|
8872
|
-
const here =
|
|
8936
|
+
const here = dirname6(fileURLToPath3(import.meta.url));
|
|
8873
8937
|
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
8874
8938
|
for (const candidate of candidates) {
|
|
8875
8939
|
try {
|
|
@@ -9097,7 +9161,7 @@ async function cmdInit(args) {
|
|
|
9097
9161
|
console.log(dim3(" Found .decantr/init-seed.json brownfield guidance."));
|
|
9098
9162
|
}
|
|
9099
9163
|
if (detected.existingEssence && !args.existing) {
|
|
9100
|
-
console.log(`${
|
|
9164
|
+
console.log(`${YELLOW12}Warning: decantr.essence.json already exists.${RESET16}`);
|
|
9101
9165
|
const overwrite = await confirm("Overwrite existing configuration?", false);
|
|
9102
9166
|
if (!overwrite) {
|
|
9103
9167
|
console.log(dim3("Cancelled."));
|
|
@@ -9200,7 +9264,7 @@ async function cmdInit(args) {
|
|
|
9200
9264
|
} else if (shouldUseRegistry && !apiAvailable) {
|
|
9201
9265
|
if (!args.blueprint) {
|
|
9202
9266
|
console.log(`
|
|
9203
|
-
${
|
|
9267
|
+
${YELLOW12}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
|
|
9204
9268
|
console.log(
|
|
9205
9269
|
dim3("Run `decantr sync` or `decantr upgrade` when online to pull full registry content.\n")
|
|
9206
9270
|
);
|
|
@@ -9249,7 +9313,7 @@ ${YELLOW11}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
|
|
|
9249
9313
|
return;
|
|
9250
9314
|
}
|
|
9251
9315
|
console.log(`
|
|
9252
|
-
${
|
|
9316
|
+
${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
9253
9317
|
console.log(dim3("Run `decantr upgrade` when online, or visit decantr.ai/registry\n"));
|
|
9254
9318
|
selectedBlueprint = "default";
|
|
9255
9319
|
} else if (shouldUseRegistry) {
|
|
@@ -9431,7 +9495,7 @@ ${YELLOW11}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9431
9495
|
return;
|
|
9432
9496
|
}
|
|
9433
9497
|
console.log(
|
|
9434
|
-
`${
|
|
9498
|
+
`${YELLOW12} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET16}`
|
|
9435
9499
|
);
|
|
9436
9500
|
}
|
|
9437
9501
|
} else if (shouldUseRegistry && options.archetype) {
|
|
@@ -9446,7 +9510,7 @@ ${YELLOW11}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9446
9510
|
return;
|
|
9447
9511
|
}
|
|
9448
9512
|
console.log(
|
|
9449
|
-
`${
|
|
9513
|
+
`${YELLOW12} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET16}`
|
|
9450
9514
|
);
|
|
9451
9515
|
}
|
|
9452
9516
|
}
|
|
@@ -9463,7 +9527,7 @@ ${YELLOW11}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9463
9527
|
return;
|
|
9464
9528
|
}
|
|
9465
9529
|
console.log(
|
|
9466
|
-
`${
|
|
9530
|
+
`${YELLOW12} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET16}`
|
|
9467
9531
|
);
|
|
9468
9532
|
}
|
|
9469
9533
|
}
|
|
@@ -9668,7 +9732,7 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
9668
9732
|
` Guard: ${v4.meta.guard.mode} (DNA: ${v4.meta.guard.dna_enforcement}, Blueprint: ${v4.meta.guard.blueprint_enforcement})`
|
|
9669
9733
|
);
|
|
9670
9734
|
} else {
|
|
9671
|
-
console.log(` ${
|
|
9735
|
+
console.log(` ${YELLOW12}Run \`decantr migrate --to v4\` to upgrade this project.${RESET16}`);
|
|
9672
9736
|
}
|
|
9673
9737
|
} catch (e) {
|
|
9674
9738
|
console.log(` ${RED12}Error reading essence: ${e.message}${RESET16}`);
|
|
@@ -9681,15 +9745,15 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
9681
9745
|
const syncStatus = projectJson.sync?.status || "unknown";
|
|
9682
9746
|
const lastSync = projectJson.sync?.lastSync || "never";
|
|
9683
9747
|
const source = projectJson.sync?.registrySource || "unknown";
|
|
9684
|
-
const statusColor = syncStatus === "synced" ? GREEN16 :
|
|
9748
|
+
const statusColor = syncStatus === "synced" ? GREEN16 : YELLOW12;
|
|
9685
9749
|
console.log(` Status: ${statusColor}${syncStatus}${RESET16}`);
|
|
9686
9750
|
console.log(` Last sync: ${dim3(lastSync)}`);
|
|
9687
9751
|
console.log(` Source: ${dim3(source)}`);
|
|
9688
9752
|
} catch {
|
|
9689
|
-
console.log(` ${
|
|
9753
|
+
console.log(` ${YELLOW12}Could not read project.json${RESET16}`);
|
|
9690
9754
|
}
|
|
9691
9755
|
} else {
|
|
9692
|
-
console.log(` ${
|
|
9756
|
+
console.log(` ${YELLOW12}No .decantr/project.json found${RESET16}`);
|
|
9693
9757
|
console.log(dim3(' Run "decantr init" to create project files.'));
|
|
9694
9758
|
}
|
|
9695
9759
|
}
|
|
@@ -9702,12 +9766,12 @@ async function cmdSync() {
|
|
|
9702
9766
|
console.log(success3("Sync completed successfully."));
|
|
9703
9767
|
console.log(` Synced: ${result.synced.join(", ")}`);
|
|
9704
9768
|
if (result.failed.length > 0) {
|
|
9705
|
-
console.log(` ${
|
|
9769
|
+
console.log(` ${YELLOW12}Failed: ${result.failed.join(", ")}${RESET16}`);
|
|
9706
9770
|
}
|
|
9707
9771
|
} else {
|
|
9708
|
-
console.log(`${
|
|
9772
|
+
console.log(`${YELLOW12}Could not sync: API unavailable${RESET16}`);
|
|
9709
9773
|
if (result.failed.length > 0) {
|
|
9710
|
-
console.log(` ${
|
|
9774
|
+
console.log(` ${YELLOW12}Failed: ${result.failed.join(", ")}${RESET16}`);
|
|
9711
9775
|
}
|
|
9712
9776
|
}
|
|
9713
9777
|
}
|
|
@@ -9717,7 +9781,7 @@ function printVerificationFindings(findings) {
|
|
|
9717
9781
|
return;
|
|
9718
9782
|
}
|
|
9719
9783
|
for (const finding of findings) {
|
|
9720
|
-
const color = finding.severity === "error" ? RED12 : finding.severity === "warn" ?
|
|
9784
|
+
const color = finding.severity === "error" ? RED12 : finding.severity === "warn" ? YELLOW12 : CYAN9;
|
|
9721
9785
|
console.log(
|
|
9722
9786
|
` ${color}[${finding.severity.toUpperCase()}]${RESET16} ${finding.category}: ${finding.message}`
|
|
9723
9787
|
);
|
|
@@ -10224,16 +10288,21 @@ async function cmdSetupWorkflow(args) {
|
|
|
10224
10288
|
console.log(` Detected: ${formatDetection(detected)}`);
|
|
10225
10289
|
console.log("");
|
|
10226
10290
|
if (detected.existingEssence) {
|
|
10291
|
+
const hasLocalPatterns = existsSync29(localPatternsPath(workspaceInfo.appRoot));
|
|
10292
|
+
const hasLocalRules = existsSync29(localRulesPath(workspaceInfo.appRoot));
|
|
10293
|
+
const verifyCommand = hasLocalPatterns || hasLocalRules ? "decantr verify --brownfield --local-patterns" : "decantr verify --brownfield";
|
|
10227
10294
|
console.log(`${BOLD9}Recommended path:${RESET16} maintain an attached Decantr project`);
|
|
10228
10295
|
console.log(
|
|
10229
10296
|
` ${cyan3(withProject('decantr task <route> "<change>"', projectArg))} Prepare LLM context before edits`
|
|
10230
10297
|
);
|
|
10231
10298
|
console.log(
|
|
10232
|
-
` ${cyan3(withProject(
|
|
10233
|
-
);
|
|
10234
|
-
console.log(
|
|
10235
|
-
` ${cyan3(withProject("decantr codify --from-audit", projectArg))} Propose project-owned local law`
|
|
10299
|
+
` ${cyan3(withProject(verifyCommand, projectArg))} Run local health and drift checks`
|
|
10236
10300
|
);
|
|
10301
|
+
if (!hasLocalPatterns || !hasLocalRules) {
|
|
10302
|
+
console.log(
|
|
10303
|
+
` ${cyan3(withProject("decantr codify --from-audit", projectArg))} Propose project-owned local law`
|
|
10304
|
+
);
|
|
10305
|
+
}
|
|
10237
10306
|
return;
|
|
10238
10307
|
}
|
|
10239
10308
|
if (hasFootprint) {
|
|
@@ -10358,7 +10427,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10358
10427
|
)
|
|
10359
10428
|
);
|
|
10360
10429
|
} catch (e) {
|
|
10361
|
-
console.log(`${
|
|
10430
|
+
console.log(`${YELLOW12}Pack hydration skipped:${RESET16} ${e.message}`);
|
|
10362
10431
|
console.log(
|
|
10363
10432
|
dim3(
|
|
10364
10433
|
`Run ${compilePacksCommandForProject(projectArg)} after adoption if you want hosted page/review packs.`
|
|
@@ -10369,7 +10438,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10369
10438
|
console.log(dim3("Skipping hosted pack hydration in offline mode."));
|
|
10370
10439
|
}
|
|
10371
10440
|
if (runVerify) {
|
|
10372
|
-
const { cmdHealth } = await import("./health-
|
|
10441
|
+
const { cmdHealth } = await import("./health-VAYRQVTF.js");
|
|
10373
10442
|
await cmdHealth(projectRoot, {
|
|
10374
10443
|
browser: runBrowser,
|
|
10375
10444
|
browserBaseUrl: baseUrl,
|
|
@@ -10440,7 +10509,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10440
10509
|
return;
|
|
10441
10510
|
}
|
|
10442
10511
|
if (workspaceMode) {
|
|
10443
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
10512
|
+
const { cmdWorkspace } = await import("./workspace-PBO3BJRL.js");
|
|
10444
10513
|
await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
|
|
10445
10514
|
return;
|
|
10446
10515
|
}
|
|
@@ -10473,7 +10542,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10473
10542
|
}
|
|
10474
10543
|
let guardExitCode;
|
|
10475
10544
|
if (brownfield) {
|
|
10476
|
-
const { cmdHeal, collectCheckIssues } = await import("./heal-
|
|
10545
|
+
const { cmdHeal, collectCheckIssues } = await import("./heal-2UCSPRTK.js");
|
|
10477
10546
|
if (quietOutput) {
|
|
10478
10547
|
const result = collectCheckIssues(workspaceInfo.appRoot, { brownfield: true });
|
|
10479
10548
|
guardExitCode = result.issues.some((issue) => issue.type === "error") ? 1 : void 0;
|
|
@@ -10483,7 +10552,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10483
10552
|
process.exitCode = void 0;
|
|
10484
10553
|
}
|
|
10485
10554
|
}
|
|
10486
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
10555
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-VAYRQVTF.js");
|
|
10487
10556
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
|
|
10488
10557
|
if (localPatterns) {
|
|
10489
10558
|
const validation = validateLocalLaw(workspaceInfo.appRoot);
|
|
@@ -10491,7 +10560,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10491
10560
|
if (!quietOutput) {
|
|
10492
10561
|
console.log("");
|
|
10493
10562
|
console.log(
|
|
10494
|
-
`${
|
|
10563
|
+
`${YELLOW12}Local pattern pack missing.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))}, review the proposal, then run ${cyan3(withProject("decantr codify --accept", projectArg))}.`
|
|
10495
10564
|
);
|
|
10496
10565
|
}
|
|
10497
10566
|
process.exitCode = process.exitCode || 1;
|
|
@@ -10507,11 +10576,11 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10507
10576
|
console.log(`${GREEN16}Local rule manifest found:${RESET16} ${validation.rulesPath}`);
|
|
10508
10577
|
} else {
|
|
10509
10578
|
console.log(
|
|
10510
|
-
`${
|
|
10579
|
+
`${YELLOW12}Local rule manifest missing.${RESET16} Run ${cyan3("decantr codify --from-audit")} to propose .decantr/rules.json.`
|
|
10511
10580
|
);
|
|
10512
10581
|
}
|
|
10513
10582
|
for (const warning of validation.warnings.slice(0, 8)) {
|
|
10514
|
-
console.log(`${
|
|
10583
|
+
console.log(`${YELLOW12}warn${RESET16} ${warning}`);
|
|
10515
10584
|
}
|
|
10516
10585
|
if (validation.findings.length > 0) {
|
|
10517
10586
|
console.log("");
|
|
@@ -10664,7 +10733,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
10664
10733
|
console.log("");
|
|
10665
10734
|
console.log(`${BOLD9}Project-owned local law:${RESET16}`);
|
|
10666
10735
|
console.log(
|
|
10667
|
-
` ${
|
|
10736
|
+
` ${YELLOW12}Not codified yet.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
|
|
10668
10737
|
);
|
|
10669
10738
|
}
|
|
10670
10739
|
if (context.changedFiles.length > 0) {
|
|
@@ -11309,7 +11378,7 @@ async function main() {
|
|
|
11309
11378
|
}
|
|
11310
11379
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
11311
11380
|
try {
|
|
11312
|
-
const here =
|
|
11381
|
+
const here = dirname6(fileURLToPath3(import.meta.url));
|
|
11313
11382
|
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
11314
11383
|
for (const candidate of candidates) {
|
|
11315
11384
|
if (existsSync29(candidate)) {
|
|
@@ -11451,7 +11520,7 @@ async function main() {
|
|
|
11451
11520
|
break;
|
|
11452
11521
|
}
|
|
11453
11522
|
case "upgrade": {
|
|
11454
|
-
const { cmdUpgrade } = await import("./upgrade-
|
|
11523
|
+
const { cmdUpgrade } = await import("./upgrade-7ZYWR2GH.js");
|
|
11455
11524
|
const { flags } = parseLooseArgs(args);
|
|
11456
11525
|
const workspaceInfo = resolveWorkflowProject(flags, "upgrade");
|
|
11457
11526
|
if (!workspaceInfo) break;
|
|
@@ -11463,10 +11532,10 @@ async function main() {
|
|
|
11463
11532
|
case "heal": {
|
|
11464
11533
|
if (command === "heal") {
|
|
11465
11534
|
console.log(
|
|
11466
|
-
`${
|
|
11535
|
+
`${YELLOW12}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET16}`
|
|
11467
11536
|
);
|
|
11468
11537
|
}
|
|
11469
|
-
const { cmdHeal } = await import("./heal-
|
|
11538
|
+
const { cmdHeal } = await import("./heal-2UCSPRTK.js");
|
|
11470
11539
|
const { flags } = parseLooseArgs(args);
|
|
11471
11540
|
const workspaceInfo = resolveWorkflowProject(flags, "check");
|
|
11472
11541
|
if (!workspaceInfo) break;
|
|
@@ -11491,7 +11560,7 @@ async function main() {
|
|
|
11491
11560
|
const { flags } = parseLooseArgs(args);
|
|
11492
11561
|
const workspaceInfo = resolveWorkflowProject(flags, "health");
|
|
11493
11562
|
if (!workspaceInfo) break;
|
|
11494
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
11563
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-VAYRQVTF.js");
|
|
11495
11564
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
|
|
11496
11565
|
} catch (e) {
|
|
11497
11566
|
console.error(error2(e.message));
|
|
@@ -11519,7 +11588,7 @@ async function main() {
|
|
|
11519
11588
|
cmdStudioHelp();
|
|
11520
11589
|
break;
|
|
11521
11590
|
}
|
|
11522
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
11591
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-WPETOZRW.js");
|
|
11523
11592
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
11524
11593
|
} catch (e) {
|
|
11525
11594
|
console.error(error2(e.message));
|
|
@@ -11533,7 +11602,7 @@ async function main() {
|
|
|
11533
11602
|
cmdWorkspaceHelp();
|
|
11534
11603
|
break;
|
|
11535
11604
|
}
|
|
11536
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
11605
|
+
const { cmdWorkspace } = await import("./workspace-PBO3BJRL.js");
|
|
11537
11606
|
await cmdWorkspace(process.cwd(), args);
|
|
11538
11607
|
} catch (e) {
|
|
11539
11608
|
console.error(error2(e.message));
|
|
@@ -277,7 +277,15 @@ async function syncRegistry(cacheDir, apiUrl = DEFAULT_API_URL) {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
// src/scaffold.ts
|
|
280
|
-
import {
|
|
280
|
+
import {
|
|
281
|
+
appendFileSync,
|
|
282
|
+
existsSync as existsSync2,
|
|
283
|
+
mkdirSync as mkdirSync2,
|
|
284
|
+
readdirSync as readdirSync2,
|
|
285
|
+
readFileSync as readFileSync2,
|
|
286
|
+
rmSync,
|
|
287
|
+
writeFileSync as writeFileSync2
|
|
288
|
+
} from "fs";
|
|
281
289
|
import { dirname, join as join2 } from "path";
|
|
282
290
|
import { fileURLToPath } from "url";
|
|
283
291
|
import { compileExecutionPackBundle } from "@decantr/core";
|
|
@@ -4504,6 +4512,24 @@ function writeExecutionPackArtifacts(basePathWithoutExtension, pack) {
|
|
|
4504
4512
|
writeFileSync2(jsonPath, JSON.stringify(pack, null, 2) + "\n");
|
|
4505
4513
|
return markdownPath;
|
|
4506
4514
|
}
|
|
4515
|
+
function isManagedExecutionPackArtifact(fileName) {
|
|
4516
|
+
return fileName === "pack-manifest.json" || /^(?:scaffold|review|section-.+-pack|page-.+-pack|mutation-.+-pack)\.(?:md|json)$/.test(
|
|
4517
|
+
fileName
|
|
4518
|
+
);
|
|
4519
|
+
}
|
|
4520
|
+
function removeObsoleteExecutionPackArtifacts(contextDir, writtenPaths) {
|
|
4521
|
+
const expected = /* @__PURE__ */ new Set();
|
|
4522
|
+
for (const path of writtenPaths) {
|
|
4523
|
+
expected.add(path);
|
|
4524
|
+
if (path.endsWith(".md")) expected.add(path.slice(0, -".md".length) + ".json");
|
|
4525
|
+
}
|
|
4526
|
+
for (const entry of readdirSync2(contextDir, { withFileTypes: true })) {
|
|
4527
|
+
if (!entry.isFile()) continue;
|
|
4528
|
+
if (!isManagedExecutionPackArtifact(entry.name)) continue;
|
|
4529
|
+
const fullPath = join2(contextDir, entry.name);
|
|
4530
|
+
if (!expected.has(fullPath)) rmSync(fullPath, { force: true });
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4507
4533
|
function writeExecutionPackBundleArtifacts(contextDir, bundle) {
|
|
4508
4534
|
mkdirSync2(contextDir, { recursive: true });
|
|
4509
4535
|
const outputPaths = [];
|
|
@@ -4540,6 +4566,7 @@ function writeExecutionPackBundleArtifacts(contextDir, bundle) {
|
|
|
4540
4566
|
const manifestPath = join2(contextDir, "pack-manifest.json");
|
|
4541
4567
|
writeFileSync2(manifestPath, JSON.stringify(bundle.manifest, null, 2) + "\n");
|
|
4542
4568
|
outputPaths.push(manifestPath);
|
|
4569
|
+
removeObsoleteExecutionPackArtifacts(contextDir, outputPaths);
|
|
4543
4570
|
return {
|
|
4544
4571
|
paths: outputPaths,
|
|
4545
4572
|
scaffoldPackPath,
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
renderProjectHealthCiWorkflow,
|
|
11
11
|
shouldFailHealth,
|
|
12
12
|
writeProjectHealthCiWorkflow
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-WPP3JEMC.js";
|
|
14
|
+
import "./chunk-4SZ4SEKT.js";
|
|
15
15
|
export {
|
|
16
16
|
cmdHealth,
|
|
17
17
|
collectDesignTokenEvidence,
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
3
|
-
import "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-66L74ZNJ.js";
|
|
2
|
+
import "./chunk-IQZCIMQJ.js";
|
|
3
|
+
import "./chunk-QDMXZSVK.js";
|
|
4
|
+
import "./chunk-WPP3JEMC.js";
|
|
5
|
+
import "./chunk-4SZ4SEKT.js";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createWorkspaceHealthReport
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QDMXZSVK.js";
|
|
4
4
|
import {
|
|
5
5
|
createProjectHealthReport
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WPP3JEMC.js";
|
|
7
7
|
import {
|
|
8
8
|
sendStudioHealthRefreshedTelemetry,
|
|
9
9
|
sendStudioStartedTelemetry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4SZ4SEKT.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/studio.ts
|
|
13
13
|
import { readFileSync } from "fs";
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
listWorkspaceProjects,
|
|
8
8
|
parseWorkspaceArgs,
|
|
9
9
|
shouldFailWorkspaceHealth
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-QDMXZSVK.js";
|
|
11
|
+
import "./chunk-WPP3JEMC.js";
|
|
12
|
+
import "./chunk-4SZ4SEKT.js";
|
|
13
13
|
export {
|
|
14
14
|
cmdWorkspace,
|
|
15
15
|
createWorkspaceHealthReport,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/cli",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.7",
|
|
4
4
|
"description": "Decantr CLI - scaffold, audit, inspect Project Health, and maintain Decantr projects from the terminal",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"decantr",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"ajv": "^8.20.0",
|
|
51
51
|
"@decantr/core": "2.1.0",
|
|
52
52
|
"@decantr/registry": "2.2.0",
|
|
53
|
-
"@decantr/
|
|
53
|
+
"@decantr/verifier": "2.3.3",
|
|
54
54
|
"@decantr/essence-spec": "2.0.1",
|
|
55
|
-
"@decantr/
|
|
55
|
+
"@decantr/telemetry": "2.2.1"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsup",
|