@decantr/cli 3.4.1 → 3.5.0

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.
@@ -22,7 +22,7 @@ import {
22
22
  listWorkspaceCandidates,
23
23
  listWorkspaceProjects,
24
24
  shouldFailWorkspaceHealth
25
- } from "./chunk-UGRAHWCG.js";
25
+ } from "./chunk-RJ6PT7WP.js";
26
26
  import {
27
27
  acceptBrownfieldLocalLaw,
28
28
  acceptStyleBridge,
@@ -52,7 +52,7 @@ import {
52
52
  writeBrownfieldCodifyProposal,
53
53
  writeHostedPatternMappingProposal,
54
54
  writeStyleBridgeProposal
55
- } from "./chunk-BDVI3SSP.js";
55
+ } from "./chunk-T45GFC6F.js";
56
56
  import {
57
57
  buildGuardRegistryContext,
58
58
  createDoctrineMap,
@@ -69,11 +69,11 @@ import {
69
69
  sendCliCommandTelemetry,
70
70
  sendNewProjectCompletedTelemetry,
71
71
  writeDoctrineMap
72
- } from "./chunk-2GCVVEQC.js";
72
+ } from "./chunk-PM7DKABI.js";
73
73
 
74
74
  // src/index.ts
75
- import { existsSync as existsSync28, mkdirSync as mkdirSync15, readdirSync as readdirSync8, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "fs";
76
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join30, relative as relative6, resolve as resolve4 } from "path";
75
+ import { existsSync as existsSync29, mkdirSync as mkdirSync16, readdirSync as readdirSync8, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "fs";
76
+ import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute3, join as join31, relative as relative6, resolve as resolve5 } from "path";
77
77
  import { fileURLToPath as fileURLToPath3 } from "url";
