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