@decantr/cli 3.4.2 → 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.
- package/README.md +6 -4
- package/dist/bin.js +4 -4
- package/dist/{chunk-32WTNJQU.js → chunk-LTNGAAV4.js} +749 -465
- package/dist/{chunk-2GCVVEQC.js → chunk-PM7DKABI.js} +27 -9
- package/dist/{chunk-BDA6TWV3.js → chunk-RJ6PT7WP.js} +36 -11
- package/dist/{chunk-PQKTJGYL.js → chunk-T45GFC6F.js} +80 -5
- package/dist/{heal-OKZ5QZN7.js → heal-YXWB6LTI.js} +1 -1
- package/dist/{health-U7O6PCLZ.js → health-RKUKPG72.js} +2 -2
- package/dist/index.js +4 -4
- package/dist/{studio-X565XJKV.js → studio-C2F72QL6.js} +352 -9
- package/dist/{workspace-NE232D4K.js → workspace-RJCFPVBL.js} +3 -3
- package/package.json +4 -4
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
listWorkspaceCandidates,
|
|
23
23
|
listWorkspaceProjects,
|
|
24
24
|
shouldFailWorkspaceHealth
|
|
25
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
72
|
+
} from "./chunk-PM7DKABI.js";
|
|
73
73
|
|
|
74
74
|
// src/index.ts
|
|
75
|
-
import { existsSync as
|
|
76
|
-
import { basename as basename2, dirname as
|
|
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
|
|
|
@@ -3392,12 +3393,13 @@ ${YELLOW2}Next step:${RESET2} Review ${BOLD}${reportDisplayPath}${RESET2}, then
|
|
|
3392
3393
|
// src/commands/ci.ts
|
|
3393
3394
|
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
3394
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";
|
|
3395
3397
|
var BOLD2 = "\x1B[1m";
|
|
3396
3398
|
var DIM3 = "\x1B[2m";
|
|
3397
3399
|
var GREEN3 = "\x1B[32m";
|
|
3398
3400
|
var RED2 = "\x1B[31m";
|
|
3399
3401
|
var RESET3 = "\x1B[0m";
|
|
3400
|
-
var CI_SCHEMA =
|
|
3402
|
+
var CI_SCHEMA = DECANTR_CI_REPORT_V2_SCHEMA_URL;
|
|
3401
3403
|
function readJson(path) {
|
|
3402
3404
|
if (!existsSync13(path)) return null;
|
|
3403
3405
|
try {
|
|
@@ -3691,6 +3693,9 @@ function formatProjectCiMarkdown(report) {
|
|
|
3691
3693
|
`- Project: \`${report.projectPath ?? "."}\``,
|
|
3692
3694
|
`- Status: **${report.status}**`,
|
|
3693
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}**`,
|
|
3694
3699
|
`- Local law: ${report.localLaw.checked ? `${report.localLaw.errorCount} error(s), ${report.localLaw.warnCount} warning(s)` : "not accepted yet"}`,
|
|
3695
3700
|
`- Style bridge: ${report.styleBridge.checked ? `${report.styleBridge.mappingCount} mapping(s)` : "not active"}`,
|
|
3696
3701
|
"",
|
|
@@ -3710,6 +3715,7 @@ function formatWorkspaceCiMarkdown(report) {
|
|
|
3710
3715
|
"- Mode: **workspace**",
|
|
3711
3716
|
`- Status: **${report.status}**`,
|
|
3712
3717
|
`- Fail on: \`${report.failOn}\``,
|
|
3718
|
+
`- Loop: **${report.loop.state}**`,
|
|
3713
3719
|
"",
|
|
3714
3720
|
formatWorkspaceHealthMarkdown(report.workspace)
|
|
3715
3721
|
];
|
|
@@ -3866,6 +3872,7 @@ async function runWorkspaceCi(root, options) {
|
|
|
3866
3872
|
mode: "workspace",
|
|
3867
3873
|
failOn,
|
|
3868
3874
|
status: workspaceStatus(workspace),
|
|
3875
|
+
loop: workspace.loop,
|
|
3869
3876
|
workspace
|
|
3870
3877
|
};
|
|
3871
3878
|
const json = `${JSON.stringify(report, null, 2)}
|
|
@@ -3904,6 +3911,9 @@ async function runProjectCi(root, options) {
|
|
|
3904
3911
|
projectPath,
|
|
3905
3912
|
failOn,
|
|
3906
3913
|
status: projectCiStatus(health, localLaw, styleBridge),
|
|
3914
|
+
loop: health.loop,
|
|
3915
|
+
authority: health.authority,
|
|
3916
|
+
evidenceTier: health.evidenceTier,
|
|
3907
3917
|
health,
|
|
3908
3918
|
localLaw,
|
|
3909
3919
|
styleBridge
|
|
@@ -6675,80 +6685,226 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
6675
6685
|
console.log(`${GREEN11}Derived files refreshed.${RESET11}`);
|
|
6676
6686
|
}
|
|
6677
6687
|
|
|
6678
|
-
// src/commands/
|
|
6679
|
-
import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "fs";
|
|
6680
|
-
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";
|
|
6681
6693
|
var GREEN12 = "\x1B[32m";
|
|
6682
6694
|
var RED10 = "\x1B[31m";
|
|
6683
6695
|
var YELLOW9 = "\x1B[33m";
|
|
6684
6696
|
var RESET12 = "\x1B[0m";
|
|
6685
|
-
|
|
6686
|
-
|
|
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";
|
|
6687
6843
|
var CYAN6 = "\x1B[36m";
|
|
6688
6844
|
async function cmdSyncDrift(projectRoot = process.cwd()) {
|
|
6689
|
-
const
|
|
6690
|
-
if (!
|
|
6691
|
-
console.log(`${
|
|
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}`);
|
|
6692
6848
|
console.log(
|
|
6693
|
-
`${
|
|
6849
|
+
`${DIM13}Drift is logged when guard violations are detected during development.${RESET13}`
|
|
6694
6850
|
);
|
|
6695
6851
|
return;
|
|
6696
6852
|
}
|
|
6697
6853
|
let entries;
|
|
6698
6854
|
try {
|
|
6699
|
-
entries = JSON.parse(
|
|
6855
|
+
entries = JSON.parse(readFileSync19(driftLogPath2, "utf-8"));
|
|
6700
6856
|
} catch {
|
|
6701
|
-
console.error(`${
|
|
6857
|
+
console.error(`${RED11}Could not parse drift-log.json${RESET13}`);
|
|
6702
6858
|
process.exitCode = 1;
|
|
6703
6859
|
return;
|
|
6704
6860
|
}
|
|
6705
6861
|
if (!Array.isArray(entries)) {
|
|
6706
|
-
console.error(`${
|
|
6862
|
+
console.error(`${RED11}drift-log.json is not an array${RESET13}`);
|
|
6707
6863
|
process.exitCode = 1;
|
|
6708
6864
|
return;
|
|
6709
6865
|
}
|
|
6710
6866
|
const unresolved = entries.filter((e) => !e.resolved);
|
|
6711
6867
|
const resolved = entries.filter((e) => e.resolved);
|
|
6712
6868
|
if (unresolved.length === 0) {
|
|
6713
|
-
console.log(`${
|
|
6869
|
+
console.log(`${GREEN13}No unresolved drift entries.${RESET13}`);
|
|
6714
6870
|
if (resolved.length > 0) {
|
|
6715
|
-
console.log(`${
|
|
6871
|
+
console.log(`${DIM13}${resolved.length} previously resolved entries in the log.${RESET13}`);
|
|
6716
6872
|
}
|
|
6717
6873
|
return;
|
|
6718
6874
|
}
|
|
6719
6875
|
console.log(`
|
|
6720
|
-
${
|
|
6876
|
+
${BOLD7}Unresolved Drift Entries (${unresolved.length})${RESET13}
|
|
6721
6877
|
`);
|
|
6722
6878
|
for (let i = 0; i < unresolved.length; i++) {
|
|
6723
6879
|
const entry = unresolved[i];
|
|
6724
|
-
const severityColor = entry.severity === "error" ?
|
|
6880
|
+
const severityColor = entry.severity === "error" ? RED11 : YELLOW10;
|
|
6725
6881
|
const icon = entry.severity === "error" ? "x" : "!";
|
|
6726
6882
|
console.log(
|
|
6727
|
-
` ${severityColor}${icon}${
|
|
6883
|
+
` ${severityColor}${icon}${RESET13} ${BOLD7}#${i + 1}${RESET13} [${entry.rule}] ${entry.message}`
|
|
6728
6884
|
);
|
|
6729
6885
|
if (entry.page) {
|
|
6730
|
-
console.log(` ${
|
|
6886
|
+
console.log(` ${DIM13}Page: ${entry.page}${RESET13}`);
|
|
6731
6887
|
}
|
|
6732
6888
|
if (entry.suggestion) {
|
|
6733
|
-
console.log(` ${CYAN6}Suggestion: ${entry.suggestion}${
|
|
6889
|
+
console.log(` ${CYAN6}Suggestion: ${entry.suggestion}${RESET13}`);
|
|
6734
6890
|
}
|
|
6735
|
-
console.log(` ${
|
|
6891
|
+
console.log(` ${DIM13}${entry.timestamp}${RESET13}`);
|
|
6736
6892
|
console.log("");
|
|
6737
6893
|
}
|
|
6738
|
-
console.log(`${
|
|
6739
|
-
console.log(` ${CYAN6}decantr sync-drift --resolve-all${
|
|
6740
|
-
console.log(` ${CYAN6}decantr sync-drift --resolve <n>${
|
|
6741
|
-
console.log(` ${CYAN6}decantr sync-drift --clear${
|
|
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`);
|
|
6742
6898
|
console.log("");
|
|
6743
6899
|
}
|
|
6744
6900
|
function resolveDriftEntries(projectRoot, options) {
|
|
6745
|
-
const
|
|
6746
|
-
if (!
|
|
6901
|
+
const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
|
|
6902
|
+
if (!existsSync26(driftLogPath2)) {
|
|
6747
6903
|
return { success: true };
|
|
6748
6904
|
}
|
|
6749
6905
|
if (options.clear) {
|
|
6750
6906
|
try {
|
|
6751
|
-
|
|
6907
|
+
writeFileSync16(driftLogPath2, "[]");
|
|
6752
6908
|
return { success: true };
|
|
6753
6909
|
} catch (e) {
|
|
6754
6910
|
return { success: false, error: `Could not clear drift log: ${e.message}` };
|
|
@@ -6756,7 +6912,7 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
6756
6912
|
}
|
|
6757
6913
|
let entries;
|
|
6758
6914
|
try {
|
|
6759
|
-
entries = JSON.parse(
|
|
6915
|
+
entries = JSON.parse(readFileSync19(driftLogPath2, "utf-8"));
|
|
6760
6916
|
} catch {
|
|
6761
6917
|
return { success: false, error: "Could not parse drift-log.json" };
|
|
6762
6918
|
}
|
|
@@ -6775,7 +6931,7 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
6775
6931
|
}
|
|
6776
6932
|
}
|
|
6777
6933
|
try {
|
|
6778
|
-
|
|
6934
|
+
writeFileSync16(driftLogPath2, JSON.stringify(entries, null, 2));
|
|
6779
6935
|
return { success: true };
|
|
6780
6936
|
} catch (e) {
|
|
6781
6937
|
return { success: false, error: `Could not write drift log: ${e.message}` };
|
|
@@ -6784,11 +6940,11 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
6784
6940
|
|
|
6785
6941
|
// src/commands/telemetry.ts
|
|
6786
6942
|
import { DECANTR_TELEMETRY_EVENT_CATALOG } from "@decantr/telemetry";
|
|
6787
|
-
var
|
|
6943
|
+
var BOLD8 = "\x1B[1m";
|
|
6788
6944
|
var CYAN7 = "\x1B[36m";
|
|
6789
|
-
var
|
|
6790
|
-
var
|
|
6791
|
-
var
|
|
6945
|
+
var DIM14 = "\x1B[2m";
|
|
6946
|
+
var GREEN14 = "\x1B[32m";
|
|
6947
|
+
var RESET14 = "\x1B[0m";
|
|
6792
6948
|
var DEFAULT_API_URL = "https://api.decantr.ai/v1";
|
|
6793
6949
|
async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
6794
6950
|
const subcommand = args[0] ?? "status";
|
|
@@ -6813,14 +6969,14 @@ async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
|
6813
6969
|
}
|
|
6814
6970
|
function printTelemetryHelp() {
|
|
6815
6971
|
console.log(`
|
|
6816
|
-
${
|
|
6972
|
+
${BOLD8}decantr telemetry${RESET14} \u2014 Inspect and link privacy-filtered CLI telemetry identity
|
|
6817
6973
|
|
|
6818
|
-
${
|
|
6974
|
+
${BOLD8}Usage:${RESET14}
|
|
6819
6975
|
decantr telemetry status [--json]
|
|
6820
6976
|
decantr telemetry explain [--json]
|
|
6821
6977
|
decantr telemetry link [--enable] [--org <slug>] [--label <label>] [--api-key <key>] [--api-url <url>]
|
|
6822
6978
|
|
|
6823
|
-
${
|
|
6979
|
+
${BOLD8}Examples:${RESET14}
|
|
6824
6980
|
decantr init --telemetry
|
|
6825
6981
|
decantr telemetry status
|
|
6826
6982
|
decantr telemetry explain
|
|
@@ -6835,18 +6991,18 @@ function printTelemetryStatus(projectRoot, options) {
|
|
|
6835
6991
|
return;
|
|
6836
6992
|
}
|
|
6837
6993
|
console.log(`
|
|
6838
|
-
${
|
|
6839
|
-
console.log(` Enabled: ${status.enabled ? `${
|
|
6994
|
+
${BOLD8}Decantr telemetry${RESET14}`);
|
|
6995
|
+
console.log(` Enabled: ${status.enabled ? `${GREEN14}yes${RESET14}` : "no"}`);
|
|
6840
6996
|
console.log(` Project: ${status.hasProjectConfig ? status.projectRoot : "not initialized"}`);
|
|
6841
|
-
console.log(` Install ID: ${status.installId ?? `${
|
|
6842
|
-
console.log(` Project ID: ${status.projectId ?? `${
|
|
6997
|
+
console.log(` Install ID: ${status.installId ?? `${DIM14}not created yet${RESET14}`}`);
|
|
6998
|
+
console.log(` Project ID: ${status.projectId ?? `${DIM14}not created yet${RESET14}`}`);
|
|
6843
6999
|
if (status.enabled) {
|
|
6844
7000
|
console.log(
|
|
6845
|
-
|
|
7001
|
+
DIM14 + "Run `decantr telemetry link` after login to attach these opaque IDs to your Decantr account/org." + RESET14
|
|
6846
7002
|
);
|
|
6847
7003
|
} else {
|
|
6848
7004
|
console.log(
|
|
6849
|
-
|
|
7005
|
+
DIM14 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET14
|
|
6850
7006
|
);
|
|
6851
7007
|
}
|
|
6852
7008
|
}
|
|
@@ -6908,25 +7064,25 @@ function printTelemetryExplain(projectRoot, options) {
|
|
|
6908
7064
|
return;
|
|
6909
7065
|
}
|
|
6910
7066
|
console.log(`
|
|
6911
|
-
${
|
|
7067
|
+
${BOLD8}Decantr telemetry explanation${RESET14}`);
|
|
6912
7068
|
console.log(` Source: cli`);
|
|
6913
|
-
console.log(` Enabled: ${status.enabled ? `${
|
|
6914
|
-
console.log(` Install ID: ${status.installId ?? `${
|
|
6915
|
-
console.log(` Project ID: ${status.projectId ?? `${
|
|
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}`}`);
|
|
6916
7072
|
console.log(` Events: ${cliEvents.length} CLI event types in the public catalog`);
|
|
6917
7073
|
console.log(`
|
|
6918
|
-
${
|
|
7074
|
+
${BOLD8}Aggregate fields${RESET14}`);
|
|
6919
7075
|
for (const field of report.aggregateFields) {
|
|
6920
7076
|
console.log(` - ${field}`);
|
|
6921
7077
|
}
|
|
6922
7078
|
console.log(`
|
|
6923
|
-
${
|
|
7079
|
+
${BOLD8}Never collected${RESET14}`);
|
|
6924
7080
|
for (const field of report.neverCollected) {
|
|
6925
7081
|
console.log(` - ${field}`);
|
|
6926
7082
|
}
|
|
6927
7083
|
console.log(`
|
|
6928
|
-
${
|
|
6929
|
-
console.log(`${
|
|
7084
|
+
${DIM14}${report.controls.optOut}${RESET14}`);
|
|
7085
|
+
console.log(`${DIM14}${report.controls.link}${RESET14}`);
|
|
6930
7086
|
}
|
|
6931
7087
|
async function linkTelemetryIdentity(projectRoot, options) {
|
|
6932
7088
|
if (options.enable && !isOptedIn(projectRoot)) {
|
|
@@ -6968,13 +7124,13 @@ async function linkTelemetryIdentity(projectRoot, options) {
|
|
|
6968
7124
|
throw new Error(body2?.error ?? `Telemetry link failed with HTTP ${response.status}.`);
|
|
6969
7125
|
}
|
|
6970
7126
|
const body = await response.json().catch(() => ({ linked: 0 }));
|
|
6971
|
-
console.log(`${
|
|
7127
|
+
console.log(`${GREEN14}Telemetry identity linked.${RESET14}`);
|
|
6972
7128
|
console.log(` Linked: ${body.linked ?? 0}`);
|
|
6973
|
-
console.log(` Install ID: ${identity.installId ?? `${
|
|
6974
|
-
console.log(` Project ID: ${identity.projectId ?? `${
|
|
6975
|
-
if (options.org) console.log(` Org: ${CYAN7}${options.org}${
|
|
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}`);
|
|
6976
7132
|
console.log(
|
|
6977
|
-
|
|
7133
|
+
DIM14 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET14
|
|
6978
7134
|
);
|
|
6979
7135
|
}
|
|
6980
7136
|
function parseTelemetryOptions(args) {
|
|
@@ -7012,41 +7168,41 @@ function trimTrailingSlashes(value) {
|
|
|
7012
7168
|
}
|
|
7013
7169
|
|
|
7014
7170
|
// src/commands/theme-switch.ts
|
|
7015
|
-
import { existsSync as
|
|
7016
|
-
import { join as
|
|
7171
|
+
import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "fs";
|
|
7172
|
+
import { join as join29 } from "path";
|
|
7017
7173
|
import { isV4 as isV47 } from "@decantr/essence-spec";
|
|
7018
|
-
var
|
|
7019
|
-
var
|
|
7020
|
-
var
|
|
7021
|
-
var
|
|
7022
|
-
var
|
|
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";
|
|
7023
7179
|
var VALID_THEME_SHAPES = ["sharp", "rounded", "pill"];
|
|
7024
7180
|
var VALID_THEME_MODES = ["light", "dark", "auto"];
|
|
7025
7181
|
async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
7026
7182
|
if (!themeName) {
|
|
7027
7183
|
console.error(
|
|
7028
|
-
`${
|
|
7184
|
+
`${RED12}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET15}`
|
|
7029
7185
|
);
|
|
7030
7186
|
process.exitCode = 1;
|
|
7031
7187
|
return;
|
|
7032
7188
|
}
|
|
7033
|
-
const essencePath =
|
|
7034
|
-
if (!
|
|
7035
|
-
console.error(`${
|
|
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}`);
|
|
7036
7192
|
process.exitCode = 1;
|
|
7037
7193
|
return;
|
|
7038
7194
|
}
|
|
7039
7195
|
let parsed;
|
|
7040
7196
|
try {
|
|
7041
|
-
parsed = JSON.parse(
|
|
7197
|
+
parsed = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
7042
7198
|
} catch (e) {
|
|
7043
|
-
console.error(`${
|
|
7199
|
+
console.error(`${RED12}Could not read essence: ${e.message}${RESET15}`);
|
|
7044
7200
|
process.exitCode = 1;
|
|
7045
7201
|
return;
|
|
7046
7202
|
}
|
|
7047
7203
|
if (!isV47(parsed)) {
|
|
7048
7204
|
console.error(
|
|
7049
|
-
`${
|
|
7205
|
+
`${RED12}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET15}`
|
|
7050
7206
|
);
|
|
7051
7207
|
process.exitCode = 1;
|
|
7052
7208
|
return;
|
|
@@ -7068,14 +7224,14 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7068
7224
|
}
|
|
7069
7225
|
if (shape && !VALID_THEME_SHAPES.includes(shape)) {
|
|
7070
7226
|
console.error(
|
|
7071
|
-
`${
|
|
7227
|
+
`${RED12}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET15}`
|
|
7072
7228
|
);
|
|
7073
7229
|
process.exitCode = 1;
|
|
7074
7230
|
return;
|
|
7075
7231
|
}
|
|
7076
7232
|
if (mode && !VALID_THEME_MODES.includes(mode)) {
|
|
7077
7233
|
console.error(
|
|
7078
|
-
`${
|
|
7234
|
+
`${RED12}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET15}`
|
|
7079
7235
|
);
|
|
7080
7236
|
process.exitCode = 1;
|
|
7081
7237
|
return;
|
|
@@ -7089,7 +7245,7 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7089
7245
|
essence.dna.theme.mode = mode;
|
|
7090
7246
|
}
|
|
7091
7247
|
const registryClient = new RegistryClient({
|
|
7092
|
-
cacheDir:
|
|
7248
|
+
cacheDir: join29(projectRoot, ".decantr", "cache")
|
|
7093
7249
|
});
|
|
7094
7250
|
try {
|
|
7095
7251
|
const themeResult = await registryClient.fetchTheme(themeName);
|
|
@@ -7104,45 +7260,45 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7104
7260
|
}
|
|
7105
7261
|
} catch {
|
|
7106
7262
|
}
|
|
7107
|
-
|
|
7108
|
-
console.log(`${
|
|
7109
|
-
if (shape) console.log(` ${
|
|
7110
|
-
if (mode) console.log(` ${
|
|
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}`);
|
|
7111
7267
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
7112
7268
|
console.log(
|
|
7113
|
-
`${
|
|
7269
|
+
`${GREEN15}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET15}`
|
|
7114
7270
|
);
|
|
7115
|
-
console.log(`${
|
|
7271
|
+
console.log(`${YELLOW11}Guard will flag code using old tokens. Run \`decantr check\`.${RESET15}`);
|
|
7116
7272
|
}
|
|
7117
7273
|
|
|
7118
7274
|
// src/prompts.ts
|
|
7119
7275
|
import { createInterface } from "readline";
|
|
7120
|
-
var
|
|
7121
|
-
var
|
|
7122
|
-
var
|
|
7123
|
-
var
|
|
7124
|
-
var
|
|
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";
|
|
7125
7281
|
var CYAN8 = "\x1B[36m";
|
|
7126
7282
|
function ask(question, defaultValue) {
|
|
7127
7283
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7128
|
-
const prompt = defaultValue ? `${question} ${
|
|
7129
|
-
return new Promise((
|
|
7284
|
+
const prompt = defaultValue ? `${question} ${DIM16}(${defaultValue})${RESET16}: ` : `${question}: `;
|
|
7285
|
+
return new Promise((resolve6) => {
|
|
7130
7286
|
rl.question(prompt, (answer) => {
|
|
7131
7287
|
rl.close();
|
|
7132
|
-
|
|
7288
|
+
resolve6(answer.trim() || defaultValue || "");
|
|
7133
7289
|
});
|
|
7134
7290
|
});
|
|
7135
7291
|
}
|
|
7136
7292
|
async function select(question, options, defaultIdx = 0, allowOther = false) {
|
|
7137
7293
|
console.log(`
|
|
7138
|
-
${
|
|
7294
|
+
${BOLD9}${question}${RESET16}`);
|
|
7139
7295
|
for (let i = 0; i < options.length; i++) {
|
|
7140
|
-
const marker = i === defaultIdx ? `${
|
|
7141
|
-
const desc = options[i].description ? ` ${
|
|
7296
|
+
const marker = i === defaultIdx ? `${GREEN16}>${RESET16}` : " ";
|
|
7297
|
+
const desc = options[i].description ? ` ${DIM16}\u2014 ${options[i].description}${RESET16}` : "";
|
|
7142
7298
|
console.log(` ${marker} ${i + 1}. ${options[i].label}${desc}`);
|
|
7143
7299
|
}
|
|
7144
7300
|
if (allowOther) {
|
|
7145
|
-
console.log(` ${options.length + 1}. ${
|
|
7301
|
+
console.log(` ${options.length + 1}. ${DIM16}other (enter custom value)${RESET16}`);
|
|
7146
7302
|
}
|
|
7147
7303
|
const maxIdx = allowOther ? options.length + 1 : options.length;
|
|
7148
7304
|
const answer = await ask(`Choose (1-${maxIdx})`, String(defaultIdx + 1));
|
|
@@ -7161,11 +7317,11 @@ async function confirm(question, defaultYes = true) {
|
|
|
7161
7317
|
}
|
|
7162
7318
|
function warn(message) {
|
|
7163
7319
|
console.log(`
|
|
7164
|
-
${
|
|
7320
|
+
${YELLOW12} Warning: ${message}${RESET16}`);
|
|
7165
7321
|
}
|
|
7166
7322
|
function showDetection(detected) {
|
|
7167
7323
|
console.log(`
|
|
7168
|
-
${CYAN8}Detected project configuration:${
|
|
7324
|
+
${CYAN8}Detected project configuration:${RESET16}`);
|
|
7169
7325
|
if (detected.framework !== "unknown") {
|
|
7170
7326
|
const version = detected.version ? ` ${detected.version}` : "";
|
|
7171
7327
|
console.log(` Framework: ${detected.framework}${version}`);
|
|
@@ -7174,13 +7330,13 @@ ${CYAN8}Detected project configuration:${RESET15}`);
|
|
|
7174
7330
|
console.log(` Package manager: ${detected.packageManager}`);
|
|
7175
7331
|
}
|
|
7176
7332
|
if (detected.hasTypeScript) {
|
|
7177
|
-
console.log(` TypeScript: ${
|
|
7333
|
+
console.log(` TypeScript: ${GREEN16}yes${RESET16}`);
|
|
7178
7334
|
}
|
|
7179
7335
|
if (detected.hasTailwind) {
|
|
7180
|
-
console.log(` Tailwind CSS: ${
|
|
7336
|
+
console.log(` Tailwind CSS: ${GREEN16}yes${RESET16}`);
|
|
7181
7337
|
}
|
|
7182
7338
|
if (detected.existingEssence) {
|
|
7183
|
-
console.log(` Existing essence: ${
|
|
7339
|
+
console.log(` Existing essence: ${YELLOW12}yes${RESET16}`);
|
|
7184
7340
|
}
|
|
7185
7341
|
}
|
|
7186
7342
|
async function runInteractivePrompts(detected, archetypes, blueprints, themes, workflowSeed) {
|
|
@@ -7255,7 +7411,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes, w
|
|
|
7255
7411
|
warn(`This project appears to be ${detected.framework} but you selected ${target}.`);
|
|
7256
7412
|
const proceed = await confirm("Continue anyway?", false);
|
|
7257
7413
|
if (!proceed) {
|
|
7258
|
-
console.log(`${
|
|
7414
|
+
console.log(`${DIM16}Using detected framework: ${detected.framework}${RESET16}`);
|
|
7259
7415
|
}
|
|
7260
7416
|
}
|
|
7261
7417
|
const guardMode = await select(
|
|
@@ -7380,7 +7536,7 @@ function mergeWithDefaults(flags, detected, workflowSeed) {
|
|
|
7380
7536
|
}
|
|
7381
7537
|
async function runSimplifiedInit(blueprints) {
|
|
7382
7538
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7383
|
-
const question = (q) => new Promise((
|
|
7539
|
+
const question = (q) => new Promise((resolve6) => rl.question(q, resolve6));
|
|
7384
7540
|
console.log("\n? What blueprint would you like to scaffold?\n");
|
|
7385
7541
|
console.log(" 1. Decantr default (recommended)");
|
|
7386
7542
|
console.log(" 2. Search registry...\n");
|
|
@@ -7412,8 +7568,8 @@ async function runSimplifiedInit(blueprints) {
|
|
|
7412
7568
|
}
|
|
7413
7569
|
|
|
7414
7570
|
// src/theme-commands.ts
|
|
7415
|
-
import { existsSync as
|
|
7416
|
-
import { join as
|
|
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";
|
|
7417
7573
|
var REQUIRED_FIELDS = [
|
|
7418
7574
|
"$schema",
|
|
7419
7575
|
"id",
|
|
@@ -7473,20 +7629,20 @@ function validateCustomTheme(theme) {
|
|
|
7473
7629
|
};
|
|
7474
7630
|
}
|
|
7475
7631
|
function createTheme(projectRoot, id, name) {
|
|
7476
|
-
const customThemesDir =
|
|
7477
|
-
const themePath =
|
|
7478
|
-
const howToPath =
|
|
7479
|
-
|
|
7480
|
-
if (
|
|
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)) {
|
|
7481
7637
|
return {
|
|
7482
7638
|
success: false,
|
|
7483
7639
|
error: `Theme "${id}" already exists at ${themePath}`
|
|
7484
7640
|
};
|
|
7485
7641
|
}
|
|
7486
7642
|
const skeleton = getThemeSkeleton(id, name);
|
|
7487
|
-
|
|
7488
|
-
if (!
|
|
7489
|
-
|
|
7643
|
+
writeFileSync18(themePath, JSON.stringify(skeleton, null, 2));
|
|
7644
|
+
if (!existsSync28(howToPath)) {
|
|
7645
|
+
writeFileSync18(howToPath, getHowToThemeDoc());
|
|
7490
7646
|
}
|
|
7491
7647
|
return {
|
|
7492
7648
|
success: true,
|
|
@@ -7494,17 +7650,17 @@ function createTheme(projectRoot, id, name) {
|
|
|
7494
7650
|
};
|
|
7495
7651
|
}
|
|
7496
7652
|
function listCustomThemes(projectRoot) {
|
|
7497
|
-
const customThemesDir =
|
|
7498
|
-
if (!
|
|
7653
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7654
|
+
if (!existsSync28(customThemesDir)) {
|
|
7499
7655
|
return [];
|
|
7500
7656
|
}
|
|
7501
7657
|
const themes = [];
|
|
7502
7658
|
try {
|
|
7503
7659
|
const files = readdirSync7(customThemesDir).filter((f) => f.endsWith(".json"));
|
|
7504
7660
|
for (const file of files) {
|
|
7505
|
-
const filePath =
|
|
7661
|
+
const filePath = join30(customThemesDir, file);
|
|
7506
7662
|
try {
|
|
7507
|
-
const data = JSON.parse(
|
|
7663
|
+
const data = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
7508
7664
|
themes.push({
|
|
7509
7665
|
id: data.id || file.replace(".json", ""),
|
|
7510
7666
|
name: data.name || data.id,
|
|
@@ -7519,8 +7675,8 @@ function listCustomThemes(projectRoot) {
|
|
|
7519
7675
|
return themes;
|
|
7520
7676
|
}
|
|
7521
7677
|
function deleteTheme(projectRoot, id) {
|
|
7522
|
-
const themePath =
|
|
7523
|
-
if (!
|
|
7678
|
+
const themePath = join30(projectRoot, ".decantr", "custom", "themes", `${id}.json`);
|
|
7679
|
+
if (!existsSync28(themePath)) {
|
|
7524
7680
|
return {
|
|
7525
7681
|
success: false,
|
|
7526
7682
|
error: `Theme "${id}" not found at ${themePath}`
|
|
@@ -7537,7 +7693,7 @@ function deleteTheme(projectRoot, id) {
|
|
|
7537
7693
|
}
|
|
7538
7694
|
}
|
|
7539
7695
|
function importTheme(projectRoot, sourcePath) {
|
|
7540
|
-
if (!
|
|
7696
|
+
if (!existsSync28(sourcePath)) {
|
|
7541
7697
|
return {
|
|
7542
7698
|
success: false,
|
|
7543
7699
|
errors: [`Source file not found: ${sourcePath}`]
|
|
@@ -7545,7 +7701,7 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7545
7701
|
}
|
|
7546
7702
|
let theme;
|
|
7547
7703
|
try {
|
|
7548
|
-
theme = JSON.parse(
|
|
7704
|
+
theme = JSON.parse(readFileSync21(sourcePath, "utf-8"));
|
|
7549
7705
|
} catch (e) {
|
|
7550
7706
|
return {
|
|
7551
7707
|
success: false,
|
|
@@ -7561,14 +7717,14 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7561
7717
|
}
|
|
7562
7718
|
theme.source = "custom";
|
|
7563
7719
|
const id = theme.id;
|
|
7564
|
-
const customThemesDir =
|
|
7565
|
-
const destPath =
|
|
7566
|
-
|
|
7567
|
-
const howToPath =
|
|
7568
|
-
if (!
|
|
7569
|
-
|
|
7570
|
-
}
|
|
7571
|
-
|
|
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));
|
|
7572
7728
|
return {
|
|
7573
7729
|
success: true,
|
|
7574
7730
|
path: destPath
|
|
@@ -7576,29 +7732,29 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7576
7732
|
}
|
|
7577
7733
|
|
|
7578
7734
|
// src/index.ts
|
|
7579
|
-
var
|
|
7580
|
-
var
|
|
7581
|
-
var
|
|
7582
|
-
var
|
|
7583
|
-
var
|
|
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";
|
|
7584
7740
|
var CYAN9 = "\x1B[36m";
|
|
7585
|
-
var
|
|
7741
|
+
var YELLOW13 = "\x1B[33m";
|
|
7586
7742
|
function heading2(text) {
|
|
7587
7743
|
return `
|
|
7588
|
-
${
|
|
7744
|
+
${BOLD10}${text}${RESET17}
|
|
7589
7745
|
`;
|
|
7590
7746
|
}
|
|
7591
7747
|
function success3(text) {
|
|
7592
|
-
return `${
|
|
7748
|
+
return `${GREEN17}${text}${RESET17}`;
|
|
7593
7749
|
}
|
|
7594
7750
|
function error2(text) {
|
|
7595
|
-
return `${
|
|
7751
|
+
return `${RED13}${text}${RESET17}`;
|
|
7596
7752
|
}
|
|
7597
7753
|
function dim3(text) {
|
|
7598
|
-
return `${
|
|
7754
|
+
return `${DIM17}${text}${RESET17}`;
|
|
7599
7755
|
}
|
|
7600
7756
|
function cyan3(text) {
|
|
7601
|
-
return `${CYAN9}${text}${
|
|
7757
|
+
return `${CYAN9}${text}${RESET17}`;
|
|
7602
7758
|
}
|
|
7603
7759
|
function formatIntelligenceSummary(intelligence) {
|
|
7604
7760
|
if (!intelligence) {
|
|
@@ -8102,7 +8258,7 @@ function getPublicAPIClient() {
|
|
|
8102
8258
|
});
|
|
8103
8259
|
}
|
|
8104
8260
|
function resolveUserPath(inputPath, cwd = process.cwd()) {
|
|
8105
|
-
return isAbsolute3(inputPath) ? inputPath :
|
|
8261
|
+
return isAbsolute3(inputPath) ? inputPath : resolve5(cwd, inputPath);
|
|
8106
8262
|
}
|
|
8107
8263
|
function extractHostedAssetPaths(indexHtml) {
|
|
8108
8264
|
const assetPaths = /* @__PURE__ */ new Set();
|
|
@@ -8115,18 +8271,18 @@ function extractHostedAssetPaths(indexHtml) {
|
|
|
8115
8271
|
return [...assetPaths];
|
|
8116
8272
|
}
|
|
8117
8273
|
function readHostedDistSnapshot(distPath) {
|
|
8118
|
-
const resolvedDistPath = distPath ? resolveUserPath(distPath) :
|
|
8119
|
-
const indexPath =
|
|
8120
|
-
if (!
|
|
8274
|
+
const resolvedDistPath = distPath ? resolveUserPath(distPath) : join31(process.cwd(), "dist");
|
|
8275
|
+
const indexPath = join31(resolvedDistPath, "index.html");
|
|
8276
|
+
if (!existsSync29(indexPath)) {
|
|
8121
8277
|
return void 0;
|
|
8122
8278
|
}
|
|
8123
|
-
const indexHtml =
|
|
8279
|
+
const indexHtml = readFileSync22(indexPath, "utf-8");
|
|
8124
8280
|
const assetPaths = extractHostedAssetPaths(indexHtml);
|
|
8125
8281
|
const assets = {};
|
|
8126
8282
|
for (const assetPath of assetPaths) {
|
|
8127
|
-
const assetFilePath =
|
|
8128
|
-
if (
|
|
8129
|
-
assets[assetPath] =
|
|
8283
|
+
const assetFilePath = join31(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
|
|
8284
|
+
if (existsSync29(assetFilePath)) {
|
|
8285
|
+
assets[assetPath] = readFileSync22(assetFilePath, "utf-8");
|
|
8130
8286
|
}
|
|
8131
8287
|
}
|
|
8132
8288
|
return {
|
|
@@ -8141,7 +8297,7 @@ function isHostedSourceSnapshotFile(path) {
|
|
|
8141
8297
|
function readHostedSourceSnapshot(sourcePath) {
|
|
8142
8298
|
if (!sourcePath) return void 0;
|
|
8143
8299
|
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
8144
|
-
if (!
|
|
8300
|
+
if (!existsSync29(resolvedSourcePath)) {
|
|
8145
8301
|
return void 0;
|
|
8146
8302
|
}
|
|
8147
8303
|
const files = {};
|
|
@@ -8157,15 +8313,15 @@ function readHostedSourceSnapshot(sourcePath) {
|
|
|
8157
8313
|
const walk = (absoluteDir, relativeDir) => {
|
|
8158
8314
|
for (const entry of readdirSync8(absoluteDir, { withFileTypes: true })) {
|
|
8159
8315
|
if (ignoredDirNames.has(entry.name)) continue;
|
|
8160
|
-
const absolutePath =
|
|
8161
|
-
const relativePath =
|
|
8316
|
+
const absolutePath = join31(absoluteDir, entry.name);
|
|
8317
|
+
const relativePath = join31(relativeDir, entry.name).replace(/\\/g, "/");
|
|
8162
8318
|
if (entry.isDirectory()) {
|
|
8163
8319
|
walk(absolutePath, relativePath);
|
|
8164
8320
|
continue;
|
|
8165
8321
|
}
|
|
8166
8322
|
if (!entry.isFile()) continue;
|
|
8167
8323
|
if (!isHostedSourceSnapshotFile(relativePath)) continue;
|
|
8168
|
-
files[relativePath] =
|
|
8324
|
+
files[relativePath] = readFileSync22(absolutePath, "utf-8");
|
|
8169
8325
|
}
|
|
8170
8326
|
};
|
|
8171
8327
|
walk(resolvedSourcePath, rootPrefix);
|
|
@@ -8349,7 +8505,7 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
8349
8505
|
console.log(` Files written: ${writtenContextPaths.length}`);
|
|
8350
8506
|
}
|
|
8351
8507
|
console.log("");
|
|
8352
|
-
console.log(`${
|
|
8508
|
+
console.log(`${BOLD10}Route Plan:${RESET17}`);
|
|
8353
8509
|
for (const route of typedBundle.scaffold.data.routes) {
|
|
8354
8510
|
const patterns = route.patternIds.length > 0 ? route.patternIds.join(", ") : "none";
|
|
8355
8511
|
const pageLabel = route.sectionId ? `${route.sectionId}/${route.pageId}` : route.pageId;
|
|
@@ -8358,24 +8514,24 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
8358
8514
|
}
|
|
8359
8515
|
async function compileHostedExecutionPackBundle(essencePath, namespace) {
|
|
8360
8516
|
const client = getPublicAPIClient();
|
|
8361
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8362
|
-
if (!
|
|
8517
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8518
|
+
if (!existsSync29(resolvedPath)) {
|
|
8363
8519
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8364
8520
|
}
|
|
8365
|
-
const essence = JSON.parse(
|
|
8521
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8366
8522
|
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
8367
|
-
const contextDir =
|
|
8523
|
+
const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
|
|
8368
8524
|
return { resolvedPath, bundle, contextDir };
|
|
8369
8525
|
}
|
|
8370
8526
|
function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
|
|
8371
|
-
|
|
8527
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8372
8528
|
return writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
8373
8529
|
}
|
|
8374
8530
|
function resolvePagePackIdForRoute(essencePath, route) {
|
|
8375
|
-
if (!
|
|
8531
|
+
if (!existsSync29(essencePath)) {
|
|
8376
8532
|
throw new Error(`Essence file not found at ${essencePath}`);
|
|
8377
8533
|
}
|
|
8378
|
-
const essence = JSON.parse(
|
|
8534
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8379
8535
|
if (!isV48(essence)) {
|
|
8380
8536
|
throw new Error("Route-based pack resolution requires Essence v4.0.0.");
|
|
8381
8537
|
}
|
|
@@ -8390,14 +8546,14 @@ function resolvePagePackIdForRoute(essencePath, route) {
|
|
|
8390
8546
|
}
|
|
8391
8547
|
async function printHostedSelectedExecutionPack(packType, id, essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
8392
8548
|
const client = getPublicAPIClient();
|
|
8393
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8394
|
-
if (!
|
|
8549
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8550
|
+
if (!existsSync29(resolvedPath)) {
|
|
8395
8551
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8396
8552
|
}
|
|
8397
8553
|
if ((packType === "section" || packType === "page" || packType === "mutation") && !id) {
|
|
8398
8554
|
throw new Error(`Pack type "${packType}" requires an id.`);
|
|
8399
8555
|
}
|
|
8400
|
-
const essence = JSON.parse(
|
|
8556
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8401
8557
|
const selected = await client.selectExecutionPack(
|
|
8402
8558
|
{
|
|
8403
8559
|
essence,
|
|
@@ -8408,17 +8564,17 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8408
8564
|
);
|
|
8409
8565
|
let writtenContextDir = null;
|
|
8410
8566
|
if (writeContext) {
|
|
8411
|
-
const contextDir =
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8567
|
+
const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
|
|
8568
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8569
|
+
writeFileSync19(
|
|
8570
|
+
join31(contextDir, "pack-manifest.json"),
|
|
8415
8571
|
JSON.stringify(selected.manifest, null, 2) + "\n"
|
|
8416
8572
|
);
|
|
8417
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);
|
|
8418
8574
|
const markdownFile = manifestEntry?.markdown ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.md`;
|
|
8419
8575
|
const jsonFile = manifestEntry?.json ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.json`;
|
|
8420
|
-
|
|
8421
|
-
|
|
8576
|
+
writeFileSync19(join31(contextDir, markdownFile), selected.pack.renderedMarkdown);
|
|
8577
|
+
writeFileSync19(join31(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
|
|
8422
8578
|
writtenContextDir = contextDir;
|
|
8423
8579
|
}
|
|
8424
8580
|
if (jsonOutput) {
|
|
@@ -8443,20 +8599,20 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8443
8599
|
}
|
|
8444
8600
|
async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
8445
8601
|
const client = getPublicAPIClient();
|
|
8446
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8447
|
-
if (!
|
|
8602
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8603
|
+
if (!existsSync29(resolvedPath)) {
|
|
8448
8604
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8449
8605
|
}
|
|
8450
|
-
const essence = JSON.parse(
|
|
8606
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8451
8607
|
const manifest = await client.getExecutionPackManifest(
|
|
8452
8608
|
essence,
|
|
8453
8609
|
namespace ? { namespace } : void 0
|
|
8454
8610
|
);
|
|
8455
8611
|
let writtenContextDir = null;
|
|
8456
8612
|
if (writeContext) {
|
|
8457
|
-
const contextDir =
|
|
8458
|
-
|
|
8459
|
-
|
|
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");
|
|
8460
8616
|
writtenContextDir = contextDir;
|
|
8461
8617
|
}
|
|
8462
8618
|
if (jsonOutput) {
|
|
@@ -8477,14 +8633,14 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
|
|
|
8477
8633
|
}
|
|
8478
8634
|
}
|
|
8479
8635
|
async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@official") {
|
|
8480
|
-
const contextDir =
|
|
8481
|
-
const reviewPackPath =
|
|
8482
|
-
const manifestPath =
|
|
8483
|
-
if (
|
|
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)) {
|
|
8484
8640
|
return { attempted: false, hydrated: false };
|
|
8485
8641
|
}
|
|
8486
|
-
const essencePath =
|
|
8487
|
-
if (!
|
|
8642
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
8643
|
+
if (!existsSync29(essencePath)) {
|
|
8488
8644
|
return { attempted: false, hydrated: false };
|
|
8489
8645
|
}
|
|
8490
8646
|
const reviewHydration = await hydrateHostedReviewPackIfMissing(projectRoot, namespace);
|
|
@@ -8493,9 +8649,9 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
8493
8649
|
}
|
|
8494
8650
|
try {
|
|
8495
8651
|
const client = getPublicAPIClient();
|
|
8496
|
-
const essence = JSON.parse(
|
|
8652
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8497
8653
|
const bundle = await client.compileExecutionPacks(essence, { namespace });
|
|
8498
|
-
|
|
8654
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8499
8655
|
writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
8500
8656
|
return { attempted: true, hydrated: true, scope: "bundle" };
|
|
8501
8657
|
} catch {
|
|
@@ -8503,19 +8659,19 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
8503
8659
|
}
|
|
8504
8660
|
}
|
|
8505
8661
|
async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@official") {
|
|
8506
|
-
const contextDir =
|
|
8507
|
-
const reviewPackPath =
|
|
8508
|
-
const manifestPath =
|
|
8509
|
-
if (
|
|
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)) {
|
|
8510
8666
|
return { attempted: false, hydrated: false };
|
|
8511
8667
|
}
|
|
8512
|
-
const essencePath =
|
|
8513
|
-
if (!
|
|
8668
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
8669
|
+
if (!existsSync29(essencePath)) {
|
|
8514
8670
|
return { attempted: false, hydrated: false };
|
|
8515
8671
|
}
|
|
8516
8672
|
try {
|
|
8517
8673
|
const client = getPublicAPIClient();
|
|
8518
|
-
const essence = JSON.parse(
|
|
8674
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8519
8675
|
const selected = await client.selectExecutionPack(
|
|
8520
8676
|
{
|
|
8521
8677
|
essence,
|
|
@@ -8523,14 +8679,14 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
8523
8679
|
},
|
|
8524
8680
|
{ namespace }
|
|
8525
8681
|
);
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
8682
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8683
|
+
writeFileSync19(join31(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
|
|
8684
|
+
writeFileSync19(
|
|
8685
|
+
join31(contextDir, "review-pack.json"),
|
|
8530
8686
|
JSON.stringify(selected.pack, null, 2) + "\n"
|
|
8531
8687
|
);
|
|
8532
|
-
if (!
|
|
8533
|
-
|
|
8688
|
+
if (!existsSync29(manifestPath)) {
|
|
8689
|
+
writeFileSync19(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
|
|
8534
8690
|
}
|
|
8535
8691
|
return { attempted: true, hydrated: true, scope: "review" };
|
|
8536
8692
|
} catch {
|
|
@@ -8540,17 +8696,17 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
8540
8696
|
async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false, essencePath, treatmentsPath) {
|
|
8541
8697
|
const client = getPublicAPIClient();
|
|
8542
8698
|
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
8543
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) :
|
|
8544
|
-
const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) :
|
|
8545
|
-
if (!
|
|
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)) {
|
|
8546
8702
|
throw new Error(`Source file not found at ${resolvedSourcePath}`);
|
|
8547
8703
|
}
|
|
8548
|
-
if (!
|
|
8704
|
+
if (!existsSync29(resolvedEssencePath)) {
|
|
8549
8705
|
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
8550
8706
|
}
|
|
8551
|
-
const code =
|
|
8552
|
-
const essence = JSON.parse(
|
|
8553
|
-
const treatmentsCss =
|
|
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;
|
|
8554
8710
|
const report = await client.critiqueFile(
|
|
8555
8711
|
{
|
|
8556
8712
|
essence,
|
|
@@ -8574,11 +8730,11 @@ async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false
|
|
|
8574
8730
|
}
|
|
8575
8731
|
async function printHostedProjectAudit(namespace, jsonOutput = false, essencePath, distPath, sourcesPath) {
|
|
8576
8732
|
const client = getPublicAPIClient();
|
|
8577
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) :
|
|
8578
|
-
if (!
|
|
8733
|
+
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8734
|
+
if (!existsSync29(resolvedEssencePath)) {
|
|
8579
8735
|
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
8580
8736
|
}
|
|
8581
|
-
const essence = JSON.parse(
|
|
8737
|
+
const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
|
|
8582
8738
|
const dist = readHostedDistSnapshot(distPath);
|
|
8583
8739
|
const sources = readHostedSourceSnapshot(sourcesPath);
|
|
8584
8740
|
const report = await client.auditProject(
|
|
@@ -8596,7 +8752,7 @@ async function printHostedProjectAudit(namespace, jsonOutput = false, essencePat
|
|
|
8596
8752
|
console.log(heading2("Hosted Project Audit"));
|
|
8597
8753
|
console.log(` Essence: ${resolvedEssencePath}`);
|
|
8598
8754
|
console.log(
|
|
8599
|
-
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) :
|
|
8755
|
+
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join31(process.cwd(), "dist") : "none"}`
|
|
8600
8756
|
);
|
|
8601
8757
|
console.log(
|
|
8602
8758
|
` Source snapshot: ${sources && sourcesPath ? resolveUserPath(sourcesPath) : "none"}`
|
|
@@ -8625,7 +8781,7 @@ function printBlueprintPortfolioNotice(blueprint) {
|
|
|
8625
8781
|
if (!portfolio) return;
|
|
8626
8782
|
if (portfolio.visibility === "hidden" || portfolio.maturity === "fold-candidate") {
|
|
8627
8783
|
console.log(
|
|
8628
|
-
`${
|
|
8784
|
+
`${YELLOW13} Warning:${RESET17} blueprint "${blueprint.id}" is folded out of public browsing.`
|
|
8629
8785
|
);
|
|
8630
8786
|
if (portfolio.recommended_alternative) {
|
|
8631
8787
|
console.log(
|
|
@@ -8638,7 +8794,7 @@ function printBlueprintPortfolioNotice(blueprint) {
|
|
|
8638
8794
|
}
|
|
8639
8795
|
if (portfolio.visibility === "labs") {
|
|
8640
8796
|
console.log(
|
|
8641
|
-
`${
|
|
8797
|
+
`${YELLOW13} Note:${RESET17} blueprint "${blueprint.id}" is a Labs blueprint; direct scaffolding is supported, but it is not a default recommendation yet.`
|
|
8642
8798
|
);
|
|
8643
8799
|
}
|
|
8644
8800
|
}
|
|
@@ -8660,7 +8816,7 @@ async function cmdSearch(query, type, sort, recommended, intelligenceSource, blu
|
|
|
8660
8816
|
}
|
|
8661
8817
|
console.log(heading2(`${results.length} result(s) for "${query}"`));
|
|
8662
8818
|
for (const r of results) {
|
|
8663
|
-
console.log(` ${cyan3(r.type.padEnd(12))} ${
|
|
8819
|
+
console.log(` ${cyan3(r.type.padEnd(12))} ${BOLD10}${r.slug}${RESET17}`);
|
|
8664
8820
|
console.log(` ${dim3(r.description || "")}`);
|
|
8665
8821
|
const intelligenceSummary = formatIntelligenceSummary(r.intelligence);
|
|
8666
8822
|
if (intelligenceSummary) {
|
|
@@ -8718,21 +8874,21 @@ function findPatternCandidateBySlug(candidates, slug) {
|
|
|
8718
8874
|
function readSuggestCodeContext(projectRoot, route, file) {
|
|
8719
8875
|
const pieces = [];
|
|
8720
8876
|
if (file) {
|
|
8721
|
-
const resolved = isAbsolute3(file) ? file :
|
|
8722
|
-
if (
|
|
8723
|
-
pieces.push(
|
|
8877
|
+
const resolved = isAbsolute3(file) ? file : join31(projectRoot, file);
|
|
8878
|
+
if (existsSync29(resolved)) {
|
|
8879
|
+
pieces.push(readFileSync22(resolved, "utf-8"));
|
|
8724
8880
|
}
|
|
8725
8881
|
}
|
|
8726
8882
|
if (route) {
|
|
8727
|
-
const analysisPath =
|
|
8728
|
-
if (
|
|
8883
|
+
const analysisPath = join31(projectRoot, ".decantr", "analysis.json");
|
|
8884
|
+
if (existsSync29(analysisPath)) {
|
|
8729
8885
|
try {
|
|
8730
|
-
const analysis = JSON.parse(
|
|
8886
|
+
const analysis = JSON.parse(readFileSync22(analysisPath, "utf-8"));
|
|
8731
8887
|
const routeEntry = analysis.routes?.routes?.find((entry) => entry.path === route);
|
|
8732
8888
|
if (routeEntry?.file) {
|
|
8733
|
-
const resolved =
|
|
8734
|
-
if (
|
|
8735
|
-
pieces.push(
|
|
8889
|
+
const resolved = join31(projectRoot, routeEntry.file);
|
|
8890
|
+
if (existsSync29(resolved)) {
|
|
8891
|
+
pieces.push(readFileSync22(resolved, "utf-8"));
|
|
8736
8892
|
}
|
|
8737
8893
|
}
|
|
8738
8894
|
} catch {
|
|
@@ -8818,7 +8974,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8818
8974
|
}
|
|
8819
8975
|
}
|
|
8820
8976
|
const registryClient = new RegistryClient({
|
|
8821
|
-
cacheDir:
|
|
8977
|
+
cacheDir: join31(projectRoot, ".decantr", "cache")
|
|
8822
8978
|
});
|
|
8823
8979
|
const code = options.fromCode || options.file ? readSuggestCodeContext(projectRoot, options.route, options.file) : "";
|
|
8824
8980
|
const localMatches = localPatternMatches(projectRoot, [query, code].filter(Boolean).join("\n"));
|
|
@@ -8854,7 +9010,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8854
9010
|
)
|
|
8855
9011
|
);
|
|
8856
9012
|
if (bridgeMatches.length > 0) {
|
|
8857
|
-
console.log(`${
|
|
9013
|
+
console.log(`${BOLD10}Project-owned style bridge:${RESET17}`);
|
|
8858
9014
|
for (const match of bridgeMatches) {
|
|
8859
9015
|
const hints = [...match.tokenHints, ...match.classHints].slice(0, 3).join(", ");
|
|
8860
9016
|
console.log(` ${cyan3(match.id)} ${match.label}${hints ? ` ${dim3(hints)}` : ""}`);
|
|
@@ -8862,13 +9018,13 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8862
9018
|
console.log("");
|
|
8863
9019
|
}
|
|
8864
9020
|
if (localMatches.length > 0) {
|
|
8865
|
-
console.log(`${
|
|
9021
|
+
console.log(`${BOLD10}Project-owned local law:${RESET17}`);
|
|
8866
9022
|
for (const match of localMatches) {
|
|
8867
9023
|
const details = [match.label, match.role].filter(Boolean).join(" | ");
|
|
8868
9024
|
console.log(` ${cyan3(match.id)}${details ? ` ${dim3(details)}` : ""}`);
|
|
8869
9025
|
}
|
|
8870
9026
|
console.log("");
|
|
8871
|
-
console.log(`${
|
|
9027
|
+
console.log(`${BOLD10}Registry patterns:${RESET17}`);
|
|
8872
9028
|
}
|
|
8873
9029
|
if (matches.length === 0) {
|
|
8874
9030
|
console.log(dim3("No hosted/bundled registry patterns matched this query."));
|
|
@@ -8907,7 +9063,7 @@ async function cmdGet(type, id) {
|
|
|
8907
9063
|
}
|
|
8908
9064
|
const apiType = CONTENT_TYPE_TO_API_CONTENT_TYPE3[type];
|
|
8909
9065
|
const registryClient = new RegistryClient({
|
|
8910
|
-
cacheDir:
|
|
9066
|
+
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
8911
9067
|
});
|
|
8912
9068
|
const result = await registryClient.fetchContentItem(apiType, id);
|
|
8913
9069
|
if (result) {
|
|
@@ -8924,10 +9080,10 @@ async function cmdGet(type, id) {
|
|
|
8924
9080
|
return;
|
|
8925
9081
|
}
|
|
8926
9082
|
async function cmdValidate(path) {
|
|
8927
|
-
const essencePath = path ||
|
|
9083
|
+
const essencePath = path || join31(process.cwd(), "decantr.essence.json");
|
|
8928
9084
|
let raw;
|
|
8929
9085
|
try {
|
|
8930
|
-
raw =
|
|
9086
|
+
raw = readFileSync22(essencePath, "utf-8");
|
|
8931
9087
|
} catch {
|
|
8932
9088
|
console.error(error2(`Could not read ${essencePath}`));
|
|
8933
9089
|
process.exitCode = 1;
|
|
@@ -8942,14 +9098,14 @@ async function cmdValidate(path) {
|
|
|
8942
9098
|
return;
|
|
8943
9099
|
}
|
|
8944
9100
|
const detectedVersion = isV48(essence) ? "v4" : "legacy";
|
|
8945
|
-
console.log(`${
|
|
9101
|
+
console.log(`${DIM17}Detected essence version: ${detectedVersion}${RESET17}`);
|
|
8946
9102
|
const result = validateEssence2(essence);
|
|
8947
9103
|
if (result.valid) {
|
|
8948
9104
|
console.log(success3(`Essence is valid (${detectedVersion}).`));
|
|
8949
9105
|
} else {
|
|
8950
9106
|
console.error(error2("Validation failed:"));
|
|
8951
9107
|
for (const err of result.errors) {
|
|
8952
|
-
console.error(` ${
|
|
9108
|
+
console.error(` ${RED13}${err}${RESET17}`);
|
|
8953
9109
|
}
|
|
8954
9110
|
process.exitCode = 1;
|
|
8955
9111
|
return;
|
|
@@ -8970,9 +9126,9 @@ async function cmdValidate(path) {
|
|
|
8970
9126
|
console.log(heading2("Guard violations:"));
|
|
8971
9127
|
for (const v of violations) {
|
|
8972
9128
|
const vr = v;
|
|
8973
|
-
console.log(` ${
|
|
9129
|
+
console.log(` ${YELLOW13}[${vr.rule}]${RESET17} ${vr.message}`);
|
|
8974
9130
|
if (vr.suggestion) {
|
|
8975
|
-
console.log(` ${
|
|
9131
|
+
console.log(` ${DIM17}Suggestion: ${vr.suggestion}${RESET17}`);
|
|
8976
9132
|
}
|
|
8977
9133
|
}
|
|
8978
9134
|
const hasError = violations.some((v) => v.severity === "error");
|
|
@@ -8994,7 +9150,7 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
|
|
|
8994
9150
|
return;
|
|
8995
9151
|
}
|
|
8996
9152
|
const registryClient = new RegistryClient({
|
|
8997
|
-
cacheDir:
|
|
9153
|
+
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
8998
9154
|
});
|
|
8999
9155
|
const result = await registryClient.fetchContentList(
|
|
9000
9156
|
type,
|
|
@@ -9071,16 +9227,16 @@ function enableCliTelemetry(projectRoot) {
|
|
|
9071
9227
|
optIn(projectRoot);
|
|
9072
9228
|
console.log(
|
|
9073
9229
|
`
|
|
9074
|
-
${CYAN9}Telemetry enabled.${
|
|
9230
|
+
${CYAN9}Telemetry enabled.${RESET17} Decantr will send privacy-filtered CLI product telemetry for this project.`
|
|
9075
9231
|
);
|
|
9076
|
-
console.log(`${
|
|
9232
|
+
console.log(`${DIM17}Set "telemetry": false in .decantr/project.json to opt out.${RESET17}`);
|
|
9077
9233
|
}
|
|
9078
9234
|
function readCliPackageVersion2() {
|
|
9079
|
-
const here =
|
|
9080
|
-
const candidates = [
|
|
9235
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
9236
|
+
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
9081
9237
|
for (const candidate of candidates) {
|
|
9082
9238
|
try {
|
|
9083
|
-
const pkg = JSON.parse(
|
|
9239
|
+
const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
|
|
9084
9240
|
if (pkg.version) return pkg.version;
|
|
9085
9241
|
} catch {
|
|
9086
9242
|
}
|
|
@@ -9091,19 +9247,19 @@ function timestampForFile() {
|
|
|
9091
9247
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9092
9248
|
}
|
|
9093
9249
|
function backupExistingEssence(projectRoot, label) {
|
|
9094
|
-
const essencePath =
|
|
9095
|
-
if (!
|
|
9096
|
-
const backupPath =
|
|
9250
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
9251
|
+
if (!existsSync29(essencePath)) return null;
|
|
9252
|
+
const backupPath = join31(
|
|
9097
9253
|
projectRoot,
|
|
9098
9254
|
`decantr.essence.${label}.${timestampForFile()}.backup.json`
|
|
9099
9255
|
);
|
|
9100
|
-
|
|
9256
|
+
writeFileSync19(backupPath, readFileSync22(essencePath, "utf-8"), "utf-8");
|
|
9101
9257
|
return backupPath;
|
|
9102
9258
|
}
|
|
9103
9259
|
function writeBrownfieldProjectJson(input) {
|
|
9104
|
-
const decantrDir =
|
|
9105
|
-
|
|
9106
|
-
|
|
9260
|
+
const decantrDir = join31(input.projectRoot, ".decantr");
|
|
9261
|
+
mkdirSync16(join31(decantrDir, "context"), { recursive: true });
|
|
9262
|
+
mkdirSync16(join31(decantrDir, "cache"), { recursive: true });
|
|
9107
9263
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9108
9264
|
const projectJson = {
|
|
9109
9265
|
detected: {
|
|
@@ -9144,7 +9300,7 @@ function writeBrownfieldProjectJson(input) {
|
|
|
9144
9300
|
}
|
|
9145
9301
|
}
|
|
9146
9302
|
};
|
|
9147
|
-
|
|
9303
|
+
writeFileSync19(join31(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
|
|
9148
9304
|
}
|
|
9149
9305
|
async function applyAcceptedBrownfieldProposal(input) {
|
|
9150
9306
|
const proposal = readBrownfieldProposal(input.projectRoot);
|
|
@@ -9160,8 +9316,8 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9160
9316
|
process.exitCode = 1;
|
|
9161
9317
|
return;
|
|
9162
9318
|
}
|
|
9163
|
-
const essencePath =
|
|
9164
|
-
const hasEssence =
|
|
9319
|
+
const essencePath = join31(input.projectRoot, "decantr.essence.json");
|
|
9320
|
+
const hasEssence = existsSync29(essencePath);
|
|
9165
9321
|
let essence;
|
|
9166
9322
|
let backupPath = null;
|
|
9167
9323
|
if (input.mode === "accept" && hasEssence) {
|
|
@@ -9175,7 +9331,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9175
9331
|
return;
|
|
9176
9332
|
}
|
|
9177
9333
|
if (input.mode === "merge" && hasEssence) {
|
|
9178
|
-
const existing = JSON.parse(
|
|
9334
|
+
const existing = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
9179
9335
|
if (!isV48(existing)) {
|
|
9180
9336
|
console.log(
|
|
9181
9337
|
error2(
|
|
@@ -9195,7 +9351,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9195
9351
|
error2("Brownfield proposal produced an invalid Decantr essence. No files were changed.")
|
|
9196
9352
|
);
|
|
9197
9353
|
for (const validationError of validation.errors) {
|
|
9198
|
-
console.log(` ${
|
|
9354
|
+
console.log(` ${RED13}${validationError}${RESET17}`);
|
|
9199
9355
|
}
|
|
9200
9356
|
process.exitCode = 1;
|
|
9201
9357
|
return;
|
|
@@ -9212,9 +9368,9 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9212
9368
|
assistantBridge: input.assistantBridge,
|
|
9213
9369
|
mode: input.mode
|
|
9214
9370
|
});
|
|
9215
|
-
|
|
9371
|
+
writeFileSync19(essencePath, JSON.stringify(essence, null, 2) + "\n", "utf-8");
|
|
9216
9372
|
const registryClient = new RegistryClient({
|
|
9217
|
-
cacheDir:
|
|
9373
|
+
cacheDir: join31(input.projectRoot, ".decantr", "cache"),
|
|
9218
9374
|
offline: true,
|
|
9219
9375
|
projectRoot: input.projectRoot
|
|
9220
9376
|
});
|
|
@@ -9309,7 +9465,7 @@ async function cmdInit(args) {
|
|
|
9309
9465
|
console.log(dim3(" Found .decantr/init-seed.json brownfield guidance."));
|
|
9310
9466
|
}
|
|
9311
9467
|
if (detected.existingEssence && !args.existing) {
|
|
9312
|
-
console.log(`${
|
|
9468
|
+
console.log(`${YELLOW13}Warning: decantr.essence.json already exists.${RESET17}`);
|
|
9313
9469
|
const overwrite = await confirm("Overwrite existing configuration?", false);
|
|
9314
9470
|
if (!overwrite) {
|
|
9315
9471
|
console.log(dim3("Cancelled."));
|
|
@@ -9393,7 +9549,7 @@ async function cmdInit(args) {
|
|
|
9393
9549
|
}
|
|
9394
9550
|
}
|
|
9395
9551
|
const registryClient = new RegistryClient({
|
|
9396
|
-
cacheDir:
|
|
9552
|
+
cacheDir: join31(projectRoot, ".decantr", "cache"),
|
|
9397
9553
|
apiUrl: args.registry,
|
|
9398
9554
|
offline: args.offline,
|
|
9399
9555
|
projectRoot
|
|
@@ -9413,7 +9569,7 @@ async function cmdInit(args) {
|
|
|
9413
9569
|
} else if (shouldUseRegistry && !apiAvailable) {
|
|
9414
9570
|
if (!args.blueprint) {
|
|
9415
9571
|
console.log(`
|
|
9416
|
-
${
|
|
9572
|
+
${YELLOW13}You're offline. Scaffolding minimal Decantr project.${RESET17}`);
|
|
9417
9573
|
console.log(
|
|
9418
9574
|
dim3("Run `decantr sync` or `decantr upgrade` when online to pull full registry content.\n")
|
|
9419
9575
|
);
|
|
@@ -9462,7 +9618,7 @@ ${YELLOW12}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
|
|
|
9462
9618
|
return;
|
|
9463
9619
|
}
|
|
9464
9620
|
console.log(`
|
|
9465
|
-
${
|
|
9621
|
+
${YELLOW13}You're offline. Scaffolding Decantr default.${RESET17}`);
|
|
9466
9622
|
console.log(dim3("Run `decantr upgrade` when online, or visit decantr.ai/registry\n"));
|
|
9467
9623
|
selectedBlueprint = "default";
|
|
9468
9624
|
} else if (shouldUseRegistry) {
|
|
@@ -9644,7 +9800,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9644
9800
|
return;
|
|
9645
9801
|
}
|
|
9646
9802
|
console.log(
|
|
9647
|
-
`${
|
|
9803
|
+
`${YELLOW13} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET17}`
|
|
9648
9804
|
);
|
|
9649
9805
|
}
|
|
9650
9806
|
} else if (shouldUseRegistry && options.archetype) {
|
|
@@ -9659,7 +9815,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9659
9815
|
return;
|
|
9660
9816
|
}
|
|
9661
9817
|
console.log(
|
|
9662
|
-
`${
|
|
9818
|
+
`${YELLOW13} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET17}`
|
|
9663
9819
|
);
|
|
9664
9820
|
}
|
|
9665
9821
|
}
|
|
@@ -9676,7 +9832,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9676
9832
|
return;
|
|
9677
9833
|
}
|
|
9678
9834
|
console.log(
|
|
9679
|
-
`${
|
|
9835
|
+
`${YELLOW13} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET17}`
|
|
9680
9836
|
);
|
|
9681
9837
|
}
|
|
9682
9838
|
}
|
|
@@ -9725,7 +9881,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9725
9881
|
if (appliedRuleFiles.length > 0) {
|
|
9726
9882
|
console.log(` ${dim3(`Rule bridge applied: ${appliedRuleFiles.join(", ")}`)}`);
|
|
9727
9883
|
}
|
|
9728
|
-
if (!
|
|
9884
|
+
if (!existsSync29(join31(projectRoot, "package.json"))) {
|
|
9729
9885
|
console.log("");
|
|
9730
9886
|
console.log(
|
|
9731
9887
|
dim3(` Note: ${cyan3("decantr init")} created Decantr contract/context files only.`)
|
|
@@ -9736,7 +9892,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9736
9892
|
)
|
|
9737
9893
|
);
|
|
9738
9894
|
}
|
|
9739
|
-
const hasCompiledPacks =
|
|
9895
|
+
const hasCompiledPacks = existsSync29(join31(projectRoot, ".decantr", "context", "scaffold-pack.md"));
|
|
9740
9896
|
console.log("");
|
|
9741
9897
|
console.log(" Next steps:");
|
|
9742
9898
|
if (hasCompiledPacks) {
|
|
@@ -9776,7 +9932,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9776
9932
|
console.log(` ${cyan3("decantr upgrade")} Update to latest patterns`);
|
|
9777
9933
|
console.log(` ${cyan3("decantr check")} Detect drift issues`);
|
|
9778
9934
|
console.log(` ${cyan3("decantr migrate --to v4")} Migrate older essence files to v4`);
|
|
9779
|
-
const essenceContent =
|
|
9935
|
+
const essenceContent = readFileSync22(result.essencePath, "utf-8");
|
|
9780
9936
|
const essence = JSON.parse(essenceContent);
|
|
9781
9937
|
const validation = validateEssence2(essence);
|
|
9782
9938
|
if (!validation.valid) {
|
|
@@ -9819,7 +9975,7 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
9819
9975
|
};
|
|
9820
9976
|
const curatedPrompt = generateCuratedPrompt(promptCtx);
|
|
9821
9977
|
console.log("");
|
|
9822
|
-
console.log(`${
|
|
9978
|
+
console.log(`${BOLD10}Prompt for your AI assistant:${RESET17}`);
|
|
9823
9979
|
console.log(dim3("\u2500".repeat(50)));
|
|
9824
9980
|
console.log("");
|
|
9825
9981
|
console.log(curatedPrompt);
|
|
@@ -9831,23 +9987,23 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
9831
9987
|
}
|
|
9832
9988
|
}
|
|
9833
9989
|
async function cmdStatus(projectRoot = process.cwd()) {
|
|
9834
|
-
const essencePath =
|
|
9835
|
-
const projectJsonPath =
|
|
9990
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
9991
|
+
const projectJsonPath = join31(projectRoot, ".decantr", "project.json");
|
|
9836
9992
|
console.log(heading2("Decantr Project Status"));
|
|
9837
|
-
if (!
|
|
9838
|
-
console.log(`${
|
|
9993
|
+
if (!existsSync29(essencePath)) {
|
|
9994
|
+
console.log(`${RED13}No decantr.essence.json found.${RESET17}`);
|
|
9839
9995
|
console.log(dim3('Run "decantr init" to create one.'));
|
|
9840
9996
|
return;
|
|
9841
9997
|
}
|
|
9842
9998
|
try {
|
|
9843
|
-
const essence = JSON.parse(
|
|
9999
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
9844
10000
|
const validation = validateEssence2(essence);
|
|
9845
10001
|
const essenceVersion = isV48(essence) ? "v4" : "legacy";
|
|
9846
|
-
console.log(`${
|
|
10002
|
+
console.log(`${BOLD10}Essence:${RESET17}`);
|
|
9847
10003
|
if (validation.valid) {
|
|
9848
|
-
console.log(` ${
|
|
10004
|
+
console.log(` ${GREEN17}Valid${RESET17} (${essenceVersion})`);
|
|
9849
10005
|
} else {
|
|
9850
|
-
console.log(` ${
|
|
10006
|
+
console.log(` ${RED13}Invalid: ${validation.errors.join(", ")}${RESET17}`);
|
|
9851
10007
|
}
|
|
9852
10008
|
if (isV48(essence)) {
|
|
9853
10009
|
const v4 = essence;
|
|
@@ -9855,7 +10011,7 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
9855
10011
|
const flatPages = sections.flatMap((section) => section.pages ?? []);
|
|
9856
10012
|
const resolvedShell = sections.find((section) => section.role === "primary")?.shell || sections[0]?.shell || v4.blueprint.shell || "unknown";
|
|
9857
10013
|
const resolvedFeatures = v4.blueprint.features ?? [];
|
|
9858
|
-
console.log(` ${
|
|
10014
|
+
console.log(` ${BOLD10}DNA:${RESET17}`);
|
|
9859
10015
|
console.log(` Theme: ${v4.dna.theme.id} (${v4.dna.theme.mode})`);
|
|
9860
10016
|
console.log(
|
|
9861
10017
|
` Spacing: ${v4.dna.spacing.density} density, ${v4.dna.spacing.content_gap} gap`
|
|
@@ -9867,60 +10023,60 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
9867
10023
|
);
|
|
9868
10024
|
console.log(` Accessibility: WCAG ${v4.dna.accessibility.wcag_level}`);
|
|
9869
10025
|
console.log(` Personality: ${v4.dna.personality.join(", ")}`);
|
|
9870
|
-
console.log(` ${
|
|
10026
|
+
console.log(` ${BOLD10}Blueprint:${RESET17}`);
|
|
9871
10027
|
console.log(` Shell: ${resolvedShell}`);
|
|
9872
10028
|
console.log(` Pages: ${flatPages.length}`);
|
|
9873
10029
|
console.log(` Sections: ${sections.length}`);
|
|
9874
10030
|
console.log(
|
|
9875
10031
|
` Features: ${resolvedFeatures.length > 0 ? resolvedFeatures.join(", ") : "none"}`
|
|
9876
10032
|
);
|
|
9877
|
-
console.log(` ${
|
|
10033
|
+
console.log(` ${BOLD10}Meta:${RESET17}`);
|
|
9878
10034
|
console.log(` Archetype: ${v4.meta.archetype}`);
|
|
9879
10035
|
console.log(` Target: ${v4.meta.target}`);
|
|
9880
10036
|
console.log(
|
|
9881
10037
|
` Guard: ${v4.meta.guard.mode} (DNA: ${v4.meta.guard.dna_enforcement}, Blueprint: ${v4.meta.guard.blueprint_enforcement})`
|
|
9882
10038
|
);
|
|
9883
10039
|
} else {
|
|
9884
|
-
console.log(` ${
|
|
10040
|
+
console.log(` ${YELLOW13}Run \`decantr migrate --to v4\` to upgrade this project.${RESET17}`);
|
|
9885
10041
|
}
|
|
9886
10042
|
} catch (e) {
|
|
9887
|
-
console.log(` ${
|
|
10043
|
+
console.log(` ${RED13}Error reading essence: ${e.message}${RESET17}`);
|
|
9888
10044
|
}
|
|
9889
10045
|
console.log("");
|
|
9890
|
-
console.log(`${
|
|
9891
|
-
if (
|
|
10046
|
+
console.log(`${BOLD10}Sync Status:${RESET17}`);
|
|
10047
|
+
if (existsSync29(projectJsonPath)) {
|
|
9892
10048
|
try {
|
|
9893
|
-
const projectJson = JSON.parse(
|
|
10049
|
+
const projectJson = JSON.parse(readFileSync22(projectJsonPath, "utf-8"));
|
|
9894
10050
|
const syncStatus = projectJson.sync?.status || "unknown";
|
|
9895
10051
|
const lastSync = projectJson.sync?.lastSync || "never";
|
|
9896
10052
|
const source = projectJson.sync?.registrySource || "unknown";
|
|
9897
|
-
const statusColor = syncStatus === "synced" ?
|
|
9898
|
-
console.log(` Status: ${statusColor}${syncStatus}${
|
|
10053
|
+
const statusColor = syncStatus === "synced" ? GREEN17 : YELLOW13;
|
|
10054
|
+
console.log(` Status: ${statusColor}${syncStatus}${RESET17}`);
|
|
9899
10055
|
console.log(` Last sync: ${dim3(lastSync)}`);
|
|
9900
10056
|
console.log(` Source: ${dim3(source)}`);
|
|
9901
10057
|
} catch {
|
|
9902
|
-
console.log(` ${
|
|
10058
|
+
console.log(` ${YELLOW13}Could not read project.json${RESET17}`);
|
|
9903
10059
|
}
|
|
9904
10060
|
} else {
|
|
9905
|
-
console.log(` ${
|
|
10061
|
+
console.log(` ${YELLOW13}No .decantr/project.json found${RESET17}`);
|
|
9906
10062
|
console.log(dim3(' Run "decantr init" to create project files.'));
|
|
9907
10063
|
}
|
|
9908
10064
|
}
|
|
9909
10065
|
async function cmdSync() {
|
|
9910
10066
|
const projectRoot = process.cwd();
|
|
9911
|
-
const cacheDir =
|
|
10067
|
+
const cacheDir = join31(projectRoot, ".decantr", "cache");
|
|
9912
10068
|
console.log(heading2("Syncing registry content..."));
|
|
9913
10069
|
const result = await syncRegistry(cacheDir);
|
|
9914
10070
|
if (result.synced.length > 0) {
|
|
9915
10071
|
console.log(success3("Sync completed successfully."));
|
|
9916
10072
|
console.log(` Synced: ${result.synced.join(", ")}`);
|
|
9917
10073
|
if (result.failed.length > 0) {
|
|
9918
|
-
console.log(` ${
|
|
10074
|
+
console.log(` ${YELLOW13}Failed: ${result.failed.join(", ")}${RESET17}`);
|
|
9919
10075
|
}
|
|
9920
10076
|
} else {
|
|
9921
|
-
console.log(`${
|
|
10077
|
+
console.log(`${YELLOW13}Could not sync: API unavailable${RESET17}`);
|
|
9922
10078
|
if (result.failed.length > 0) {
|
|
9923
|
-
console.log(` ${
|
|
10079
|
+
console.log(` ${YELLOW13}Failed: ${result.failed.join(", ")}${RESET17}`);
|
|
9924
10080
|
}
|
|
9925
10081
|
}
|
|
9926
10082
|
}
|
|
@@ -9930,15 +10086,15 @@ function printVerificationFindings(findings) {
|
|
|
9930
10086
|
return;
|
|
9931
10087
|
}
|
|
9932
10088
|
for (const finding of findings) {
|
|
9933
|
-
const color = finding.severity === "error" ?
|
|
10089
|
+
const color = finding.severity === "error" ? RED13 : finding.severity === "warn" ? YELLOW13 : CYAN9;
|
|
9934
10090
|
console.log(
|
|
9935
|
-
` ${color}[${finding.severity.toUpperCase()}]${
|
|
10091
|
+
` ${color}[${finding.severity.toUpperCase()}]${RESET17} ${finding.category}: ${finding.message}`
|
|
9936
10092
|
);
|
|
9937
10093
|
for (const evidence of finding.evidence) {
|
|
9938
|
-
console.log(` ${
|
|
10094
|
+
console.log(` ${DIM17}${evidence}${RESET17}`);
|
|
9939
10095
|
}
|
|
9940
10096
|
if (finding.suggestedFix) {
|
|
9941
|
-
console.log(` ${
|
|
10097
|
+
console.log(` ${DIM17}Fix: ${finding.suggestedFix}${RESET17}`);
|
|
9942
10098
|
}
|
|
9943
10099
|
}
|
|
9944
10100
|
}
|
|
@@ -9946,10 +10102,10 @@ function printProjectAuditReport(report) {
|
|
|
9946
10102
|
if (report.valid) {
|
|
9947
10103
|
console.log(success3("Project contract is valid."));
|
|
9948
10104
|
} else {
|
|
9949
|
-
console.log(`${
|
|
10105
|
+
console.log(`${RED13}Project audit found blocking issues.${RESET17}`);
|
|
9950
10106
|
}
|
|
9951
10107
|
console.log("");
|
|
9952
|
-
console.log(`${
|
|
10108
|
+
console.log(`${BOLD10}Summary:${RESET17}`);
|
|
9953
10109
|
console.log(` Essence version: ${report.summary.essenceVersion ?? "missing"}`);
|
|
9954
10110
|
console.log(` Pages defined: ${report.summary.pageCount}`);
|
|
9955
10111
|
console.log(` Pack manifest: ${report.summary.packManifestPresent ? "present" : "missing"}`);
|
|
@@ -9978,23 +10134,23 @@ function printProjectAuditReport(report) {
|
|
|
9978
10134
|
` Findings: ${report.summary.errorCount} error(s), ${report.summary.warnCount} warn(s), ${report.summary.infoCount} info`
|
|
9979
10135
|
);
|
|
9980
10136
|
console.log("");
|
|
9981
|
-
console.log(`${
|
|
10137
|
+
console.log(`${BOLD10}Findings:${RESET17}`);
|
|
9982
10138
|
printVerificationFindings(report.findings);
|
|
9983
10139
|
}
|
|
9984
10140
|
function printFileCritiqueReport(report) {
|
|
9985
10141
|
console.log(success3(`Critiqued ${report.file}`));
|
|
9986
10142
|
console.log("");
|
|
9987
|
-
console.log(`${
|
|
10143
|
+
console.log(`${BOLD10}Summary:${RESET17}`);
|
|
9988
10144
|
console.log(` Overall score: ${report.overall}/5`);
|
|
9989
10145
|
console.log(` Focus areas: ${report.focusAreas.join(", ")}`);
|
|
9990
10146
|
console.log(` Review pack: ${report.reviewPack ? "present" : "missing"}`);
|
|
9991
10147
|
console.log("");
|
|
9992
|
-
console.log(`${
|
|
10148
|
+
console.log(`${BOLD10}Scores:${RESET17}`);
|
|
9993
10149
|
for (const score of report.scores) {
|
|
9994
10150
|
console.log(` ${cyan3(score.category.padEnd(20))} ${score.score}/5 ${dim3(score.details)}`);
|
|
9995
10151
|
}
|
|
9996
10152
|
console.log("");
|
|
9997
|
-
console.log(`${
|
|
10153
|
+
console.log(`${BOLD10}Findings:${RESET17}`);
|
|
9998
10154
|
printVerificationFindings(report.findings);
|
|
9999
10155
|
}
|
|
10000
10156
|
async function cmdAudit(filePath) {
|
|
@@ -10035,7 +10191,7 @@ async function cmdAudit(filePath) {
|
|
|
10035
10191
|
console.log(dim3("Project audit completed with advisory findings."));
|
|
10036
10192
|
}
|
|
10037
10193
|
} catch (e) {
|
|
10038
|
-
console.log(`${
|
|
10194
|
+
console.log(`${RED13}Error: ${e.message}${RESET17}`);
|
|
10039
10195
|
process.exitCode = 1;
|
|
10040
10196
|
}
|
|
10041
10197
|
}
|
|
@@ -10043,9 +10199,9 @@ async function cmdTheme(args, projectRoot = process.cwd()) {
|
|
|
10043
10199
|
const subcommand = args[0];
|
|
10044
10200
|
if (!subcommand || subcommand === "help") {
|
|
10045
10201
|
console.log(`
|
|
10046
|
-
${
|
|
10202
|
+
${BOLD10}decantr theme${RESET17} \u2014 Manage custom themes
|
|
10047
10203
|
|
|
10048
|
-
${
|
|
10204
|
+
${BOLD10}Commands:${RESET17}
|
|
10049
10205
|
${cyan3("create")} <name> Create a new custom theme
|
|
10050
10206
|
${cyan3("create")} <name> --guided Interactive theme creation
|
|
10051
10207
|
${cyan3("list")} List custom themes
|
|
@@ -10053,7 +10209,7 @@ ${BOLD9}Commands:${RESET16}
|
|
|
10053
10209
|
${cyan3("delete")} <name> Delete a custom theme
|
|
10054
10210
|
${cyan3("import")} <path> Import theme from JSON file
|
|
10055
10211
|
|
|
10056
|
-
${
|
|
10212
|
+
${BOLD10}Examples:${RESET17}
|
|
10057
10213
|
decantr theme create mytheme
|
|
10058
10214
|
decantr theme list
|
|
10059
10215
|
decantr theme validate mytheme
|
|
@@ -10102,21 +10258,21 @@ ${BOLD9}Examples:${RESET16}
|
|
|
10102
10258
|
process.exitCode = 1;
|
|
10103
10259
|
return;
|
|
10104
10260
|
}
|
|
10105
|
-
const themePath =
|
|
10106
|
-
if (!
|
|
10261
|
+
const themePath = join31(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
|
|
10262
|
+
if (!existsSync29(themePath)) {
|
|
10107
10263
|
console.error(error2(`Theme "${name}" not found at ${themePath}`));
|
|
10108
10264
|
process.exitCode = 1;
|
|
10109
10265
|
return;
|
|
10110
10266
|
}
|
|
10111
10267
|
try {
|
|
10112
|
-
const theme = JSON.parse(
|
|
10268
|
+
const theme = JSON.parse(readFileSync22(themePath, "utf-8"));
|
|
10113
10269
|
const result = validateCustomTheme(theme);
|
|
10114
10270
|
if (result.valid) {
|
|
10115
10271
|
console.log(success3(`Custom theme "${name}" is valid`));
|
|
10116
10272
|
} else {
|
|
10117
10273
|
console.error(error2("Validation failed:"));
|
|
10118
10274
|
for (const err of result.errors) {
|
|
10119
|
-
console.error(` ${
|
|
10275
|
+
console.error(` ${RED13}${err}${RESET17}`);
|
|
10120
10276
|
}
|
|
10121
10277
|
process.exitCode = 1;
|
|
10122
10278
|
}
|
|
@@ -10156,7 +10312,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
10156
10312
|
} else {
|
|
10157
10313
|
console.error(error2("Import failed:"));
|
|
10158
10314
|
for (const err of result.errors || []) {
|
|
10159
|
-
console.error(` ${
|
|
10315
|
+
console.error(` ${RED13}${err}${RESET17}`);
|
|
10160
10316
|
}
|
|
10161
10317
|
process.exitCode = 1;
|
|
10162
10318
|
}
|
|
@@ -10241,7 +10397,7 @@ function withProject(command, projectArg) {
|
|
|
10241
10397
|
return projectArg ? `${command} --project ${projectArg}` : command;
|
|
10242
10398
|
}
|
|
10243
10399
|
function displayProjectPath(workspaceInfo, projectPath) {
|
|
10244
|
-
const absolutePath =
|
|
10400
|
+
const absolutePath = join31(workspaceInfo.appRoot, projectPath);
|
|
10245
10401
|
const relativePath = relative6(workspaceInfo.cwd, absolutePath).replace(/\\/g, "/");
|
|
10246
10402
|
if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
|
|
10247
10403
|
return relativePath;
|
|
@@ -10249,7 +10405,7 @@ function displayProjectPath(workspaceInfo, projectPath) {
|
|
|
10249
10405
|
return absolutePath;
|
|
10250
10406
|
}
|
|
10251
10407
|
function projectRelativeGraphPath(projectRoot, filePath) {
|
|
10252
|
-
const relativePath = relative6(projectRoot, isAbsolute3(filePath) ? filePath :
|
|
10408
|
+
const relativePath = relative6(projectRoot, isAbsolute3(filePath) ? filePath : resolve5(filePath));
|
|
10253
10409
|
if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
|
|
10254
10410
|
return relativePath.replace(/\\/g, "/");
|
|
10255
10411
|
}
|
|
@@ -10265,7 +10421,7 @@ function graphSourceNodeIdForTaskFile(projectRoot, snapshot, filePath) {
|
|
|
10265
10421
|
candidates.add(trimmed.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
10266
10422
|
const cwdRelative = projectRelativeGraphPath(projectRoot, trimmed);
|
|
10267
10423
|
if (cwdRelative) candidates.add(cwdRelative);
|
|
10268
|
-
const projectRelative = projectRelativeGraphPath(projectRoot,
|
|
10424
|
+
const projectRelative = projectRelativeGraphPath(projectRoot, join31(projectRoot, trimmed));
|
|
10269
10425
|
if (projectRelative) candidates.add(projectRelative);
|
|
10270
10426
|
for (const candidate of candidates) {
|
|
10271
10427
|
const nodeId = `src:${candidate}`;
|
|
@@ -10319,7 +10475,7 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
|
|
|
10319
10475
|
const noun = commandName === "adopt" ? "Brownfield adoption" : `decantr ${commandName}`;
|
|
10320
10476
|
console.log(error2(`${noun} needs an app path.`));
|
|
10321
10477
|
console.log("");
|
|
10322
|
-
console.log(`${
|
|
10478
|
+
console.log(`${BOLD10}This looks like a monorepo.${RESET17}`);
|
|
10323
10479
|
console.log("Install Decantr at the workspace root, then attach it to one app with --project.");
|
|
10324
10480
|
console.log("");
|
|
10325
10481
|
console.log("App candidates:");
|
|
@@ -10339,11 +10495,11 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
|
|
|
10339
10495
|
function printMonorepoSetupGuidance(workspaceInfo) {
|
|
10340
10496
|
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
10341
10497
|
const attachedProjects = workspaceInfo.appCandidates.filter(
|
|
10342
|
-
(appCandidate) =>
|
|
10498
|
+
(appCandidate) => existsSync29(join31(workspaceInfo.workspaceRoot, appCandidate, "decantr.essence.json"))
|
|
10343
10499
|
);
|
|
10344
10500
|
const firstAttached = attachedProjects[0];
|
|
10345
10501
|
console.log(heading2("Decantr Setup"));
|
|
10346
|
-
console.log(`${
|
|
10502
|
+
console.log(`${BOLD10}This looks like a monorepo.${RESET17}`);
|
|
10347
10503
|
console.log(` Workspace root: ${workspaceInfo.workspaceRoot}`);
|
|
10348
10504
|
console.log("");
|
|
10349
10505
|
if (firstAttached) {
|
|
@@ -10354,7 +10510,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10354
10510
|
console.log(` ${project}`);
|
|
10355
10511
|
}
|
|
10356
10512
|
console.log("");
|
|
10357
|
-
console.log(`${
|
|
10513
|
+
console.log(`${BOLD10}Next:${RESET17}`);
|
|
10358
10514
|
console.log(
|
|
10359
10515
|
` ${cyan3(`decantr doctor --project ${firstAttached}`)} Explain current state and next command`
|
|
10360
10516
|
);
|
|
@@ -10388,7 +10544,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10388
10544
|
console.log(` ${appCandidate}`);
|
|
10389
10545
|
}
|
|
10390
10546
|
console.log("");
|
|
10391
|
-
console.log(`${
|
|
10547
|
+
console.log(`${BOLD10}Start here:${RESET17}`);
|
|
10392
10548
|
console.log(
|
|
10393
10549
|
` ${cyan3("decantr workspace list")} Show attached projects and app candidates`
|
|
10394
10550
|
);
|
|
@@ -10399,7 +10555,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10399
10555
|
` ${cyan3(`decantr codify --from-audit --style-bridge --project ${candidate}`)} Propose project-owned UI law and style bridge`
|
|
10400
10556
|
);
|
|
10401
10557
|
console.log("");
|
|
10402
|
-
console.log(`${
|
|
10558
|
+
console.log(`${BOLD10}Optional visual evidence:${RESET17}`);
|
|
10403
10559
|
console.log(
|
|
10404
10560
|
` ${cyan3(`decantr verify --project ${candidate} --base-url http://localhost:3000 --evidence`)}`
|
|
10405
10561
|
);
|
|
@@ -10407,7 +10563,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10407
10563
|
function resolveWorkflowProject(flags, commandName = "command", options = {}) {
|
|
10408
10564
|
const projectArg = flagString(flags, "project");
|
|
10409
10565
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
10410
|
-
if (projectArg && options.requireExisting !== false && !
|
|
10566
|
+
if (projectArg && options.requireExisting !== false && !existsSync29(workspaceInfo.appRoot)) {
|
|
10411
10567
|
printProjectNotFound(projectArg, commandName);
|
|
10412
10568
|
process.exitCode = 1;
|
|
10413
10569
|
return null;
|
|
@@ -10457,7 +10613,7 @@ function studioCommandForProject(projectArg) {
|
|
|
10457
10613
|
}
|
|
10458
10614
|
function formatWhichCommandFirst(projectArg) {
|
|
10459
10615
|
return [
|
|
10460
|
-
`${
|
|
10616
|
+
`${BOLD10}Which command first?${RESET17}`,
|
|
10461
10617
|
` ${cyan3(withProject("decantr scan", projectArg))} Existing app, read-only preview`,
|
|
10462
10618
|
` ${cyan3(withProject("decantr adopt --yes", projectArg))} Existing app, attach Decantr`,
|
|
10463
10619
|
` ${cyan3("decantr new my-app --blueprint=<slug>")} New runnable app`,
|
|
@@ -10467,19 +10623,19 @@ function formatWhichCommandFirst(projectArg) {
|
|
|
10467
10623
|
function scanSeverityColor(finding) {
|
|
10468
10624
|
if (finding.severity === "success") return success3("ok");
|
|
10469
10625
|
if (finding.severity === "error") return error2("error");
|
|
10470
|
-
if (finding.severity === "warn") return `${
|
|
10626
|
+
if (finding.severity === "warn") return `${YELLOW13}warn${RESET17}`;
|
|
10471
10627
|
return cyan3("info");
|
|
10472
10628
|
}
|
|
10473
10629
|
function formatScanApplicability(status) {
|
|
10474
10630
|
if (status === "strong_fit") return success3("strong fit");
|
|
10475
|
-
if (status === "partial_fit") return `${
|
|
10631
|
+
if (status === "partial_fit") return `${YELLOW13}partial fit${RESET17}`;
|
|
10476
10632
|
if (status === "not_applicable") return dim3("not applicable");
|
|
10477
10633
|
return dim3("unknown");
|
|
10478
10634
|
}
|
|
10479
10635
|
function formatScanGraphPreviewStatus(status) {
|
|
10480
10636
|
if (status === "current") return success3("current");
|
|
10481
|
-
if (status === "stale") return `${
|
|
10482
|
-
if (status === "needs_migration") return `${
|
|
10637
|
+
if (status === "stale") return `${YELLOW13}stale or missing${RESET17}`;
|
|
10638
|
+
if (status === "needs_migration") return `${YELLOW13}needs migration${RESET17}`;
|
|
10483
10639
|
if (status === "not_attached") return dim3("not attached");
|
|
10484
10640
|
return dim3("unavailable");
|
|
10485
10641
|
}
|
|
@@ -10561,7 +10717,7 @@ function buildScanGraphPreview(workspaceInfo, projectArg) {
|
|
|
10561
10717
|
}
|
|
10562
10718
|
function printScanGraphPreview(preview) {
|
|
10563
10719
|
if (!preview) return;
|
|
10564
|
-
console.log(`${
|
|
10720
|
+
console.log(`${BOLD10}Typed Contract Graph${RESET17}`);
|
|
10565
10721
|
console.log(` Status: ${formatScanGraphPreviewStatus(preview.status)}`);
|
|
10566
10722
|
console.log(` Read-only: ${preview.readOnly ? "yes" : "no"}`);
|
|
10567
10723
|
if (preview.snapshot && preview.capsule) {
|
|
@@ -10603,7 +10759,7 @@ function printScanReport(report, projectArg) {
|
|
|
10603
10759
|
console.log(heading2("Decantr Scan"));
|
|
10604
10760
|
console.log(dim3("Read-only Brownfield reconnaissance. No files were written."));
|
|
10605
10761
|
console.log("");
|
|
10606
|
-
console.log(`${
|
|
10762
|
+
console.log(`${BOLD10}Verdict${RESET17}`);
|
|
10607
10763
|
console.log(
|
|
10608
10764
|
` ${formatScanApplicability(report.applicability.status)} ${report.applicability.label}`
|
|
10609
10765
|
);
|
|
@@ -10614,7 +10770,7 @@ function printScanReport(report, projectArg) {
|
|
|
10614
10770
|
console.log(` ${dim3("-")} ${reason}`);
|
|
10615
10771
|
}
|
|
10616
10772
|
console.log("");
|
|
10617
|
-
console.log(`${
|
|
10773
|
+
console.log(`${BOLD10}Project${RESET17}`);
|
|
10618
10774
|
console.log(
|
|
10619
10775
|
` Framework: ${cyan3(report.project.framework)}${report.project.frameworkVersion ? ` ${report.project.frameworkVersion}` : ""}`
|
|
10620
10776
|
);
|
|
@@ -10624,7 +10780,7 @@ function printScanReport(report, projectArg) {
|
|
|
10624
10780
|
console.log(` Decantr: ${report.project.hasDecantr ? "present" : "not attached"}`);
|
|
10625
10781
|
console.log("");
|
|
10626
10782
|
printScanGraphPreview(report.graphPreview);
|
|
10627
|
-
console.log(`${
|
|
10783
|
+
console.log(`${BOLD10}Routes And Styling${RESET17}`);
|
|
10628
10784
|
console.log(` Routes: ${report.routes.count} (${report.routes.strategy})`);
|
|
10629
10785
|
for (const route of report.routes.items.slice(0, 8)) {
|
|
10630
10786
|
console.log(` ${cyan3(route.path.padEnd(18))} ${dim3(route.file)}`);
|
|
@@ -10640,7 +10796,7 @@ function printScanReport(report, projectArg) {
|
|
|
10640
10796
|
console.log(` Dark mode: ${report.styling.darkMode ? "yes" : "no"}`);
|
|
10641
10797
|
console.log("");
|
|
10642
10798
|
if (report.staticHosting.githubPagesLikely || report.pagesProbe) {
|
|
10643
|
-
console.log(`${
|
|
10799
|
+
console.log(`${BOLD10}Published Surface${RESET17}`);
|
|
10644
10800
|
console.log(
|
|
10645
10801
|
` GitHub Pages: ${report.staticHosting.githubPagesLikely ? "likely" : "not detected"}`
|
|
10646
10802
|
);
|
|
@@ -10649,7 +10805,7 @@ function printScanReport(report, projectArg) {
|
|
|
10649
10805
|
}
|
|
10650
10806
|
if (report.pagesProbe?.checked) {
|
|
10651
10807
|
console.log(
|
|
10652
|
-
` HTTP probe: ${report.pagesProbe.reachable ? success3("reachable") : `${
|
|
10808
|
+
` HTTP probe: ${report.pagesProbe.reachable ? success3("reachable") : `${YELLOW13}unreachable${RESET17}`} ${report.pagesProbe.status ?? ""}`
|
|
10653
10809
|
);
|
|
10654
10810
|
if (report.pagesProbe.title) console.log(` Title: ${report.pagesProbe.title}`);
|
|
10655
10811
|
}
|
|
@@ -10658,14 +10814,14 @@ function printScanReport(report, projectArg) {
|
|
|
10658
10814
|
}
|
|
10659
10815
|
console.log("");
|
|
10660
10816
|
}
|
|
10661
|
-
console.log(`${
|
|
10817
|
+
console.log(`${BOLD10}Findings${RESET17}`);
|
|
10662
10818
|
for (const finding of report.findings.slice(0, 8)) {
|
|
10663
10819
|
console.log(` [${scanSeverityColor(finding)}] ${finding.title}`);
|
|
10664
10820
|
console.log(` ${finding.message}`);
|
|
10665
10821
|
if (finding.recommendation) console.log(` ${dim3(finding.recommendation)}`);
|
|
10666
10822
|
}
|
|
10667
10823
|
console.log("");
|
|
10668
|
-
console.log(`${
|
|
10824
|
+
console.log(`${BOLD10}Next Commands${RESET17}`);
|
|
10669
10825
|
for (const command of report.recommendedCommands) {
|
|
10670
10826
|
console.log(` ${cyan3(command)}`);
|
|
10671
10827
|
}
|
|
@@ -10724,11 +10880,11 @@ async function cmdSetupWorkflow(args) {
|
|
|
10724
10880
|
console.log(` Detected: ${formatDetection(detected)}`);
|
|
10725
10881
|
console.log("");
|
|
10726
10882
|
if (detected.existingEssence) {
|
|
10727
|
-
const hasLocalPatterns =
|
|
10728
|
-
const hasLocalRules =
|
|
10729
|
-
const hasStyleBridge =
|
|
10883
|
+
const hasLocalPatterns = existsSync29(localPatternsPath(workspaceInfo.appRoot));
|
|
10884
|
+
const hasLocalRules = existsSync29(localRulesPath(workspaceInfo.appRoot));
|
|
10885
|
+
const hasStyleBridge = existsSync29(styleBridgePath(workspaceInfo.appRoot));
|
|
10730
10886
|
const verifyCommand = hasLocalPatterns || hasLocalRules ? "decantr verify --brownfield --local-patterns" : "decantr verify --brownfield";
|
|
10731
|
-
console.log(`${
|
|
10887
|
+
console.log(`${BOLD10}Recommended path:${RESET17} maintain an attached Decantr project`);
|
|
10732
10888
|
console.log(
|
|
10733
10889
|
` ${cyan3(withProject("decantr doctor", projectArg))} Explain current state and next command`
|
|
10734
10890
|
);
|
|
@@ -10750,7 +10906,7 @@ async function cmdSetupWorkflow(args) {
|
|
|
10750
10906
|
return;
|
|
10751
10907
|
}
|
|
10752
10908
|
if (hasFootprint) {
|
|
10753
|
-
console.log(`${
|
|
10909
|
+
console.log(`${BOLD10}Recommended path:${RESET17} brownfield adoption`);
|
|
10754
10910
|
console.log(
|
|
10755
10911
|
` ${cyan3(withProject("decantr adopt --yes", projectArg))} Analyze, attach, and verify`
|
|
10756
10912
|
);
|
|
@@ -10758,13 +10914,13 @@ async function cmdSetupWorkflow(args) {
|
|
|
10758
10914
|
` ${cyan3(withProject("decantr codify --from-audit --style-bridge", projectArg))} Propose local UI law and style bridge`
|
|
10759
10915
|
);
|
|
10760
10916
|
console.log("");
|
|
10761
|
-
console.log(`${
|
|
10917
|
+
console.log(`${BOLD10}Optional visual evidence after the app is running:${RESET17}`);
|
|
10762
10918
|
console.log(
|
|
10763
10919
|
` ${cyan3(withProject("decantr verify --base-url http://localhost:3000 --evidence", projectArg))}`
|
|
10764
10920
|
);
|
|
10765
10921
|
return;
|
|
10766
10922
|
}
|
|
10767
|
-
console.log(`${
|
|
10923
|
+
console.log(`${BOLD10}Recommended path:${RESET17} greenfield start`);
|
|
10768
10924
|
console.log(` ${cyan3("decantr new my-app --blueprint=<slug>")}`);
|
|
10769
10925
|
console.log(` ${cyan3("decantr init --workflow=greenfield --adoption=contract-only")}`);
|
|
10770
10926
|
}
|
|
@@ -10814,7 +10970,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10814
10970
|
const hydratePacks = flagBoolean(flags, "packs", true) && !flagBoolean(flags, "skip-packs") && !flagBoolean(flags, "offline") && process.env.DECANTR_OFFLINE !== "true";
|
|
10815
10971
|
const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
|
|
10816
10972
|
const assistantBridge = flagString(flags, "assistant-bridge");
|
|
10817
|
-
const hasEssence =
|
|
10973
|
+
const hasEssence = existsSync29(join31(projectRoot, "decantr.essence.json"));
|
|
10818
10974
|
const proposalFlag = flagBoolean(flags, "replace-essence") ? "--replace-essence" : flagBoolean(flags, "merge-proposal") || hasEssence ? "--merge-proposal" : "--accept-proposal";
|
|
10819
10975
|
const steps = [
|
|
10820
10976
|
"analyze current app and write .decantr/brownfield intelligence",
|
|
@@ -10863,7 +11019,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10863
11019
|
if (hydratePacks) {
|
|
10864
11020
|
try {
|
|
10865
11021
|
const { bundle, contextDir } = await compileHostedExecutionPackBundle(
|
|
10866
|
-
|
|
11022
|
+
join31(projectRoot, "decantr.essence.json")
|
|
10867
11023
|
);
|
|
10868
11024
|
const written = writeHostedExecutionPackContextArtifacts(
|
|
10869
11025
|
contextDir,
|
|
@@ -10875,7 +11031,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10875
11031
|
)
|
|
10876
11032
|
);
|
|
10877
11033
|
} catch (e) {
|
|
10878
|
-
console.log(`${
|
|
11034
|
+
console.log(`${YELLOW13}Pack hydration skipped:${RESET17} ${e.message}`);
|
|
10879
11035
|
console.log(
|
|
10880
11036
|
dim3(
|
|
10881
11037
|
`Run ${compilePacksCommandForProject(projectArg)} after adoption if you want hosted page/review packs.`
|
|
@@ -10888,7 +11044,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10888
11044
|
await cmdGraph(projectRoot, { displayRoot: process.cwd() });
|
|
10889
11045
|
if (process.exitCode && process.exitCode !== 0) return;
|
|
10890
11046
|
if (runVerify) {
|
|
10891
|
-
const { cmdHealth } = await import("./health-
|
|
11047
|
+
const { cmdHealth } = await import("./health-RKUKPG72.js");
|
|
10892
11048
|
await cmdHealth(projectRoot, {
|
|
10893
11049
|
browser: runBrowser,
|
|
10894
11050
|
browserBaseUrl: baseUrl,
|
|
@@ -10904,7 +11060,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10904
11060
|
await cmdCi(ciArgs, process.cwd());
|
|
10905
11061
|
}
|
|
10906
11062
|
console.log("");
|
|
10907
|
-
console.log(`${
|
|
11063
|
+
console.log(`${BOLD10}Brownfield operating loop:${RESET17}`);
|
|
10908
11064
|
console.log(
|
|
10909
11065
|
` ${cyan3(withProject("decantr codify --from-audit --style-bridge", projectArg))} Propose project-owned UI law and style bridge`
|
|
10910
11066
|
);
|
|
@@ -10962,7 +11118,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10962
11118
|
return;
|
|
10963
11119
|
}
|
|
10964
11120
|
if (workspaceMode) {
|
|
10965
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
11121
|
+
const { cmdWorkspace } = await import("./workspace-RJCFPVBL.js");
|
|
10966
11122
|
await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
|
|
10967
11123
|
return;
|
|
10968
11124
|
}
|
|
@@ -10995,7 +11151,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10995
11151
|
}
|
|
10996
11152
|
let guardExitCode;
|
|
10997
11153
|
if (brownfield) {
|
|
10998
|
-
const { cmdHeal, collectCheckIssues } = await import("./heal-
|
|
11154
|
+
const { cmdHeal, collectCheckIssues } = await import("./heal-YXWB6LTI.js");
|
|
10999
11155
|
if (quietOutput) {
|
|
11000
11156
|
const result = collectCheckIssues(workspaceInfo.appRoot, { brownfield: true });
|
|
11001
11157
|
guardExitCode = result.issues.some((issue) => issue.type === "error") ? 1 : void 0;
|
|
@@ -11005,7 +11161,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11005
11161
|
process.exitCode = void 0;
|
|
11006
11162
|
}
|
|
11007
11163
|
}
|
|
11008
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
11164
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-RKUKPG72.js");
|
|
11009
11165
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
|
|
11010
11166
|
if (localPatterns) {
|
|
11011
11167
|
const validation = validateLocalLaw(workspaceInfo.appRoot);
|
|
@@ -11013,7 +11169,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11013
11169
|
if (!quietOutput) {
|
|
11014
11170
|
console.log("");
|
|
11015
11171
|
console.log(
|
|
11016
|
-
`${
|
|
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))}.`
|
|
11017
11173
|
);
|
|
11018
11174
|
}
|
|
11019
11175
|
process.exitCode = process.exitCode || 1;
|
|
@@ -11024,23 +11180,23 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11024
11180
|
const blockingWarnings = failOn === "warn" ? validation.warnings : [];
|
|
11025
11181
|
if (!quietOutput) {
|
|
11026
11182
|
console.log("");
|
|
11027
|
-
console.log(`${
|
|
11183
|
+
console.log(`${GREEN17}Local pattern pack found:${RESET17} ${validation.patternsPath}`);
|
|
11028
11184
|
if (validation.ruleManifestPresent) {
|
|
11029
|
-
console.log(`${
|
|
11185
|
+
console.log(`${GREEN17}Local rule manifest found:${RESET17} ${validation.rulesPath}`);
|
|
11030
11186
|
console.log(
|
|
11031
|
-
`${
|
|
11187
|
+
`${DIM17}Enforcement: accepted .decantr/rules.json is the Decantr-scanned layer; --fail-on controls whether findings block.${RESET17}`
|
|
11032
11188
|
);
|
|
11033
11189
|
} else {
|
|
11034
11190
|
console.log(
|
|
11035
|
-
`${
|
|
11191
|
+
`${YELLOW13}Local rule manifest missing.${RESET17} Run ${cyan3("decantr codify --from-audit")} to propose .decantr/rules.json.`
|
|
11036
11192
|
);
|
|
11037
11193
|
}
|
|
11038
11194
|
for (const warning of validation.warnings.slice(0, 8)) {
|
|
11039
|
-
console.log(`${
|
|
11195
|
+
console.log(`${YELLOW13}warn${RESET17} ${warning}`);
|
|
11040
11196
|
}
|
|
11041
11197
|
if (validation.findings.length > 0) {
|
|
11042
11198
|
console.log("");
|
|
11043
|
-
console.log(`${
|
|
11199
|
+
console.log(`${BOLD10}Local law findings:${RESET17}`);
|
|
11044
11200
|
for (const finding of validation.findings.slice(0, 20)) {
|
|
11045
11201
|
console.log(
|
|
11046
11202
|
` ${finding.severity.toUpperCase()} ${finding.ruleId} ${finding.file}:${finding.line}:${finding.column} ${finding.message}`
|
|
@@ -11050,7 +11206,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11050
11206
|
console.log(dim3(` ...${validation.findings.length - 20} more finding(s)`));
|
|
11051
11207
|
}
|
|
11052
11208
|
} else if (validation.ruleManifestPresent) {
|
|
11053
|
-
console.log(`${
|
|
11209
|
+
console.log(`${GREEN17}Local rule checks passed.${RESET17}`);
|
|
11054
11210
|
}
|
|
11055
11211
|
}
|
|
11056
11212
|
if (blockingFindings.length > 0 || blockingWarnings.length > 0) {
|
|
@@ -11061,12 +11217,12 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11061
11217
|
const styleBridge = createStyleBridgeTaskSummary(workspaceInfo.appRoot);
|
|
11062
11218
|
if (!quietOutput && styleBridge.path) {
|
|
11063
11219
|
console.log("");
|
|
11064
|
-
console.log(`${
|
|
11220
|
+
console.log(`${GREEN17}Style bridge found:${RESET17} ${styleBridge.path}`);
|
|
11065
11221
|
console.log(
|
|
11066
|
-
`${
|
|
11222
|
+
`${DIM17}${styleBridge.mappingCount} mapping(s), ${styleBridge.stylingApproach ?? "unknown"} styling${styleBridge.themeModes.length > 0 ? `, themes: ${styleBridge.themeModes.join(", ")}` : ""}${RESET17}`
|
|
11067
11223
|
);
|
|
11068
11224
|
console.log(
|
|
11069
|
-
`${
|
|
11225
|
+
`${DIM17}Enforcement: advisory style-intent mapping; pair with accepted local rules, lint, tests, or visual regression when it should block.${RESET17}`
|
|
11070
11226
|
);
|
|
11071
11227
|
}
|
|
11072
11228
|
if (guardExitCode && guardExitCode !== 0 && (!process.exitCode || process.exitCode === 0)) {
|
|
@@ -11074,9 +11230,9 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11074
11230
|
}
|
|
11075
11231
|
}
|
|
11076
11232
|
function readJsonIfPresent(path) {
|
|
11077
|
-
if (!
|
|
11233
|
+
if (!existsSync29(path)) return null;
|
|
11078
11234
|
try {
|
|
11079
|
-
return JSON.parse(
|
|
11235
|
+
return JSON.parse(readFileSync22(path, "utf-8"));
|
|
11080
11236
|
} catch {
|
|
11081
11237
|
return null;
|
|
11082
11238
|
}
|
|
@@ -11228,7 +11384,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11228
11384
|
}
|
|
11229
11385
|
const route = routeInput.startsWith("/") ? routeInput : `/${routeInput}`;
|
|
11230
11386
|
const taskSummary = positional.slice(1).join(" ").trim();
|
|
11231
|
-
const essencePath =
|
|
11387
|
+
const essencePath = join31(workspaceInfo.appRoot, "decantr.essence.json");
|
|
11232
11388
|
const essence = readJsonIfPresent(essencePath);
|
|
11233
11389
|
if (!essence) {
|
|
11234
11390
|
console.error(
|
|
@@ -11252,19 +11408,19 @@ async function cmdTaskWorkflow(args) {
|
|
|
11252
11408
|
}
|
|
11253
11409
|
const section = essence.blueprint.sections.find((entry) => entry.id === target.section);
|
|
11254
11410
|
const page = section?.pages.find((entry) => entry.id === target.page);
|
|
11255
|
-
const contextDir =
|
|
11256
|
-
const manifest = readJsonIfPresent(
|
|
11257
|
-
const projectJson = readJsonIfPresent(
|
|
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"));
|
|
11258
11414
|
const pagePack = manifest?.pages?.find((entry) => entry.id === target.page);
|
|
11259
11415
|
const sectionPack = manifest?.sections?.find((entry) => entry.id === target.section);
|
|
11260
|
-
const visualManifest = readJsonIfPresent(
|
|
11416
|
+
const visualManifest = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
|
|
11261
11417
|
const screenshot = visualManifest?.routes?.find((entry) => entry.route === route)?.screenshot;
|
|
11262
11418
|
const localPatternPackPath = localPatternsPath(workspaceInfo.appRoot);
|
|
11263
11419
|
const localRuleManifestPath = localRulesPath(workspaceInfo.appRoot);
|
|
11264
11420
|
const acceptedStyleBridgePath = styleBridgePath(workspaceInfo.appRoot);
|
|
11265
|
-
const graphDir =
|
|
11266
|
-
const contractCapsulePath =
|
|
11267
|
-
const graphSnapshotPath =
|
|
11421
|
+
const graphDir = join31(workspaceInfo.appRoot, ".decantr", "graph");
|
|
11422
|
+
const contractCapsulePath = join31(graphDir, "contract-capsule.json");
|
|
11423
|
+
const graphSnapshotPath = join31(graphDir, "graph.snapshot.json");
|
|
11268
11424
|
const contractCapsule = readJsonIfPresent(contractCapsulePath);
|
|
11269
11425
|
const graphSnapshot = readJsonIfPresent(graphSnapshotPath);
|
|
11270
11426
|
const routeGraphContext = buildGraphRouteContext(graphSnapshot, route, { task: taskSummary });
|
|
@@ -11307,12 +11463,96 @@ async function cmdTaskWorkflow(args) {
|
|
|
11307
11463
|
projectRoot: workspaceInfo.appRoot,
|
|
11308
11464
|
workflowMode: projectJson?.initialized?.workflowMode ?? null,
|
|
11309
11465
|
adoptionMode: projectJson?.initialized?.adoptionMode ?? null,
|
|
11310
|
-
hasLocalPatterns:
|
|
11311
|
-
hasLocalRules:
|
|
11466
|
+
hasLocalPatterns: existsSync29(localPatternPackPath),
|
|
11467
|
+
hasLocalRules: existsSync29(localRuleManifestPath),
|
|
11312
11468
|
hasPackManifest: Boolean(manifest),
|
|
11313
11469
|
taskSummary,
|
|
11314
|
-
hasStyleBridge:
|
|
11470
|
+
hasStyleBridge: existsSync29(acceptedStyleBridgePath)
|
|
11315
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
|
+
};
|
|
11316
11556
|
const context = {
|
|
11317
11557
|
route,
|
|
11318
11558
|
task: taskSummary || null,
|
|
@@ -11320,18 +11560,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11320
11560
|
page: target.page,
|
|
11321
11561
|
shell: page?.shell ?? section?.shell ?? null,
|
|
11322
11562
|
patterns: routePatterns,
|
|
11323
|
-
read:
|
|
11324
|
-
pagePack ? displayProjectPath(workspaceInfo, join30(".decantr/context", pagePack.markdown)) : null,
|
|
11325
|
-
sectionPack ? displayProjectPath(workspaceInfo, join30(".decantr/context", sectionPack.markdown)) : null,
|
|
11326
|
-
manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join30(".decantr/context", manifest.scaffold.markdown)) : null,
|
|
11327
|
-
displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
|
|
11328
|
-
displayProjectPath(workspaceInfo, "DECANTR.md"),
|
|
11329
|
-
existsSync28(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
|
|
11330
|
-
existsSync28(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null,
|
|
11331
|
-
existsSync28(acceptedStyleBridgePath) ? displayProjectPath(workspaceInfo, ".decantr/style-bridge.json") : null,
|
|
11332
|
-
contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json") : null,
|
|
11333
|
-
routeGraphContext && !contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json") : null
|
|
11334
|
-
].filter(Boolean),
|
|
11563
|
+
read: readTargets,
|
|
11335
11564
|
graph: contractCapsule || graphSnapshot ? {
|
|
11336
11565
|
capsule: contractCapsule ? {
|
|
11337
11566
|
path: displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json"),
|
|
@@ -11374,6 +11603,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11374
11603
|
styleBridge: displayedStyleBridge,
|
|
11375
11604
|
changedFiles: currentChangedFiles,
|
|
11376
11605
|
changedRoutes,
|
|
11606
|
+
loop: taskLoop,
|
|
11377
11607
|
verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
|
|
11378
11608
|
};
|
|
11379
11609
|
if (flagBoolean(flags, "json")) {
|
|
@@ -11387,18 +11617,18 @@ async function cmdTaskWorkflow(args) {
|
|
|
11387
11617
|
if (context.patterns.length > 0) console.log(` Patterns: ${context.patterns.join(", ")}`);
|
|
11388
11618
|
if (taskSummary) console.log(` Task: ${taskSummary}`);
|
|
11389
11619
|
console.log("");
|
|
11390
|
-
console.log(`${
|
|
11620
|
+
console.log(`${BOLD10}Read before editing:${RESET17}`);
|
|
11391
11621
|
for (const path of context.read) {
|
|
11392
11622
|
console.log(` ${cyan3(path)}`);
|
|
11393
11623
|
}
|
|
11394
11624
|
if (context.screenshot) {
|
|
11395
11625
|
console.log("");
|
|
11396
|
-
console.log(`${
|
|
11626
|
+
console.log(`${BOLD10}Visual evidence:${RESET17}`);
|
|
11397
11627
|
console.log(` ${cyan3(context.screenshot)}`);
|
|
11398
11628
|
}
|
|
11399
11629
|
if (context.graph?.capsule || context.graph?.snapshot) {
|
|
11400
11630
|
console.log("");
|
|
11401
|
-
console.log(`${
|
|
11631
|
+
console.log(`${BOLD10}Typed contract graph:${RESET17}`);
|
|
11402
11632
|
if (context.graph.capsule) {
|
|
11403
11633
|
console.log(` Capsule: ${cyan3(context.graph.capsule.path)}`);
|
|
11404
11634
|
if (context.graph.capsule.cacheKey) {
|
|
@@ -11446,18 +11676,18 @@ async function cmdTaskWorkflow(args) {
|
|
|
11446
11676
|
}
|
|
11447
11677
|
}
|
|
11448
11678
|
console.log("");
|
|
11449
|
-
console.log(`${
|
|
11679
|
+
console.log(`${BOLD10}Authority for this task:${RESET17}`);
|
|
11450
11680
|
console.log(` Lane: ${context.authority.lane}`);
|
|
11451
11681
|
console.log(` Source: ${context.authority.sourceAuthority}`);
|
|
11452
11682
|
console.log(` Style: ${context.authority.styleAuthority}`);
|
|
11453
11683
|
console.log(` Active: ${context.authority.activeAuthorities.join(", ")}`);
|
|
11454
11684
|
console.log(` Runtime: ${context.authority.runtimeBoundary}`);
|
|
11455
11685
|
for (const warning of context.authority.warnings) {
|
|
11456
|
-
console.log(` ${
|
|
11686
|
+
console.log(` ${YELLOW13}Boundary:${RESET17} ${warning}`);
|
|
11457
11687
|
}
|
|
11458
11688
|
if (context.localLaw.patternCount > 0 || context.localLaw.ruleCount > 0) {
|
|
11459
11689
|
console.log("");
|
|
11460
|
-
console.log(`${
|
|
11690
|
+
console.log(`${BOLD10}Project-owned local law:${RESET17}`);
|
|
11461
11691
|
if (context.localLaw.patternsPath) {
|
|
11462
11692
|
console.log(
|
|
11463
11693
|
` Patterns: ${cyan3(context.localLaw.patternsPath)} (${context.localLaw.patternCount})`
|
|
@@ -11479,7 +11709,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11479
11709
|
}
|
|
11480
11710
|
if (context.localLaw.behaviorObligations.length > 0) {
|
|
11481
11711
|
console.log("");
|
|
11482
|
-
console.log(`${
|
|
11712
|
+
console.log(`${BOLD10}Behavior obligations:${RESET17}`);
|
|
11483
11713
|
for (const behavior of context.localLaw.behaviorObligations.slice(0, 3)) {
|
|
11484
11714
|
const obligations = behavior.obligations.slice(0, 3).map((obligation) => obligation.label).join("; ");
|
|
11485
11715
|
const reasons = behavior.relevance.reasons.slice(0, 3).join(", ");
|
|
@@ -11496,14 +11726,14 @@ async function cmdTaskWorkflow(args) {
|
|
|
11496
11726
|
}
|
|
11497
11727
|
} else {
|
|
11498
11728
|
console.log("");
|
|
11499
|
-
console.log(`${
|
|
11729
|
+
console.log(`${BOLD10}Project-owned local law:${RESET17}`);
|
|
11500
11730
|
console.log(
|
|
11501
|
-
` ${
|
|
11731
|
+
` ${YELLOW13}Not codified yet.${RESET17} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
|
|
11502
11732
|
);
|
|
11503
11733
|
}
|
|
11504
11734
|
if (context.styleBridge.path) {
|
|
11505
11735
|
console.log("");
|
|
11506
|
-
console.log(`${
|
|
11736
|
+
console.log(`${BOLD10}Project-owned style bridge:${RESET17}`);
|
|
11507
11737
|
console.log(
|
|
11508
11738
|
` Bridge: ${cyan3(context.styleBridge.path)} (${context.styleBridge.mappingCount} mappings, ${context.styleBridge.stylingApproach ?? "unknown"} styling)`
|
|
11509
11739
|
);
|
|
@@ -11520,7 +11750,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11520
11750
|
}
|
|
11521
11751
|
if (context.changedFiles.length > 0) {
|
|
11522
11752
|
console.log("");
|
|
11523
|
-
console.log(`${
|
|
11753
|
+
console.log(`${BOLD10}Changed-file context:${RESET17}`);
|
|
11524
11754
|
for (const file of context.changedFiles.slice(0, 8)) {
|
|
11525
11755
|
console.log(` ${file}`);
|
|
11526
11756
|
}
|
|
@@ -11532,7 +11762,14 @@ async function cmdTaskWorkflow(args) {
|
|
|
11532
11762
|
}
|
|
11533
11763
|
}
|
|
11534
11764
|
console.log("");
|
|
11535
|
-
console.log(`${
|
|
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}`);
|
|
11536
11773
|
console.log(
|
|
11537
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."
|
|
11538
11775
|
);
|
|
@@ -11560,7 +11797,7 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11560
11797
|
const workspaceInfo = resolveWorkflowProject(flags, "codify");
|
|
11561
11798
|
if (!workspaceInfo) return;
|
|
11562
11799
|
if (flagBoolean(flags, "accept")) {
|
|
11563
|
-
if (!
|
|
11800
|
+
if (!existsSync29(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync29(localRulesProposalPath(workspaceInfo.appRoot)) && !existsSync29(styleBridgeProposalPath(workspaceInfo.appRoot))) {
|
|
11564
11801
|
console.error(
|
|
11565
11802
|
error2(
|
|
11566
11803
|
"No codify proposal found. Run `decantr codify --from-audit`, `decantr codify --style-bridge`, or `decantr codify` first."
|
|
@@ -11594,14 +11831,14 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11594
11831
|
}
|
|
11595
11832
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
11596
11833
|
const essence = readJsonIfPresent(
|
|
11597
|
-
|
|
11834
|
+
join31(workspaceInfo.appRoot, "decantr.essence.json")
|
|
11598
11835
|
);
|
|
11599
11836
|
const fromAudit = flagBoolean(flags, "from-audit") || flagBoolean(flags, "discover-local-patterns") || flagBoolean(flags, "codify-local-patterns");
|
|
11600
11837
|
const wantsStyleBridge = flagBoolean(flags, "style-bridge");
|
|
11601
11838
|
const mapPatternSlug = flagString(flags, "map-pattern") ?? flagString(flags, "hosted-pattern");
|
|
11602
11839
|
if (mapPatternSlug) {
|
|
11603
11840
|
const registryClient = new RegistryClient({
|
|
11604
|
-
cacheDir:
|
|
11841
|
+
cacheDir: join31(workspaceInfo.appRoot, ".decantr", "cache")
|
|
11605
11842
|
});
|
|
11606
11843
|
const candidates = await loadPatternDiscoveryCandidates(registryClient);
|
|
11607
11844
|
const candidate = findPatternCandidateBySlug(candidates, mapPatternSlug);
|
|
@@ -11725,15 +11962,16 @@ async function cmdContentWorkflow(args) {
|
|
|
11725
11962
|
}
|
|
11726
11963
|
function cmdHelp() {
|
|
11727
11964
|
console.log(`
|
|
11728
|
-
${
|
|
11965
|
+
${BOLD10}decantr${RESET17} \u2014 AI Frontend Governance for codebases touched by AI agents
|
|
11729
11966
|
|
|
11730
|
-
${
|
|
11967
|
+
${BOLD10}Usage:${RESET17}
|
|
11731
11968
|
decantr setup [--project <path>]
|
|
11732
11969
|
decantr scan [--project <path>] [--json]
|
|
11733
11970
|
decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
|
|
11734
11971
|
decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--no-packs] [--yes]
|
|
11735
11972
|
decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
|
|
11736
11973
|
decantr verify [--project <path>] [--brownfield] [--local-patterns] [health options]
|
|
11974
|
+
decantr resolve [--project <path>] [--json] [--defer <finding-id>] [--mark-advisory <finding-id>]
|
|
11737
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]
|
|
11738
11976
|
decantr ci [--project <path>] [--workspace] [--fail-on error|warn|none]
|
|
11739
11977
|
decantr doctor [--project <path>] [--workspace] [--json]
|
|
@@ -11742,7 +11980,7 @@ ${BOLD9}Usage:${RESET16}
|
|
|
11742
11980
|
|
|
11743
11981
|
${formatWhichCommandFirst()}
|
|
11744
11982
|
|
|
11745
|
-
${
|
|
11983
|
+
${BOLD10}Advanced primitives:${RESET17}
|
|
11746
11984
|
decantr init [options]
|
|
11747
11985
|
decantr analyze
|
|
11748
11986
|
decantr magic <prompt> [--dry-run]
|
|
@@ -11753,6 +11991,7 @@ ${BOLD9}Advanced primitives:${RESET16}
|
|
|
11753
11991
|
decantr check
|
|
11754
11992
|
decantr check --brownfield
|
|
11755
11993
|
decantr sync-drift
|
|
11994
|
+
decantr resolve [--json]
|
|
11756
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]
|
|
11757
11996
|
decantr search <query> [--type <type>] [--sort <recommended|recent|name>] [--recommended] [--source <authored|benchmark|hybrid>]
|
|
11758
11997
|
decantr suggest <query> [--type <type>] [--route <route>] [--file <path>] [--from-code]
|
|
@@ -11787,7 +12026,7 @@ ${BOLD9}Advanced primitives:${RESET16}
|
|
|
11787
12026
|
decantr logout
|
|
11788
12027
|
decantr help
|
|
11789
12028
|
|
|
11790
|
-
${
|
|
12029
|
+
${BOLD10}Init Options:${RESET17}
|
|
11791
12030
|
--blueprint, -b Blueprint ID
|
|
11792
12031
|
--theme Theme ID
|
|
11793
12032
|
--mode Color mode: dark | light | auto
|
|
@@ -11809,13 +12048,14 @@ ${BOLD9}Init Options:${RESET16}
|
|
|
11809
12048
|
--registry Custom registry URL
|
|
11810
12049
|
--telemetry Opt this project into privacy-filtered CLI product telemetry
|
|
11811
12050
|
|
|
11812
|
-
${
|
|
12051
|
+
${BOLD10}Commands:${RESET17}
|
|
11813
12052
|
${cyan3("setup")} Detect project state and recommend the right Decantr workflow
|
|
11814
12053
|
${cyan3("scan")} Read-only Brownfield reconnaissance; no files written
|
|
11815
12054
|
${cyan3("new")} Create a new greenfield workspace and bootstrap the available starter adapter
|
|
11816
12055
|
${cyan3("adopt")} Brownfield one-liner: analyze, attach, verify, and show next steps
|
|
11817
12056
|
${cyan3("task")} Prepare route/task context, local law, behavior obligations, evidence, and changed-file impact for an AI coding assistant
|
|
11818
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
|
|
11819
12059
|
${cyan3("graph")} Build typed Contract graph artifacts and the agent cache capsule
|
|
11820
12060
|
${cyan3("ci")} Non-mutating CI gate and CI integration generator
|
|
11821
12061
|
${cyan3("doctor")} Explain Decantr state, artifact ownership, and the next command
|
|
@@ -11823,7 +12063,7 @@ ${BOLD9}Commands:${RESET16}
|
|
|
11823
12063
|
${cyan3("studio")} Open a local Project Health dashboard backed by the same report
|
|
11824
12064
|
${cyan3("content")} Content-author namespace: check, create, publish
|
|
11825
12065
|
|
|
11826
|
-
${
|
|
12066
|
+
${BOLD10}Advanced commands:${RESET17}
|
|
11827
12067
|
${cyan3("magic")} Greenfield-first intent flow; steers existing apps into analyze + init
|
|
11828
12068
|
${cyan3("init")} Attach Decantr contract/context files to an existing project or empty workspace
|
|
11829
12069
|
${cyan3("status")} Show project status, DNA axioms, and blueprint info
|
|
@@ -11835,6 +12075,7 @@ ${BOLD9}Advanced commands:${RESET16}
|
|
|
11835
12075
|
${cyan3("migrate")} Migrate older essence files to v4 format (with .pre-v4.backup.json backup)
|
|
11836
12076
|
${cyan3("check")} Detect drift issues (validate + guard rules) [--telemetry] [--brownfield]
|
|
11837
12077
|
${cyan3("sync-drift")} Review and resolve drift log entries
|
|
12078
|
+
${cyan3("resolve")} Group source-vs-contract conflicts and print exact resolution actions
|
|
11838
12079
|
${cyan3("graph")} Generate .decantr/graph snapshot, history, manifest, diff, and contract capsule
|
|
11839
12080
|
${cyan3("search")} Search official/community vocabulary
|
|
11840
12081
|
${cyan3("suggest")} Suggest patterns or alternatives for a query
|
|
@@ -11855,7 +12096,7 @@ ${BOLD9}Advanced commands:${RESET16}
|
|
|
11855
12096
|
${cyan3("upgrade")} Check for content updates from registry
|
|
11856
12097
|
${cyan3("help")} Show this help
|
|
11857
12098
|
|
|
11858
|
-
${
|
|
12099
|
+
${BOLD10}Examples:${RESET17}
|
|
11859
12100
|
decantr setup
|
|
11860
12101
|
decantr scan
|
|
11861
12102
|
decantr scan --json
|
|
@@ -11864,6 +12105,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
11864
12105
|
decantr adopt --project apps/web --yes
|
|
11865
12106
|
decantr task /feed "add saved recipe actions"
|
|
11866
12107
|
decantr verify --brownfield --local-patterns
|
|
12108
|
+
decantr resolve
|
|
11867
12109
|
decantr graph --project apps/web
|
|
11868
12110
|
decantr graph --project apps/web --route /feed --task "improve loading" --json
|
|
11869
12111
|
decantr graph --project apps/web --file src/app/page.tsx --impact --json
|
|
@@ -11919,35 +12161,36 @@ ${BOLD9}Examples:${RESET16}
|
|
|
11919
12161
|
decantr registry audit-project --namespace @official --dist dist --sources src
|
|
11920
12162
|
decantr create pattern my-card
|
|
11921
12163
|
|
|
11922
|
-
${
|
|
12164
|
+
${BOLD10}Workflow Model:${RESET17}
|
|
11923
12165
|
${cyan3("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=decantr-css
|
|
11924
12166
|
${cyan3("Greenfield contract")} decantr init --workflow=greenfield --adoption=contract-only
|
|
11925
12167
|
${cyan3("Brownfield adoption")} decantr adopt --yes
|
|
11926
12168
|
${cyan3("Brownfield preview")} decantr scan -> decantr adopt --yes
|
|
11927
12169
|
${cyan3("Brownfield monorepo")} decantr adopt --project apps/web --yes
|
|
11928
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
|
|
11929
12172
|
${cyan3("Typed contract graph")} decantr graph -> agent session loads .decantr/graph/contract-capsule.json
|
|
11930
12173
|
${cyan3("Project-owned law")} decantr codify --from-audit -> edit proposal -> decantr codify --accept
|
|
11931
12174
|
${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
|
|
11932
12175
|
|
|
11933
|
-
${
|
|
12176
|
+
${BOLD10}Bootstrap adapters:${RESET17}
|
|
11934
12177
|
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}, ${cyan3("vanilla-vite")}, ${cyan3("vue-vite")}, ${cyan3("sveltekit")}, ${cyan3("angular")}, ${cyan3("solid-vite")}
|
|
11935
12178
|
Unsupported targets resolve through ${cyan3("generic-web")} contract-only mode until their starter adapters land.
|
|
11936
12179
|
`);
|
|
11937
12180
|
}
|
|
11938
12181
|
function cmdRulesHelp() {
|
|
11939
12182
|
console.log(`
|
|
11940
|
-
${
|
|
12183
|
+
${BOLD10}decantr rules${RESET17} \u2014 Preview or apply assistant bridge snippets
|
|
11941
12184
|
|
|
11942
|
-
${
|
|
12185
|
+
${BOLD10}Usage:${RESET17}
|
|
11943
12186
|
decantr rules preview [--project=<path>]
|
|
11944
12187
|
decantr rules apply [--project=<path>]
|
|
11945
12188
|
|
|
11946
|
-
${
|
|
12189
|
+
${BOLD10}Subcommands:${RESET17}
|
|
11947
12190
|
${cyan3("preview")} Print target-specific Decantr bridge guidance without mutating rule files
|
|
11948
12191
|
${cyan3("apply")} Idempotently write Decantr bridge blocks to supported assistant rule files
|
|
11949
12192
|
|
|
11950
|
-
${
|
|
12193
|
+
${BOLD10}Examples:${RESET17}
|
|
11951
12194
|
decantr rules preview
|
|
11952
12195
|
decantr rules preview --project=apps/web
|
|
11953
12196
|
decantr rules apply --project=apps/web
|
|
@@ -11955,23 +12198,23 @@ ${BOLD9}Examples:${RESET16}
|
|
|
11955
12198
|
}
|
|
11956
12199
|
function cmdScanHelp() {
|
|
11957
12200
|
console.log(`
|
|
11958
|
-
${
|
|
12201
|
+
${BOLD10}decantr scan${RESET17} \u2014 Read-only Brownfield reconnaissance
|
|
11959
12202
|
|
|
11960
|
-
${
|
|
12203
|
+
${BOLD10}Usage:${RESET17}
|
|
11961
12204
|
decantr scan [--project <path>] [--json]
|
|
11962
12205
|
|
|
11963
|
-
${
|
|
12206
|
+
${BOLD10}Options:${RESET17}
|
|
11964
12207
|
--project App path inside a workspace/monorepo
|
|
11965
12208
|
--json Emit the ScanReportV1 JSON to stdout
|
|
11966
12209
|
|
|
11967
|
-
${
|
|
12210
|
+
${BOLD10}Behavior:${RESET17}
|
|
11968
12211
|
Reads local project files, detects frontend framework/routes/styling/static-hosting signals,
|
|
11969
12212
|
and prints a terminal report. It does not write .decantr files, install dependencies,
|
|
11970
12213
|
build the app, execute scripts, upload source, or open pull requests.
|
|
11971
12214
|
|
|
11972
12215
|
${formatWhichCommandFirst()}
|
|
11973
12216
|
|
|
11974
|
-
${
|
|
12217
|
+
${BOLD10}Examples:${RESET17}
|
|
11975
12218
|
decantr scan
|
|
11976
12219
|
decantr scan --project apps/web
|
|
11977
12220
|
decantr scan --json
|
|
@@ -11982,9 +12225,9 @@ function isCommandHelpRequest(args) {
|
|
|
11982
12225
|
}
|
|
11983
12226
|
function cmdHealthHelp() {
|
|
11984
12227
|
console.log(`
|
|
11985
|
-
${
|
|
12228
|
+
${BOLD10}decantr health${RESET17} \u2014 Generate a local Project Health report
|
|
11986
12229
|
|
|
11987
|
-
${
|
|
12230
|
+
${BOLD10}Usage:${RESET17}
|
|
11988
12231
|
decantr health [--format text|json|markdown] [--output <file>]
|
|
11989
12232
|
decantr health --json
|
|
11990
12233
|
decantr health --markdown
|
|
@@ -11997,7 +12240,7 @@ ${BOLD9}Usage:${RESET16}
|
|
|
11997
12240
|
decantr health --since-baseline
|
|
11998
12241
|
decantr health init-ci [legacy alias for decantr ci init]
|
|
11999
12242
|
|
|
12000
|
-
${
|
|
12243
|
+
${BOLD10}Options:${RESET17}
|
|
12001
12244
|
--format Output format: text, json, or markdown
|
|
12002
12245
|
--json Emit JSON report
|
|
12003
12246
|
--markdown Emit markdown report
|
|
@@ -12013,7 +12256,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
12013
12256
|
--since-baseline Compare this run to .decantr/health-baseline.json
|
|
12014
12257
|
--design-tokens Compare against a Figma/Tokens Studio JSON export
|
|
12015
12258
|
|
|
12016
|
-
${
|
|
12259
|
+
${BOLD10}Examples:${RESET17}
|
|
12017
12260
|
decantr health
|
|
12018
12261
|
decantr health --json
|
|
12019
12262
|
decantr health --markdown --output decantr-health.md
|
|
@@ -12027,14 +12270,14 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12027
12270
|
}
|
|
12028
12271
|
function cmdWorkspaceHelp() {
|
|
12029
12272
|
console.log(`
|
|
12030
|
-
${
|
|
12273
|
+
${BOLD10}decantr workspace${RESET17} \u2014 Inspect Decantr projects and app candidates across a monorepo
|
|
12031
12274
|
|
|
12032
|
-
${
|
|
12275
|
+
${BOLD10}Usage:${RESET17}
|
|
12033
12276
|
decantr workspace list [--json]
|
|
12034
12277
|
decantr workspace health [--json|--markdown] [--output <file>]
|
|
12035
12278
|
decantr workspace health --changed --since origin/main
|
|
12036
12279
|
|
|
12037
|
-
${
|
|
12280
|
+
${BOLD10}Examples:${RESET17}
|
|
12038
12281
|
decantr workspace list
|
|
12039
12282
|
decantr adopt --project apps/web --yes
|
|
12040
12283
|
decantr workspace health
|
|
@@ -12044,16 +12287,16 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12044
12287
|
}
|
|
12045
12288
|
function cmdContentHealthHelp() {
|
|
12046
12289
|
console.log(`
|
|
12047
|
-
${
|
|
12290
|
+
${BOLD10}decantr content-health${RESET17} \u2014 Generate a local official-vocabulary health report
|
|
12048
12291
|
|
|
12049
|
-
${
|
|
12292
|
+
${BOLD10}Usage:${RESET17}
|
|
12050
12293
|
decantr content-health [--format text|json|markdown] [--output <file>]
|
|
12051
12294
|
decantr content-health --json
|
|
12052
12295
|
decantr content-health --markdown
|
|
12053
12296
|
decantr content-health --ci [--fail-on error|warn|none]
|
|
12054
12297
|
decantr content-health --prompt <finding-id>
|
|
12055
12298
|
|
|
12056
|
-
${
|
|
12299
|
+
${BOLD10}Options:${RESET17}
|
|
12057
12300
|
--format Output format: text, json, or markdown
|
|
12058
12301
|
--json Emit JSON report
|
|
12059
12302
|
--markdown Emit markdown report
|
|
@@ -12062,7 +12305,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
12062
12305
|
--fail-on CI threshold: error, warn, or none
|
|
12063
12306
|
--prompt Print an AI-ready remediation prompt for a finding
|
|
12064
12307
|
|
|
12065
|
-
${
|
|
12308
|
+
${BOLD10}Examples:${RESET17}
|
|
12066
12309
|
decantr content-health
|
|
12067
12310
|
decantr content-health --json
|
|
12068
12311
|
decantr content-health --markdown --output content-health.md
|
|
@@ -12071,23 +12314,29 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12071
12314
|
}
|
|
12072
12315
|
function cmdStudioHelp() {
|
|
12073
12316
|
console.log(`
|
|
12074
|
-
${
|
|
12317
|
+
${BOLD10}decantr studio${RESET17} \u2014 Run a local Project Health dashboard
|
|
12075
12318
|
|
|
12076
|
-
${
|
|
12319
|
+
${BOLD10}Usage:${RESET17}
|
|
12077
12320
|
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
|
|
12078
12321
|
|
|
12079
|
-
${
|
|
12322
|
+
${BOLD10}Options:${RESET17}
|
|
12080
12323
|
--port Local port to bind; defaults to 4319
|
|
12081
12324
|
--host Local host to bind; defaults to 127.0.0.1
|
|
12082
12325
|
--report Serve a read-only Project Health JSON artifact instead of scanning the current project
|
|
12083
12326
|
--workspace Serve a monorepo workspace health dashboard
|
|
12084
12327
|
|
|
12085
|
-
${
|
|
12328
|
+
${BOLD10}Endpoints:${RESET17}
|
|
12086
12329
|
GET /
|
|
12087
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
|
|
12088
12337
|
POST /api/refresh
|
|
12089
12338
|
|
|
12090
|
-
${
|
|
12339
|
+
${BOLD10}Examples:${RESET17}
|
|
12091
12340
|
decantr studio
|
|
12092
12341
|
decantr studio --port 4320
|
|
12093
12342
|
decantr studio --host 127.0.0.1 --port 4319
|
|
@@ -12098,9 +12347,9 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12098
12347
|
}
|
|
12099
12348
|
function cmdRegistryHelp() {
|
|
12100
12349
|
console.log(`
|
|
12101
|
-
${
|
|
12350
|
+
${BOLD10}decantr registry${RESET17} \u2014 Read hosted execution packs and registry intelligence
|
|
12102
12351
|
|
|
12103
|
-
${
|
|
12352
|
+
${BOLD10}Usage:${RESET17}
|
|
12104
12353
|
decantr registry summary [--namespace <namespace>] [--json]
|
|
12105
12354
|
decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
|
|
12106
12355
|
decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
|
|
@@ -12111,9 +12360,9 @@ ${BOLD9}Usage:${RESET16}
|
|
|
12111
12360
|
}
|
|
12112
12361
|
function cmdThemeHelp() {
|
|
12113
12362
|
console.log(`
|
|
12114
|
-
${
|
|
12363
|
+
${BOLD10}decantr theme${RESET17} \u2014 Manage custom themes
|
|
12115
12364
|
|
|
12116
|
-
${
|
|
12365
|
+
${BOLD10}Usage:${RESET17}
|
|
12117
12366
|
decantr theme create <name>
|
|
12118
12367
|
decantr theme create <name> --guided
|
|
12119
12368
|
decantr theme list
|
|
@@ -12124,27 +12373,27 @@ ${BOLD9}Usage:${RESET16}
|
|
|
12124
12373
|
}
|
|
12125
12374
|
function cmdSetupHelp() {
|
|
12126
12375
|
console.log(`
|
|
12127
|
-
${
|
|
12376
|
+
${BOLD10}decantr setup${RESET17} \u2014 Detect the project state and recommend the right Decantr path
|
|
12128
12377
|
|
|
12129
|
-
${
|
|
12378
|
+
${BOLD10}Usage:${RESET17}
|
|
12130
12379
|
decantr setup [--project <path>]
|
|
12131
12380
|
|
|
12132
12381
|
${formatWhichCommandFirst()}
|
|
12133
12382
|
|
|
12134
|
-
${
|
|
12383
|
+
${BOLD10}Examples:${RESET17}
|
|
12135
12384
|
decantr setup
|
|
12136
12385
|
decantr setup --project apps/web
|
|
12137
12386
|
`);
|
|
12138
12387
|
}
|
|
12139
12388
|
function cmdAdoptHelp() {
|
|
12140
12389
|
console.log(`
|
|
12141
|
-
${
|
|
12390
|
+
${BOLD10}decantr adopt${RESET17} \u2014 Brownfield one-liner: analyze, attach, hydrate packs, verify, and show the operating loop
|
|
12142
12391
|
|
|
12143
|
-
${
|
|
12392
|
+
${BOLD10}Usage:${RESET17}
|
|
12144
12393
|
decantr adopt [--project <path>] [--yes] [--dry-run] [--no-packs]
|
|
12145
12394
|
decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes] [--no-packs]
|
|
12146
12395
|
|
|
12147
|
-
${
|
|
12396
|
+
${BOLD10}Options:${RESET17}
|
|
12148
12397
|
--project App path inside a workspace/monorepo
|
|
12149
12398
|
--yes, -y Run without confirmation
|
|
12150
12399
|
--dry-run Show the workflow without writing files
|
|
@@ -12159,7 +12408,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
12159
12408
|
--merge-proposal Merge the observed proposal into an existing essence
|
|
12160
12409
|
--replace-essence Replace an existing essence with backup
|
|
12161
12410
|
|
|
12162
|
-
${
|
|
12411
|
+
${BOLD10}Examples:${RESET17}
|
|
12163
12412
|
decantr adopt --yes
|
|
12164
12413
|
decantr adopt --project apps/web --yes
|
|
12165
12414
|
decantr adopt --project apps/web --base-url http://localhost:3000 --evidence --yes
|
|
@@ -12169,16 +12418,16 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12169
12418
|
}
|
|
12170
12419
|
function cmdVerifyHelp() {
|
|
12171
12420
|
console.log(`
|
|
12172
|
-
${
|
|
12421
|
+
${BOLD10}decantr verify${RESET17} \u2014 One reliability command for local work and LLM agent loops
|
|
12173
12422
|
|
|
12174
|
-
${
|
|
12423
|
+
${BOLD10}Usage:${RESET17}
|
|
12175
12424
|
decantr verify [--project <path>] [--brownfield] [--local-patterns]
|
|
12176
12425
|
decantr verify --base-url <url> --evidence
|
|
12177
12426
|
decantr verify --since-baseline
|
|
12178
12427
|
decantr verify --workspace [--changed --since origin/main]
|
|
12179
12428
|
decantr verify init-ci [legacy alias for decantr ci init]
|
|
12180
12429
|
|
|
12181
|
-
${
|
|
12430
|
+
${BOLD10}Examples:${RESET17}
|
|
12182
12431
|
decantr verify
|
|
12183
12432
|
decantr verify --brownfield --local-patterns
|
|
12184
12433
|
decantr verify --brownfield --local-patterns --project apps/web
|
|
@@ -12190,32 +12439,54 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12190
12439
|
}
|
|
12191
12440
|
function cmdTaskHelp() {
|
|
12192
12441
|
console.log(`
|
|
12193
|
-
${
|
|
12442
|
+
${BOLD10}decantr task${RESET17} \u2014 Prepare compact route/task context for an AI coding assistant
|
|
12194
12443
|
|
|
12195
|
-
${
|
|
12444
|
+
${BOLD10}Usage:${RESET17}
|
|
12196
12445
|
decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
|
|
12197
12446
|
|
|
12198
|
-
${
|
|
12447
|
+
${BOLD10}Behavior:${RESET17}
|
|
12199
12448
|
Includes accepted local law and behavior obligations, plus the typed contract capsule path when
|
|
12200
12449
|
.decantr/graph exists. Run decantr graph first when you want graph-backed agent context in
|
|
12201
12450
|
CLI-only workflows.
|
|
12202
12451
|
|
|
12203
|
-
${
|
|
12452
|
+
${BOLD10}Examples:${RESET17}
|
|
12204
12453
|
decantr task /feed "add saved recipe actions"
|
|
12205
12454
|
decantr task /feed "add saved recipe actions" --since origin/main
|
|
12206
12455
|
decantr task /profile --json
|
|
12207
12456
|
`);
|
|
12208
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
|
+
}
|
|
12209
12480
|
function cmdCodifyHelp() {
|
|
12210
12481
|
console.log(`
|
|
12211
|
-
${
|
|
12482
|
+
${BOLD10}decantr codify${RESET17} \u2014 Propose or accept project-owned Brownfield UI law, behavior obligations, and style bridges
|
|
12212
12483
|
|
|
12213
|
-
${
|
|
12484
|
+
${BOLD10}Usage:${RESET17}
|
|
12214
12485
|
decantr codify [--from-audit] [--style-bridge] [--project <path>]
|
|
12215
12486
|
decantr codify --map-pattern <registry-pattern-slug> [--project <path>]
|
|
12216
12487
|
decantr codify --accept [--project <path>]
|
|
12217
12488
|
|
|
12218
|
-
${
|
|
12489
|
+
${BOLD10}Examples:${RESET17}
|
|
12219
12490
|
decantr codify
|
|
12220
12491
|
decantr codify --from-audit
|
|
12221
12492
|
decantr codify --style-bridge
|
|
@@ -12227,14 +12498,14 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12227
12498
|
}
|
|
12228
12499
|
function cmdContentHelp() {
|
|
12229
12500
|
console.log(`
|
|
12230
|
-
${
|
|
12501
|
+
${BOLD10}decantr content${RESET17} \u2014 Content-author namespace for official-vocabulary repositories
|
|
12231
12502
|
|
|
12232
|
-
${
|
|
12503
|
+
${BOLD10}Usage:${RESET17}
|
|
12233
12504
|
decantr content check [content-health options]
|
|
12234
12505
|
decantr content create <type> <name>
|
|
12235
12506
|
decantr content publish <type> <name>
|
|
12236
12507
|
|
|
12237
|
-
${
|
|
12508
|
+
${BOLD10}Examples:${RESET17}
|
|
12238
12509
|
decantr content check --ci --fail-on error
|
|
12239
12510
|
decantr content create pattern my-card
|
|
12240
12511
|
decantr content publish pattern my-card
|
|
@@ -12267,6 +12538,9 @@ function printCommandHelp(command, args) {
|
|
|
12267
12538
|
case "task":
|
|
12268
12539
|
cmdTaskHelp();
|
|
12269
12540
|
return true;
|
|
12541
|
+
case "resolve":
|
|
12542
|
+
cmdResolveHelp();
|
|
12543
|
+
return true;
|
|
12270
12544
|
case "codify":
|
|
12271
12545
|
cmdCodifyHelp();
|
|
12272
12546
|
return true;
|
|
@@ -12308,11 +12582,11 @@ async function main() {
|
|
|
12308
12582
|
}
|
|
12309
12583
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
12310
12584
|
try {
|
|
12311
|
-
const here =
|
|
12312
|
-
const candidates = [
|
|
12585
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
12586
|
+
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
12313
12587
|
for (const candidate of candidates) {
|
|
12314
|
-
if (
|
|
12315
|
-
const pkg = JSON.parse(
|
|
12588
|
+
if (existsSync29(candidate)) {
|
|
12589
|
+
const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
|
|
12316
12590
|
if (pkg.version) {
|
|
12317
12591
|
console.log(pkg.version);
|
|
12318
12592
|
return;
|
|
@@ -12351,6 +12625,16 @@ async function main() {
|
|
|
12351
12625
|
await cmdVerifyWorkflow(args);
|
|
12352
12626
|
break;
|
|
12353
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
|
+
}
|
|
12354
12638
|
case "graph": {
|
|
12355
12639
|
const { flags } = parseLooseArgs(args);
|
|
12356
12640
|
if (!ensureAllowedFlags(
|
|
@@ -12511,10 +12795,10 @@ async function main() {
|
|
|
12511
12795
|
case "heal": {
|
|
12512
12796
|
if (command === "heal") {
|
|
12513
12797
|
console.log(
|
|
12514
|
-
`${
|
|
12798
|
+
`${YELLOW13}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET17}`
|
|
12515
12799
|
);
|
|
12516
12800
|
}
|
|
12517
|
-
const { cmdHeal } = await import("./heal-
|
|
12801
|
+
const { cmdHeal } = await import("./heal-YXWB6LTI.js");
|
|
12518
12802
|
const { flags } = parseLooseArgs(args);
|
|
12519
12803
|
const workspaceInfo = resolveWorkflowProject(flags, "check");
|
|
12520
12804
|
if (!workspaceInfo) break;
|
|
@@ -12539,7 +12823,7 @@ async function main() {
|
|
|
12539
12823
|
const { flags } = parseLooseArgs(args);
|
|
12540
12824
|
const workspaceInfo = resolveWorkflowProject(flags, "health");
|
|
12541
12825
|
if (!workspaceInfo) break;
|
|
12542
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
12826
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-RKUKPG72.js");
|
|
12543
12827
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
|
|
12544
12828
|
} catch (e) {
|
|
12545
12829
|
console.error(error2(e.message));
|
|
@@ -12567,7 +12851,7 @@ async function main() {
|
|
|
12567
12851
|
cmdStudioHelp();
|
|
12568
12852
|
break;
|
|
12569
12853
|
}
|
|
12570
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
12854
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-C2F72QL6.js");
|
|
12571
12855
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
12572
12856
|
} catch (e) {
|
|
12573
12857
|
console.error(error2(e.message));
|
|
@@ -12581,7 +12865,7 @@ async function main() {
|
|
|
12581
12865
|
cmdWorkspaceHelp();
|
|
12582
12866
|
break;
|
|
12583
12867
|
}
|
|
12584
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
12868
|
+
const { cmdWorkspace } = await import("./workspace-RJCFPVBL.js");
|
|
12585
12869
|
await cmdWorkspace(process.cwd(), args);
|
|
12586
12870
|
} catch (e) {
|
|
12587
12871
|
console.error(error2(e.message));
|
|
@@ -12890,7 +13174,7 @@ async function main() {
|
|
|
12890
13174
|
let id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
|
|
12891
13175
|
if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
|
|
12892
13176
|
console.error(
|
|
12893
|
-
`${
|
|
13177
|
+
`${RED13}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET17}`
|
|
12894
13178
|
);
|
|
12895
13179
|
process.exitCode = 1;
|
|
12896
13180
|
break;
|
|
@@ -12900,7 +13184,7 @@ async function main() {
|
|
|
12900
13184
|
break;
|
|
12901
13185
|
}
|
|
12902
13186
|
if (packType === "page" && route && !id) {
|
|
12903
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
13187
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
12904
13188
|
id = resolvePagePackIdForRoute(resolvedPath, route);
|
|
12905
13189
|
}
|
|
12906
13190
|
await printHostedSelectedExecutionPack(
|
|
@@ -12922,7 +13206,7 @@ async function main() {
|
|
|
12922
13206
|
const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
12923
13207
|
if (!sourcePath) {
|
|
12924
13208
|
console.error(
|
|
12925
|
-
`${
|
|
13209
|
+
`${RED13}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET17}`
|
|
12926
13210
|
);
|
|
12927
13211
|
process.exitCode = 1;
|
|
12928
13212
|
break;
|
|
@@ -12947,7 +13231,7 @@ async function main() {
|
|
|
12947
13231
|
await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
|
|
12948
13232
|
} else {
|
|
12949
13233
|
console.error(
|
|
12950
|
-
`${
|
|
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}`
|
|
12951
13235
|
);
|
|
12952
13236
|
process.exitCode = 1;
|
|
12953
13237
|
}
|
|
@@ -13119,7 +13403,7 @@ async function main() {
|
|
|
13119
13403
|
console.error("");
|
|
13120
13404
|
console.error(" Example:");
|
|
13121
13405
|
console.error(
|
|
13122
|
-
` ${CYAN9}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${
|
|
13406
|
+
` ${CYAN9}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${RESET17}`
|
|
13123
13407
|
);
|
|
13124
13408
|
process.exitCode = 1;
|
|
13125
13409
|
break;
|