78
78
  import {
79
79
  buildGraphImpactContext,
@@ -98,6 +98,7 @@ import {
98
98
  import {
99
99
  auditProject,
100
100
  critiqueFile as critiqueProjectFile,
101
+ LOOP_READINESS_V2_SCHEMA_URL,
101
102
  scanProject as scanProjectReadOnly
102
103
  } from "@decantr/verifier";
103
104
 
@@ -188,11 +189,14 @@ function buildAssistantBridgeContent(input) {
188
189
  lines.push("## Suggested Rule Block");
189
190
  lines.push("");
190
191
  lines.push(START);
192
+ lines.push(
193
+ 'Before editing any route, run `decantr task <route> "<intent>"` and use the printed authority block, read targets, local law, evidence, and verify command as the working contract.'
194
+ );
191
195
  lines.push(
192
196
  "Before implementing Decantr-scoped work, read `decantr.essence.json`, `.decantr/brownfield-report.md`, `.decantr/doctrine-map.json`, `.decantr/ambient-context.json`, and the compiled packs in `.decantr/context/`."
193
197
  );
194
198
  lines.push(
195
- "Treat Decantr as the reconciled contract layer and the original project docs/rules as cited evidence; if they conflict, stop and report the conflict instead of guessing."
199
+ "Treat Decantr as the reconciled contract layer and the original project docs/rules as cited evidence; if runtime source and Decantr context conflict, stop and report the drift instead of guessing which side wins."
196
200
  );
197
201
  lines.push(
198
202
  "For brownfield adoption, preserve existing framework, routing, styling, package manager, data boundaries, and build conventions unless the Decantr contract explicitly records a reviewed change."
@@ -215,8 +219,9 @@ function writeAssistantBridgePreview(input) {
215
219
  function bridgeBlock() {
216
220
  return [
217
221
  START,
222
+ 'Before editing any route, run `decantr task <route> "<intent>"` and use the printed authority block, read targets, local law, evidence, and verify command as the working contract.',
218
223
  "Before implementing Decantr-scoped work, read `decantr.essence.json`, `.decantr/brownfield-report.md`, `.decantr/doctrine-map.json`, `.decantr/ambient-context.json`, and `.decantr/context/scaffold-pack.md` first.",
219
- "Treat Decantr as the reconciled contract layer and the original project docs/rules as cited evidence; if they conflict, stop and report the conflict instead of guessing.",
224
+ "Treat Decantr as the reconciled contract layer and the original project docs/rules as cited evidence; if runtime source and Decantr context conflict, stop and report the drift instead of guessing which side wins.",
220
225
  "For brownfield adoption, preserve existing framework, routing, styling, package manager, data boundaries, and build conventions unless the Decantr contract explicitly records a reviewed change.",
221
226
  "Do not install `@decantr/css` or rewrite styling unless the project adoption mode says `decantr-css` or the task explicitly asks for it.",
222
227
  END,
@@ -3388,12 +3393,13 @@ ${YELLOW2}Next step:${RESET2} Review ${BOLD}${reportDisplayPath}${RESET2}, then
3388
3393
  // src/commands/ci.ts
3389
3394
  import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
3390
3395
  import { dirname as dirname3, join as join15, relative as relative3, resolve } from "path";
3396
+ import { DECANTR_CI_REPORT_V2_SCHEMA_URL } from "@decantr/verifier";
3391
3397
  var BOLD2 = "\x1B[1m";
3392
3398
  var DIM3 = "\x1B[2m";
3393
3399
  var GREEN3 = "\x1B[32m";
3394
3400
  var RED2 = "\x1B[31m";
3395
3401
  var RESET3 = "\x1B[0m";
3396
- var CI_SCHEMA = "https://decantr.ai/schemas/decantr-ci-report.v1.json";
3402
+ var CI_SCHEMA = DECANTR_CI_REPORT_V2_SCHEMA_URL;
3397
3403
  function readJson(path) {
3398
3404
  if (!existsSync13(path)) return null;
3399
3405
  try {
@@ -3585,7 +3591,7 @@ function formatLocalLawText(summary, health) {
3585
3591
  lines.push(` ${DIM3}[WARN] ${warning}${RESET3}`);
3586
3592
  }
3587
3593
  for (const finding of summary.findings.slice(0, 8)) {
3588
- const label = finding.severity.toUpperCase();
3594
+ const label = finding.severity === "error" ? "Local law error" : finding.severity === "warn" ? "Local law warning" : "Local law info";
3589
3595
  lines.push(
3590
3596
  ` [${label}] ${finding.ruleId} ${finding.file}:${finding.line}:${finding.column} ${finding.message}`
3591
3597
  );
@@ -3687,6 +3693,9 @@ function formatProjectCiMarkdown(report) {
3687
3693
  `- Project: \`${report.projectPath ?? "."}\``,
3688
3694
  `- Status: **${report.status}**`,
3689
3695
  `- Fail on: \`${report.failOn}\``,
3696
+ `- Loop: **${report.loop.state}**`,
3697
+ `- Evidence tier: **${report.evidenceTier.stage}** / ${report.evidenceTier.confidence.level}`,
3698
+ `- Authority: **${report.authority.activeLane}**`,
3690
3699
  `- Local law: ${report.localLaw.checked ? `${report.localLaw.errorCount} error(s), ${report.localLaw.warnCount} warning(s)` : "not accepted yet"}`,
3691
3700
  `- Style bridge: ${report.styleBridge.checked ? `${report.styleBridge.mappingCount} mapping(s)` : "not active"}`,
3692
3701
  "",
@@ -3706,6 +3715,7 @@ function formatWorkspaceCiMarkdown(report) {
3706
3715
  "- Mode: **workspace**",
3707
3716
  `- Status: **${report.status}**`,
3708
3717
  `- Fail on: \`${report.failOn}\``,
3718
+ `- Loop: **${report.loop.state}**`,
3709
3719
  "",
3710
3720
  formatWorkspaceHealthMarkdown(report.workspace)
3711
3721
  ];
@@ -3862,6 +3872,7 @@ async function runWorkspaceCi(root, options) {
3862
3872
  mode: "workspace",
3863
3873
  failOn,
3864
3874
  status: workspaceStatus(workspace),
3875
+ loop: workspace.loop,
3865
3876
  workspace
3866
3877
  };
3867
3878
  const json = `${JSON.stringify(report, null, 2)}
@@ -3900,6 +3911,9 @@ async function runProjectCi(root, options) {
3900
3911
  projectPath,
3901
3912
  failOn,
3902
3913
  status: projectCiStatus(health, localLaw, styleBridge),
3914
+ loop: health.loop,
3915
+ authority: health.authority,
3916
+ evidenceTier: health.evidenceTier,
3903
3917
  health,
3904
3918
  localLaw,
3905
3919
  styleBridge
@@ -6671,80 +6685,226 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
6671
6685
  console.log(`${GREEN11}Derived files refreshed.${RESET11}`);
6672
6686
  }
6673
6687
 
6674
- // src/commands/sync-drift.ts
6675
- import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "fs";
6676
- import { join as join27 } from "path";
6688
+ // src/commands/resolve.ts
6689
+ import { existsSync as existsSync25, mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "fs";
6690
+ import { dirname as dirname6, join as join27, resolve as resolve4 } from "path";
6691
+ var BOLD6 = "\x1B[1m";
6692
+ var DIM12 = "\x1B[2m";
6677
6693
  var GREEN12 = "\x1B[32m";
6678
6694
  var RED10 = "\x1B[31m";
6679
6695
  var YELLOW9 = "\x1B[33m";
6680
6696
  var RESET12 = "\x1B[0m";
6681
- var DIM12 = "\x1B[2m";
6682
- var BOLD6 = "\x1B[1m";
6697
+ function driftLogPath(projectRoot) {
6698
+ return join27(projectRoot, ".decantr", "drift-log.json");
6699
+ }
6700
+ function readDriftLog(projectRoot) {
6701
+ const path = driftLogPath(projectRoot);
6702
+ if (!existsSync25(path)) return { version: 1, entries: [] };
6703
+ try {
6704
+ const parsed = JSON.parse(readFileSync18(path, "utf-8"));
6705
+ return {
6706
+ version: 1,
6707
+ entries: Array.isArray(parsed.entries) ? parsed.entries : []
6708
+ };
6709
+ } catch {
6710
+ return { version: 1, entries: [] };
6711
+ }
6712
+ }
6713
+ function writeDriftLog(projectRoot, log) {
6714
+ const path = driftLogPath(projectRoot);
6715
+ mkdirSync14(dirname6(path), { recursive: true });
6716
+ writeFileSync15(path, `${JSON.stringify(log, null, 2)}
6717
+ `, "utf-8");
6718
+ }
6719
+ function actionLabel(action) {
6720
+ return `${action.kind}${action.command ? ` -> ${action.command}` : ""}`;
6721
+ }
6722
+ function appendDriftAction(projectRoot, conflict, action) {
6723
+ const log = readDriftLog(projectRoot);
6724
+ const status = action === "mark_advisory" ? "advisory" : "deferred";
6725
+ const entry = {
6726
+ id: `${action}:${conflict.id}:${Date.now()}`,
6727
+ findingId: conflict.id,
6728
+ action,
6729
+ status,
6730
+ message: conflict.message,
6731
+ source: conflict.source,
6732
+ severity: conflict.severity,
6733
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString()
6734
+ };
6735
+ log.entries = log.entries.filter(
6736
+ (candidate) => !(candidate.findingId === conflict.id && candidate.action === action)
6737
+ );
6738
+ log.entries.push(entry);
6739
+ writeDriftLog(projectRoot, log);
6740
+ return driftLogPath(projectRoot);
6741
+ }
6742
+ function parseResolveArgs(args) {
6743
+ const options = {};
6744
+ for (let index = 1; index < args.length; index += 1) {
6745
+ const arg = args[index];
6746
+ if (arg === "--json") options.json = true;
6747
+ else if (arg === "--defer" && args[index + 1]) options.defer = args[++index];
6748
+ else if (arg.startsWith("--defer=")) options.defer = arg.split("=")[1];
6749
+ else if (arg === "--mark-advisory" && args[index + 1]) options.markAdvisory = args[++index];
6750
+ else if (arg.startsWith("--mark-advisory=")) options.markAdvisory = arg.split("=")[1];
6751
+ }
6752
+ return options;
6753
+ }
6754
+ function groupConflicts(conflicts) {
6755
+ const grouped = /* @__PURE__ */ new Map();
6756
+ for (const conflict of conflicts) {
6757
+ const key = conflict.lane;
6758
+ grouped.set(key, [...grouped.get(key) ?? [], conflict]);
6759
+ }
6760
+ return grouped;
6761
+ }
6762
+ function formatAuthorityResolutionText(projectRoot, conflicts, summary, stopRule) {
6763
+ const lines = [
6764
+ `${BOLD6}Decantr Authority Resolver${RESET12}`,
6765
+ "",
6766
+ `${DIM12}${resolve4(projectRoot)}${RESET12}`,
6767
+ `Authority: ${summary}`,
6768
+ `Stop rule: ${stopRule}`,
6769
+ ""
6770
+ ];
6771
+ if (conflicts.length === 0) {
6772
+ lines.push(`${GREEN12}No authority conflicts found.${RESET12}`);
6773
+ lines.push("");
6774
+ lines.push(`Next: ${DIM12}Run decantr task <route> "<intent>" before editing.${RESET12}`);
6775
+ return `${lines.join("\n")}
6776
+ `;
6777
+ }
6778
+ for (const [lane, laneConflicts] of groupConflicts(conflicts)) {
6779
+ lines.push(`${BOLD6}${lane}:${RESET12}`);
6780
+ for (const conflict of laneConflicts) {
6781
+ const color = conflict.status === "blocking" ? RED10 : conflict.status === "repairable" ? YELLOW9 : DIM12;
6782
+ lines.push(` ${color}[${conflict.status}]${RESET12} ${conflict.id}: ${conflict.message}`);
6783
+ lines.push(
6784
+ ` ${DIM12}${conflict.source} / ${conflict.category} / ${conflict.severity}${RESET12}`
6785
+ );
6786
+ for (const action of conflict.recommendedActions.slice(0, 4)) {
6787
+ lines.push(` - ${actionLabel(action)}`);
6788
+ }
6789
+ }
6790
+ lines.push("");
6791
+ }
6792
+ lines.push(`${BOLD6}Read-only by default:${RESET12}`);
6793
+ lines.push(
6794
+ " Use --defer <finding-id> or --mark-advisory <finding-id> to write only .decantr/drift-log.json."
6795
+ );
6796
+ return `${lines.join("\n")}
6797
+ `;
6798
+ }
6799
+ async function cmdResolve(projectRoot = process.cwd(), args = ["resolve"]) {
6800
+ const options = parseResolveArgs(args);
6801
+ const report = await createProjectHealthReport(projectRoot);
6802
+ const resolution = report.authority;
6803
+ if (options.defer || options.markAdvisory) {
6804
+ const findingId = options.defer ?? options.markAdvisory;
6805
+ const conflict = resolution.conflicts.find((entry) => entry.id === findingId);
6806
+ if (!conflict) {
6807
+ console.error(`${RED10}No authority conflict found for finding: ${findingId}${RESET12}`);
6808
+ process.exitCode = 1;
6809
+ return;
6810
+ }
6811
+ const path = appendDriftAction(
6812
+ projectRoot,
6813
+ conflict,
6814
+ options.defer ? "defer_to_drift_log" : "mark_advisory"
6815
+ );
6816
+ console.log(`${GREEN12}Updated drift log:${RESET12} ${path}`);
6817
+ return;
6818
+ }
6819
+ if (options.json) {
6820
+ process.stdout.write(`${JSON.stringify(resolution, null, 2)}
6821
+ `);
6822
+ return;
6823
+ }
6824
+ process.stdout.write(
6825
+ formatAuthorityResolutionText(
6826
+ projectRoot,
6827
+ resolution.conflicts,
6828
+ resolution.summary,
6829
+ resolution.stopRule
6830
+ )
6831
+ );
6832
+ }
6833
+
6834
+ // src/commands/sync-drift.ts
6835
+ import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "fs";
6836
+ import { join as join28 } from "path";
6837
+ var GREEN13 = "\x1B[32m";
6838
+ var RED11 = "\x1B[31m";
6839
+ var YELLOW10 = "\x1B[33m";
6840
+ var RESET13 = "\x1B[0m";
6841
+ var DIM13 = "\x1B[2m";
6842
+ var BOLD7 = "\x1B[1m";
6683
6843
  var CYAN6 = "\x1B[36m";
6684
6844
  async function cmdSyncDrift(projectRoot = process.cwd()) {
6685
- const driftLogPath = join27(projectRoot, ".decantr", "drift-log.json");
6686
- if (!existsSync25(driftLogPath)) {
6687
- console.log(`${GREEN12}No drift log found \u2014 no drift recorded.${RESET12}`);
6845
+ const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
6846
+ if (!existsSync26(driftLogPath2)) {
6847
+ console.log(`${GREEN13}No drift log found \u2014 no drift recorded.${RESET13}`);
6688
6848
  console.log(
6689
- `${DIM12}Drift is logged when guard violations are detected during development.${RESET12}`
6849
+ `${DIM13}Drift is logged when guard violations are detected during development.${RESET13}`
6690
6850
  );
6691
6851
  return;
6692
6852
  }
6693
6853
  let entries;
6694
6854
  try {
6695
- entries = JSON.parse(readFileSync18(driftLogPath, "utf-8"));
6855
+ entries = JSON.parse(readFileSync19(driftLogPath2, "utf-8"));
6696
6856
  } catch {
6697
- console.error(`${RED10}Could not parse drift-log.json${RESET12}`);
6857
+ console.error(`${RED11}Could not parse drift-log.json${RESET13}`);
6698
6858
  process.exitCode = 1;
6699
6859
  return;
6700
6860
  }
6701
6861
  if (!Array.isArray(entries)) {
6702
- console.error(`${RED10}drift-log.json is not an array${RESET12}`);
6862
+ console.error(`${RED11}drift-log.json is not an array${RESET13}`);
6703
6863
  process.exitCode = 1;
6704
6864
  return;
6705
6865
  }
6706
6866
  const unresolved = entries.filter((e) => !e.resolved);
6707
6867
  const resolved = entries.filter((e) => e.resolved);
6708
6868
  if (unresolved.length === 0) {
6709
- console.log(`${GREEN12}No unresolved drift entries.${RESET12}`);
6869
+ console.log(`${GREEN13}No unresolved drift entries.${RESET13}`);
6710
6870
  if (resolved.length > 0) {
6711
- console.log(`${DIM12}${resolved.length} previously resolved entries in the log.${RESET12}`);
6871
+ console.log(`${DIM13}${resolved.length} previously resolved entries in the log.${RESET13}`);
6712
6872
  }
6713
6873
  return;
6714
6874
  }
6715
6875
  console.log(`
6716
- ${BOLD6}Unresolved Drift Entries (${unresolved.length})${RESET12}
6876
+ ${BOLD7}Unresolved Drift Entries (${unresolved.length})${RESET13}
6717
6877
  `);
6718
6878
  for (let i = 0; i < unresolved.length; i++) {
6719
6879
  const entry = unresolved[i];
6720
- const severityColor = entry.severity === "error" ? RED10 : YELLOW9;
6880
+ const severityColor = entry.severity === "error" ? RED11 : YELLOW10;
6721
6881
  const icon = entry.severity === "error" ? "x" : "!";
6722
6882
  console.log(
6723
- ` ${severityColor}${icon}${RESET12} ${BOLD6}#${i + 1}${RESET12} [${entry.rule}] ${entry.message}`
6883
+ ` ${severityColor}${icon}${RESET13} ${BOLD7}#${i + 1}${RESET13} [${entry.rule}] ${entry.message}`
6724
6884
  );
6725
6885
  if (entry.page) {
6726
- console.log(` ${DIM12}Page: ${entry.page}${RESET12}`);
6886
+ console.log(` ${DIM13}Page: ${entry.page}${RESET13}`);
6727
6887
  }
6728
6888
  if (entry.suggestion) {
6729
- console.log(` ${CYAN6}Suggestion: ${entry.suggestion}${RESET12}`);
6889
+ console.log(` ${CYAN6}Suggestion: ${entry.suggestion}${RESET13}`);
6730
6890
  }
6731
- console.log(` ${DIM12}${entry.timestamp}${RESET12}`);
6891
+ console.log(` ${DIM13}${entry.timestamp}${RESET13}`);
6732
6892
  console.log("");
6733
6893
  }
6734
- console.log(`${BOLD6}Actions:${RESET12}`);
6735
- console.log(` ${CYAN6}decantr sync-drift --resolve-all${RESET12} Mark all entries as resolved`);
6736
- console.log(` ${CYAN6}decantr sync-drift --resolve <n>${RESET12} Mark entry #n as resolved`);
6737
- console.log(` ${CYAN6}decantr sync-drift --clear${RESET12} Clear the entire drift log`);
6894
+ console.log(`${BOLD7}Actions:${RESET13}`);
6895
+ console.log(` ${CYAN6}decantr sync-drift --resolve-all${RESET13} Mark all entries as resolved`);
6896
+ console.log(` ${CYAN6}decantr sync-drift --resolve <n>${RESET13} Mark entry #n as resolved`);
6897
+ console.log(` ${CYAN6}decantr sync-drift --clear${RESET13} Clear the entire drift log`);
6738
6898
  console.log("");
6739
6899
  }
6740
6900
  function resolveDriftEntries(projectRoot, options) {
6741
- const driftLogPath = join27(projectRoot, ".decantr", "drift-log.json");
6742
- if (!existsSync25(driftLogPath)) {
6901
+ const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
6902
+ if (!existsSync26(driftLogPath2)) {
6743
6903
  return { success: true };
6744
6904
  }
6745
6905
  if (options.clear) {
6746
6906
  try {
6747
- writeFileSync15(driftLogPath, "[]");
6907
+ writeFileSync16(driftLogPath2, "[]");
6748
6908
  return { success: true };
6749
6909
  } catch (e) {
6750
6910
  return { success: false, error: `Could not clear drift log: ${e.message}` };
@@ -6752,7 +6912,7 @@ function resolveDriftEntries(projectRoot, options) {
6752
6912
  }
6753
6913
  let entries;
6754
6914
  try {
6755
- entries = JSON.parse(readFileSync18(driftLogPath, "utf-8"));
6915
+ entries = JSON.parse(readFileSync19(driftLogPath2, "utf-8"));
6756
6916
  } catch {
6757
6917
  return { success: false, error: "Could not parse drift-log.json" };
6758
6918
  }
@@ -6771,7 +6931,7 @@ function resolveDriftEntries(projectRoot, options) {
6771
6931
  }
6772
6932
  }
6773
6933
  try {
6774
- writeFileSync15(driftLogPath, JSON.stringify(entries, null, 2));
6934
+ writeFileSync16(driftLogPath2, JSON.stringify(entries, null, 2));
6775
6935
  return { success: true };
6776
6936
  } catch (e) {
6777
6937
  return { success: false, error: `Could not write drift log: ${e.message}` };
@@ -6780,11 +6940,11 @@ function resolveDriftEntries(projectRoot, options) {
6780
6940
 
6781
6941
  // src/commands/telemetry.ts
6782
6942
  import { DECANTR_TELEMETRY_EVENT_CATALOG } from "@decantr/telemetry";
6783
- var BOLD7 = "\x1B[1m";
6943
+ var BOLD8 = "\x1B[1m";
6784
6944
  var CYAN7 = "\x1B[36m";
6785
- var DIM13 = "\x1B[2m";
6786
- var GREEN13 = "\x1B[32m";
6787
- var RESET13 = "\x1B[0m";
6945
+ var DIM14 = "\x1B[2m";
6946
+ var GREEN14 = "\x1B[32m";
6947
+ var RESET14 = "\x1B[0m";
6788
6948
  var DEFAULT_API_URL = "https://api.decantr.ai/v1";
6789
6949
  async function cmdTelemetry(args, projectRoot = process.cwd()) {
6790
6950
  const subcommand = args[0] ?? "status";
@@ -6809,14 +6969,14 @@ async function cmdTelemetry(args, projectRoot = process.cwd()) {
6809
6969
  }
6810
6970
  function printTelemetryHelp() {
6811
6971
  console.log(`
6812
- ${BOLD7}decantr telemetry${RESET13} \u2014 Inspect and link privacy-filtered CLI telemetry identity
6972
+ ${BOLD8}decantr telemetry${RESET14} \u2014 Inspect and link privacy-filtered CLI telemetry identity
6813
6973
 
6814
- ${BOLD7}Usage:${RESET13}
6974
+ ${BOLD8}Usage:${RESET14}
6815
6975
  decantr telemetry status [--json]
6816
6976
  decantr telemetry explain [--json]
6817
6977
  decantr telemetry link [--enable] [--org <slug>] [--label <label>] [--api-key <key>] [--api-url <url>]
6818
6978
 
6819
- ${BOLD7}Examples:${RESET13}
6979
+ ${BOLD8}Examples:${RESET14}
6820
6980
  decantr init --telemetry
6821
6981
  decantr telemetry status
6822
6982
  decantr telemetry explain
@@ -6831,18 +6991,18 @@ function printTelemetryStatus(projectRoot, options) {
6831
6991
  return;
6832
6992
  }
6833
6993
  console.log(`
6834
- ${BOLD7}Decantr telemetry${RESET13}`);
6835
- console.log(` Enabled: ${status.enabled ? `${GREEN13}yes${RESET13}` : "no"}`);
6994
+ ${BOLD8}Decantr telemetry${RESET14}`);
6995
+ console.log(` Enabled: ${status.enabled ? `${GREEN14}yes${RESET14}` : "no"}`);
6836
6996
  console.log(` Project: ${status.hasProjectConfig ? status.projectRoot : "not initialized"}`);
6837
- console.log(` Install ID: ${status.installId ?? `${DIM13}not created yet${RESET13}`}`);
6838
- console.log(` Project ID: ${status.projectId ?? `${DIM13}not created yet${RESET13}`}`);
6997
+ console.log(` Install ID: ${status.installId ?? `${DIM14}not created yet${RESET14}`}`);
6998
+ console.log(` Project ID: ${status.projectId ?? `${DIM14}not created yet${RESET14}`}`);
6839
6999
  if (status.enabled) {
6840
7000
  console.log(
6841
- DIM13 + "Run `decantr telemetry link` after login to attach these opaque IDs to your Decantr account/org." + RESET13
7001
+ DIM14 + "Run `decantr telemetry link` after login to attach these opaque IDs to your Decantr account/org." + RESET14
6842
7002
  );
6843
7003
  } else {
6844
7004
  console.log(
6845
- DIM13 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET13
7005
+ DIM14 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET14
6846
7006
  );
6847
7007
  }
6848
7008
  }
@@ -6904,25 +7064,25 @@ function printTelemetryExplain(projectRoot, options) {
6904
7064
  return;
6905
7065
  }
6906
7066
  console.log(`
6907
- ${BOLD7}Decantr telemetry explanation${RESET13}`);
7067
+ ${BOLD8}Decantr telemetry explanation${RESET14}`);
6908
7068
  console.log(` Source: cli`);
6909
- console.log(` Enabled: ${status.enabled ? `${GREEN13}yes${RESET13}` : "no"}`);
6910
- console.log(` Install ID: ${status.installId ?? `${DIM13}not created yet${RESET13}`}`);
6911
- console.log(` Project ID: ${status.projectId ?? `${DIM13}not created yet${RESET13}`}`);
7069
+ console.log(` Enabled: ${status.enabled ? `${GREEN14}yes${RESET14}` : "no"}`);
7070
+ console.log(` Install ID: ${status.installId ?? `${DIM14}not created yet${RESET14}`}`);
7071
+ console.log(` Project ID: ${status.projectId ?? `${DIM14}not created yet${RESET14}`}`);
6912
7072
  console.log(` Events: ${cliEvents.length} CLI event types in the public catalog`);
6913
7073
  console.log(`
6914
- ${BOLD7}Aggregate fields${RESET13}`);
7074
+ ${BOLD8}Aggregate fields${RESET14}`);
6915
7075
  for (const field of report.aggregateFields) {
6916
7076
  console.log(` - ${field}`);
6917
7077
  }
6918
7078
  console.log(`
6919
- ${BOLD7}Never collected${RESET13}`);
7079
+ ${BOLD8}Never collected${RESET14}`);
6920
7080
  for (const field of report.neverCollected) {
6921
7081
  console.log(` - ${field}`);
6922
7082
  }
6923
7083
  console.log(`
6924
- ${DIM13}${report.controls.optOut}${RESET13}`);
6925
- console.log(`${DIM13}${report.controls.link}${RESET13}`);
7084
+ ${DIM14}${report.controls.optOut}${RESET14}`);
7085
+ console.log(`${DIM14}${report.controls.link}${RESET14}`);
6926
7086
  }
6927
7087
  async function linkTelemetryIdentity(projectRoot, options) {
6928
7088
  if (options.enable && !isOptedIn(projectRoot)) {
@@ -6964,13 +7124,13 @@ async function linkTelemetryIdentity(projectRoot, options) {
6964
7124
  throw new Error(body2?.error ?? `Telemetry link failed with HTTP ${response.status}.`);
6965
7125
  }
6966
7126
  const body = await response.json().catch(() => ({ linked: 0 }));
6967
- console.log(`${GREEN13}Telemetry identity linked.${RESET13}`);
7127
+ console.log(`${GREEN14}Telemetry identity linked.${RESET14}`);
6968
7128
  console.log(` Linked: ${body.linked ?? 0}`);
6969
- console.log(` Install ID: ${identity.installId ?? `${DIM13}none${RESET13}`}`);
6970
- console.log(` Project ID: ${identity.projectId ?? `${DIM13}none${RESET13}`}`);
6971
- if (options.org) console.log(` Org: ${CYAN7}${options.org}${RESET13}`);
7129
+ console.log(` Install ID: ${identity.installId ?? `${DIM14}none${RESET14}`}`);
7130
+ console.log(` Project ID: ${identity.projectId ?? `${DIM14}none${RESET14}`}`);
7131
+ if (options.org) console.log(` Org: ${CYAN7}${options.org}${RESET14}`);
6972
7132
  console.log(
6973
- DIM13 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET13
7133
+ DIM14 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET14
6974
7134
  );
6975
7135
  }
6976
7136
  function parseTelemetryOptions(args) {
@@ -7008,41 +7168,41 @@ function trimTrailingSlashes(value) {
7008
7168
  }
7009
7169
 
7010
7170
  // src/commands/theme-switch.ts
7011
- import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "fs";
7012
- import { join as join28 } from "path";
7171
+ import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "fs";
7172
+ import { join as join29 } from "path";
7013
7173
  import { isV4 as isV47 } from "@decantr/essence-spec";
7014
- var GREEN14 = "\x1B[32m";
7015
- var RED11 = "\x1B[31m";
7016
- var YELLOW10 = "\x1B[33m";
7017
- var DIM14 = "\x1B[2m";
7018
- var RESET14 = "\x1B[0m";
7174
+ var GREEN15 = "\x1B[32m";
7175
+ var RED12 = "\x1B[31m";
7176
+ var YELLOW11 = "\x1B[33m";
7177
+ var DIM15 = "\x1B[2m";
7178
+ var RESET15 = "\x1B[0m";
7019
7179
  var VALID_THEME_SHAPES = ["sharp", "rounded", "pill"];
7020
7180
  var VALID_THEME_MODES = ["light", "dark", "auto"];
7021
7181
  async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
7022
7182
  if (!themeName) {
7023
7183
  console.error(
7024
- `${RED11}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET14}`
7184
+ `${RED12}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET15}`
7025
7185
  );
7026
7186
  process.exitCode = 1;
7027
7187
  return;
7028
7188
  }
7029
- const essencePath = join28(projectRoot, "decantr.essence.json");
7030
- if (!existsSync26(essencePath)) {
7031
- console.error(`${RED11}No decantr.essence.json found. Run \`decantr init\` first.${RESET14}`);
7189
+ const essencePath = join29(projectRoot, "decantr.essence.json");
7190
+ if (!existsSync27(essencePath)) {
7191
+ console.error(`${RED12}No decantr.essence.json found. Run \`decantr init\` first.${RESET15}`);
7032
7192
  process.exitCode = 1;
7033
7193
  return;
7034
7194
  }
7035
7195
  let parsed;
7036
7196
  try {
7037
- parsed = JSON.parse(readFileSync19(essencePath, "utf-8"));
7197
+ parsed = JSON.parse(readFileSync20(essencePath, "utf-8"));
7038
7198
  } catch (e) {
7039
- console.error(`${RED11}Could not read essence: ${e.message}${RESET14}`);
7199
+ console.error(`${RED12}Could not read essence: ${e.message}${RESET15}`);
7040
7200
  process.exitCode = 1;
7041
7201
  return;
7042
7202
  }
7043
7203
  if (!isV47(parsed)) {
7044
7204
  console.error(
7045
- `${RED11}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET14}`
7205
+ `${RED12}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET15}`
7046
7206
  );
7047
7207
  process.exitCode = 1;
7048
7208
  return;
@@ -7064,14 +7224,14 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
7064
7224
  }
7065
7225
  if (shape && !VALID_THEME_SHAPES.includes(shape)) {
7066
7226
  console.error(
7067
- `${RED11}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET14}`
7227
+ `${RED12}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET15}`
7068
7228
  );
7069
7229
  process.exitCode = 1;
7070
7230
  return;
7071
7231
  }
7072
7232
  if (mode && !VALID_THEME_MODES.includes(mode)) {
7073
7233
  console.error(
7074
- `${RED11}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET14}`
7234
+ `${RED12}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET15}`
7075
7235
  );
7076
7236
  process.exitCode = 1;
7077
7237
  return;
@@ -7085,7 +7245,7 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
7085
7245
  essence.dna.theme.mode = mode;
7086
7246
  }
7087
7247
  const registryClient = new RegistryClient({
7088
- cacheDir: join28(projectRoot, ".decantr", "cache")
7248
+ cacheDir: join29(projectRoot, ".decantr", "cache")
7089
7249
  });
7090
7250
  try {
7091
7251
  const themeResult = await registryClient.fetchTheme(themeName);
@@ -7100,45 +7260,45 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
7100
7260
  }
7101
7261
  } catch {
7102
7262
  }
7103
- writeFileSync16(essencePath, JSON.stringify(essence, null, 2) + "\n");
7104
- console.log(`${GREEN14}Switched theme: ${oldThemeId} \u2192 ${themeName}${RESET14}`);
7105
- if (shape) console.log(` ${DIM14}Shape: ${shape}${RESET14}`);
7106
- if (mode) console.log(` ${DIM14}Mode: ${mode}${RESET14}`);
7263
+ writeFileSync17(essencePath, JSON.stringify(essence, null, 2) + "\n");
7264
+ console.log(`${GREEN15}Switched theme: ${oldThemeId} \u2192 ${themeName}${RESET15}`);
7265
+ if (shape) console.log(` ${DIM15}Shape: ${shape}${RESET15}`);
7266
+ if (mode) console.log(` ${DIM15}Mode: ${mode}${RESET15}`);
7107
7267
  await refreshDerivedFiles(projectRoot, essence, registryClient);
7108
7268
  console.log(
7109
- `${GREEN14}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET14}`
7269
+ `${GREEN15}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET15}`
7110
7270
  );
7111
- console.log(`${YELLOW10}Guard will flag code using old tokens. Run \`decantr check\`.${RESET14}`);
7271
+ console.log(`${YELLOW11}Guard will flag code using old tokens. Run \`decantr check\`.${RESET15}`);
7112
7272
  }
7113
7273
 
7114
7274
  // src/prompts.ts
7115
7275
  import { createInterface } from "readline";
7116
- var BOLD8 = "\x1B[1m";
7117
- var DIM15 = "\x1B[2m";
7118
- var RESET15 = "\x1B[0m";
7119
- var GREEN15 = "\x1B[32m";
7120
- var YELLOW11 = "\x1B[33m";
7276
+ var BOLD9 = "\x1B[1m";
7277
+ var DIM16 = "\x1B[2m";
7278
+ var RESET16 = "\x1B[0m";
7279
+ var GREEN16 = "\x1B[32m";
7280
+ var YELLOW12 = "\x1B[33m";
7121
7281
  var CYAN8 = "\x1B[36m";
7122
7282
  function ask(question, defaultValue) {
7123
7283
  const rl = createInterface({ input: process.stdin, output: process.stdout });
7124
- const prompt = defaultValue ? `${question} ${DIM15}(${defaultValue})${RESET15}: ` : `${question}: `;
7125
- return new Promise((resolve5) => {
7284
+ const prompt = defaultValue ? `${question} ${DIM16}(${defaultValue})${RESET16}: ` : `${question}: `;
7285
+ return new Promise((resolve6) => {
7126
7286
  rl.question(prompt, (answer) => {
7127
7287
  rl.close();
7128
- resolve5(answer.trim() || defaultValue || "");
7288
+ resolve6(answer.trim() || defaultValue || "");
7129
7289
  });
7130
7290
  });
7131
7291
  }
7132
7292
  async function select(question, options, defaultIdx = 0, allowOther = false) {
7133
7293
  console.log(`
7134
- ${BOLD8}${question}${RESET15}`);
7294
+ ${BOLD9}${question}${RESET16}`);
7135
7295
  for (let i = 0; i < options.length; i++) {
7136
- const marker = i === defaultIdx ? `${GREEN15}>${RESET15}` : " ";
7137
- const desc = options[i].description ? ` ${DIM15}\u2014 ${options[i].description}${RESET15}` : "";
7296
+ const marker = i === defaultIdx ? `${GREEN16}>${RESET16}` : " ";
7297
+ const desc = options[i].description ? ` ${DIM16}\u2014 ${options[i].description}${RESET16}` : "";
7138
7298
  console.log(` ${marker} ${i + 1}. ${options[i].label}${desc}`);
7139
7299
  }
7140
7300
  if (allowOther) {
7141
- console.log(` ${options.length + 1}. ${DIM15}other (enter custom value)${RESET15}`);
7301
+ console.log(` ${options.length + 1}. ${DIM16}other (enter custom value)${RESET16}`);
7142
7302
  }
7143
7303
  const maxIdx = allowOther ? options.length + 1 : options.length;
7144
7304
  const answer = await ask(`Choose (1-${maxIdx})`, String(defaultIdx + 1));
@@ -7157,11 +7317,11 @@ async function confirm(question, defaultYes = true) {
7157
7317
  }
7158
7318
  function warn(message) {
7159
7319
  console.log(`
7160
- ${YELLOW11} Warning: ${message}${RESET15}`);
7320
+ ${YELLOW12} Warning: ${message}${RESET16}`);
7161
7321
  }
7162
7322
  function showDetection(detected) {
7163
7323
  console.log(`
7164
- ${CYAN8}Detected project configuration:${RESET15}`);
7324
+ ${CYAN8}Detected project configuration:${RESET16}`);
7165
7325
  if (detected.framework !== "unknown") {
7166
7326
  const version = detected.version ? ` ${detected.version}` : "";
7167
7327
  console.log(` Framework: ${detected.framework}${version}`);
@@ -7170,13 +7330,13 @@ ${CYAN8}Detected project configuration:${RESET15}`);
7170
7330
  console.log(` Package manager: ${detected.packageManager}`);
7171
7331
  }
7172
7332
  if (detected.hasTypeScript) {
7173
- console.log(` TypeScript: ${GREEN15}yes${RESET15}`);
7333
+ console.log(` TypeScript: ${GREEN16}yes${RESET16}`);
7174
7334
  }
7175
7335
  if (detected.hasTailwind) {
7176
- console.log(` Tailwind CSS: ${GREEN15}yes${RESET15}`);
7336
+ console.log(` Tailwind CSS: ${GREEN16}yes${RESET16}`);
7177
7337
  }
7178
7338
  if (detected.existingEssence) {
7179
- console.log(` Existing essence: ${YELLOW11}yes${RESET15}`);
7339
+ console.log(` Existing essence: ${YELLOW12}yes${RESET16}`);
7180
7340
  }
7181
7341
  }
7182
7342
  async function runInteractivePrompts(detected, archetypes, blueprints, themes, workflowSeed) {
@@ -7251,7 +7411,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes, w
7251
7411
  warn(`This project appears to be ${detected.framework} but you selected ${target}.`);
7252
7412
  const proceed = await confirm("Continue anyway?", false);
7253
7413
  if (!proceed) {
7254
- console.log(`${DIM15}Using detected framework: ${detected.framework}${RESET15}`);
7414
+ console.log(`${DIM16}Using detected framework: ${detected.framework}${RESET16}`);
7255
7415
  }
7256
7416
  }
7257
7417
  const guardMode = await select(
@@ -7376,7 +7536,7 @@ function mergeWithDefaults(flags, detected, workflowSeed) {
7376
7536
  }
7377
7537
  async function runSimplifiedInit(blueprints) {
7378
7538
  const rl = createInterface({ input: process.stdin, output: process.stdout });
7379
- const question = (q) => new Promise((resolve5) => rl.question(q, resolve5));
7539
+ const question = (q) => new Promise((resolve6) => rl.question(q, resolve6));
7380
7540
  console.log("\n? What blueprint would you like to scaffold?\n");
7381
7541
  console.log(" 1. Decantr default (recommended)");
7382
7542
  console.log(" 2. Search registry...\n");
@@ -7408,8 +7568,8 @@ async function runSimplifiedInit(blueprints) {
7408
7568
  }
7409
7569
 
7410
7570
  // src/theme-commands.ts
7411
- import { existsSync as existsSync27, mkdirSync as mkdirSync14, readdirSync as readdirSync7, readFileSync as readFileSync20, rmSync as rmSync3, writeFileSync as writeFileSync17 } from "fs";
7412
- import { join as join29 } from "path";
7571
+ import { existsSync as existsSync28, mkdirSync as mkdirSync15, readdirSync as readdirSync7, readFileSync as readFileSync21, rmSync as rmSync3, writeFileSync as writeFileSync18 } from "fs";
7572
+ import { join as join30 } from "path";
7413
7573
  var REQUIRED_FIELDS = [
7414
7574
  "$schema",
7415
7575
  "id",
@@ -7469,20 +7629,20 @@ function validateCustomTheme(theme) {
7469
7629
  };
7470
7630
  }
7471
7631
  function createTheme(projectRoot, id, name) {
7472
- const customThemesDir = join29(projectRoot, ".decantr", "custom", "themes");
7473
- const themePath = join29(customThemesDir, `${id}.json`);
7474
- const howToPath = join29(customThemesDir, "how-to-theme.md");
7475
- mkdirSync14(customThemesDir, { recursive: true });
7476
- if (existsSync27(themePath)) {
7632
+ const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
7633
+ const themePath = join30(customThemesDir, `${id}.json`);
7634
+ const howToPath = join30(customThemesDir, "how-to-theme.md");
7635
+ mkdirSync15(customThemesDir, { recursive: true });
7636
+ if (existsSync28(themePath)) {
7477
7637
  return {
7478
7638
  success: false,
7479
7639
  error: `Theme "${id}" already exists at ${themePath}`
7480
7640
  };
7481
7641
  }
7482
7642
  const skeleton = getThemeSkeleton(id, name);
7483
- writeFileSync17(themePath, JSON.stringify(skeleton, null, 2));
7484
- if (!existsSync27(howToPath)) {
7485
- writeFileSync17(howToPath, getHowToThemeDoc());
7643
+ writeFileSync18(themePath, JSON.stringify(skeleton, null, 2));
7644
+ if (!existsSync28(howToPath)) {
7645
+ writeFileSync18(howToPath, getHowToThemeDoc());
7486
7646
  }
7487
7647
  return {
7488
7648
  success: true,
@@ -7490,17 +7650,17 @@ function createTheme(projectRoot, id, name) {
7490
7650
  };
7491
7651
  }
7492
7652
  function listCustomThemes(projectRoot) {
7493
- const customThemesDir = join29(projectRoot, ".decantr", "custom", "themes");
7494
- if (!existsSync27(customThemesDir)) {
7653
+ const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
7654
+ if (!existsSync28(customThemesDir)) {
7495
7655
  return [];
7496
7656
  }
7497
7657
  const themes = [];
7498
7658
  try {
7499
7659
  const files = readdirSync7(customThemesDir).filter((f) => f.endsWith(".json"));
7500
7660
  for (const file of files) {
7501
- const filePath = join29(customThemesDir, file);
7661
+ const filePath = join30(customThemesDir, file);
7502
7662
  try {
7503
- const data = JSON.parse(readFileSync20(filePath, "utf-8"));
7663
+ const data = JSON.parse(readFileSync21(filePath, "utf-8"));
7504
7664
  themes.push({
7505
7665
  id: data.id || file.replace(".json", ""),
7506
7666
  name: data.name || data.id,
@@ -7515,8 +7675,8 @@ function listCustomThemes(projectRoot) {
7515
7675
  return themes;
7516
7676
  }
7517
7677
  function deleteTheme(projectRoot, id) {
7518
- const themePath = join29(projectRoot, ".decantr", "custom", "themes", `${id}.json`);
7519
- if (!existsSync27(themePath)) {
7678
+ const themePath = join30(projectRoot, ".decantr", "custom", "themes", `${id}.json`);
7679
+ if (!existsSync28(themePath)) {
7520
7680
  return {
7521
7681
  success: false,
7522
7682
  error: `Theme "${id}" not found at ${themePath}`
@@ -7533,7 +7693,7 @@ function deleteTheme(projectRoot, id) {
7533
7693
  }
7534
7694
  }
7535
7695
  function importTheme(projectRoot, sourcePath) {
7536
- if (!existsSync27(sourcePath)) {
7696
+ if (!existsSync28(sourcePath)) {
7537
7697
  return {
7538
7698
  success: false,
7539
7699
  errors: [`Source file not found: ${sourcePath}`]
@@ -7541,7 +7701,7 @@ function importTheme(projectRoot, sourcePath) {
7541
7701
  }
7542
7702
  let theme;
7543
7703
  try {
7544
- theme = JSON.parse(readFileSync20(sourcePath, "utf-8"));
7704
+ theme = JSON.parse(readFileSync21(sourcePath, "utf-8"));
7545
7705
  } catch (e) {
7546
7706
  return {
7547
7707
  success: false,
@@ -7557,14 +7717,14 @@ function importTheme(projectRoot, sourcePath) {
7557
7717
  }
7558
7718
  theme.source = "custom";
7559
7719
  const id = theme.id;
7560
- const customThemesDir = join29(projectRoot, ".decantr", "custom", "themes");
7561
- const destPath = join29(customThemesDir, `${id}.json`);
7562
- mkdirSync14(customThemesDir, { recursive: true });
7563
- const howToPath = join29(customThemesDir, "how-to-theme.md");
7564
- if (!existsSync27(howToPath)) {
7565
- writeFileSync17(howToPath, getHowToThemeDoc());
7566
- }
7567
- writeFileSync17(destPath, JSON.stringify(theme, null, 2));
7720
+ const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
7721
+ const destPath = join30(customThemesDir, `${id}.json`);
7722
+ mkdirSync15(customThemesDir, { recursive: true });
7723
+ const howToPath = join30(customThemesDir, "how-to-theme.md");
7724
+ if (!existsSync28(howToPath)) {
7725
+ writeFileSync18(howToPath, getHowToThemeDoc());
7726
+ }
7727
+ writeFileSync18(destPath, JSON.stringify(theme, null, 2));
7568
7728
  return {
7569
7729
  success: true,
7570
7730
  path: destPath
@@ -7572,29 +7732,29 @@ function importTheme(projectRoot, sourcePath) {
7572
7732
  }
7573
7733
 
7574
7734
  // src/index.ts
7575
- var BOLD9 = "\x1B[1m";
7576
- var DIM16 = "\x1B[2m";
7577
- var RESET16 = "\x1B[0m";
7578
- var RED12 = "\x1B[31m";
7579
- var GREEN16 = "\x1B[32m";
7735
+ var BOLD10 = "\x1B[1m";
7736
+ var DIM17 = "\x1B[2m";
7737
+ var RESET17 = "\x1B[0m";
7738
+ var RED13 = "\x1B[31m";
7739
+ var GREEN17 = "\x1B[32m";
7580
7740
  var CYAN9 = "\x1B[36m";
7581
- var YELLOW12 = "\x1B[33m";
7741
+ var YELLOW13 = "\x1B[33m";
7582
7742
  function heading2(text) {
7583
7743
  return `
7584
- ${BOLD9}${text}${RESET16}
7744
+ ${BOLD10}${text}${RESET17}
7585
7745
  `;
7586
7746
  }
7587
7747
  function success3(text) {
7588
- return `${GREEN16}${text}${RESET16}`;
7748
+ return `${GREEN17}${text}${RESET17}`;
7589
7749
  }
7590
7750
  function error2(text) {
7591
- return `${RED12}${text}${RESET16}`;
7751
+ return `${RED13}${text}${RESET17}`;
7592
7752
  }
7593
7753
  function dim3(text) {
7594
- return `${DIM16}${text}${RESET16}`;
7754
+ return `${DIM17}${text}${RESET17}`;
7595
7755
  }
7596
7756
  function cyan3(text) {
7597
- return `${CYAN9}${text}${RESET16}`;
7757
+ return `${CYAN9}${text}${RESET17}`;
7598
7758
  }
7599
7759
  function formatIntelligenceSummary(intelligence) {
7600
7760
  if (!intelligence) {
@@ -8098,7 +8258,7 @@ function getPublicAPIClient() {
8098
8258
  });
8099
8259
  }
8100
8260
  function resolveUserPath(inputPath, cwd = process.cwd()) {
8101
- return isAbsolute3(inputPath) ? inputPath : resolve4(cwd, inputPath);
8261
+ return isAbsolute3(inputPath) ? inputPath : resolve5(cwd, inputPath);
8102
8262
  }
8103
8263
  function extractHostedAssetPaths(indexHtml) {
8104
8264
  const assetPaths = /* @__PURE__ */ new Set();
@@ -8111,18 +8271,18 @@ function extractHostedAssetPaths(indexHtml) {
8111
8271
  return [...assetPaths];
8112
8272
  }
8113
8273
  function readHostedDistSnapshot(distPath) {
8114
- const resolvedDistPath = distPath ? resolveUserPath(distPath) : join30(process.cwd(), "dist");
8115
- const indexPath = join30(resolvedDistPath, "index.html");
8116
- if (!existsSync28(indexPath)) {
8274
+ const resolvedDistPath = distPath ? resolveUserPath(distPath) : join31(process.cwd(), "dist");
8275
+ const indexPath = join31(resolvedDistPath, "index.html");
8276
+ if (!existsSync29(indexPath)) {
8117
8277
  return void 0;
8118
8278
  }
8119
- const indexHtml = readFileSync21(indexPath, "utf-8");
8279
+ const indexHtml = readFileSync22(indexPath, "utf-8");
8120
8280
  const assetPaths = extractHostedAssetPaths(indexHtml);
8121
8281
  const assets = {};
8122
8282
  for (const assetPath of assetPaths) {
8123
- const assetFilePath = join30(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
8124
- if (existsSync28(assetFilePath)) {
8125
- assets[assetPath] = readFileSync21(assetFilePath, "utf-8");
8283
+ const assetFilePath = join31(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
8284
+ if (existsSync29(assetFilePath)) {
8285
+ assets[assetPath] = readFileSync22(assetFilePath, "utf-8");
8126
8286
  }
8127
8287
  }
8128
8288
  return {
@@ -8137,7 +8297,7 @@ function isHostedSourceSnapshotFile(path) {
8137
8297
  function readHostedSourceSnapshot(sourcePath) {
8138
8298
  if (!sourcePath) return void 0;
8139
8299
  const resolvedSourcePath = resolveUserPath(sourcePath);
8140
- if (!existsSync28(resolvedSourcePath)) {
8300
+ if (!existsSync29(resolvedSourcePath)) {
8141
8301
  return void 0;
8142
8302
  }
8143
8303
  const files = {};
@@ -8153,15 +8313,15 @@ function readHostedSourceSnapshot(sourcePath) {
8153
8313
  const walk = (absoluteDir, relativeDir) => {
8154
8314
  for (const entry of readdirSync8(absoluteDir, { withFileTypes: true })) {
8155
8315
  if (ignoredDirNames.has(entry.name)) continue;
8156
- const absolutePath = join30(absoluteDir, entry.name);
8157
- const relativePath = join30(relativeDir, entry.name).replace(/\\/g, "/");
8316
+ const absolutePath = join31(absoluteDir, entry.name);
8317
+ const relativePath = join31(relativeDir, entry.name).replace(/\\/g, "/");
8158
8318
  if (entry.isDirectory()) {
8159
8319
  walk(absolutePath, relativePath);
8160
8320
  continue;
8161
8321
  }
8162
8322
  if (!entry.isFile()) continue;
8163
8323
  if (!isHostedSourceSnapshotFile(relativePath)) continue;
8164
- files[relativePath] = readFileSync21(absolutePath, "utf-8");
8324
+ files[relativePath] = readFileSync22(absolutePath, "utf-8");
8165
8325
  }
8166
8326
  };
8167
8327
  walk(resolvedSourcePath, rootPrefix);
@@ -8345,7 +8505,7 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
8345
8505
  console.log(` Files written: ${writtenContextPaths.length}`);
8346
8506
  }
8347
8507
  console.log("");
8348
- console.log(`${BOLD9}Route Plan:${RESET16}`);
8508
+ console.log(`${BOLD10}Route Plan:${RESET17}`);
8349
8509
  for (const route of typedBundle.scaffold.data.routes) {
8350
8510
  const patterns = route.patternIds.length > 0 ? route.patternIds.join(", ") : "none";
8351
8511
  const pageLabel = route.sectionId ? `${route.sectionId}/${route.pageId}` : route.pageId;
@@ -8354,24 +8514,24 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
8354
8514
  }
8355
8515
  async function compileHostedExecutionPackBundle(essencePath, namespace) {
8356
8516
  const client = getPublicAPIClient();
8357
- const resolvedPath = essencePath ? resolveUserPath(essencePath) : join30(process.cwd(), "decantr.essence.json");
8358
- if (!existsSync28(resolvedPath)) {
8517
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
8518
+ if (!existsSync29(resolvedPath)) {
8359
8519
  throw new Error(`Essence file not found at ${resolvedPath}`);
8360
8520
  }
8361
- const essence = JSON.parse(readFileSync21(resolvedPath, "utf-8"));
8521
+ const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
8362
8522
  const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
8363
- const contextDir = join30(dirname6(resolvedPath), ".decantr", "context");
8523
+ const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
8364
8524
  return { resolvedPath, bundle, contextDir };
8365
8525
  }
8366
8526
  function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
8367
- mkdirSync15(contextDir, { recursive: true });
8527
+ mkdirSync16(contextDir, { recursive: true });
8368
8528
  return writeExecutionPackBundleArtifacts(contextDir, bundle);
8369
8529
  }
8370
8530
  function resolvePagePackIdForRoute(essencePath, route) {
8371
- if (!existsSync28(essencePath)) {
8531
+ if (!existsSync29(essencePath)) {
8372
8532
  throw new Error(`Essence file not found at ${essencePath}`);
8373
8533
  }
8374
- const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
8534
+ const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
8375
8535
  if (!isV48(essence)) {
8376
8536
  throw new Error("Route-based pack resolution requires Essence v4.0.0.");
8377
8537
  }
@@ -8386,14 +8546,14 @@ function resolvePagePackIdForRoute(essencePath, route) {
8386
8546
  }
8387
8547
  async function printHostedSelectedExecutionPack(packType, id, essencePath, namespace, jsonOutput = false, writeContext = false) {
8388
8548
  const client = getPublicAPIClient();
8389
- const resolvedPath = essencePath ? resolveUserPath(essencePath) : join30(process.cwd(), "decantr.essence.json");
8390
- if (!existsSync28(resolvedPath)) {
8549
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
8550
+ if (!existsSync29(resolvedPath)) {
8391
8551
  throw new Error(`Essence file not found at ${resolvedPath}`);
8392
8552
  }
8393
8553
  if ((packType === "section" || packType === "page" || packType === "mutation") && !id) {
8394
8554
  throw new Error(`Pack type "${packType}" requires an id.`);
8395
8555
  }
8396
- const essence = JSON.parse(readFileSync21(resolvedPath, "utf-8"));
8556
+ const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
8397
8557
  const selected = await client.selectExecutionPack(
8398
8558
  {
8399
8559
  essence,
@@ -8404,17 +8564,17 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
8404
8564
  );
8405
8565
  let writtenContextDir = null;
8406
8566
  if (writeContext) {
8407
- const contextDir = join30(dirname6(resolvedPath), ".decantr", "context");
8408
- mkdirSync15(contextDir, { recursive: true });
8409
- writeFileSync18(
8410
- join30(contextDir, "pack-manifest.json"),
8567
+ const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
8568
+ mkdirSync16(contextDir, { recursive: true });
8569
+ writeFileSync19(
8570
+ join31(contextDir, "pack-manifest.json"),
8411
8571
  JSON.stringify(selected.manifest, null, 2) + "\n"
8412
8572
  );
8413
8573
  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);
8414
8574
  const markdownFile = manifestEntry?.markdown ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.md`;
8415
8575
  const jsonFile = manifestEntry?.json ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.json`;
8416
- writeFileSync18(join30(contextDir, markdownFile), selected.pack.renderedMarkdown);
8417
- writeFileSync18(join30(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
8576
+ writeFileSync19(join31(contextDir, markdownFile), selected.pack.renderedMarkdown);
8577
+ writeFileSync19(join31(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
8418
8578
  writtenContextDir = contextDir;
8419
8579
  }
8420
8580
  if (jsonOutput) {
@@ -8439,20 +8599,20 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
8439
8599
  }
8440
8600
  async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutput = false, writeContext = false) {
8441
8601
  const client = getPublicAPIClient();
8442
- const resolvedPath = essencePath ? resolveUserPath(essencePath) : join30(process.cwd(), "decantr.essence.json");
8443
- if (!existsSync28(resolvedPath)) {
8602
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
8603
+ if (!existsSync29(resolvedPath)) {
8444
8604
  throw new Error(`Essence file not found at ${resolvedPath}`);
8445
8605
  }
8446
- const essence = JSON.parse(readFileSync21(resolvedPath, "utf-8"));
8606
+ const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
8447
8607
  const manifest = await client.getExecutionPackManifest(
8448
8608
  essence,
8449
8609
  namespace ? { namespace } : void 0
8450
8610
  );
8451
8611
  let writtenContextDir = null;
8452
8612
  if (writeContext) {
8453
- const contextDir = join30(dirname6(resolvedPath), ".decantr", "context");
8454
- mkdirSync15(contextDir, { recursive: true });
8455
- writeFileSync18(join30(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
8613
+ const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
8614
+ mkdirSync16(contextDir, { recursive: true });
8615
+ writeFileSync19(join31(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
8456
8616
  writtenContextDir = contextDir;
8457
8617
  }
8458
8618
  if (jsonOutput) {
@@ -8473,14 +8633,14 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
8473
8633
  }
8474
8634
  }
8475
8635
  async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@official") {
8476
- const contextDir = join30(projectRoot, ".decantr", "context");
8477
- const reviewPackPath = join30(contextDir, "review-pack.json");
8478
- const manifestPath = join30(contextDir, "pack-manifest.json");
8479
- if (existsSync28(reviewPackPath) && existsSync28(manifestPath)) {
8636
+ const contextDir = join31(projectRoot, ".decantr", "context");
8637
+ const reviewPackPath = join31(contextDir, "review-pack.json");
8638
+ const manifestPath = join31(contextDir, "pack-manifest.json");
8639
+ if (existsSync29(reviewPackPath) && existsSync29(manifestPath)) {
8480
8640
  return { attempted: false, hydrated: false };
8481
8641
  }
8482
- const essencePath = join30(projectRoot, "decantr.essence.json");
8483
- if (!existsSync28(essencePath)) {
8642
+ const essencePath = join31(projectRoot, "decantr.essence.json");
8643
+ if (!existsSync29(essencePath)) {
8484
8644
  return { attempted: false, hydrated: false };
8485
8645
  }
8486
8646
  const reviewHydration = await hydrateHostedReviewPackIfMissing(projectRoot, namespace);
@@ -8489,9 +8649,9 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
8489
8649
  }
8490
8650
  try {
8491
8651
  const client = getPublicAPIClient();
8492
- const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
8652
+ const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
8493
8653
  const bundle = await client.compileExecutionPacks(essence, { namespace });
8494
- mkdirSync15(contextDir, { recursive: true });
8654
+ mkdirSync16(contextDir, { recursive: true });
8495
8655
  writeExecutionPackBundleArtifacts(contextDir, bundle);
8496
8656
  return { attempted: true, hydrated: true, scope: "bundle" };
8497
8657
  } catch {
@@ -8499,19 +8659,19 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
8499
8659
  }
8500
8660
  }
8501
8661
  async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@official") {
8502
- const contextDir = join30(projectRoot, ".decantr", "context");
8503
- const reviewPackPath = join30(contextDir, "review-pack.json");
8504
- const manifestPath = join30(contextDir, "pack-manifest.json");
8505
- if (existsSync28(reviewPackPath) && existsSync28(manifestPath)) {
8662
+ const contextDir = join31(projectRoot, ".decantr", "context");
8663
+ const reviewPackPath = join31(contextDir, "review-pack.json");
8664
+ const manifestPath = join31(contextDir, "pack-manifest.json");
8665
+ if (existsSync29(reviewPackPath) && existsSync29(manifestPath)) {
8506
8666
  return { attempted: false, hydrated: false };
8507
8667
  }
8508
- const essencePath = join30(projectRoot, "decantr.essence.json");
8509
- if (!existsSync28(essencePath)) {
8668
+ const essencePath = join31(projectRoot, "decantr.essence.json");
8669
+ if (!existsSync29(essencePath)) {
8510
8670
  return { attempted: false, hydrated: false };
8511
8671
  }
8512
8672
  try {
8513
8673
  const client = getPublicAPIClient();
8514
- const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
8674
+ const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
8515
8675
  const selected = await client.selectExecutionPack(
8516
8676
  {
8517
8677
  essence,
@@ -8519,14 +8679,14 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
8519
8679
  },
8520
8680
  { namespace }
8521
8681
  );
8522
- mkdirSync15(contextDir, { recursive: true });
8523
- writeFileSync18(join30(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
8524
- writeFileSync18(
8525
- join30(contextDir, "review-pack.json"),
8682
+ mkdirSync16(contextDir, { recursive: true });
8683
+ writeFileSync19(join31(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
8684
+ writeFileSync19(
8685
+ join31(contextDir, "review-pack.json"),
8526
8686
  JSON.stringify(selected.pack, null, 2) + "\n"
8527
8687
  );
8528
- if (!existsSync28(manifestPath)) {
8529
- writeFileSync18(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
8688
+ if (!existsSync29(manifestPath)) {
8689
+ writeFileSync19(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
8530
8690
  }
8531
8691
  return { attempted: true, hydrated: true, scope: "review" };
8532
8692
  } catch {
@@ -8536,17 +8696,17 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
8536
8696
  async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false, essencePath, treatmentsPath) {
8537
8697
  const client = getPublicAPIClient();
8538
8698
  const resolvedSourcePath = resolveUserPath(sourcePath);
8539
- const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join30(process.cwd(), "decantr.essence.json");
8540
- const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join30(process.cwd(), "src", "styles", "treatments.css");
8541
- if (!existsSync28(resolvedSourcePath)) {
8699
+ const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
8700
+ const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join31(process.cwd(), "src", "styles", "treatments.css");
8701
+ if (!existsSync29(resolvedSourcePath)) {
8542
8702
  throw new Error(`Source file not found at ${resolvedSourcePath}`);
8543
8703
  }
8544
- if (!existsSync28(resolvedEssencePath)) {
8704
+ if (!existsSync29(resolvedEssencePath)) {
8545
8705
  throw new Error(`Essence file not found at ${resolvedEssencePath}`);
8546
8706
  }
8547
- const code = readFileSync21(resolvedSourcePath, "utf-8");
8548
- const essence = JSON.parse(readFileSync21(resolvedEssencePath, "utf-8"));
8549
- const treatmentsCss = existsSync28(resolvedTreatmentsPath) ? readFileSync21(resolvedTreatmentsPath, "utf-8") : void 0;
8707
+ const code = readFileSync22(resolvedSourcePath, "utf-8");
8708
+ const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
8709
+ const treatmentsCss = existsSync29(resolvedTreatmentsPath) ? readFileSync22(resolvedTreatmentsPath, "utf-8") : void 0;
8550
8710
  const report = await client.critiqueFile(
8551
8711
  {
8552
8712
  essence,
@@ -8570,11 +8730,11 @@ async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false
8570
8730
  }
8571
8731
  async function printHostedProjectAudit(namespace, jsonOutput = false, essencePath, distPath, sourcesPath) {
8572
8732
  const client = getPublicAPIClient();
8573
- const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join30(process.cwd(), "decantr.essence.json");
8574
- if (!existsSync28(resolvedEssencePath)) {
8733
+ const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
8734
+ if (!existsSync29(resolvedEssencePath)) {
8575
8735
  throw new Error(`Essence file not found at ${resolvedEssencePath}`);
8576
8736
  }
8577
- const essence = JSON.parse(readFileSync21(resolvedEssencePath, "utf-8"));
8737
+ const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
8578
8738
  const dist = readHostedDistSnapshot(distPath);
8579
8739
  const sources = readHostedSourceSnapshot(sourcesPath);
8580
8740
  const report = await client.auditProject(
@@ -8592,7 +8752,7 @@ async function printHostedProjectAudit(namespace, jsonOutput = false, essencePat
8592
8752
  console.log(heading2("Hosted Project Audit"));
8593
8753
  console.log(` Essence: ${resolvedEssencePath}`);
8594
8754
  console.log(
8595
- ` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join30(process.cwd(), "dist") : "none"}`
8755
+ ` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join31(process.cwd(), "dist") : "none"}`
8596
8756
  );
8597
8757
  console.log(
8598
8758
  ` Source snapshot: ${sources && sourcesPath ? resolveUserPath(sourcesPath) : "none"}`
@@ -8621,7 +8781,7 @@ function printBlueprintPortfolioNotice(blueprint) {
8621
8781
  if (!portfolio) return;
8622
8782
  if (portfolio.visibility === "hidden" || portfolio.maturity === "fold-candidate") {
8623
8783
  console.log(
8624
- `${YELLOW12} Warning:${RESET16} blueprint "${blueprint.id}" is folded out of public browsing.`
8784
+ `${YELLOW13} Warning:${RESET17} blueprint "${blueprint.id}" is folded out of public browsing.`
8625
8785
  );
8626
8786
  if (portfolio.recommended_alternative) {
8627
8787
  console.log(
@@ -8634,7 +8794,7 @@ function printBlueprintPortfolioNotice(blueprint) {
8634
8794
  }
8635
8795
  if (portfolio.visibility === "labs") {
8636
8796
  console.log(
8637
- `${YELLOW12} Note:${RESET16} blueprint "${blueprint.id}" is a Labs blueprint; direct scaffolding is supported, but it is not a default recommendation yet.`
8797
+ `${YELLOW13} Note:${RESET17} blueprint "${blueprint.id}" is a Labs blueprint; direct scaffolding is supported, but it is not a default recommendation yet.`
8638
8798
  );
8639
8799
  }
8640
8800
  }
@@ -8656,7 +8816,7 @@ async function cmdSearch(query, type, sort, recommended, intelligenceSource, blu
8656
8816
  }
8657
8817
  console.log(heading2(`${results.length} result(s) for "${query}"`));
8658
8818
  for (const r of results) {
8659
- console.log(` ${cyan3(r.type.padEnd(12))} ${BOLD9}${r.slug}${RESET16}`);
8819
+ console.log(` ${cyan3(r.type.padEnd(12))} ${BOLD10}${r.slug}${RESET17}`);
8660
8820
  console.log(` ${dim3(r.description || "")}`);
8661
8821
  const intelligenceSummary = formatIntelligenceSummary(r.intelligence);
8662
8822
  if (intelligenceSummary) {
@@ -8714,21 +8874,21 @@ function findPatternCandidateBySlug(candidates, slug) {
8714
8874
  function readSuggestCodeContext(projectRoot, route, file) {
8715
8875
  const pieces = [];
8716
8876
  if (file) {
8717
- const resolved = isAbsolute3(file) ? file : join30(projectRoot, file);
8718
- if (existsSync28(resolved)) {
8719
- pieces.push(readFileSync21(resolved, "utf-8"));
8877
+ const resolved = isAbsolute3(file) ? file : join31(projectRoot, file);
8878
+ if (existsSync29(resolved)) {
8879
+ pieces.push(readFileSync22(resolved, "utf-8"));
8720
8880
  }
8721
8881
  }
8722
8882
  if (route) {
8723
- const analysisPath = join30(projectRoot, ".decantr", "analysis.json");
8724
- if (existsSync28(analysisPath)) {
8883
+ const analysisPath = join31(projectRoot, ".decantr", "analysis.json");
8884
+ if (existsSync29(analysisPath)) {
8725
8885
  try {
8726
- const analysis = JSON.parse(readFileSync21(analysisPath, "utf-8"));
8886
+ const analysis = JSON.parse(readFileSync22(analysisPath, "utf-8"));
8727
8887
  const routeEntry = analysis.routes?.routes?.find((entry) => entry.path === route);
8728
8888
  if (routeEntry?.file) {
8729
- const resolved = join30(projectRoot, routeEntry.file);
8730
- if (existsSync28(resolved)) {
8731
- pieces.push(readFileSync21(resolved, "utf-8"));
8889
+ const resolved = join31(projectRoot, routeEntry.file);
8890
+ if (existsSync29(resolved)) {
8891
+ pieces.push(readFileSync22(resolved, "utf-8"));
8732
8892
  }
8733
8893
  }
8734
8894
  } catch {
@@ -8814,7 +8974,7 @@ async function cmdSuggest(query, options = {}) {
8814
8974
  }
8815
8975
  }
8816
8976
  const registryClient = new RegistryClient({
8817
- cacheDir: join30(projectRoot, ".decantr", "cache")
8977
+ cacheDir: join31(projectRoot, ".decantr", "cache")
8818
8978
  });
8819
8979
  const code = options.fromCode || options.file ? readSuggestCodeContext(projectRoot, options.route, options.file) : "";
8820
8980
  const localMatches = localPatternMatches(projectRoot, [query, code].filter(Boolean).join("\n"));
@@ -8850,7 +9010,7 @@ async function cmdSuggest(query, options = {}) {
8850
9010
  )
8851
9011
  );
8852
9012
  if (bridgeMatches.length > 0) {
8853
- console.log(`${BOLD9}Project-owned style bridge:${RESET16}`);
9013
+ console.log(`${BOLD10}Project-owned style bridge:${RESET17}`);
8854
9014
  for (const match of bridgeMatches) {
8855
9015
  const hints = [...match.tokenHints, ...match.classHints].slice(0, 3).join(", ");
8856
9016
  console.log(` ${cyan3(match.id)} ${match.label}${hints ? ` ${dim3(hints)}` : ""}`);
@@ -8858,13 +9018,13 @@ async function cmdSuggest(query, options = {}) {
8858
9018
  console.log("");
8859
9019
  }
8860
9020
  if (localMatches.length > 0) {
8861
- console.log(`${BOLD9}Project-owned local law:${RESET16}`);
9021
+ console.log(`${BOLD10}Project-owned local law:${RESET17}`);
8862
9022
  for (const match of localMatches) {
8863
9023
  const details = [match.label, match.role].filter(Boolean).join(" | ");
8864
9024
  console.log(` ${cyan3(match.id)}${details ? ` ${dim3(details)}` : ""}`);
8865
9025
  }
8866
9026
  console.log("");
8867
- console.log(`${BOLD9}Registry patterns:${RESET16}`);
9027
+ console.log(`${BOLD10}Registry patterns:${RESET17}`);
8868
9028
  }
8869
9029
  if (matches.length === 0) {
8870
9030
  console.log(dim3("No hosted/bundled registry patterns matched this query."));
@@ -8903,7 +9063,7 @@ async function cmdGet(type, id) {
8903
9063
  }
8904
9064
  const apiType = CONTENT_TYPE_TO_API_CONTENT_TYPE3[type];
8905
9065
  const registryClient = new RegistryClient({
8906
- cacheDir: join30(process.cwd(), ".decantr", "cache")
9066
+ cacheDir: join31(process.cwd(), ".decantr", "cache")
8907
9067
  });
8908
9068
  const result = await registryClient.fetchContentItem(apiType, id);
8909
9069
  if (result) {
@@ -8920,10 +9080,10 @@ async function cmdGet(type, id) {
8920
9080
  return;
8921
9081
  }
8922
9082
  async function cmdValidate(path) {
8923
- const essencePath = path || join30(process.cwd(), "decantr.essence.json");
9083
+ const essencePath = path || join31(process.cwd(), "decantr.essence.json");
8924
9084
  let raw;
8925
9085
  try {
8926
- raw = readFileSync21(essencePath, "utf-8");
9086
+ raw = readFileSync22(essencePath, "utf-8");
8927
9087
  } catch {
8928
9088
  console.error(error2(`Could not read ${essencePath}`));
8929
9089
  process.exitCode = 1;
@@ -8938,14 +9098,14 @@ async function cmdValidate(path) {
8938
9098
  return;
8939
9099
  }
8940
9100
  const detectedVersion = isV48(essence) ? "v4" : "legacy";
8941
- console.log(`${DIM16}Detected essence version: ${detectedVersion}${RESET16}`);
9101
+ console.log(`${DIM17}Detected essence version: ${detectedVersion}${RESET17}`);
8942
9102
  const result = validateEssence2(essence);
8943
9103
  if (result.valid) {
8944
9104
  console.log(success3(`Essence is valid (${detectedVersion}).`));
8945
9105
  } else {
8946
9106
  console.error(error2("Validation failed:"));
8947
9107
  for (const err of result.errors) {
8948
- console.error(` ${RED12}${err}${RESET16}`);
9108
+ console.error(` ${RED13}${err}${RESET17}`);
8949
9109
  }
8950
9110
  process.exitCode = 1;
8951
9111
  return;
@@ -8966,9 +9126,9 @@ async function cmdValidate(path) {
8966
9126
  console.log(heading2("Guard violations:"));
8967
9127
  for (const v of violations) {
8968
9128
  const vr = v;
8969
- console.log(` ${YELLOW12}[${vr.rule}]${RESET16} ${vr.message}`);
9129
+ console.log(` ${YELLOW13}[${vr.rule}]${RESET17} ${vr.message}`);
8970
9130
  if (vr.suggestion) {
8971
- console.log(` ${DIM16}Suggestion: ${vr.suggestion}${RESET16}`);
9131
+ console.log(` ${DIM17}Suggestion: ${vr.suggestion}${RESET17}`);
8972
9132
  }
8973
9133
  }
8974
9134
  const hasError = violations.some((v) => v.severity === "error");
@@ -8990,7 +9150,7 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
8990
9150
  return;
8991
9151
  }
8992
9152
  const registryClient = new RegistryClient({
8993
- cacheDir: join30(process.cwd(), ".decantr", "cache")
9153
+ cacheDir: join31(process.cwd(), ".decantr", "cache")
8994
9154
  });
8995
9155
  const result = await registryClient.fetchContentList(
8996
9156
  type,
@@ -9067,16 +9227,16 @@ function enableCliTelemetry(projectRoot) {
9067
9227
  optIn(projectRoot);
9068
9228
  console.log(
9069
9229
  `
9070
- ${CYAN9}Telemetry enabled.${RESET16} Decantr will send privacy-filtered CLI product telemetry for this project.`
9230
+ ${CYAN9}Telemetry enabled.${RESET17} Decantr will send privacy-filtered CLI product telemetry for this project.`
9071
9231
  );
9072
- console.log(`${DIM16}Set "telemetry": false in .decantr/project.json to opt out.${RESET16}`);
9232
+ console.log(`${DIM17}Set "telemetry": false in .decantr/project.json to opt out.${RESET17}`);
9073
9233
  }
9074
9234
  function readCliPackageVersion2() {
9075
- const here = dirname6(fileURLToPath3(import.meta.url));
9076
- const candidates = [join30(here, "..", "package.json"), join30(here, "..", "..", "package.json")];
9235
+ const here = dirname7(fileURLToPath3(import.meta.url));
9236
+ const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
9077
9237
  for (const candidate of candidates) {
9078
9238
  try {
9079
- const pkg = JSON.parse(readFileSync21(candidate, "utf-8"));
9239
+ const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
9080
9240
  if (pkg.version) return pkg.version;
9081
9241
  } catch {
9082
9242
  }
@@ -9087,19 +9247,19 @@ function timestampForFile() {
9087
9247
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
9088
9248
  }
9089
9249
  function backupExistingEssence(projectRoot, label) {
9090
- const essencePath = join30(projectRoot, "decantr.essence.json");
9091
- if (!existsSync28(essencePath)) return null;
9092
- const backupPath = join30(
9250
+ const essencePath = join31(projectRoot, "decantr.essence.json");
9251
+ if (!existsSync29(essencePath)) return null;
9252
+ const backupPath = join31(
9093
9253
  projectRoot,
9094
9254
  `decantr.essence.${label}.${timestampForFile()}.backup.json`
9095
9255
  );
9096
- writeFileSync18(backupPath, readFileSync21(essencePath, "utf-8"), "utf-8");
9256
+ writeFileSync19(backupPath, readFileSync22(essencePath, "utf-8"), "utf-8");
9097
9257
  return backupPath;
9098
9258
  }
9099
9259
  function writeBrownfieldProjectJson(input) {
9100
- const decantrDir = join30(input.projectRoot, ".decantr");
9101
- mkdirSync15(join30(decantrDir, "context"), { recursive: true });
9102
- mkdirSync15(join30(decantrDir, "cache"), { recursive: true });
9260
+ const decantrDir = join31(input.projectRoot, ".decantr");
9261
+ mkdirSync16(join31(decantrDir, "context"), { recursive: true });
9262
+ mkdirSync16(join31(decantrDir, "cache"), { recursive: true });
9103
9263
  const now = (/* @__PURE__ */ new Date()).toISOString();
9104
9264
  const projectJson = {
9105
9265
  detected: {
@@ -9140,7 +9300,7 @@ function writeBrownfieldProjectJson(input) {
9140
9300
  }
9141
9301
  }
9142
9302
  };
9143
- writeFileSync18(join30(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
9303
+ writeFileSync19(join31(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
9144
9304
  }
9145
9305
  async function applyAcceptedBrownfieldProposal(input) {
9146
9306
  const proposal = readBrownfieldProposal(input.projectRoot);
@@ -9156,8 +9316,8 @@ async function applyAcceptedBrownfieldProposal(input) {
9156
9316
  process.exitCode = 1;
9157
9317
  return;
9158
9318
  }
9159
- const essencePath = join30(input.projectRoot, "decantr.essence.json");
9160
- const hasEssence = existsSync28(essencePath);
9319
+ const essencePath = join31(input.projectRoot, "decantr.essence.json");
9320
+ const hasEssence = existsSync29(essencePath);
9161
9321
  let essence;
9162
9322
  let backupPath = null;
9163
9323
  if (input.mode === "accept" && hasEssence) {
@@ -9171,7 +9331,7 @@ async function applyAcceptedBrownfieldProposal(input) {
9171
9331
  return;
9172
9332
  }
9173
9333
  if (input.mode === "merge" && hasEssence) {
9174
- const existing = JSON.parse(readFileSync21(essencePath, "utf-8"));
9334
+ const existing = JSON.parse(readFileSync22(essencePath, "utf-8"));
9175
9335
  if (!isV48(existing)) {
9176
9336
  console.log(
9177
9337
  error2(
@@ -9191,7 +9351,7 @@ async function applyAcceptedBrownfieldProposal(input) {
9191
9351
  error2("Brownfield proposal produced an invalid Decantr essence. No files were changed.")
9192
9352
  );
9193
9353
  for (const validationError of validation.errors) {
9194
- console.log(` ${RED12}${validationError}${RESET16}`);
9354
+ console.log(` ${RED13}${validationError}${RESET17}`);
9195
9355
  }
9196
9356
  process.exitCode = 1;
9197
9357
  return;
@@ -9208,9 +9368,9 @@ async function applyAcceptedBrownfieldProposal(input) {
9208
9368
  assistantBridge: input.assistantBridge,
9209
9369
  mode: input.mode
9210
9370
  });
9211
- writeFileSync18(essencePath, JSON.stringify(essence, null, 2) + "\n", "utf-8");
9371
+ writeFileSync19(essencePath, JSON.stringify(essence, null, 2) + "\n", "utf-8");
9212
9372
  const registryClient = new RegistryClient({
9213
- cacheDir: join30(input.projectRoot, ".decantr", "cache"),
9373
+ cacheDir: join31(input.projectRoot, ".decantr", "cache"),
9214
9374
  offline: true,
9215
9375
  projectRoot: input.projectRoot
9216
9376
  });
@@ -9305,7 +9465,7 @@ async function cmdInit(args) {
9305
9465
  console.log(dim3(" Found .decantr/init-seed.json brownfield guidance."));
9306
9466
  }
9307
9467
  if (detected.existingEssence && !args.existing) {
9308
- console.log(`${YELLOW12}Warning: decantr.essence.json already exists.${RESET16}`);
9468
+ console.log(`${YELLOW13}Warning: decantr.essence.json already exists.${RESET17}`);
9309
9469
  const overwrite = await confirm("Overwrite existing configuration?", false);
9310
9470
  if (!overwrite) {
9311
9471
  console.log(dim3("Cancelled."));
@@ -9389,7 +9549,7 @@ async function cmdInit(args) {
9389
9549
  }
9390
9550
  }
9391
9551
  const registryClient = new RegistryClient({
9392
- cacheDir: join30(projectRoot, ".decantr", "cache"),
9552
+ cacheDir: join31(projectRoot, ".decantr", "cache"),
9393
9553
  apiUrl: args.registry,
9394
9554
  offline: args.offline,
9395
9555
  projectRoot
@@ -9409,7 +9569,7 @@ async function cmdInit(args) {
9409
9569
  } else if (shouldUseRegistry && !apiAvailable) {
9410
9570
  if (!args.blueprint) {
9411
9571
  console.log(`
9412
- ${YELLOW12}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
9572
+ ${YELLOW13}You're offline. Scaffolding minimal Decantr project.${RESET17}`);
9413
9573
  console.log(
9414
9574
  dim3("Run `decantr sync` or `decantr upgrade` when online to pull full registry content.\n")
9415
9575
  );
@@ -9458,7 +9618,7 @@ ${YELLOW12}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
9458
9618
  return;
9459
9619
  }
9460
9620
  console.log(`
9461
- ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9621
+ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET17}`);
9462
9622
  console.log(dim3("Run `decantr upgrade` when online, or visit decantr.ai/registry\n"));
9463
9623
  selectedBlueprint = "default";
9464
9624
  } else if (shouldUseRegistry) {
@@ -9640,7 +9800,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9640
9800
  return;
9641
9801
  }
9642
9802
  console.log(
9643
- `${YELLOW12} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET16}`
9803
+ `${YELLOW13} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET17}`
9644
9804
  );
9645
9805
  }
9646
9806
  } else if (shouldUseRegistry && options.archetype) {
@@ -9655,7 +9815,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9655
9815
  return;
9656
9816
  }
9657
9817
  console.log(
9658
- `${YELLOW12} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET16}`
9818
+ `${YELLOW13} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET17}`
9659
9819
  );
9660
9820
  }
9661
9821
  }
@@ -9672,7 +9832,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9672
9832
  return;
9673
9833
  }
9674
9834
  console.log(
9675
- `${YELLOW12} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET16}`
9835
+ `${YELLOW13} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET17}`
9676
9836
  );
9677
9837
  }
9678
9838
  }
@@ -9721,7 +9881,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9721
9881
  if (appliedRuleFiles.length > 0) {
9722
9882
  console.log(` ${dim3(`Rule bridge applied: ${appliedRuleFiles.join(", ")}`)}`);
9723
9883
  }
9724
- if (!existsSync28(join30(projectRoot, "package.json"))) {
9884
+ if (!existsSync29(join31(projectRoot, "package.json"))) {
9725
9885
  console.log("");
9726
9886
  console.log(
9727
9887
  dim3(` Note: ${cyan3("decantr init")} created Decantr contract/context files only.`)
@@ -9732,7 +9892,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9732
9892
  )
9733
9893
  );
9734
9894
  }
9735
- const hasCompiledPacks = existsSync28(join30(projectRoot, ".decantr", "context", "scaffold-pack.md"));
9895
+ const hasCompiledPacks = existsSync29(join31(projectRoot, ".decantr", "context", "scaffold-pack.md"));
9736
9896
  console.log("");
9737
9897
  console.log(" Next steps:");
9738
9898
  if (hasCompiledPacks) {
@@ -9772,7 +9932,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
9772
9932
  console.log(` ${cyan3("decantr upgrade")} Update to latest patterns`);
9773
9933
  console.log(` ${cyan3("decantr check")} Detect drift issues`);
9774
9934
  console.log(` ${cyan3("decantr migrate --to v4")} Migrate older essence files to v4`);
9775
- const essenceContent = readFileSync21(result.essencePath, "utf-8");
9935
+ const essenceContent = readFileSync22(result.essencePath, "utf-8");
9776
9936
  const essence = JSON.parse(essenceContent);
9777
9937
  const validation = validateEssence2(essence);
9778
9938
  if (!validation.valid) {
@@ -9815,7 +9975,7 @@ Validation warnings: ${validation.errors.join(", ")}`));
9815
9975
  };
9816
9976
  const curatedPrompt = generateCuratedPrompt(promptCtx);
9817
9977
  console.log("");
9818
- console.log(`${BOLD9}Prompt for your AI assistant:${RESET16}`);
9978
+ console.log(`${BOLD10}Prompt for your AI assistant:${RESET17}`);
9819
9979
  console.log(dim3("\u2500".repeat(50)));
9820
9980
  console.log("");
9821
9981
  console.log(curatedPrompt);
@@ -9827,23 +9987,23 @@ Validation warnings: ${validation.errors.join(", ")}`));
9827
9987
  }
9828
9988
  }
9829
9989
  async function cmdStatus(projectRoot = process.cwd()) {
9830
- const essencePath = join30(projectRoot, "decantr.essence.json");
9831
- const projectJsonPath = join30(projectRoot, ".decantr", "project.json");
9990
+ const essencePath = join31(projectRoot, "decantr.essence.json");
9991
+ const projectJsonPath = join31(projectRoot, ".decantr", "project.json");
9832
9992
  console.log(heading2("Decantr Project Status"));
9833
- if (!existsSync28(essencePath)) {
9834
- console.log(`${RED12}No decantr.essence.json found.${RESET16}`);
9993
+ if (!existsSync29(essencePath)) {
9994
+ console.log(`${RED13}No decantr.essence.json found.${RESET17}`);
9835
9995
  console.log(dim3('Run "decantr init" to create one.'));
9836
9996
  return;
9837
9997
  }
9838
9998
  try {
9839
- const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
9999
+ const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
9840
10000
  const validation = validateEssence2(essence);
9841
10001
  const essenceVersion = isV48(essence) ? "v4" : "legacy";
9842
- console.log(`${BOLD9}Essence:${RESET16}`);
10002
+ console.log(`${BOLD10}Essence:${RESET17}`);
9843
10003
  if (validation.valid) {
9844
- console.log(` ${GREEN16}Valid${RESET16} (${essenceVersion})`);
10004
+ console.log(` ${GREEN17}Valid${RESET17} (${essenceVersion})`);
9845
10005
  } else {
9846
- console.log(` ${RED12}Invalid: ${validation.errors.join(", ")}${RESET16}`);
10006
+ console.log(` ${RED13}Invalid: ${validation.errors.join(", ")}${RESET17}`);
9847
10007
  }
9848
10008
  if (isV48(essence)) {
9849
10009
  const v4 = essence;
@@ -9851,7 +10011,7 @@ async function cmdStatus(projectRoot = process.cwd()) {
9851
10011
  const flatPages = sections.flatMap((section) => section.pages ?? []);
9852
10012
  const resolvedShell = sections.find((section) => section.role === "primary")?.shell || sections[0]?.shell || v4.blueprint.shell || "unknown";
9853
10013
  const resolvedFeatures = v4.blueprint.features ?? [];
9854
- console.log(` ${BOLD9}DNA:${RESET16}`);
10014
+ console.log(` ${BOLD10}DNA:${RESET17}`);
9855
10015
  console.log(` Theme: ${v4.dna.theme.id} (${v4.dna.theme.mode})`);
9856
10016
  console.log(
9857
10017
  ` Spacing: ${v4.dna.spacing.density} density, ${v4.dna.spacing.content_gap} gap`
@@ -9863,60 +10023,60 @@ async function cmdStatus(projectRoot = process.cwd()) {
9863
10023
  );
9864
10024
  console.log(` Accessibility: WCAG ${v4.dna.accessibility.wcag_level}`);
9865
10025
  console.log(` Personality: ${v4.dna.personality.join(", ")}`);
9866
- console.log(` ${BOLD9}Blueprint:${RESET16}`);
10026
+ console.log(` ${BOLD10}Blueprint:${RESET17}`);
9867
10027
  console.log(` Shell: ${resolvedShell}`);
9868
10028
  console.log(` Pages: ${flatPages.length}`);
9869
10029
  console.log(` Sections: ${sections.length}`);
9870
10030
  console.log(
9871
10031
  ` Features: ${resolvedFeatures.length > 0 ? resolvedFeatures.join(", ") : "none"}`
9872
10032
  );
9873
- console.log(` ${BOLD9}Meta:${RESET16}`);
10033
+ console.log(` ${BOLD10}Meta:${RESET17}`);
9874
10034
  console.log(` Archetype: ${v4.meta.archetype}`);
9875
10035
  console.log(` Target: ${v4.meta.target}`);
9876
10036
  console.log(
9877
10037
  ` Guard: ${v4.meta.guard.mode} (DNA: ${v4.meta.guard.dna_enforcement}, Blueprint: ${v4.meta.guard.blueprint_enforcement})`
9878
10038
  );
9879
10039
  } else {
9880
- console.log(` ${YELLOW12}Run \`decantr migrate --to v4\` to upgrade this project.${RESET16}`);
10040
+ console.log(` ${YELLOW13}Run \`decantr migrate --to v4\` to upgrade this project.${RESET17}`);
9881
10041
  }
9882
10042
  } catch (e) {
9883
- console.log(` ${RED12}Error reading essence: ${e.message}${RESET16}`);
10043
+ console.log(` ${RED13}Error reading essence: ${e.message}${RESET17}`);
9884
10044
  }
9885
10045
  console.log("");
9886
- console.log(`${BOLD9}Sync Status:${RESET16}`);
9887
- if (existsSync28(projectJsonPath)) {
10046
+ console.log(`${BOLD10}Sync Status:${RESET17}`);
10047
+ if (existsSync29(projectJsonPath)) {
9888
10048
  try {
9889
- const projectJson = JSON.parse(readFileSync21(projectJsonPath, "utf-8"));
10049
+ const projectJson = JSON.parse(readFileSync22(projectJsonPath, "utf-8"));
9890
10050
  const syncStatus = projectJson.sync?.status || "unknown";
9891
10051
  const lastSync = projectJson.sync?.lastSync || "never";
9892
10052
  const source = projectJson.sync?.registrySource || "unknown";
9893
- const statusColor = syncStatus === "synced" ? GREEN16 : YELLOW12;
9894
- console.log(` Status: ${statusColor}${syncStatus}${RESET16}`);
10053
+ const statusColor = syncStatus === "synced" ? GREEN17 : YELLOW13;
10054
+ console.log(` Status: ${statusColor}${syncStatus}${RESET17}`);
9895
10055
  console.log(` Last sync: ${dim3(lastSync)}`);
9896
10056
  console.log(` Source: ${dim3(source)}`);
9897
10057
  } catch {
9898
- console.log(` ${YELLOW12}Could not read project.json${RESET16}`);
10058
+ console.log(` ${YELLOW13}Could not read project.json${RESET17}`);
9899
10059
  }
9900
10060
  } else {
9901
- console.log(` ${YELLOW12}No .decantr/project.json found${RESET16}`);
10061
+ console.log(` ${YELLOW13}No .decantr/project.json found${RESET17}`);
9902
10062
  console.log(dim3(' Run "decantr init" to create project files.'));
9903
10063
  }
9904
10064
  }
9905
10065
  async function cmdSync() {
9906
10066
  const projectRoot = process.cwd();
9907
- const cacheDir = join30(projectRoot, ".decantr", "cache");
10067
+ const cacheDir = join31(projectRoot, ".decantr", "cache");
9908
10068
  console.log(heading2("Syncing registry content..."));
9909
10069
  const result = await syncRegistry(cacheDir);
9910
10070
  if (result.synced.length > 0) {
9911
10071
  console.log(success3("Sync completed successfully."));
9912
10072
  console.log(` Synced: ${result.synced.join(", ")}`);
9913
10073
  if (result.failed.length > 0) {
9914
- console.log(` ${YELLOW12}Failed: ${result.failed.join(", ")}${RESET16}`);
10074
+ console.log(` ${YELLOW13}Failed: ${result.failed.join(", ")}${RESET17}`);
9915
10075
  }
9916
10076
  } else {
9917
- console.log(`${YELLOW12}Could not sync: API unavailable${RESET16}`);
10077
+ console.log(`${YELLOW13}Could not sync: API unavailable${RESET17}`);
9918
10078
  if (result.failed.length > 0) {
9919
- console.log(` ${YELLOW12}Failed: ${result.failed.join(", ")}${RESET16}`);
10079
+ console.log(` ${YELLOW13}Failed: ${result.failed.join(", ")}${RESET17}`);
9920
10080
  }
9921
10081
  }
9922
10082
  }
@@ -9926,15 +10086,15 @@ function printVerificationFindings(findings) {
9926
10086
  return;
9927
10087
  }
9928
10088
  for (const finding of findings) {
9929
- const color = finding.severity === "error" ? RED12 : finding.severity === "warn" ? YELLOW12 : CYAN9;
10089
+ const color = finding.severity === "error" ? RED13 : finding.severity === "warn" ? YELLOW13 : CYAN9;
9930
10090
  console.log(
9931
- ` ${color}[${finding.severity.toUpperCase()}]${RESET16} ${finding.category}: ${finding.message}`
10091
+ ` ${color}[${finding.severity.toUpperCase()}]${RESET17} ${finding.category}: ${finding.message}`
9932
10092
  );
9933
10093
  for (const evidence of finding.evidence) {
9934
- console.log(` ${DIM16}${evidence}${RESET16}`);
10094
+ console.log(` ${DIM17}${evidence}${RESET17}`);
9935
10095
  }
9936
10096
  if (finding.suggestedFix) {
9937
- console.log(` ${DIM16}Fix: ${finding.suggestedFix}${RESET16}`);
10097
+ console.log(` ${DIM17}Fix: ${finding.suggestedFix}${RESET17}`);
9938
10098
  }
9939
10099
  }
9940
10100
  }
@@ -9942,10 +10102,10 @@ function printProjectAuditReport(report) {
9942
10102
  if (report.valid) {
9943
10103
  console.log(success3("Project contract is valid."));
9944
10104
  } else {
9945
- console.log(`${RED12}Project audit found blocking issues.${RESET16}`);
10105
+ console.log(`${RED13}Project audit found blocking issues.${RESET17}`);
9946
10106
  }
9947
10107
  console.log("");
9948
- console.log(`${BOLD9}Summary:${RESET16}`);
10108
+ console.log(`${BOLD10}Summary:${RESET17}`);
9949
10109
  console.log(` Essence version: ${report.summary.essenceVersion ?? "missing"}`);
9950
10110
  console.log(` Pages defined: ${report.summary.pageCount}`);
9951
10111
  console.log(` Pack manifest: ${report.summary.packManifestPresent ? "present" : "missing"}`);
@@ -9974,23 +10134,23 @@ function printProjectAuditReport(report) {
9974
10134
  ` Findings: ${report.summary.errorCount} error(s), ${report.summary.warnCount} warn(s), ${report.summary.infoCount} info`
9975
10135
  );
9976
10136
  console.log("");
9977
- console.log(`${BOLD9}Findings:${RESET16}`);
10137
+ console.log(`${BOLD10}Findings:${RESET17}`);
9978
10138
  printVerificationFindings(report.findings);
9979
10139
  }
9980
10140
  function printFileCritiqueReport(report) {
9981
10141
  console.log(success3(`Critiqued ${report.file}`));
9982
10142
  console.log("");
9983
- console.log(`${BOLD9}Summary:${RESET16}`);
10143
+ console.log(`${BOLD10}Summary:${RESET17}`);
9984
10144
  console.log(` Overall score: ${report.overall}/5`);
9985
10145
  console.log(` Focus areas: ${report.focusAreas.join(", ")}`);
9986
10146
  console.log(` Review pack: ${report.reviewPack ? "present" : "missing"}`);
9987
10147
  console.log("");
9988
- console.log(`${BOLD9}Scores:${RESET16}`);
10148
+ console.log(`${BOLD10}Scores:${RESET17}`);
9989
10149
  for (const score of report.scores) {
9990
10150
  console.log(` ${cyan3(score.category.padEnd(20))} ${score.score}/5 ${dim3(score.details)}`);
9991
10151
  }
9992
10152
  console.log("");
9993
- console.log(`${BOLD9}Findings:${RESET16}`);
10153
+ console.log(`${BOLD10}Findings:${RESET17}`);
9994
10154
  printVerificationFindings(report.findings);
9995
10155
  }
9996
10156
  async function cmdAudit(filePath) {
@@ -10031,7 +10191,7 @@ async function cmdAudit(filePath) {
10031
10191
  console.log(dim3("Project audit completed with advisory findings."));
10032
10192
  }
10033
10193
  } catch (e) {
10034
- console.log(`${RED12}Error: ${e.message}${RESET16}`);
10194
+ console.log(`${RED13}Error: ${e.message}${RESET17}`);
10035
10195
  process.exitCode = 1;
10036
10196
  }
10037
10197
  }
@@ -10039,9 +10199,9 @@ async function cmdTheme(args, projectRoot = process.cwd()) {
10039
10199
  const subcommand = args[0];
10040
10200
  if (!subcommand || subcommand === "help") {
10041
10201
  console.log(`
10042
- ${BOLD9}decantr theme${RESET16} \u2014 Manage custom themes
10202
+ ${BOLD10}decantr theme${RESET17} \u2014 Manage custom themes
10043
10203
 
10044
- ${BOLD9}Commands:${RESET16}
10204
+ ${BOLD10}Commands:${RESET17}
10045
10205
  ${cyan3("create")} <name> Create a new custom theme
10046
10206
  ${cyan3("create")} <name> --guided Interactive theme creation
10047
10207
  ${cyan3("list")} List custom themes
@@ -10049,7 +10209,7 @@ ${BOLD9}Commands:${RESET16}
10049
10209
  ${cyan3("delete")} <name> Delete a custom theme
10050
10210
  ${cyan3("import")} <path> Import theme from JSON file
10051
10211
 
10052
- ${BOLD9}Examples:${RESET16}
10212
+ ${BOLD10}Examples:${RESET17}
10053
10213
  decantr theme create mytheme
10054
10214
  decantr theme list
10055
10215
  decantr theme validate mytheme
@@ -10098,21 +10258,21 @@ ${BOLD9}Examples:${RESET16}
10098
10258
  process.exitCode = 1;
10099
10259
  return;
10100
10260
  }
10101
- const themePath = join30(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
10102
- if (!existsSync28(themePath)) {
10261
+ const themePath = join31(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
10262
+ if (!existsSync29(themePath)) {
10103
10263
  console.error(error2(`Theme "${name}" not found at ${themePath}`));
10104
10264
  process.exitCode = 1;
10105
10265
  return;
10106
10266
  }
10107
10267
  try {
10108
- const theme = JSON.parse(readFileSync21(themePath, "utf-8"));
10268
+ const theme = JSON.parse(readFileSync22(themePath, "utf-8"));
10109
10269
  const result = validateCustomTheme(theme);
10110
10270
  if (result.valid) {
10111
10271
  console.log(success3(`Custom theme "${name}" is valid`));
10112
10272
  } else {
10113
10273
  console.error(error2("Validation failed:"));
10114
10274
  for (const err of result.errors) {
10115
- console.error(` ${RED12}${err}${RESET16}`);
10275
+ console.error(` ${RED13}${err}${RESET17}`);
10116
10276
  }
10117
10277
  process.exitCode = 1;
10118
10278
  }
@@ -10152,7 +10312,7 @@ ${BOLD9}Examples:${RESET16}
10152
10312
  } else {
10153
10313
  console.error(error2("Import failed:"));
10154
10314
  for (const err of result.errors || []) {
10155
- console.error(` ${RED12}${err}${RESET16}`);
10315
+ console.error(` ${RED13}${err}${RESET17}`);
10156
10316
  }
10157
10317
  process.exitCode = 1;
10158
10318
  }
@@ -10237,7 +10397,7 @@ function withProject(command, projectArg) {
10237
10397
  return projectArg ? `${command} --project ${projectArg}` : command;
10238
10398
  }
10239
10399
  function displayProjectPath(workspaceInfo, projectPath) {
10240
- const absolutePath = join30(workspaceInfo.appRoot, projectPath);
10400
+ const absolutePath = join31(workspaceInfo.appRoot, projectPath);
10241
10401
  const relativePath = relative6(workspaceInfo.cwd, absolutePath).replace(/\\/g, "/");
10242
10402
  if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
10243
10403
  return relativePath;
@@ -10245,7 +10405,7 @@ function displayProjectPath(workspaceInfo, projectPath) {
10245
10405
  return absolutePath;
10246
10406
  }
10247
10407
  function projectRelativeGraphPath(projectRoot, filePath) {
10248
- const relativePath = relative6(projectRoot, isAbsolute3(filePath) ? filePath : resolve4(filePath));
10408
+ const relativePath = relative6(projectRoot, isAbsolute3(filePath) ? filePath : resolve5(filePath));
10249
10409
  if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
10250
10410
  return relativePath.replace(/\\/g, "/");
10251
10411
  }
@@ -10261,7 +10421,7 @@ function graphSourceNodeIdForTaskFile(projectRoot, snapshot, filePath) {
10261
10421
  candidates.add(trimmed.replace(/\\/g, "/").replace(/^\.\//, ""));
10262
10422
  const cwdRelative = projectRelativeGraphPath(projectRoot, trimmed);
10263
10423
  if (cwdRelative) candidates.add(cwdRelative);
10264
- const projectRelative = projectRelativeGraphPath(projectRoot, join30(projectRoot, trimmed));
10424
+ const projectRelative = projectRelativeGraphPath(projectRoot, join31(projectRoot, trimmed));
10265
10425
  if (projectRelative) candidates.add(projectRelative);
10266
10426
  for (const candidate of candidates) {
10267
10427
  const nodeId = `src:${candidate}`;
@@ -10315,7 +10475,7 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
10315
10475
  const noun = commandName === "adopt" ? "Brownfield adoption" : `decantr ${commandName}`;
10316
10476
  console.log(error2(`${noun} needs an app path.`));
10317
10477
  console.log("");
10318
- console.log(`${BOLD9}This looks like a monorepo.${RESET16}`);
10478
+ console.log(`${BOLD10}This looks like a monorepo.${RESET17}`);
10319
10479
  console.log("Install Decantr at the workspace root, then attach it to one app with --project.");
10320
10480
  console.log("");
10321
10481
  console.log("App candidates:");
@@ -10335,11 +10495,11 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
10335
10495
  function printMonorepoSetupGuidance(workspaceInfo) {
10336
10496
  const candidate = firstWorkspaceCandidate(workspaceInfo);
10337
10497
  const attachedProjects = workspaceInfo.appCandidates.filter(
10338
- (appCandidate) => existsSync28(join30(workspaceInfo.workspaceRoot, appCandidate, "decantr.essence.json"))
10498
+ (appCandidate) => existsSync29(join31(workspaceInfo.workspaceRoot, appCandidate, "decantr.essence.json"))
10339
10499
  );
10340
10500
  const firstAttached = attachedProjects[0];
10341
10501
  console.log(heading2("Decantr Setup"));
10342
- console.log(`${BOLD9}This looks like a monorepo.${RESET16}`);
10502
+ console.log(`${BOLD10}This looks like a monorepo.${RESET17}`);
10343
10503
  console.log(` Workspace root: ${workspaceInfo.workspaceRoot}`);
10344
10504
  console.log("");
10345
10505
  if (firstAttached) {
@@ -10350,7 +10510,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
10350
10510
  console.log(` ${project}`);
10351
10511
  }
10352
10512
  console.log("");
10353
- console.log(`${BOLD9}Next:${RESET16}`);
10513
+ console.log(`${BOLD10}Next:${RESET17}`);
10354
10514
  console.log(
10355
10515
  ` ${cyan3(`decantr doctor --project ${firstAttached}`)} Explain current state and next command`
10356
10516
  );
@@ -10384,7 +10544,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
10384
10544
  console.log(` ${appCandidate}`);
10385
10545
  }
10386
10546
  console.log("");
10387
- console.log(`${BOLD9}Start here:${RESET16}`);
10547
+ console.log(`${BOLD10}Start here:${RESET17}`);
10388
10548
  console.log(
10389
10549
  ` ${cyan3("decantr workspace list")} Show attached projects and app candidates`
10390
10550
  );
@@ -10395,7 +10555,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
10395
10555
  ` ${cyan3(`decantr codify --from-audit --style-bridge --project ${candidate}`)} Propose project-owned UI law and style bridge`
10396
10556
  );
10397
10557
  console.log("");
10398
- console.log(`${BOLD9}Optional visual evidence:${RESET16}`);
10558
+ console.log(`${BOLD10}Optional visual evidence:${RESET17}`);
10399
10559
  console.log(
10400
10560
  ` ${cyan3(`decantr verify --project ${candidate} --base-url http://localhost:3000 --evidence`)}`
10401
10561
  );
@@ -10403,7 +10563,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
10403
10563
  function resolveWorkflowProject(flags, commandName = "command", options = {}) {
10404
10564
  const projectArg = flagString(flags, "project");
10405
10565
  const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
10406
- if (projectArg && options.requireExisting !== false && !existsSync28(workspaceInfo.appRoot)) {
10566
+ if (projectArg && options.requireExisting !== false && !existsSync29(workspaceInfo.appRoot)) {
10407
10567
  printProjectNotFound(projectArg, commandName);
10408
10568
  process.exitCode = 1;
10409
10569
  return null;
@@ -10448,22 +10608,34 @@ function printWorkflowPlan(title, steps) {
10448
10608
  }
10449
10609
  console.log("");
10450
10610
  }
10611
+ function studioCommandForProject(projectArg) {
10612
+ return projectArg ? `cd ${projectArg} && decantr studio` : "decantr studio";
10613
+ }
10614
+ function formatWhichCommandFirst(projectArg) {
10615
+ return [
10616
+ `${BOLD10}Which command first?${RESET17}`,
10617
+ ` ${cyan3(withProject("decantr scan", projectArg))} Existing app, read-only preview`,
10618
+ ` ${cyan3(withProject("decantr adopt --yes", projectArg))} Existing app, attach Decantr`,
10619
+ ` ${cyan3("decantr new my-app --blueprint=<slug>")} New runnable app`,
10620
+ ` ${cyan3(withProject("decantr init --existing", projectArg))} Advanced attach primitive`
10621
+ ].join("\n");
10622
+ }
10451
10623
  function scanSeverityColor(finding) {
10452
10624
  if (finding.severity === "success") return success3("ok");
10453
10625
  if (finding.severity === "error") return error2("error");
10454
- if (finding.severity === "warn") return `${YELLOW12}warn${RESET16}`;
10626
+ if (finding.severity === "warn") return `${YELLOW13}warn${RESET17}`;
10455
10627
  return cyan3("info");
10456
10628
  }
10457
10629
  function formatScanApplicability(status) {
10458
10630
  if (status === "strong_fit") return success3("strong fit");
10459
- if (status === "partial_fit") return `${YELLOW12}partial fit${RESET16}`;
10631
+ if (status === "partial_fit") return `${YELLOW13}partial fit${RESET17}`;
10460
10632
  if (status === "not_applicable") return dim3("not applicable");
10461
10633
  return dim3("unknown");
10462
10634
  }
10463
10635
  function formatScanGraphPreviewStatus(status) {
10464
10636
  if (status === "current") return success3("current");
10465
- if (status === "stale") return `${YELLOW12}stale or missing${RESET16}`;
10466
- if (status === "needs_migration") return `${YELLOW12}needs migration${RESET16}`;
10637
+ if (status === "stale") return `${YELLOW13}stale or missing${RESET17}`;
10638
+ if (status === "needs_migration") return `${YELLOW13}needs migration${RESET17}`;
10467
10639
  if (status === "not_attached") return dim3("not attached");
10468
10640
  return dim3("unavailable");
10469
10641
  }
@@ -10545,7 +10717,7 @@ function buildScanGraphPreview(workspaceInfo, projectArg) {
10545
10717
  }
10546
10718
  function printScanGraphPreview(preview) {
10547
10719
  if (!preview) return;
10548
- console.log(`${BOLD9}Typed Contract Graph${RESET16}`);
10720
+ console.log(`${BOLD10}Typed Contract Graph${RESET17}`);
10549
10721
  console.log(` Status: ${formatScanGraphPreviewStatus(preview.status)}`);
10550
10722
  console.log(` Read-only: ${preview.readOnly ? "yes" : "no"}`);
10551
10723
  if (preview.snapshot && preview.capsule) {
@@ -10583,11 +10755,11 @@ function printScanGraphPreview(preview) {
10583
10755
  }
10584
10756
  console.log("");
10585
10757
  }
10586
- function printScanReport(report) {
10758
+ function printScanReport(report, projectArg) {
10587
10759
  console.log(heading2("Decantr Scan"));
10588
10760
  console.log(dim3("Read-only Brownfield reconnaissance. No files were written."));
10589
10761
  console.log("");
10590
- console.log(`${BOLD9}Verdict${RESET16}`);
10762
+ console.log(`${BOLD10}Verdict${RESET17}`);
10591
10763
  console.log(
10592
10764
  ` ${formatScanApplicability(report.applicability.status)} ${report.applicability.label}`
10593
10765
  );
@@ -10598,7 +10770,7 @@ function printScanReport(report) {
10598
10770
  console.log(` ${dim3("-")} ${reason}`);
10599
10771
  }
10600
10772
  console.log("");
10601
- console.log(`${BOLD9}Project${RESET16}`);
10773
+ console.log(`${BOLD10}Project${RESET17}`);
10602
10774
  console.log(
10603
10775
  ` Framework: ${cyan3(report.project.framework)}${report.project.frameworkVersion ? ` ${report.project.frameworkVersion}` : ""}`
10604
10776
  );
@@ -10608,7 +10780,7 @@ function printScanReport(report) {
10608
10780
  console.log(` Decantr: ${report.project.hasDecantr ? "present" : "not attached"}`);
10609
10781
  console.log("");
10610
10782
  printScanGraphPreview(report.graphPreview);
10611
- console.log(`${BOLD9}Routes And Styling${RESET16}`);
10783
+ console.log(`${BOLD10}Routes And Styling${RESET17}`);
10612
10784
  console.log(` Routes: ${report.routes.count} (${report.routes.strategy})`);
10613
10785
  for (const route of report.routes.items.slice(0, 8)) {
10614
10786
  console.log(` ${cyan3(route.path.padEnd(18))} ${dim3(route.file)}`);
@@ -10624,7 +10796,7 @@ function printScanReport(report) {
10624
10796
  console.log(` Dark mode: ${report.styling.darkMode ? "yes" : "no"}`);
10625
10797
  console.log("");
10626
10798
  if (report.staticHosting.githubPagesLikely || report.pagesProbe) {
10627
- console.log(`${BOLD9}Published Surface${RESET16}`);
10799
+ console.log(`${BOLD10}Published Surface${RESET17}`);
10628
10800
  console.log(
10629
10801
  ` GitHub Pages: ${report.staticHosting.githubPagesLikely ? "likely" : "not detected"}`
10630
10802
  );
@@ -10633,7 +10805,7 @@ function printScanReport(report) {
10633
10805
  }
10634
10806
  if (report.pagesProbe?.checked) {
10635
10807
  console.log(
10636
- ` HTTP probe: ${report.pagesProbe.reachable ? success3("reachable") : `${YELLOW12}unreachable${RESET16}`} ${report.pagesProbe.status ?? ""}`
10808
+ ` HTTP probe: ${report.pagesProbe.reachable ? success3("reachable") : `${YELLOW13}unreachable${RESET17}`} ${report.pagesProbe.status ?? ""}`
10637
10809
  );
10638
10810
  if (report.pagesProbe.title) console.log(` Title: ${report.pagesProbe.title}`);
10639
10811
  }
@@ -10642,19 +10814,32 @@ function printScanReport(report) {
10642
10814
  }
10643
10815
  console.log("");
10644
10816
  }
10645
- console.log(`${BOLD9}Findings${RESET16}`);
10817
+ console.log(`${BOLD10}Findings${RESET17}`);
10646
10818
  for (const finding of report.findings.slice(0, 8)) {
10647
10819
  console.log(` [${scanSeverityColor(finding)}] ${finding.title}`);
10648
10820
  console.log(` ${finding.message}`);
10649
10821
  if (finding.recommendation) console.log(` ${dim3(finding.recommendation)}`);
10650
10822
  }
10651
10823
  console.log("");
10652
- console.log(`${BOLD9}Next Commands${RESET16}`);
10824
+ console.log(`${BOLD10}Next Commands${RESET17}`);
10653
10825
  for (const command of report.recommendedCommands) {
10654
10826
  console.log(` ${cyan3(command)}`);
10655
10827
  }
10656
10828
  console.log("");
10657
10829
  console.log(dim3(report.privacy.notes[0] ?? "Scan completed without writing files."));
10830
+ console.log(
10831
+ dim3(
10832
+ "This scan was read-only: no Decantr files, dependencies, scripts, uploads, or reports were created."
10833
+ )
10834
+ );
10835
+ if (report.applicability.status !== "not_applicable") {
10836
+ console.log(
10837
+ `When ready to attach Decantr, run ${cyan3(withProject("decantr adopt --yes", projectArg))}.`
10838
+ );
10839
+ console.log(
10840
+ `After adoption, inspect what Decantr found with ${cyan3(studioCommandForProject(projectArg))}.`
10841
+ );
10842
+ }
10658
10843
  }
10659
10844
  async function cmdScanWorkflow(args) {
10660
10845
  const { flags } = parseLooseArgs(args);
@@ -10673,7 +10858,7 @@ async function cmdScanWorkflow(args) {
10673
10858
  console.log(JSON.stringify(reportWithGraph, null, 2));
10674
10859
  return;
10675
10860
  }
10676
- printScanReport(reportWithGraph);
10861
+ printScanReport(reportWithGraph, projectArg);
10677
10862
  }
10678
10863
  async function cmdSetupWorkflow(args) {
10679
10864
  const { flags } = parseLooseArgs(args);
@@ -10695,11 +10880,11 @@ async function cmdSetupWorkflow(args) {
10695
10880
  console.log(` Detected: ${formatDetection(detected)}`);
10696
10881
  console.log("");
10697
10882
  if (detected.existingEssence) {
10698
- const hasLocalPatterns = existsSync28(localPatternsPath(workspaceInfo.appRoot));
10699
- const hasLocalRules = existsSync28(localRulesPath(workspaceInfo.appRoot));
10700
- const hasStyleBridge = existsSync28(styleBridgePath(workspaceInfo.appRoot));
10883
+ const hasLocalPatterns = existsSync29(localPatternsPath(workspaceInfo.appRoot));
10884
+ const hasLocalRules = existsSync29(localRulesPath(workspaceInfo.appRoot));
10885
+ const hasStyleBridge = existsSync29(styleBridgePath(workspaceInfo.appRoot));
10701
10886
  const verifyCommand = hasLocalPatterns || hasLocalRules ? "decantr verify --brownfield --local-patterns" : "decantr verify --brownfield";
10702
- console.log(`${BOLD9}Recommended path:${RESET16} maintain an attached Decantr project`);
10887
+ console.log(`${BOLD10}Recommended path:${RESET17} maintain an attached Decantr project`);
10703
10888
  console.log(
10704
10889
  ` ${cyan3(withProject("decantr doctor", projectArg))} Explain current state and next command`
10705
10890
  );
@@ -10721,7 +10906,7 @@ async function cmdSetupWorkflow(args) {
10721
10906
  return;
10722
10907
  }
10723
10908
  if (hasFootprint) {
10724
- console.log(`${BOLD9}Recommended path:${RESET16} brownfield adoption`);
10909
+ console.log(`${BOLD10}Recommended path:${RESET17} brownfield adoption`);
10725
10910
  console.log(
10726
10911
  ` ${cyan3(withProject("decantr adopt --yes", projectArg))} Analyze, attach, and verify`
10727
10912
  );
@@ -10729,13 +10914,13 @@ async function cmdSetupWorkflow(args) {
10729
10914
  ` ${cyan3(withProject("decantr codify --from-audit --style-bridge", projectArg))} Propose local UI law and style bridge`
10730
10915
  );
10731
10916
  console.log("");
10732
- console.log(`${BOLD9}Optional visual evidence after the app is running:${RESET16}`);
10917
+ console.log(`${BOLD10}Optional visual evidence after the app is running:${RESET17}`);
10733
10918
  console.log(
10734
10919
  ` ${cyan3(withProject("decantr verify --base-url http://localhost:3000 --evidence", projectArg))}`
10735
10920
  );
10736
10921
  return;
10737
10922
  }
10738
- console.log(`${BOLD9}Recommended path:${RESET16} greenfield start`);
10923
+ console.log(`${BOLD10}Recommended path:${RESET17} greenfield start`);
10739
10924
  console.log(` ${cyan3("decantr new my-app --blueprint=<slug>")}`);
10740
10925
  console.log(` ${cyan3("decantr init --workflow=greenfield --adoption=contract-only")}`);
10741
10926
  }
@@ -10785,7 +10970,7 @@ async function cmdAdoptWorkflow(args) {
10785
10970
  const hydratePacks = flagBoolean(flags, "packs", true) && !flagBoolean(flags, "skip-packs") && !flagBoolean(flags, "offline") && process.env.DECANTR_OFFLINE !== "true";
10786
10971
  const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
10787
10972
  const assistantBridge = flagString(flags, "assistant-bridge");
10788
- const hasEssence = existsSync28(join30(projectRoot, "decantr.essence.json"));
10973
+ const hasEssence = existsSync29(join31(projectRoot, "decantr.essence.json"));
10789
10974
  const proposalFlag = flagBoolean(flags, "replace-essence") ? "--replace-essence" : flagBoolean(flags, "merge-proposal") || hasEssence ? "--merge-proposal" : "--accept-proposal";
10790
10975
  const steps = [
10791
10976
  "analyze current app and write .decantr/brownfield intelligence",
@@ -10834,7 +11019,7 @@ async function cmdAdoptWorkflow(args) {
10834
11019
  if (hydratePacks) {
10835
11020
  try {
10836
11021
  const { bundle, contextDir } = await compileHostedExecutionPackBundle(
10837
- join30(projectRoot, "decantr.essence.json")
11022
+ join31(projectRoot, "decantr.essence.json")
10838
11023
  );
10839
11024
  const written = writeHostedExecutionPackContextArtifacts(
10840
11025
  contextDir,
@@ -10846,7 +11031,7 @@ async function cmdAdoptWorkflow(args) {
10846
11031
  )
10847
11032
  );
10848
11033
  } catch (e) {
10849
- console.log(`${YELLOW12}Pack hydration skipped:${RESET16} ${e.message}`);
11034
+ console.log(`${YELLOW13}Pack hydration skipped:${RESET17} ${e.message}`);
10850
11035
  console.log(
10851
11036
  dim3(
10852
11037
  `Run ${compilePacksCommandForProject(projectArg)} after adoption if you want hosted page/review packs.`
@@ -10859,7 +11044,7 @@ async function cmdAdoptWorkflow(args) {
10859
11044
  await cmdGraph(projectRoot, { displayRoot: process.cwd() });
10860
11045
  if (process.exitCode && process.exitCode !== 0) return;
10861
11046
  if (runVerify) {
10862
- const { cmdHealth } = await import("./health-G7HQCDXX.js");
11047
+ const { cmdHealth } = await import("./health-RKUKPG72.js");
10863
11048
  await cmdHealth(projectRoot, {
10864
11049
  browser: runBrowser,
10865
11050
  browserBaseUrl: baseUrl,
@@ -10875,7 +11060,7 @@ async function cmdAdoptWorkflow(args) {
10875
11060
  await cmdCi(ciArgs, process.cwd());
10876
11061
  }
10877
11062
  console.log("");
10878
- console.log(`${BOLD9}Brownfield operating loop:${RESET16}`);
11063
+ console.log(`${BOLD10}Brownfield operating loop:${RESET17}`);
10879
11064
  console.log(
10880
11065
  ` ${cyan3(withProject("decantr codify --from-audit --style-bridge", projectArg))} Propose project-owned UI law and style bridge`
10881
11066
  );
@@ -10888,6 +11073,9 @@ async function cmdAdoptWorkflow(args) {
10888
11073
  console.log(
10889
11074
  ` ${cyan3(withProject("decantr verify --brownfield --local-patterns", projectArg))} Check contract, health, and local law after edits`
10890
11075
  );
11076
+ console.log(
11077
+ ` ${cyan3(studioCommandForProject(projectArg))} Inspect routes, findings, and attention areas visually`
11078
+ );
10891
11079
  console.log(
10892
11080
  ` ${cyan3(withProject("decantr verify --since-baseline", projectArg))} Compare future work against this baseline`
10893
11081
  );
@@ -10930,7 +11118,7 @@ async function cmdVerifyWorkflow(args) {
10930
11118
  return;
10931
11119
  }
10932
11120
  if (workspaceMode) {
10933
- const { cmdWorkspace } = await import("./workspace-3AJEXXUL.js");
11121
+ const { cmdWorkspace } = await import("./workspace-RJCFPVBL.js");
10934
11122
  await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
10935
11123
  return;
10936
11124
  }
@@ -10963,7 +11151,7 @@ async function cmdVerifyWorkflow(args) {
10963
11151
  }
10964
11152
  let guardExitCode;
10965
11153
  if (brownfield) {
10966
- const { cmdHeal, collectCheckIssues } = await import("./heal-OKZ5QZN7.js");
11154
+ const { cmdHeal, collectCheckIssues } = await import("./heal-YXWB6LTI.js");
10967
11155
  if (quietOutput) {
10968
11156
  const result = collectCheckIssues(workspaceInfo.appRoot, { brownfield: true });
10969
11157
  guardExitCode = result.issues.some((issue) => issue.type === "error") ? 1 : void 0;
@@ -10973,7 +11161,7 @@ async function cmdVerifyWorkflow(args) {
10973
11161
  process.exitCode = void 0;
10974
11162
  }
10975
11163
  }
10976
- const { cmdHealth, parseHealthArgs } = await import("./health-G7HQCDXX.js");
11164
+ const { cmdHealth, parseHealthArgs } = await import("./health-RKUKPG72.js");
10977
11165
  await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
10978
11166
  if (localPatterns) {
10979
11167
  const validation = validateLocalLaw(workspaceInfo.appRoot);
@@ -10981,7 +11169,7 @@ async function cmdVerifyWorkflow(args) {
10981
11169
  if (!quietOutput) {
10982
11170
  console.log("");
10983
11171
  console.log(
10984
- `${YELLOW12}Local pattern pack missing.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))}, review the proposal, then run ${cyan3(withProject("decantr codify --accept", projectArg))}.`
11172
+ `${YELLOW13}Local pattern pack missing.${RESET17} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))}, review the proposal, then run ${cyan3(withProject("decantr codify --accept", projectArg))}.`
10985
11173
  );
10986
11174
  }
10987
11175
  process.exitCode = process.exitCode || 1;
@@ -10992,23 +11180,23 @@ async function cmdVerifyWorkflow(args) {
10992
11180
  const blockingWarnings = failOn === "warn" ? validation.warnings : [];
10993
11181
  if (!quietOutput) {
10994
11182
  console.log("");
10995
- console.log(`${GREEN16}Local pattern pack found:${RESET16} ${validation.patternsPath}`);
11183
+ console.log(`${GREEN17}Local pattern pack found:${RESET17} ${validation.patternsPath}`);
10996
11184
  if (validation.ruleManifestPresent) {
10997
- console.log(`${GREEN16}Local rule manifest found:${RESET16} ${validation.rulesPath}`);
11185
+ console.log(`${GREEN17}Local rule manifest found:${RESET17} ${validation.rulesPath}`);
10998
11186
  console.log(
10999
- `${DIM16}Enforcement: accepted .decantr/rules.json is the Decantr-scanned layer; --fail-on controls whether findings block.${RESET16}`
11187
+ `${DIM17}Enforcement: accepted .decantr/rules.json is the Decantr-scanned layer; --fail-on controls whether findings block.${RESET17}`
11000
11188
  );
11001
11189
  } else {
11002
11190
  console.log(
11003
- `${YELLOW12}Local rule manifest missing.${RESET16} Run ${cyan3("decantr codify --from-audit")} to propose .decantr/rules.json.`
11191
+ `${YELLOW13}Local rule manifest missing.${RESET17} Run ${cyan3("decantr codify --from-audit")} to propose .decantr/rules.json.`
11004
11192
  );
11005
11193
  }
11006
11194
  for (const warning of validation.warnings.slice(0, 8)) {
11007
- console.log(`${YELLOW12}warn${RESET16} ${warning}`);
11195
+ console.log(`${YELLOW13}warn${RESET17} ${warning}`);
11008
11196
  }
11009
11197
  if (validation.findings.length > 0) {
11010
11198
  console.log("");
11011
- console.log(`${BOLD9}Local law findings:${RESET16}`);
11199
+ console.log(`${BOLD10}Local law findings:${RESET17}`);
11012
11200
  for (const finding of validation.findings.slice(0, 20)) {
11013
11201
  console.log(
11014
11202
  ` ${finding.severity.toUpperCase()} ${finding.ruleId} ${finding.file}:${finding.line}:${finding.column} ${finding.message}`
@@ -11018,7 +11206,7 @@ async function cmdVerifyWorkflow(args) {
11018
11206
  console.log(dim3(` ...${validation.findings.length - 20} more finding(s)`));
11019
11207
  }
11020
11208
  } else if (validation.ruleManifestPresent) {
11021
- console.log(`${GREEN16}Local rule checks passed.${RESET16}`);
11209
+ console.log(`${GREEN17}Local rule checks passed.${RESET17}`);
11022
11210
  }
11023
11211
  }
11024
11212
  if (blockingFindings.length > 0 || blockingWarnings.length > 0) {
@@ -11029,12 +11217,12 @@ async function cmdVerifyWorkflow(args) {
11029
11217
  const styleBridge = createStyleBridgeTaskSummary(workspaceInfo.appRoot);
11030
11218
  if (!quietOutput && styleBridge.path) {
11031
11219
  console.log("");
11032
- console.log(`${GREEN16}Style bridge found:${RESET16} ${styleBridge.path}`);
11220
+ console.log(`${GREEN17}Style bridge found:${RESET17} ${styleBridge.path}`);
11033
11221
  console.log(
11034
- `${DIM16}${styleBridge.mappingCount} mapping(s), ${styleBridge.stylingApproach ?? "unknown"} styling${styleBridge.themeModes.length > 0 ? `, themes: ${styleBridge.themeModes.join(", ")}` : ""}${RESET16}`
11222
+ `${DIM17}${styleBridge.mappingCount} mapping(s), ${styleBridge.stylingApproach ?? "unknown"} styling${styleBridge.themeModes.length > 0 ? `, themes: ${styleBridge.themeModes.join(", ")}` : ""}${RESET17}`
11035
11223
  );
11036
11224
  console.log(
11037
- `${DIM16}Enforcement: advisory style-intent mapping; pair with accepted local rules, lint, tests, or visual regression when it should block.${RESET16}`
11225
+ `${DIM17}Enforcement: advisory style-intent mapping; pair with accepted local rules, lint, tests, or visual regression when it should block.${RESET17}`
11038
11226
  );
11039
11227
  }
11040
11228
  if (guardExitCode && guardExitCode !== 0 && (!process.exitCode || process.exitCode === 0)) {
@@ -11042,9 +11230,9 @@ async function cmdVerifyWorkflow(args) {
11042
11230
  }
11043
11231
  }
11044
11232
  function readJsonIfPresent(path) {
11045
- if (!existsSync28(path)) return null;
11233
+ if (!existsSync29(path)) return null;
11046
11234
  try {
11047
- return JSON.parse(readFileSync21(path, "utf-8"));
11235
+ return JSON.parse(readFileSync22(path, "utf-8"));
11048
11236
  } catch {
11049
11237
  return null;
11050
11238
  }
@@ -11196,7 +11384,7 @@ async function cmdTaskWorkflow(args) {
11196
11384
  }
11197
11385
  const route = routeInput.startsWith("/") ? routeInput : `/${routeInput}`;
11198
11386
  const taskSummary = positional.slice(1).join(" ").trim();
11199
- const essencePath = join30(workspaceInfo.appRoot, "decantr.essence.json");
11387
+ const essencePath = join31(workspaceInfo.appRoot, "decantr.essence.json");
11200
11388
  const essence = readJsonIfPresent(essencePath);
11201
11389
  if (!essence) {
11202
11390
  console.error(
@@ -11220,19 +11408,19 @@ async function cmdTaskWorkflow(args) {
11220
11408
  }
11221
11409
  const section = essence.blueprint.sections.find((entry) => entry.id === target.section);
11222
11410
  const page = section?.pages.find((entry) => entry.id === target.page);
11223
- const contextDir = join30(workspaceInfo.appRoot, ".decantr", "context");
11224
- const manifest = readJsonIfPresent(join30(contextDir, "pack-manifest.json"));
11225
- const projectJson = readJsonIfPresent(join30(workspaceInfo.appRoot, ".decantr", "project.json"));
11411
+ const contextDir = join31(workspaceInfo.appRoot, ".decantr", "context");
11412
+ const manifest = readJsonIfPresent(join31(contextDir, "pack-manifest.json"));
11413
+ const projectJson = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "project.json"));
11226
11414
  const pagePack = manifest?.pages?.find((entry) => entry.id === target.page);
11227
11415
  const sectionPack = manifest?.sections?.find((entry) => entry.id === target.section);
11228
- const visualManifest = readJsonIfPresent(join30(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
11416
+ const visualManifest = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
11229
11417
  const screenshot = visualManifest?.routes?.find((entry) => entry.route === route)?.screenshot;
11230
11418
  const localPatternPackPath = localPatternsPath(workspaceInfo.appRoot);
11231
11419
  const localRuleManifestPath = localRulesPath(workspaceInfo.appRoot);
11232
11420
  const acceptedStyleBridgePath = styleBridgePath(workspaceInfo.appRoot);
11233
- const graphDir = join30(workspaceInfo.appRoot, ".decantr", "graph");
11234
- const contractCapsulePath = join30(graphDir, "contract-capsule.json");
11235
- const graphSnapshotPath = join30(graphDir, "graph.snapshot.json");
11421
+ const graphDir = join31(workspaceInfo.appRoot, ".decantr", "graph");
11422
+ const contractCapsulePath = join31(graphDir, "contract-capsule.json");
11423
+ const graphSnapshotPath = join31(graphDir, "graph.snapshot.json");
11236
11424
  const contractCapsule = readJsonIfPresent(contractCapsulePath);
11237
11425
  const graphSnapshot = readJsonIfPresent(graphSnapshotPath);
11238
11426
  const routeGraphContext = buildGraphRouteContext(graphSnapshot, route, { task: taskSummary });
@@ -11275,12 +11463,96 @@ async function cmdTaskWorkflow(args) {
11275
11463
  projectRoot: workspaceInfo.appRoot,
11276
11464
  workflowMode: projectJson?.initialized?.workflowMode ?? null,
11277
11465
  adoptionMode: projectJson?.initialized?.adoptionMode ?? null,
11278
- hasLocalPatterns: existsSync28(localPatternPackPath),
11279
- hasLocalRules: existsSync28(localRuleManifestPath),
11466
+ hasLocalPatterns: existsSync29(localPatternPackPath),
11467
+ hasLocalRules: existsSync29(localRuleManifestPath),
11280
11468
  hasPackManifest: Boolean(manifest),
11281
11469
  taskSummary,
11282
- hasStyleBridge: existsSync28(acceptedStyleBridgePath)
11470
+ hasStyleBridge: existsSync29(acceptedStyleBridgePath)
11283
11471
  });
11472
+ const readTargets = [
11473
+ pagePack ? displayProjectPath(workspaceInfo, join31(".decantr/context", pagePack.markdown)) : null,
11474
+ sectionPack ? displayProjectPath(workspaceInfo, join31(".decantr/context", sectionPack.markdown)) : null,
11475
+ manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join31(".decantr/context", manifest.scaffold.markdown)) : null,
11476
+ displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
11477
+ displayProjectPath(workspaceInfo, "DECANTR.md"),
11478
+ existsSync29(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
11479
+ existsSync29(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null,
11480
+ existsSync29(acceptedStyleBridgePath) ? displayProjectPath(workspaceInfo, ".decantr/style-bridge.json") : null,
11481
+ contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json") : null,
11482
+ routeGraphContext && !contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json") : null
11483
+ ].filter((value) => Boolean(value));
11484
+ const taskLoopState = readTargets.length === 0 ? "blocked_missing_context" : !routeGraphContext ? "blocked_missing_graph" : "ready_to_edit";
11485
+ const taskLoop = {
11486
+ $schema: LOOP_READINESS_V2_SCHEMA_URL,
11487
+ schemaVersion: 2,
11488
+ state: taskLoopState,
11489
+ status: taskLoopState === "ready_to_edit" ? "healthy" : "blocked",
11490
+ verdict: taskLoopState === "ready_to_edit" ? "Task context is ready for an agent edit." : "Task context is missing required context or graph evidence.",
11491
+ summary: `${route} task context with ${readTargets.length} read target(s), ${routeGraphContext ? routeGraphContext.summary.nodes : 0} graph node(s), and ${changedRoutes.length} changed-route hint(s).`,
11492
+ authority: {
11493
+ activeLane: projectJson?.initialized?.workflowMode === "brownfield-attach" ? "production-source" : "essence-contract",
11494
+ summary: `${authority.lane}: ${authority.sourceAuthority}`,
11495
+ stopRule: "If runtime source and Decantr context disagree, stop and report drift instead of guessing."
11496
+ },
11497
+ evidenceTier: {
11498
+ schemaVersion: 2,
11499
+ stage: routeGraphContext ? "graph" : "static",
11500
+ status: taskLoopState === "ready_to_edit" ? "healthy" : "incomplete",
11501
+ capabilities: routeGraphContext ? ["static-audit", "project-health", "typed-graph"] : ["static-audit", "project-health"],
11502
+ coverage: {
11503
+ declaredRoutes: 1,
11504
+ runtimeRoutesChecked: 0,
11505
+ findingsAnchored: routeGraphContext?.summary.openFindings ?? 0,
11506
+ findingsWithRepairPlan: 0,
11507
+ runtimeProbeCount: 0,
11508
+ visualArtifactCount: screenshot ? 1 : 0
11509
+ },
11510
+ confidence: {
11511
+ level: routeGraphContext ? "moderate" : "low",
11512
+ score: routeGraphContext ? 0.64 : 0.32,
11513
+ reasons: [
11514
+ routeGraphContext ? "route graph context is present" : "route graph context is missing",
11515
+ screenshot ? "visual evidence reference is available" : "no visual evidence reference was found"
11516
+ ]
11517
+ }
11518
+ },
11519
+ blockingReasons: taskLoopState === "ready_to_edit" ? [] : [
11520
+ taskLoopState === "blocked_missing_graph" ? "Route graph context is missing or stale." : "Route context read targets are missing."
11521
+ ],
11522
+ nextActions: taskLoopState === "ready_to_edit" ? ["Edit only after reading the listed context, then run the verify command."] : [
11523
+ taskLoopState === "blocked_missing_graph" ? "Run `decantr graph`, then rerun `decantr task`." : "Run `decantr refresh`, then rerun `decantr task`."
11524
+ ],
11525
+ maker: {
11526
+ title: "Maker instructions",
11527
+ instructions: [
11528
+ "Read the listed route, section, scaffold, DECANTR, local-law, and graph targets before editing.",
11529
+ "Preserve the active authority lane and existing production behavior outside this task.",
11530
+ "Stop and report drift if source, graph, and contract context disagree."
11531
+ ]
11532
+ },
11533
+ checker: {
11534
+ title: "Checker instructions",
11535
+ instructions: [
11536
+ "Rerun the verify command after edits.",
11537
+ "Use changed-file graph impact and route findings to decide whether more routes need review.",
11538
+ "Do not treat advisory critique as blocking without T1/T2 evidence."
11539
+ ]
11540
+ },
11541
+ readTargets,
11542
+ graphImpact: {
11543
+ status: routeGraphContext ? "ready" : graphSnapshot ? "stale" : "missing",
11544
+ snapshotId: routeGraphContext?.snapshotId ?? graphSnapshot?.id ?? null,
11545
+ sourceHash: routeGraphContext?.sourceHash ?? graphSnapshot?.source_hash ?? null,
11546
+ sourceArtifactCount: routeGraphContext?.summary.sourceArtifacts ?? 0,
11547
+ staleArtifacts: []
11548
+ },
11549
+ stopConditions: [
11550
+ "Runtime source and Decantr context disagree.",
11551
+ "The route graph cannot resolve a source file affected by the edit.",
11552
+ "A fix requires contract/source/local-law mutation outside the explicit workflow."
11553
+ ],
11554
+ verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
11555
+ };
11284
11556
  const context = {
11285
11557
  route,
11286
11558
  task: taskSummary || null,
@@ -11288,18 +11560,7 @@ async function cmdTaskWorkflow(args) {
11288
11560
  page: target.page,
11289
11561
  shell: page?.shell ?? section?.shell ?? null,
11290
11562
  patterns: routePatterns,
11291
- read: [
11292
- pagePack ? displayProjectPath(workspaceInfo, join30(".decantr/context", pagePack.markdown)) : null,
11293
- sectionPack ? displayProjectPath(workspaceInfo, join30(".decantr/context", sectionPack.markdown)) : null,
11294
- manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join30(".decantr/context", manifest.scaffold.markdown)) : null,
11295
- displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
11296
- displayProjectPath(workspaceInfo, "DECANTR.md"),
11297
- existsSync28(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
11298
- existsSync28(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null,
11299
- existsSync28(acceptedStyleBridgePath) ? displayProjectPath(workspaceInfo, ".decantr/style-bridge.json") : null,
11300
- contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json") : null,
11301
- routeGraphContext && !contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json") : null
11302
- ].filter(Boolean),
11563
+ read: readTargets,
11303
11564
  graph: contractCapsule || graphSnapshot ? {
11304
11565
  capsule: contractCapsule ? {
11305
11566
  path: displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json"),
@@ -11342,6 +11603,7 @@ async function cmdTaskWorkflow(args) {
11342
11603
  styleBridge: displayedStyleBridge,
11343
11604
  changedFiles: currentChangedFiles,
11344
11605
  changedRoutes,
11606
+ loop: taskLoop,
11345
11607
  verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
11346
11608
  };
11347
11609
  if (flagBoolean(flags, "json")) {
@@ -11355,18 +11617,18 @@ async function cmdTaskWorkflow(args) {
11355
11617
  if (context.patterns.length > 0) console.log(` Patterns: ${context.patterns.join(", ")}`);
11356
11618
  if (taskSummary) console.log(` Task: ${taskSummary}`);
11357
11619
  console.log("");
11358
- console.log(`${BOLD9}Read before editing:${RESET16}`);
11620
+ console.log(`${BOLD10}Read before editing:${RESET17}`);
11359
11621
  for (const path of context.read) {
11360
11622
  console.log(` ${cyan3(path)}`);
11361
11623
  }
11362
11624
  if (context.screenshot) {
11363
11625
  console.log("");
11364
- console.log(`${BOLD9}Visual evidence:${RESET16}`);
11626
+ console.log(`${BOLD10}Visual evidence:${RESET17}`);
11365
11627
  console.log(` ${cyan3(context.screenshot)}`);
11366
11628
  }
11367
11629
  if (context.graph?.capsule || context.graph?.snapshot) {
11368
11630
  console.log("");
11369
- console.log(`${BOLD9}Typed contract graph:${RESET16}`);
11631
+ console.log(`${BOLD10}Typed contract graph:${RESET17}`);
11370
11632
  if (context.graph.capsule) {
11371
11633
  console.log(` Capsule: ${cyan3(context.graph.capsule.path)}`);
11372
11634
  if (context.graph.capsule.cacheKey) {
@@ -11414,18 +11676,18 @@ async function cmdTaskWorkflow(args) {
11414
11676
  }
11415
11677
  }
11416
11678
  console.log("");
11417
- console.log(`${BOLD9}Authority for this task:${RESET16}`);
11679
+ console.log(`${BOLD10}Authority for this task:${RESET17}`);
11418
11680
  console.log(` Lane: ${context.authority.lane}`);
11419
11681
  console.log(` Source: ${context.authority.sourceAuthority}`);
11420
11682
  console.log(` Style: ${context.authority.styleAuthority}`);
11421
11683
  console.log(` Active: ${context.authority.activeAuthorities.join(", ")}`);
11422
11684
  console.log(` Runtime: ${context.authority.runtimeBoundary}`);
11423
11685
  for (const warning of context.authority.warnings) {
11424
- console.log(` ${YELLOW12}Boundary:${RESET16} ${warning}`);
11686
+ console.log(` ${YELLOW13}Boundary:${RESET17} ${warning}`);
11425
11687
  }
11426
11688
  if (context.localLaw.patternCount > 0 || context.localLaw.ruleCount > 0) {
11427
11689
  console.log("");
11428
- console.log(`${BOLD9}Project-owned local law:${RESET16}`);
11690
+ console.log(`${BOLD10}Project-owned local law:${RESET17}`);
11429
11691
  if (context.localLaw.patternsPath) {
11430
11692
  console.log(
11431
11693
  ` Patterns: ${cyan3(context.localLaw.patternsPath)} (${context.localLaw.patternCount})`
@@ -11447,7 +11709,7 @@ async function cmdTaskWorkflow(args) {
11447
11709
  }
11448
11710
  if (context.localLaw.behaviorObligations.length > 0) {
11449
11711
  console.log("");
11450
- console.log(`${BOLD9}Behavior obligations:${RESET16}`);
11712
+ console.log(`${BOLD10}Behavior obligations:${RESET17}`);
11451
11713
  for (const behavior of context.localLaw.behaviorObligations.slice(0, 3)) {
11452
11714
  const obligations = behavior.obligations.slice(0, 3).map((obligation) => obligation.label).join("; ");
11453
11715
  const reasons = behavior.relevance.reasons.slice(0, 3).join(", ");
@@ -11464,14 +11726,14 @@ async function cmdTaskWorkflow(args) {
11464
11726
  }
11465
11727
  } else {
11466
11728
  console.log("");
11467
- console.log(`${BOLD9}Project-owned local law:${RESET16}`);
11729
+ console.log(`${BOLD10}Project-owned local law:${RESET17}`);
11468
11730
  console.log(
11469
- ` ${YELLOW12}Not codified yet.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
11731
+ ` ${YELLOW13}Not codified yet.${RESET17} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
11470
11732
  );
11471
11733
  }
11472
11734
  if (context.styleBridge.path) {
11473
11735
  console.log("");
11474
- console.log(`${BOLD9}Project-owned style bridge:${RESET16}`);
11736
+ console.log(`${BOLD10}Project-owned style bridge:${RESET17}`);
11475
11737
  console.log(
11476
11738
  ` Bridge: ${cyan3(context.styleBridge.path)} (${context.styleBridge.mappingCount} mappings, ${context.styleBridge.stylingApproach ?? "unknown"} styling)`
11477
11739
  );
@@ -11488,7 +11750,7 @@ async function cmdTaskWorkflow(args) {
11488
11750
  }
11489
11751
  if (context.changedFiles.length > 0) {
11490
11752
  console.log("");
11491
- console.log(`${BOLD9}Changed-file context:${RESET16}`);
11753
+ console.log(`${BOLD10}Changed-file context:${RESET17}`);
11492
11754
  for (const file of context.changedFiles.slice(0, 8)) {
11493
11755
  console.log(` ${file}`);
11494
11756
  }
@@ -11500,7 +11762,14 @@ async function cmdTaskWorkflow(args) {
11500
11762
  }
11501
11763
  }
11502
11764
  console.log("");
11503
- console.log(`${BOLD9}LLM instruction:${RESET16}`);
11765
+ console.log(`${BOLD10}Control loop:${RESET17}`);
11766
+ console.log(
11767
+ ` State: ${context.loop.state} | evidence ${context.loop.evidenceTier.confidence.level}`
11768
+ );
11769
+ console.log(` Next: ${context.loop.nextActions[0]}`);
11770
+ console.log(` Stop: ${context.loop.stopConditions[0]}`);
11771
+ console.log("");
11772
+ console.log(`${BOLD10}LLM instruction:${RESET17}`);
11504
11773
  console.log(
11505
11774
  " Preserve the active authority above. Use the route pack, section context, typed route graph, local laws, changed-file impact, and visual evidence as the task contract before changing code."
11506
11775
  );
@@ -11528,7 +11797,7 @@ async function cmdCodifyWorkflow(args) {
11528
11797
  const workspaceInfo = resolveWorkflowProject(flags, "codify");
11529
11798
  if (!workspaceInfo) return;
11530
11799
  if (flagBoolean(flags, "accept")) {
11531
- if (!existsSync28(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync28(localRulesProposalPath(workspaceInfo.appRoot)) && !existsSync28(styleBridgeProposalPath(workspaceInfo.appRoot))) {
11800
+ if (!existsSync29(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync29(localRulesProposalPath(workspaceInfo.appRoot)) && !existsSync29(styleBridgeProposalPath(workspaceInfo.appRoot))) {
11532
11801
  console.error(
11533
11802
  error2(
11534
11803
  "No codify proposal found. Run `decantr codify --from-audit`, `decantr codify --style-bridge`, or `decantr codify` first."
@@ -11562,14 +11831,14 @@ async function cmdCodifyWorkflow(args) {
11562
11831
  }
11563
11832
  const detected = detectProject(workspaceInfo.appRoot);
11564
11833
  const essence = readJsonIfPresent(
11565
- join30(workspaceInfo.appRoot, "decantr.essence.json")
11834
+ join31(workspaceInfo.appRoot, "decantr.essence.json")
11566
11835
  );
11567
11836
  const fromAudit = flagBoolean(flags, "from-audit") || flagBoolean(flags, "discover-local-patterns") || flagBoolean(flags, "codify-local-patterns");
11568
11837
  const wantsStyleBridge = flagBoolean(flags, "style-bridge");
11569
11838
  const mapPatternSlug = flagString(flags, "map-pattern") ?? flagString(flags, "hosted-pattern");
11570
11839
  if (mapPatternSlug) {
11571
11840
  const registryClient = new RegistryClient({
11572
- cacheDir: join30(workspaceInfo.appRoot, ".decantr", "cache")
11841
+ cacheDir: join31(workspaceInfo.appRoot, ".decantr", "cache")
11573
11842
  });
11574
11843
  const candidates = await loadPatternDiscoveryCandidates(registryClient);
11575
11844
  const candidate = findPatternCandidateBySlug(candidates, mapPatternSlug);
@@ -11693,22 +11962,25 @@ async function cmdContentWorkflow(args) {
11693
11962
  }
11694
11963
  function cmdHelp() {
11695
11964
  console.log(`
11696
- ${BOLD9}decantr${RESET16} \u2014 AI Frontend Governance for codebases touched by AI agents
11965
+ ${BOLD10}decantr${RESET17} \u2014 AI Frontend Governance for codebases touched by AI agents
11697
11966
 
11698
- ${BOLD9}Usage:${RESET16}
11967
+ ${BOLD10}Usage:${RESET17}
11699
11968
  decantr setup [--project <path>]
11700
11969
  decantr scan [--project <path>] [--json]
11701
11970
  decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
11702
11971
  decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--no-packs] [--yes]
11703
11972
  decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
11704
11973
  decantr verify [--project <path>] [--brownfield] [--local-patterns] [health options]
11974
+ decantr resolve [--project <path>] [--json] [--defer <finding-id>] [--mark-advisory <finding-id>]
11705
11975
  decantr graph [--project <path>] [--route <route>] [--node <id>] [--file <path>] [--task <text>] [--snapshot-id <id>] [--compare-to <id>] [--capsule-source-limit <count>] [--check] [--json]
11706
11976
  decantr ci [--project <path>] [--workspace] [--fail-on error|warn|none]
11707
11977
  decantr doctor [--project <path>] [--workspace] [--json]
11708
11978
  decantr codify [--from-audit] [--style-bridge] [--map-pattern <slug>] [--accept] [--project <path>]
11709
11979
  decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json] [--workspace]
11710
11980
 
11711
- ${BOLD9}Advanced primitives:${RESET16}
11981
+ ${formatWhichCommandFirst()}
11982
+
11983
+ ${BOLD10}Advanced primitives:${RESET17}
11712
11984
  decantr init [options]
11713
11985
  decantr analyze
11714
11986
  decantr magic <prompt> [--dry-run]
@@ -11719,6 +11991,7 @@ ${BOLD9}Advanced primitives:${RESET16}
11719
11991
  decantr check
11720
11992
  decantr check --brownfield
11721
11993
  decantr sync-drift
11994
+ decantr resolve [--json]
11722
11995
  decantr graph [--project <path>] [--route <route>] [--node <id>] [--file <path>] [--task <text>] [--snapshot-id <id>] [--compare-to <id>] [--capsule-source-limit <count>] [--check] [--json]
11723
11996
  decantr search <query> [--type <type>] [--sort <recommended|recent|name>] [--recommended] [--source <authored|benchmark|hybrid>]
11724
11997
  decantr suggest <query> [--type <type>] [--route <route>] [--file <path>] [--from-code]
@@ -11753,7 +12026,7 @@ ${BOLD9}Advanced primitives:${RESET16}
11753
12026
  decantr logout
11754
12027
  decantr help
11755
12028
 
11756
- ${BOLD9}Init Options:${RESET16}
12029
+ ${BOLD10}Init Options:${RESET17}
11757
12030
  --blueprint, -b Blueprint ID
11758
12031
  --theme Theme ID
11759
12032
  --mode Color mode: dark | light | auto
@@ -11775,13 +12048,14 @@ ${BOLD9}Init Options:${RESET16}
11775
12048
  --registry Custom registry URL
11776
12049
  --telemetry Opt this project into privacy-filtered CLI product telemetry
11777
12050
 
11778
- ${BOLD9}Commands:${RESET16}
12051
+ ${BOLD10}Commands:${RESET17}
11779
12052
  ${cyan3("setup")} Detect project state and recommend the right Decantr workflow
11780
12053
  ${cyan3("scan")} Read-only Brownfield reconnaissance; no files written
11781
12054
  ${cyan3("new")} Create a new greenfield workspace and bootstrap the available starter adapter
11782
12055
  ${cyan3("adopt")} Brownfield one-liner: analyze, attach, verify, and show next steps
11783
12056
  ${cyan3("task")} Prepare route/task context, local law, behavior obligations, evidence, and changed-file impact for an AI coding assistant
11784
12057
  ${cyan3("verify")} One reliability gate over Project Health, Brownfield checks, baselines, and evidence
12058
+ ${cyan3("resolve")} Read authority conflicts and explicitly defer/advisory-mark drift
11785
12059
  ${cyan3("graph")} Build typed Contract graph artifacts and the agent cache capsule
11786
12060
  ${cyan3("ci")} Non-mutating CI gate and CI integration generator
11787
12061
  ${cyan3("doctor")} Explain Decantr state, artifact ownership, and the next command
@@ -11789,7 +12063,7 @@ ${BOLD9}Commands:${RESET16}
11789
12063
  ${cyan3("studio")} Open a local Project Health dashboard backed by the same report
11790
12064
  ${cyan3("content")} Content-author namespace: check, create, publish
11791
12065
 
11792
- ${BOLD9}Advanced commands:${RESET16}
12066
+ ${BOLD10}Advanced commands:${RESET17}
11793
12067
  ${cyan3("magic")} Greenfield-first intent flow; steers existing apps into analyze + init
11794
12068
  ${cyan3("init")} Attach Decantr contract/context files to an existing project or empty workspace
11795
12069
  ${cyan3("status")} Show project status, DNA axioms, and blueprint info
@@ -11801,6 +12075,7 @@ ${BOLD9}Advanced commands:${RESET16}
11801
12075
  ${cyan3("migrate")} Migrate older essence files to v4 format (with .pre-v4.backup.json backup)
11802
12076
  ${cyan3("check")} Detect drift issues (validate + guard rules) [--telemetry] [--brownfield]
11803
12077
  ${cyan3("sync-drift")} Review and resolve drift log entries
12078
+ ${cyan3("resolve")} Group source-vs-contract conflicts and print exact resolution actions
11804
12079
  ${cyan3("graph")} Generate .decantr/graph snapshot, history, manifest, diff, and contract capsule
11805
12080
  ${cyan3("search")} Search official/community vocabulary
11806
12081
  ${cyan3("suggest")} Suggest patterns or alternatives for a query
@@ -11821,7 +12096,7 @@ ${BOLD9}Advanced commands:${RESET16}
11821
12096
  ${cyan3("upgrade")} Check for content updates from registry
11822
12097
  ${cyan3("help")} Show this help
11823
12098
 
11824
- ${BOLD9}Examples:${RESET16}
12099
+ ${BOLD10}Examples:${RESET17}
11825
12100
  decantr setup
11826
12101
  decantr scan
11827
12102
  decantr scan --json
@@ -11830,6 +12105,7 @@ ${BOLD9}Examples:${RESET16}
11830
12105
  decantr adopt --project apps/web --yes
11831
12106
  decantr task /feed "add saved recipe actions"
11832
12107
  decantr verify --brownfield --local-patterns
12108
+ decantr resolve
11833
12109
  decantr graph --project apps/web
11834
12110
  decantr graph --project apps/web --route /feed --task "improve loading" --json
11835
12111
  decantr graph --project apps/web --file src/app/page.tsx --impact --json
@@ -11885,35 +12161,36 @@ ${BOLD9}Examples:${RESET16}
11885
12161
  decantr registry audit-project --namespace @official --dist dist --sources src
11886
12162
  decantr create pattern my-card
11887
12163
 
11888
- ${BOLD9}Workflow Model:${RESET16}
12164
+ ${BOLD10}Workflow Model:${RESET17}
11889
12165
  ${cyan3("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=decantr-css
11890
12166
  ${cyan3("Greenfield contract")} decantr init --workflow=greenfield --adoption=contract-only
11891
12167
  ${cyan3("Brownfield adoption")} decantr adopt --yes
11892
12168
  ${cyan3("Brownfield preview")} decantr scan -> decantr adopt --yes
11893
12169
  ${cyan3("Brownfield monorepo")} decantr adopt --project apps/web --yes
11894
12170
  ${cyan3("Daily LLM work")} decantr task <route> "<change>" -> decantr verify --brownfield --local-patterns
12171
+ ${cyan3("Drift resolution")} decantr resolve -> codify/init/graph/repair source explicitly
11895
12172
  ${cyan3("Typed contract graph")} decantr graph -> agent session loads .decantr/graph/contract-capsule.json
11896
12173
  ${cyan3("Project-owned law")} decantr codify --from-audit -> edit proposal -> decantr codify --accept
11897
12174
  ${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
11898
12175
 
11899
- ${BOLD9}Bootstrap adapters:${RESET16}
12176
+ ${BOLD10}Bootstrap adapters:${RESET17}
11900
12177
  Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}, ${cyan3("vanilla-vite")}, ${cyan3("vue-vite")}, ${cyan3("sveltekit")}, ${cyan3("angular")}, ${cyan3("solid-vite")}
11901
12178
  Unsupported targets resolve through ${cyan3("generic-web")} contract-only mode until their starter adapters land.
11902
12179
  `);
11903
12180
  }
11904
12181
  function cmdRulesHelp() {
11905
12182
  console.log(`
11906
- ${BOLD9}decantr rules${RESET16} \u2014 Preview or apply assistant bridge snippets
12183
+ ${BOLD10}decantr rules${RESET17} \u2014 Preview or apply assistant bridge snippets
11907
12184
 
11908
- ${BOLD9}Usage:${RESET16}
12185
+ ${BOLD10}Usage:${RESET17}
11909
12186
  decantr rules preview [--project=<path>]
11910
12187
  decantr rules apply [--project=<path>]
11911
12188
 
11912
- ${BOLD9}Subcommands:${RESET16}
12189
+ ${BOLD10}Subcommands:${RESET17}
11913
12190
  ${cyan3("preview")} Print target-specific Decantr bridge guidance without mutating rule files
11914
12191
  ${cyan3("apply")} Idempotently write Decantr bridge blocks to supported assistant rule files
11915
12192
 
11916
- ${BOLD9}Examples:${RESET16}
12193
+ ${BOLD10}Examples:${RESET17}
11917
12194
  decantr rules preview
11918
12195
  decantr rules preview --project=apps/web
11919
12196
  decantr rules apply --project=apps/web
@@ -11921,21 +12198,23 @@ ${BOLD9}Examples:${RESET16}
11921
12198
  }
11922
12199
  function cmdScanHelp() {
11923
12200
  console.log(`
11924
- ${BOLD9}decantr scan${RESET16} \u2014 Read-only Brownfield reconnaissance
12201
+ ${BOLD10}decantr scan${RESET17} \u2014 Read-only Brownfield reconnaissance
11925
12202
 
11926
- ${BOLD9}Usage:${RESET16}
12203
+ ${BOLD10}Usage:${RESET17}
11927
12204
  decantr scan [--project <path>] [--json]
11928
12205
 
11929
- ${BOLD9}Options:${RESET16}
12206
+ ${BOLD10}Options:${RESET17}
11930
12207
  --project App path inside a workspace/monorepo
11931
12208
  --json Emit the ScanReportV1 JSON to stdout
11932
12209
 
11933
- ${BOLD9}Behavior:${RESET16}
12210
+ ${BOLD10}Behavior:${RESET17}
11934
12211
  Reads local project files, detects frontend framework/routes/styling/static-hosting signals,
11935
12212
  and prints a terminal report. It does not write .decantr files, install dependencies,
11936
12213
  build the app, execute scripts, upload source, or open pull requests.
11937
12214
 
11938
- ${BOLD9}Examples:${RESET16}
12215
+ ${formatWhichCommandFirst()}
12216
+
12217
+ ${BOLD10}Examples:${RESET17}
11939
12218
  decantr scan
11940
12219
  decantr scan --project apps/web
11941
12220
  decantr scan --json
@@ -11946,9 +12225,9 @@ function isCommandHelpRequest(args) {
11946
12225
  }
11947
12226
  function cmdHealthHelp() {
11948
12227
  console.log(`
11949
- ${BOLD9}decantr health${RESET16} \u2014 Generate a local Project Health report
12228
+ ${BOLD10}decantr health${RESET17} \u2014 Generate a local Project Health report
11950
12229
 
11951
- ${BOLD9}Usage:${RESET16}
12230
+ ${BOLD10}Usage:${RESET17}
11952
12231
  decantr health [--format text|json|markdown] [--output <file>]
11953
12232
  decantr health --json
11954
12233
  decantr health --markdown
@@ -11961,7 +12240,7 @@ ${BOLD9}Usage:${RESET16}
11961
12240
  decantr health --since-baseline
11962
12241
  decantr health init-ci [legacy alias for decantr ci init]
11963
12242
 
11964
- ${BOLD9}Options:${RESET16}
12243
+ ${BOLD10}Options:${RESET17}
11965
12244
  --format Output format: text, json, or markdown
11966
12245
  --json Emit JSON report
11967
12246
  --markdown Emit markdown report
@@ -11977,7 +12256,7 @@ ${BOLD9}Options:${RESET16}
11977
12256
  --since-baseline Compare this run to .decantr/health-baseline.json
11978
12257
  --design-tokens Compare against a Figma/Tokens Studio JSON export
11979
12258
 
11980
- ${BOLD9}Examples:${RESET16}
12259
+ ${BOLD10}Examples:${RESET17}
11981
12260
  decantr health
11982
12261
  decantr health --json
11983
12262
  decantr health --markdown --output decantr-health.md
@@ -11991,14 +12270,14 @@ ${BOLD9}Examples:${RESET16}
11991
12270
  }
11992
12271
  function cmdWorkspaceHelp() {
11993
12272
  console.log(`
11994
- ${BOLD9}decantr workspace${RESET16} \u2014 Inspect Decantr projects and app candidates across a monorepo
12273
+ ${BOLD10}decantr workspace${RESET17} \u2014 Inspect Decantr projects and app candidates across a monorepo
11995
12274
 
11996
- ${BOLD9}Usage:${RESET16}
12275
+ ${BOLD10}Usage:${RESET17}
11997
12276
  decantr workspace list [--json]
11998
12277
  decantr workspace health [--json|--markdown] [--output <file>]
11999
12278
  decantr workspace health --changed --since origin/main
12000
12279
 
12001
- ${BOLD9}Examples:${RESET16}
12280
+ ${BOLD10}Examples:${RESET17}
12002
12281
  decantr workspace list
12003
12282
  decantr adopt --project apps/web --yes
12004
12283
  decantr workspace health
@@ -12008,16 +12287,16 @@ ${BOLD9}Examples:${RESET16}
12008
12287
  }
12009
12288
  function cmdContentHealthHelp() {
12010
12289
  console.log(`
12011
- ${BOLD9}decantr content-health${RESET16} \u2014 Generate a local official-vocabulary health report
12290
+ ${BOLD10}decantr content-health${RESET17} \u2014 Generate a local official-vocabulary health report
12012
12291
 
12013
- ${BOLD9}Usage:${RESET16}
12292
+ ${BOLD10}Usage:${RESET17}
12014
12293
  decantr content-health [--format text|json|markdown] [--output <file>]
12015
12294
  decantr content-health --json
12016
12295
  decantr content-health --markdown
12017
12296
  decantr content-health --ci [--fail-on error|warn|none]
12018
12297
  decantr content-health --prompt <finding-id>
12019
12298
 
12020
- ${BOLD9}Options:${RESET16}
12299
+ ${BOLD10}Options:${RESET17}
12021
12300
  --format Output format: text, json, or markdown
12022
12301
  --json Emit JSON report
12023
12302
  --markdown Emit markdown report
@@ -12026,7 +12305,7 @@ ${BOLD9}Options:${RESET16}
12026
12305
  --fail-on CI threshold: error, warn, or none
12027
12306
  --prompt Print an AI-ready remediation prompt for a finding
12028
12307
 
12029
- ${BOLD9}Examples:${RESET16}
12308
+ ${BOLD10}Examples:${RESET17}
12030
12309
  decantr content-health
12031
12310
  decantr content-health --json
12032
12311
  decantr content-health --markdown --output content-health.md
@@ -12035,23 +12314,29 @@ ${BOLD9}Examples:${RESET16}
12035
12314
  }
12036
12315
  function cmdStudioHelp() {
12037
12316
  console.log(`
12038
- ${BOLD9}decantr studio${RESET16} \u2014 Run a local Project Health dashboard
12317
+ ${BOLD10}decantr studio${RESET17} \u2014 Run a local Project Health dashboard
12039
12318
 
12040
- ${BOLD9}Usage:${RESET16}
12319
+ ${BOLD10}Usage:${RESET17}
12041
12320
  decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
12042
12321
 
12043
- ${BOLD9}Options:${RESET16}
12322
+ ${BOLD10}Options:${RESET17}
12044
12323
  --port Local port to bind; defaults to 4319
12045
12324
  --host Local host to bind; defaults to 127.0.0.1
12046
12325
  --report Serve a read-only Project Health JSON artifact instead of scanning the current project
12047
12326
  --workspace Serve a monorepo workspace health dashboard
12048
12327
 
12049
- ${BOLD9}Endpoints:${RESET16}
12328
+ ${BOLD10}Endpoints:${RESET17}
12050
12329
  GET /
12051
12330
  GET /api/health
12331
+ GET /api/control-room
12332
+ GET /api/resolve
12333
+ GET /api/evidence
12334
+ GET /api/graph-impact
12335
+ GET /api/task-preview
12336
+ GET /api/proof
12052
12337
  POST /api/refresh
12053
12338
 
12054
- ${BOLD9}Examples:${RESET16}
12339
+ ${BOLD10}Examples:${RESET17}
12055
12340
  decantr studio
12056
12341
  decantr studio --port 4320
12057
12342
  decantr studio --host 127.0.0.1 --port 4319
@@ -12062,9 +12347,9 @@ ${BOLD9}Examples:${RESET16}
12062
12347
  }
12063
12348
  function cmdRegistryHelp() {
12064
12349
  console.log(`
12065
- ${BOLD9}decantr registry${RESET16} \u2014 Read hosted execution packs and registry intelligence
12350
+ ${BOLD10}decantr registry${RESET17} \u2014 Read hosted execution packs and registry intelligence
12066
12351
 
12067
- ${BOLD9}Usage:${RESET16}
12352
+ ${BOLD10}Usage:${RESET17}
12068
12353
  decantr registry summary [--namespace <namespace>] [--json]
12069
12354
  decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
12070
12355
  decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
@@ -12075,9 +12360,9 @@ ${BOLD9}Usage:${RESET16}
12075
12360
  }
12076
12361
  function cmdThemeHelp() {
12077
12362
  console.log(`
12078
- ${BOLD9}decantr theme${RESET16} \u2014 Manage custom themes
12363
+ ${BOLD10}decantr theme${RESET17} \u2014 Manage custom themes
12079
12364
 
12080
- ${BOLD9}Usage:${RESET16}
12365
+ ${BOLD10}Usage:${RESET17}
12081
12366
  decantr theme create <name>
12082
12367
  decantr theme create <name> --guided
12083
12368
  decantr theme list
@@ -12088,25 +12373,27 @@ ${BOLD9}Usage:${RESET16}
12088
12373
  }
12089
12374
  function cmdSetupHelp() {
12090
12375
  console.log(`
12091
- ${BOLD9}decantr setup${RESET16} \u2014 Detect the project state and recommend the right Decantr path
12376
+ ${BOLD10}decantr setup${RESET17} \u2014 Detect the project state and recommend the right Decantr path
12092
12377
 
12093
- ${BOLD9}Usage:${RESET16}
12378
+ ${BOLD10}Usage:${RESET17}
12094
12379
  decantr setup [--project <path>]
12095
12380
 
12096
- ${BOLD9}Examples:${RESET16}
12381
+ ${formatWhichCommandFirst()}
12382
+
12383
+ ${BOLD10}Examples:${RESET17}
12097
12384
  decantr setup
12098
12385
  decantr setup --project apps/web
12099
12386
  `);
12100
12387
  }
12101
12388
  function cmdAdoptHelp() {
12102
12389
  console.log(`
12103
- ${BOLD9}decantr adopt${RESET16} \u2014 Brownfield one-liner: analyze, attach, hydrate packs, verify, and show the operating loop
12390
+ ${BOLD10}decantr adopt${RESET17} \u2014 Brownfield one-liner: analyze, attach, hydrate packs, verify, and show the operating loop
12104
12391
 
12105
- ${BOLD9}Usage:${RESET16}
12392
+ ${BOLD10}Usage:${RESET17}
12106
12393
  decantr adopt [--project <path>] [--yes] [--dry-run] [--no-packs]
12107
12394
  decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes] [--no-packs]
12108
12395
 
12109
- ${BOLD9}Options:${RESET16}
12396
+ ${BOLD10}Options:${RESET17}
12110
12397
  --project App path inside a workspace/monorepo
12111
12398
  --yes, -y Run without confirmation
12112
12399
  --dry-run Show the workflow without writing files
@@ -12121,7 +12408,7 @@ ${BOLD9}Options:${RESET16}
12121
12408
  --merge-proposal Merge the observed proposal into an existing essence
12122
12409
  --replace-essence Replace an existing essence with backup
12123
12410
 
12124
- ${BOLD9}Examples:${RESET16}
12411
+ ${BOLD10}Examples:${RESET17}
12125
12412
  decantr adopt --yes
12126
12413
  decantr adopt --project apps/web --yes
12127
12414
  decantr adopt --project apps/web --base-url http://localhost:3000 --evidence --yes
@@ -12131,16 +12418,16 @@ ${BOLD9}Examples:${RESET16}
12131
12418
  }
12132
12419
  function cmdVerifyHelp() {
12133
12420
  console.log(`
12134
- ${BOLD9}decantr verify${RESET16} \u2014 One reliability command for local work and LLM agent loops
12421
+ ${BOLD10}decantr verify${RESET17} \u2014 One reliability command for local work and LLM agent loops
12135
12422
 
12136
- ${BOLD9}Usage:${RESET16}
12423
+ ${BOLD10}Usage:${RESET17}
12137
12424
  decantr verify [--project <path>] [--brownfield] [--local-patterns]
12138
12425
  decantr verify --base-url <url> --evidence
12139
12426
  decantr verify --since-baseline
12140
12427
  decantr verify --workspace [--changed --since origin/main]
12141
12428
  decantr verify init-ci [legacy alias for decantr ci init]
12142
12429
 
12143
- ${BOLD9}Examples:${RESET16}
12430
+ ${BOLD10}Examples:${RESET17}
12144
12431
  decantr verify
12145
12432
  decantr verify --brownfield --local-patterns
12146
12433
  decantr verify --brownfield --local-patterns --project apps/web
@@ -12152,32 +12439,54 @@ ${BOLD9}Examples:${RESET16}
12152
12439
  }
12153
12440
  function cmdTaskHelp() {
12154
12441
  console.log(`
12155
- ${BOLD9}decantr task${RESET16} \u2014 Prepare compact route/task context for an AI coding assistant
12442
+ ${BOLD10}decantr task${RESET17} \u2014 Prepare compact route/task context for an AI coding assistant
12156
12443
 
12157
- ${BOLD9}Usage:${RESET16}
12444
+ ${BOLD10}Usage:${RESET17}
12158
12445
  decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
12159
12446
 
12160
- ${BOLD9}Behavior:${RESET16}
12447
+ ${BOLD10}Behavior:${RESET17}
12161
12448
  Includes accepted local law and behavior obligations, plus the typed contract capsule path when
12162
12449
  .decantr/graph exists. Run decantr graph first when you want graph-backed agent context in
12163
12450
  CLI-only workflows.
12164
12451
 
12165
- ${BOLD9}Examples:${RESET16}
12452
+ ${BOLD10}Examples:${RESET17}
12166
12453
  decantr task /feed "add saved recipe actions"
12167
12454
  decantr task /feed "add saved recipe actions" --since origin/main
12168
12455
  decantr task /profile --json
12169
12456
  `);
12170
12457
  }
12458
+ function cmdResolveHelp() {
12459
+ console.log(`
12460
+ ${BOLD10}decantr resolve${RESET17} \u2014 Explain source-vs-contract authority conflicts
12461
+
12462
+ ${BOLD10}Usage:${RESET17}
12463
+ decantr resolve [--project <path>] [--json]
12464
+ decantr resolve --defer <finding-id>
12465
+ decantr resolve --mark-advisory <finding-id>
12466
+
12467
+ ${BOLD10}Behavior:${RESET17}
12468
+ Read-only by default. Writes are limited to .decantr/drift-log.json and require
12469
+ --defer or --mark-advisory. Contract, source, local-law, and style-bridge changes
12470
+ still go through explicit commands such as codify, init --existing --merge-proposal,
12471
+ graph, or contract_write over MCP.
12472
+
12473
+ ${BOLD10}Examples:${RESET17}
12474
+ decantr resolve
12475
+ decantr resolve --json
12476
+ decantr resolve --project apps/web
12477
+ decantr resolve --defer brownfield-route-drift
12478
+ `);
12479
+ }
12171
12480
  function cmdCodifyHelp() {
12172
12481
  console.log(`
12173
- ${BOLD9}decantr codify${RESET16} \u2014 Propose or accept project-owned Brownfield UI law, behavior obligations, and style bridges
12482
+ ${BOLD10}decantr codify${RESET17} \u2014 Propose or accept project-owned Brownfield UI law, behavior obligations, and style bridges
12174
12483
 
12175
- ${BOLD9}Usage:${RESET16}
12484
+ ${BOLD10}Usage:${RESET17}
12176
12485
  decantr codify [--from-audit] [--style-bridge] [--project <path>]
12177
12486
  decantr codify --map-pattern <registry-pattern-slug> [--project <path>]
12178
12487
  decantr codify --accept [--project <path>]
12179
12488
 
12180
- ${BOLD9}Examples:${RESET16}
12489
+ ${BOLD10}Examples:${RESET17}
12181
12490
  decantr codify
12182
12491
  decantr codify --from-audit
12183
12492
  decantr codify --style-bridge
@@ -12189,14 +12498,14 @@ ${BOLD9}Examples:${RESET16}
12189
12498
  }
12190
12499
  function cmdContentHelp() {
12191
12500
  console.log(`
12192
- ${BOLD9}decantr content${RESET16} \u2014 Content-author namespace for official-vocabulary repositories
12501
+ ${BOLD10}decantr content${RESET17} \u2014 Content-author namespace for official-vocabulary repositories
12193
12502
 
12194
- ${BOLD9}Usage:${RESET16}
12503
+ ${BOLD10}Usage:${RESET17}
12195
12504
  decantr content check [content-health options]
12196
12505
  decantr content create <type> <name>
12197
12506
  decantr content publish <type> <name>
12198
12507
 
12199
- ${BOLD9}Examples:${RESET16}
12508
+ ${BOLD10}Examples:${RESET17}
12200
12509
  decantr content check --ci --fail-on error
12201
12510
  decantr content create pattern my-card
12202
12511
  decantr content publish pattern my-card
@@ -12229,6 +12538,9 @@ function printCommandHelp(command, args) {
12229
12538
  case "task":
12230
12539
  cmdTaskHelp();
12231
12540
  return true;
12541
+ case "resolve":
12542
+ cmdResolveHelp();
12543
+ return true;
12232
12544
  case "codify":
12233
12545
  cmdCodifyHelp();
12234
12546
  return true;
@@ -12270,11 +12582,11 @@ async function main() {
12270
12582
  }
12271
12583
  if (command === "--version" || command === "-v" || command === "version") {
12272
12584
  try {
12273
- const here = dirname6(fileURLToPath3(import.meta.url));
12274
- const candidates = [join30(here, "..", "package.json"), join30(here, "..", "..", "package.json")];
12585
+ const here = dirname7(fileURLToPath3(import.meta.url));
12586
+ const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
12275
12587
  for (const candidate of candidates) {
12276
- if (existsSync28(candidate)) {
12277
- const pkg = JSON.parse(readFileSync21(candidate, "utf-8"));
12588
+ if (existsSync29(candidate)) {
12589
+ const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
12278
12590
  if (pkg.version) {
12279
12591
  console.log(pkg.version);
12280
12592
  return;
@@ -12313,6 +12625,16 @@ async function main() {
12313
12625
  await cmdVerifyWorkflow(args);
12314
12626
  break;
12315
12627
  }
12628
+ case "resolve": {
12629
+ const { flags } = parseLooseArgs(args);
12630
+ if (!ensureAllowedFlags(flags, ["project", "json", "defer", "mark-advisory"], "resolve")) {
12631
+ break;
12632
+ }
12633
+ const workspaceInfo = resolveWorkflowProject(flags, "resolve");
12634
+ if (!workspaceInfo) break;
12635
+ await cmdResolve(workspaceInfo.appRoot, args);
12636
+ break;
12637
+ }
12316
12638
  case "graph": {
12317
12639
  const { flags } = parseLooseArgs(args);
12318
12640
  if (!ensureAllowedFlags(
@@ -12473,10 +12795,10 @@ async function main() {
12473
12795
  case "heal": {
12474
12796
  if (command === "heal") {
12475
12797
  console.log(
12476
- `${YELLOW12}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET16}`
12798
+ `${YELLOW13}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET17}`
12477
12799
  );
12478
12800
  }
12479
- const { cmdHeal } = await import("./heal-OKZ5QZN7.js");
12801
+ const { cmdHeal } = await import("./heal-YXWB6LTI.js");
12480
12802
  const { flags } = parseLooseArgs(args);
12481
12803
  const workspaceInfo = resolveWorkflowProject(flags, "check");
12482
12804
  if (!workspaceInfo) break;
@@ -12501,7 +12823,7 @@ async function main() {
12501
12823
  const { flags } = parseLooseArgs(args);
12502
12824
  const workspaceInfo = resolveWorkflowProject(flags, "health");
12503
12825
  if (!workspaceInfo) break;
12504
- const { cmdHealth, parseHealthArgs } = await import("./health-G7HQCDXX.js");
12826
+ const { cmdHealth, parseHealthArgs } = await import("./health-RKUKPG72.js");
12505
12827
  await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
12506
12828
  } catch (e) {
12507
12829
  console.error(error2(e.message));
@@ -12529,7 +12851,7 @@ async function main() {
12529
12851
  cmdStudioHelp();
12530
12852
  break;
12531
12853
  }
12532
- const { cmdStudio, parseStudioArgs } = await import("./studio-T73T4Q2V.js");
12854
+ const { cmdStudio, parseStudioArgs } = await import("./studio-C2F72QL6.js");
12533
12855
  await cmdStudio(process.cwd(), parseStudioArgs(args));
12534
12856
  } catch (e) {
12535
12857
  console.error(error2(e.message));
@@ -12543,7 +12865,7 @@ async function main() {
12543
12865
  cmdWorkspaceHelp();
12544
12866
  break;
12545
12867
  }
12546
- const { cmdWorkspace } = await import("./workspace-3AJEXXUL.js");
12868
+ const { cmdWorkspace } = await import("./workspace-RJCFPVBL.js");
12547
12869
  await cmdWorkspace(process.cwd(), args);
12548
12870
  } catch (e) {
12549
12871
  console.error(error2(e.message));
@@ -12852,7 +13174,7 @@ async function main() {
12852
13174
  let id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
12853
13175
  if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
12854
13176
  console.error(
12855
- `${RED12}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET16}`
13177
+ `${RED13}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET17}`
12856
13178
  );
12857
13179
  process.exitCode = 1;
12858
13180
  break;
@@ -12862,7 +13184,7 @@ async function main() {
12862
13184
  break;
12863
13185
  }
12864
13186
  if (packType === "page" && route && !id) {
12865
- const resolvedPath = essencePath ? resolveUserPath(essencePath) : join30(process.cwd(), "decantr.essence.json");
13187
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
12866
13188
  id = resolvePagePackIdForRoute(resolvedPath, route);
12867
13189
  }
12868
13190
  await printHostedSelectedExecutionPack(
@@ -12884,7 +13206,7 @@ async function main() {
12884
13206
  const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
12885
13207
  if (!sourcePath) {
12886
13208
  console.error(
12887
- `${RED12}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET16}`
13209
+ `${RED13}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET17}`
12888
13210
  );
12889
13211
  process.exitCode = 1;
12890
13212
  break;
@@ -12909,7 +13231,7 @@ async function main() {
12909
13231
  await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
12910
13232
  } else {
12911
13233
  console.error(
12912
- `${RED12}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${RESET16}`
13234
+ `${RED13}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${RESET17}`
12913
13235
  );
12914
13236
  process.exitCode = 1;
12915
13237
  }
@@ -13081,7 +13403,7 @@ async function main() {
13081
13403
  console.error("");
13082
13404
  console.error(" Example:");
13083
13405
  console.error(
13084
- ` ${CYAN9}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${RESET16}`
13406
+ ` ${CYAN9}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${RESET17}`
13085
13407
  );
13086
13408
  process.exitCode = 1;
13087
13409
  break;