@decantr/cli 2.9.1 → 2.9.3
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 +10 -5
- package/dist/bin.js +3 -3
- package/dist/{chunk-FKM4OQDF.js → chunk-ARR3EPS2.js} +17 -107
- package/dist/{chunk-6UDJDQPT.js → chunk-VMNUJOEH.js} +794 -328
- package/dist/{chunk-TMOCTDYY.js → chunk-XZFKK6V7.js} +311 -50
- package/dist/{health-Q7XF3I5Z.js → health-MB63O56B.js} +1 -1
- package/dist/index.js +3 -3
- package/dist/{studio-EDQMI6JE.js → studio-6QGXJBVH.js} +2 -2
- package/dist/{workspace-JA2RZI6V.js → workspace-OGFYJA4N.js} +2 -2
- package/package.json +4 -4
|
@@ -21,15 +21,15 @@ import {
|
|
|
21
21
|
formatWorkspaceHealthText,
|
|
22
22
|
listWorkspaceCandidates,
|
|
23
23
|
listWorkspaceProjects,
|
|
24
|
-
resolveWorkspaceInfo,
|
|
25
24
|
shouldFailWorkspaceHealth
|
|
26
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-ARR3EPS2.js";
|
|
27
26
|
import {
|
|
28
27
|
createProjectHealthReport,
|
|
29
28
|
formatProjectHealthMarkdown,
|
|
30
29
|
formatProjectHealthText,
|
|
30
|
+
resolveWorkspaceInfo,
|
|
31
31
|
shouldFailHealth
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-XZFKK6V7.js";
|
|
33
33
|
import {
|
|
34
34
|
buildGuardRegistryContext,
|
|
35
35
|
createDoctrineMap,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
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 dirname5, isAbsolute, join as join31, resolve as resolve4 } from "path";
|
|
53
|
+
import { basename as basename3, dirname as dirname5, 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 {
|
|
@@ -1772,6 +1772,20 @@ function readV4Essence(projectRoot) {
|
|
|
1772
1772
|
function writeEssence(essencePath, essence) {
|
|
1773
1773
|
writeFileSync6(essencePath, JSON.stringify(essence, null, 2) + "\n");
|
|
1774
1774
|
}
|
|
1775
|
+
function readFlagValue(args, name) {
|
|
1776
|
+
const prefix = `--${name}=`;
|
|
1777
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1778
|
+
const arg = args[index];
|
|
1779
|
+
if (arg === `--${name}` && args[index + 1]) return args[index + 1];
|
|
1780
|
+
if (arg.startsWith(prefix)) return arg.slice(prefix.length);
|
|
1781
|
+
}
|
|
1782
|
+
return void 0;
|
|
1783
|
+
}
|
|
1784
|
+
function normalizeRoute(route) {
|
|
1785
|
+
const trimmed = route.trim();
|
|
1786
|
+
if (!trimmed || trimmed === "/") return "/";
|
|
1787
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
1788
|
+
}
|
|
1775
1789
|
async function cmdAddSection(archetypeId, args, projectRoot = process.cwd()) {
|
|
1776
1790
|
if (!archetypeId) {
|
|
1777
1791
|
console.error(`${RED}Usage: decantr add section <archetypeId>${RESET}`);
|
|
@@ -1847,12 +1861,27 @@ async function cmdAddPage(path, args, projectRoot = process.cwd()) {
|
|
|
1847
1861
|
process.exitCode = 1;
|
|
1848
1862
|
return;
|
|
1849
1863
|
}
|
|
1864
|
+
const route = normalizeRoute(readFlagValue(args, "route") ?? pageId);
|
|
1865
|
+
const routes = essence.blueprint.routes ??= {};
|
|
1866
|
+
const existingRoute = routes[route];
|
|
1867
|
+
if (existingRoute) {
|
|
1868
|
+
console.error(
|
|
1869
|
+
`${RED}Route "${route}" already maps to ${existingRoute.section}/${existingRoute.page}.${RESET}`
|
|
1870
|
+
);
|
|
1871
|
+
console.error(`${DIM}Pass a unique route with --route /some-path.${RESET}`);
|
|
1872
|
+
process.exitCode = 1;
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1850
1875
|
section.pages.push({
|
|
1851
1876
|
id: pageId,
|
|
1877
|
+
route,
|
|
1852
1878
|
layout: ["hero"]
|
|
1853
1879
|
});
|
|
1880
|
+
routes[route] = { section: sectionId, page: pageId };
|
|
1854
1881
|
writeEssence(essencePath, essence);
|
|
1855
|
-
console.log(
|
|
1882
|
+
console.log(
|
|
1883
|
+
`${GREEN}Added page "${pageId}" to section "${sectionId}" at route "${route}".${RESET}`
|
|
1884
|
+
);
|
|
1856
1885
|
const registryClient = new RegistryClient({
|
|
1857
1886
|
cacheDir: join6(projectRoot, ".decantr", "cache")
|
|
1858
1887
|
});
|
|
@@ -1869,10 +1898,7 @@ async function cmdAddFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
1869
1898
|
if (!loaded) return;
|
|
1870
1899
|
const { essence, essencePath } = loaded;
|
|
1871
1900
|
let sectionId;
|
|
1872
|
-
|
|
1873
|
-
if (sectionIdx !== -1 && args[sectionIdx + 1]) {
|
|
1874
|
-
sectionId = args[sectionIdx + 1];
|
|
1875
|
-
}
|
|
1901
|
+
sectionId = readFlagValue(args, "section");
|
|
1876
1902
|
if (sectionId) {
|
|
1877
1903
|
const sections = essence.blueprint.sections;
|
|
1878
1904
|
const section = sections.find((s) => s.id === sectionId);
|
|
@@ -1901,7 +1927,7 @@ async function cmdAddFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
1901
1927
|
|
|
1902
1928
|
// src/commands/analyze.ts
|
|
1903
1929
|
import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
1904
|
-
import { join as join14 } from "path";
|
|
1930
|
+
import { join as join14, relative as relative2 } from "path";
|
|
1905
1931
|
|
|
1906
1932
|
// src/analyzers/components.ts
|
|
1907
1933
|
import { existsSync as existsSync5, readdirSync, statSync as statSync2 } from "fs";
|
|
@@ -2957,6 +2983,10 @@ ${BOLD}Analyzing project...${RESET2}
|
|
|
2957
2983
|
const doctrine = createDoctrineMap(ambient);
|
|
2958
2984
|
const initSeed = createBrownfieldInitSeed(project, layout, styling);
|
|
2959
2985
|
initSeed.projectScope = workspace?.projectScope ?? "single-app";
|
|
2986
|
+
const projectLabel = workspace && workspace.appRoot !== workspace.workspaceRoot ? relative2(workspace.workspaceRoot, workspace.appRoot).replace(/\\/g, "/") : null;
|
|
2987
|
+
const projectFlag = projectLabel ? ` --project ${projectLabel}` : "";
|
|
2988
|
+
const reportDisplayPath = projectLabel ? `${projectLabel}/.decantr/brownfield-report.md` : ".decantr/brownfield-report.md";
|
|
2989
|
+
const recommendedAttachCommand = `decantr init${projectFlag} --existing --accept-proposal`;
|
|
2960
2990
|
const proposal = createBrownfieldProposal({
|
|
2961
2991
|
project,
|
|
2962
2992
|
routes,
|
|
@@ -2996,7 +3026,7 @@ ${BOLD}Analyzing project...${RESET2}
|
|
|
2996
3026
|
adoptionMode: "contract-only",
|
|
2997
3027
|
initSeedPath: ".decantr/init-seed.json",
|
|
2998
3028
|
proposalPath: ".decantr/observed-essence.proposal.json",
|
|
2999
|
-
recommendedCommand:
|
|
3029
|
+
recommendedCommand: recommendedAttachCommand
|
|
3000
3030
|
},
|
|
3001
3031
|
hybrid: {
|
|
3002
3032
|
ownerCommands: [
|
|
@@ -3096,7 +3126,7 @@ ${DIM2}Written to:${RESET2} ${outputPath}`);
|
|
|
3096
3126
|
console.log(`${DIM2}Enrichment backlog:${RESET2} ${intelligenceArtifacts.backlogPath}`);
|
|
3097
3127
|
console.log(
|
|
3098
3128
|
`
|
|
3099
|
-
${YELLOW}Next step:${RESET2} Review ${BOLD}
|
|
3129
|
+
${YELLOW}Next step:${RESET2} Review ${BOLD}${reportDisplayPath}${RESET2}, then run ${BOLD}${recommendedAttachCommand}${RESET2} to attach Decantr using the observed proposal.
|
|
3100
3130
|
`
|
|
3101
3131
|
);
|
|
3102
3132
|
await sendAnalyzeCompletedTelemetry({
|
|
@@ -3119,12 +3149,12 @@ ${YELLOW}Next step:${RESET2} Review ${BOLD}.decantr/brownfield-report.md${RESET2
|
|
|
3119
3149
|
|
|
3120
3150
|
// src/commands/ci.ts
|
|
3121
3151
|
import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
3122
|
-
import { dirname as dirname2, join as join16, relative as
|
|
3152
|
+
import { dirname as dirname2, join as join16, relative as relative4, resolve } from "path";
|
|
3123
3153
|
|
|
3124
3154
|
// src/local-law.ts
|
|
3125
3155
|
import { execFileSync } from "child_process";
|
|
3126
3156
|
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
3127
|
-
import { basename as basename2, extname, join as join15, relative as
|
|
3157
|
+
import { basename as basename2, extname, join as join15, relative as relative3, sep } from "path";
|
|
3128
3158
|
import { isV4 as isV43 } from "@decantr/essence-spec";
|
|
3129
3159
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
3130
3160
|
".astro",
|
|
@@ -3565,7 +3595,7 @@ function listSourceFiles(projectRoot, maxFiles) {
|
|
|
3565
3595
|
if (stat.isDirectory()) {
|
|
3566
3596
|
visit(absolute);
|
|
3567
3597
|
} else if (stat.isFile() && SOURCE_EXTENSIONS.has(extname(entry))) {
|
|
3568
|
-
files.push({ absolute, relative: normalizePath(
|
|
3598
|
+
files.push({ absolute, relative: normalizePath(relative3(projectRoot, absolute)) });
|
|
3569
3599
|
}
|
|
3570
3600
|
}
|
|
3571
3601
|
};
|
|
@@ -3653,7 +3683,8 @@ function parseCiArgs(args) {
|
|
|
3653
3683
|
return options;
|
|
3654
3684
|
}
|
|
3655
3685
|
function parseProvider(value) {
|
|
3656
|
-
|
|
3686
|
+
if (value === "github" || value === "generic") return value;
|
|
3687
|
+
throw new Error("Invalid --provider value. Use github or generic.");
|
|
3657
3688
|
}
|
|
3658
3689
|
function detectPackageManager(root) {
|
|
3659
3690
|
const pkg = readJson(join16(root, "package.json"));
|
|
@@ -3667,6 +3698,12 @@ function detectPackageManager(root) {
|
|
|
3667
3698
|
if (existsSync14(join16(root, "bun.lock")) || existsSync14(join16(root, "bun.lockb"))) return "bun";
|
|
3668
3699
|
return "unknown";
|
|
3669
3700
|
}
|
|
3701
|
+
function hasWorkspaceMarker(root) {
|
|
3702
|
+
const pkg = readJson(join16(root, "package.json"));
|
|
3703
|
+
return Boolean(
|
|
3704
|
+
existsSync14(join16(root, "pnpm-workspace.yaml")) || existsSync14(join16(root, "turbo.json")) || existsSync14(join16(root, "nx.json")) || pkg?.workspaces
|
|
3705
|
+
);
|
|
3706
|
+
}
|
|
3670
3707
|
function installCommand(packageManager) {
|
|
3671
3708
|
switch (packageManager) {
|
|
3672
3709
|
case "pnpm":
|
|
@@ -3681,6 +3718,20 @@ function installCommand(packageManager) {
|
|
|
3681
3718
|
return "npm install";
|
|
3682
3719
|
}
|
|
3683
3720
|
}
|
|
3721
|
+
function pinCliCommand(packageManager, root) {
|
|
3722
|
+
switch (packageManager) {
|
|
3723
|
+
case "pnpm":
|
|
3724
|
+
return hasWorkspaceMarker(root) ? "pnpm add -D -w @decantr/cli" : "pnpm add -D @decantr/cli";
|
|
3725
|
+
case "yarn":
|
|
3726
|
+
return "yarn add -D @decantr/cli";
|
|
3727
|
+
case "bun":
|
|
3728
|
+
return "bun add -d @decantr/cli";
|
|
3729
|
+
case "npm":
|
|
3730
|
+
return "npm install -D @decantr/cli";
|
|
3731
|
+
default:
|
|
3732
|
+
return "npm install -D @decantr/cli";
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3684
3735
|
function decantrCommand(packageManager) {
|
|
3685
3736
|
switch (packageManager) {
|
|
3686
3737
|
case "pnpm":
|
|
@@ -3823,6 +3874,9 @@ jobs:
|
|
|
3823
3874
|
}
|
|
3824
3875
|
function writeCiInit(root, options) {
|
|
3825
3876
|
const workspaceInfo = resolveWorkspaceInfo(root, options.project);
|
|
3877
|
+
if (options.project && !existsSync14(workspaceInfo.appRoot)) {
|
|
3878
|
+
throw new Error(`Project path does not exist: ${options.project}`);
|
|
3879
|
+
}
|
|
3826
3880
|
if (workspaceInfo.requiresProjectSelection && !options.workspace) {
|
|
3827
3881
|
const candidate = workspaceInfo.appCandidates[0] ?? "apps/web";
|
|
3828
3882
|
throw new Error(
|
|
@@ -3830,14 +3884,14 @@ function writeCiInit(root, options) {
|
|
|
3830
3884
|
);
|
|
3831
3885
|
}
|
|
3832
3886
|
const outputRoot = workspaceInfo.workspaceRoot;
|
|
3833
|
-
const projectPath = options.project ?? (options.workspace || workspaceInfo.appRoot === workspaceInfo.workspaceRoot ? void 0 :
|
|
3887
|
+
const projectPath = options.project ?? (options.workspace || workspaceInfo.appRoot === workspaceInfo.workspaceRoot ? void 0 : relative4(workspaceInfo.workspaceRoot, workspaceInfo.appRoot).replace(/\\/g, "/"));
|
|
3834
3888
|
const packageManager = detectPackageManager(outputRoot);
|
|
3835
3889
|
const command = decantrCommand(packageManager);
|
|
3836
3890
|
const failOn = options.failOn ?? "error";
|
|
3837
3891
|
const provider = options.provider ?? "github";
|
|
3838
3892
|
if (!localCliPinned(outputRoot)) {
|
|
3839
3893
|
console.log(
|
|
3840
|
-
`${DIM3}No @decantr/cli dependency was found in the workspace root package.json.
|
|
3894
|
+
`${DIM3}No @decantr/cli dependency was found in the workspace root package.json. Before relying on CI, pin it with: ${pinCliCommand(packageManager, outputRoot)}${RESET3}`
|
|
3841
3895
|
);
|
|
3842
3896
|
}
|
|
3843
3897
|
if (provider === "generic") {
|
|
@@ -3913,6 +3967,10 @@ async function runWorkspaceCi(root, options) {
|
|
|
3913
3967
|
}
|
|
3914
3968
|
async function runProjectCi(root, options) {
|
|
3915
3969
|
const workspaceInfo = resolveWorkspaceInfo(root, options.project);
|
|
3970
|
+
if (options.project && !existsSync14(workspaceInfo.appRoot)) {
|
|
3971
|
+
console.error(`${RED2}Project path does not exist: ${options.project}${RESET3}`);
|
|
3972
|
+
return 1;
|
|
3973
|
+
}
|
|
3916
3974
|
if (workspaceInfo.requiresProjectSelection) {
|
|
3917
3975
|
const candidate = workspaceInfo.appCandidates[0] ?? "apps/web";
|
|
3918
3976
|
console.error(`${RED2}Decantr CI needs an app path in this monorepo.${RESET3}`);
|
|
@@ -3963,16 +4021,16 @@ ${BOLD2}Examples:${RESET3}
|
|
|
3963
4021
|
`);
|
|
3964
4022
|
}
|
|
3965
4023
|
async function cmdCi(args = ["ci"], root = process.cwd()) {
|
|
3966
|
-
const options = parseCiArgs(args);
|
|
3967
4024
|
try {
|
|
4025
|
+
const options = parseCiArgs(args);
|
|
3968
4026
|
if (options.init) {
|
|
3969
4027
|
writeCiInit(root, options);
|
|
3970
4028
|
return;
|
|
3971
4029
|
}
|
|
3972
4030
|
const exitCode = options.workspace ? await runWorkspaceCi(root, options) : await runProjectCi(root, options);
|
|
3973
4031
|
if (exitCode !== 0) process.exitCode = exitCode;
|
|
3974
|
-
} catch (
|
|
3975
|
-
console.error(`${RED2}${
|
|
4032
|
+
} catch (error3) {
|
|
4033
|
+
console.error(`${RED2}${error3.message}${RESET3}`);
|
|
3976
4034
|
process.exitCode = 1;
|
|
3977
4035
|
}
|
|
3978
4036
|
}
|
|
@@ -4191,7 +4249,7 @@ function cmdCreate(type, name, projectRoot = process.cwd()) {
|
|
|
4191
4249
|
|
|
4192
4250
|
// src/commands/doctor.ts
|
|
4193
4251
|
import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
|
|
4194
|
-
import { dirname as dirname3, join as join18, relative as
|
|
4252
|
+
import { dirname as dirname3, join as join18, relative as relative5 } from "path";
|
|
4195
4253
|
import { fileURLToPath } from "url";
|
|
4196
4254
|
import { isV4 as isV44 } from "@decantr/essence-spec";
|
|
4197
4255
|
import { collectMissingPackManifestFiles } from "@decantr/verifier";
|
|
@@ -4210,6 +4268,10 @@ function readJson2(path) {
|
|
|
4210
4268
|
return null;
|
|
4211
4269
|
}
|
|
4212
4270
|
}
|
|
4271
|
+
function isContractOnlyProject(projectRoot) {
|
|
4272
|
+
const projectJson = readJson2(join18(projectRoot, ".decantr", "project.json"));
|
|
4273
|
+
return projectJson?.initialized?.adoptionMode === "contract-only";
|
|
4274
|
+
}
|
|
4213
4275
|
function readCliPackageVersion() {
|
|
4214
4276
|
const packagePath = join18(dirname3(fileURLToPath(import.meta.url)), "..", "..", "package.json");
|
|
4215
4277
|
const srcPackagePath = join18(dirname3(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
@@ -4235,8 +4297,28 @@ function localCliDependency(root) {
|
|
|
4235
4297
|
const pkg = readPackageJson(root);
|
|
4236
4298
|
return pkg?.devDependencies?.["@decantr/cli"] ?? pkg?.dependencies?.["@decantr/cli"] ?? null;
|
|
4237
4299
|
}
|
|
4300
|
+
function hasWorkspaceMarker2(root) {
|
|
4301
|
+
const pkg = readPackageJson(root);
|
|
4302
|
+
return Boolean(
|
|
4303
|
+
existsSync16(join18(root, "pnpm-workspace.yaml")) || existsSync16(join18(root, "turbo.json")) || existsSync16(join18(root, "nx.json")) || pkg?.workspaces
|
|
4304
|
+
);
|
|
4305
|
+
}
|
|
4306
|
+
function pinCliCommand2(packageManager, root) {
|
|
4307
|
+
switch (packageManager) {
|
|
4308
|
+
case "pnpm":
|
|
4309
|
+
return hasWorkspaceMarker2(root) ? "pnpm add -D -w @decantr/cli" : "pnpm add -D @decantr/cli";
|
|
4310
|
+
case "yarn":
|
|
4311
|
+
return "yarn add -D @decantr/cli";
|
|
4312
|
+
case "bun":
|
|
4313
|
+
return "bun add -d @decantr/cli";
|
|
4314
|
+
case "npm":
|
|
4315
|
+
return "npm install -D @decantr/cli";
|
|
4316
|
+
default:
|
|
4317
|
+
return "npm install -D @decantr/cli";
|
|
4318
|
+
}
|
|
4319
|
+
}
|
|
4238
4320
|
function rel(root, path) {
|
|
4239
|
-
const value =
|
|
4321
|
+
const value = relative5(root, path).replace(/\\/g, "/");
|
|
4240
4322
|
return value || ".";
|
|
4241
4323
|
}
|
|
4242
4324
|
function hasAnyFile(dir, names) {
|
|
@@ -4315,14 +4397,20 @@ function statusFromIssues(issues, essenceVersion) {
|
|
|
4315
4397
|
return "healthy";
|
|
4316
4398
|
}
|
|
4317
4399
|
function buildDoctorReport(root, args) {
|
|
4318
|
-
|
|
4319
|
-
|
|
4400
|
+
let projectArg;
|
|
4401
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
4402
|
+
const arg = args[index];
|
|
4403
|
+
if (arg === "--project" && args[index + 1]) projectArg = args[++index];
|
|
4404
|
+
else if (arg.startsWith("--project=")) projectArg = arg.slice("--project=".length);
|
|
4405
|
+
}
|
|
4320
4406
|
const workspaceMode = args.includes("--workspace");
|
|
4321
4407
|
const workspaceInfo = resolveWorkspaceInfo(root, projectArg);
|
|
4322
4408
|
const workspaceRoot = workspaceInfo.workspaceRoot;
|
|
4323
4409
|
const appRoot = workspaceMode ? workspaceRoot : workspaceInfo.appRoot;
|
|
4410
|
+
const projectMissing = Boolean(projectArg && !existsSync16(appRoot));
|
|
4324
4411
|
const projectPath = appRoot === workspaceRoot ? null : rel(workspaceRoot, appRoot);
|
|
4325
4412
|
const packageManager = detectPackageManager2(workspaceRoot);
|
|
4413
|
+
const cliDependency = localCliDependency(workspaceRoot);
|
|
4326
4414
|
const detected = detectProject(appRoot);
|
|
4327
4415
|
const projectJson = readJson2(join18(appRoot, ".decantr", "project.json"));
|
|
4328
4416
|
const essence = readJson2(join18(appRoot, "decantr.essence.json"));
|
|
@@ -4340,6 +4428,7 @@ function buildDoctorReport(root, args) {
|
|
|
4340
4428
|
const ciFiles = findCiFiles(workspaceRoot);
|
|
4341
4429
|
const workflowMode = projectJson?.initialized?.workflowMode ?? null;
|
|
4342
4430
|
const adoptionMode = projectJson?.initialized?.adoptionMode ?? null;
|
|
4431
|
+
const packHydrationOptional = adoptionMode === "contract-only";
|
|
4343
4432
|
const missingPackReferences = workspaceMode ? projects.flatMap(
|
|
4344
4433
|
(project) => collectMissingPackManifestFiles(join18(workspaceRoot, project.path)).map(
|
|
4345
4434
|
(missing) => `${project.path}/${missing.relativePath}`
|
|
@@ -4347,14 +4436,21 @@ function buildDoctorReport(root, args) {
|
|
|
4347
4436
|
) : collectMissingPackManifestFiles(appRoot).map((missing) => missing.relativePath);
|
|
4348
4437
|
const workspaceProjectsMissingManifest = workspaceMode ? projects.map((project) => project.path).filter((projectPath2) => {
|
|
4349
4438
|
const projectContextDir = join18(workspaceRoot, projectPath2, ".decantr", "context");
|
|
4350
|
-
return !existsSync16(join18(projectContextDir, "pack-manifest.json"));
|
|
4439
|
+
return !isContractOnlyProject(join18(workspaceRoot, projectPath2)) && !existsSync16(join18(projectContextDir, "pack-manifest.json"));
|
|
4351
4440
|
}) : [];
|
|
4352
4441
|
const workspaceProjectsMissingReviewPack = workspaceMode ? projects.map((project) => project.path).filter((projectPath2) => {
|
|
4353
4442
|
const projectContextDir = join18(workspaceRoot, projectPath2, ".decantr", "context");
|
|
4354
|
-
return !existsSync16(join18(projectContextDir, "review-pack.json"));
|
|
4443
|
+
return !isContractOnlyProject(join18(workspaceRoot, projectPath2)) && !existsSync16(join18(projectContextDir, "review-pack.json"));
|
|
4355
4444
|
}) : [];
|
|
4356
4445
|
const issues = [];
|
|
4357
|
-
if (
|
|
4446
|
+
if (projectMissing) {
|
|
4447
|
+
issues.push({
|
|
4448
|
+
category: "workspace",
|
|
4449
|
+
severity: "error",
|
|
4450
|
+
message: `Project path does not exist: ${projectArg}`,
|
|
4451
|
+
nextCommand: "decantr workspace list"
|
|
4452
|
+
});
|
|
4453
|
+
} else if (!essenceVersion && !workspaceMode && !workspaceInfo.requiresProjectSelection) {
|
|
4358
4454
|
issues.push({
|
|
4359
4455
|
category: "setup",
|
|
4360
4456
|
severity: "error",
|
|
@@ -4385,6 +4481,14 @@ function buildDoctorReport(root, args) {
|
|
|
4385
4481
|
nextCommand: "decantr setup"
|
|
4386
4482
|
});
|
|
4387
4483
|
}
|
|
4484
|
+
if ((essenceVersion === "4.0.0" || workspaceMode || projects.length > 0) && !cliDependency) {
|
|
4485
|
+
issues.push({
|
|
4486
|
+
category: "ci",
|
|
4487
|
+
severity: "info",
|
|
4488
|
+
message: "@decantr/cli is not pinned in the workspace root package.json.",
|
|
4489
|
+
nextCommand: pinCliCommand2(packageManager, workspaceRoot)
|
|
4490
|
+
});
|
|
4491
|
+
}
|
|
4388
4492
|
if (essenceVersion === "4.0.0" && !artifactReadmePresent) {
|
|
4389
4493
|
issues.push({
|
|
4390
4494
|
category: "generated-artifact",
|
|
@@ -4393,7 +4497,7 @@ function buildDoctorReport(root, args) {
|
|
|
4393
4497
|
nextCommand: "decantr refresh"
|
|
4394
4498
|
});
|
|
4395
4499
|
}
|
|
4396
|
-
if (essenceVersion === "4.0.0" && (!existsSync16(contextDir) || !packManifestPresent)) {
|
|
4500
|
+
if (essenceVersion === "4.0.0" && !packHydrationOptional && (!existsSync16(contextDir) || !packManifestPresent)) {
|
|
4397
4501
|
issues.push({
|
|
4398
4502
|
category: "generated-artifact",
|
|
4399
4503
|
severity: "warn",
|
|
@@ -4453,7 +4557,7 @@ function buildDoctorReport(root, args) {
|
|
|
4453
4557
|
projectPath,
|
|
4454
4558
|
packageManager,
|
|
4455
4559
|
cli: {
|
|
4456
|
-
localDependency:
|
|
4560
|
+
localDependency: cliDependency,
|
|
4457
4561
|
runningVersion: readCliPackageVersion()
|
|
4458
4562
|
},
|
|
4459
4563
|
project: {
|
|
@@ -4564,18 +4668,24 @@ async function cmdDoctor(args = ["doctor"], root = process.cwd()) {
|
|
|
4564
4668
|
const report = buildDoctorReport(root, args);
|
|
4565
4669
|
if (args.includes("--json")) {
|
|
4566
4670
|
console.log(JSON.stringify(report, null, 2));
|
|
4671
|
+
if (report.issues.some((issue) => issue.severity === "error")) process.exitCode = 1;
|
|
4567
4672
|
return;
|
|
4568
4673
|
}
|
|
4569
4674
|
process.stdout.write(formatDoctorText(report));
|
|
4675
|
+
if (report.issues.some((issue) => issue.severity === "error")) process.exitCode = 1;
|
|
4570
4676
|
}
|
|
4571
4677
|
|
|
4572
4678
|
// src/commands/export.ts
|
|
4573
4679
|
import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
|
|
4574
|
-
import { dirname as dirname4, join as join19 } from "path";
|
|
4680
|
+
import { dirname as dirname4, isAbsolute, join as join19 } from "path";
|
|
4575
4681
|
var GREEN5 = "\x1B[32m";
|
|
4576
4682
|
var RED4 = "\x1B[31m";
|
|
4577
4683
|
var DIM5 = "\x1B[2m";
|
|
4578
4684
|
var RESET5 = "\x1B[0m";
|
|
4685
|
+
function resolveOutputPath(projectRoot, output, fallback) {
|
|
4686
|
+
if (!output) return fallback;
|
|
4687
|
+
return isAbsolute(output) ? output : join19(projectRoot, output);
|
|
4688
|
+
}
|
|
4579
4689
|
var SHADCN_MAP = {
|
|
4580
4690
|
"--d-bg": "--background",
|
|
4581
4691
|
"--d-text": "--foreground",
|
|
@@ -4724,9 +4834,7 @@ function generateFigmaTokens(tokens) {
|
|
|
4724
4834
|
const out = {};
|
|
4725
4835
|
for (const [key, value] of tokens) {
|
|
4726
4836
|
const name = key.replace(/^--/, "").replace(/-/g, ".");
|
|
4727
|
-
const type = /color|bg|surface|text|border|primary|secondary|accent|error|warning|success|info/.test(
|
|
4728
|
-
key
|
|
4729
|
-
) ? "color" : /radius/.test(key) ? "borderRadius" : /shadow/.test(key) ? "shadow" : /gap|space|spacing/.test(key) ? "dimension" : "string";
|
|
4837
|
+
const type = /color|bg|surface|text|border|primary|secondary|accent|error|warning|success|info/.test(key) ? "color" : /radius/.test(key) ? "borderRadius" : /shadow/.test(key) ? "shadow" : /gap|space|spacing/.test(key) ? "dimension" : "string";
|
|
4730
4838
|
out[name] = {
|
|
4731
4839
|
$type: type,
|
|
4732
4840
|
$value: value,
|
|
@@ -4760,7 +4868,11 @@ async function cmdExport(target, projectRoot, options = {}) {
|
|
|
4760
4868
|
}
|
|
4761
4869
|
switch (target) {
|
|
4762
4870
|
case "shadcn": {
|
|
4763
|
-
const cssOut =
|
|
4871
|
+
const cssOut = resolveOutputPath(
|
|
4872
|
+
projectRoot,
|
|
4873
|
+
options.output,
|
|
4874
|
+
join19(projectRoot, "src", "styles", "shadcn-theme.css")
|
|
4875
|
+
);
|
|
4764
4876
|
const jsonOut = join19(projectRoot, "components.json");
|
|
4765
4877
|
ensureDir(cssOut);
|
|
4766
4878
|
writeFileSync12(cssOut, generateShadcnCSS(tokens), "utf-8");
|
|
@@ -4771,7 +4883,11 @@ async function cmdExport(target, projectRoot, options = {}) {
|
|
|
4771
4883
|
break;
|
|
4772
4884
|
}
|
|
4773
4885
|
case "tailwind": {
|
|
4774
|
-
const out =
|
|
4886
|
+
const out = resolveOutputPath(
|
|
4887
|
+
projectRoot,
|
|
4888
|
+
options.output,
|
|
4889
|
+
join19(projectRoot, "tailwind.decantr.config.ts")
|
|
4890
|
+
);
|
|
4775
4891
|
ensureDir(out);
|
|
4776
4892
|
writeFileSync12(out, generateTailwindConfig(tokens), "utf-8");
|
|
4777
4893
|
console.log(`${GREEN5}Exported Tailwind config:${RESET5}`);
|
|
@@ -4779,7 +4895,11 @@ async function cmdExport(target, projectRoot, options = {}) {
|
|
|
4779
4895
|
break;
|
|
4780
4896
|
}
|
|
4781
4897
|
case "css-vars": {
|
|
4782
|
-
const out =
|
|
4898
|
+
const out = resolveOutputPath(
|
|
4899
|
+
projectRoot,
|
|
4900
|
+
options.output,
|
|
4901
|
+
join19(projectRoot, "decantr-tokens.css")
|
|
4902
|
+
);
|
|
4783
4903
|
ensureDir(out);
|
|
4784
4904
|
writeFileSync12(out, generateCSSVars(tokens), "utf-8");
|
|
4785
4905
|
console.log(`${GREEN5}Exported CSS variables:${RESET5}`);
|
|
@@ -4787,7 +4907,11 @@ async function cmdExport(target, projectRoot, options = {}) {
|
|
|
4787
4907
|
break;
|
|
4788
4908
|
}
|
|
4789
4909
|
case "figma-tokens": {
|
|
4790
|
-
const out =
|
|
4910
|
+
const out = resolveOutputPath(
|
|
4911
|
+
projectRoot,
|
|
4912
|
+
options.output,
|
|
4913
|
+
join19(projectRoot, ".decantr", "design", "figma-tokens.json")
|
|
4914
|
+
);
|
|
4791
4915
|
ensureDir(out);
|
|
4792
4916
|
writeFileSync12(out, generateFigmaTokens(tokens), "utf-8");
|
|
4793
4917
|
console.log(`${GREEN5}Exported Figma/Tokens Studio tokens:${RESET5}`);
|
|
@@ -4810,7 +4934,6 @@ import { join as join20 } from "path";
|
|
|
4810
4934
|
var BOLD4 = "\x1B[1m";
|
|
4811
4935
|
var DIM6 = "\x1B[2m";
|
|
4812
4936
|
var RESET6 = "\x1B[0m";
|
|
4813
|
-
var RED5 = "\x1B[31m";
|
|
4814
4937
|
var GREEN6 = "\x1B[32m";
|
|
4815
4938
|
var CYAN3 = "\x1B[36m";
|
|
4816
4939
|
var YELLOW3 = "\x1B[33m";
|
|
@@ -4818,9 +4941,6 @@ var MAGENTA = "\x1B[35m";
|
|
|
4818
4941
|
function success(text) {
|
|
4819
4942
|
return `${GREEN6}${text}${RESET6}`;
|
|
4820
4943
|
}
|
|
4821
|
-
function error(text) {
|
|
4822
|
-
return `${RED5}${text}${RESET6}`;
|
|
4823
|
-
}
|
|
4824
4944
|
function dim(text) {
|
|
4825
4945
|
return `${DIM6}${text}${RESET6}`;
|
|
4826
4946
|
}
|
|
@@ -5036,9 +5156,16 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
5036
5156
|
console.log("");
|
|
5037
5157
|
const essencePath = join20(projectRoot, "decantr.essence.json");
|
|
5038
5158
|
if (existsSync18(essencePath)) {
|
|
5039
|
-
|
|
5040
|
-
console.log(
|
|
5041
|
-
|
|
5159
|
+
const projectFlag = options.projectLabel ? ` --project ${options.projectLabel}` : "";
|
|
5160
|
+
console.log(`${YELLOW3} Decantr is already attached to this project.${RESET6}`);
|
|
5161
|
+
console.log(
|
|
5162
|
+
dim(" decantr magic is greenfield-first; use task-time context for existing apps.")
|
|
5163
|
+
);
|
|
5164
|
+
console.log("");
|
|
5165
|
+
console.log(`${BOLD4}Recommended next steps:${RESET6}`);
|
|
5166
|
+
console.log(` ${cyan(`decantr doctor${projectFlag}`)}`);
|
|
5167
|
+
console.log(` ${cyan(`decantr task <route> "${prompt}"${projectFlag}`)}`);
|
|
5168
|
+
console.log(` ${cyan(`decantr verify --brownfield --local-patterns${projectFlag}`)}`);
|
|
5042
5169
|
return;
|
|
5043
5170
|
}
|
|
5044
5171
|
const detected = detectProject(projectRoot);
|
|
@@ -5053,8 +5180,9 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
5053
5180
|
dim(" Running brownfield analysis instead so you can attach Decantr deliberately.\n")
|
|
5054
5181
|
);
|
|
5055
5182
|
await cmdAnalyze(projectRoot);
|
|
5183
|
+
const projectFlag = options.projectLabel ? ` --project ${options.projectLabel}` : "";
|
|
5056
5184
|
console.log(
|
|
5057
|
-
`${BOLD4}Recommended next step:${RESET6} ${cyan(
|
|
5185
|
+
`${BOLD4}Recommended next step:${RESET6} ${cyan(`decantr init${projectFlag} --existing --accept-proposal`)}`
|
|
5058
5186
|
);
|
|
5059
5187
|
console.log("");
|
|
5060
5188
|
return;
|
|
@@ -5380,7 +5508,7 @@ import {
|
|
|
5380
5508
|
validateLegacyEssenceForMigration
|
|
5381
5509
|
} from "@decantr/essence-spec";
|
|
5382
5510
|
var GREEN7 = "\x1B[32m";
|
|
5383
|
-
var
|
|
5511
|
+
var RED5 = "\x1B[31m";
|
|
5384
5512
|
var YELLOW4 = "\x1B[33m";
|
|
5385
5513
|
var RESET7 = "\x1B[0m";
|
|
5386
5514
|
var DIM7 = "\x1B[2m";
|
|
@@ -5448,13 +5576,13 @@ async function cmdMigrate(projectRoot = process.cwd(), args = []) {
|
|
|
5448
5576
|
const inlineTarget = hasInlineTarget?.split("=")[1];
|
|
5449
5577
|
const requestedTarget = inlineTarget ?? target;
|
|
5450
5578
|
if (requestedTarget !== "v4") {
|
|
5451
|
-
console.error(`${
|
|
5579
|
+
console.error(`${RED5}Usage: decantr migrate --to v4${RESET7}`);
|
|
5452
5580
|
process.exitCode = 1;
|
|
5453
5581
|
return;
|
|
5454
5582
|
}
|
|
5455
5583
|
const essencePath = join21(projectRoot, "decantr.essence.json");
|
|
5456
5584
|
if (!existsSync19(essencePath)) {
|
|
5457
|
-
console.error(`${
|
|
5585
|
+
console.error(`${RED5}No decantr.essence.json found. Run \`decantr init\` first.${RESET7}`);
|
|
5458
5586
|
process.exitCode = 1;
|
|
5459
5587
|
return;
|
|
5460
5588
|
}
|
|
@@ -5465,7 +5593,7 @@ async function cmdMigrate(projectRoot = process.cwd(), args = []) {
|
|
|
5465
5593
|
return;
|
|
5466
5594
|
}
|
|
5467
5595
|
if (!result.success) {
|
|
5468
|
-
console.error(`${
|
|
5596
|
+
console.error(`${RED5}Migration failed: ${result.error}${RESET7}`);
|
|
5469
5597
|
process.exitCode = 1;
|
|
5470
5598
|
return;
|
|
5471
5599
|
}
|
|
@@ -5545,7 +5673,7 @@ function seedOfflineRegistry(projectDir, workspaceRoot) {
|
|
|
5545
5673
|
var BOLD5 = "\x1B[1m";
|
|
5546
5674
|
var DIM8 = "\x1B[2m";
|
|
5547
5675
|
var RESET8 = "\x1B[0m";
|
|
5548
|
-
var
|
|
5676
|
+
var RED6 = "\x1B[31m";
|
|
5549
5677
|
var GREEN8 = "\x1B[32m";
|
|
5550
5678
|
var CYAN4 = "\x1B[36m";
|
|
5551
5679
|
var YELLOW5 = "\x1B[33m";
|
|
@@ -5557,8 +5685,8 @@ ${BOLD5}${text}${RESET8}
|
|
|
5557
5685
|
function success2(text) {
|
|
5558
5686
|
return `${GREEN8}${text}${RESET8}`;
|
|
5559
5687
|
}
|
|
5560
|
-
function
|
|
5561
|
-
return `${
|
|
5688
|
+
function error(text) {
|
|
5689
|
+
return `${RED6}${text}${RESET8}`;
|
|
5562
5690
|
}
|
|
5563
5691
|
function dim2(text) {
|
|
5564
5692
|
return `${DIM8}${text}${RESET8}`;
|
|
@@ -5665,13 +5793,13 @@ async function cmdNewProject(projectName, options) {
|
|
|
5665
5793
|
const shouldBootstrapRuntime = Boolean(bootstrapAdapter && inferredAdoption === "decantr-css");
|
|
5666
5794
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(projectName)) {
|
|
5667
5795
|
console.error(
|
|
5668
|
-
|
|
5796
|
+
error("Invalid project name. Use alphanumeric characters, hyphens, dots, or underscores.")
|
|
5669
5797
|
);
|
|
5670
5798
|
process.exitCode = 1;
|
|
5671
5799
|
return;
|
|
5672
5800
|
}
|
|
5673
5801
|
if (existsSync21(projectDir)) {
|
|
5674
|
-
console.error(
|
|
5802
|
+
console.error(error(`Directory "${projectName}" already exists.`));
|
|
5675
5803
|
process.exitCode = 1;
|
|
5676
5804
|
return;
|
|
5677
5805
|
}
|
|
@@ -5679,7 +5807,7 @@ async function cmdNewProject(projectName, options) {
|
|
|
5679
5807
|
try {
|
|
5680
5808
|
initFlags = buildNewProjectInitArgs(options, inferredAdoption);
|
|
5681
5809
|
} catch (err) {
|
|
5682
|
-
console.error(
|
|
5810
|
+
console.error(error(err.message));
|
|
5683
5811
|
process.exitCode = 1;
|
|
5684
5812
|
return;
|
|
5685
5813
|
}
|
|
@@ -5862,11 +5990,11 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
|
|
|
5862
5990
|
// src/commands/refresh.ts
|
|
5863
5991
|
import { createHash } from "crypto";
|
|
5864
5992
|
import { existsSync as existsSync23, readdirSync as readdirSync7, readFileSync as readFileSync17, statSync as statSync6 } from "fs";
|
|
5865
|
-
import { join as join25 } from "path";
|
|
5993
|
+
import { isAbsolute as isAbsolute2, join as join25, relative as relative6 } from "path";
|
|
5866
5994
|
import { collectMissingPackManifestFiles as collectMissingPackManifestFiles2 } from "@decantr/verifier";
|
|
5867
5995
|
import { isV4 as isV46 } from "@decantr/essence-spec";
|
|
5868
5996
|
var GREEN9 = "\x1B[32m";
|
|
5869
|
-
var
|
|
5997
|
+
var RED7 = "\x1B[31m";
|
|
5870
5998
|
var DIM9 = "\x1B[2m";
|
|
5871
5999
|
var RESET9 = "\x1B[0m";
|
|
5872
6000
|
function hashFile(path) {
|
|
@@ -5917,18 +6045,29 @@ function newestInputMtime(projectRoot) {
|
|
|
5917
6045
|
fileMtimeMs(join25(projectRoot, ".decantr", "project.json"))
|
|
5918
6046
|
);
|
|
5919
6047
|
}
|
|
6048
|
+
function isContractOnlyProject2(projectRoot) {
|
|
6049
|
+
const projectJsonPath = join25(projectRoot, ".decantr", "project.json");
|
|
6050
|
+
if (!existsSync23(projectJsonPath)) return false;
|
|
6051
|
+
try {
|
|
6052
|
+
const projectJson = JSON.parse(readFileSync17(projectJsonPath, "utf-8"));
|
|
6053
|
+
return projectJson.initialized?.adoptionMode === "contract-only";
|
|
6054
|
+
} catch {
|
|
6055
|
+
return false;
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
5920
6058
|
function checkRefreshFreshness(projectRoot) {
|
|
5921
6059
|
const contextDir = join25(projectRoot, ".decantr", "context");
|
|
5922
6060
|
const generated = trackedGeneratedFiles(projectRoot);
|
|
5923
6061
|
const reasons = [];
|
|
6062
|
+
const packHydrationOptional = isContractOnlyProject2(projectRoot);
|
|
5924
6063
|
if (!existsSync23(join25(projectRoot, "DECANTR.md"))) reasons.push("DECANTR.md is missing.");
|
|
5925
6064
|
if (!existsSync23(contextDir)) reasons.push(".decantr/context is missing.");
|
|
5926
6065
|
if (!existsSync23(join25(contextDir, "scaffold.md"))) {
|
|
5927
6066
|
reasons.push(".decantr/context/scaffold.md is missing.");
|
|
5928
6067
|
}
|
|
5929
|
-
if (!existsSync23(join25(contextDir, "pack-manifest.json"))) {
|
|
6068
|
+
if (!packHydrationOptional && !existsSync23(join25(contextDir, "pack-manifest.json"))) {
|
|
5930
6069
|
reasons.push(".decantr/context/pack-manifest.json is missing.");
|
|
5931
|
-
} else {
|
|
6070
|
+
} else if (existsSync23(join25(contextDir, "pack-manifest.json"))) {
|
|
5932
6071
|
const missingPackFiles = collectMissingPackManifestFiles2(projectRoot);
|
|
5933
6072
|
if (missingPackFiles.length > 0) {
|
|
5934
6073
|
reasons.push(
|
|
@@ -5979,10 +6118,19 @@ function summarizeChanges(projectRoot, before, after) {
|
|
|
5979
6118
|
unchanged: unchanged.sort()
|
|
5980
6119
|
};
|
|
5981
6120
|
}
|
|
5982
|
-
function
|
|
6121
|
+
function displayGeneratedPath(summary, file, displayRoot) {
|
|
6122
|
+
if (!displayRoot) return file;
|
|
6123
|
+
const absolutePath = join25(summary.projectRoot, file);
|
|
6124
|
+
const relativePath = relative6(displayRoot, absolutePath).replace(/\\/g, "/");
|
|
6125
|
+
if (relativePath && !relativePath.startsWith("..") && !isAbsolute2(relativePath)) {
|
|
6126
|
+
return relativePath;
|
|
6127
|
+
}
|
|
6128
|
+
return absolutePath;
|
|
6129
|
+
}
|
|
6130
|
+
function printRefreshSummary(summary, displayRoot) {
|
|
5983
6131
|
if (summary.check) {
|
|
5984
6132
|
if (summary.stale) {
|
|
5985
|
-
console.log(`${
|
|
6133
|
+
console.log(`${RED7}Generated Decantr context is stale.${RESET9}`);
|
|
5986
6134
|
for (const reason of summary.reasons) console.log(` ${reason}`);
|
|
5987
6135
|
console.log(`${DIM9}Run \`decantr refresh\` to regenerate derived files.${RESET9}`);
|
|
5988
6136
|
} else {
|
|
@@ -5998,7 +6146,9 @@ function printRefreshSummary(summary) {
|
|
|
5998
6146
|
for (const [label, files] of groups) {
|
|
5999
6147
|
if (files.length === 0) continue;
|
|
6000
6148
|
console.log(`${GREEN9}${label}:${RESET9}`);
|
|
6001
|
-
for (const file of files)
|
|
6149
|
+
for (const file of files) {
|
|
6150
|
+
console.log(` ${DIM9}${displayGeneratedPath(summary, file, displayRoot)}${RESET9}`);
|
|
6151
|
+
}
|
|
6002
6152
|
}
|
|
6003
6153
|
if (groups.every(([, files]) => files.length === 0)) {
|
|
6004
6154
|
console.log(`${GREEN9}Generated files were already current.${RESET9}`);
|
|
@@ -6007,7 +6157,7 @@ function printRefreshSummary(summary) {
|
|
|
6007
6157
|
async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
6008
6158
|
const essencePath = join25(projectRoot, "decantr.essence.json");
|
|
6009
6159
|
if (!existsSync23(essencePath)) {
|
|
6010
|
-
console.error(`${
|
|
6160
|
+
console.error(`${RED7}No decantr.essence.json found. Run \`decantr init\` first.${RESET9}`);
|
|
6011
6161
|
process.exitCode = 1;
|
|
6012
6162
|
return;
|
|
6013
6163
|
}
|
|
@@ -6017,14 +6167,14 @@ async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
|
6017
6167
|
const parsed = JSON.parse(raw);
|
|
6018
6168
|
if (!isV46(parsed)) {
|
|
6019
6169
|
console.error(
|
|
6020
|
-
`${
|
|
6170
|
+
`${RED7}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET9}`
|
|
6021
6171
|
);
|
|
6022
6172
|
process.exitCode = 1;
|
|
6023
6173
|
return;
|
|
6024
6174
|
}
|
|
6025
6175
|
essence = parsed;
|
|
6026
6176
|
} catch (e) {
|
|
6027
|
-
console.error(`${
|
|
6177
|
+
console.error(`${RED7}Could not read essence: ${e.message}${RESET9}`);
|
|
6028
6178
|
process.exitCode = 1;
|
|
6029
6179
|
return;
|
|
6030
6180
|
}
|
|
@@ -6033,7 +6183,7 @@ async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
|
6033
6183
|
if (options.json) {
|
|
6034
6184
|
console.log(JSON.stringify(summary2, null, 2));
|
|
6035
6185
|
} else {
|
|
6036
|
-
printRefreshSummary(summary2);
|
|
6186
|
+
printRefreshSummary(summary2, options.displayRoot);
|
|
6037
6187
|
}
|
|
6038
6188
|
if (summary2.stale) process.exitCode = 1;
|
|
6039
6189
|
return;
|
|
@@ -6050,17 +6200,19 @@ async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
|
6050
6200
|
if (options.json) {
|
|
6051
6201
|
console.log(JSON.stringify({ ...summary, result }, null, 2));
|
|
6052
6202
|
} else if (options.listChanges) {
|
|
6053
|
-
printRefreshSummary(summary);
|
|
6203
|
+
printRefreshSummary(summary, options.displayRoot);
|
|
6054
6204
|
} else {
|
|
6055
6205
|
console.log(`${GREEN9}Regenerated:${RESET9}`);
|
|
6056
|
-
console.log(
|
|
6206
|
+
console.log(
|
|
6207
|
+
` ${DIM9}${displayGeneratedPath(summary, "DECANTR.md", options.displayRoot)}${RESET9}`
|
|
6208
|
+
);
|
|
6057
6209
|
for (const css of result.cssFiles) {
|
|
6058
6210
|
const rel2 = css.replace(projectRoot + "/", "");
|
|
6059
|
-
console.log(` ${DIM9}${rel2}${RESET9}`);
|
|
6211
|
+
console.log(` ${DIM9}${displayGeneratedPath(summary, rel2, options.displayRoot)}${RESET9}`);
|
|
6060
6212
|
}
|
|
6061
6213
|
for (const ctx of result.contextFiles) {
|
|
6062
6214
|
const rel2 = ctx.replace(projectRoot + "/", "");
|
|
6063
|
-
console.log(` ${DIM9}${rel2}${RESET9}`);
|
|
6215
|
+
console.log(` ${DIM9}${displayGeneratedPath(summary, rel2, options.displayRoot)}${RESET9}`);
|
|
6064
6216
|
}
|
|
6065
6217
|
}
|
|
6066
6218
|
console.log("");
|
|
@@ -6072,7 +6224,7 @@ import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync14 } from "fs";
|
|
|
6072
6224
|
import { join as join26 } from "path";
|
|
6073
6225
|
import { API_CONTENT_TYPES, RegistryAPIClient as RegistryAPIClient2 } from "@decantr/registry";
|
|
6074
6226
|
var GREEN10 = "\x1B[32m";
|
|
6075
|
-
var
|
|
6227
|
+
var RED8 = "\x1B[31m";
|
|
6076
6228
|
var DIM10 = "\x1B[2m";
|
|
6077
6229
|
var CYAN5 = "\x1B[36m";
|
|
6078
6230
|
var YELLOW6 = "\x1B[33m";
|
|
@@ -6086,13 +6238,13 @@ async function cmdRegistryMirror(projectRoot, options = {}) {
|
|
|
6086
6238
|
});
|
|
6087
6239
|
const healthy = await apiClient.checkHealth();
|
|
6088
6240
|
if (!healthy) {
|
|
6089
|
-
console.error(`${
|
|
6241
|
+
console.error(`${RED8}Registry API is unavailable. Check your connection.${RESET10}`);
|
|
6090
6242
|
process.exitCode = 1;
|
|
6091
6243
|
return;
|
|
6092
6244
|
}
|
|
6093
6245
|
const types = options.type ? [options.type] : ALL_CONTENT_TYPES;
|
|
6094
6246
|
if (options.type && !ALL_CONTENT_TYPES.includes(options.type)) {
|
|
6095
|
-
console.error(`${
|
|
6247
|
+
console.error(`${RED8}Unknown content type: ${options.type}${RESET10}`);
|
|
6096
6248
|
console.error(`${DIM10}Valid types: ${ALL_CONTENT_TYPES.join(", ")}${RESET10}`);
|
|
6097
6249
|
process.exitCode = 1;
|
|
6098
6250
|
return;
|
|
@@ -6127,7 +6279,7 @@ Mirroring registry content to ${DIM10}.decantr/cache/${RESET10}
|
|
|
6127
6279
|
console.log(` ${GREEN10}\u2713${RESET10} ${type}: ${CYAN5}${itemCount}${RESET10} items`);
|
|
6128
6280
|
} catch (e) {
|
|
6129
6281
|
failed.push(type);
|
|
6130
|
-
console.log(` ${
|
|
6282
|
+
console.log(` ${RED8}\u2717${RESET10} ${type}: ${e.message}`);
|
|
6131
6283
|
}
|
|
6132
6284
|
}
|
|
6133
6285
|
const manifest = {
|
|
@@ -6156,13 +6308,13 @@ import { existsSync as existsSync25, readFileSync as readFileSync18, rmSync as r
|
|
|
6156
6308
|
import { join as join27 } from "path";
|
|
6157
6309
|
import { isV4 as isV47 } from "@decantr/essence-spec";
|
|
6158
6310
|
var GREEN11 = "\x1B[32m";
|
|
6159
|
-
var
|
|
6311
|
+
var RED9 = "\x1B[31m";
|
|
6160
6312
|
var DIM11 = "\x1B[2m";
|
|
6161
6313
|
var RESET11 = "\x1B[0m";
|
|
6162
6314
|
function readV4Essence2(projectRoot) {
|
|
6163
6315
|
const essencePath = join27(projectRoot, "decantr.essence.json");
|
|
6164
6316
|
if (!existsSync25(essencePath)) {
|
|
6165
|
-
console.error(`${
|
|
6317
|
+
console.error(`${RED9}No decantr.essence.json found. Run \`decantr init\` first.${RESET11}`);
|
|
6166
6318
|
process.exitCode = 1;
|
|
6167
6319
|
return null;
|
|
6168
6320
|
}
|
|
@@ -6170,13 +6322,13 @@ function readV4Essence2(projectRoot) {
|
|
|
6170
6322
|
try {
|
|
6171
6323
|
parsed = JSON.parse(readFileSync18(essencePath, "utf-8"));
|
|
6172
6324
|
} catch (e) {
|
|
6173
|
-
console.error(`${
|
|
6325
|
+
console.error(`${RED9}Could not read essence: ${e.message}${RESET11}`);
|
|
6174
6326
|
process.exitCode = 1;
|
|
6175
6327
|
return null;
|
|
6176
6328
|
}
|
|
6177
6329
|
if (!isV47(parsed)) {
|
|
6178
6330
|
console.error(
|
|
6179
|
-
`${
|
|
6331
|
+
`${RED9}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET11}`
|
|
6180
6332
|
);
|
|
6181
6333
|
process.exitCode = 1;
|
|
6182
6334
|
return null;
|
|
@@ -6186,6 +6338,15 @@ function readV4Essence2(projectRoot) {
|
|
|
6186
6338
|
function writeEssence2(essencePath, essence) {
|
|
6187
6339
|
writeFileSync15(essencePath, JSON.stringify(essence, null, 2) + "\n");
|
|
6188
6340
|
}
|
|
6341
|
+
function readFlagValue2(args, name) {
|
|
6342
|
+
const prefix = `--${name}=`;
|
|
6343
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
6344
|
+
const arg = args[index];
|
|
6345
|
+
if (arg === `--${name}` && args[index + 1]) return args[index + 1];
|
|
6346
|
+
if (arg.startsWith(prefix)) return arg.slice(prefix.length);
|
|
6347
|
+
}
|
|
6348
|
+
return void 0;
|
|
6349
|
+
}
|
|
6189
6350
|
function recomputeGlobalFeatures(essence) {
|
|
6190
6351
|
const all = /* @__PURE__ */ new Set();
|
|
6191
6352
|
for (const section of essence.blueprint.sections || []) {
|
|
@@ -6208,7 +6369,7 @@ function removeRoutes(essence, sectionId, pageId) {
|
|
|
6208
6369
|
}
|
|
6209
6370
|
async function cmdRemoveSection(sectionId, args, projectRoot = process.cwd()) {
|
|
6210
6371
|
if (!sectionId) {
|
|
6211
|
-
console.error(`${
|
|
6372
|
+
console.error(`${RED9}Usage: decantr remove section <sectionId>${RESET11}`);
|
|
6212
6373
|
process.exitCode = 1;
|
|
6213
6374
|
return;
|
|
6214
6375
|
}
|
|
@@ -6218,7 +6379,7 @@ async function cmdRemoveSection(sectionId, args, projectRoot = process.cwd()) {
|
|
|
6218
6379
|
const sections = essence.blueprint.sections;
|
|
6219
6380
|
const idx = sections.findIndex((s) => s.id === sectionId);
|
|
6220
6381
|
if (idx === -1) {
|
|
6221
|
-
console.error(`${
|
|
6382
|
+
console.error(`${RED9}Section "${sectionId}" not found.${RESET11}`);
|
|
6222
6383
|
console.error(`${DIM11}Available sections: ${sections.map((s) => s.id).join(", ")}${RESET11}`);
|
|
6223
6384
|
process.exitCode = 1;
|
|
6224
6385
|
return;
|
|
@@ -6240,7 +6401,7 @@ async function cmdRemoveSection(sectionId, args, projectRoot = process.cwd()) {
|
|
|
6240
6401
|
}
|
|
6241
6402
|
async function cmdRemovePage(path, args, projectRoot = process.cwd()) {
|
|
6242
6403
|
if (!path || !path.includes("/")) {
|
|
6243
|
-
console.error(`${
|
|
6404
|
+
console.error(`${RED9}Usage: decantr remove page <section>/<page>${RESET11}`);
|
|
6244
6405
|
console.error(`${DIM11}Example: decantr remove page settings/notifications${RESET11}`);
|
|
6245
6406
|
process.exitCode = 1;
|
|
6246
6407
|
return;
|
|
@@ -6252,14 +6413,14 @@ async function cmdRemovePage(path, args, projectRoot = process.cwd()) {
|
|
|
6252
6413
|
const sections = essence.blueprint.sections;
|
|
6253
6414
|
const section = sections.find((s) => s.id === sectionId);
|
|
6254
6415
|
if (!section) {
|
|
6255
|
-
console.error(`${
|
|
6416
|
+
console.error(`${RED9}Section "${sectionId}" not found.${RESET11}`);
|
|
6256
6417
|
console.error(`${DIM11}Available sections: ${sections.map((s) => s.id).join(", ")}${RESET11}`);
|
|
6257
6418
|
process.exitCode = 1;
|
|
6258
6419
|
return;
|
|
6259
6420
|
}
|
|
6260
6421
|
const pageIdx = section.pages.findIndex((p) => p.id === pageId);
|
|
6261
6422
|
if (pageIdx === -1) {
|
|
6262
|
-
console.error(`${
|
|
6423
|
+
console.error(`${RED9}Page "${pageId}" not found in section "${sectionId}".${RESET11}`);
|
|
6263
6424
|
console.error(`${DIM11}Available pages: ${section.pages.map((p) => p.id).join(", ")}${RESET11}`);
|
|
6264
6425
|
process.exitCode = 1;
|
|
6265
6426
|
return;
|
|
@@ -6276,7 +6437,7 @@ async function cmdRemovePage(path, args, projectRoot = process.cwd()) {
|
|
|
6276
6437
|
}
|
|
6277
6438
|
async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
6278
6439
|
if (!feature) {
|
|
6279
|
-
console.error(`${
|
|
6440
|
+
console.error(`${RED9}Usage: decantr remove feature <feature> [--section <sectionId>]${RESET11}`);
|
|
6280
6441
|
process.exitCode = 1;
|
|
6281
6442
|
return;
|
|
6282
6443
|
}
|
|
@@ -6284,15 +6445,12 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
6284
6445
|
if (!loaded) return;
|
|
6285
6446
|
const { essence, essencePath } = loaded;
|
|
6286
6447
|
let sectionId;
|
|
6287
|
-
|
|
6288
|
-
if (sectionIdx !== -1 && args[sectionIdx + 1]) {
|
|
6289
|
-
sectionId = args[sectionIdx + 1];
|
|
6290
|
-
}
|
|
6448
|
+
sectionId = readFlagValue2(args, "section");
|
|
6291
6449
|
if (sectionId) {
|
|
6292
6450
|
const sections = essence.blueprint.sections;
|
|
6293
6451
|
const section = sections.find((s) => s.id === sectionId);
|
|
6294
6452
|
if (!section) {
|
|
6295
|
-
console.error(`${
|
|
6453
|
+
console.error(`${RED9}Section "${sectionId}" not found.${RESET11}`);
|
|
6296
6454
|
console.error(`${DIM11}Available sections: ${sections.map((s) => s.id).join(", ")}${RESET11}`);
|
|
6297
6455
|
process.exitCode = 1;
|
|
6298
6456
|
return;
|
|
@@ -6320,7 +6478,7 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
6320
6478
|
import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "fs";
|
|
6321
6479
|
import { join as join28 } from "path";
|
|
6322
6480
|
var GREEN12 = "\x1B[32m";
|
|
6323
|
-
var
|
|
6481
|
+
var RED10 = "\x1B[31m";
|
|
6324
6482
|
var YELLOW7 = "\x1B[33m";
|
|
6325
6483
|
var RESET12 = "\x1B[0m";
|
|
6326
6484
|
var DIM12 = "\x1B[2m";
|
|
@@ -6339,12 +6497,12 @@ async function cmdSyncDrift(projectRoot = process.cwd()) {
|
|
|
6339
6497
|
try {
|
|
6340
6498
|
entries = JSON.parse(readFileSync19(driftLogPath, "utf-8"));
|
|
6341
6499
|
} catch {
|
|
6342
|
-
console.error(`${
|
|
6500
|
+
console.error(`${RED10}Could not parse drift-log.json${RESET12}`);
|
|
6343
6501
|
process.exitCode = 1;
|
|
6344
6502
|
return;
|
|
6345
6503
|
}
|
|
6346
6504
|
if (!Array.isArray(entries)) {
|
|
6347
|
-
console.error(`${
|
|
6505
|
+
console.error(`${RED10}drift-log.json is not an array${RESET12}`);
|
|
6348
6506
|
process.exitCode = 1;
|
|
6349
6507
|
return;
|
|
6350
6508
|
}
|
|
@@ -6362,7 +6520,7 @@ ${BOLD6}Unresolved Drift Entries (${unresolved.length})${RESET12}
|
|
|
6362
6520
|
`);
|
|
6363
6521
|
for (let i = 0; i < unresolved.length; i++) {
|
|
6364
6522
|
const entry = unresolved[i];
|
|
6365
|
-
const severityColor = entry.severity === "error" ?
|
|
6523
|
+
const severityColor = entry.severity === "error" ? RED10 : YELLOW7;
|
|
6366
6524
|
const icon = entry.severity === "error" ? "x" : "!";
|
|
6367
6525
|
console.log(
|
|
6368
6526
|
` ${severityColor}${icon}${RESET12} ${BOLD6}#${i + 1}${RESET12} [${entry.rule}] ${entry.message}`
|
|
@@ -6645,7 +6803,7 @@ import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSy
|
|
|
6645
6803
|
import { join as join29 } from "path";
|
|
6646
6804
|
import { isV4 as isV48 } from "@decantr/essence-spec";
|
|
6647
6805
|
var GREEN14 = "\x1B[32m";
|
|
6648
|
-
var
|
|
6806
|
+
var RED11 = "\x1B[31m";
|
|
6649
6807
|
var YELLOW8 = "\x1B[33m";
|
|
6650
6808
|
var DIM14 = "\x1B[2m";
|
|
6651
6809
|
var RESET14 = "\x1B[0m";
|
|
@@ -6654,14 +6812,14 @@ var VALID_THEME_MODES = ["light", "dark", "auto"];
|
|
|
6654
6812
|
async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
6655
6813
|
if (!themeName) {
|
|
6656
6814
|
console.error(
|
|
6657
|
-
`${
|
|
6815
|
+
`${RED11}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET14}`
|
|
6658
6816
|
);
|
|
6659
6817
|
process.exitCode = 1;
|
|
6660
6818
|
return;
|
|
6661
6819
|
}
|
|
6662
6820
|
const essencePath = join29(projectRoot, "decantr.essence.json");
|
|
6663
6821
|
if (!existsSync27(essencePath)) {
|
|
6664
|
-
console.error(`${
|
|
6822
|
+
console.error(`${RED11}No decantr.essence.json found. Run \`decantr init\` first.${RESET14}`);
|
|
6665
6823
|
process.exitCode = 1;
|
|
6666
6824
|
return;
|
|
6667
6825
|
}
|
|
@@ -6669,13 +6827,13 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
6669
6827
|
try {
|
|
6670
6828
|
parsed = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
6671
6829
|
} catch (e) {
|
|
6672
|
-
console.error(`${
|
|
6830
|
+
console.error(`${RED11}Could not read essence: ${e.message}${RESET14}`);
|
|
6673
6831
|
process.exitCode = 1;
|
|
6674
6832
|
return;
|
|
6675
6833
|
}
|
|
6676
6834
|
if (!isV48(parsed)) {
|
|
6677
6835
|
console.error(
|
|
6678
|
-
`${
|
|
6836
|
+
`${RED11}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET14}`
|
|
6679
6837
|
);
|
|
6680
6838
|
process.exitCode = 1;
|
|
6681
6839
|
return;
|
|
@@ -6697,14 +6855,14 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
6697
6855
|
}
|
|
6698
6856
|
if (shape && !VALID_THEME_SHAPES.includes(shape)) {
|
|
6699
6857
|
console.error(
|
|
6700
|
-
`${
|
|
6858
|
+
`${RED11}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET14}`
|
|
6701
6859
|
);
|
|
6702
6860
|
process.exitCode = 1;
|
|
6703
6861
|
return;
|
|
6704
6862
|
}
|
|
6705
6863
|
if (mode && !VALID_THEME_MODES.includes(mode)) {
|
|
6706
6864
|
console.error(
|
|
6707
|
-
`${
|
|
6865
|
+
`${RED11}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET14}`
|
|
6708
6866
|
);
|
|
6709
6867
|
process.exitCode = 1;
|
|
6710
6868
|
return;
|
|
@@ -7208,7 +7366,7 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7208
7366
|
var BOLD9 = "\x1B[1m";
|
|
7209
7367
|
var DIM16 = "\x1B[2m";
|
|
7210
7368
|
var RESET16 = "\x1B[0m";
|
|
7211
|
-
var
|
|
7369
|
+
var RED12 = "\x1B[31m";
|
|
7212
7370
|
var GREEN16 = "\x1B[32m";
|
|
7213
7371
|
var CYAN9 = "\x1B[36m";
|
|
7214
7372
|
var YELLOW10 = "\x1B[33m";
|
|
@@ -7220,8 +7378,8 @@ ${BOLD9}${text}${RESET16}
|
|
|
7220
7378
|
function success3(text) {
|
|
7221
7379
|
return `${GREEN16}${text}${RESET16}`;
|
|
7222
7380
|
}
|
|
7223
|
-
function
|
|
7224
|
-
return `${
|
|
7381
|
+
function error2(text) {
|
|
7382
|
+
return `${RED12}${text}${RESET16}`;
|
|
7225
7383
|
}
|
|
7226
7384
|
function dim3(text) {
|
|
7227
7385
|
return `${DIM16}${text}${RESET16}`;
|
|
@@ -7731,7 +7889,7 @@ function getPublicAPIClient() {
|
|
|
7731
7889
|
});
|
|
7732
7890
|
}
|
|
7733
7891
|
function resolveUserPath(inputPath, cwd = process.cwd()) {
|
|
7734
|
-
return
|
|
7892
|
+
return isAbsolute3(inputPath) ? inputPath : resolve4(cwd, inputPath);
|
|
7735
7893
|
}
|
|
7736
7894
|
function extractHostedAssetPaths(indexHtml) {
|
|
7737
7895
|
const assetPaths = /* @__PURE__ */ new Set();
|
|
@@ -7944,18 +8102,13 @@ async function printRegistryIntelligenceSummary(namespace, jsonOutput = false) {
|
|
|
7944
8102
|
}
|
|
7945
8103
|
}
|
|
7946
8104
|
async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
7947
|
-
const
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
}
|
|
7952
|
-
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
7953
|
-
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
7954
|
-
const contextDir = join31(dirname5(resolvedPath), ".decantr", "context");
|
|
8105
|
+
const { resolvedPath, bundle, contextDir } = await compileHostedExecutionPackBundle(
|
|
8106
|
+
essencePath,
|
|
8107
|
+
namespace
|
|
8108
|
+
);
|
|
7955
8109
|
let writtenContextPaths = [];
|
|
7956
8110
|
if (writeContext) {
|
|
7957
|
-
|
|
7958
|
-
const written = writeExecutionPackBundleArtifacts(
|
|
8111
|
+
const written = writeHostedExecutionPackContextArtifacts(
|
|
7959
8112
|
contextDir,
|
|
7960
8113
|
bundle
|
|
7961
8114
|
);
|
|
@@ -7990,6 +8143,21 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
7990
8143
|
console.log(` ${cyan3(route.path)} -> ${pageLabel} [${patterns}]`);
|
|
7991
8144
|
}
|
|
7992
8145
|
}
|
|
8146
|
+
async function compileHostedExecutionPackBundle(essencePath, namespace) {
|
|
8147
|
+
const client = getPublicAPIClient();
|
|
8148
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8149
|
+
if (!existsSync29(resolvedPath)) {
|
|
8150
|
+
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8151
|
+
}
|
|
8152
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8153
|
+
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
8154
|
+
const contextDir = join31(dirname5(resolvedPath), ".decantr", "context");
|
|
8155
|
+
return { resolvedPath, bundle, contextDir };
|
|
8156
|
+
}
|
|
8157
|
+
function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
|
|
8158
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8159
|
+
return writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
8160
|
+
}
|
|
7993
8161
|
function resolvePagePackIdForRoute(essencePath, route) {
|
|
7994
8162
|
if (!existsSync29(essencePath)) {
|
|
7995
8163
|
throw new Error(`Essence file not found at ${essencePath}`);
|
|
@@ -8315,22 +8483,22 @@ function patternCandidateFromRegistryItem(item, source) {
|
|
|
8315
8483
|
{ source, slug }
|
|
8316
8484
|
);
|
|
8317
8485
|
}
|
|
8318
|
-
function readSuggestCodeContext(route, file) {
|
|
8486
|
+
function readSuggestCodeContext(projectRoot, route, file) {
|
|
8319
8487
|
const pieces = [];
|
|
8320
8488
|
if (file) {
|
|
8321
|
-
const resolved =
|
|
8489
|
+
const resolved = isAbsolute3(file) ? file : join31(projectRoot, file);
|
|
8322
8490
|
if (existsSync29(resolved)) {
|
|
8323
8491
|
pieces.push(readFileSync22(resolved, "utf-8"));
|
|
8324
8492
|
}
|
|
8325
8493
|
}
|
|
8326
8494
|
if (route) {
|
|
8327
|
-
const analysisPath = join31(
|
|
8495
|
+
const analysisPath = join31(projectRoot, ".decantr", "analysis.json");
|
|
8328
8496
|
if (existsSync29(analysisPath)) {
|
|
8329
8497
|
try {
|
|
8330
8498
|
const analysis = JSON.parse(readFileSync22(analysisPath, "utf-8"));
|
|
8331
8499
|
const routeEntry = analysis.routes?.routes?.find((entry) => entry.path === route);
|
|
8332
8500
|
if (routeEntry?.file) {
|
|
8333
|
-
const resolved = join31(
|
|
8501
|
+
const resolved = join31(projectRoot, routeEntry.file);
|
|
8334
8502
|
if (existsSync29(resolved)) {
|
|
8335
8503
|
pieces.push(readFileSync22(resolved, "utf-8"));
|
|
8336
8504
|
}
|
|
@@ -8341,6 +8509,28 @@ function readSuggestCodeContext(route, file) {
|
|
|
8341
8509
|
}
|
|
8342
8510
|
return pieces.join("\n\n").slice(0, 2e4);
|
|
8343
8511
|
}
|
|
8512
|
+
function localPatternMatches(projectRoot, query) {
|
|
8513
|
+
if (!projectRoot) return [];
|
|
8514
|
+
const pack = readLocalPatternPack(projectRoot);
|
|
8515
|
+
const patterns = Array.isArray(pack?.patterns) ? pack.patterns : [];
|
|
8516
|
+
const queryTerms = query.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 1);
|
|
8517
|
+
if (queryTerms.length === 0) return [];
|
|
8518
|
+
return patterns.map((pattern) => {
|
|
8519
|
+
const id = typeof pattern.id === "string" ? pattern.id : "local-pattern";
|
|
8520
|
+
const label = typeof pattern.label === "string" ? pattern.label : null;
|
|
8521
|
+
const role = typeof pattern.role === "string" ? pattern.role : null;
|
|
8522
|
+
const haystack = [
|
|
8523
|
+
id,
|
|
8524
|
+
label,
|
|
8525
|
+
role,
|
|
8526
|
+
typeof pattern.decide === "string" ? pattern.decide : null,
|
|
8527
|
+
...Array.isArray(pattern.appliesTo) ? pattern.appliesTo : [],
|
|
8528
|
+
...Array.isArray(pattern.componentPaths) ? pattern.componentPaths : []
|
|
8529
|
+
].filter((entry) => typeof entry === "string").join(" ").toLowerCase();
|
|
8530
|
+
const score = queryTerms.reduce((sum, term) => sum + (haystack.includes(term) ? 1 : 0), 0);
|
|
8531
|
+
return { id, label, role, score };
|
|
8532
|
+
}).filter((match) => match.score > 0).sort((a, b) => b.score - a.score || a.id.localeCompare(b.id)).slice(0, 5);
|
|
8533
|
+
}
|
|
8344
8534
|
async function loadPatternDiscoveryCandidates(registryClient) {
|
|
8345
8535
|
const candidates = [];
|
|
8346
8536
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8389,9 +8579,9 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8389
8579
|
}
|
|
8390
8580
|
}
|
|
8391
8581
|
const registryClient = new RegistryClient({
|
|
8392
|
-
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
8582
|
+
cacheDir: join31(options.projectRoot ?? process.cwd(), ".decantr", "cache")
|
|
8393
8583
|
});
|
|
8394
|
-
const code = options.fromCode || options.file ? readSuggestCodeContext(options.route, options.file) : "";
|
|
8584
|
+
const code = options.fromCode || options.file ? readSuggestCodeContext(options.projectRoot ?? process.cwd(), options.route, options.file) : "";
|
|
8395
8585
|
const candidates = await loadPatternDiscoveryCandidates(registryClient);
|
|
8396
8586
|
const matches = rankPatternCandidates(
|
|
8397
8587
|
{
|
|
@@ -8422,6 +8612,16 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8422
8612
|
`Pattern suggestions for "${query}"${contextBits.length > 0 ? ` (${contextBits.join(", ")})` : ""}`
|
|
8423
8613
|
)
|
|
8424
8614
|
);
|
|
8615
|
+
const localMatches = localPatternMatches(options.projectRoot, query);
|
|
8616
|
+
if (localMatches.length > 0) {
|
|
8617
|
+
console.log(`${BOLD9}Project-owned local law:${RESET16}`);
|
|
8618
|
+
for (const match of localMatches) {
|
|
8619
|
+
const details = [match.label, match.role].filter(Boolean).join(" | ");
|
|
8620
|
+
console.log(` ${cyan3(match.id)}${details ? ` ${dim3(details)}` : ""}`);
|
|
8621
|
+
}
|
|
8622
|
+
console.log("");
|
|
8623
|
+
console.log(`${BOLD9}Registry patterns:${RESET16}`);
|
|
8624
|
+
}
|
|
8425
8625
|
for (const match of matches.slice(0, 8)) {
|
|
8426
8626
|
const candidate = match.candidate;
|
|
8427
8627
|
const slug = candidate.slug || candidate.id;
|
|
@@ -8445,7 +8645,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8445
8645
|
}
|
|
8446
8646
|
async function cmdGet(type, id) {
|
|
8447
8647
|
if (!isGetContentType(type)) {
|
|
8448
|
-
console.error(
|
|
8648
|
+
console.error(error2(`Invalid type "${type}". Must be one of: ${GET_CONTENT_TYPES.join(", ")}`));
|
|
8449
8649
|
process.exitCode = 1;
|
|
8450
8650
|
return;
|
|
8451
8651
|
}
|
|
@@ -8463,7 +8663,7 @@ async function cmdGet(type, id) {
|
|
|
8463
8663
|
console.log(JSON.stringify(bundled.data, null, 2));
|
|
8464
8664
|
return;
|
|
8465
8665
|
}
|
|
8466
|
-
console.error(
|
|
8666
|
+
console.error(error2(`${type} "${id}" not found.`));
|
|
8467
8667
|
process.exitCode = 1;
|
|
8468
8668
|
return;
|
|
8469
8669
|
}
|
|
@@ -8473,7 +8673,7 @@ async function cmdValidate(path) {
|
|
|
8473
8673
|
try {
|
|
8474
8674
|
raw = readFileSync22(essencePath, "utf-8");
|
|
8475
8675
|
} catch {
|
|
8476
|
-
console.error(
|
|
8676
|
+
console.error(error2(`Could not read ${essencePath}`));
|
|
8477
8677
|
process.exitCode = 1;
|
|
8478
8678
|
return;
|
|
8479
8679
|
}
|
|
@@ -8481,7 +8681,7 @@ async function cmdValidate(path) {
|
|
|
8481
8681
|
try {
|
|
8482
8682
|
essence = JSON.parse(raw);
|
|
8483
8683
|
} catch (e) {
|
|
8484
|
-
console.error(
|
|
8684
|
+
console.error(error2(`Invalid JSON: ${e.message}`));
|
|
8485
8685
|
process.exitCode = 1;
|
|
8486
8686
|
return;
|
|
8487
8687
|
}
|
|
@@ -8491,9 +8691,9 @@ async function cmdValidate(path) {
|
|
|
8491
8691
|
if (result.valid) {
|
|
8492
8692
|
console.log(success3(`Essence is valid (${detectedVersion}).`));
|
|
8493
8693
|
} else {
|
|
8494
|
-
console.error(
|
|
8694
|
+
console.error(error2("Validation failed:"));
|
|
8495
8695
|
for (const err of result.errors) {
|
|
8496
|
-
console.error(` ${
|
|
8696
|
+
console.error(` ${RED12}${err}${RESET16}`);
|
|
8497
8697
|
}
|
|
8498
8698
|
process.exitCode = 1;
|
|
8499
8699
|
return;
|
|
@@ -8532,7 +8732,7 @@ async function cmdValidate(path) {
|
|
|
8532
8732
|
async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet) {
|
|
8533
8733
|
if (!isApiContentType(type)) {
|
|
8534
8734
|
console.error(
|
|
8535
|
-
|
|
8735
|
+
error2(`Invalid type "${type}". Must be one of: ${LIST_CONTENT_TYPES.join(", ")}`)
|
|
8536
8736
|
);
|
|
8537
8737
|
process.exitCode = 1;
|
|
8538
8738
|
return;
|
|
@@ -8694,7 +8894,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
8694
8894
|
const proposal = readBrownfieldProposal(input.projectRoot);
|
|
8695
8895
|
if (!proposal) {
|
|
8696
8896
|
console.log(
|
|
8697
|
-
|
|
8897
|
+
error2(`No observed brownfield proposal found at ${proposalPath(input.projectRoot)}.`)
|
|
8698
8898
|
);
|
|
8699
8899
|
console.log(
|
|
8700
8900
|
dim3(
|
|
@@ -8709,7 +8909,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
8709
8909
|
let essence;
|
|
8710
8910
|
let backupPath = null;
|
|
8711
8911
|
if (input.mode === "accept" && hasEssence) {
|
|
8712
|
-
console.log(
|
|
8912
|
+
console.log(error2("Refusing to accept proposal over an existing decantr.essence.json."));
|
|
8713
8913
|
console.log(
|
|
8714
8914
|
dim3(
|
|
8715
8915
|
"Use `--merge-proposal` to preserve the existing contract or `--replace-essence` for an explicit destructive replacement."
|
|
@@ -8722,7 +8922,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
8722
8922
|
const existing = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8723
8923
|
if (!isV49(existing)) {
|
|
8724
8924
|
console.log(
|
|
8725
|
-
|
|
8925
|
+
error2(
|
|
8726
8926
|
"Existing essence is not v4. Run `decantr migrate --to v4` before merging a brownfield proposal."
|
|
8727
8927
|
)
|
|
8728
8928
|
);
|
|
@@ -8736,10 +8936,10 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
8736
8936
|
const validation = validateEssence2(essence);
|
|
8737
8937
|
if (!validation.valid) {
|
|
8738
8938
|
console.log(
|
|
8739
|
-
|
|
8939
|
+
error2("Brownfield proposal produced an invalid Decantr essence. No files were changed.")
|
|
8740
8940
|
);
|
|
8741
8941
|
for (const validationError of validation.errors) {
|
|
8742
|
-
console.log(` ${
|
|
8942
|
+
console.log(` ${RED12}${validationError}${RESET16}`);
|
|
8743
8943
|
}
|
|
8744
8944
|
process.exitCode = 1;
|
|
8745
8945
|
return;
|
|
@@ -8785,13 +8985,24 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
8785
8985
|
}
|
|
8786
8986
|
const appliedRuleFiles = input.assistantBridge === "apply" ? applyAssistantBridge(input.projectRoot, input.detected) : [];
|
|
8787
8987
|
console.log(success3("\nBrownfield proposal accepted.\n"));
|
|
8988
|
+
const projectLabel = input.workspaceInfo.appRoot !== input.workspaceInfo.workspaceRoot ? relative7(input.workspaceInfo.workspaceRoot, input.workspaceInfo.appRoot).replace(/\\/g, "/") : void 0;
|
|
8788
8989
|
console.log(" Files created/updated:");
|
|
8789
|
-
console.log(
|
|
8790
|
-
|
|
8791
|
-
|
|
8792
|
-
console.log(
|
|
8990
|
+
console.log(
|
|
8991
|
+
` ${cyan3(displayProjectPath(input.workspaceInfo, "decantr.essence.json"))} Observed brownfield contract`
|
|
8992
|
+
);
|
|
8993
|
+
console.log(
|
|
8994
|
+
` ${cyan3(displayProjectPath(input.workspaceInfo, "DECANTR.md"))} Reconciled assistant guidance`
|
|
8995
|
+
);
|
|
8996
|
+
console.log(
|
|
8997
|
+
` ${cyan3(displayProjectPath(input.workspaceInfo, ".decantr/project.json"))} Brownfield attach metadata`
|
|
8998
|
+
);
|
|
8999
|
+
console.log(
|
|
9000
|
+
` ${cyan3(displayProjectPath(input.workspaceInfo, ".decantr/context/"))} Generated contract context`
|
|
9001
|
+
);
|
|
8793
9002
|
if (assistantBridgePath) {
|
|
8794
|
-
console.log(
|
|
9003
|
+
console.log(
|
|
9004
|
+
` ${cyan3(displayProjectPath(input.workspaceInfo, ".decantr/context/assistant-bridge.md"))} Assistant bridge preview`
|
|
9005
|
+
);
|
|
8795
9006
|
}
|
|
8796
9007
|
if (appliedRuleFiles.length > 0) {
|
|
8797
9008
|
console.log(` ${dim3(`Rule bridge applied: ${appliedRuleFiles.join(", ")}`)}`);
|
|
@@ -8802,16 +9013,24 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
8802
9013
|
console.log("");
|
|
8803
9014
|
console.log(" Generated context:");
|
|
8804
9015
|
for (const contextFile of refreshResult.contextFiles.slice(0, 8)) {
|
|
8805
|
-
console.log(
|
|
9016
|
+
console.log(
|
|
9017
|
+
` ${dim3(displayProjectPath(input.workspaceInfo, contextFile.replace(`${input.projectRoot}/`, "")))}`
|
|
9018
|
+
);
|
|
8806
9019
|
}
|
|
8807
9020
|
if (refreshResult.contextFiles.length > 8) {
|
|
8808
9021
|
console.log(` ${dim3(`(+${refreshResult.contextFiles.length - 8} more)`)}`);
|
|
8809
9022
|
}
|
|
8810
9023
|
console.log("");
|
|
8811
9024
|
console.log(" Next steps:");
|
|
8812
|
-
console.log(
|
|
8813
|
-
|
|
8814
|
-
|
|
9025
|
+
console.log(
|
|
9026
|
+
` 1. Run ${cyan3(withProject("decantr check --brownfield", projectLabel))} to verify contract coverage`
|
|
9027
|
+
);
|
|
9028
|
+
console.log(
|
|
9029
|
+
` 2. Read ${cyan3(displayProjectPath(input.workspaceInfo, ".decantr/brownfield-report.md"))} for unresolved doctrine risks`
|
|
9030
|
+
);
|
|
9031
|
+
console.log(
|
|
9032
|
+
` 3. Use ${cyan3(withProject("decantr rules preview", projectLabel))} before mutating assistant rule files`
|
|
9033
|
+
);
|
|
8815
9034
|
console.log("");
|
|
8816
9035
|
}
|
|
8817
9036
|
async function cmdInit(args) {
|
|
@@ -8868,7 +9087,7 @@ async function cmdInit(args) {
|
|
|
8868
9087
|
}
|
|
8869
9088
|
if (policy.workflowMode === "brownfield-attach" && detected.existingEssence) {
|
|
8870
9089
|
console.log(
|
|
8871
|
-
|
|
9090
|
+
error2("Refusing to overwrite existing decantr.essence.json in brownfield attach mode.")
|
|
8872
9091
|
);
|
|
8873
9092
|
console.log(
|
|
8874
9093
|
dim3(
|
|
@@ -8879,7 +9098,7 @@ async function cmdInit(args) {
|
|
|
8879
9098
|
return;
|
|
8880
9099
|
}
|
|
8881
9100
|
if (policy.workflowMode === "brownfield-attach" && readBrownfieldProposal(projectRoot)) {
|
|
8882
|
-
console.log(
|
|
9101
|
+
console.log(error2("Observed brownfield proposal found, but it was not accepted."));
|
|
8883
9102
|
console.log(
|
|
8884
9103
|
dim3(
|
|
8885
9104
|
"Review `.decantr/brownfield-report.md`, then run `decantr init --existing --accept-proposal`."
|
|
@@ -8900,7 +9119,7 @@ async function cmdInit(args) {
|
|
|
8900
9119
|
console.log(dim3(` Seeded offline registry content from ${offlineSeed.strategy}.`));
|
|
8901
9120
|
} else if (requestedBlueprint || requestedArchetype) {
|
|
8902
9121
|
console.log(
|
|
8903
|
-
|
|
9122
|
+
error2("\nOffline blueprint/archetype scaffolding requires a local Decantr content source.")
|
|
8904
9123
|
);
|
|
8905
9124
|
console.log(
|
|
8906
9125
|
dim3(
|
|
@@ -8968,7 +9187,7 @@ ${YELLOW10}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
|
|
|
8968
9187
|
}
|
|
8969
9188
|
if (requestedBlueprint || requestedArchetype) {
|
|
8970
9189
|
console.log(
|
|
8971
|
-
|
|
9190
|
+
error2(
|
|
8972
9191
|
"\nThe requested blueprint/archetype could not be resolved from the hosted registry or local cache."
|
|
8973
9192
|
)
|
|
8974
9193
|
);
|
|
@@ -9157,7 +9376,7 @@ ${YELLOW10}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9157
9376
|
}
|
|
9158
9377
|
} else {
|
|
9159
9378
|
if (requestedBlueprint) {
|
|
9160
|
-
console.log(
|
|
9379
|
+
console.log(error2(` Error: Could not fetch blueprint "${options.blueprint}".`));
|
|
9161
9380
|
console.log(dim3("Resolve local registry content or retry against the hosted registry."));
|
|
9162
9381
|
process.exitCode = 1;
|
|
9163
9382
|
return;
|
|
@@ -9172,7 +9391,7 @@ ${YELLOW10}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9172
9391
|
archetypeData = mapRegistryArchetypeToArchetypeData(archetypeResult.data);
|
|
9173
9392
|
} else {
|
|
9174
9393
|
if (requestedArchetype) {
|
|
9175
|
-
console.log(
|
|
9394
|
+
console.log(error2(` Error: Could not fetch archetype "${options.archetype}".`));
|
|
9176
9395
|
console.log(dim3("Resolve local registry content or retry against the hosted registry."));
|
|
9177
9396
|
process.exitCode = 1;
|
|
9178
9397
|
return;
|
|
@@ -9189,7 +9408,7 @@ ${YELLOW10}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9189
9408
|
themeData = mapRegistryThemeToThemeData(themeResult.data);
|
|
9190
9409
|
} else {
|
|
9191
9410
|
if (requestedTheme) {
|
|
9192
|
-
console.log(
|
|
9411
|
+
console.log(error2(` Error: Could not fetch theme "${options.theme}".`));
|
|
9193
9412
|
console.log(dim3("Resolve local registry content or retry against the hosted registry."));
|
|
9194
9413
|
process.exitCode = 1;
|
|
9195
9414
|
return;
|
|
@@ -9299,7 +9518,7 @@ ${YELLOW10}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9299
9518
|
const essence = JSON.parse(essenceContent);
|
|
9300
9519
|
const validation = validateEssence2(essence);
|
|
9301
9520
|
if (!validation.valid) {
|
|
9302
|
-
console.log(
|
|
9521
|
+
console.log(error2(`
|
|
9303
9522
|
Validation warnings: ${validation.errors.join(", ")}`));
|
|
9304
9523
|
}
|
|
9305
9524
|
console.log("");
|
|
@@ -9349,13 +9568,12 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
9349
9568
|
console.log(dim3('Run "decantr sync" when online to get the latest registry content.'));
|
|
9350
9569
|
}
|
|
9351
9570
|
}
|
|
9352
|
-
async function cmdStatus() {
|
|
9353
|
-
const projectRoot = process.cwd();
|
|
9571
|
+
async function cmdStatus(projectRoot = process.cwd()) {
|
|
9354
9572
|
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
9355
9573
|
const projectJsonPath = join31(projectRoot, ".decantr", "project.json");
|
|
9356
9574
|
console.log(heading2("Decantr Project Status"));
|
|
9357
9575
|
if (!existsSync29(essencePath)) {
|
|
9358
|
-
console.log(`${
|
|
9576
|
+
console.log(`${RED12}No decantr.essence.json found.${RESET16}`);
|
|
9359
9577
|
console.log(dim3('Run "decantr init" to create one.'));
|
|
9360
9578
|
return;
|
|
9361
9579
|
}
|
|
@@ -9367,7 +9585,7 @@ async function cmdStatus() {
|
|
|
9367
9585
|
if (validation.valid) {
|
|
9368
9586
|
console.log(` ${GREEN16}Valid${RESET16} (${essenceVersion})`);
|
|
9369
9587
|
} else {
|
|
9370
|
-
console.log(` ${
|
|
9588
|
+
console.log(` ${RED12}Invalid: ${validation.errors.join(", ")}${RESET16}`);
|
|
9371
9589
|
}
|
|
9372
9590
|
if (isV49(essence)) {
|
|
9373
9591
|
const v4 = essence;
|
|
@@ -9404,7 +9622,7 @@ async function cmdStatus() {
|
|
|
9404
9622
|
console.log(` ${YELLOW10}Run \`decantr migrate --to v4\` to upgrade this project.${RESET16}`);
|
|
9405
9623
|
}
|
|
9406
9624
|
} catch (e) {
|
|
9407
|
-
console.log(` ${
|
|
9625
|
+
console.log(` ${RED12}Error reading essence: ${e.message}${RESET16}`);
|
|
9408
9626
|
}
|
|
9409
9627
|
console.log("");
|
|
9410
9628
|
console.log(`${BOLD9}Sync Status:${RESET16}`);
|
|
@@ -9450,7 +9668,7 @@ function printVerificationFindings(findings) {
|
|
|
9450
9668
|
return;
|
|
9451
9669
|
}
|
|
9452
9670
|
for (const finding of findings) {
|
|
9453
|
-
const color = finding.severity === "error" ?
|
|
9671
|
+
const color = finding.severity === "error" ? RED12 : finding.severity === "warn" ? YELLOW10 : CYAN9;
|
|
9454
9672
|
console.log(
|
|
9455
9673
|
` ${color}[${finding.severity.toUpperCase()}]${RESET16} ${finding.category}: ${finding.message}`
|
|
9456
9674
|
);
|
|
@@ -9466,7 +9684,7 @@ function printProjectAuditReport(report) {
|
|
|
9466
9684
|
if (report.valid) {
|
|
9467
9685
|
console.log(success3("Project contract is valid."));
|
|
9468
9686
|
} else {
|
|
9469
|
-
console.log(`${
|
|
9687
|
+
console.log(`${RED12}Project audit found blocking issues.${RESET16}`);
|
|
9470
9688
|
}
|
|
9471
9689
|
console.log("");
|
|
9472
9690
|
console.log(`${BOLD9}Summary:${RESET16}`);
|
|
@@ -9555,13 +9773,12 @@ async function cmdAudit(filePath) {
|
|
|
9555
9773
|
console.log(dim3("Project audit completed with advisory findings."));
|
|
9556
9774
|
}
|
|
9557
9775
|
} catch (e) {
|
|
9558
|
-
console.log(`${
|
|
9776
|
+
console.log(`${RED12}Error: ${e.message}${RESET16}`);
|
|
9559
9777
|
process.exitCode = 1;
|
|
9560
9778
|
}
|
|
9561
9779
|
}
|
|
9562
|
-
async function cmdTheme(args) {
|
|
9780
|
+
async function cmdTheme(args, projectRoot = process.cwd()) {
|
|
9563
9781
|
const subcommand = args[0];
|
|
9564
|
-
const projectRoot = process.cwd();
|
|
9565
9782
|
if (!subcommand || subcommand === "help") {
|
|
9566
9783
|
console.log(`
|
|
9567
9784
|
${BOLD9}decantr theme${RESET16} \u2014 Manage custom themes
|
|
@@ -9586,7 +9803,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9586
9803
|
case "create": {
|
|
9587
9804
|
const name = args[1];
|
|
9588
9805
|
if (!name) {
|
|
9589
|
-
console.error(
|
|
9806
|
+
console.error(error2("Usage: decantr theme create <name>"));
|
|
9590
9807
|
process.exitCode = 1;
|
|
9591
9808
|
return;
|
|
9592
9809
|
}
|
|
@@ -9598,7 +9815,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9598
9815
|
console.log("");
|
|
9599
9816
|
console.log(`Use in essence: ${cyan3(`"id": "custom:${name}"`)}`);
|
|
9600
9817
|
} else {
|
|
9601
|
-
console.error(
|
|
9818
|
+
console.error(error2(result.error || "Failed to create theme"));
|
|
9602
9819
|
process.exitCode = 1;
|
|
9603
9820
|
}
|
|
9604
9821
|
break;
|
|
@@ -9619,13 +9836,13 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9619
9836
|
case "validate": {
|
|
9620
9837
|
const name = args[1];
|
|
9621
9838
|
if (!name) {
|
|
9622
|
-
console.error(
|
|
9839
|
+
console.error(error2("Usage: decantr theme validate <name>"));
|
|
9623
9840
|
process.exitCode = 1;
|
|
9624
9841
|
return;
|
|
9625
9842
|
}
|
|
9626
9843
|
const themePath = join31(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
|
|
9627
9844
|
if (!existsSync29(themePath)) {
|
|
9628
|
-
console.error(
|
|
9845
|
+
console.error(error2(`Theme "${name}" not found at ${themePath}`));
|
|
9629
9846
|
process.exitCode = 1;
|
|
9630
9847
|
return;
|
|
9631
9848
|
}
|
|
@@ -9635,14 +9852,14 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9635
9852
|
if (result.valid) {
|
|
9636
9853
|
console.log(success3(`Custom theme "${name}" is valid`));
|
|
9637
9854
|
} else {
|
|
9638
|
-
console.error(
|
|
9855
|
+
console.error(error2("Validation failed:"));
|
|
9639
9856
|
for (const err of result.errors) {
|
|
9640
|
-
console.error(` ${
|
|
9857
|
+
console.error(` ${RED12}${err}${RESET16}`);
|
|
9641
9858
|
}
|
|
9642
9859
|
process.exitCode = 1;
|
|
9643
9860
|
}
|
|
9644
9861
|
} catch (e) {
|
|
9645
|
-
console.error(
|
|
9862
|
+
console.error(error2(`Invalid JSON: ${e.message}`));
|
|
9646
9863
|
process.exitCode = 1;
|
|
9647
9864
|
}
|
|
9648
9865
|
break;
|
|
@@ -9650,7 +9867,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9650
9867
|
case "delete": {
|
|
9651
9868
|
const name = args[1];
|
|
9652
9869
|
if (!name) {
|
|
9653
|
-
console.error(
|
|
9870
|
+
console.error(error2("Usage: decantr theme delete <name>"));
|
|
9654
9871
|
process.exitCode = 1;
|
|
9655
9872
|
return;
|
|
9656
9873
|
}
|
|
@@ -9658,7 +9875,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9658
9875
|
if (result.success) {
|
|
9659
9876
|
console.log(success3(`Deleted custom theme "${name}"`));
|
|
9660
9877
|
} else {
|
|
9661
|
-
console.error(
|
|
9878
|
+
console.error(error2(result.error || "Failed to delete theme"));
|
|
9662
9879
|
process.exitCode = 1;
|
|
9663
9880
|
}
|
|
9664
9881
|
break;
|
|
@@ -9666,7 +9883,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9666
9883
|
case "import": {
|
|
9667
9884
|
const sourcePath = args[1];
|
|
9668
9885
|
if (!sourcePath) {
|
|
9669
|
-
console.error(
|
|
9886
|
+
console.error(error2("Usage: decantr theme import <path>"));
|
|
9670
9887
|
process.exitCode = 1;
|
|
9671
9888
|
return;
|
|
9672
9889
|
}
|
|
@@ -9675,9 +9892,9 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9675
9892
|
console.log(success3("Theme imported successfully"));
|
|
9676
9893
|
console.log(dim3(` Path: ${result.path}`));
|
|
9677
9894
|
} else {
|
|
9678
|
-
console.error(
|
|
9895
|
+
console.error(error2("Import failed:"));
|
|
9679
9896
|
for (const err of result.errors || []) {
|
|
9680
|
-
console.error(` ${
|
|
9897
|
+
console.error(` ${RED12}${err}${RESET16}`);
|
|
9681
9898
|
}
|
|
9682
9899
|
process.exitCode = 1;
|
|
9683
9900
|
}
|
|
@@ -9686,7 +9903,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9686
9903
|
case "switch": {
|
|
9687
9904
|
const name = args[1];
|
|
9688
9905
|
if (!name) {
|
|
9689
|
-
console.error(
|
|
9906
|
+
console.error(error2("Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]"));
|
|
9690
9907
|
process.exitCode = 1;
|
|
9691
9908
|
return;
|
|
9692
9909
|
}
|
|
@@ -9694,7 +9911,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
9694
9911
|
break;
|
|
9695
9912
|
}
|
|
9696
9913
|
default:
|
|
9697
|
-
console.error(
|
|
9914
|
+
console.error(error2(`Unknown theme command: ${subcommand}`));
|
|
9698
9915
|
process.exitCode = 1;
|
|
9699
9916
|
}
|
|
9700
9917
|
}
|
|
@@ -9761,13 +9978,55 @@ function withoutWorkflowOnlyFlags(args) {
|
|
|
9761
9978
|
function withProject(command, projectArg) {
|
|
9762
9979
|
return projectArg ? `${command} --project ${projectArg}` : command;
|
|
9763
9980
|
}
|
|
9981
|
+
function displayProjectPath(workspaceInfo, projectPath) {
|
|
9982
|
+
const absolutePath = join31(workspaceInfo.appRoot, projectPath);
|
|
9983
|
+
const relativePath = relative7(workspaceInfo.cwd, absolutePath).replace(/\\/g, "/");
|
|
9984
|
+
if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
|
|
9985
|
+
return relativePath;
|
|
9986
|
+
}
|
|
9987
|
+
return absolutePath;
|
|
9988
|
+
}
|
|
9989
|
+
function stripProjectArgs(args, startIndex = 1) {
|
|
9990
|
+
const stripped = [args[0]];
|
|
9991
|
+
for (let index = startIndex; index < args.length; index += 1) {
|
|
9992
|
+
const arg = args[index];
|
|
9993
|
+
if (arg === "--project" && args[index + 1]) {
|
|
9994
|
+
index += 1;
|
|
9995
|
+
continue;
|
|
9996
|
+
}
|
|
9997
|
+
if (arg.startsWith("--project=")) continue;
|
|
9998
|
+
stripped.push(arg);
|
|
9999
|
+
}
|
|
10000
|
+
return stripped;
|
|
10001
|
+
}
|
|
10002
|
+
function normalizedProjectPath(value) {
|
|
10003
|
+
if (!value) return null;
|
|
10004
|
+
return value.replace(/\\/g, "/").replace(/\/+$/g, "");
|
|
10005
|
+
}
|
|
10006
|
+
function printProjectNotFound(projectArg, commandName) {
|
|
10007
|
+
console.error(error2(`decantr ${commandName} could not find project path: ${projectArg}`));
|
|
10008
|
+
console.error(dim3("Pass an existing app path, for example `--project apps/web`."));
|
|
10009
|
+
}
|
|
10010
|
+
function ensureAllowedFlags(flags, allowed, commandName) {
|
|
10011
|
+
const allowedSet = new Set(allowed);
|
|
10012
|
+
const unknown = Object.keys(flags).filter((flag) => !allowedSet.has(flag));
|
|
10013
|
+
if (unknown.length === 0) return true;
|
|
10014
|
+
console.error(error2(`Unsupported option for decantr ${commandName}: --${unknown[0]}`));
|
|
10015
|
+
console.error(dim3("Run `decantr help` or the command-specific help to see supported options."));
|
|
10016
|
+
process.exitCode = 1;
|
|
10017
|
+
return false;
|
|
10018
|
+
}
|
|
10019
|
+
function compilePacksCommandForProject(projectArg) {
|
|
10020
|
+
const essencePath = projectArg ? `${projectArg}/decantr.essence.json` : "decantr.essence.json";
|
|
10021
|
+
return `decantr registry compile-packs ${essencePath} --write-context`;
|
|
10022
|
+
}
|
|
9764
10023
|
function firstWorkspaceCandidate(workspaceInfo) {
|
|
9765
10024
|
return workspaceInfo.appCandidates[0] ?? "apps/web";
|
|
9766
10025
|
}
|
|
9767
10026
|
function printWorkspaceProjectSelection(workspaceInfo, commandName = "command") {
|
|
9768
10027
|
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
9769
10028
|
const noun = commandName === "adopt" ? "Brownfield adoption" : `decantr ${commandName}`;
|
|
9770
|
-
console.log(
|
|
10029
|
+
console.log(error2(`${noun} needs an app path.`));
|
|
9771
10030
|
console.log("");
|
|
9772
10031
|
console.log(`${BOLD9}This looks like a monorepo.${RESET16}`);
|
|
9773
10032
|
console.log("Install Decantr at the workspace root, then attach it to one app with --project.");
|
|
@@ -9787,10 +10046,47 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
|
|
|
9787
10046
|
}
|
|
9788
10047
|
function printMonorepoSetupGuidance(workspaceInfo) {
|
|
9789
10048
|
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
10049
|
+
const attachedProjects = workspaceInfo.appCandidates.filter(
|
|
10050
|
+
(appCandidate) => existsSync29(join31(workspaceInfo.workspaceRoot, appCandidate, "decantr.essence.json"))
|
|
10051
|
+
);
|
|
10052
|
+
const firstAttached = attachedProjects[0];
|
|
9790
10053
|
console.log(heading2("Decantr Setup"));
|
|
9791
10054
|
console.log(`${BOLD9}This looks like a monorepo.${RESET16}`);
|
|
9792
10055
|
console.log(` Workspace root: ${workspaceInfo.workspaceRoot}`);
|
|
9793
10056
|
console.log("");
|
|
10057
|
+
if (firstAttached) {
|
|
10058
|
+
console.log("Decantr is already attached to at least one app.");
|
|
10059
|
+
console.log("");
|
|
10060
|
+
console.log("Attached projects:");
|
|
10061
|
+
for (const project of attachedProjects) {
|
|
10062
|
+
console.log(` ${project}`);
|
|
10063
|
+
}
|
|
10064
|
+
console.log("");
|
|
10065
|
+
console.log(`${BOLD9}Next:${RESET16}`);
|
|
10066
|
+
console.log(
|
|
10067
|
+
` ${cyan3(`decantr doctor --project ${firstAttached}`)} Explain current state and next command`
|
|
10068
|
+
);
|
|
10069
|
+
console.log(
|
|
10070
|
+
` ${cyan3(`decantr task <route> "<change>" --project ${firstAttached}`)} Prepare LLM context before edits`
|
|
10071
|
+
);
|
|
10072
|
+
console.log(
|
|
10073
|
+
` ${cyan3(`decantr verify --brownfield --local-patterns --project ${firstAttached}`)} Check after edits`
|
|
10074
|
+
);
|
|
10075
|
+
console.log(
|
|
10076
|
+
` ${cyan3(`decantr ci init --project ${firstAttached}`)} Wire the app into CI`
|
|
10077
|
+
);
|
|
10078
|
+
const unattached = workspaceInfo.appCandidates.filter(
|
|
10079
|
+
(appCandidate) => !attachedProjects.includes(appCandidate)
|
|
10080
|
+
);
|
|
10081
|
+
if (unattached.length > 0) {
|
|
10082
|
+
console.log("");
|
|
10083
|
+
console.log("Other app candidates:");
|
|
10084
|
+
for (const appCandidate of unattached) {
|
|
10085
|
+
console.log(` ${appCandidate}`);
|
|
10086
|
+
}
|
|
10087
|
+
}
|
|
10088
|
+
return;
|
|
10089
|
+
}
|
|
9794
10090
|
console.log(
|
|
9795
10091
|
"Install Decantr at the workspace root, then attach it to the app you want Decantr to govern."
|
|
9796
10092
|
);
|
|
@@ -9816,9 +10112,34 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
9816
10112
|
` ${cyan3(`decantr verify --project ${candidate} --base-url http://localhost:3000 --evidence`)}`
|
|
9817
10113
|
);
|
|
9818
10114
|
}
|
|
9819
|
-
function resolveWorkflowProject(flags, commandName = "command") {
|
|
10115
|
+
function resolveWorkflowProject(flags, commandName = "command", options = {}) {
|
|
9820
10116
|
const projectArg = flagString(flags, "project");
|
|
9821
10117
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
10118
|
+
if (projectArg && options.requireExisting !== false && !existsSync29(workspaceInfo.appRoot)) {
|
|
10119
|
+
printProjectNotFound(projectArg, commandName);
|
|
10120
|
+
process.exitCode = 1;
|
|
10121
|
+
return null;
|
|
10122
|
+
}
|
|
10123
|
+
if (projectArg && options.requireAppCandidate && workspaceInfo.appCandidates.length > 0) {
|
|
10124
|
+
const normalizedProject = normalizedProjectPath(projectArg);
|
|
10125
|
+
const knownCandidate = normalizedProject ? workspaceInfo.appCandidates.includes(normalizedProject) : false;
|
|
10126
|
+
const forcePackage = flagBoolean(flags, "force-package") || flagBoolean(flags, "allow-package") || flagBoolean(flags, "force");
|
|
10127
|
+
if (!knownCandidate && !forcePackage && !options.allowPackageProject) {
|
|
10128
|
+
console.error(
|
|
10129
|
+
error2(`decantr ${commandName} is app-scoped, but "${projectArg}" is not an app candidate.`)
|
|
10130
|
+
);
|
|
10131
|
+
if (workspaceInfo.appCandidates.length > 0) {
|
|
10132
|
+
console.error(dim3(`App candidates: ${workspaceInfo.appCandidates.join(", ")}`));
|
|
10133
|
+
}
|
|
10134
|
+
console.error(
|
|
10135
|
+
dim3(
|
|
10136
|
+
"Use --force-package only if you intentionally want Decantr attached to a non-app package."
|
|
10137
|
+
)
|
|
10138
|
+
);
|
|
10139
|
+
process.exitCode = 1;
|
|
10140
|
+
return null;
|
|
10141
|
+
}
|
|
10142
|
+
}
|
|
9822
10143
|
if (workspaceInfo.requiresProjectSelection) {
|
|
9823
10144
|
printWorkspaceProjectSelection(workspaceInfo, commandName);
|
|
9824
10145
|
process.exitCode = 1;
|
|
@@ -9887,7 +10208,37 @@ async function cmdSetupWorkflow(args) {
|
|
|
9887
10208
|
}
|
|
9888
10209
|
async function cmdAdoptWorkflow(args) {
|
|
9889
10210
|
const { flags } = parseLooseArgs(args);
|
|
9890
|
-
|
|
10211
|
+
if (!ensureAllowedFlags(
|
|
10212
|
+
flags,
|
|
10213
|
+
[
|
|
10214
|
+
"project",
|
|
10215
|
+
"dry-run",
|
|
10216
|
+
"yes",
|
|
10217
|
+
"y",
|
|
10218
|
+
"base-url",
|
|
10219
|
+
"verify",
|
|
10220
|
+
"browser",
|
|
10221
|
+
"evidence",
|
|
10222
|
+
"baseline",
|
|
10223
|
+
"save-baseline",
|
|
10224
|
+
"packs",
|
|
10225
|
+
"skip-packs",
|
|
10226
|
+
"offline",
|
|
10227
|
+
"ci",
|
|
10228
|
+
"init-ci",
|
|
10229
|
+
"assistant-bridge",
|
|
10230
|
+
"replace-essence",
|
|
10231
|
+
"merge-proposal",
|
|
10232
|
+
"telemetry",
|
|
10233
|
+
"force-package",
|
|
10234
|
+
"allow-package",
|
|
10235
|
+
"force"
|
|
10236
|
+
],
|
|
10237
|
+
"adopt"
|
|
10238
|
+
)) {
|
|
10239
|
+
return;
|
|
10240
|
+
}
|
|
10241
|
+
const workspaceInfo = resolveWorkflowProject(flags, "adopt", { requireAppCandidate: true });
|
|
9891
10242
|
if (!workspaceInfo) return;
|
|
9892
10243
|
const projectRoot = workspaceInfo.appRoot;
|
|
9893
10244
|
const projectArg = flagString(flags, "project");
|
|
@@ -9898,6 +10249,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
9898
10249
|
const runBrowser = flagBoolean(flags, "browser") || Boolean(baseUrl);
|
|
9899
10250
|
const evidence = flagBoolean(flags, "evidence") || runBrowser;
|
|
9900
10251
|
const saveBaseline = flagBoolean(flags, "baseline", true) || flagBoolean(flags, "save-baseline");
|
|
10252
|
+
const hydratePacks = flagBoolean(flags, "packs", true) && !flagBoolean(flags, "skip-packs") && !flagBoolean(flags, "offline") && process.env.DECANTR_OFFLINE !== "true";
|
|
9901
10253
|
const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
|
|
9902
10254
|
const assistantBridge = flagString(flags, "assistant-bridge");
|
|
9903
10255
|
const hasEssence = existsSync29(join31(projectRoot, "decantr.essence.json"));
|
|
@@ -9906,6 +10258,9 @@ async function cmdAdoptWorkflow(args) {
|
|
|
9906
10258
|
"analyze current app and write .decantr/brownfield intelligence",
|
|
9907
10259
|
`init --existing ${proposalFlag} as contract-only Brownfield`
|
|
9908
10260
|
];
|
|
10261
|
+
if (hydratePacks) {
|
|
10262
|
+
steps.push("hydrate hosted execution packs into the app context");
|
|
10263
|
+
}
|
|
9909
10264
|
if (runVerify) {
|
|
9910
10265
|
steps.push(
|
|
9911
10266
|
runBrowser ? "verify with Project Health, browser evidence, visual manifest, and baseline" : "verify with Project Health and baseline"
|
|
@@ -9939,8 +10294,33 @@ async function cmdAdoptWorkflow(args) {
|
|
|
9939
10294
|
telemetry: flagBoolean(flags, "telemetry")
|
|
9940
10295
|
});
|
|
9941
10296
|
if (process.exitCode && process.exitCode !== 0) return;
|
|
10297
|
+
if (hydratePacks) {
|
|
10298
|
+
try {
|
|
10299
|
+
const { bundle, contextDir } = await compileHostedExecutionPackBundle(
|
|
10300
|
+
join31(projectRoot, "decantr.essence.json")
|
|
10301
|
+
);
|
|
10302
|
+
const written = writeHostedExecutionPackContextArtifacts(
|
|
10303
|
+
contextDir,
|
|
10304
|
+
bundle
|
|
10305
|
+
);
|
|
10306
|
+
console.log(
|
|
10307
|
+
success3(
|
|
10308
|
+
`Hydrated Decantr execution packs (${written.paths.length} files) into ${contextDir}.`
|
|
10309
|
+
)
|
|
10310
|
+
);
|
|
10311
|
+
} catch (e) {
|
|
10312
|
+
console.log(`${YELLOW10}Pack hydration skipped:${RESET16} ${e.message}`);
|
|
10313
|
+
console.log(
|
|
10314
|
+
dim3(
|
|
10315
|
+
`Run ${compilePacksCommandForProject(projectArg)} after adoption if you want hosted page/review packs.`
|
|
10316
|
+
)
|
|
10317
|
+
);
|
|
10318
|
+
}
|
|
10319
|
+
} else if (flagBoolean(flags, "offline") || process.env.DECANTR_OFFLINE === "true") {
|
|
10320
|
+
console.log(dim3("Skipping hosted pack hydration in offline mode."));
|
|
10321
|
+
}
|
|
9942
10322
|
if (runVerify) {
|
|
9943
|
-
const { cmdHealth } = await import("./health-
|
|
10323
|
+
const { cmdHealth } = await import("./health-MB63O56B.js");
|
|
9944
10324
|
await cmdHealth(projectRoot, {
|
|
9945
10325
|
browser: runBrowser,
|
|
9946
10326
|
browserBaseUrl: baseUrl,
|
|
@@ -9975,13 +10355,43 @@ async function cmdAdoptWorkflow(args) {
|
|
|
9975
10355
|
}
|
|
9976
10356
|
async function cmdVerifyWorkflow(args) {
|
|
9977
10357
|
const { flags } = parseLooseArgs(args);
|
|
10358
|
+
const projectArg = flagString(flags, "project");
|
|
10359
|
+
if (!ensureAllowedFlags(
|
|
10360
|
+
flags,
|
|
10361
|
+
[
|
|
10362
|
+
"project",
|
|
10363
|
+
"workspace",
|
|
10364
|
+
"changed",
|
|
10365
|
+
"since",
|
|
10366
|
+
"json",
|
|
10367
|
+
"markdown",
|
|
10368
|
+
"format",
|
|
10369
|
+
"output",
|
|
10370
|
+
"ci",
|
|
10371
|
+
"fail-on",
|
|
10372
|
+
"prompt",
|
|
10373
|
+
"brownfield",
|
|
10374
|
+
"local-patterns",
|
|
10375
|
+
"evidence",
|
|
10376
|
+
"browser",
|
|
10377
|
+
"require-browser",
|
|
10378
|
+
"base-url",
|
|
10379
|
+
"design-tokens",
|
|
10380
|
+
"save-baseline",
|
|
10381
|
+
"since-baseline",
|
|
10382
|
+
"baseline"
|
|
10383
|
+
],
|
|
10384
|
+
"verify"
|
|
10385
|
+
)) {
|
|
10386
|
+
return;
|
|
10387
|
+
}
|
|
9978
10388
|
const workspaceMode = flagBoolean(flags, "workspace");
|
|
9979
10389
|
if (args[1] === "init-ci") {
|
|
9980
10390
|
await cmdCi(["ci", "init", ...args.slice(2)], process.cwd());
|
|
9981
10391
|
return;
|
|
9982
10392
|
}
|
|
9983
10393
|
if (workspaceMode) {
|
|
9984
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
10394
|
+
const { cmdWorkspace } = await import("./workspace-OGFYJA4N.js");
|
|
9985
10395
|
await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
|
|
9986
10396
|
return;
|
|
9987
10397
|
}
|
|
@@ -10024,7 +10434,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10024
10434
|
process.exitCode = void 0;
|
|
10025
10435
|
}
|
|
10026
10436
|
}
|
|
10027
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
10437
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-MB63O56B.js");
|
|
10028
10438
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
|
|
10029
10439
|
if (localPatterns) {
|
|
10030
10440
|
const validation = validateLocalLaw(workspaceInfo.appRoot);
|
|
@@ -10032,7 +10442,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10032
10442
|
if (!quietOutput) {
|
|
10033
10443
|
console.log("");
|
|
10034
10444
|
console.log(
|
|
10035
|
-
`${YELLOW10}Local pattern pack missing.${RESET16} Run ${cyan3("decantr codify --from-audit")}, review the proposal, then run ${cyan3("decantr codify --accept")}.`
|
|
10445
|
+
`${YELLOW10}Local pattern pack missing.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))}, review the proposal, then run ${cyan3(withProject("decantr codify --accept", projectArg))}.`
|
|
10036
10446
|
);
|
|
10037
10447
|
}
|
|
10038
10448
|
process.exitCode = process.exitCode || 1;
|
|
@@ -10090,10 +10500,11 @@ async function cmdTaskWorkflow(args) {
|
|
|
10090
10500
|
const { flags, positional } = parseLooseArgs(args);
|
|
10091
10501
|
const workspaceInfo = resolveWorkflowProject(flags, "task");
|
|
10092
10502
|
if (!workspaceInfo) return;
|
|
10503
|
+
const projectArg = flagString(flags, "project");
|
|
10093
10504
|
const routeInput = positional[0];
|
|
10094
10505
|
if (!routeInput) {
|
|
10095
10506
|
console.error(
|
|
10096
|
-
|
|
10507
|
+
error2(
|
|
10097
10508
|
'Usage: decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]'
|
|
10098
10509
|
)
|
|
10099
10510
|
);
|
|
@@ -10106,20 +10517,20 @@ async function cmdTaskWorkflow(args) {
|
|
|
10106
10517
|
const essence = readJsonIfPresent(essencePath);
|
|
10107
10518
|
if (!essence) {
|
|
10108
10519
|
console.error(
|
|
10109
|
-
|
|
10520
|
+
error2("No decantr.essence.json found. Run `decantr adopt` or `decantr init` first.")
|
|
10110
10521
|
);
|
|
10111
10522
|
process.exitCode = 1;
|
|
10112
10523
|
return;
|
|
10113
10524
|
}
|
|
10114
10525
|
if (!isV49(essence)) {
|
|
10115
|
-
console.error(
|
|
10526
|
+
console.error(error2("Task context requires Essence v4. Run `decantr migrate --to v4` first."));
|
|
10116
10527
|
process.exitCode = 1;
|
|
10117
10528
|
return;
|
|
10118
10529
|
}
|
|
10119
10530
|
const target = essence.blueprint.routes?.[route];
|
|
10120
10531
|
if (!target) {
|
|
10121
10532
|
const knownRoutes = Object.keys(essence.blueprint.routes ?? {}).sort();
|
|
10122
|
-
console.error(
|
|
10533
|
+
console.error(error2(`Route not found in Decantr contract: ${route}`));
|
|
10123
10534
|
console.error(dim3(`Known routes: ${knownRoutes.join(", ") || "none"}`));
|
|
10124
10535
|
process.exitCode = 1;
|
|
10125
10536
|
return;
|
|
@@ -10135,6 +10546,11 @@ async function cmdTaskWorkflow(args) {
|
|
|
10135
10546
|
const localPatternPackPath = localPatternsPath(workspaceInfo.appRoot);
|
|
10136
10547
|
const localRuleManifestPath = localRulesPath(workspaceInfo.appRoot);
|
|
10137
10548
|
const localLaw = createLocalLawTaskSummary(workspaceInfo.appRoot);
|
|
10549
|
+
const displayedLocalLaw = {
|
|
10550
|
+
...localLaw,
|
|
10551
|
+
patternsPath: localLaw.patternsPath ? displayProjectPath(workspaceInfo, localLaw.patternsPath) : null,
|
|
10552
|
+
rulesPath: localLaw.rulesPath ? displayProjectPath(workspaceInfo, localLaw.rulesPath) : null
|
|
10553
|
+
};
|
|
10138
10554
|
const changedSince = flagString(flags, "since");
|
|
10139
10555
|
const currentChangedFiles = changedFiles(workspaceInfo.appRoot, changedSince);
|
|
10140
10556
|
const changedRoutes = routeImpacts(workspaceInfo.appRoot, currentChangedFiles);
|
|
@@ -10146,19 +10562,19 @@ async function cmdTaskWorkflow(args) {
|
|
|
10146
10562
|
shell: page?.shell ?? section?.shell ?? null,
|
|
10147
10563
|
patterns: page?.layout?.map(extractPatternName) ?? [],
|
|
10148
10564
|
read: [
|
|
10149
|
-
pagePack ? join31(".decantr/context", pagePack.markdown) : null,
|
|
10150
|
-
sectionPack ? join31(".decantr/context", sectionPack.markdown) : null,
|
|
10151
|
-
manifest?.scaffold?.markdown ? join31(".decantr/context", manifest.scaffold.markdown) : null,
|
|
10152
|
-
".decantr/context/scaffold.md",
|
|
10153
|
-
"DECANTR.md",
|
|
10154
|
-
existsSync29(localPatternPackPath) ? ".decantr/local-patterns.json" : null,
|
|
10155
|
-
existsSync29(localRuleManifestPath) ? ".decantr/rules.json" : null
|
|
10565
|
+
pagePack ? displayProjectPath(workspaceInfo, join31(".decantr/context", pagePack.markdown)) : null,
|
|
10566
|
+
sectionPack ? displayProjectPath(workspaceInfo, join31(".decantr/context", sectionPack.markdown)) : null,
|
|
10567
|
+
manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join31(".decantr/context", manifest.scaffold.markdown)) : null,
|
|
10568
|
+
displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
|
|
10569
|
+
displayProjectPath(workspaceInfo, "DECANTR.md"),
|
|
10570
|
+
existsSync29(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
|
|
10571
|
+
existsSync29(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null
|
|
10156
10572
|
].filter(Boolean),
|
|
10157
|
-
screenshot: screenshot ?? null,
|
|
10158
|
-
localLaw,
|
|
10573
|
+
screenshot: screenshot?.startsWith(".decantr/") ? displayProjectPath(workspaceInfo, screenshot) : screenshot ?? null,
|
|
10574
|
+
localLaw: displayedLocalLaw,
|
|
10159
10575
|
changedFiles: currentChangedFiles,
|
|
10160
10576
|
changedRoutes,
|
|
10161
|
-
verifyCommand: "decantr verify --brownfield --local-patterns"
|
|
10577
|
+
verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
|
|
10162
10578
|
};
|
|
10163
10579
|
if (flagBoolean(flags, "json")) {
|
|
10164
10580
|
console.log(JSON.stringify(context, null, 2));
|
|
@@ -10199,7 +10615,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
10199
10615
|
console.log("");
|
|
10200
10616
|
console.log(`${BOLD9}Project-owned local law:${RESET16}`);
|
|
10201
10617
|
console.log(
|
|
10202
|
-
` ${YELLOW10}Not codified yet.${RESET16} Run ${cyan3("decantr codify --from-audit")} after adoption.`
|
|
10618
|
+
` ${YELLOW10}Not codified yet.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
|
|
10203
10619
|
);
|
|
10204
10620
|
}
|
|
10205
10621
|
if (context.changedFiles.length > 0) {
|
|
@@ -10224,12 +10640,20 @@ async function cmdTaskWorkflow(args) {
|
|
|
10224
10640
|
}
|
|
10225
10641
|
async function cmdCodifyWorkflow(args) {
|
|
10226
10642
|
const { flags } = parseLooseArgs(args);
|
|
10643
|
+
const projectArg = flagString(flags, "project");
|
|
10644
|
+
if (!ensureAllowedFlags(
|
|
10645
|
+
flags,
|
|
10646
|
+
["project", "from-audit", "discover-local-patterns", "codify-local-patterns", "accept"],
|
|
10647
|
+
"codify"
|
|
10648
|
+
)) {
|
|
10649
|
+
return;
|
|
10650
|
+
}
|
|
10227
10651
|
const workspaceInfo = resolveWorkflowProject(flags, "codify");
|
|
10228
10652
|
if (!workspaceInfo) return;
|
|
10229
10653
|
if (flagBoolean(flags, "accept")) {
|
|
10230
10654
|
if (!existsSync29(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync29(localRulesProposalPath(workspaceInfo.appRoot))) {
|
|
10231
10655
|
console.error(
|
|
10232
|
-
|
|
10656
|
+
error2(
|
|
10233
10657
|
"No local law proposal found. Run `decantr codify --from-audit` or `decantr codify` first."
|
|
10234
10658
|
)
|
|
10235
10659
|
);
|
|
@@ -10243,7 +10667,11 @@ async function cmdCodifyWorkflow(args) {
|
|
|
10243
10667
|
if (result2.rulesAcceptedPath) {
|
|
10244
10668
|
console.log(success3(`Accepted local rule manifest: ${result2.rulesAcceptedPath}`));
|
|
10245
10669
|
}
|
|
10246
|
-
console.log(
|
|
10670
|
+
console.log(
|
|
10671
|
+
dim3(
|
|
10672
|
+
`Run \`${withProject("decantr verify --brownfield --local-patterns", projectArg)}\` after project edits.`
|
|
10673
|
+
)
|
|
10674
|
+
);
|
|
10247
10675
|
return;
|
|
10248
10676
|
}
|
|
10249
10677
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
@@ -10267,7 +10695,7 @@ async function cmdCodifyWorkflow(args) {
|
|
|
10267
10695
|
}
|
|
10268
10696
|
console.log(
|
|
10269
10697
|
dim3(
|
|
10270
|
-
|
|
10698
|
+
`Review both files, add real component paths/token recipes, then run \`${withProject("decantr codify --accept", projectArg)}\`.`
|
|
10271
10699
|
)
|
|
10272
10700
|
);
|
|
10273
10701
|
}
|
|
@@ -10282,10 +10710,12 @@ async function cmdContentWorkflow(args) {
|
|
|
10282
10710
|
return;
|
|
10283
10711
|
}
|
|
10284
10712
|
if (subcommand === "create") {
|
|
10713
|
+
const { flags } = parseLooseArgs(args);
|
|
10714
|
+
if (!ensureAllowedFlags(flags, [], "content create")) return;
|
|
10285
10715
|
const type = args[2];
|
|
10286
10716
|
const name = args[3];
|
|
10287
10717
|
if (!type || !name) {
|
|
10288
|
-
console.error(
|
|
10718
|
+
console.error(error2("Usage: decantr content create <type> <name>"));
|
|
10289
10719
|
process.exitCode = 1;
|
|
10290
10720
|
return;
|
|
10291
10721
|
}
|
|
@@ -10293,17 +10723,19 @@ async function cmdContentWorkflow(args) {
|
|
|
10293
10723
|
return;
|
|
10294
10724
|
}
|
|
10295
10725
|
if (subcommand === "publish") {
|
|
10726
|
+
const { flags } = parseLooseArgs(args);
|
|
10727
|
+
if (!ensureAllowedFlags(flags, [], "content publish")) return;
|
|
10296
10728
|
const type = args[2];
|
|
10297
10729
|
const name = args[3];
|
|
10298
10730
|
if (!type || !name) {
|
|
10299
|
-
console.error(
|
|
10731
|
+
console.error(error2("Usage: decantr content publish <type> <name>"));
|
|
10300
10732
|
process.exitCode = 1;
|
|
10301
10733
|
return;
|
|
10302
10734
|
}
|
|
10303
10735
|
await cmdPublish(type, name);
|
|
10304
10736
|
return;
|
|
10305
10737
|
}
|
|
10306
|
-
console.error(
|
|
10738
|
+
console.error(error2("Usage: decantr content <check|create|publish>"));
|
|
10307
10739
|
process.exitCode = 1;
|
|
10308
10740
|
}
|
|
10309
10741
|
function cmdHelp() {
|
|
@@ -10313,7 +10745,7 @@ ${BOLD9}decantr${RESET16} \u2014 Design intelligence for AI-generated UI
|
|
|
10313
10745
|
${BOLD9}Usage:${RESET16}
|
|
10314
10746
|
decantr setup [--project <path>]
|
|
10315
10747
|
decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
|
|
10316
|
-
decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--yes]
|
|
10748
|
+
decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--no-packs] [--yes]
|
|
10317
10749
|
decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
|
|
10318
10750
|
decantr verify [--project <path>] [--brownfield] [--local-patterns] [health options]
|
|
10319
10751
|
decantr ci [--project <path>] [--workspace] [--fail-on error|warn|none]
|
|
@@ -10673,11 +11105,11 @@ ${BOLD9}Examples:${RESET16}
|
|
|
10673
11105
|
}
|
|
10674
11106
|
function cmdAdoptHelp() {
|
|
10675
11107
|
console.log(`
|
|
10676
|
-
${BOLD9}decantr adopt${RESET16} \u2014 Brownfield one-liner: analyze, attach, verify, and show the operating loop
|
|
11108
|
+
${BOLD9}decantr adopt${RESET16} \u2014 Brownfield one-liner: analyze, attach, hydrate packs, verify, and show the operating loop
|
|
10677
11109
|
|
|
10678
11110
|
${BOLD9}Usage:${RESET16}
|
|
10679
|
-
decantr adopt [--project <path>] [--yes] [--dry-run]
|
|
10680
|
-
decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes]
|
|
11111
|
+
decantr adopt [--project <path>] [--yes] [--dry-run] [--no-packs]
|
|
11112
|
+
decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes] [--no-packs]
|
|
10681
11113
|
|
|
10682
11114
|
${BOLD9}Options:${RESET16}
|
|
10683
11115
|
--project App path inside a workspace/monorepo
|
|
@@ -10688,6 +11120,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
10688
11120
|
--baseline Save a health baseline (default)
|
|
10689
11121
|
--no-baseline Skip baseline save
|
|
10690
11122
|
--no-verify Skip the verification step
|
|
11123
|
+
--no-packs Skip hosted execution-pack hydration
|
|
10691
11124
|
--ci, --init-ci Install the Decantr CI gate after adoption
|
|
10692
11125
|
--telemetry Opt this project into privacy-filtered CLI product telemetry
|
|
10693
11126
|
--merge-proposal Merge the observed proposal into an existing essence
|
|
@@ -10838,10 +11271,10 @@ async function main() {
|
|
|
10838
11271
|
}
|
|
10839
11272
|
}
|
|
10840
11273
|
}
|
|
10841
|
-
console.error(
|
|
11274
|
+
console.error(error2("Could not resolve @decantr/cli version from package.json."));
|
|
10842
11275
|
process.exitCode = 1;
|
|
10843
11276
|
} catch (e) {
|
|
10844
|
-
console.error(
|
|
11277
|
+
console.error(error2(`Failed to read CLI version: ${e.message}`));
|
|
10845
11278
|
process.exitCode = 1;
|
|
10846
11279
|
}
|
|
10847
11280
|
return;
|
|
@@ -10886,7 +11319,7 @@ async function main() {
|
|
|
10886
11319
|
const newName = args[1];
|
|
10887
11320
|
if (!newName) {
|
|
10888
11321
|
console.error(
|
|
10889
|
-
|
|
11322
|
+
error2("Usage: decantr new <project-name> [--blueprint=X] [--archetype=X] [--theme=X]")
|
|
10890
11323
|
);
|
|
10891
11324
|
process.exitCode = 1;
|
|
10892
11325
|
break;
|
|
@@ -10958,7 +11391,10 @@ async function main() {
|
|
|
10958
11391
|
break;
|
|
10959
11392
|
}
|
|
10960
11393
|
case "status": {
|
|
10961
|
-
|
|
11394
|
+
const { flags } = parseLooseArgs(args);
|
|
11395
|
+
const workspaceInfo = resolveWorkflowProject(flags, "status");
|
|
11396
|
+
if (!workspaceInfo) break;
|
|
11397
|
+
await cmdStatus(workspaceInfo.appRoot);
|
|
10962
11398
|
break;
|
|
10963
11399
|
}
|
|
10964
11400
|
case "sync": {
|
|
@@ -10967,8 +11403,11 @@ async function main() {
|
|
|
10967
11403
|
}
|
|
10968
11404
|
case "upgrade": {
|
|
10969
11405
|
const { cmdUpgrade } = await import("./upgrade-VON7Y3LG.js");
|
|
11406
|
+
const { flags } = parseLooseArgs(args);
|
|
11407
|
+
const workspaceInfo = resolveWorkflowProject(flags, "upgrade");
|
|
11408
|
+
if (!workspaceInfo) break;
|
|
10970
11409
|
const applyFlag = args.includes("--apply");
|
|
10971
|
-
await cmdUpgrade(
|
|
11410
|
+
await cmdUpgrade(workspaceInfo.appRoot, { apply: applyFlag });
|
|
10972
11411
|
break;
|
|
10973
11412
|
}
|
|
10974
11413
|
case "check":
|
|
@@ -10984,7 +11423,10 @@ async function main() {
|
|
|
10984
11423
|
if (!workspaceInfo) break;
|
|
10985
11424
|
const telemetryFlag = args.includes("--telemetry");
|
|
10986
11425
|
const brownfieldFlag = args.includes("--brownfield");
|
|
10987
|
-
await cmdHeal(workspaceInfo.appRoot, {
|
|
11426
|
+
await cmdHeal(workspaceInfo.appRoot, {
|
|
11427
|
+
telemetry: telemetryFlag,
|
|
11428
|
+
brownfield: brownfieldFlag
|
|
11429
|
+
});
|
|
10988
11430
|
break;
|
|
10989
11431
|
}
|
|
10990
11432
|
case "health": {
|
|
@@ -10993,10 +11435,17 @@ async function main() {
|
|
|
10993
11435
|
cmdHealthHelp();
|
|
10994
11436
|
break;
|
|
10995
11437
|
}
|
|
10996
|
-
|
|
10997
|
-
|
|
11438
|
+
if (args[1] === "init-ci") {
|
|
11439
|
+
await cmdCi(["ci", "init", ...args.slice(2)], process.cwd());
|
|
11440
|
+
break;
|
|
11441
|
+
}
|
|
11442
|
+
const { flags } = parseLooseArgs(args);
|
|
11443
|
+
const workspaceInfo = resolveWorkflowProject(flags, "health");
|
|
11444
|
+
if (!workspaceInfo) break;
|
|
11445
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-MB63O56B.js");
|
|
11446
|
+
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
|
|
10998
11447
|
} catch (e) {
|
|
10999
|
-
console.error(
|
|
11448
|
+
console.error(error2(e.message));
|
|
11000
11449
|
process.exitCode = 1;
|
|
11001
11450
|
}
|
|
11002
11451
|
break;
|
|
@@ -11010,7 +11459,7 @@ async function main() {
|
|
|
11010
11459
|
const { cmdContentHealth, parseContentHealthArgs } = await import("./content-health-4KP2EGTI.js");
|
|
11011
11460
|
await cmdContentHealth(process.cwd(), parseContentHealthArgs(args));
|
|
11012
11461
|
} catch (e) {
|
|
11013
|
-
console.error(
|
|
11462
|
+
console.error(error2(e.message));
|
|
11014
11463
|
process.exitCode = 1;
|
|
11015
11464
|
}
|
|
11016
11465
|
break;
|
|
@@ -11021,10 +11470,10 @@ async function main() {
|
|
|
11021
11470
|
cmdStudioHelp();
|
|
11022
11471
|
break;
|
|
11023
11472
|
}
|
|
11024
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
11473
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-6QGXJBVH.js");
|
|
11025
11474
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
11026
11475
|
} catch (e) {
|
|
11027
|
-
console.error(
|
|
11476
|
+
console.error(error2(e.message));
|
|
11028
11477
|
process.exitCode = 1;
|
|
11029
11478
|
}
|
|
11030
11479
|
break;
|
|
@@ -11035,10 +11484,10 @@ async function main() {
|
|
|
11035
11484
|
cmdWorkspaceHelp();
|
|
11036
11485
|
break;
|
|
11037
11486
|
}
|
|
11038
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
11487
|
+
const { cmdWorkspace } = await import("./workspace-OGFYJA4N.js");
|
|
11039
11488
|
await cmdWorkspace(process.cwd(), args);
|
|
11040
11489
|
} catch (e) {
|
|
11041
|
-
console.error(
|
|
11490
|
+
console.error(error2(e.message));
|
|
11042
11491
|
process.exitCode = 1;
|
|
11043
11492
|
}
|
|
11044
11493
|
break;
|
|
@@ -11061,7 +11510,7 @@ async function main() {
|
|
|
11061
11510
|
if (result.success) {
|
|
11062
11511
|
console.log(success3(clearFlag ? "Drift log cleared." : "Entries resolved."));
|
|
11063
11512
|
} else {
|
|
11064
|
-
console.error(
|
|
11513
|
+
console.error(error2(result.error || "Failed"));
|
|
11065
11514
|
process.exitCode = 1;
|
|
11066
11515
|
}
|
|
11067
11516
|
} else {
|
|
@@ -11077,7 +11526,7 @@ async function main() {
|
|
|
11077
11526
|
const query = args[1];
|
|
11078
11527
|
if (!query) {
|
|
11079
11528
|
console.error(
|
|
11080
|
-
|
|
11529
|
+
error2(
|
|
11081
11530
|
"Usage: decantr search <query> [--type <type>] [--sort <recommended|recent|name>] [--source <authored|benchmark|hybrid>] [--blueprint-set <all|featured|certified|labs>]"
|
|
11082
11531
|
)
|
|
11083
11532
|
);
|
|
@@ -11095,7 +11544,7 @@ async function main() {
|
|
|
11095
11544
|
const blueprintSet = rawBlueprintSet && isPublicBlueprintSet(rawBlueprintSet) ? rawBlueprintSet : void 0;
|
|
11096
11545
|
if (rawBlueprintSet && !blueprintSet) {
|
|
11097
11546
|
console.error(
|
|
11098
|
-
|
|
11547
|
+
error2(
|
|
11099
11548
|
`Invalid blueprint set "${rawBlueprintSet}". Must be one of: all, featured, certified, labs.`
|
|
11100
11549
|
)
|
|
11101
11550
|
);
|
|
@@ -11104,7 +11553,7 @@ async function main() {
|
|
|
11104
11553
|
}
|
|
11105
11554
|
if (intelligenceSource && !isContentIntelligenceSource(intelligenceSource)) {
|
|
11106
11555
|
console.error(
|
|
11107
|
-
|
|
11556
|
+
error2(
|
|
11108
11557
|
`Invalid source "${intelligenceSource}". Must be one of: authored, benchmark, hybrid.`
|
|
11109
11558
|
)
|
|
11110
11559
|
);
|
|
@@ -11116,31 +11565,51 @@ async function main() {
|
|
|
11116
11565
|
break;
|
|
11117
11566
|
}
|
|
11118
11567
|
case "suggest": {
|
|
11119
|
-
const
|
|
11568
|
+
const { flags, positional } = parseLooseArgs(args);
|
|
11569
|
+
if (!ensureAllowedFlags(flags, ["type", "route", "file", "from-code", "project"], "suggest")) {
|
|
11570
|
+
break;
|
|
11571
|
+
}
|
|
11572
|
+
const projectArg = flagString(flags, "project");
|
|
11573
|
+
const route = flagString(flags, "route");
|
|
11574
|
+
let file = flagString(flags, "file");
|
|
11575
|
+
const normalizedProject = normalizedProjectPath(projectArg);
|
|
11576
|
+
if (file && normalizedProject && normalizedProjectPath(file)?.startsWith(`${normalizedProject}/`)) {
|
|
11577
|
+
file = normalizedProjectPath(file)?.slice(normalizedProject.length + 1);
|
|
11578
|
+
}
|
|
11579
|
+
const fromCode = flagBoolean(flags, "from-code");
|
|
11580
|
+
let query = positional.join(" ").trim();
|
|
11581
|
+
if (!query && (route || file || fromCode)) {
|
|
11582
|
+
query = [
|
|
11583
|
+
route ? `route ${route}` : null,
|
|
11584
|
+
file ? `file ${basename3(file)}` : null,
|
|
11585
|
+
fromCode ? "source code patterns" : null
|
|
11586
|
+
].filter((entry) => Boolean(entry)).join(" ");
|
|
11587
|
+
}
|
|
11120
11588
|
if (!query) {
|
|
11121
11589
|
console.error(
|
|
11122
|
-
|
|
11123
|
-
"Usage: decantr suggest <query> [--type <type>] [--route <route>] [--file <path>] [--from-code]"
|
|
11590
|
+
error2(
|
|
11591
|
+
"Usage: decantr suggest <query> [--type <type>] [--route <route>] [--file <path>] [--from-code] [--project <path>]"
|
|
11124
11592
|
)
|
|
11125
11593
|
);
|
|
11126
11594
|
process.exitCode = 1;
|
|
11127
11595
|
return;
|
|
11128
11596
|
}
|
|
11129
|
-
const
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11597
|
+
const workspaceInfo = projectArg ? resolveWorkflowProject(flags, "suggest") : null;
|
|
11598
|
+
if (projectArg && !workspaceInfo) break;
|
|
11599
|
+
await cmdSuggest(query, {
|
|
11600
|
+
type: flagString(flags, "type"),
|
|
11601
|
+
route,
|
|
11602
|
+
file,
|
|
11603
|
+
fromCode,
|
|
11604
|
+
projectRoot: workspaceInfo?.appRoot
|
|
11605
|
+
});
|
|
11137
11606
|
break;
|
|
11138
11607
|
}
|
|
11139
11608
|
case "get": {
|
|
11140
11609
|
const type = args[1];
|
|
11141
11610
|
const id = args[2];
|
|
11142
11611
|
if (!type || !id) {
|
|
11143
|
-
console.error(
|
|
11612
|
+
console.error(error2("Usage: decantr get <type> <id>"));
|
|
11144
11613
|
process.exitCode = 1;
|
|
11145
11614
|
return;
|
|
11146
11615
|
}
|
|
@@ -11151,7 +11620,7 @@ async function main() {
|
|
|
11151
11620
|
const type = args[1];
|
|
11152
11621
|
if (!type) {
|
|
11153
11622
|
console.error(
|
|
11154
|
-
|
|
11623
|
+
error2(
|
|
11155
11624
|
"Usage: decantr list <type> [--sort <recommended|recent|name>] [--source <authored|benchmark|hybrid>] [--blueprint-set <all|featured|certified|labs>]"
|
|
11156
11625
|
)
|
|
11157
11626
|
);
|
|
@@ -11167,7 +11636,7 @@ async function main() {
|
|
|
11167
11636
|
const blueprintSet = rawBlueprintSet && isPublicBlueprintSet(rawBlueprintSet) ? rawBlueprintSet : void 0;
|
|
11168
11637
|
if (rawBlueprintSet && !blueprintSet) {
|
|
11169
11638
|
console.error(
|
|
11170
|
-
|
|
11639
|
+
error2(
|
|
11171
11640
|
`Invalid blueprint set "${rawBlueprintSet}". Must be one of: all, featured, certified, labs.`
|
|
11172
11641
|
)
|
|
11173
11642
|
);
|
|
@@ -11176,7 +11645,7 @@ async function main() {
|
|
|
11176
11645
|
}
|
|
11177
11646
|
if (intelligenceSource && !isContentIntelligenceSource(intelligenceSource)) {
|
|
11178
11647
|
console.error(
|
|
11179
|
-
|
|
11648
|
+
error2(
|
|
11180
11649
|
`Invalid source "${intelligenceSource}". Must be one of: authored, benchmark, hybrid.`
|
|
11181
11650
|
)
|
|
11182
11651
|
);
|
|
@@ -11196,7 +11665,7 @@ async function main() {
|
|
|
11196
11665
|
break;
|
|
11197
11666
|
}
|
|
11198
11667
|
if (requestedView && !["manifest", "shortlist", "verification"].includes(requestedView)) {
|
|
11199
|
-
console.error(
|
|
11668
|
+
console.error(error2("Usage: decantr showcase [manifest|shortlist|verification] [--json]"));
|
|
11200
11669
|
process.exitCode = 1;
|
|
11201
11670
|
break;
|
|
11202
11671
|
}
|
|
@@ -11208,7 +11677,10 @@ async function main() {
|
|
|
11208
11677
|
break;
|
|
11209
11678
|
}
|
|
11210
11679
|
case "theme": {
|
|
11211
|
-
|
|
11680
|
+
const { flags } = parseLooseArgs(args);
|
|
11681
|
+
const workspaceInfo = flagString(flags, "project") ? resolveWorkflowProject(flags, "theme") : null;
|
|
11682
|
+
if (flagString(flags, "project") && !workspaceInfo) break;
|
|
11683
|
+
await cmdTheme(stripProjectArgs(args).slice(1), workspaceInfo?.appRoot ?? process.cwd());
|
|
11212
11684
|
break;
|
|
11213
11685
|
}
|
|
11214
11686
|
case "login": {
|
|
@@ -11242,14 +11714,19 @@ async function main() {
|
|
|
11242
11714
|
break;
|
|
11243
11715
|
}
|
|
11244
11716
|
case "telemetry": {
|
|
11245
|
-
|
|
11717
|
+
const { flags } = parseLooseArgs(args);
|
|
11718
|
+
const workspaceInfo = flagString(flags, "project") ? resolveWorkflowProject(flags, "telemetry") : null;
|
|
11719
|
+
if (flagString(flags, "project") && !workspaceInfo) break;
|
|
11720
|
+
await cmdTelemetry(stripProjectArgs(args).slice(1), workspaceInfo?.appRoot ?? process.cwd());
|
|
11246
11721
|
break;
|
|
11247
11722
|
}
|
|
11248
11723
|
case "create": {
|
|
11724
|
+
const { flags } = parseLooseArgs(args);
|
|
11725
|
+
if (!ensureAllowedFlags(flags, [], "create")) break;
|
|
11249
11726
|
const type = args[1];
|
|
11250
11727
|
const name = args[2];
|
|
11251
11728
|
if (!type || !name) {
|
|
11252
|
-
console.error(
|
|
11729
|
+
console.error(error2("Usage: decantr create <type> <name>"));
|
|
11253
11730
|
console.error(dim3("Types: pattern, theme, blueprint, archetype, shell"));
|
|
11254
11731
|
process.exitCode = 1;
|
|
11255
11732
|
break;
|
|
@@ -11258,10 +11735,12 @@ async function main() {
|
|
|
11258
11735
|
break;
|
|
11259
11736
|
}
|
|
11260
11737
|
case "publish": {
|
|
11738
|
+
const { flags } = parseLooseArgs(args);
|
|
11739
|
+
if (!ensureAllowedFlags(flags, [], "publish")) break;
|
|
11261
11740
|
const type = args[1];
|
|
11262
11741
|
const name = args[2];
|
|
11263
11742
|
if (!type || !name) {
|
|
11264
|
-
console.error(
|
|
11743
|
+
console.error(error2("Usage: decantr publish <type> <name>"));
|
|
11265
11744
|
console.error(dim3("Types: pattern, theme, blueprint, archetype, shell"));
|
|
11266
11745
|
process.exitCode = 1;
|
|
11267
11746
|
break;
|
|
@@ -11278,7 +11757,8 @@ async function main() {
|
|
|
11278
11757
|
offline: refreshOffline,
|
|
11279
11758
|
check: args.includes("--check"),
|
|
11280
11759
|
listChanges: args.includes("--list-changes"),
|
|
11281
|
-
json: args.includes("--json")
|
|
11760
|
+
json: args.includes("--json"),
|
|
11761
|
+
displayRoot: workspaceInfo.cwd
|
|
11282
11762
|
});
|
|
11283
11763
|
break;
|
|
11284
11764
|
}
|
|
@@ -11313,7 +11793,7 @@ async function main() {
|
|
|
11313
11793
|
let id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
|
|
11314
11794
|
if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
|
|
11315
11795
|
console.error(
|
|
11316
|
-
`${
|
|
11796
|
+
`${RED12}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET16}`
|
|
11317
11797
|
);
|
|
11318
11798
|
process.exitCode = 1;
|
|
11319
11799
|
break;
|
|
@@ -11345,7 +11825,7 @@ async function main() {
|
|
|
11345
11825
|
const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
11346
11826
|
if (!sourcePath) {
|
|
11347
11827
|
console.error(
|
|
11348
|
-
`${
|
|
11828
|
+
`${RED12}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET16}`
|
|
11349
11829
|
);
|
|
11350
11830
|
process.exitCode = 1;
|
|
11351
11831
|
break;
|
|
@@ -11370,16 +11850,20 @@ async function main() {
|
|
|
11370
11850
|
await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
|
|
11371
11851
|
} else {
|
|
11372
11852
|
console.error(
|
|
11373
|
-
`${
|
|
11853
|
+
`${RED12}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${RESET16}`
|
|
11374
11854
|
);
|
|
11375
11855
|
process.exitCode = 1;
|
|
11376
11856
|
}
|
|
11377
11857
|
break;
|
|
11378
11858
|
}
|
|
11379
11859
|
case "add": {
|
|
11860
|
+
const { flags } = parseLooseArgs(args);
|
|
11861
|
+
if (!ensureAllowedFlags(flags, ["project", "route", "section"], "add")) break;
|
|
11862
|
+
const workspaceInfo = resolveWorkflowProject(flags, "add");
|
|
11863
|
+
if (!workspaceInfo) break;
|
|
11380
11864
|
const subcommand = args[1];
|
|
11381
11865
|
if (!subcommand) {
|
|
11382
|
-
console.error(
|
|
11866
|
+
console.error(error2("Usage: decantr add <section|page|feature> <target>"));
|
|
11383
11867
|
process.exitCode = 1;
|
|
11384
11868
|
break;
|
|
11385
11869
|
}
|
|
@@ -11387,45 +11871,49 @@ async function main() {
|
|
|
11387
11871
|
case "section": {
|
|
11388
11872
|
const id = args[2];
|
|
11389
11873
|
if (!id) {
|
|
11390
|
-
console.error(
|
|
11874
|
+
console.error(error2("Usage: decantr add section <archetypeId>"));
|
|
11391
11875
|
process.exitCode = 1;
|
|
11392
11876
|
break;
|
|
11393
11877
|
}
|
|
11394
|
-
await cmdAddSection(id, args,
|
|
11878
|
+
await cmdAddSection(id, args, workspaceInfo.appRoot);
|
|
11395
11879
|
break;
|
|
11396
11880
|
}
|
|
11397
11881
|
case "page": {
|
|
11398
11882
|
const pagePath = args[2];
|
|
11399
11883
|
if (!pagePath) {
|
|
11400
|
-
console.error(
|
|
11884
|
+
console.error(error2("Usage: decantr add page <section>/<page>"));
|
|
11401
11885
|
process.exitCode = 1;
|
|
11402
11886
|
break;
|
|
11403
11887
|
}
|
|
11404
|
-
await cmdAddPage(pagePath, args,
|
|
11888
|
+
await cmdAddPage(pagePath, args, workspaceInfo.appRoot);
|
|
11405
11889
|
break;
|
|
11406
11890
|
}
|
|
11407
11891
|
case "feature": {
|
|
11408
11892
|
const feature = args[2];
|
|
11409
11893
|
if (!feature) {
|
|
11410
|
-
console.error(
|
|
11894
|
+
console.error(error2("Usage: decantr add feature <feature> [--section <id>]"));
|
|
11411
11895
|
process.exitCode = 1;
|
|
11412
11896
|
break;
|
|
11413
11897
|
}
|
|
11414
|
-
await cmdAddFeature(feature, args,
|
|
11898
|
+
await cmdAddFeature(feature, args, workspaceInfo.appRoot);
|
|
11415
11899
|
break;
|
|
11416
11900
|
}
|
|
11417
11901
|
default:
|
|
11418
11902
|
console.error(
|
|
11419
|
-
|
|
11903
|
+
error2(`Unknown add subcommand: ${subcommand}. Use section, page, or feature.`)
|
|
11420
11904
|
);
|
|
11421
11905
|
process.exitCode = 1;
|
|
11422
11906
|
}
|
|
11423
11907
|
break;
|
|
11424
11908
|
}
|
|
11425
11909
|
case "remove": {
|
|
11910
|
+
const { flags } = parseLooseArgs(args);
|
|
11911
|
+
if (!ensureAllowedFlags(flags, ["project", "section"], "remove")) break;
|
|
11912
|
+
const workspaceInfo = resolveWorkflowProject(flags, "remove");
|
|
11913
|
+
if (!workspaceInfo) break;
|
|
11426
11914
|
const subcommand = args[1];
|
|
11427
11915
|
if (!subcommand) {
|
|
11428
|
-
console.error(
|
|
11916
|
+
console.error(error2("Usage: decantr remove <section|page|feature> <target>"));
|
|
11429
11917
|
process.exitCode = 1;
|
|
11430
11918
|
break;
|
|
11431
11919
|
}
|
|
@@ -11433,56 +11921,54 @@ async function main() {
|
|
|
11433
11921
|
case "section": {
|
|
11434
11922
|
const id = args[2];
|
|
11435
11923
|
if (!id) {
|
|
11436
|
-
console.error(
|
|
11924
|
+
console.error(error2("Usage: decantr remove section <sectionId>"));
|
|
11437
11925
|
process.exitCode = 1;
|
|
11438
11926
|
break;
|
|
11439
11927
|
}
|
|
11440
|
-
await cmdRemoveSection(id, args,
|
|
11928
|
+
await cmdRemoveSection(id, args, workspaceInfo.appRoot);
|
|
11441
11929
|
break;
|
|
11442
11930
|
}
|
|
11443
11931
|
case "page": {
|
|
11444
11932
|
const pagePath = args[2];
|
|
11445
11933
|
if (!pagePath) {
|
|
11446
|
-
console.error(
|
|
11934
|
+
console.error(error2("Usage: decantr remove page <section>/<page>"));
|
|
11447
11935
|
process.exitCode = 1;
|
|
11448
11936
|
break;
|
|
11449
11937
|
}
|
|
11450
|
-
await cmdRemovePage(pagePath, args,
|
|
11938
|
+
await cmdRemovePage(pagePath, args, workspaceInfo.appRoot);
|
|
11451
11939
|
break;
|
|
11452
11940
|
}
|
|
11453
11941
|
case "feature": {
|
|
11454
11942
|
const feature = args[2];
|
|
11455
11943
|
if (!feature) {
|
|
11456
|
-
console.error(
|
|
11944
|
+
console.error(error2("Usage: decantr remove feature <feature> [--section <id>]"));
|
|
11457
11945
|
process.exitCode = 1;
|
|
11458
11946
|
break;
|
|
11459
11947
|
}
|
|
11460
|
-
await cmdRemoveFeature(feature, args,
|
|
11948
|
+
await cmdRemoveFeature(feature, args, workspaceInfo.appRoot);
|
|
11461
11949
|
break;
|
|
11462
11950
|
}
|
|
11463
11951
|
default:
|
|
11464
11952
|
console.error(
|
|
11465
|
-
|
|
11953
|
+
error2(`Unknown remove subcommand: ${subcommand}. Use section, page, or feature.`)
|
|
11466
11954
|
);
|
|
11467
11955
|
process.exitCode = 1;
|
|
11468
11956
|
}
|
|
11469
11957
|
break;
|
|
11470
11958
|
}
|
|
11471
11959
|
case "analyze": {
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
}
|
|
11479
|
-
}
|
|
11480
|
-
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
11481
|
-
if (workspaceInfo.requiresProjectSelection) {
|
|
11482
|
-
printWorkspaceProjectSelection(workspaceInfo, "analyze");
|
|
11483
|
-
process.exitCode = 1;
|
|
11960
|
+
const { flags } = parseLooseArgs(args);
|
|
11961
|
+
if (!ensureAllowedFlags(
|
|
11962
|
+
flags,
|
|
11963
|
+
["project", "force-package", "allow-package", "force"],
|
|
11964
|
+
"analyze"
|
|
11965
|
+
)) {
|
|
11484
11966
|
break;
|
|
11485
11967
|
}
|
|
11968
|
+
const workspaceInfo = resolveWorkflowProject(flags, "analyze", {
|
|
11969
|
+
requireAppCandidate: true
|
|
11970
|
+
});
|
|
11971
|
+
if (!workspaceInfo) break;
|
|
11486
11972
|
await cmdAnalyze(workspaceInfo.appRoot, workspaceInfo);
|
|
11487
11973
|
break;
|
|
11488
11974
|
}
|
|
@@ -11493,24 +11979,14 @@ async function main() {
|
|
|
11493
11979
|
break;
|
|
11494
11980
|
}
|
|
11495
11981
|
if (subcommand !== "apply" && subcommand !== "preview") {
|
|
11496
|
-
console.error(
|
|
11497
|
-
process.exitCode = 1;
|
|
11498
|
-
break;
|
|
11499
|
-
}
|
|
11500
|
-
let projectArg;
|
|
11501
|
-
for (let i = 2; i < args.length; i++) {
|
|
11502
|
-
if (args[i].startsWith("--project=")) {
|
|
11503
|
-
projectArg = args[i].split("=")[1];
|
|
11504
|
-
} else if (args[i] === "--project" && args[i + 1]) {
|
|
11505
|
-
projectArg = args[++i];
|
|
11506
|
-
}
|
|
11507
|
-
}
|
|
11508
|
-
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
11509
|
-
if (workspaceInfo.requiresProjectSelection) {
|
|
11510
|
-
printWorkspaceProjectSelection(workspaceInfo, "rules");
|
|
11982
|
+
console.error(error2("Usage: decantr rules <preview|apply> [--project=<path>]"));
|
|
11511
11983
|
process.exitCode = 1;
|
|
11512
11984
|
break;
|
|
11513
11985
|
}
|
|
11986
|
+
const { flags } = parseLooseArgs(args);
|
|
11987
|
+
if (!ensureAllowedFlags(flags, ["project"], "rules")) break;
|
|
11988
|
+
const workspaceInfo = resolveWorkflowProject(flags, "rules");
|
|
11989
|
+
if (!workspaceInfo) break;
|
|
11514
11990
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
11515
11991
|
if (subcommand === "preview") {
|
|
11516
11992
|
console.log(
|
|
@@ -11531,24 +12007,18 @@ async function main() {
|
|
|
11531
12007
|
break;
|
|
11532
12008
|
}
|
|
11533
12009
|
case "magic": {
|
|
11534
|
-
const
|
|
11535
|
-
|
|
11536
|
-
|
|
11537
|
-
if (args[i] === "--dry-run") {
|
|
11538
|
-
magicFlags.dryRun = true;
|
|
11539
|
-
} else if (args[i] === "--offline") {
|
|
11540
|
-
magicFlags.offline = true;
|
|
11541
|
-
} else if (args[i].startsWith("--registry=")) {
|
|
11542
|
-
magicFlags.registry = args[i].split("=")[1];
|
|
11543
|
-
} else if (args[i].startsWith("--registry") && args[i + 1]) {
|
|
11544
|
-
magicFlags.registry = args[++i];
|
|
11545
|
-
} else {
|
|
11546
|
-
promptParts.push(args[i]);
|
|
11547
|
-
}
|
|
12010
|
+
const { flags, positional } = parseLooseArgs(args);
|
|
12011
|
+
if (!ensureAllowedFlags(flags, ["dry-run", "offline", "registry", "project"], "magic")) {
|
|
12012
|
+
break;
|
|
11548
12013
|
}
|
|
11549
|
-
const
|
|
12014
|
+
const workspaceInfo = flagString(flags, "project") ? resolveWorkflowProject(flags, "magic") : null;
|
|
12015
|
+
if (flagString(flags, "project") && !workspaceInfo) break;
|
|
12016
|
+
const projectArg = flagString(flags, "project");
|
|
12017
|
+
const magicPrompt = positional.join(" ").trim();
|
|
11550
12018
|
if (!magicPrompt) {
|
|
11551
|
-
console.error(
|
|
12019
|
+
console.error(
|
|
12020
|
+
error2("Usage: decantr magic <prompt> [--dry-run] [--offline] [--project <path>]")
|
|
12021
|
+
);
|
|
11552
12022
|
console.error("");
|
|
11553
12023
|
console.error(" Example:");
|
|
11554
12024
|
console.error(
|
|
@@ -11557,38 +12027,34 @@ async function main() {
|
|
|
11557
12027
|
process.exitCode = 1;
|
|
11558
12028
|
break;
|
|
11559
12029
|
}
|
|
11560
|
-
await cmdMagic(magicPrompt, process.cwd(), {
|
|
11561
|
-
dryRun:
|
|
11562
|
-
offline:
|
|
11563
|
-
registry:
|
|
12030
|
+
await cmdMagic(magicPrompt, workspaceInfo?.appRoot ?? process.cwd(), {
|
|
12031
|
+
dryRun: flagBoolean(flags, "dry-run"),
|
|
12032
|
+
offline: flagBoolean(flags, "offline"),
|
|
12033
|
+
registry: flagString(flags, "registry"),
|
|
12034
|
+
projectLabel: projectArg
|
|
11564
12035
|
});
|
|
11565
12036
|
break;
|
|
11566
12037
|
}
|
|
11567
12038
|
case "export": {
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
exportTarget = args[i].split("=")[1];
|
|
11575
|
-
} else if (args[i] === "--output" && args[i + 1]) {
|
|
11576
|
-
exportOutput = args[++i];
|
|
11577
|
-
} else if (args[i].startsWith("--output=")) {
|
|
11578
|
-
exportOutput = args[i].split("=")[1];
|
|
11579
|
-
}
|
|
11580
|
-
}
|
|
12039
|
+
const { flags } = parseLooseArgs(args);
|
|
12040
|
+
if (!ensureAllowedFlags(flags, ["to", "output", "project"], "export")) break;
|
|
12041
|
+
const workspaceInfo = flagString(flags, "project") ? resolveWorkflowProject(flags, "export") : null;
|
|
12042
|
+
if (flagString(flags, "project") && !workspaceInfo) break;
|
|
12043
|
+
const exportTarget = flagString(flags, "to");
|
|
12044
|
+
const exportOutput = flagString(flags, "output");
|
|
11581
12045
|
const validTargets = ["shadcn", "tailwind", "css-vars", "figma-tokens"];
|
|
11582
12046
|
if (!exportTarget || !validTargets.includes(exportTarget)) {
|
|
11583
|
-
console.error(
|
|
12047
|
+
console.error(error2(`Usage: decantr export --to <${validTargets.join("|")}>`));
|
|
11584
12048
|
process.exitCode = 1;
|
|
11585
12049
|
break;
|
|
11586
12050
|
}
|
|
11587
|
-
await cmdExport(exportTarget, process.cwd(), {
|
|
12051
|
+
await cmdExport(exportTarget, workspaceInfo?.appRoot ?? process.cwd(), {
|
|
12052
|
+
output: exportOutput
|
|
12053
|
+
});
|
|
11588
12054
|
break;
|
|
11589
12055
|
}
|
|
11590
12056
|
default:
|
|
11591
|
-
console.error(
|
|
12057
|
+
console.error(error2(`Unknown command: ${command}`));
|
|
11592
12058
|
cmdHelp();
|
|
11593
12059
|
process.exitCode = 1;
|
|
11594
12060
|
}
|
|
@@ -11603,7 +12069,7 @@ main().then(async () => {
|
|
|
11603
12069
|
success: !process.exitCode || process.exitCode === 0
|
|
11604
12070
|
});
|
|
11605
12071
|
}).catch(async (e) => {
|
|
11606
|
-
console.error(
|
|
12072
|
+
console.error(error2(e.message));
|
|
11607
12073
|
if (e.stack) console.error(e.stack);
|
|
11608
12074
|
process.exitCode = 1;
|
|
11609
12075
|
await sendCliCommandTelemetry({
|