@decantr/cli 2.8.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/dist/bin.js +2 -1
- package/dist/{chunk-ICSLIYSX.js → chunk-FV6DGYD7.js} +49 -8
- package/dist/{chunk-QTPNV5WU.js → chunk-RKZMHS2K.js} +292 -240
- package/dist/chunk-VE6N3XWG.js +78 -0
- package/dist/index.js +2 -1
- package/dist/{studio-MKLBUC3A.js → studio-G3YOU5YF.js} +2 -1
- package/dist/{workspace-KSFWRZEX.js → workspace-U7J3CJY3.js} +4 -1
- package/package.json +4 -4
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
syncRegistry,
|
|
16
16
|
writeExecutionPackBundleArtifacts
|
|
17
17
|
} from "./chunk-V3XAQWKD.js";
|
|
18
|
+
import {
|
|
19
|
+
resolveWorkspaceInfo
|
|
20
|
+
} from "./chunk-VE6N3XWG.js";
|
|
18
21
|
import {
|
|
19
22
|
buildGuardRegistryContext,
|
|
20
23
|
createDoctrineMap,
|
|
@@ -34,8 +37,8 @@ import {
|
|
|
34
37
|
} from "./chunk-KT2ROK2D.js";
|
|
35
38
|
|
|
36
39
|
// src/index.ts
|
|
37
|
-
import { existsSync as
|
|
38
|
-
import { basename as basename3, dirname as
|
|
40
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync14, readdirSync as readdirSync7, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "fs";
|
|
41
|
+
import { basename as basename3, dirname as dirname3, isAbsolute, join as join28, resolve as resolve3 } from "path";
|
|
39
42
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
40
43
|
import { evaluateGuard, isV4 as isV48, validateEssence as validateEssence2 } from "@decantr/essence-spec";
|
|
41
44
|
import {
|
|
@@ -5764,10 +5767,10 @@ var CYAN7 = "\x1B[36m";
|
|
|
5764
5767
|
function ask(question, defaultValue) {
|
|
5765
5768
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
5766
5769
|
const prompt = defaultValue ? `${question} ${DIM13}(${defaultValue})${RESET13}: ` : `${question}: `;
|
|
5767
|
-
return new Promise((
|
|
5770
|
+
return new Promise((resolve4) => {
|
|
5768
5771
|
rl.question(prompt, (answer) => {
|
|
5769
5772
|
rl.close();
|
|
5770
|
-
|
|
5773
|
+
resolve4(answer.trim() || defaultValue || "");
|
|
5771
5774
|
});
|
|
5772
5775
|
});
|
|
5773
5776
|
}
|
|
@@ -6018,7 +6021,7 @@ function mergeWithDefaults(flags, detected, workflowSeed) {
|
|
|
6018
6021
|
}
|
|
6019
6022
|
async function runSimplifiedInit(blueprints) {
|
|
6020
6023
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
6021
|
-
const question = (q) => new Promise((
|
|
6024
|
+
const question = (q) => new Promise((resolve4) => rl.question(q, resolve4));
|
|
6022
6025
|
console.log("\n? What blueprint would you like to scaffold?\n");
|
|
6023
6026
|
console.log(" 1. Decantr default (recommended)");
|
|
6024
6027
|
console.log(" 2. Search registry...\n");
|
|
@@ -6213,76 +6216,6 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
6213
6216
|
};
|
|
6214
6217
|
}
|
|
6215
6218
|
|
|
6216
|
-
// src/workspace.ts
|
|
6217
|
-
import { existsSync as existsSync27, readdirSync as readdirSync7, readFileSync as readFileSync20 } from "fs";
|
|
6218
|
-
import { dirname as dirname3, join as join28, resolve as resolve3 } from "path";
|
|
6219
|
-
function readPackageJson(dir) {
|
|
6220
|
-
const path = join28(dir, "package.json");
|
|
6221
|
-
if (!existsSync27(path)) return null;
|
|
6222
|
-
try {
|
|
6223
|
-
return JSON.parse(readFileSync20(path, "utf-8"));
|
|
6224
|
-
} catch {
|
|
6225
|
-
return null;
|
|
6226
|
-
}
|
|
6227
|
-
}
|
|
6228
|
-
function hasWorkspaceMarker(dir) {
|
|
6229
|
-
if (existsSync27(join28(dir, "pnpm-workspace.yaml")) || existsSync27(join28(dir, "turbo.json")) || existsSync27(join28(dir, "nx.json"))) {
|
|
6230
|
-
return true;
|
|
6231
|
-
}
|
|
6232
|
-
const pkg = readPackageJson(dir);
|
|
6233
|
-
return Boolean(pkg?.workspaces);
|
|
6234
|
-
}
|
|
6235
|
-
function findWorkspaceRoot(startDir) {
|
|
6236
|
-
let current = resolve3(startDir);
|
|
6237
|
-
while (true) {
|
|
6238
|
-
if (hasWorkspaceMarker(current)) return current;
|
|
6239
|
-
const parent = dirname3(current);
|
|
6240
|
-
if (parent === current) return null;
|
|
6241
|
-
current = parent;
|
|
6242
|
-
}
|
|
6243
|
-
}
|
|
6244
|
-
function looksLikeApp(dir) {
|
|
6245
|
-
if (existsSync27(join28(dir, "next.config.js")) || existsSync27(join28(dir, "next.config.ts")) || existsSync27(join28(dir, "next.config.mjs")) || existsSync27(join28(dir, "vite.config.ts")) || existsSync27(join28(dir, "vite.config.js")) || existsSync27(join28(dir, "angular.json")) || existsSync27(join28(dir, "svelte.config.js")) || existsSync27(join28(dir, "svelte.config.ts")) || existsSync27(join28(dir, "astro.config.mjs")) || existsSync27(join28(dir, "src")) || existsSync27(join28(dir, "app")) || existsSync27(join28(dir, "pages"))) {
|
|
6246
|
-
return true;
|
|
6247
|
-
}
|
|
6248
|
-
const pkg = readPackageJson(dir);
|
|
6249
|
-
const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
6250
|
-
return Boolean(
|
|
6251
|
-
deps.react || deps.next || deps.vue || deps.svelte || deps["@angular/core"] || deps.astro || deps.nuxt
|
|
6252
|
-
);
|
|
6253
|
-
}
|
|
6254
|
-
function listWorkspaceApps(workspaceRoot) {
|
|
6255
|
-
const candidates = [];
|
|
6256
|
-
for (const base of ["apps", "packages"]) {
|
|
6257
|
-
const baseDir = join28(workspaceRoot, base);
|
|
6258
|
-
if (!existsSync27(baseDir)) continue;
|
|
6259
|
-
for (const entry of readdirSync7(baseDir, { withFileTypes: true })) {
|
|
6260
|
-
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
6261
|
-
const candidate = join28(baseDir, entry.name);
|
|
6262
|
-
if (looksLikeApp(candidate)) {
|
|
6263
|
-
candidates.push(`${base}/${entry.name}`);
|
|
6264
|
-
}
|
|
6265
|
-
}
|
|
6266
|
-
}
|
|
6267
|
-
return candidates.sort();
|
|
6268
|
-
}
|
|
6269
|
-
function resolveWorkspaceInfo(cwd, projectArg) {
|
|
6270
|
-
const absoluteCwd = resolve3(cwd);
|
|
6271
|
-
const workspaceRoot = findWorkspaceRoot(absoluteCwd) ?? absoluteCwd;
|
|
6272
|
-
const appRoot = projectArg ? resolve3(absoluteCwd, projectArg) : absoluteCwd;
|
|
6273
|
-
const appCandidates = listWorkspaceApps(workspaceRoot);
|
|
6274
|
-
const projectScope = workspaceRoot !== appRoot || appCandidates.length > 0 ? "workspace-app" : "single-app";
|
|
6275
|
-
const requiresProjectSelection = !projectArg && workspaceRoot === absoluteCwd && appCandidates.length > 1;
|
|
6276
|
-
return {
|
|
6277
|
-
cwd: absoluteCwd,
|
|
6278
|
-
workspaceRoot,
|
|
6279
|
-
appRoot,
|
|
6280
|
-
projectScope,
|
|
6281
|
-
appCandidates,
|
|
6282
|
-
requiresProjectSelection
|
|
6283
|
-
};
|
|
6284
|
-
}
|
|
6285
|
-
|
|
6286
6219
|
// src/index.ts
|
|
6287
6220
|
var BOLD7 = "\x1B[1m";
|
|
6288
6221
|
var DIM14 = "\x1B[2m";
|
|
@@ -6810,7 +6743,7 @@ function getPublicAPIClient() {
|
|
|
6810
6743
|
});
|
|
6811
6744
|
}
|
|
6812
6745
|
function resolveUserPath(inputPath, cwd = process.cwd()) {
|
|
6813
|
-
return isAbsolute(inputPath) ? inputPath :
|
|
6746
|
+
return isAbsolute(inputPath) ? inputPath : resolve3(cwd, inputPath);
|
|
6814
6747
|
}
|
|
6815
6748
|
function extractHostedAssetPaths(indexHtml) {
|
|
6816
6749
|
const assetPaths = /* @__PURE__ */ new Set();
|
|
@@ -6823,18 +6756,18 @@ function extractHostedAssetPaths(indexHtml) {
|
|
|
6823
6756
|
return [...assetPaths];
|
|
6824
6757
|
}
|
|
6825
6758
|
function readHostedDistSnapshot(distPath) {
|
|
6826
|
-
const resolvedDistPath = distPath ? resolveUserPath(distPath) :
|
|
6827
|
-
const indexPath =
|
|
6828
|
-
if (!
|
|
6759
|
+
const resolvedDistPath = distPath ? resolveUserPath(distPath) : join28(process.cwd(), "dist");
|
|
6760
|
+
const indexPath = join28(resolvedDistPath, "index.html");
|
|
6761
|
+
if (!existsSync27(indexPath)) {
|
|
6829
6762
|
return void 0;
|
|
6830
6763
|
}
|
|
6831
|
-
const indexHtml =
|
|
6764
|
+
const indexHtml = readFileSync20(indexPath, "utf-8");
|
|
6832
6765
|
const assetPaths = extractHostedAssetPaths(indexHtml);
|
|
6833
6766
|
const assets = {};
|
|
6834
6767
|
for (const assetPath of assetPaths) {
|
|
6835
|
-
const assetFilePath =
|
|
6836
|
-
if (
|
|
6837
|
-
assets[assetPath] =
|
|
6768
|
+
const assetFilePath = join28(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
|
|
6769
|
+
if (existsSync27(assetFilePath)) {
|
|
6770
|
+
assets[assetPath] = readFileSync20(assetFilePath, "utf-8");
|
|
6838
6771
|
}
|
|
6839
6772
|
}
|
|
6840
6773
|
return {
|
|
@@ -6849,7 +6782,7 @@ function isHostedSourceSnapshotFile(path) {
|
|
|
6849
6782
|
function readHostedSourceSnapshot(sourcePath) {
|
|
6850
6783
|
if (!sourcePath) return void 0;
|
|
6851
6784
|
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
6852
|
-
if (!
|
|
6785
|
+
if (!existsSync27(resolvedSourcePath)) {
|
|
6853
6786
|
return void 0;
|
|
6854
6787
|
}
|
|
6855
6788
|
const files = {};
|
|
@@ -6863,17 +6796,17 @@ function readHostedSourceSnapshot(sourcePath) {
|
|
|
6863
6796
|
]);
|
|
6864
6797
|
const rootPrefix = basename3(resolvedSourcePath);
|
|
6865
6798
|
const walk = (absoluteDir, relativeDir) => {
|
|
6866
|
-
for (const entry of
|
|
6799
|
+
for (const entry of readdirSync7(absoluteDir, { withFileTypes: true })) {
|
|
6867
6800
|
if (ignoredDirNames.has(entry.name)) continue;
|
|
6868
|
-
const absolutePath =
|
|
6869
|
-
const relativePath =
|
|
6801
|
+
const absolutePath = join28(absoluteDir, entry.name);
|
|
6802
|
+
const relativePath = join28(relativeDir, entry.name).replace(/\\/g, "/");
|
|
6870
6803
|
if (entry.isDirectory()) {
|
|
6871
6804
|
walk(absolutePath, relativePath);
|
|
6872
6805
|
continue;
|
|
6873
6806
|
}
|
|
6874
6807
|
if (!entry.isFile()) continue;
|
|
6875
6808
|
if (!isHostedSourceSnapshotFile(relativePath)) continue;
|
|
6876
|
-
files[relativePath] =
|
|
6809
|
+
files[relativePath] = readFileSync20(absolutePath, "utf-8");
|
|
6877
6810
|
}
|
|
6878
6811
|
};
|
|
6879
6812
|
walk(resolvedSourcePath, rootPrefix);
|
|
@@ -7024,15 +6957,15 @@ async function printRegistryIntelligenceSummary(namespace, jsonOutput = false) {
|
|
|
7024
6957
|
}
|
|
7025
6958
|
async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
7026
6959
|
const client = getPublicAPIClient();
|
|
7027
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
7028
|
-
if (!
|
|
6960
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join28(process.cwd(), "decantr.essence.json");
|
|
6961
|
+
if (!existsSync27(resolvedPath)) {
|
|
7029
6962
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
7030
6963
|
}
|
|
7031
|
-
const essence = JSON.parse(
|
|
6964
|
+
const essence = JSON.parse(readFileSync20(resolvedPath, "utf-8"));
|
|
7032
6965
|
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
7033
6966
|
let writtenContextPaths = [];
|
|
7034
6967
|
if (writeContext) {
|
|
7035
|
-
const contextDir =
|
|
6968
|
+
const contextDir = join28(process.cwd(), ".decantr", "context");
|
|
7036
6969
|
mkdirSync14(contextDir, { recursive: true });
|
|
7037
6970
|
const written = writeExecutionPackBundleArtifacts(
|
|
7038
6971
|
contextDir,
|
|
@@ -7058,7 +6991,7 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
7058
6991
|
console.log(` Sections: ${typedBundle.sections.length}`);
|
|
7059
6992
|
console.log(` Mutations: ${typedBundle.mutations.length}`);
|
|
7060
6993
|
if (writeContext) {
|
|
7061
|
-
console.log(` Context bundle: ${
|
|
6994
|
+
console.log(` Context bundle: ${join28(process.cwd(), ".decantr", "context")}`);
|
|
7062
6995
|
console.log(` Files written: ${writtenContextPaths.length}`);
|
|
7063
6996
|
}
|
|
7064
6997
|
console.log("");
|
|
@@ -7070,10 +7003,10 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
7070
7003
|
}
|
|
7071
7004
|
}
|
|
7072
7005
|
function resolvePagePackIdForRoute(essencePath, route) {
|
|
7073
|
-
if (!
|
|
7006
|
+
if (!existsSync27(essencePath)) {
|
|
7074
7007
|
throw new Error(`Essence file not found at ${essencePath}`);
|
|
7075
7008
|
}
|
|
7076
|
-
const essence = JSON.parse(
|
|
7009
|
+
const essence = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
7077
7010
|
if (!isV48(essence)) {
|
|
7078
7011
|
throw new Error("Route-based pack resolution requires Essence v4.0.0.");
|
|
7079
7012
|
}
|
|
@@ -7088,14 +7021,14 @@ function resolvePagePackIdForRoute(essencePath, route) {
|
|
|
7088
7021
|
}
|
|
7089
7022
|
async function printHostedSelectedExecutionPack(packType, id, essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
7090
7023
|
const client = getPublicAPIClient();
|
|
7091
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
7092
|
-
if (!
|
|
7024
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join28(process.cwd(), "decantr.essence.json");
|
|
7025
|
+
if (!existsSync27(resolvedPath)) {
|
|
7093
7026
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
7094
7027
|
}
|
|
7095
7028
|
if ((packType === "section" || packType === "page" || packType === "mutation") && !id) {
|
|
7096
7029
|
throw new Error(`Pack type "${packType}" requires an id.`);
|
|
7097
7030
|
}
|
|
7098
|
-
const essence = JSON.parse(
|
|
7031
|
+
const essence = JSON.parse(readFileSync20(resolvedPath, "utf-8"));
|
|
7099
7032
|
const selected = await client.selectExecutionPack(
|
|
7100
7033
|
{
|
|
7101
7034
|
essence,
|
|
@@ -7106,17 +7039,17 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
7106
7039
|
);
|
|
7107
7040
|
let writtenContextDir = null;
|
|
7108
7041
|
if (writeContext) {
|
|
7109
|
-
const contextDir =
|
|
7042
|
+
const contextDir = join28(process.cwd(), ".decantr", "context");
|
|
7110
7043
|
mkdirSync14(contextDir, { recursive: true });
|
|
7111
7044
|
writeFileSync17(
|
|
7112
|
-
|
|
7045
|
+
join28(contextDir, "pack-manifest.json"),
|
|
7113
7046
|
JSON.stringify(selected.manifest, null, 2) + "\n"
|
|
7114
7047
|
);
|
|
7115
7048
|
const manifestEntry = selected.selector.packType === "scaffold" ? selected.manifest.scaffold : selected.selector.packType === "review" ? selected.manifest.review : selected.selector.packType === "section" ? selected.manifest.sections.find((entry) => entry.id === selected.selector.id) : selected.selector.packType === "page" ? selected.manifest.pages.find((entry) => entry.id === selected.selector.id) : selected.manifest.mutations.find((entry) => entry.id === selected.selector.id);
|
|
7116
7049
|
const markdownFile = manifestEntry?.markdown ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.md`;
|
|
7117
7050
|
const jsonFile = manifestEntry?.json ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.json`;
|
|
7118
|
-
writeFileSync17(
|
|
7119
|
-
writeFileSync17(
|
|
7051
|
+
writeFileSync17(join28(contextDir, markdownFile), selected.pack.renderedMarkdown);
|
|
7052
|
+
writeFileSync17(join28(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
|
|
7120
7053
|
writtenContextDir = contextDir;
|
|
7121
7054
|
}
|
|
7122
7055
|
if (jsonOutput) {
|
|
@@ -7141,20 +7074,20 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
7141
7074
|
}
|
|
7142
7075
|
async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
7143
7076
|
const client = getPublicAPIClient();
|
|
7144
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
7145
|
-
if (!
|
|
7077
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join28(process.cwd(), "decantr.essence.json");
|
|
7078
|
+
if (!existsSync27(resolvedPath)) {
|
|
7146
7079
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
7147
7080
|
}
|
|
7148
|
-
const essence = JSON.parse(
|
|
7081
|
+
const essence = JSON.parse(readFileSync20(resolvedPath, "utf-8"));
|
|
7149
7082
|
const manifest = await client.getExecutionPackManifest(
|
|
7150
7083
|
essence,
|
|
7151
7084
|
namespace ? { namespace } : void 0
|
|
7152
7085
|
);
|
|
7153
7086
|
let writtenContextDir = null;
|
|
7154
7087
|
if (writeContext) {
|
|
7155
|
-
const contextDir =
|
|
7088
|
+
const contextDir = join28(process.cwd(), ".decantr", "context");
|
|
7156
7089
|
mkdirSync14(contextDir, { recursive: true });
|
|
7157
|
-
writeFileSync17(
|
|
7090
|
+
writeFileSync17(join28(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
7158
7091
|
writtenContextDir = contextDir;
|
|
7159
7092
|
}
|
|
7160
7093
|
if (jsonOutput) {
|
|
@@ -7175,14 +7108,14 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
|
|
|
7175
7108
|
}
|
|
7176
7109
|
}
|
|
7177
7110
|
async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@official") {
|
|
7178
|
-
const contextDir =
|
|
7179
|
-
const reviewPackPath =
|
|
7180
|
-
const manifestPath =
|
|
7181
|
-
if (
|
|
7111
|
+
const contextDir = join28(projectRoot, ".decantr", "context");
|
|
7112
|
+
const reviewPackPath = join28(contextDir, "review-pack.json");
|
|
7113
|
+
const manifestPath = join28(contextDir, "pack-manifest.json");
|
|
7114
|
+
if (existsSync27(reviewPackPath) && existsSync27(manifestPath)) {
|
|
7182
7115
|
return { attempted: false, hydrated: false };
|
|
7183
7116
|
}
|
|
7184
|
-
const essencePath =
|
|
7185
|
-
if (!
|
|
7117
|
+
const essencePath = join28(projectRoot, "decantr.essence.json");
|
|
7118
|
+
if (!existsSync27(essencePath)) {
|
|
7186
7119
|
return { attempted: false, hydrated: false };
|
|
7187
7120
|
}
|
|
7188
7121
|
const reviewHydration = await hydrateHostedReviewPackIfMissing(projectRoot, namespace);
|
|
@@ -7191,7 +7124,7 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
7191
7124
|
}
|
|
7192
7125
|
try {
|
|
7193
7126
|
const client = getPublicAPIClient();
|
|
7194
|
-
const essence = JSON.parse(
|
|
7127
|
+
const essence = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
7195
7128
|
const bundle = await client.compileExecutionPacks(essence, { namespace });
|
|
7196
7129
|
mkdirSync14(contextDir, { recursive: true });
|
|
7197
7130
|
writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
@@ -7201,19 +7134,19 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
7201
7134
|
}
|
|
7202
7135
|
}
|
|
7203
7136
|
async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@official") {
|
|
7204
|
-
const contextDir =
|
|
7205
|
-
const reviewPackPath =
|
|
7206
|
-
const manifestPath =
|
|
7207
|
-
if (
|
|
7137
|
+
const contextDir = join28(projectRoot, ".decantr", "context");
|
|
7138
|
+
const reviewPackPath = join28(contextDir, "review-pack.json");
|
|
7139
|
+
const manifestPath = join28(contextDir, "pack-manifest.json");
|
|
7140
|
+
if (existsSync27(reviewPackPath) && existsSync27(manifestPath)) {
|
|
7208
7141
|
return { attempted: false, hydrated: false };
|
|
7209
7142
|
}
|
|
7210
|
-
const essencePath =
|
|
7211
|
-
if (!
|
|
7143
|
+
const essencePath = join28(projectRoot, "decantr.essence.json");
|
|
7144
|
+
if (!existsSync27(essencePath)) {
|
|
7212
7145
|
return { attempted: false, hydrated: false };
|
|
7213
7146
|
}
|
|
7214
7147
|
try {
|
|
7215
7148
|
const client = getPublicAPIClient();
|
|
7216
|
-
const essence = JSON.parse(
|
|
7149
|
+
const essence = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
7217
7150
|
const selected = await client.selectExecutionPack(
|
|
7218
7151
|
{
|
|
7219
7152
|
essence,
|
|
@@ -7222,12 +7155,12 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
7222
7155
|
{ namespace }
|
|
7223
7156
|
);
|
|
7224
7157
|
mkdirSync14(contextDir, { recursive: true });
|
|
7225
|
-
writeFileSync17(
|
|
7158
|
+
writeFileSync17(join28(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
|
|
7226
7159
|
writeFileSync17(
|
|
7227
|
-
|
|
7160
|
+
join28(contextDir, "review-pack.json"),
|
|
7228
7161
|
JSON.stringify(selected.pack, null, 2) + "\n"
|
|
7229
7162
|
);
|
|
7230
|
-
if (!
|
|
7163
|
+
if (!existsSync27(manifestPath)) {
|
|
7231
7164
|
writeFileSync17(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
|
|
7232
7165
|
}
|
|
7233
7166
|
return { attempted: true, hydrated: true, scope: "review" };
|
|
@@ -7238,17 +7171,17 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
7238
7171
|
async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false, essencePath, treatmentsPath) {
|
|
7239
7172
|
const client = getPublicAPIClient();
|
|
7240
7173
|
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
7241
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) :
|
|
7242
|
-
const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) :
|
|
7243
|
-
if (!
|
|
7174
|
+
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join28(process.cwd(), "decantr.essence.json");
|
|
7175
|
+
const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join28(process.cwd(), "src", "styles", "treatments.css");
|
|
7176
|
+
if (!existsSync27(resolvedSourcePath)) {
|
|
7244
7177
|
throw new Error(`Source file not found at ${resolvedSourcePath}`);
|
|
7245
7178
|
}
|
|
7246
|
-
if (!
|
|
7179
|
+
if (!existsSync27(resolvedEssencePath)) {
|
|
7247
7180
|
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
7248
7181
|
}
|
|
7249
|
-
const code =
|
|
7250
|
-
const essence = JSON.parse(
|
|
7251
|
-
const treatmentsCss =
|
|
7182
|
+
const code = readFileSync20(resolvedSourcePath, "utf-8");
|
|
7183
|
+
const essence = JSON.parse(readFileSync20(resolvedEssencePath, "utf-8"));
|
|
7184
|
+
const treatmentsCss = existsSync27(resolvedTreatmentsPath) ? readFileSync20(resolvedTreatmentsPath, "utf-8") : void 0;
|
|
7252
7185
|
const report = await client.critiqueFile(
|
|
7253
7186
|
{
|
|
7254
7187
|
essence,
|
|
@@ -7272,11 +7205,11 @@ async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false
|
|
|
7272
7205
|
}
|
|
7273
7206
|
async function printHostedProjectAudit(namespace, jsonOutput = false, essencePath, distPath, sourcesPath) {
|
|
7274
7207
|
const client = getPublicAPIClient();
|
|
7275
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) :
|
|
7276
|
-
if (!
|
|
7208
|
+
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join28(process.cwd(), "decantr.essence.json");
|
|
7209
|
+
if (!existsSync27(resolvedEssencePath)) {
|
|
7277
7210
|
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
7278
7211
|
}
|
|
7279
|
-
const essence = JSON.parse(
|
|
7212
|
+
const essence = JSON.parse(readFileSync20(resolvedEssencePath, "utf-8"));
|
|
7280
7213
|
const dist = readHostedDistSnapshot(distPath);
|
|
7281
7214
|
const sources = readHostedSourceSnapshot(sourcesPath);
|
|
7282
7215
|
const report = await client.auditProject(
|
|
@@ -7294,7 +7227,7 @@ async function printHostedProjectAudit(namespace, jsonOutput = false, essencePat
|
|
|
7294
7227
|
console.log(heading2("Hosted Project Audit"));
|
|
7295
7228
|
console.log(` Essence: ${resolvedEssencePath}`);
|
|
7296
7229
|
console.log(
|
|
7297
|
-
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) :
|
|
7230
|
+
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join28(process.cwd(), "dist") : "none"}`
|
|
7298
7231
|
);
|
|
7299
7232
|
console.log(
|
|
7300
7233
|
` Source snapshot: ${sources && sourcesPath ? resolveUserPath(sourcesPath) : "none"}`
|
|
@@ -7397,21 +7330,21 @@ function patternCandidateFromRegistryItem(item, source) {
|
|
|
7397
7330
|
function readSuggestCodeContext(route, file) {
|
|
7398
7331
|
const pieces = [];
|
|
7399
7332
|
if (file) {
|
|
7400
|
-
const resolved = isAbsolute(file) ? file :
|
|
7401
|
-
if (
|
|
7402
|
-
pieces.push(
|
|
7333
|
+
const resolved = isAbsolute(file) ? file : join28(process.cwd(), file);
|
|
7334
|
+
if (existsSync27(resolved)) {
|
|
7335
|
+
pieces.push(readFileSync20(resolved, "utf-8"));
|
|
7403
7336
|
}
|
|
7404
7337
|
}
|
|
7405
7338
|
if (route) {
|
|
7406
|
-
const analysisPath =
|
|
7407
|
-
if (
|
|
7339
|
+
const analysisPath = join28(process.cwd(), ".decantr", "analysis.json");
|
|
7340
|
+
if (existsSync27(analysisPath)) {
|
|
7408
7341
|
try {
|
|
7409
|
-
const analysis = JSON.parse(
|
|
7342
|
+
const analysis = JSON.parse(readFileSync20(analysisPath, "utf-8"));
|
|
7410
7343
|
const routeEntry = analysis.routes?.routes?.find((entry) => entry.path === route);
|
|
7411
7344
|
if (routeEntry?.file) {
|
|
7412
|
-
const resolved =
|
|
7413
|
-
if (
|
|
7414
|
-
pieces.push(
|
|
7345
|
+
const resolved = join28(process.cwd(), routeEntry.file);
|
|
7346
|
+
if (existsSync27(resolved)) {
|
|
7347
|
+
pieces.push(readFileSync20(resolved, "utf-8"));
|
|
7415
7348
|
}
|
|
7416
7349
|
}
|
|
7417
7350
|
} catch {
|
|
@@ -7468,7 +7401,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
7468
7401
|
}
|
|
7469
7402
|
}
|
|
7470
7403
|
const registryClient = new RegistryClient({
|
|
7471
|
-
cacheDir:
|
|
7404
|
+
cacheDir: join28(process.cwd(), ".decantr", "cache")
|
|
7472
7405
|
});
|
|
7473
7406
|
const code = options.fromCode || options.file ? readSuggestCodeContext(options.route, options.file) : "";
|
|
7474
7407
|
const candidates = await loadPatternDiscoveryCandidates(registryClient);
|
|
@@ -7530,7 +7463,7 @@ async function cmdGet(type, id) {
|
|
|
7530
7463
|
}
|
|
7531
7464
|
const apiType = CONTENT_TYPE_TO_API_CONTENT_TYPE3[type];
|
|
7532
7465
|
const registryClient = new RegistryClient({
|
|
7533
|
-
cacheDir:
|
|
7466
|
+
cacheDir: join28(process.cwd(), ".decantr", "cache")
|
|
7534
7467
|
});
|
|
7535
7468
|
const result = await registryClient.fetchContentItem(apiType, id);
|
|
7536
7469
|
if (result) {
|
|
@@ -7547,10 +7480,10 @@ async function cmdGet(type, id) {
|
|
|
7547
7480
|
return;
|
|
7548
7481
|
}
|
|
7549
7482
|
async function cmdValidate(path) {
|
|
7550
|
-
const essencePath = path ||
|
|
7483
|
+
const essencePath = path || join28(process.cwd(), "decantr.essence.json");
|
|
7551
7484
|
let raw;
|
|
7552
7485
|
try {
|
|
7553
|
-
raw =
|
|
7486
|
+
raw = readFileSync20(essencePath, "utf-8");
|
|
7554
7487
|
} catch {
|
|
7555
7488
|
console.error(error3(`Could not read ${essencePath}`));
|
|
7556
7489
|
process.exitCode = 1;
|
|
@@ -7617,7 +7550,7 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
|
|
|
7617
7550
|
return;
|
|
7618
7551
|
}
|
|
7619
7552
|
const registryClient = new RegistryClient({
|
|
7620
|
-
cacheDir:
|
|
7553
|
+
cacheDir: join28(process.cwd(), ".decantr", "cache")
|
|
7621
7554
|
});
|
|
7622
7555
|
const result = await registryClient.fetchContentList(
|
|
7623
7556
|
type,
|
|
@@ -7699,11 +7632,11 @@ ${CYAN8}Telemetry enabled.${RESET14} Decantr will send privacy-filtered CLI prod
|
|
|
7699
7632
|
console.log(`${DIM14}Set "telemetry": false in .decantr/project.json to opt out.${RESET14}`);
|
|
7700
7633
|
}
|
|
7701
7634
|
function readCliPackageVersion() {
|
|
7702
|
-
const here =
|
|
7703
|
-
const candidates = [
|
|
7635
|
+
const here = dirname3(fileURLToPath2(import.meta.url));
|
|
7636
|
+
const candidates = [join28(here, "..", "package.json"), join28(here, "..", "..", "package.json")];
|
|
7704
7637
|
for (const candidate of candidates) {
|
|
7705
7638
|
try {
|
|
7706
|
-
const pkg = JSON.parse(
|
|
7639
|
+
const pkg = JSON.parse(readFileSync20(candidate, "utf-8"));
|
|
7707
7640
|
if (pkg.version) return pkg.version;
|
|
7708
7641
|
} catch {
|
|
7709
7642
|
}
|
|
@@ -7714,19 +7647,19 @@ function timestampForFile() {
|
|
|
7714
7647
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7715
7648
|
}
|
|
7716
7649
|
function backupExistingEssence(projectRoot, label) {
|
|
7717
|
-
const essencePath =
|
|
7718
|
-
if (!
|
|
7719
|
-
const backupPath =
|
|
7650
|
+
const essencePath = join28(projectRoot, "decantr.essence.json");
|
|
7651
|
+
if (!existsSync27(essencePath)) return null;
|
|
7652
|
+
const backupPath = join28(
|
|
7720
7653
|
projectRoot,
|
|
7721
7654
|
`decantr.essence.${label}.${timestampForFile()}.backup.json`
|
|
7722
7655
|
);
|
|
7723
|
-
writeFileSync17(backupPath,
|
|
7656
|
+
writeFileSync17(backupPath, readFileSync20(essencePath, "utf-8"), "utf-8");
|
|
7724
7657
|
return backupPath;
|
|
7725
7658
|
}
|
|
7726
7659
|
function writeBrownfieldProjectJson(input) {
|
|
7727
|
-
const decantrDir =
|
|
7728
|
-
mkdirSync14(
|
|
7729
|
-
mkdirSync14(
|
|
7660
|
+
const decantrDir = join28(input.projectRoot, ".decantr");
|
|
7661
|
+
mkdirSync14(join28(decantrDir, "context"), { recursive: true });
|
|
7662
|
+
mkdirSync14(join28(decantrDir, "cache"), { recursive: true });
|
|
7730
7663
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7731
7664
|
const projectJson = {
|
|
7732
7665
|
detected: {
|
|
@@ -7767,7 +7700,7 @@ function writeBrownfieldProjectJson(input) {
|
|
|
7767
7700
|
}
|
|
7768
7701
|
}
|
|
7769
7702
|
};
|
|
7770
|
-
writeFileSync17(
|
|
7703
|
+
writeFileSync17(join28(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
|
|
7771
7704
|
}
|
|
7772
7705
|
async function applyAcceptedBrownfieldProposal(input) {
|
|
7773
7706
|
const proposal = readBrownfieldProposal(input.projectRoot);
|
|
@@ -7783,8 +7716,8 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
7783
7716
|
process.exitCode = 1;
|
|
7784
7717
|
return;
|
|
7785
7718
|
}
|
|
7786
|
-
const essencePath =
|
|
7787
|
-
const hasEssence =
|
|
7719
|
+
const essencePath = join28(input.projectRoot, "decantr.essence.json");
|
|
7720
|
+
const hasEssence = existsSync27(essencePath);
|
|
7788
7721
|
let essence;
|
|
7789
7722
|
let backupPath = null;
|
|
7790
7723
|
if (input.mode === "accept" && hasEssence) {
|
|
@@ -7798,7 +7731,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
7798
7731
|
return;
|
|
7799
7732
|
}
|
|
7800
7733
|
if (input.mode === "merge" && hasEssence) {
|
|
7801
|
-
const existing = JSON.parse(
|
|
7734
|
+
const existing = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
7802
7735
|
if (!isV48(existing)) {
|
|
7803
7736
|
console.log(
|
|
7804
7737
|
error3(
|
|
@@ -7837,7 +7770,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
7837
7770
|
});
|
|
7838
7771
|
writeFileSync17(essencePath, JSON.stringify(essence, null, 2) + "\n", "utf-8");
|
|
7839
7772
|
const registryClient = new RegistryClient({
|
|
7840
|
-
cacheDir:
|
|
7773
|
+
cacheDir: join28(input.projectRoot, ".decantr", "cache"),
|
|
7841
7774
|
offline: true,
|
|
7842
7775
|
projectRoot: input.projectRoot
|
|
7843
7776
|
});
|
|
@@ -7896,8 +7829,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
7896
7829
|
async function cmdInit(args) {
|
|
7897
7830
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), args.project);
|
|
7898
7831
|
if (args.yes && workspaceInfo.requiresProjectSelection) {
|
|
7899
|
-
|
|
7900
|
-
console.log(dim3(`Use --project=<path>. Candidates: ${workspaceInfo.appCandidates.join(", ")}`));
|
|
7832
|
+
printWorkspaceProjectSelection(workspaceInfo, "init");
|
|
7901
7833
|
process.exitCode = 1;
|
|
7902
7834
|
return;
|
|
7903
7835
|
}
|
|
@@ -7991,7 +7923,7 @@ async function cmdInit(args) {
|
|
|
7991
7923
|
}
|
|
7992
7924
|
}
|
|
7993
7925
|
const registryClient = new RegistryClient({
|
|
7994
|
-
cacheDir:
|
|
7926
|
+
cacheDir: join28(projectRoot, ".decantr", "cache"),
|
|
7995
7927
|
apiUrl: args.registry,
|
|
7996
7928
|
offline: args.offline,
|
|
7997
7929
|
projectRoot
|
|
@@ -8321,7 +8253,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET14}`);
|
|
|
8321
8253
|
if (appliedRuleFiles.length > 0) {
|
|
8322
8254
|
console.log(` ${dim3(`Rule bridge applied: ${appliedRuleFiles.join(", ")}`)}`);
|
|
8323
8255
|
}
|
|
8324
|
-
if (!
|
|
8256
|
+
if (!existsSync27(join28(projectRoot, "package.json"))) {
|
|
8325
8257
|
console.log("");
|
|
8326
8258
|
console.log(
|
|
8327
8259
|
dim3(` Note: ${cyan3("decantr init")} created Decantr contract/context files only.`)
|
|
@@ -8332,7 +8264,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET14}`);
|
|
|
8332
8264
|
)
|
|
8333
8265
|
);
|
|
8334
8266
|
}
|
|
8335
|
-
const hasCompiledPacks =
|
|
8267
|
+
const hasCompiledPacks = existsSync27(join28(projectRoot, ".decantr", "context", "scaffold-pack.md"));
|
|
8336
8268
|
console.log("");
|
|
8337
8269
|
console.log(" Next steps:");
|
|
8338
8270
|
if (hasCompiledPacks) {
|
|
@@ -8372,7 +8304,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET14}`);
|
|
|
8372
8304
|
console.log(` ${cyan3("decantr upgrade")} Update to latest patterns`);
|
|
8373
8305
|
console.log(` ${cyan3("decantr check")} Detect drift issues`);
|
|
8374
8306
|
console.log(` ${cyan3("decantr migrate --to v4")} Migrate older essence files to v4`);
|
|
8375
|
-
const essenceContent =
|
|
8307
|
+
const essenceContent = readFileSync20(result.essencePath, "utf-8");
|
|
8376
8308
|
const essence = JSON.parse(essenceContent);
|
|
8377
8309
|
const validation = validateEssence2(essence);
|
|
8378
8310
|
if (!validation.valid) {
|
|
@@ -8428,16 +8360,16 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
8428
8360
|
}
|
|
8429
8361
|
async function cmdStatus() {
|
|
8430
8362
|
const projectRoot = process.cwd();
|
|
8431
|
-
const essencePath =
|
|
8432
|
-
const projectJsonPath =
|
|
8363
|
+
const essencePath = join28(projectRoot, "decantr.essence.json");
|
|
8364
|
+
const projectJsonPath = join28(projectRoot, ".decantr", "project.json");
|
|
8433
8365
|
console.log(heading2("Decantr Project Status"));
|
|
8434
|
-
if (!
|
|
8366
|
+
if (!existsSync27(essencePath)) {
|
|
8435
8367
|
console.log(`${RED11}No decantr.essence.json found.${RESET14}`);
|
|
8436
8368
|
console.log(dim3('Run "decantr init" to create one.'));
|
|
8437
8369
|
return;
|
|
8438
8370
|
}
|
|
8439
8371
|
try {
|
|
8440
|
-
const essence = JSON.parse(
|
|
8372
|
+
const essence = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
8441
8373
|
const validation = validateEssence2(essence);
|
|
8442
8374
|
const essenceVersion = isV48(essence) ? "v4" : "legacy";
|
|
8443
8375
|
console.log(`${BOLD7}Essence:${RESET14}`);
|
|
@@ -8485,9 +8417,9 @@ async function cmdStatus() {
|
|
|
8485
8417
|
}
|
|
8486
8418
|
console.log("");
|
|
8487
8419
|
console.log(`${BOLD7}Sync Status:${RESET14}`);
|
|
8488
|
-
if (
|
|
8420
|
+
if (existsSync27(projectJsonPath)) {
|
|
8489
8421
|
try {
|
|
8490
|
-
const projectJson = JSON.parse(
|
|
8422
|
+
const projectJson = JSON.parse(readFileSync20(projectJsonPath, "utf-8"));
|
|
8491
8423
|
const syncStatus = projectJson.sync?.status || "unknown";
|
|
8492
8424
|
const lastSync = projectJson.sync?.lastSync || "never";
|
|
8493
8425
|
const source = projectJson.sync?.registrySource || "unknown";
|
|
@@ -8505,7 +8437,7 @@ async function cmdStatus() {
|
|
|
8505
8437
|
}
|
|
8506
8438
|
async function cmdSync() {
|
|
8507
8439
|
const projectRoot = process.cwd();
|
|
8508
|
-
const cacheDir =
|
|
8440
|
+
const cacheDir = join28(projectRoot, ".decantr", "cache");
|
|
8509
8441
|
console.log(heading2("Syncing registry content..."));
|
|
8510
8442
|
const result = await syncRegistry(cacheDir);
|
|
8511
8443
|
if (result.synced.length > 0) {
|
|
@@ -8700,14 +8632,14 @@ ${BOLD7}Examples:${RESET14}
|
|
|
8700
8632
|
process.exitCode = 1;
|
|
8701
8633
|
return;
|
|
8702
8634
|
}
|
|
8703
|
-
const themePath =
|
|
8704
|
-
if (!
|
|
8635
|
+
const themePath = join28(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
|
|
8636
|
+
if (!existsSync27(themePath)) {
|
|
8705
8637
|
console.error(error3(`Theme "${name}" not found at ${themePath}`));
|
|
8706
8638
|
process.exitCode = 1;
|
|
8707
8639
|
return;
|
|
8708
8640
|
}
|
|
8709
8641
|
try {
|
|
8710
|
-
const theme = JSON.parse(
|
|
8642
|
+
const theme = JSON.parse(readFileSync20(themePath, "utf-8"));
|
|
8711
8643
|
const result = validateCustomTheme(theme);
|
|
8712
8644
|
if (result.valid) {
|
|
8713
8645
|
console.log(success3(`Custom theme "${name}" is valid`));
|
|
@@ -8835,12 +8767,69 @@ function withoutWorkflowOnlyFlags(args) {
|
|
|
8835
8767
|
}
|
|
8836
8768
|
return stripped;
|
|
8837
8769
|
}
|
|
8838
|
-
function
|
|
8770
|
+
function withProject(command, projectArg) {
|
|
8771
|
+
return projectArg ? `${command} --project ${projectArg}` : command;
|
|
8772
|
+
}
|
|
8773
|
+
function firstWorkspaceCandidate(workspaceInfo) {
|
|
8774
|
+
return workspaceInfo.appCandidates[0] ?? "apps/web";
|
|
8775
|
+
}
|
|
8776
|
+
function printWorkspaceProjectSelection(workspaceInfo, commandName = "command") {
|
|
8777
|
+
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
8778
|
+
const noun = commandName === "adopt" ? "Brownfield adoption" : `decantr ${commandName}`;
|
|
8779
|
+
console.log(error3(`${noun} needs an app path.`));
|
|
8780
|
+
console.log("");
|
|
8781
|
+
console.log(`${BOLD7}This looks like a monorepo.${RESET14}`);
|
|
8782
|
+
console.log("Install Decantr at the workspace root, then attach it to one app with --project.");
|
|
8783
|
+
console.log("");
|
|
8784
|
+
console.log("App candidates:");
|
|
8785
|
+
for (const appCandidate of workspaceInfo.appCandidates) {
|
|
8786
|
+
console.log(` ${appCandidate}`);
|
|
8787
|
+
}
|
|
8788
|
+
console.log("");
|
|
8789
|
+
console.log("Start by attaching one app:");
|
|
8790
|
+
console.log(` ${cyan3(`decantr adopt --project ${candidate} --yes`)}`);
|
|
8791
|
+
console.log("");
|
|
8792
|
+
console.log("Optional visual evidence after the app is running:");
|
|
8793
|
+
console.log(
|
|
8794
|
+
` ${cyan3(`decantr verify --project ${candidate} --base-url http://localhost:3000 --evidence`)}`
|
|
8795
|
+
);
|
|
8796
|
+
}
|
|
8797
|
+
function printMonorepoSetupGuidance(workspaceInfo) {
|
|
8798
|
+
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
8799
|
+
console.log(heading2("Decantr Setup"));
|
|
8800
|
+
console.log(`${BOLD7}This looks like a monorepo.${RESET14}`);
|
|
8801
|
+
console.log(` Workspace root: ${workspaceInfo.workspaceRoot}`);
|
|
8802
|
+
console.log("");
|
|
8803
|
+
console.log(
|
|
8804
|
+
"Install Decantr at the workspace root, then attach it to the app you want Decantr to govern."
|
|
8805
|
+
);
|
|
8806
|
+
console.log("");
|
|
8807
|
+
console.log("App candidates:");
|
|
8808
|
+
for (const appCandidate of workspaceInfo.appCandidates) {
|
|
8809
|
+
console.log(` ${appCandidate}`);
|
|
8810
|
+
}
|
|
8811
|
+
console.log("");
|
|
8812
|
+
console.log(`${BOLD7}Start here:${RESET14}`);
|
|
8813
|
+
console.log(
|
|
8814
|
+
` ${cyan3("decantr workspace list")} Show attached projects and app candidates`
|
|
8815
|
+
);
|
|
8816
|
+
console.log(
|
|
8817
|
+
` ${cyan3(`decantr adopt --project ${candidate} --yes`)} Attach Decantr to one app`
|
|
8818
|
+
);
|
|
8819
|
+
console.log(
|
|
8820
|
+
` ${cyan3(`decantr codify --from-audit --project ${candidate}`)} Propose project-owned UI law`
|
|
8821
|
+
);
|
|
8822
|
+
console.log("");
|
|
8823
|
+
console.log(`${BOLD7}Optional visual evidence:${RESET14}`);
|
|
8824
|
+
console.log(
|
|
8825
|
+
` ${cyan3(`decantr verify --project ${candidate} --base-url http://localhost:3000 --evidence`)}`
|
|
8826
|
+
);
|
|
8827
|
+
}
|
|
8828
|
+
function resolveWorkflowProject(flags, commandName = "command") {
|
|
8839
8829
|
const projectArg = flagString(flags, "project");
|
|
8840
8830
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
8841
8831
|
if (workspaceInfo.requiresProjectSelection) {
|
|
8842
|
-
|
|
8843
|
-
console.log(dim3(`Use --project=<path>. Candidates: ${workspaceInfo.appCandidates.join(", ")}`));
|
|
8832
|
+
printWorkspaceProjectSelection(workspaceInfo, commandName);
|
|
8844
8833
|
process.exitCode = 1;
|
|
8845
8834
|
return null;
|
|
8846
8835
|
}
|
|
@@ -8856,8 +8845,17 @@ function printWorkflowPlan(title, steps) {
|
|
|
8856
8845
|
}
|
|
8857
8846
|
async function cmdSetupWorkflow(args) {
|
|
8858
8847
|
const { flags } = parseLooseArgs(args);
|
|
8859
|
-
const
|
|
8860
|
-
|
|
8848
|
+
const projectArg = flagString(flags, "project");
|
|
8849
|
+
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
8850
|
+
if (!projectArg && workspaceInfo.workspaceRoot === workspaceInfo.cwd && workspaceInfo.appCandidates.length > 0) {
|
|
8851
|
+
printMonorepoSetupGuidance(workspaceInfo);
|
|
8852
|
+
return;
|
|
8853
|
+
}
|
|
8854
|
+
if (workspaceInfo.requiresProjectSelection) {
|
|
8855
|
+
printWorkspaceProjectSelection(workspaceInfo, "setup");
|
|
8856
|
+
process.exitCode = 1;
|
|
8857
|
+
return;
|
|
8858
|
+
}
|
|
8861
8859
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
8862
8860
|
const hasFootprint = detected.framework !== "unknown" || detected.packageManager !== "unknown" || detected.hasTypeScript || detected.hasTailwind || detected.existingRuleFiles.length > 0;
|
|
8863
8861
|
console.log(heading2("Decantr Setup"));
|
|
@@ -8866,18 +8864,30 @@ async function cmdSetupWorkflow(args) {
|
|
|
8866
8864
|
console.log("");
|
|
8867
8865
|
if (detected.existingEssence) {
|
|
8868
8866
|
console.log(`${BOLD7}Recommended path:${RESET14} maintain an attached Decantr project`);
|
|
8869
|
-
console.log(
|
|
8870
|
-
|
|
8871
|
-
|
|
8867
|
+
console.log(
|
|
8868
|
+
` ${cyan3(withProject('decantr task <route> "<change>"', projectArg))} Prepare LLM context before edits`
|
|
8869
|
+
);
|
|
8870
|
+
console.log(
|
|
8871
|
+
` ${cyan3(withProject("decantr verify --brownfield", projectArg))} Run local health and drift checks`
|
|
8872
|
+
);
|
|
8873
|
+
console.log(
|
|
8874
|
+
` ${cyan3(withProject("decantr codify --from-audit", projectArg))} Propose project-owned local law`
|
|
8875
|
+
);
|
|
8872
8876
|
return;
|
|
8873
8877
|
}
|
|
8874
8878
|
if (hasFootprint) {
|
|
8875
8879
|
console.log(`${BOLD7}Recommended path:${RESET14} brownfield adoption`);
|
|
8876
|
-
console.log(` ${cyan3("decantr adopt --yes")} Analyze, attach, and verify`);
|
|
8877
8880
|
console.log(
|
|
8878
|
-
` ${cyan3("decantr adopt --
|
|
8881
|
+
` ${cyan3(withProject("decantr adopt --yes", projectArg))} Analyze, attach, and verify`
|
|
8882
|
+
);
|
|
8883
|
+
console.log(
|
|
8884
|
+
` ${cyan3(withProject("decantr codify --from-audit", projectArg))} Propose local UI law`
|
|
8885
|
+
);
|
|
8886
|
+
console.log("");
|
|
8887
|
+
console.log(`${BOLD7}Optional visual evidence after the app is running:${RESET14}`);
|
|
8888
|
+
console.log(
|
|
8889
|
+
` ${cyan3(withProject("decantr verify --base-url http://localhost:3000 --evidence", projectArg))}`
|
|
8879
8890
|
);
|
|
8880
|
-
console.log(` ${cyan3("decantr codify --from-audit")} Propose local UI law`);
|
|
8881
8891
|
return;
|
|
8882
8892
|
}
|
|
8883
8893
|
console.log(`${BOLD7}Recommended path:${RESET14} greenfield start`);
|
|
@@ -8886,9 +8896,10 @@ async function cmdSetupWorkflow(args) {
|
|
|
8886
8896
|
}
|
|
8887
8897
|
async function cmdAdoptWorkflow(args) {
|
|
8888
8898
|
const { flags } = parseLooseArgs(args);
|
|
8889
|
-
const workspaceInfo = resolveWorkflowProject(flags);
|
|
8899
|
+
const workspaceInfo = resolveWorkflowProject(flags, "adopt");
|
|
8890
8900
|
if (!workspaceInfo) return;
|
|
8891
8901
|
const projectRoot = workspaceInfo.appRoot;
|
|
8902
|
+
const projectArg = flagString(flags, "project");
|
|
8892
8903
|
const dryRun = flagBoolean(flags, "dry-run");
|
|
8893
8904
|
const yes = flagBoolean(flags, "yes") || flagBoolean(flags, "y");
|
|
8894
8905
|
const baseUrl = flagString(flags, "base-url");
|
|
@@ -8898,7 +8909,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
8898
8909
|
const saveBaseline = flagBoolean(flags, "baseline", true) || flagBoolean(flags, "save-baseline");
|
|
8899
8910
|
const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
|
|
8900
8911
|
const assistantBridge = flagString(flags, "assistant-bridge");
|
|
8901
|
-
const hasEssence =
|
|
8912
|
+
const hasEssence = existsSync27(join28(projectRoot, "decantr.essence.json"));
|
|
8902
8913
|
const proposalFlag = flagBoolean(flags, "replace-essence") ? "--replace-essence" : flagBoolean(flags, "merge-proposal") || hasEssence ? "--merge-proposal" : "--accept-proposal";
|
|
8903
8914
|
const steps = [
|
|
8904
8915
|
"analyze current app and write .decantr/brownfield intelligence",
|
|
@@ -8959,11 +8970,21 @@ async function cmdAdoptWorkflow(args) {
|
|
|
8959
8970
|
}
|
|
8960
8971
|
console.log("");
|
|
8961
8972
|
console.log(`${BOLD7}Brownfield operating loop:${RESET14}`);
|
|
8962
|
-
console.log(
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
console.log(
|
|
8966
|
-
|
|
8973
|
+
console.log(
|
|
8974
|
+
` ${cyan3(withProject("decantr codify --from-audit", projectArg))} Discover and propose project-owned UI law`
|
|
8975
|
+
);
|
|
8976
|
+
console.log(
|
|
8977
|
+
` ${cyan3(withProject("decantr codify --accept", projectArg))} Accept reviewed local patterns and rules`
|
|
8978
|
+
);
|
|
8979
|
+
console.log(
|
|
8980
|
+
` ${cyan3(withProject('decantr task <route> "<change>"', projectArg))} Give your LLM route-specific context before edits`
|
|
8981
|
+
);
|
|
8982
|
+
console.log(
|
|
8983
|
+
` ${cyan3(withProject("decantr verify --brownfield --local-patterns", projectArg))} Check contract, health, and local law after edits`
|
|
8984
|
+
);
|
|
8985
|
+
console.log(
|
|
8986
|
+
` ${cyan3(withProject("decantr verify --since-baseline", projectArg))} Compare future work against this baseline`
|
|
8987
|
+
);
|
|
8967
8988
|
}
|
|
8968
8989
|
async function cmdVerifyWorkflow(args) {
|
|
8969
8990
|
const { flags } = parseLooseArgs(args);
|
|
@@ -8974,11 +8995,11 @@ async function cmdVerifyWorkflow(args) {
|
|
|
8974
8995
|
return;
|
|
8975
8996
|
}
|
|
8976
8997
|
if (workspaceMode) {
|
|
8977
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
8998
|
+
const { cmdWorkspace } = await import("./workspace-U7J3CJY3.js");
|
|
8978
8999
|
await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
|
|
8979
9000
|
return;
|
|
8980
9001
|
}
|
|
8981
|
-
const workspaceInfo = resolveWorkflowProject(flags);
|
|
9002
|
+
const workspaceInfo = resolveWorkflowProject(flags, "verify");
|
|
8982
9003
|
if (!workspaceInfo) return;
|
|
8983
9004
|
const brownfield = flagBoolean(flags, "brownfield");
|
|
8984
9005
|
const localPatterns = flagBoolean(flags, "local-patterns");
|
|
@@ -9072,29 +9093,35 @@ async function cmdVerifyWorkflow(args) {
|
|
|
9072
9093
|
}
|
|
9073
9094
|
}
|
|
9074
9095
|
function readJsonIfPresent(path) {
|
|
9075
|
-
if (!
|
|
9096
|
+
if (!existsSync27(path)) return null;
|
|
9076
9097
|
try {
|
|
9077
|
-
return JSON.parse(
|
|
9098
|
+
return JSON.parse(readFileSync20(path, "utf-8"));
|
|
9078
9099
|
} catch {
|
|
9079
9100
|
return null;
|
|
9080
9101
|
}
|
|
9081
9102
|
}
|
|
9082
9103
|
async function cmdTaskWorkflow(args) {
|
|
9083
9104
|
const { flags, positional } = parseLooseArgs(args);
|
|
9084
|
-
const workspaceInfo = resolveWorkflowProject(flags);
|
|
9105
|
+
const workspaceInfo = resolveWorkflowProject(flags, "task");
|
|
9085
9106
|
if (!workspaceInfo) return;
|
|
9086
9107
|
const routeInput = positional[0];
|
|
9087
9108
|
if (!routeInput) {
|
|
9088
|
-
console.error(
|
|
9109
|
+
console.error(
|
|
9110
|
+
error3(
|
|
9111
|
+
'Usage: decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]'
|
|
9112
|
+
)
|
|
9113
|
+
);
|
|
9089
9114
|
process.exitCode = 1;
|
|
9090
9115
|
return;
|
|
9091
9116
|
}
|
|
9092
9117
|
const route = routeInput.startsWith("/") ? routeInput : `/${routeInput}`;
|
|
9093
9118
|
const taskSummary = positional.slice(1).join(" ").trim();
|
|
9094
|
-
const essencePath =
|
|
9119
|
+
const essencePath = join28(workspaceInfo.appRoot, "decantr.essence.json");
|
|
9095
9120
|
const essence = readJsonIfPresent(essencePath);
|
|
9096
9121
|
if (!essence) {
|
|
9097
|
-
console.error(
|
|
9122
|
+
console.error(
|
|
9123
|
+
error3("No decantr.essence.json found. Run `decantr adopt` or `decantr init` first.")
|
|
9124
|
+
);
|
|
9098
9125
|
process.exitCode = 1;
|
|
9099
9126
|
return;
|
|
9100
9127
|
}
|
|
@@ -9113,11 +9140,11 @@ async function cmdTaskWorkflow(args) {
|
|
|
9113
9140
|
}
|
|
9114
9141
|
const section = essence.blueprint.sections.find((entry) => entry.id === target.section);
|
|
9115
9142
|
const page = section?.pages.find((entry) => entry.id === target.page);
|
|
9116
|
-
const contextDir =
|
|
9117
|
-
const manifest = readJsonIfPresent(
|
|
9143
|
+
const contextDir = join28(workspaceInfo.appRoot, ".decantr", "context");
|
|
9144
|
+
const manifest = readJsonIfPresent(join28(contextDir, "pack-manifest.json"));
|
|
9118
9145
|
const pagePack = manifest?.pages?.find((entry) => entry.id === target.page);
|
|
9119
9146
|
const sectionPack = manifest?.sections?.find((entry) => entry.id === target.section);
|
|
9120
|
-
const visualManifest = readJsonIfPresent(
|
|
9147
|
+
const visualManifest = readJsonIfPresent(join28(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
|
|
9121
9148
|
const screenshot = visualManifest?.routes?.find((entry) => entry.route === route)?.screenshot;
|
|
9122
9149
|
const localPatternPackPath = localPatternsPath(workspaceInfo.appRoot);
|
|
9123
9150
|
const localRuleManifestPath = localRulesPath(workspaceInfo.appRoot);
|
|
@@ -9133,13 +9160,13 @@ async function cmdTaskWorkflow(args) {
|
|
|
9133
9160
|
shell: page?.shell ?? section?.shell ?? null,
|
|
9134
9161
|
patterns: page?.layout?.map(extractPatternName) ?? [],
|
|
9135
9162
|
read: [
|
|
9136
|
-
pagePack ?
|
|
9137
|
-
sectionPack ?
|
|
9138
|
-
manifest?.scaffold?.markdown ?
|
|
9163
|
+
pagePack ? join28(".decantr/context", pagePack.markdown) : null,
|
|
9164
|
+
sectionPack ? join28(".decantr/context", sectionPack.markdown) : null,
|
|
9165
|
+
manifest?.scaffold?.markdown ? join28(".decantr/context", manifest.scaffold.markdown) : null,
|
|
9139
9166
|
".decantr/context/scaffold.md",
|
|
9140
9167
|
"DECANTR.md",
|
|
9141
|
-
|
|
9142
|
-
|
|
9168
|
+
existsSync27(localPatternPackPath) ? ".decantr/local-patterns.json" : null,
|
|
9169
|
+
existsSync27(localRuleManifestPath) ? ".decantr/rules.json" : null
|
|
9143
9170
|
].filter(Boolean),
|
|
9144
9171
|
screenshot: screenshot ?? null,
|
|
9145
9172
|
localLaw,
|
|
@@ -9171,7 +9198,9 @@ async function cmdTaskWorkflow(args) {
|
|
|
9171
9198
|
console.log("");
|
|
9172
9199
|
console.log(`${BOLD7}Project-owned local law:${RESET14}`);
|
|
9173
9200
|
if (context.localLaw.patternsPath) {
|
|
9174
|
-
console.log(
|
|
9201
|
+
console.log(
|
|
9202
|
+
` Patterns: ${cyan3(context.localLaw.patternsPath)} (${context.localLaw.patternCount})`
|
|
9203
|
+
);
|
|
9175
9204
|
}
|
|
9176
9205
|
if (context.localLaw.rulesPath) {
|
|
9177
9206
|
console.log(` Rules: ${cyan3(context.localLaw.rulesPath)} (${context.localLaw.ruleCount})`);
|
|
@@ -9183,7 +9212,9 @@ async function cmdTaskWorkflow(args) {
|
|
|
9183
9212
|
} else {
|
|
9184
9213
|
console.log("");
|
|
9185
9214
|
console.log(`${BOLD7}Project-owned local law:${RESET14}`);
|
|
9186
|
-
console.log(
|
|
9215
|
+
console.log(
|
|
9216
|
+
` ${YELLOW9}Not codified yet.${RESET14} Run ${cyan3("decantr codify --from-audit")} after adoption.`
|
|
9217
|
+
);
|
|
9187
9218
|
}
|
|
9188
9219
|
if (context.changedFiles.length > 0) {
|
|
9189
9220
|
console.log("");
|
|
@@ -9207,12 +9238,14 @@ async function cmdTaskWorkflow(args) {
|
|
|
9207
9238
|
}
|
|
9208
9239
|
async function cmdCodifyWorkflow(args) {
|
|
9209
9240
|
const { flags } = parseLooseArgs(args);
|
|
9210
|
-
const workspaceInfo = resolveWorkflowProject(flags);
|
|
9241
|
+
const workspaceInfo = resolveWorkflowProject(flags, "codify");
|
|
9211
9242
|
if (!workspaceInfo) return;
|
|
9212
9243
|
if (flagBoolean(flags, "accept")) {
|
|
9213
|
-
if (!
|
|
9244
|
+
if (!existsSync27(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync27(localRulesProposalPath(workspaceInfo.appRoot))) {
|
|
9214
9245
|
console.error(
|
|
9215
|
-
error3(
|
|
9246
|
+
error3(
|
|
9247
|
+
"No local law proposal found. Run `decantr codify --from-audit` or `decantr codify` first."
|
|
9248
|
+
)
|
|
9216
9249
|
);
|
|
9217
9250
|
process.exitCode = 1;
|
|
9218
9251
|
return;
|
|
@@ -9228,7 +9261,9 @@ async function cmdCodifyWorkflow(args) {
|
|
|
9228
9261
|
return;
|
|
9229
9262
|
}
|
|
9230
9263
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
9231
|
-
const essence = readJsonIfPresent(
|
|
9264
|
+
const essence = readJsonIfPresent(
|
|
9265
|
+
join28(workspaceInfo.appRoot, "decantr.essence.json")
|
|
9266
|
+
);
|
|
9232
9267
|
const fromAudit = flagBoolean(flags, "from-audit") || flagBoolean(flags, "discover-local-patterns") || flagBoolean(flags, "codify-local-patterns");
|
|
9233
9268
|
const proposal = createBrownfieldCodifyProposal({
|
|
9234
9269
|
projectRoot: workspaceInfo.appRoot,
|
|
@@ -9240,15 +9275,24 @@ async function cmdCodifyWorkflow(args) {
|
|
|
9240
9275
|
console.log(success3(`Wrote local pattern proposal: ${result.patternPath}`));
|
|
9241
9276
|
console.log(success3(`Wrote local rule proposal: ${result.rulesPath}`));
|
|
9242
9277
|
if (fromAudit) {
|
|
9243
|
-
console.log(
|
|
9278
|
+
console.log(
|
|
9279
|
+
dim3("Proposal includes source-derived component candidates and starter mechanical rules.")
|
|
9280
|
+
);
|
|
9244
9281
|
}
|
|
9245
|
-
console.log(
|
|
9282
|
+
console.log(
|
|
9283
|
+
dim3(
|
|
9284
|
+
"Review both files, add real component paths/token recipes, then run `decantr codify --accept`."
|
|
9285
|
+
)
|
|
9286
|
+
);
|
|
9246
9287
|
}
|
|
9247
9288
|
async function cmdContentWorkflow(args) {
|
|
9248
9289
|
const subcommand = args[1] ?? "check";
|
|
9249
9290
|
if (subcommand === "check" || subcommand === "health") {
|
|
9250
9291
|
const { cmdContentHealth, parseContentHealthArgs } = await import("./content-health-QQHBR6XG.js");
|
|
9251
|
-
await cmdContentHealth(
|
|
9292
|
+
await cmdContentHealth(
|
|
9293
|
+
process.cwd(),
|
|
9294
|
+
parseContentHealthArgs(["content-health", ...args.slice(2)])
|
|
9295
|
+
);
|
|
9252
9296
|
return;
|
|
9253
9297
|
}
|
|
9254
9298
|
if (subcommand === "create") {
|
|
@@ -9397,9 +9441,11 @@ ${BOLD7}Advanced commands:${RESET14}
|
|
|
9397
9441
|
${BOLD7}Examples:${RESET14}
|
|
9398
9442
|
decantr setup
|
|
9399
9443
|
decantr new my-app --blueprint=carbon-ai-portal
|
|
9400
|
-
decantr adopt --
|
|
9444
|
+
decantr adopt --yes
|
|
9445
|
+
decantr adopt --project apps/web --yes
|
|
9401
9446
|
decantr task /feed "add saved recipe actions"
|
|
9402
9447
|
decantr verify --brownfield --local-patterns
|
|
9448
|
+
decantr verify --base-url http://localhost:3000 --evidence
|
|
9403
9449
|
decantr verify --since-baseline
|
|
9404
9450
|
decantr codify --from-audit
|
|
9405
9451
|
decantr codify --accept
|
|
@@ -9451,7 +9497,8 @@ ${BOLD7}Examples:${RESET14}
|
|
|
9451
9497
|
${BOLD7}Workflow Model:${RESET14}
|
|
9452
9498
|
${cyan3("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=decantr-css
|
|
9453
9499
|
${cyan3("Greenfield contract")} decantr init --workflow=greenfield --adoption=contract-only
|
|
9454
|
-
${cyan3("Brownfield adoption")} decantr adopt --
|
|
9500
|
+
${cyan3("Brownfield adoption")} decantr adopt --yes
|
|
9501
|
+
${cyan3("Brownfield monorepo")} decantr adopt --project apps/web --yes
|
|
9455
9502
|
${cyan3("Daily LLM work")} decantr task <route> "<change>" -> decantr verify --brownfield --local-patterns
|
|
9456
9503
|
${cyan3("Project-owned law")} decantr codify --from-audit -> edit proposal -> decantr codify --accept
|
|
9457
9504
|
${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
|
|
@@ -9526,7 +9573,7 @@ ${BOLD7}Examples:${RESET14}
|
|
|
9526
9573
|
}
|
|
9527
9574
|
function cmdWorkspaceHelp() {
|
|
9528
9575
|
console.log(`
|
|
9529
|
-
${BOLD7}decantr workspace${RESET14} \u2014 Inspect Decantr projects across a monorepo
|
|
9576
|
+
${BOLD7}decantr workspace${RESET14} \u2014 Inspect Decantr projects and app candidates across a monorepo
|
|
9530
9577
|
|
|
9531
9578
|
${BOLD7}Usage:${RESET14}
|
|
9532
9579
|
decantr workspace list [--json]
|
|
@@ -9535,6 +9582,7 @@ ${BOLD7}Usage:${RESET14}
|
|
|
9535
9582
|
|
|
9536
9583
|
${BOLD7}Examples:${RESET14}
|
|
9537
9584
|
decantr workspace list
|
|
9585
|
+
decantr adopt --project apps/web --yes
|
|
9538
9586
|
decantr workspace health
|
|
9539
9587
|
decantr workspace health --json --output .decantr/workspace-health.json
|
|
9540
9588
|
decantr workspace health --changed --since origin/main
|
|
@@ -9638,7 +9686,7 @@ ${BOLD7}decantr adopt${RESET14} \u2014 Brownfield one-liner: analyze, attach, ve
|
|
|
9638
9686
|
|
|
9639
9687
|
${BOLD7}Usage:${RESET14}
|
|
9640
9688
|
decantr adopt [--project <path>] [--yes] [--dry-run]
|
|
9641
|
-
decantr adopt --base-url <url> [--evidence] [--ci] [--yes]
|
|
9689
|
+
decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes]
|
|
9642
9690
|
|
|
9643
9691
|
${BOLD7}Options:${RESET14}
|
|
9644
9692
|
--project App path inside a workspace/monorepo
|
|
@@ -9656,9 +9704,10 @@ ${BOLD7}Options:${RESET14}
|
|
|
9656
9704
|
|
|
9657
9705
|
${BOLD7}Examples:${RESET14}
|
|
9658
9706
|
decantr adopt --yes
|
|
9659
|
-
decantr adopt --
|
|
9707
|
+
decantr adopt --project apps/web --yes
|
|
9708
|
+
decantr adopt --project apps/web --base-url http://localhost:3000 --evidence --yes
|
|
9660
9709
|
decantr adopt --project apps/web --ci --yes
|
|
9661
|
-
decantr codify --from-audit
|
|
9710
|
+
decantr codify --from-audit --project apps/web
|
|
9662
9711
|
`);
|
|
9663
9712
|
}
|
|
9664
9713
|
function cmdVerifyHelp() {
|
|
@@ -9675,6 +9724,7 @@ ${BOLD7}Usage:${RESET14}
|
|
|
9675
9724
|
${BOLD7}Examples:${RESET14}
|
|
9676
9725
|
decantr verify
|
|
9677
9726
|
decantr verify --brownfield --local-patterns
|
|
9727
|
+
decantr verify --brownfield --local-patterns --project apps/web
|
|
9678
9728
|
decantr verify --brownfield --local-patterns --fail-on warn
|
|
9679
9729
|
decantr verify --base-url http://localhost:3000 --evidence
|
|
9680
9730
|
decantr verify --workspace --changed --since origin/main
|
|
@@ -9780,11 +9830,11 @@ async function main() {
|
|
|
9780
9830
|
}
|
|
9781
9831
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
9782
9832
|
try {
|
|
9783
|
-
const here =
|
|
9784
|
-
const candidates = [
|
|
9833
|
+
const here = dirname3(fileURLToPath2(import.meta.url));
|
|
9834
|
+
const candidates = [join28(here, "..", "package.json"), join28(here, "..", "..", "package.json")];
|
|
9785
9835
|
for (const candidate of candidates) {
|
|
9786
|
-
if (
|
|
9787
|
-
const pkg = JSON.parse(
|
|
9836
|
+
if (existsSync27(candidate)) {
|
|
9837
|
+
const pkg = JSON.parse(readFileSync20(candidate, "utf-8"));
|
|
9788
9838
|
if (pkg.version) {
|
|
9789
9839
|
console.log(pkg.version);
|
|
9790
9840
|
return;
|
|
@@ -9963,7 +10013,7 @@ async function main() {
|
|
|
9963
10013
|
cmdStudioHelp();
|
|
9964
10014
|
break;
|
|
9965
10015
|
}
|
|
9966
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
10016
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-G3YOU5YF.js");
|
|
9967
10017
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
9968
10018
|
} catch (e) {
|
|
9969
10019
|
console.error(error3(e.message));
|
|
@@ -9977,7 +10027,7 @@ async function main() {
|
|
|
9977
10027
|
cmdWorkspaceHelp();
|
|
9978
10028
|
break;
|
|
9979
10029
|
}
|
|
9980
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
10030
|
+
const { cmdWorkspace } = await import("./workspace-U7J3CJY3.js");
|
|
9981
10031
|
await cmdWorkspace(process.cwd(), args);
|
|
9982
10032
|
} catch (e) {
|
|
9983
10033
|
console.error(error3(e.message));
|
|
@@ -10257,7 +10307,7 @@ async function main() {
|
|
|
10257
10307
|
break;
|
|
10258
10308
|
}
|
|
10259
10309
|
if (packType === "page" && route && !id) {
|
|
10260
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
10310
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join28(process.cwd(), "decantr.essence.json");
|
|
10261
10311
|
id = resolvePagePackIdForRoute(resolvedPath, route);
|
|
10262
10312
|
}
|
|
10263
10313
|
await printHostedSelectedExecutionPack(
|
|
@@ -10413,10 +10463,7 @@ async function main() {
|
|
|
10413
10463
|
}
|
|
10414
10464
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
10415
10465
|
if (workspaceInfo.requiresProjectSelection) {
|
|
10416
|
-
|
|
10417
|
-
console.log(
|
|
10418
|
-
dim3(`Use --project=<path>. Candidates: ${workspaceInfo.appCandidates.join(", ")}`)
|
|
10419
|
-
);
|
|
10466
|
+
printWorkspaceProjectSelection(workspaceInfo, "analyze");
|
|
10420
10467
|
process.exitCode = 1;
|
|
10421
10468
|
break;
|
|
10422
10469
|
}
|
|
@@ -10443,6 +10490,11 @@ async function main() {
|
|
|
10443
10490
|
}
|
|
10444
10491
|
}
|
|
10445
10492
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
10493
|
+
if (workspaceInfo.requiresProjectSelection) {
|
|
10494
|
+
printWorkspaceProjectSelection(workspaceInfo, "rules");
|
|
10495
|
+
process.exitCode = 1;
|
|
10496
|
+
break;
|
|
10497
|
+
}
|
|
10446
10498
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
10447
10499
|
if (subcommand === "preview") {
|
|
10448
10500
|
console.log(
|