@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.
@@ -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 existsSync28, mkdirSync as mkdirSync14, readdirSync as readdirSync8, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "fs";
38
- import { basename as basename3, dirname as dirname4, isAbsolute, join as join29, resolve as resolve4 } from "path";
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((resolve5) => {
5770
+ return new Promise((resolve4) => {
5768
5771
  rl.question(prompt, (answer) => {
5769
5772
  rl.close();
5770
- resolve5(answer.trim() || defaultValue || "");
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((resolve5) => rl.question(q, resolve5));
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 : resolve4(cwd, 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) : join29(process.cwd(), "dist");
6827
- const indexPath = join29(resolvedDistPath, "index.html");
6828
- if (!existsSync28(indexPath)) {
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 = readFileSync21(indexPath, "utf-8");
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 = join29(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
6836
- if (existsSync28(assetFilePath)) {
6837
- assets[assetPath] = readFileSync21(assetFilePath, "utf-8");
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 (!existsSync28(resolvedSourcePath)) {
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 readdirSync8(absoluteDir, { withFileTypes: true })) {
6799
+ for (const entry of readdirSync7(absoluteDir, { withFileTypes: true })) {
6867
6800
  if (ignoredDirNames.has(entry.name)) continue;
6868
- const absolutePath = join29(absoluteDir, entry.name);
6869
- const relativePath = join29(relativeDir, entry.name).replace(/\\/g, "/");
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] = readFileSync21(absolutePath, "utf-8");
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) : join29(process.cwd(), "decantr.essence.json");
7028
- if (!existsSync28(resolvedPath)) {
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(readFileSync21(resolvedPath, "utf-8"));
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 = join29(process.cwd(), ".decantr", "context");
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: ${join29(process.cwd(), ".decantr", "context")}`);
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 (!existsSync28(essencePath)) {
7006
+ if (!existsSync27(essencePath)) {
7074
7007
  throw new Error(`Essence file not found at ${essencePath}`);
7075
7008
  }
7076
- const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
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) : join29(process.cwd(), "decantr.essence.json");
7092
- if (!existsSync28(resolvedPath)) {
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(readFileSync21(resolvedPath, "utf-8"));
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 = join29(process.cwd(), ".decantr", "context");
7042
+ const contextDir = join28(process.cwd(), ".decantr", "context");
7110
7043
  mkdirSync14(contextDir, { recursive: true });
7111
7044
  writeFileSync17(
7112
- join29(contextDir, "pack-manifest.json"),
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(join29(contextDir, markdownFile), selected.pack.renderedMarkdown);
7119
- writeFileSync17(join29(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
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) : join29(process.cwd(), "decantr.essence.json");
7145
- if (!existsSync28(resolvedPath)) {
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(readFileSync21(resolvedPath, "utf-8"));
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 = join29(process.cwd(), ".decantr", "context");
7088
+ const contextDir = join28(process.cwd(), ".decantr", "context");
7156
7089
  mkdirSync14(contextDir, { recursive: true });
7157
- writeFileSync17(join29(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
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 = join29(projectRoot, ".decantr", "context");
7179
- const reviewPackPath = join29(contextDir, "review-pack.json");
7180
- const manifestPath = join29(contextDir, "pack-manifest.json");
7181
- if (existsSync28(reviewPackPath) && existsSync28(manifestPath)) {
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 = join29(projectRoot, "decantr.essence.json");
7185
- if (!existsSync28(essencePath)) {
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(readFileSync21(essencePath, "utf-8"));
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 = join29(projectRoot, ".decantr", "context");
7205
- const reviewPackPath = join29(contextDir, "review-pack.json");
7206
- const manifestPath = join29(contextDir, "pack-manifest.json");
7207
- if (existsSync28(reviewPackPath) && existsSync28(manifestPath)) {
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 = join29(projectRoot, "decantr.essence.json");
7211
- if (!existsSync28(essencePath)) {
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(readFileSync21(essencePath, "utf-8"));
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(join29(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
7158
+ writeFileSync17(join28(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
7226
7159
  writeFileSync17(
7227
- join29(contextDir, "review-pack.json"),
7160
+ join28(contextDir, "review-pack.json"),
7228
7161
  JSON.stringify(selected.pack, null, 2) + "\n"
7229
7162
  );
7230
- if (!existsSync28(manifestPath)) {
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) : join29(process.cwd(), "decantr.essence.json");
7242
- const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join29(process.cwd(), "src", "styles", "treatments.css");
7243
- if (!existsSync28(resolvedSourcePath)) {
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 (!existsSync28(resolvedEssencePath)) {
7179
+ if (!existsSync27(resolvedEssencePath)) {
7247
7180
  throw new Error(`Essence file not found at ${resolvedEssencePath}`);
7248
7181
  }
7249
- const code = readFileSync21(resolvedSourcePath, "utf-8");
7250
- const essence = JSON.parse(readFileSync21(resolvedEssencePath, "utf-8"));
7251
- const treatmentsCss = existsSync28(resolvedTreatmentsPath) ? readFileSync21(resolvedTreatmentsPath, "utf-8") : void 0;
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) : join29(process.cwd(), "decantr.essence.json");
7276
- if (!existsSync28(resolvedEssencePath)) {
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(readFileSync21(resolvedEssencePath, "utf-8"));
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) : join29(process.cwd(), "dist") : "none"}`
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 : join29(process.cwd(), file);
7401
- if (existsSync28(resolved)) {
7402
- pieces.push(readFileSync21(resolved, "utf-8"));
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 = join29(process.cwd(), ".decantr", "analysis.json");
7407
- if (existsSync28(analysisPath)) {
7339
+ const analysisPath = join28(process.cwd(), ".decantr", "analysis.json");
7340
+ if (existsSync27(analysisPath)) {
7408
7341
  try {
7409
- const analysis = JSON.parse(readFileSync21(analysisPath, "utf-8"));
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 = join29(process.cwd(), routeEntry.file);
7413
- if (existsSync28(resolved)) {
7414
- pieces.push(readFileSync21(resolved, "utf-8"));
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: join29(process.cwd(), ".decantr", "cache")
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: join29(process.cwd(), ".decantr", "cache")
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 || join29(process.cwd(), "decantr.essence.json");
7483
+ const essencePath = path || join28(process.cwd(), "decantr.essence.json");
7551
7484
  let raw;
7552
7485
  try {
7553
- raw = readFileSync21(essencePath, "utf-8");
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: join29(process.cwd(), ".decantr", "cache")
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 = dirname4(fileURLToPath2(import.meta.url));
7703
- const candidates = [join29(here, "..", "package.json"), join29(here, "..", "..", "package.json")];
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(readFileSync21(candidate, "utf-8"));
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 = join29(projectRoot, "decantr.essence.json");
7718
- if (!existsSync28(essencePath)) return null;
7719
- const backupPath = join29(
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, readFileSync21(essencePath, "utf-8"), "utf-8");
7656
+ writeFileSync17(backupPath, readFileSync20(essencePath, "utf-8"), "utf-8");
7724
7657
  return backupPath;
7725
7658
  }
7726
7659
  function writeBrownfieldProjectJson(input) {
7727
- const decantrDir = join29(input.projectRoot, ".decantr");
7728
- mkdirSync14(join29(decantrDir, "context"), { recursive: true });
7729
- mkdirSync14(join29(decantrDir, "cache"), { recursive: true });
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(join29(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
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 = join29(input.projectRoot, "decantr.essence.json");
7787
- const hasEssence = existsSync28(essencePath);
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(readFileSync21(essencePath, "utf-8"));
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: join29(input.projectRoot, ".decantr", "cache"),
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
- console.log(error3("This looks like a workspace root with multiple app candidates."));
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: join29(projectRoot, ".decantr", "cache"),
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 (!existsSync28(join29(projectRoot, "package.json"))) {
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 = existsSync28(join29(projectRoot, ".decantr", "context", "scaffold-pack.md"));
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 = readFileSync21(result.essencePath, "utf-8");
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 = join29(projectRoot, "decantr.essence.json");
8432
- const projectJsonPath = join29(projectRoot, ".decantr", "project.json");
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 (!existsSync28(essencePath)) {
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(readFileSync21(essencePath, "utf-8"));
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 (existsSync28(projectJsonPath)) {
8420
+ if (existsSync27(projectJsonPath)) {
8489
8421
  try {
8490
- const projectJson = JSON.parse(readFileSync21(projectJsonPath, "utf-8"));
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 = join29(projectRoot, ".decantr", "cache");
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 = join29(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
8704
- if (!existsSync28(themePath)) {
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(readFileSync21(themePath, "utf-8"));
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 resolveWorkflowProject(flags) {
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
- console.log(error3("This looks like a workspace root with multiple app candidates."));
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 workspaceInfo = resolveWorkflowProject(flags);
8860
- if (!workspaceInfo) return;
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(` ${cyan3('decantr task <route> "<change>"')} Prepare LLM context before edits`);
8870
- console.log(` ${cyan3("decantr verify --brownfield")} Run local health and drift checks`);
8871
- console.log(` ${cyan3("decantr codify --from-audit")} Propose project-owned local law`);
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 --base-url http://localhost:3000 --evidence --yes")} Include visual evidence`
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 = existsSync28(join29(projectRoot, "decantr.essence.json"));
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(` ${cyan3("decantr codify --from-audit")} Discover and propose project-owned UI law`);
8963
- console.log(` ${cyan3("decantr codify --accept")} Accept reviewed local patterns and rules`);
8964
- console.log(` ${cyan3('decantr task <route> "<change>"')} Give your LLM route-specific context before edits`);
8965
- console.log(` ${cyan3("decantr verify --brownfield --local-patterns")} Check contract, health, and local law after edits`);
8966
- console.log(` ${cyan3("decantr verify --since-baseline")} Compare future work against this baseline`);
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-KSFWRZEX.js");
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 (!existsSync28(path)) return null;
9096
+ if (!existsSync27(path)) return null;
9076
9097
  try {
9077
- return JSON.parse(readFileSync21(path, "utf-8"));
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(error3('Usage: decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]'));
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 = join29(workspaceInfo.appRoot, "decantr.essence.json");
9119
+ const essencePath = join28(workspaceInfo.appRoot, "decantr.essence.json");
9095
9120
  const essence = readJsonIfPresent(essencePath);
9096
9121
  if (!essence) {
9097
- console.error(error3("No decantr.essence.json found. Run `decantr adopt` or `decantr init` first."));
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 = join29(workspaceInfo.appRoot, ".decantr", "context");
9117
- const manifest = readJsonIfPresent(join29(contextDir, "pack-manifest.json"));
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(join29(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
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 ? join29(".decantr/context", pagePack.markdown) : null,
9137
- sectionPack ? join29(".decantr/context", sectionPack.markdown) : null,
9138
- manifest?.scaffold?.markdown ? join29(".decantr/context", manifest.scaffold.markdown) : null,
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
- existsSync28(localPatternPackPath) ? ".decantr/local-patterns.json" : null,
9142
- existsSync28(localRuleManifestPath) ? ".decantr/rules.json" : null
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(` Patterns: ${cyan3(context.localLaw.patternsPath)} (${context.localLaw.patternCount})`);
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(` ${YELLOW9}Not codified yet.${RESET14} Run ${cyan3("decantr codify --from-audit")} after adoption.`);
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 (!existsSync28(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync28(localRulesProposalPath(workspaceInfo.appRoot))) {
9244
+ if (!existsSync27(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync27(localRulesProposalPath(workspaceInfo.appRoot))) {
9214
9245
  console.error(
9215
- error3("No local law proposal found. Run `decantr codify --from-audit` or `decantr codify` first.")
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(join29(workspaceInfo.appRoot, "decantr.essence.json"));
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(dim3("Proposal includes source-derived component candidates and starter mechanical rules."));
9278
+ console.log(
9279
+ dim3("Proposal includes source-derived component candidates and starter mechanical rules.")
9280
+ );
9244
9281
  }
9245
- console.log(dim3("Review both files, add real component paths/token recipes, then run `decantr codify --accept`."));
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(process.cwd(), parseContentHealthArgs(["content-health", ...args.slice(2)]));
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 --base-url http://localhost:3000 --evidence --yes
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 --base-url <url> --evidence --yes
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 --base-url http://localhost:3000 --evidence --yes
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 = dirname4(fileURLToPath2(import.meta.url));
9784
- const candidates = [join29(here, "..", "package.json"), join29(here, "..", "..", "package.json")];
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 (existsSync28(candidate)) {
9787
- const pkg = JSON.parse(readFileSync21(candidate, "utf-8"));
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-MKLBUC3A.js");
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-KSFWRZEX.js");
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) : join29(process.cwd(), "decantr.essence.json");
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
- console.log(error3("This looks like a workspace root with multiple app candidates."));
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(