@decantr/cli 3.4.2 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/bin.js +4 -4
- package/dist/{chunk-PQKTJGYL.js → chunk-EUEQMXN5.js} +85 -8
- package/dist/{chunk-BDA6TWV3.js → chunk-MDQSTAP5.js} +36 -11
- package/dist/{chunk-2GCVVEQC.js → chunk-PM7DKABI.js} +27 -9
- package/dist/{chunk-32WTNJQU.js → chunk-S3ZDXBRM.js} +768 -470
- package/dist/{heal-OKZ5QZN7.js → heal-YXWB6LTI.js} +1 -1
- package/dist/{health-U7O6PCLZ.js → health-5S2L44SX.js} +2 -2
- package/dist/index.js +4 -4
- package/dist/{studio-X565XJKV.js → studio-EN347SLA.js} +352 -9
- package/dist/{workspace-NE232D4K.js → workspace-UIKTIWUN.js} +3 -3
- package/package.json +4 -4
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
listWorkspaceCandidates,
|
|
23
23
|
listWorkspaceProjects,
|
|
24
24
|
shouldFailWorkspaceHealth
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-MDQSTAP5.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-EUEQMXN5.js";
|
|
56
56
|
import {
|
|
57
57
|
buildGuardRegistryContext,
|
|
58
58
|
createDoctrineMap,
|
|
@@ -69,11 +69,11 @@ import {
|
|
|
69
69
|
sendCliCommandTelemetry,
|
|
70
70
|
sendNewProjectCompletedTelemetry,
|
|
71
71
|
writeDoctrineMap
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-PM7DKABI.js";
|
|
73
73
|
|
|
74
74
|
// src/index.ts
|
|
75
|
-
import { existsSync as
|
|
76
|
-
import { basename as basename2, dirname as
|
|
75
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync16, readdirSync as readdirSync8, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "fs";
|
|
76
|
+
import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute3, join as join31, relative as relative6, resolve as resolve5 } from "path";
|
|
77
77
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
78
78
|
import {
|
|
79
79
|
buildGraphImpactContext,
|
|
@@ -98,6 +98,7 @@ import {
|
|
|
98
98
|
import {
|
|
99
99
|
auditProject,
|
|
100
100
|
critiqueFile as critiqueProjectFile,
|
|
101
|
+
LOOP_READINESS_V2_SCHEMA_URL,
|
|
101
102
|
scanProject as scanProjectReadOnly
|
|
102
103
|
} from "@decantr/verifier";
|
|
103
104
|
|
|
@@ -3392,12 +3393,13 @@ ${YELLOW2}Next step:${RESET2} Review ${BOLD}${reportDisplayPath}${RESET2}, then
|
|
|
3392
3393
|
// src/commands/ci.ts
|
|
3393
3394
|
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
3394
3395
|
import { dirname as dirname3, join as join15, relative as relative3, resolve } from "path";
|
|
3396
|
+
import { DECANTR_CI_REPORT_V2_SCHEMA_URL } from "@decantr/verifier";
|
|
3395
3397
|
var BOLD2 = "\x1B[1m";
|
|
3396
3398
|
var DIM3 = "\x1B[2m";
|
|
3397
3399
|
var GREEN3 = "\x1B[32m";
|
|
3398
3400
|
var RED2 = "\x1B[31m";
|
|
3399
3401
|
var RESET3 = "\x1B[0m";
|
|
3400
|
-
var CI_SCHEMA =
|
|
3402
|
+
var CI_SCHEMA = DECANTR_CI_REPORT_V2_SCHEMA_URL;
|
|
3401
3403
|
function readJson(path) {
|
|
3402
3404
|
if (!existsSync13(path)) return null;
|
|
3403
3405
|
try {
|
|
@@ -3691,6 +3693,9 @@ function formatProjectCiMarkdown(report) {
|
|
|
3691
3693
|
`- Project: \`${report.projectPath ?? "."}\``,
|
|
3692
3694
|
`- Status: **${report.status}**`,
|
|
3693
3695
|
`- Fail on: \`${report.failOn}\``,
|
|
3696
|
+
`- Loop: **${report.loop.state}**`,
|
|
3697
|
+
`- Evidence tier: **${report.evidenceTier.stage}** / ${report.evidenceTier.confidence.level}`,
|
|
3698
|
+
`- Authority: **${report.authority.activeLane}**`,
|
|
3694
3699
|
`- Local law: ${report.localLaw.checked ? `${report.localLaw.errorCount} error(s), ${report.localLaw.warnCount} warning(s)` : "not accepted yet"}`,
|
|
3695
3700
|
`- Style bridge: ${report.styleBridge.checked ? `${report.styleBridge.mappingCount} mapping(s)` : "not active"}`,
|
|
3696
3701
|
"",
|
|
@@ -3710,6 +3715,7 @@ function formatWorkspaceCiMarkdown(report) {
|
|
|
3710
3715
|
"- Mode: **workspace**",
|
|
3711
3716
|
`- Status: **${report.status}**`,
|
|
3712
3717
|
`- Fail on: \`${report.failOn}\``,
|
|
3718
|
+
`- Loop: **${report.loop.state}**`,
|
|
3713
3719
|
"",
|
|
3714
3720
|
formatWorkspaceHealthMarkdown(report.workspace)
|
|
3715
3721
|
];
|
|
@@ -3866,6 +3872,7 @@ async function runWorkspaceCi(root, options) {
|
|
|
3866
3872
|
mode: "workspace",
|
|
3867
3873
|
failOn,
|
|
3868
3874
|
status: workspaceStatus(workspace),
|
|
3875
|
+
loop: workspace.loop,
|
|
3869
3876
|
workspace
|
|
3870
3877
|
};
|
|
3871
3878
|
const json = `${JSON.stringify(report, null, 2)}
|
|
@@ -3904,6 +3911,9 @@ async function runProjectCi(root, options) {
|
|
|
3904
3911
|
projectPath,
|
|
3905
3912
|
failOn,
|
|
3906
3913
|
status: projectCiStatus(health, localLaw, styleBridge),
|
|
3914
|
+
loop: health.loop,
|
|
3915
|
+
authority: health.authority,
|
|
3916
|
+
evidenceTier: health.evidenceTier,
|
|
3907
3917
|
health,
|
|
3908
3918
|
localLaw,
|
|
3909
3919
|
styleBridge
|
|
@@ -4168,7 +4178,7 @@ function cmdCreate(type, name, projectRoot = process.cwd()) {
|
|
|
4168
4178
|
}
|
|
4169
4179
|
|
|
4170
4180
|
// src/commands/doctor.ts
|
|
4171
|
-
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync12 } from "fs";
|
|
4181
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync12, statSync as statSync5 } from "fs";
|
|
4172
4182
|
import { dirname as dirname4, join as join17, relative as relative4 } from "path";
|
|
4173
4183
|
import { fileURLToPath } from "url";
|
|
4174
4184
|
import { isV4 as isV43 } from "@decantr/essence-spec";
|
|
@@ -4292,7 +4302,7 @@ function detectDesignAuthority(workspaceRoot, appRoot) {
|
|
|
4292
4302
|
function findCiFiles(root) {
|
|
4293
4303
|
const files = [];
|
|
4294
4304
|
const workflows = join17(root, ".github", "workflows");
|
|
4295
|
-
if (
|
|
4305
|
+
if (pathIsDirectory(workflows)) {
|
|
4296
4306
|
for (const entry of readdirSync5(workflows, { withFileTypes: true })) {
|
|
4297
4307
|
if (!entry.isFile()) continue;
|
|
4298
4308
|
const path = join17(workflows, entry.name);
|
|
@@ -4302,12 +4312,26 @@ function findCiFiles(root) {
|
|
|
4302
4312
|
}
|
|
4303
4313
|
for (const candidate of ["Jenkinsfile", ".gitlab-ci.yml", "azure-pipelines.yml", "BUILD"]) {
|
|
4304
4314
|
const path = join17(root, candidate);
|
|
4305
|
-
if (
|
|
4315
|
+
if (pathIsFile(path) && readFileSync12(path, "utf-8").includes("decantr")) {
|
|
4306
4316
|
files.push(candidate);
|
|
4307
4317
|
}
|
|
4308
4318
|
}
|
|
4309
4319
|
return files.sort();
|
|
4310
4320
|
}
|
|
4321
|
+
function pathIsFile(path) {
|
|
4322
|
+
try {
|
|
4323
|
+
return statSync5(path).isFile();
|
|
4324
|
+
} catch {
|
|
4325
|
+
return false;
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
function pathIsDirectory(path) {
|
|
4329
|
+
try {
|
|
4330
|
+
return statSync5(path).isDirectory();
|
|
4331
|
+
} catch {
|
|
4332
|
+
return false;
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4311
4335
|
function statusFromIssues(issues, essenceVersion) {
|
|
4312
4336
|
if (!essenceVersion) return "needs-setup";
|
|
4313
4337
|
if (essenceVersion && essenceVersion !== "4.0.0") return "needs-migration";
|
|
@@ -6156,7 +6180,7 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
|
|
|
6156
6180
|
|
|
6157
6181
|
// src/commands/refresh.ts
|
|
6158
6182
|
import { createHash } from "crypto";
|
|
6159
|
-
import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync16, statSync as
|
|
6183
|
+
import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync16, statSync as statSync6 } from "fs";
|
|
6160
6184
|
import { isAbsolute as isAbsolute2, join as join24, relative as relative5 } from "path";
|
|
6161
6185
|
import { isV4 as isV45 } from "@decantr/essence-spec";
|
|
6162
6186
|
import { collectMissingPackManifestFiles as collectMissingPackManifestFiles2 } from "@decantr/verifier";
|
|
@@ -6201,7 +6225,7 @@ function snapshotGeneratedFiles(projectRoot) {
|
|
|
6201
6225
|
}
|
|
6202
6226
|
function fileMtimeMs(path) {
|
|
6203
6227
|
try {
|
|
6204
|
-
return
|
|
6228
|
+
return statSync6(path).mtimeMs;
|
|
6205
6229
|
} catch {
|
|
6206
6230
|
return 0;
|
|
6207
6231
|
}
|
|
@@ -6675,80 +6699,226 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
6675
6699
|
console.log(`${GREEN11}Derived files refreshed.${RESET11}`);
|
|
6676
6700
|
}
|
|
6677
6701
|
|
|
6678
|
-
// src/commands/
|
|
6679
|
-
import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "fs";
|
|
6680
|
-
import { join as join27 } from "path";
|
|
6702
|
+
// src/commands/resolve.ts
|
|
6703
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "fs";
|
|
6704
|
+
import { dirname as dirname6, join as join27, resolve as resolve4 } from "path";
|
|
6705
|
+
var BOLD6 = "\x1B[1m";
|
|
6706
|
+
var DIM12 = "\x1B[2m";
|
|
6681
6707
|
var GREEN12 = "\x1B[32m";
|
|
6682
6708
|
var RED10 = "\x1B[31m";
|
|
6683
6709
|
var YELLOW9 = "\x1B[33m";
|
|
6684
6710
|
var RESET12 = "\x1B[0m";
|
|
6685
|
-
|
|
6686
|
-
|
|
6711
|
+
function driftLogPath(projectRoot) {
|
|
6712
|
+
return join27(projectRoot, ".decantr", "drift-log.json");
|
|
6713
|
+
}
|
|
6714
|
+
function readDriftLog(projectRoot) {
|
|
6715
|
+
const path = driftLogPath(projectRoot);
|
|
6716
|
+
if (!existsSync25(path)) return { version: 1, entries: [] };
|
|
6717
|
+
try {
|
|
6718
|
+
const parsed = JSON.parse(readFileSync18(path, "utf-8"));
|
|
6719
|
+
return {
|
|
6720
|
+
version: 1,
|
|
6721
|
+
entries: Array.isArray(parsed.entries) ? parsed.entries : []
|
|
6722
|
+
};
|
|
6723
|
+
} catch {
|
|
6724
|
+
return { version: 1, entries: [] };
|
|
6725
|
+
}
|
|
6726
|
+
}
|
|
6727
|
+
function writeDriftLog(projectRoot, log) {
|
|
6728
|
+
const path = driftLogPath(projectRoot);
|
|
6729
|
+
mkdirSync14(dirname6(path), { recursive: true });
|
|
6730
|
+
writeFileSync15(path, `${JSON.stringify(log, null, 2)}
|
|
6731
|
+
`, "utf-8");
|
|
6732
|
+
}
|
|
6733
|
+
function actionLabel(action) {
|
|
6734
|
+
return `${action.kind}${action.command ? ` -> ${action.command}` : ""}`;
|
|
6735
|
+
}
|
|
6736
|
+
function appendDriftAction(projectRoot, conflict, action) {
|
|
6737
|
+
const log = readDriftLog(projectRoot);
|
|
6738
|
+
const status = action === "mark_advisory" ? "advisory" : "deferred";
|
|
6739
|
+
const entry = {
|
|
6740
|
+
id: `${action}:${conflict.id}:${Date.now()}`,
|
|
6741
|
+
findingId: conflict.id,
|
|
6742
|
+
action,
|
|
6743
|
+
status,
|
|
6744
|
+
message: conflict.message,
|
|
6745
|
+
source: conflict.source,
|
|
6746
|
+
severity: conflict.severity,
|
|
6747
|
+
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6748
|
+
};
|
|
6749
|
+
log.entries = log.entries.filter(
|
|
6750
|
+
(candidate) => !(candidate.findingId === conflict.id && candidate.action === action)
|
|
6751
|
+
);
|
|
6752
|
+
log.entries.push(entry);
|
|
6753
|
+
writeDriftLog(projectRoot, log);
|
|
6754
|
+
return driftLogPath(projectRoot);
|
|
6755
|
+
}
|
|
6756
|
+
function parseResolveArgs(args) {
|
|
6757
|
+
const options = {};
|
|
6758
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
6759
|
+
const arg = args[index];
|
|
6760
|
+
if (arg === "--json") options.json = true;
|
|
6761
|
+
else if (arg === "--defer" && args[index + 1]) options.defer = args[++index];
|
|
6762
|
+
else if (arg.startsWith("--defer=")) options.defer = arg.split("=")[1];
|
|
6763
|
+
else if (arg === "--mark-advisory" && args[index + 1]) options.markAdvisory = args[++index];
|
|
6764
|
+
else if (arg.startsWith("--mark-advisory=")) options.markAdvisory = arg.split("=")[1];
|
|
6765
|
+
}
|
|
6766
|
+
return options;
|
|
6767
|
+
}
|
|
6768
|
+
function groupConflicts(conflicts) {
|
|
6769
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
6770
|
+
for (const conflict of conflicts) {
|
|
6771
|
+
const key = conflict.lane;
|
|
6772
|
+
grouped.set(key, [...grouped.get(key) ?? [], conflict]);
|
|
6773
|
+
}
|
|
6774
|
+
return grouped;
|
|
6775
|
+
}
|
|
6776
|
+
function formatAuthorityResolutionText(projectRoot, conflicts, summary, stopRule) {
|
|
6777
|
+
const lines = [
|
|
6778
|
+
`${BOLD6}Decantr Authority Resolver${RESET12}`,
|
|
6779
|
+
"",
|
|
6780
|
+
`${DIM12}${resolve4(projectRoot)}${RESET12}`,
|
|
6781
|
+
`Authority: ${summary}`,
|
|
6782
|
+
`Stop rule: ${stopRule}`,
|
|
6783
|
+
""
|
|
6784
|
+
];
|
|
6785
|
+
if (conflicts.length === 0) {
|
|
6786
|
+
lines.push(`${GREEN12}No authority conflicts found.${RESET12}`);
|
|
6787
|
+
lines.push("");
|
|
6788
|
+
lines.push(`Next: ${DIM12}Run decantr task <route> "<intent>" before editing.${RESET12}`);
|
|
6789
|
+
return `${lines.join("\n")}
|
|
6790
|
+
`;
|
|
6791
|
+
}
|
|
6792
|
+
for (const [lane, laneConflicts] of groupConflicts(conflicts)) {
|
|
6793
|
+
lines.push(`${BOLD6}${lane}:${RESET12}`);
|
|
6794
|
+
for (const conflict of laneConflicts) {
|
|
6795
|
+
const color = conflict.status === "blocking" ? RED10 : conflict.status === "repairable" ? YELLOW9 : DIM12;
|
|
6796
|
+
lines.push(` ${color}[${conflict.status}]${RESET12} ${conflict.id}: ${conflict.message}`);
|
|
6797
|
+
lines.push(
|
|
6798
|
+
` ${DIM12}${conflict.source} / ${conflict.category} / ${conflict.severity}${RESET12}`
|
|
6799
|
+
);
|
|
6800
|
+
for (const action of conflict.recommendedActions.slice(0, 4)) {
|
|
6801
|
+
lines.push(` - ${actionLabel(action)}`);
|
|
6802
|
+
}
|
|
6803
|
+
}
|
|
6804
|
+
lines.push("");
|
|
6805
|
+
}
|
|
6806
|
+
lines.push(`${BOLD6}Read-only by default:${RESET12}`);
|
|
6807
|
+
lines.push(
|
|
6808
|
+
" Use --defer <finding-id> or --mark-advisory <finding-id> to write only .decantr/drift-log.json."
|
|
6809
|
+
);
|
|
6810
|
+
return `${lines.join("\n")}
|
|
6811
|
+
`;
|
|
6812
|
+
}
|
|
6813
|
+
async function cmdResolve(projectRoot = process.cwd(), args = ["resolve"]) {
|
|
6814
|
+
const options = parseResolveArgs(args);
|
|
6815
|
+
const report = await createProjectHealthReport(projectRoot);
|
|
6816
|
+
const resolution = report.authority;
|
|
6817
|
+
if (options.defer || options.markAdvisory) {
|
|
6818
|
+
const findingId = options.defer ?? options.markAdvisory;
|
|
6819
|
+
const conflict = resolution.conflicts.find((entry) => entry.id === findingId);
|
|
6820
|
+
if (!conflict) {
|
|
6821
|
+
console.error(`${RED10}No authority conflict found for finding: ${findingId}${RESET12}`);
|
|
6822
|
+
process.exitCode = 1;
|
|
6823
|
+
return;
|
|
6824
|
+
}
|
|
6825
|
+
const path = appendDriftAction(
|
|
6826
|
+
projectRoot,
|
|
6827
|
+
conflict,
|
|
6828
|
+
options.defer ? "defer_to_drift_log" : "mark_advisory"
|
|
6829
|
+
);
|
|
6830
|
+
console.log(`${GREEN12}Updated drift log:${RESET12} ${path}`);
|
|
6831
|
+
return;
|
|
6832
|
+
}
|
|
6833
|
+
if (options.json) {
|
|
6834
|
+
process.stdout.write(`${JSON.stringify(resolution, null, 2)}
|
|
6835
|
+
`);
|
|
6836
|
+
return;
|
|
6837
|
+
}
|
|
6838
|
+
process.stdout.write(
|
|
6839
|
+
formatAuthorityResolutionText(
|
|
6840
|
+
projectRoot,
|
|
6841
|
+
resolution.conflicts,
|
|
6842
|
+
resolution.summary,
|
|
6843
|
+
resolution.stopRule
|
|
6844
|
+
)
|
|
6845
|
+
);
|
|
6846
|
+
}
|
|
6847
|
+
|
|
6848
|
+
// src/commands/sync-drift.ts
|
|
6849
|
+
import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "fs";
|
|
6850
|
+
import { join as join28 } from "path";
|
|
6851
|
+
var GREEN13 = "\x1B[32m";
|
|
6852
|
+
var RED11 = "\x1B[31m";
|
|
6853
|
+
var YELLOW10 = "\x1B[33m";
|
|
6854
|
+
var RESET13 = "\x1B[0m";
|
|
6855
|
+
var DIM13 = "\x1B[2m";
|
|
6856
|
+
var BOLD7 = "\x1B[1m";
|
|
6687
6857
|
var CYAN6 = "\x1B[36m";
|
|
6688
6858
|
async function cmdSyncDrift(projectRoot = process.cwd()) {
|
|
6689
|
-
const
|
|
6690
|
-
if (!
|
|
6691
|
-
console.log(`${
|
|
6859
|
+
const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
|
|
6860
|
+
if (!existsSync26(driftLogPath2)) {
|
|
6861
|
+
console.log(`${GREEN13}No drift log found \u2014 no drift recorded.${RESET13}`);
|
|
6692
6862
|
console.log(
|
|
6693
|
-
`${
|
|
6863
|
+
`${DIM13}Drift is logged when guard violations are detected during development.${RESET13}`
|
|
6694
6864
|
);
|
|
6695
6865
|
return;
|
|
6696
6866
|
}
|
|
6697
6867
|
let entries;
|
|
6698
6868
|
try {
|
|
6699
|
-
entries = JSON.parse(
|
|
6869
|
+
entries = JSON.parse(readFileSync19(driftLogPath2, "utf-8"));
|
|
6700
6870
|
} catch {
|
|
6701
|
-
console.error(`${
|
|
6871
|
+
console.error(`${RED11}Could not parse drift-log.json${RESET13}`);
|
|
6702
6872
|
process.exitCode = 1;
|
|
6703
6873
|
return;
|
|
6704
6874
|
}
|
|
6705
6875
|
if (!Array.isArray(entries)) {
|
|
6706
|
-
console.error(`${
|
|
6876
|
+
console.error(`${RED11}drift-log.json is not an array${RESET13}`);
|
|
6707
6877
|
process.exitCode = 1;
|
|
6708
6878
|
return;
|
|
6709
6879
|
}
|
|
6710
6880
|
const unresolved = entries.filter((e) => !e.resolved);
|
|
6711
6881
|
const resolved = entries.filter((e) => e.resolved);
|
|
6712
6882
|
if (unresolved.length === 0) {
|
|
6713
|
-
console.log(`${
|
|
6883
|
+
console.log(`${GREEN13}No unresolved drift entries.${RESET13}`);
|
|
6714
6884
|
if (resolved.length > 0) {
|
|
6715
|
-
console.log(`${
|
|
6885
|
+
console.log(`${DIM13}${resolved.length} previously resolved entries in the log.${RESET13}`);
|
|
6716
6886
|
}
|
|
6717
6887
|
return;
|
|
6718
6888
|
}
|
|
6719
6889
|
console.log(`
|
|
6720
|
-
${
|
|
6890
|
+
${BOLD7}Unresolved Drift Entries (${unresolved.length})${RESET13}
|
|
6721
6891
|
`);
|
|
6722
6892
|
for (let i = 0; i < unresolved.length; i++) {
|
|
6723
6893
|
const entry = unresolved[i];
|
|
6724
|
-
const severityColor = entry.severity === "error" ?
|
|
6894
|
+
const severityColor = entry.severity === "error" ? RED11 : YELLOW10;
|
|
6725
6895
|
const icon = entry.severity === "error" ? "x" : "!";
|
|
6726
6896
|
console.log(
|
|
6727
|
-
` ${severityColor}${icon}${
|
|
6897
|
+
` ${severityColor}${icon}${RESET13} ${BOLD7}#${i + 1}${RESET13} [${entry.rule}] ${entry.message}`
|
|
6728
6898
|
);
|
|
6729
6899
|
if (entry.page) {
|
|
6730
|
-
console.log(` ${
|
|
6900
|
+
console.log(` ${DIM13}Page: ${entry.page}${RESET13}`);
|
|
6731
6901
|
}
|
|
6732
6902
|
if (entry.suggestion) {
|
|
6733
|
-
console.log(` ${CYAN6}Suggestion: ${entry.suggestion}${
|
|
6903
|
+
console.log(` ${CYAN6}Suggestion: ${entry.suggestion}${RESET13}`);
|
|
6734
6904
|
}
|
|
6735
|
-
console.log(` ${
|
|
6905
|
+
console.log(` ${DIM13}${entry.timestamp}${RESET13}`);
|
|
6736
6906
|
console.log("");
|
|
6737
6907
|
}
|
|
6738
|
-
console.log(`${
|
|
6739
|
-
console.log(` ${CYAN6}decantr sync-drift --resolve-all${
|
|
6740
|
-
console.log(` ${CYAN6}decantr sync-drift --resolve <n>${
|
|
6741
|
-
console.log(` ${CYAN6}decantr sync-drift --clear${
|
|
6908
|
+
console.log(`${BOLD7}Actions:${RESET13}`);
|
|
6909
|
+
console.log(` ${CYAN6}decantr sync-drift --resolve-all${RESET13} Mark all entries as resolved`);
|
|
6910
|
+
console.log(` ${CYAN6}decantr sync-drift --resolve <n>${RESET13} Mark entry #n as resolved`);
|
|
6911
|
+
console.log(` ${CYAN6}decantr sync-drift --clear${RESET13} Clear the entire drift log`);
|
|
6742
6912
|
console.log("");
|
|
6743
6913
|
}
|
|
6744
6914
|
function resolveDriftEntries(projectRoot, options) {
|
|
6745
|
-
const
|
|
6746
|
-
if (!
|
|
6915
|
+
const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
|
|
6916
|
+
if (!existsSync26(driftLogPath2)) {
|
|
6747
6917
|
return { success: true };
|
|
6748
6918
|
}
|
|
6749
6919
|
if (options.clear) {
|
|
6750
6920
|
try {
|
|
6751
|
-
|
|
6921
|
+
writeFileSync16(driftLogPath2, "[]");
|
|
6752
6922
|
return { success: true };
|
|
6753
6923
|
} catch (e) {
|
|
6754
6924
|
return { success: false, error: `Could not clear drift log: ${e.message}` };
|
|
@@ -6756,7 +6926,7 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
6756
6926
|
}
|
|
6757
6927
|
let entries;
|
|
6758
6928
|
try {
|
|
6759
|
-
entries = JSON.parse(
|
|
6929
|
+
entries = JSON.parse(readFileSync19(driftLogPath2, "utf-8"));
|
|
6760
6930
|
} catch {
|
|
6761
6931
|
return { success: false, error: "Could not parse drift-log.json" };
|
|
6762
6932
|
}
|
|
@@ -6775,7 +6945,7 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
6775
6945
|
}
|
|
6776
6946
|
}
|
|
6777
6947
|
try {
|
|
6778
|
-
|
|
6948
|
+
writeFileSync16(driftLogPath2, JSON.stringify(entries, null, 2));
|
|
6779
6949
|
return { success: true };
|
|
6780
6950
|
} catch (e) {
|
|
6781
6951
|
return { success: false, error: `Could not write drift log: ${e.message}` };
|
|
@@ -6784,11 +6954,11 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
6784
6954
|
|
|
6785
6955
|
// src/commands/telemetry.ts
|
|
6786
6956
|
import { DECANTR_TELEMETRY_EVENT_CATALOG } from "@decantr/telemetry";
|
|
6787
|
-
var
|
|
6957
|
+
var BOLD8 = "\x1B[1m";
|
|
6788
6958
|
var CYAN7 = "\x1B[36m";
|
|
6789
|
-
var
|
|
6790
|
-
var
|
|
6791
|
-
var
|
|
6959
|
+
var DIM14 = "\x1B[2m";
|
|
6960
|
+
var GREEN14 = "\x1B[32m";
|
|
6961
|
+
var RESET14 = "\x1B[0m";
|
|
6792
6962
|
var DEFAULT_API_URL = "https://api.decantr.ai/v1";
|
|
6793
6963
|
async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
6794
6964
|
const subcommand = args[0] ?? "status";
|
|
@@ -6813,14 +6983,14 @@ async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
|
6813
6983
|
}
|
|
6814
6984
|
function printTelemetryHelp() {
|
|
6815
6985
|
console.log(`
|
|
6816
|
-
${
|
|
6986
|
+
${BOLD8}decantr telemetry${RESET14} \u2014 Inspect and link privacy-filtered CLI telemetry identity
|
|
6817
6987
|
|
|
6818
|
-
${
|
|
6988
|
+
${BOLD8}Usage:${RESET14}
|
|
6819
6989
|
decantr telemetry status [--json]
|
|
6820
6990
|
decantr telemetry explain [--json]
|
|
6821
6991
|
decantr telemetry link [--enable] [--org <slug>] [--label <label>] [--api-key <key>] [--api-url <url>]
|
|
6822
6992
|
|
|
6823
|
-
${
|
|
6993
|
+
${BOLD8}Examples:${RESET14}
|
|
6824
6994
|
decantr init --telemetry
|
|
6825
6995
|
decantr telemetry status
|
|
6826
6996
|
decantr telemetry explain
|
|
@@ -6835,18 +7005,18 @@ function printTelemetryStatus(projectRoot, options) {
|
|
|
6835
7005
|
return;
|
|
6836
7006
|
}
|
|
6837
7007
|
console.log(`
|
|
6838
|
-
${
|
|
6839
|
-
console.log(` Enabled: ${status.enabled ? `${
|
|
7008
|
+
${BOLD8}Decantr telemetry${RESET14}`);
|
|
7009
|
+
console.log(` Enabled: ${status.enabled ? `${GREEN14}yes${RESET14}` : "no"}`);
|
|
6840
7010
|
console.log(` Project: ${status.hasProjectConfig ? status.projectRoot : "not initialized"}`);
|
|
6841
|
-
console.log(` Install ID: ${status.installId ?? `${
|
|
6842
|
-
console.log(` Project ID: ${status.projectId ?? `${
|
|
7011
|
+
console.log(` Install ID: ${status.installId ?? `${DIM14}not created yet${RESET14}`}`);
|
|
7012
|
+
console.log(` Project ID: ${status.projectId ?? `${DIM14}not created yet${RESET14}`}`);
|
|
6843
7013
|
if (status.enabled) {
|
|
6844
7014
|
console.log(
|
|
6845
|
-
|
|
7015
|
+
DIM14 + "Run `decantr telemetry link` after login to attach these opaque IDs to your Decantr account/org." + RESET14
|
|
6846
7016
|
);
|
|
6847
7017
|
} else {
|
|
6848
7018
|
console.log(
|
|
6849
|
-
|
|
7019
|
+
DIM14 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET14
|
|
6850
7020
|
);
|
|
6851
7021
|
}
|
|
6852
7022
|
}
|
|
@@ -6908,25 +7078,25 @@ function printTelemetryExplain(projectRoot, options) {
|
|
|
6908
7078
|
return;
|
|
6909
7079
|
}
|
|
6910
7080
|
console.log(`
|
|
6911
|
-
${
|
|
7081
|
+
${BOLD8}Decantr telemetry explanation${RESET14}`);
|
|
6912
7082
|
console.log(` Source: cli`);
|
|
6913
|
-
console.log(` Enabled: ${status.enabled ? `${
|
|
6914
|
-
console.log(` Install ID: ${status.installId ?? `${
|
|
6915
|
-
console.log(` Project ID: ${status.projectId ?? `${
|
|
7083
|
+
console.log(` Enabled: ${status.enabled ? `${GREEN14}yes${RESET14}` : "no"}`);
|
|
7084
|
+
console.log(` Install ID: ${status.installId ?? `${DIM14}not created yet${RESET14}`}`);
|
|
7085
|
+
console.log(` Project ID: ${status.projectId ?? `${DIM14}not created yet${RESET14}`}`);
|
|
6916
7086
|
console.log(` Events: ${cliEvents.length} CLI event types in the public catalog`);
|
|
6917
7087
|
console.log(`
|
|
6918
|
-
${
|
|
7088
|
+
${BOLD8}Aggregate fields${RESET14}`);
|
|
6919
7089
|
for (const field of report.aggregateFields) {
|
|
6920
7090
|
console.log(` - ${field}`);
|
|
6921
7091
|
}
|
|
6922
7092
|
console.log(`
|
|
6923
|
-
${
|
|
7093
|
+
${BOLD8}Never collected${RESET14}`);
|
|
6924
7094
|
for (const field of report.neverCollected) {
|
|
6925
7095
|
console.log(` - ${field}`);
|
|
6926
7096
|
}
|
|
6927
7097
|
console.log(`
|
|
6928
|
-
${
|
|
6929
|
-
console.log(`${
|
|
7098
|
+
${DIM14}${report.controls.optOut}${RESET14}`);
|
|
7099
|
+
console.log(`${DIM14}${report.controls.link}${RESET14}`);
|
|
6930
7100
|
}
|
|
6931
7101
|
async function linkTelemetryIdentity(projectRoot, options) {
|
|
6932
7102
|
if (options.enable && !isOptedIn(projectRoot)) {
|
|
@@ -6968,13 +7138,13 @@ async function linkTelemetryIdentity(projectRoot, options) {
|
|
|
6968
7138
|
throw new Error(body2?.error ?? `Telemetry link failed with HTTP ${response.status}.`);
|
|
6969
7139
|
}
|
|
6970
7140
|
const body = await response.json().catch(() => ({ linked: 0 }));
|
|
6971
|
-
console.log(`${
|
|
7141
|
+
console.log(`${GREEN14}Telemetry identity linked.${RESET14}`);
|
|
6972
7142
|
console.log(` Linked: ${body.linked ?? 0}`);
|
|
6973
|
-
console.log(` Install ID: ${identity.installId ?? `${
|
|
6974
|
-
console.log(` Project ID: ${identity.projectId ?? `${
|
|
6975
|
-
if (options.org) console.log(` Org: ${CYAN7}${options.org}${
|
|
7143
|
+
console.log(` Install ID: ${identity.installId ?? `${DIM14}none${RESET14}`}`);
|
|
7144
|
+
console.log(` Project ID: ${identity.projectId ?? `${DIM14}none${RESET14}`}`);
|
|
7145
|
+
if (options.org) console.log(` Org: ${CYAN7}${options.org}${RESET14}`);
|
|
6976
7146
|
console.log(
|
|
6977
|
-
|
|
7147
|
+
DIM14 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET14
|
|
6978
7148
|
);
|
|
6979
7149
|
}
|
|
6980
7150
|
function parseTelemetryOptions(args) {
|
|
@@ -7012,41 +7182,41 @@ function trimTrailingSlashes(value) {
|
|
|
7012
7182
|
}
|
|
7013
7183
|
|
|
7014
7184
|
// src/commands/theme-switch.ts
|
|
7015
|
-
import { existsSync as
|
|
7016
|
-
import { join as
|
|
7185
|
+
import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "fs";
|
|
7186
|
+
import { join as join29 } from "path";
|
|
7017
7187
|
import { isV4 as isV47 } from "@decantr/essence-spec";
|
|
7018
|
-
var
|
|
7019
|
-
var
|
|
7020
|
-
var
|
|
7021
|
-
var
|
|
7022
|
-
var
|
|
7188
|
+
var GREEN15 = "\x1B[32m";
|
|
7189
|
+
var RED12 = "\x1B[31m";
|
|
7190
|
+
var YELLOW11 = "\x1B[33m";
|
|
7191
|
+
var DIM15 = "\x1B[2m";
|
|
7192
|
+
var RESET15 = "\x1B[0m";
|
|
7023
7193
|
var VALID_THEME_SHAPES = ["sharp", "rounded", "pill"];
|
|
7024
7194
|
var VALID_THEME_MODES = ["light", "dark", "auto"];
|
|
7025
7195
|
async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
7026
7196
|
if (!themeName) {
|
|
7027
7197
|
console.error(
|
|
7028
|
-
`${
|
|
7198
|
+
`${RED12}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET15}`
|
|
7029
7199
|
);
|
|
7030
7200
|
process.exitCode = 1;
|
|
7031
7201
|
return;
|
|
7032
7202
|
}
|
|
7033
|
-
const essencePath =
|
|
7034
|
-
if (!
|
|
7035
|
-
console.error(`${
|
|
7203
|
+
const essencePath = join29(projectRoot, "decantr.essence.json");
|
|
7204
|
+
if (!existsSync27(essencePath)) {
|
|
7205
|
+
console.error(`${RED12}No decantr.essence.json found. Run \`decantr init\` first.${RESET15}`);
|
|
7036
7206
|
process.exitCode = 1;
|
|
7037
7207
|
return;
|
|
7038
7208
|
}
|
|
7039
7209
|
let parsed;
|
|
7040
7210
|
try {
|
|
7041
|
-
parsed = JSON.parse(
|
|
7211
|
+
parsed = JSON.parse(readFileSync20(essencePath, "utf-8"));
|
|
7042
7212
|
} catch (e) {
|
|
7043
|
-
console.error(`${
|
|
7213
|
+
console.error(`${RED12}Could not read essence: ${e.message}${RESET15}`);
|
|
7044
7214
|
process.exitCode = 1;
|
|
7045
7215
|
return;
|
|
7046
7216
|
}
|
|
7047
7217
|
if (!isV47(parsed)) {
|
|
7048
7218
|
console.error(
|
|
7049
|
-
`${
|
|
7219
|
+
`${RED12}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET15}`
|
|
7050
7220
|
);
|
|
7051
7221
|
process.exitCode = 1;
|
|
7052
7222
|
return;
|
|
@@ -7068,14 +7238,14 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7068
7238
|
}
|
|
7069
7239
|
if (shape && !VALID_THEME_SHAPES.includes(shape)) {
|
|
7070
7240
|
console.error(
|
|
7071
|
-
`${
|
|
7241
|
+
`${RED12}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET15}`
|
|
7072
7242
|
);
|
|
7073
7243
|
process.exitCode = 1;
|
|
7074
7244
|
return;
|
|
7075
7245
|
}
|
|
7076
7246
|
if (mode && !VALID_THEME_MODES.includes(mode)) {
|
|
7077
7247
|
console.error(
|
|
7078
|
-
`${
|
|
7248
|
+
`${RED12}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET15}`
|
|
7079
7249
|
);
|
|
7080
7250
|
process.exitCode = 1;
|
|
7081
7251
|
return;
|
|
@@ -7089,7 +7259,7 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7089
7259
|
essence.dna.theme.mode = mode;
|
|
7090
7260
|
}
|
|
7091
7261
|
const registryClient = new RegistryClient({
|
|
7092
|
-
cacheDir:
|
|
7262
|
+
cacheDir: join29(projectRoot, ".decantr", "cache")
|
|
7093
7263
|
});
|
|
7094
7264
|
try {
|
|
7095
7265
|
const themeResult = await registryClient.fetchTheme(themeName);
|
|
@@ -7104,45 +7274,45 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7104
7274
|
}
|
|
7105
7275
|
} catch {
|
|
7106
7276
|
}
|
|
7107
|
-
|
|
7108
|
-
console.log(`${
|
|
7109
|
-
if (shape) console.log(` ${
|
|
7110
|
-
if (mode) console.log(` ${
|
|
7277
|
+
writeFileSync17(essencePath, JSON.stringify(essence, null, 2) + "\n");
|
|
7278
|
+
console.log(`${GREEN15}Switched theme: ${oldThemeId} \u2192 ${themeName}${RESET15}`);
|
|
7279
|
+
if (shape) console.log(` ${DIM15}Shape: ${shape}${RESET15}`);
|
|
7280
|
+
if (mode) console.log(` ${DIM15}Mode: ${mode}${RESET15}`);
|
|
7111
7281
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
7112
7282
|
console.log(
|
|
7113
|
-
`${
|
|
7283
|
+
`${GREEN15}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET15}`
|
|
7114
7284
|
);
|
|
7115
|
-
console.log(`${
|
|
7285
|
+
console.log(`${YELLOW11}Guard will flag code using old tokens. Run \`decantr check\`.${RESET15}`);
|
|
7116
7286
|
}
|
|
7117
7287
|
|
|
7118
7288
|
// src/prompts.ts
|
|
7119
7289
|
import { createInterface } from "readline";
|
|
7120
|
-
var
|
|
7121
|
-
var
|
|
7122
|
-
var
|
|
7123
|
-
var
|
|
7124
|
-
var
|
|
7290
|
+
var BOLD9 = "\x1B[1m";
|
|
7291
|
+
var DIM16 = "\x1B[2m";
|
|
7292
|
+
var RESET16 = "\x1B[0m";
|
|
7293
|
+
var GREEN16 = "\x1B[32m";
|
|
7294
|
+
var YELLOW12 = "\x1B[33m";
|
|
7125
7295
|
var CYAN8 = "\x1B[36m";
|
|
7126
7296
|
function ask(question, defaultValue) {
|
|
7127
7297
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7128
|
-
const prompt = defaultValue ? `${question} ${
|
|
7129
|
-
return new Promise((
|
|
7298
|
+
const prompt = defaultValue ? `${question} ${DIM16}(${defaultValue})${RESET16}: ` : `${question}: `;
|
|
7299
|
+
return new Promise((resolve6) => {
|
|
7130
7300
|
rl.question(prompt, (answer) => {
|
|
7131
7301
|
rl.close();
|
|
7132
|
-
|
|
7302
|
+
resolve6(answer.trim() || defaultValue || "");
|
|
7133
7303
|
});
|
|
7134
7304
|
});
|
|
7135
7305
|
}
|
|
7136
7306
|
async function select(question, options, defaultIdx = 0, allowOther = false) {
|
|
7137
7307
|
console.log(`
|
|
7138
|
-
${
|
|
7308
|
+
${BOLD9}${question}${RESET16}`);
|
|
7139
7309
|
for (let i = 0; i < options.length; i++) {
|
|
7140
|
-
const marker = i === defaultIdx ? `${
|
|
7141
|
-
const desc = options[i].description ? ` ${
|
|
7310
|
+
const marker = i === defaultIdx ? `${GREEN16}>${RESET16}` : " ";
|
|
7311
|
+
const desc = options[i].description ? ` ${DIM16}\u2014 ${options[i].description}${RESET16}` : "";
|
|
7142
7312
|
console.log(` ${marker} ${i + 1}. ${options[i].label}${desc}`);
|
|
7143
7313
|
}
|
|
7144
7314
|
if (allowOther) {
|
|
7145
|
-
console.log(` ${options.length + 1}. ${
|
|
7315
|
+
console.log(` ${options.length + 1}. ${DIM16}other (enter custom value)${RESET16}`);
|
|
7146
7316
|
}
|
|
7147
7317
|
const maxIdx = allowOther ? options.length + 1 : options.length;
|
|
7148
7318
|
const answer = await ask(`Choose (1-${maxIdx})`, String(defaultIdx + 1));
|
|
@@ -7161,11 +7331,11 @@ async function confirm(question, defaultYes = true) {
|
|
|
7161
7331
|
}
|
|
7162
7332
|
function warn(message) {
|
|
7163
7333
|
console.log(`
|
|
7164
|
-
${
|
|
7334
|
+
${YELLOW12} Warning: ${message}${RESET16}`);
|
|
7165
7335
|
}
|
|
7166
7336
|
function showDetection(detected) {
|
|
7167
7337
|
console.log(`
|
|
7168
|
-
${CYAN8}Detected project configuration:${
|
|
7338
|
+
${CYAN8}Detected project configuration:${RESET16}`);
|
|
7169
7339
|
if (detected.framework !== "unknown") {
|
|
7170
7340
|
const version = detected.version ? ` ${detected.version}` : "";
|
|
7171
7341
|
console.log(` Framework: ${detected.framework}${version}`);
|
|
@@ -7174,13 +7344,13 @@ ${CYAN8}Detected project configuration:${RESET15}`);
|
|
|
7174
7344
|
console.log(` Package manager: ${detected.packageManager}`);
|
|
7175
7345
|
}
|
|
7176
7346
|
if (detected.hasTypeScript) {
|
|
7177
|
-
console.log(` TypeScript: ${
|
|
7347
|
+
console.log(` TypeScript: ${GREEN16}yes${RESET16}`);
|
|
7178
7348
|
}
|
|
7179
7349
|
if (detected.hasTailwind) {
|
|
7180
|
-
console.log(` Tailwind CSS: ${
|
|
7350
|
+
console.log(` Tailwind CSS: ${GREEN16}yes${RESET16}`);
|
|
7181
7351
|
}
|
|
7182
7352
|
if (detected.existingEssence) {
|
|
7183
|
-
console.log(` Existing essence: ${
|
|
7353
|
+
console.log(` Existing essence: ${YELLOW12}yes${RESET16}`);
|
|
7184
7354
|
}
|
|
7185
7355
|
}
|
|
7186
7356
|
async function runInteractivePrompts(detected, archetypes, blueprints, themes, workflowSeed) {
|
|
@@ -7255,7 +7425,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes, w
|
|
|
7255
7425
|
warn(`This project appears to be ${detected.framework} but you selected ${target}.`);
|
|
7256
7426
|
const proceed = await confirm("Continue anyway?", false);
|
|
7257
7427
|
if (!proceed) {
|
|
7258
|
-
console.log(`${
|
|
7428
|
+
console.log(`${DIM16}Using detected framework: ${detected.framework}${RESET16}`);
|
|
7259
7429
|
}
|
|
7260
7430
|
}
|
|
7261
7431
|
const guardMode = await select(
|
|
@@ -7380,7 +7550,7 @@ function mergeWithDefaults(flags, detected, workflowSeed) {
|
|
|
7380
7550
|
}
|
|
7381
7551
|
async function runSimplifiedInit(blueprints) {
|
|
7382
7552
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7383
|
-
const question = (q) => new Promise((
|
|
7553
|
+
const question = (q) => new Promise((resolve6) => rl.question(q, resolve6));
|
|
7384
7554
|
console.log("\n? What blueprint would you like to scaffold?\n");
|
|
7385
7555
|
console.log(" 1. Decantr default (recommended)");
|
|
7386
7556
|
console.log(" 2. Search registry...\n");
|
|
@@ -7412,8 +7582,8 @@ async function runSimplifiedInit(blueprints) {
|
|
|
7412
7582
|
}
|
|
7413
7583
|
|
|
7414
7584
|
// src/theme-commands.ts
|
|
7415
|
-
import { existsSync as
|
|
7416
|
-
import { join as
|
|
7585
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync15, readdirSync as readdirSync7, readFileSync as readFileSync21, rmSync as rmSync3, writeFileSync as writeFileSync18 } from "fs";
|
|
7586
|
+
import { join as join30 } from "path";
|
|
7417
7587
|
var REQUIRED_FIELDS = [
|
|
7418
7588
|
"$schema",
|
|
7419
7589
|
"id",
|
|
@@ -7473,20 +7643,20 @@ function validateCustomTheme(theme) {
|
|
|
7473
7643
|
};
|
|
7474
7644
|
}
|
|
7475
7645
|
function createTheme(projectRoot, id, name) {
|
|
7476
|
-
const customThemesDir =
|
|
7477
|
-
const themePath =
|
|
7478
|
-
const howToPath =
|
|
7479
|
-
|
|
7480
|
-
if (
|
|
7646
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7647
|
+
const themePath = join30(customThemesDir, `${id}.json`);
|
|
7648
|
+
const howToPath = join30(customThemesDir, "how-to-theme.md");
|
|
7649
|
+
mkdirSync15(customThemesDir, { recursive: true });
|
|
7650
|
+
if (existsSync28(themePath)) {
|
|
7481
7651
|
return {
|
|
7482
7652
|
success: false,
|
|
7483
7653
|
error: `Theme "${id}" already exists at ${themePath}`
|
|
7484
7654
|
};
|
|
7485
7655
|
}
|
|
7486
7656
|
const skeleton = getThemeSkeleton(id, name);
|
|
7487
|
-
|
|
7488
|
-
if (!
|
|
7489
|
-
|
|
7657
|
+
writeFileSync18(themePath, JSON.stringify(skeleton, null, 2));
|
|
7658
|
+
if (!existsSync28(howToPath)) {
|
|
7659
|
+
writeFileSync18(howToPath, getHowToThemeDoc());
|
|
7490
7660
|
}
|
|
7491
7661
|
return {
|
|
7492
7662
|
success: true,
|
|
@@ -7494,17 +7664,17 @@ function createTheme(projectRoot, id, name) {
|
|
|
7494
7664
|
};
|
|
7495
7665
|
}
|
|
7496
7666
|
function listCustomThemes(projectRoot) {
|
|
7497
|
-
const customThemesDir =
|
|
7498
|
-
if (!
|
|
7667
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7668
|
+
if (!existsSync28(customThemesDir)) {
|
|
7499
7669
|
return [];
|
|
7500
7670
|
}
|
|
7501
7671
|
const themes = [];
|
|
7502
7672
|
try {
|
|
7503
7673
|
const files = readdirSync7(customThemesDir).filter((f) => f.endsWith(".json"));
|
|
7504
7674
|
for (const file of files) {
|
|
7505
|
-
const filePath =
|
|
7675
|
+
const filePath = join30(customThemesDir, file);
|
|
7506
7676
|
try {
|
|
7507
|
-
const data = JSON.parse(
|
|
7677
|
+
const data = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
7508
7678
|
themes.push({
|
|
7509
7679
|
id: data.id || file.replace(".json", ""),
|
|
7510
7680
|
name: data.name || data.id,
|
|
@@ -7519,8 +7689,8 @@ function listCustomThemes(projectRoot) {
|
|
|
7519
7689
|
return themes;
|
|
7520
7690
|
}
|
|
7521
7691
|
function deleteTheme(projectRoot, id) {
|
|
7522
|
-
const themePath =
|
|
7523
|
-
if (!
|
|
7692
|
+
const themePath = join30(projectRoot, ".decantr", "custom", "themes", `${id}.json`);
|
|
7693
|
+
if (!existsSync28(themePath)) {
|
|
7524
7694
|
return {
|
|
7525
7695
|
success: false,
|
|
7526
7696
|
error: `Theme "${id}" not found at ${themePath}`
|
|
@@ -7537,7 +7707,7 @@ function deleteTheme(projectRoot, id) {
|
|
|
7537
7707
|
}
|
|
7538
7708
|
}
|
|
7539
7709
|
function importTheme(projectRoot, sourcePath) {
|
|
7540
|
-
if (!
|
|
7710
|
+
if (!existsSync28(sourcePath)) {
|
|
7541
7711
|
return {
|
|
7542
7712
|
success: false,
|
|
7543
7713
|
errors: [`Source file not found: ${sourcePath}`]
|
|
@@ -7545,7 +7715,7 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7545
7715
|
}
|
|
7546
7716
|
let theme;
|
|
7547
7717
|
try {
|
|
7548
|
-
theme = JSON.parse(
|
|
7718
|
+
theme = JSON.parse(readFileSync21(sourcePath, "utf-8"));
|
|
7549
7719
|
} catch (e) {
|
|
7550
7720
|
return {
|
|
7551
7721
|
success: false,
|
|
@@ -7561,14 +7731,14 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7561
7731
|
}
|
|
7562
7732
|
theme.source = "custom";
|
|
7563
7733
|
const id = theme.id;
|
|
7564
|
-
const customThemesDir =
|
|
7565
|
-
const destPath =
|
|
7566
|
-
|
|
7567
|
-
const howToPath =
|
|
7568
|
-
if (!
|
|
7569
|
-
|
|
7570
|
-
}
|
|
7571
|
-
|
|
7734
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7735
|
+
const destPath = join30(customThemesDir, `${id}.json`);
|
|
7736
|
+
mkdirSync15(customThemesDir, { recursive: true });
|
|
7737
|
+
const howToPath = join30(customThemesDir, "how-to-theme.md");
|
|
7738
|
+
if (!existsSync28(howToPath)) {
|
|
7739
|
+
writeFileSync18(howToPath, getHowToThemeDoc());
|
|
7740
|
+
}
|
|
7741
|
+
writeFileSync18(destPath, JSON.stringify(theme, null, 2));
|
|
7572
7742
|
return {
|
|
7573
7743
|
success: true,
|
|
7574
7744
|
path: destPath
|
|
@@ -7576,29 +7746,29 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7576
7746
|
}
|
|
7577
7747
|
|
|
7578
7748
|
// src/index.ts
|
|
7579
|
-
var
|
|
7580
|
-
var
|
|
7581
|
-
var
|
|
7582
|
-
var
|
|
7583
|
-
var
|
|
7749
|
+
var BOLD10 = "\x1B[1m";
|
|
7750
|
+
var DIM17 = "\x1B[2m";
|
|
7751
|
+
var RESET17 = "\x1B[0m";
|
|
7752
|
+
var RED13 = "\x1B[31m";
|
|
7753
|
+
var GREEN17 = "\x1B[32m";
|
|
7584
7754
|
var CYAN9 = "\x1B[36m";
|
|
7585
|
-
var
|
|
7755
|
+
var YELLOW13 = "\x1B[33m";
|
|
7586
7756
|
function heading2(text) {
|
|
7587
7757
|
return `
|
|
7588
|
-
${
|
|
7758
|
+
${BOLD10}${text}${RESET17}
|
|
7589
7759
|
`;
|
|
7590
7760
|
}
|
|
7591
7761
|
function success3(text) {
|
|
7592
|
-
return `${
|
|
7762
|
+
return `${GREEN17}${text}${RESET17}`;
|
|
7593
7763
|
}
|
|
7594
7764
|
function error2(text) {
|
|
7595
|
-
return `${
|
|
7765
|
+
return `${RED13}${text}${RESET17}`;
|
|
7596
7766
|
}
|
|
7597
7767
|
function dim3(text) {
|
|
7598
|
-
return `${
|
|
7768
|
+
return `${DIM17}${text}${RESET17}`;
|
|
7599
7769
|
}
|
|
7600
7770
|
function cyan3(text) {
|
|
7601
|
-
return `${CYAN9}${text}${
|
|
7771
|
+
return `${CYAN9}${text}${RESET17}`;
|
|
7602
7772
|
}
|
|
7603
7773
|
function formatIntelligenceSummary(intelligence) {
|
|
7604
7774
|
if (!intelligence) {
|
|
@@ -8102,7 +8272,7 @@ function getPublicAPIClient() {
|
|
|
8102
8272
|
});
|
|
8103
8273
|
}
|
|
8104
8274
|
function resolveUserPath(inputPath, cwd = process.cwd()) {
|
|
8105
|
-
return isAbsolute3(inputPath) ? inputPath :
|
|
8275
|
+
return isAbsolute3(inputPath) ? inputPath : resolve5(cwd, inputPath);
|
|
8106
8276
|
}
|
|
8107
8277
|
function extractHostedAssetPaths(indexHtml) {
|
|
8108
8278
|
const assetPaths = /* @__PURE__ */ new Set();
|
|
@@ -8115,18 +8285,18 @@ function extractHostedAssetPaths(indexHtml) {
|
|
|
8115
8285
|
return [...assetPaths];
|
|
8116
8286
|
}
|
|
8117
8287
|
function readHostedDistSnapshot(distPath) {
|
|
8118
|
-
const resolvedDistPath = distPath ? resolveUserPath(distPath) :
|
|
8119
|
-
const indexPath =
|
|
8120
|
-
if (!
|
|
8288
|
+
const resolvedDistPath = distPath ? resolveUserPath(distPath) : join31(process.cwd(), "dist");
|
|
8289
|
+
const indexPath = join31(resolvedDistPath, "index.html");
|
|
8290
|
+
if (!existsSync29(indexPath)) {
|
|
8121
8291
|
return void 0;
|
|
8122
8292
|
}
|
|
8123
|
-
const indexHtml =
|
|
8293
|
+
const indexHtml = readFileSync22(indexPath, "utf-8");
|
|
8124
8294
|
const assetPaths = extractHostedAssetPaths(indexHtml);
|
|
8125
8295
|
const assets = {};
|
|
8126
8296
|
for (const assetPath of assetPaths) {
|
|
8127
|
-
const assetFilePath =
|
|
8128
|
-
if (
|
|
8129
|
-
assets[assetPath] =
|
|
8297
|
+
const assetFilePath = join31(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
|
|
8298
|
+
if (existsSync29(assetFilePath)) {
|
|
8299
|
+
assets[assetPath] = readFileSync22(assetFilePath, "utf-8");
|
|
8130
8300
|
}
|
|
8131
8301
|
}
|
|
8132
8302
|
return {
|
|
@@ -8141,7 +8311,7 @@ function isHostedSourceSnapshotFile(path) {
|
|
|
8141
8311
|
function readHostedSourceSnapshot(sourcePath) {
|
|
8142
8312
|
if (!sourcePath) return void 0;
|
|
8143
8313
|
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
8144
|
-
if (!
|
|
8314
|
+
if (!existsSync29(resolvedSourcePath)) {
|
|
8145
8315
|
return void 0;
|
|
8146
8316
|
}
|
|
8147
8317
|
const files = {};
|
|
@@ -8157,15 +8327,15 @@ function readHostedSourceSnapshot(sourcePath) {
|
|
|
8157
8327
|
const walk = (absoluteDir, relativeDir) => {
|
|
8158
8328
|
for (const entry of readdirSync8(absoluteDir, { withFileTypes: true })) {
|
|
8159
8329
|
if (ignoredDirNames.has(entry.name)) continue;
|
|
8160
|
-
const absolutePath =
|
|
8161
|
-
const relativePath =
|
|
8330
|
+
const absolutePath = join31(absoluteDir, entry.name);
|
|
8331
|
+
const relativePath = join31(relativeDir, entry.name).replace(/\\/g, "/");
|
|
8162
8332
|
if (entry.isDirectory()) {
|
|
8163
8333
|
walk(absolutePath, relativePath);
|
|
8164
8334
|
continue;
|
|
8165
8335
|
}
|
|
8166
8336
|
if (!entry.isFile()) continue;
|
|
8167
8337
|
if (!isHostedSourceSnapshotFile(relativePath)) continue;
|
|
8168
|
-
files[relativePath] =
|
|
8338
|
+
files[relativePath] = readFileSync22(absolutePath, "utf-8");
|
|
8169
8339
|
}
|
|
8170
8340
|
};
|
|
8171
8341
|
walk(resolvedSourcePath, rootPrefix);
|
|
@@ -8349,7 +8519,7 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
8349
8519
|
console.log(` Files written: ${writtenContextPaths.length}`);
|
|
8350
8520
|
}
|
|
8351
8521
|
console.log("");
|
|
8352
|
-
console.log(`${
|
|
8522
|
+
console.log(`${BOLD10}Route Plan:${RESET17}`);
|
|
8353
8523
|
for (const route of typedBundle.scaffold.data.routes) {
|
|
8354
8524
|
const patterns = route.patternIds.length > 0 ? route.patternIds.join(", ") : "none";
|
|
8355
8525
|
const pageLabel = route.sectionId ? `${route.sectionId}/${route.pageId}` : route.pageId;
|
|
@@ -8358,24 +8528,24 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
8358
8528
|
}
|
|
8359
8529
|
async function compileHostedExecutionPackBundle(essencePath, namespace) {
|
|
8360
8530
|
const client = getPublicAPIClient();
|
|
8361
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8362
|
-
if (!
|
|
8531
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8532
|
+
if (!existsSync29(resolvedPath)) {
|
|
8363
8533
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8364
8534
|
}
|
|
8365
|
-
const essence = JSON.parse(
|
|
8535
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8366
8536
|
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
8367
|
-
const contextDir =
|
|
8537
|
+
const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
|
|
8368
8538
|
return { resolvedPath, bundle, contextDir };
|
|
8369
8539
|
}
|
|
8370
8540
|
function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
|
|
8371
|
-
|
|
8541
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8372
8542
|
return writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
8373
8543
|
}
|
|
8374
8544
|
function resolvePagePackIdForRoute(essencePath, route) {
|
|
8375
|
-
if (!
|
|
8545
|
+
if (!existsSync29(essencePath)) {
|
|
8376
8546
|
throw new Error(`Essence file not found at ${essencePath}`);
|
|
8377
8547
|
}
|
|
8378
|
-
const essence = JSON.parse(
|
|
8548
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8379
8549
|
if (!isV48(essence)) {
|
|
8380
8550
|
throw new Error("Route-based pack resolution requires Essence v4.0.0.");
|
|
8381
8551
|
}
|
|
@@ -8390,14 +8560,14 @@ function resolvePagePackIdForRoute(essencePath, route) {
|
|
|
8390
8560
|
}
|
|
8391
8561
|
async function printHostedSelectedExecutionPack(packType, id, essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
8392
8562
|
const client = getPublicAPIClient();
|
|
8393
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8394
|
-
if (!
|
|
8563
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8564
|
+
if (!existsSync29(resolvedPath)) {
|
|
8395
8565
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8396
8566
|
}
|
|
8397
8567
|
if ((packType === "section" || packType === "page" || packType === "mutation") && !id) {
|
|
8398
8568
|
throw new Error(`Pack type "${packType}" requires an id.`);
|
|
8399
8569
|
}
|
|
8400
|
-
const essence = JSON.parse(
|
|
8570
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8401
8571
|
const selected = await client.selectExecutionPack(
|
|
8402
8572
|
{
|
|
8403
8573
|
essence,
|
|
@@ -8408,17 +8578,17 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8408
8578
|
);
|
|
8409
8579
|
let writtenContextDir = null;
|
|
8410
8580
|
if (writeContext) {
|
|
8411
|
-
const contextDir =
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8581
|
+
const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
|
|
8582
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8583
|
+
writeFileSync19(
|
|
8584
|
+
join31(contextDir, "pack-manifest.json"),
|
|
8415
8585
|
JSON.stringify(selected.manifest, null, 2) + "\n"
|
|
8416
8586
|
);
|
|
8417
8587
|
const manifestEntry = selected.selector.packType === "scaffold" ? selected.manifest.scaffold : selected.selector.packType === "review" ? selected.manifest.review : selected.selector.packType === "section" ? selected.manifest.sections.find((entry) => entry.id === selected.selector.id) : selected.selector.packType === "page" ? selected.manifest.pages.find((entry) => entry.id === selected.selector.id) : selected.manifest.mutations.find((entry) => entry.id === selected.selector.id);
|
|
8418
8588
|
const markdownFile = manifestEntry?.markdown ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.md`;
|
|
8419
8589
|
const jsonFile = manifestEntry?.json ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.json`;
|
|
8420
|
-
|
|
8421
|
-
|
|
8590
|
+
writeFileSync19(join31(contextDir, markdownFile), selected.pack.renderedMarkdown);
|
|
8591
|
+
writeFileSync19(join31(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
|
|
8422
8592
|
writtenContextDir = contextDir;
|
|
8423
8593
|
}
|
|
8424
8594
|
if (jsonOutput) {
|
|
@@ -8443,20 +8613,20 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8443
8613
|
}
|
|
8444
8614
|
async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
8445
8615
|
const client = getPublicAPIClient();
|
|
8446
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8447
|
-
if (!
|
|
8616
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8617
|
+
if (!existsSync29(resolvedPath)) {
|
|
8448
8618
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8449
8619
|
}
|
|
8450
|
-
const essence = JSON.parse(
|
|
8620
|
+
const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
|
|
8451
8621
|
const manifest = await client.getExecutionPackManifest(
|
|
8452
8622
|
essence,
|
|
8453
8623
|
namespace ? { namespace } : void 0
|
|
8454
8624
|
);
|
|
8455
8625
|
let writtenContextDir = null;
|
|
8456
8626
|
if (writeContext) {
|
|
8457
|
-
const contextDir =
|
|
8458
|
-
|
|
8459
|
-
|
|
8627
|
+
const contextDir = join31(dirname7(resolvedPath), ".decantr", "context");
|
|
8628
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8629
|
+
writeFileSync19(join31(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
8460
8630
|
writtenContextDir = contextDir;
|
|
8461
8631
|
}
|
|
8462
8632
|
if (jsonOutput) {
|
|
@@ -8477,14 +8647,14 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
|
|
|
8477
8647
|
}
|
|
8478
8648
|
}
|
|
8479
8649
|
async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@official") {
|
|
8480
|
-
const contextDir =
|
|
8481
|
-
const reviewPackPath =
|
|
8482
|
-
const manifestPath =
|
|
8483
|
-
if (
|
|
8650
|
+
const contextDir = join31(projectRoot, ".decantr", "context");
|
|
8651
|
+
const reviewPackPath = join31(contextDir, "review-pack.json");
|
|
8652
|
+
const manifestPath = join31(contextDir, "pack-manifest.json");
|
|
8653
|
+
if (existsSync29(reviewPackPath) && existsSync29(manifestPath)) {
|
|
8484
8654
|
return { attempted: false, hydrated: false };
|
|
8485
8655
|
}
|
|
8486
|
-
const essencePath =
|
|
8487
|
-
if (!
|
|
8656
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
8657
|
+
if (!existsSync29(essencePath)) {
|
|
8488
8658
|
return { attempted: false, hydrated: false };
|
|
8489
8659
|
}
|
|
8490
8660
|
const reviewHydration = await hydrateHostedReviewPackIfMissing(projectRoot, namespace);
|
|
@@ -8493,9 +8663,9 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
8493
8663
|
}
|
|
8494
8664
|
try {
|
|
8495
8665
|
const client = getPublicAPIClient();
|
|
8496
|
-
const essence = JSON.parse(
|
|
8666
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8497
8667
|
const bundle = await client.compileExecutionPacks(essence, { namespace });
|
|
8498
|
-
|
|
8668
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8499
8669
|
writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
8500
8670
|
return { attempted: true, hydrated: true, scope: "bundle" };
|
|
8501
8671
|
} catch {
|
|
@@ -8503,19 +8673,19 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
8503
8673
|
}
|
|
8504
8674
|
}
|
|
8505
8675
|
async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@official") {
|
|
8506
|
-
const contextDir =
|
|
8507
|
-
const reviewPackPath =
|
|
8508
|
-
const manifestPath =
|
|
8509
|
-
if (
|
|
8676
|
+
const contextDir = join31(projectRoot, ".decantr", "context");
|
|
8677
|
+
const reviewPackPath = join31(contextDir, "review-pack.json");
|
|
8678
|
+
const manifestPath = join31(contextDir, "pack-manifest.json");
|
|
8679
|
+
if (existsSync29(reviewPackPath) && existsSync29(manifestPath)) {
|
|
8510
8680
|
return { attempted: false, hydrated: false };
|
|
8511
8681
|
}
|
|
8512
|
-
const essencePath =
|
|
8513
|
-
if (!
|
|
8682
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
8683
|
+
if (!existsSync29(essencePath)) {
|
|
8514
8684
|
return { attempted: false, hydrated: false };
|
|
8515
8685
|
}
|
|
8516
8686
|
try {
|
|
8517
8687
|
const client = getPublicAPIClient();
|
|
8518
|
-
const essence = JSON.parse(
|
|
8688
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
8519
8689
|
const selected = await client.selectExecutionPack(
|
|
8520
8690
|
{
|
|
8521
8691
|
essence,
|
|
@@ -8523,14 +8693,14 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
8523
8693
|
},
|
|
8524
8694
|
{ namespace }
|
|
8525
8695
|
);
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
8696
|
+
mkdirSync16(contextDir, { recursive: true });
|
|
8697
|
+
writeFileSync19(join31(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
|
|
8698
|
+
writeFileSync19(
|
|
8699
|
+
join31(contextDir, "review-pack.json"),
|
|
8530
8700
|
JSON.stringify(selected.pack, null, 2) + "\n"
|
|
8531
8701
|
);
|
|
8532
|
-
if (!
|
|
8533
|
-
|
|
8702
|
+
if (!existsSync29(manifestPath)) {
|
|
8703
|
+
writeFileSync19(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
|
|
8534
8704
|
}
|
|
8535
8705
|
return { attempted: true, hydrated: true, scope: "review" };
|
|
8536
8706
|
} catch {
|
|
@@ -8540,17 +8710,17 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
8540
8710
|
async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false, essencePath, treatmentsPath) {
|
|
8541
8711
|
const client = getPublicAPIClient();
|
|
8542
8712
|
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
8543
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) :
|
|
8544
|
-
const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) :
|
|
8545
|
-
if (!
|
|
8713
|
+
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8714
|
+
const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join31(process.cwd(), "src", "styles", "treatments.css");
|
|
8715
|
+
if (!existsSync29(resolvedSourcePath)) {
|
|
8546
8716
|
throw new Error(`Source file not found at ${resolvedSourcePath}`);
|
|
8547
8717
|
}
|
|
8548
|
-
if (!
|
|
8718
|
+
if (!existsSync29(resolvedEssencePath)) {
|
|
8549
8719
|
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
8550
8720
|
}
|
|
8551
|
-
const code =
|
|
8552
|
-
const essence = JSON.parse(
|
|
8553
|
-
const treatmentsCss =
|
|
8721
|
+
const code = readFileSync22(resolvedSourcePath, "utf-8");
|
|
8722
|
+
const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
|
|
8723
|
+
const treatmentsCss = existsSync29(resolvedTreatmentsPath) ? readFileSync22(resolvedTreatmentsPath, "utf-8") : void 0;
|
|
8554
8724
|
const report = await client.critiqueFile(
|
|
8555
8725
|
{
|
|
8556
8726
|
essence,
|
|
@@ -8574,11 +8744,11 @@ async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false
|
|
|
8574
8744
|
}
|
|
8575
8745
|
async function printHostedProjectAudit(namespace, jsonOutput = false, essencePath, distPath, sourcesPath) {
|
|
8576
8746
|
const client = getPublicAPIClient();
|
|
8577
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) :
|
|
8578
|
-
if (!
|
|
8747
|
+
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8748
|
+
if (!existsSync29(resolvedEssencePath)) {
|
|
8579
8749
|
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
8580
8750
|
}
|
|
8581
|
-
const essence = JSON.parse(
|
|
8751
|
+
const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
|
|
8582
8752
|
const dist = readHostedDistSnapshot(distPath);
|
|
8583
8753
|
const sources = readHostedSourceSnapshot(sourcesPath);
|
|
8584
8754
|
const report = await client.auditProject(
|
|
@@ -8596,7 +8766,7 @@ async function printHostedProjectAudit(namespace, jsonOutput = false, essencePat
|
|
|
8596
8766
|
console.log(heading2("Hosted Project Audit"));
|
|
8597
8767
|
console.log(` Essence: ${resolvedEssencePath}`);
|
|
8598
8768
|
console.log(
|
|
8599
|
-
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) :
|
|
8769
|
+
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join31(process.cwd(), "dist") : "none"}`
|
|
8600
8770
|
);
|
|
8601
8771
|
console.log(
|
|
8602
8772
|
` Source snapshot: ${sources && sourcesPath ? resolveUserPath(sourcesPath) : "none"}`
|
|
@@ -8625,7 +8795,7 @@ function printBlueprintPortfolioNotice(blueprint) {
|
|
|
8625
8795
|
if (!portfolio) return;
|
|
8626
8796
|
if (portfolio.visibility === "hidden" || portfolio.maturity === "fold-candidate") {
|
|
8627
8797
|
console.log(
|
|
8628
|
-
`${
|
|
8798
|
+
`${YELLOW13} Warning:${RESET17} blueprint "${blueprint.id}" is folded out of public browsing.`
|
|
8629
8799
|
);
|
|
8630
8800
|
if (portfolio.recommended_alternative) {
|
|
8631
8801
|
console.log(
|
|
@@ -8638,7 +8808,7 @@ function printBlueprintPortfolioNotice(blueprint) {
|
|
|
8638
8808
|
}
|
|
8639
8809
|
if (portfolio.visibility === "labs") {
|
|
8640
8810
|
console.log(
|
|
8641
|
-
`${
|
|
8811
|
+
`${YELLOW13} Note:${RESET17} blueprint "${blueprint.id}" is a Labs blueprint; direct scaffolding is supported, but it is not a default recommendation yet.`
|
|
8642
8812
|
);
|
|
8643
8813
|
}
|
|
8644
8814
|
}
|
|
@@ -8660,7 +8830,7 @@ async function cmdSearch(query, type, sort, recommended, intelligenceSource, blu
|
|
|
8660
8830
|
}
|
|
8661
8831
|
console.log(heading2(`${results.length} result(s) for "${query}"`));
|
|
8662
8832
|
for (const r of results) {
|
|
8663
|
-
console.log(` ${cyan3(r.type.padEnd(12))} ${
|
|
8833
|
+
console.log(` ${cyan3(r.type.padEnd(12))} ${BOLD10}${r.slug}${RESET17}`);
|
|
8664
8834
|
console.log(` ${dim3(r.description || "")}`);
|
|
8665
8835
|
const intelligenceSummary = formatIntelligenceSummary(r.intelligence);
|
|
8666
8836
|
if (intelligenceSummary) {
|
|
@@ -8718,21 +8888,21 @@ function findPatternCandidateBySlug(candidates, slug) {
|
|
|
8718
8888
|
function readSuggestCodeContext(projectRoot, route, file) {
|
|
8719
8889
|
const pieces = [];
|
|
8720
8890
|
if (file) {
|
|
8721
|
-
const resolved = isAbsolute3(file) ? file :
|
|
8722
|
-
if (
|
|
8723
|
-
pieces.push(
|
|
8891
|
+
const resolved = isAbsolute3(file) ? file : join31(projectRoot, file);
|
|
8892
|
+
if (existsSync29(resolved)) {
|
|
8893
|
+
pieces.push(readFileSync22(resolved, "utf-8"));
|
|
8724
8894
|
}
|
|
8725
8895
|
}
|
|
8726
8896
|
if (route) {
|
|
8727
|
-
const analysisPath =
|
|
8728
|
-
if (
|
|
8897
|
+
const analysisPath = join31(projectRoot, ".decantr", "analysis.json");
|
|
8898
|
+
if (existsSync29(analysisPath)) {
|
|
8729
8899
|
try {
|
|
8730
|
-
const analysis = JSON.parse(
|
|
8900
|
+
const analysis = JSON.parse(readFileSync22(analysisPath, "utf-8"));
|
|
8731
8901
|
const routeEntry = analysis.routes?.routes?.find((entry) => entry.path === route);
|
|
8732
8902
|
if (routeEntry?.file) {
|
|
8733
|
-
const resolved =
|
|
8734
|
-
if (
|
|
8735
|
-
pieces.push(
|
|
8903
|
+
const resolved = join31(projectRoot, routeEntry.file);
|
|
8904
|
+
if (existsSync29(resolved)) {
|
|
8905
|
+
pieces.push(readFileSync22(resolved, "utf-8"));
|
|
8736
8906
|
}
|
|
8737
8907
|
}
|
|
8738
8908
|
} catch {
|
|
@@ -8818,7 +8988,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8818
8988
|
}
|
|
8819
8989
|
}
|
|
8820
8990
|
const registryClient = new RegistryClient({
|
|
8821
|
-
cacheDir:
|
|
8991
|
+
cacheDir: join31(projectRoot, ".decantr", "cache")
|
|
8822
8992
|
});
|
|
8823
8993
|
const code = options.fromCode || options.file ? readSuggestCodeContext(projectRoot, options.route, options.file) : "";
|
|
8824
8994
|
const localMatches = localPatternMatches(projectRoot, [query, code].filter(Boolean).join("\n"));
|
|
@@ -8854,7 +9024,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8854
9024
|
)
|
|
8855
9025
|
);
|
|
8856
9026
|
if (bridgeMatches.length > 0) {
|
|
8857
|
-
console.log(`${
|
|
9027
|
+
console.log(`${BOLD10}Project-owned style bridge:${RESET17}`);
|
|
8858
9028
|
for (const match of bridgeMatches) {
|
|
8859
9029
|
const hints = [...match.tokenHints, ...match.classHints].slice(0, 3).join(", ");
|
|
8860
9030
|
console.log(` ${cyan3(match.id)} ${match.label}${hints ? ` ${dim3(hints)}` : ""}`);
|
|
@@ -8862,13 +9032,13 @@ async function cmdSuggest(query, options = {}) {
|
|
|
8862
9032
|
console.log("");
|
|
8863
9033
|
}
|
|
8864
9034
|
if (localMatches.length > 0) {
|
|
8865
|
-
console.log(`${
|
|
9035
|
+
console.log(`${BOLD10}Project-owned local law:${RESET17}`);
|
|
8866
9036
|
for (const match of localMatches) {
|
|
8867
9037
|
const details = [match.label, match.role].filter(Boolean).join(" | ");
|
|
8868
9038
|
console.log(` ${cyan3(match.id)}${details ? ` ${dim3(details)}` : ""}`);
|
|
8869
9039
|
}
|
|
8870
9040
|
console.log("");
|
|
8871
|
-
console.log(`${
|
|
9041
|
+
console.log(`${BOLD10}Registry patterns:${RESET17}`);
|
|
8872
9042
|
}
|
|
8873
9043
|
if (matches.length === 0) {
|
|
8874
9044
|
console.log(dim3("No hosted/bundled registry patterns matched this query."));
|
|
@@ -8907,7 +9077,7 @@ async function cmdGet(type, id) {
|
|
|
8907
9077
|
}
|
|
8908
9078
|
const apiType = CONTENT_TYPE_TO_API_CONTENT_TYPE3[type];
|
|
8909
9079
|
const registryClient = new RegistryClient({
|
|
8910
|
-
cacheDir:
|
|
9080
|
+
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
8911
9081
|
});
|
|
8912
9082
|
const result = await registryClient.fetchContentItem(apiType, id);
|
|
8913
9083
|
if (result) {
|
|
@@ -8924,10 +9094,10 @@ async function cmdGet(type, id) {
|
|
|
8924
9094
|
return;
|
|
8925
9095
|
}
|
|
8926
9096
|
async function cmdValidate(path) {
|
|
8927
|
-
const essencePath = path ||
|
|
9097
|
+
const essencePath = path || join31(process.cwd(), "decantr.essence.json");
|
|
8928
9098
|
let raw;
|
|
8929
9099
|
try {
|
|
8930
|
-
raw =
|
|
9100
|
+
raw = readFileSync22(essencePath, "utf-8");
|
|
8931
9101
|
} catch {
|
|
8932
9102
|
console.error(error2(`Could not read ${essencePath}`));
|
|
8933
9103
|
process.exitCode = 1;
|
|
@@ -8942,14 +9112,14 @@ async function cmdValidate(path) {
|
|
|
8942
9112
|
return;
|
|
8943
9113
|
}
|
|
8944
9114
|
const detectedVersion = isV48(essence) ? "v4" : "legacy";
|
|
8945
|
-
console.log(`${
|
|
9115
|
+
console.log(`${DIM17}Detected essence version: ${detectedVersion}${RESET17}`);
|
|
8946
9116
|
const result = validateEssence2(essence);
|
|
8947
9117
|
if (result.valid) {
|
|
8948
9118
|
console.log(success3(`Essence is valid (${detectedVersion}).`));
|
|
8949
9119
|
} else {
|
|
8950
9120
|
console.error(error2("Validation failed:"));
|
|
8951
9121
|
for (const err of result.errors) {
|
|
8952
|
-
console.error(` ${
|
|
9122
|
+
console.error(` ${RED13}${err}${RESET17}`);
|
|
8953
9123
|
}
|
|
8954
9124
|
process.exitCode = 1;
|
|
8955
9125
|
return;
|
|
@@ -8970,9 +9140,9 @@ async function cmdValidate(path) {
|
|
|
8970
9140
|
console.log(heading2("Guard violations:"));
|
|
8971
9141
|
for (const v of violations) {
|
|
8972
9142
|
const vr = v;
|
|
8973
|
-
console.log(` ${
|
|
9143
|
+
console.log(` ${YELLOW13}[${vr.rule}]${RESET17} ${vr.message}`);
|
|
8974
9144
|
if (vr.suggestion) {
|
|
8975
|
-
console.log(` ${
|
|
9145
|
+
console.log(` ${DIM17}Suggestion: ${vr.suggestion}${RESET17}`);
|
|
8976
9146
|
}
|
|
8977
9147
|
}
|
|
8978
9148
|
const hasError = violations.some((v) => v.severity === "error");
|
|
@@ -8994,7 +9164,7 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
|
|
|
8994
9164
|
return;
|
|
8995
9165
|
}
|
|
8996
9166
|
const registryClient = new RegistryClient({
|
|
8997
|
-
cacheDir:
|
|
9167
|
+
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
8998
9168
|
});
|
|
8999
9169
|
const result = await registryClient.fetchContentList(
|
|
9000
9170
|
type,
|
|
@@ -9071,16 +9241,16 @@ function enableCliTelemetry(projectRoot) {
|
|
|
9071
9241
|
optIn(projectRoot);
|
|
9072
9242
|
console.log(
|
|
9073
9243
|
`
|
|
9074
|
-
${CYAN9}Telemetry enabled.${
|
|
9244
|
+
${CYAN9}Telemetry enabled.${RESET17} Decantr will send privacy-filtered CLI product telemetry for this project.`
|
|
9075
9245
|
);
|
|
9076
|
-
console.log(`${
|
|
9246
|
+
console.log(`${DIM17}Set "telemetry": false in .decantr/project.json to opt out.${RESET17}`);
|
|
9077
9247
|
}
|
|
9078
9248
|
function readCliPackageVersion2() {
|
|
9079
|
-
const here =
|
|
9080
|
-
const candidates = [
|
|
9249
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
9250
|
+
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
9081
9251
|
for (const candidate of candidates) {
|
|
9082
9252
|
try {
|
|
9083
|
-
const pkg = JSON.parse(
|
|
9253
|
+
const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
|
|
9084
9254
|
if (pkg.version) return pkg.version;
|
|
9085
9255
|
} catch {
|
|
9086
9256
|
}
|
|
@@ -9091,19 +9261,19 @@ function timestampForFile() {
|
|
|
9091
9261
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9092
9262
|
}
|
|
9093
9263
|
function backupExistingEssence(projectRoot, label) {
|
|
9094
|
-
const essencePath =
|
|
9095
|
-
if (!
|
|
9096
|
-
const backupPath =
|
|
9264
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
9265
|
+
if (!existsSync29(essencePath)) return null;
|
|
9266
|
+
const backupPath = join31(
|
|
9097
9267
|
projectRoot,
|
|
9098
9268
|
`decantr.essence.${label}.${timestampForFile()}.backup.json`
|
|
9099
9269
|
);
|
|
9100
|
-
|
|
9270
|
+
writeFileSync19(backupPath, readFileSync22(essencePath, "utf-8"), "utf-8");
|
|
9101
9271
|
return backupPath;
|
|
9102
9272
|
}
|
|
9103
9273
|
function writeBrownfieldProjectJson(input) {
|
|
9104
|
-
const decantrDir =
|
|
9105
|
-
|
|
9106
|
-
|
|
9274
|
+
const decantrDir = join31(input.projectRoot, ".decantr");
|
|
9275
|
+
mkdirSync16(join31(decantrDir, "context"), { recursive: true });
|
|
9276
|
+
mkdirSync16(join31(decantrDir, "cache"), { recursive: true });
|
|
9107
9277
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9108
9278
|
const projectJson = {
|
|
9109
9279
|
detected: {
|
|
@@ -9144,7 +9314,7 @@ function writeBrownfieldProjectJson(input) {
|
|
|
9144
9314
|
}
|
|
9145
9315
|
}
|
|
9146
9316
|
};
|
|
9147
|
-
|
|
9317
|
+
writeFileSync19(join31(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
|
|
9148
9318
|
}
|
|
9149
9319
|
async function applyAcceptedBrownfieldProposal(input) {
|
|
9150
9320
|
const proposal = readBrownfieldProposal(input.projectRoot);
|
|
@@ -9160,8 +9330,8 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9160
9330
|
process.exitCode = 1;
|
|
9161
9331
|
return;
|
|
9162
9332
|
}
|
|
9163
|
-
const essencePath =
|
|
9164
|
-
const hasEssence =
|
|
9333
|
+
const essencePath = join31(input.projectRoot, "decantr.essence.json");
|
|
9334
|
+
const hasEssence = existsSync29(essencePath);
|
|
9165
9335
|
let essence;
|
|
9166
9336
|
let backupPath = null;
|
|
9167
9337
|
if (input.mode === "accept" && hasEssence) {
|
|
@@ -9175,7 +9345,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9175
9345
|
return;
|
|
9176
9346
|
}
|
|
9177
9347
|
if (input.mode === "merge" && hasEssence) {
|
|
9178
|
-
const existing = JSON.parse(
|
|
9348
|
+
const existing = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
9179
9349
|
if (!isV48(existing)) {
|
|
9180
9350
|
console.log(
|
|
9181
9351
|
error2(
|
|
@@ -9195,7 +9365,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9195
9365
|
error2("Brownfield proposal produced an invalid Decantr essence. No files were changed.")
|
|
9196
9366
|
);
|
|
9197
9367
|
for (const validationError of validation.errors) {
|
|
9198
|
-
console.log(` ${
|
|
9368
|
+
console.log(` ${RED13}${validationError}${RESET17}`);
|
|
9199
9369
|
}
|
|
9200
9370
|
process.exitCode = 1;
|
|
9201
9371
|
return;
|
|
@@ -9212,9 +9382,9 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9212
9382
|
assistantBridge: input.assistantBridge,
|
|
9213
9383
|
mode: input.mode
|
|
9214
9384
|
});
|
|
9215
|
-
|
|
9385
|
+
writeFileSync19(essencePath, JSON.stringify(essence, null, 2) + "\n", "utf-8");
|
|
9216
9386
|
const registryClient = new RegistryClient({
|
|
9217
|
-
cacheDir:
|
|
9387
|
+
cacheDir: join31(input.projectRoot, ".decantr", "cache"),
|
|
9218
9388
|
offline: true,
|
|
9219
9389
|
projectRoot: input.projectRoot
|
|
9220
9390
|
});
|
|
@@ -9309,7 +9479,7 @@ async function cmdInit(args) {
|
|
|
9309
9479
|
console.log(dim3(" Found .decantr/init-seed.json brownfield guidance."));
|
|
9310
9480
|
}
|
|
9311
9481
|
if (detected.existingEssence && !args.existing) {
|
|
9312
|
-
console.log(`${
|
|
9482
|
+
console.log(`${YELLOW13}Warning: decantr.essence.json already exists.${RESET17}`);
|
|
9313
9483
|
const overwrite = await confirm("Overwrite existing configuration?", false);
|
|
9314
9484
|
if (!overwrite) {
|
|
9315
9485
|
console.log(dim3("Cancelled."));
|
|
@@ -9393,7 +9563,7 @@ async function cmdInit(args) {
|
|
|
9393
9563
|
}
|
|
9394
9564
|
}
|
|
9395
9565
|
const registryClient = new RegistryClient({
|
|
9396
|
-
cacheDir:
|
|
9566
|
+
cacheDir: join31(projectRoot, ".decantr", "cache"),
|
|
9397
9567
|
apiUrl: args.registry,
|
|
9398
9568
|
offline: args.offline,
|
|
9399
9569
|
projectRoot
|
|
@@ -9413,7 +9583,7 @@ async function cmdInit(args) {
|
|
|
9413
9583
|
} else if (shouldUseRegistry && !apiAvailable) {
|
|
9414
9584
|
if (!args.blueprint) {
|
|
9415
9585
|
console.log(`
|
|
9416
|
-
${
|
|
9586
|
+
${YELLOW13}You're offline. Scaffolding minimal Decantr project.${RESET17}`);
|
|
9417
9587
|
console.log(
|
|
9418
9588
|
dim3("Run `decantr sync` or `decantr upgrade` when online to pull full registry content.\n")
|
|
9419
9589
|
);
|
|
@@ -9462,7 +9632,7 @@ ${YELLOW12}You're offline. Scaffolding minimal Decantr project.${RESET16}`);
|
|
|
9462
9632
|
return;
|
|
9463
9633
|
}
|
|
9464
9634
|
console.log(`
|
|
9465
|
-
${
|
|
9635
|
+
${YELLOW13}You're offline. Scaffolding Decantr default.${RESET17}`);
|
|
9466
9636
|
console.log(dim3("Run `decantr upgrade` when online, or visit decantr.ai/registry\n"));
|
|
9467
9637
|
selectedBlueprint = "default";
|
|
9468
9638
|
} else if (shouldUseRegistry) {
|
|
@@ -9644,7 +9814,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9644
9814
|
return;
|
|
9645
9815
|
}
|
|
9646
9816
|
console.log(
|
|
9647
|
-
`${
|
|
9817
|
+
`${YELLOW13} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET17}`
|
|
9648
9818
|
);
|
|
9649
9819
|
}
|
|
9650
9820
|
} else if (shouldUseRegistry && options.archetype) {
|
|
@@ -9659,7 +9829,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9659
9829
|
return;
|
|
9660
9830
|
}
|
|
9661
9831
|
console.log(
|
|
9662
|
-
`${
|
|
9832
|
+
`${YELLOW13} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET17}`
|
|
9663
9833
|
);
|
|
9664
9834
|
}
|
|
9665
9835
|
}
|
|
@@ -9676,7 +9846,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9676
9846
|
return;
|
|
9677
9847
|
}
|
|
9678
9848
|
console.log(
|
|
9679
|
-
`${
|
|
9849
|
+
`${YELLOW13} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET17}`
|
|
9680
9850
|
);
|
|
9681
9851
|
}
|
|
9682
9852
|
}
|
|
@@ -9725,7 +9895,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9725
9895
|
if (appliedRuleFiles.length > 0) {
|
|
9726
9896
|
console.log(` ${dim3(`Rule bridge applied: ${appliedRuleFiles.join(", ")}`)}`);
|
|
9727
9897
|
}
|
|
9728
|
-
if (!
|
|
9898
|
+
if (!existsSync29(join31(projectRoot, "package.json"))) {
|
|
9729
9899
|
console.log("");
|
|
9730
9900
|
console.log(
|
|
9731
9901
|
dim3(` Note: ${cyan3("decantr init")} created Decantr contract/context files only.`)
|
|
@@ -9736,7 +9906,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9736
9906
|
)
|
|
9737
9907
|
);
|
|
9738
9908
|
}
|
|
9739
|
-
const hasCompiledPacks =
|
|
9909
|
+
const hasCompiledPacks = existsSync29(join31(projectRoot, ".decantr", "context", "scaffold-pack.md"));
|
|
9740
9910
|
console.log("");
|
|
9741
9911
|
console.log(" Next steps:");
|
|
9742
9912
|
if (hasCompiledPacks) {
|
|
@@ -9776,7 +9946,7 @@ ${YELLOW12}You're offline. Scaffolding Decantr default.${RESET16}`);
|
|
|
9776
9946
|
console.log(` ${cyan3("decantr upgrade")} Update to latest patterns`);
|
|
9777
9947
|
console.log(` ${cyan3("decantr check")} Detect drift issues`);
|
|
9778
9948
|
console.log(` ${cyan3("decantr migrate --to v4")} Migrate older essence files to v4`);
|
|
9779
|
-
const essenceContent =
|
|
9949
|
+
const essenceContent = readFileSync22(result.essencePath, "utf-8");
|
|
9780
9950
|
const essence = JSON.parse(essenceContent);
|
|
9781
9951
|
const validation = validateEssence2(essence);
|
|
9782
9952
|
if (!validation.valid) {
|
|
@@ -9819,7 +9989,7 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
9819
9989
|
};
|
|
9820
9990
|
const curatedPrompt = generateCuratedPrompt(promptCtx);
|
|
9821
9991
|
console.log("");
|
|
9822
|
-
console.log(`${
|
|
9992
|
+
console.log(`${BOLD10}Prompt for your AI assistant:${RESET17}`);
|
|
9823
9993
|
console.log(dim3("\u2500".repeat(50)));
|
|
9824
9994
|
console.log("");
|
|
9825
9995
|
console.log(curatedPrompt);
|
|
@@ -9831,23 +10001,23 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
9831
10001
|
}
|
|
9832
10002
|
}
|
|
9833
10003
|
async function cmdStatus(projectRoot = process.cwd()) {
|
|
9834
|
-
const essencePath =
|
|
9835
|
-
const projectJsonPath =
|
|
10004
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
10005
|
+
const projectJsonPath = join31(projectRoot, ".decantr", "project.json");
|
|
9836
10006
|
console.log(heading2("Decantr Project Status"));
|
|
9837
|
-
if (!
|
|
9838
|
-
console.log(`${
|
|
10007
|
+
if (!existsSync29(essencePath)) {
|
|
10008
|
+
console.log(`${RED13}No decantr.essence.json found.${RESET17}`);
|
|
9839
10009
|
console.log(dim3('Run "decantr init" to create one.'));
|
|
9840
10010
|
return;
|
|
9841
10011
|
}
|
|
9842
10012
|
try {
|
|
9843
|
-
const essence = JSON.parse(
|
|
10013
|
+
const essence = JSON.parse(readFileSync22(essencePath, "utf-8"));
|
|
9844
10014
|
const validation = validateEssence2(essence);
|
|
9845
10015
|
const essenceVersion = isV48(essence) ? "v4" : "legacy";
|
|
9846
|
-
console.log(`${
|
|
10016
|
+
console.log(`${BOLD10}Essence:${RESET17}`);
|
|
9847
10017
|
if (validation.valid) {
|
|
9848
|
-
console.log(` ${
|
|
10018
|
+
console.log(` ${GREEN17}Valid${RESET17} (${essenceVersion})`);
|
|
9849
10019
|
} else {
|
|
9850
|
-
console.log(` ${
|
|
10020
|
+
console.log(` ${RED13}Invalid: ${validation.errors.join(", ")}${RESET17}`);
|
|
9851
10021
|
}
|
|
9852
10022
|
if (isV48(essence)) {
|
|
9853
10023
|
const v4 = essence;
|
|
@@ -9855,7 +10025,7 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
9855
10025
|
const flatPages = sections.flatMap((section) => section.pages ?? []);
|
|
9856
10026
|
const resolvedShell = sections.find((section) => section.role === "primary")?.shell || sections[0]?.shell || v4.blueprint.shell || "unknown";
|
|
9857
10027
|
const resolvedFeatures = v4.blueprint.features ?? [];
|
|
9858
|
-
console.log(` ${
|
|
10028
|
+
console.log(` ${BOLD10}DNA:${RESET17}`);
|
|
9859
10029
|
console.log(` Theme: ${v4.dna.theme.id} (${v4.dna.theme.mode})`);
|
|
9860
10030
|
console.log(
|
|
9861
10031
|
` Spacing: ${v4.dna.spacing.density} density, ${v4.dna.spacing.content_gap} gap`
|
|
@@ -9867,60 +10037,60 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
9867
10037
|
);
|
|
9868
10038
|
console.log(` Accessibility: WCAG ${v4.dna.accessibility.wcag_level}`);
|
|
9869
10039
|
console.log(` Personality: ${v4.dna.personality.join(", ")}`);
|
|
9870
|
-
console.log(` ${
|
|
10040
|
+
console.log(` ${BOLD10}Blueprint:${RESET17}`);
|
|
9871
10041
|
console.log(` Shell: ${resolvedShell}`);
|
|
9872
10042
|
console.log(` Pages: ${flatPages.length}`);
|
|
9873
10043
|
console.log(` Sections: ${sections.length}`);
|
|
9874
10044
|
console.log(
|
|
9875
10045
|
` Features: ${resolvedFeatures.length > 0 ? resolvedFeatures.join(", ") : "none"}`
|
|
9876
10046
|
);
|
|
9877
|
-
console.log(` ${
|
|
10047
|
+
console.log(` ${BOLD10}Meta:${RESET17}`);
|
|
9878
10048
|
console.log(` Archetype: ${v4.meta.archetype}`);
|
|
9879
10049
|
console.log(` Target: ${v4.meta.target}`);
|
|
9880
10050
|
console.log(
|
|
9881
10051
|
` Guard: ${v4.meta.guard.mode} (DNA: ${v4.meta.guard.dna_enforcement}, Blueprint: ${v4.meta.guard.blueprint_enforcement})`
|
|
9882
10052
|
);
|
|
9883
10053
|
} else {
|
|
9884
|
-
console.log(` ${
|
|
10054
|
+
console.log(` ${YELLOW13}Run \`decantr migrate --to v4\` to upgrade this project.${RESET17}`);
|
|
9885
10055
|
}
|
|
9886
10056
|
} catch (e) {
|
|
9887
|
-
console.log(` ${
|
|
10057
|
+
console.log(` ${RED13}Error reading essence: ${e.message}${RESET17}`);
|
|
9888
10058
|
}
|
|
9889
10059
|
console.log("");
|
|
9890
|
-
console.log(`${
|
|
9891
|
-
if (
|
|
10060
|
+
console.log(`${BOLD10}Sync Status:${RESET17}`);
|
|
10061
|
+
if (existsSync29(projectJsonPath)) {
|
|
9892
10062
|
try {
|
|
9893
|
-
const projectJson = JSON.parse(
|
|
10063
|
+
const projectJson = JSON.parse(readFileSync22(projectJsonPath, "utf-8"));
|
|
9894
10064
|
const syncStatus = projectJson.sync?.status || "unknown";
|
|
9895
10065
|
const lastSync = projectJson.sync?.lastSync || "never";
|
|
9896
10066
|
const source = projectJson.sync?.registrySource || "unknown";
|
|
9897
|
-
const statusColor = syncStatus === "synced" ?
|
|
9898
|
-
console.log(` Status: ${statusColor}${syncStatus}${
|
|
10067
|
+
const statusColor = syncStatus === "synced" ? GREEN17 : YELLOW13;
|
|
10068
|
+
console.log(` Status: ${statusColor}${syncStatus}${RESET17}`);
|
|
9899
10069
|
console.log(` Last sync: ${dim3(lastSync)}`);
|
|
9900
10070
|
console.log(` Source: ${dim3(source)}`);
|
|
9901
10071
|
} catch {
|
|
9902
|
-
console.log(` ${
|
|
10072
|
+
console.log(` ${YELLOW13}Could not read project.json${RESET17}`);
|
|
9903
10073
|
}
|
|
9904
10074
|
} else {
|
|
9905
|
-
console.log(` ${
|
|
10075
|
+
console.log(` ${YELLOW13}No .decantr/project.json found${RESET17}`);
|
|
9906
10076
|
console.log(dim3(' Run "decantr init" to create project files.'));
|
|
9907
10077
|
}
|
|
9908
10078
|
}
|
|
9909
10079
|
async function cmdSync() {
|
|
9910
10080
|
const projectRoot = process.cwd();
|
|
9911
|
-
const cacheDir =
|
|
10081
|
+
const cacheDir = join31(projectRoot, ".decantr", "cache");
|
|
9912
10082
|
console.log(heading2("Syncing registry content..."));
|
|
9913
10083
|
const result = await syncRegistry(cacheDir);
|
|
9914
10084
|
if (result.synced.length > 0) {
|
|
9915
10085
|
console.log(success3("Sync completed successfully."));
|
|
9916
10086
|
console.log(` Synced: ${result.synced.join(", ")}`);
|
|
9917
10087
|
if (result.failed.length > 0) {
|
|
9918
|
-
console.log(` ${
|
|
10088
|
+
console.log(` ${YELLOW13}Failed: ${result.failed.join(", ")}${RESET17}`);
|
|
9919
10089
|
}
|
|
9920
10090
|
} else {
|
|
9921
|
-
console.log(`${
|
|
10091
|
+
console.log(`${YELLOW13}Could not sync: API unavailable${RESET17}`);
|
|
9922
10092
|
if (result.failed.length > 0) {
|
|
9923
|
-
console.log(` ${
|
|
10093
|
+
console.log(` ${YELLOW13}Failed: ${result.failed.join(", ")}${RESET17}`);
|
|
9924
10094
|
}
|
|
9925
10095
|
}
|
|
9926
10096
|
}
|
|
@@ -9930,15 +10100,15 @@ function printVerificationFindings(findings) {
|
|
|
9930
10100
|
return;
|
|
9931
10101
|
}
|
|
9932
10102
|
for (const finding of findings) {
|
|
9933
|
-
const color = finding.severity === "error" ?
|
|
10103
|
+
const color = finding.severity === "error" ? RED13 : finding.severity === "warn" ? YELLOW13 : CYAN9;
|
|
9934
10104
|
console.log(
|
|
9935
|
-
` ${color}[${finding.severity.toUpperCase()}]${
|
|
10105
|
+
` ${color}[${finding.severity.toUpperCase()}]${RESET17} ${finding.category}: ${finding.message}`
|
|
9936
10106
|
);
|
|
9937
10107
|
for (const evidence of finding.evidence) {
|
|
9938
|
-
console.log(` ${
|
|
10108
|
+
console.log(` ${DIM17}${evidence}${RESET17}`);
|
|
9939
10109
|
}
|
|
9940
10110
|
if (finding.suggestedFix) {
|
|
9941
|
-
console.log(` ${
|
|
10111
|
+
console.log(` ${DIM17}Fix: ${finding.suggestedFix}${RESET17}`);
|
|
9942
10112
|
}
|
|
9943
10113
|
}
|
|
9944
10114
|
}
|
|
@@ -9946,10 +10116,10 @@ function printProjectAuditReport(report) {
|
|
|
9946
10116
|
if (report.valid) {
|
|
9947
10117
|
console.log(success3("Project contract is valid."));
|
|
9948
10118
|
} else {
|
|
9949
|
-
console.log(`${
|
|
10119
|
+
console.log(`${RED13}Project audit found blocking issues.${RESET17}`);
|
|
9950
10120
|
}
|
|
9951
10121
|
console.log("");
|
|
9952
|
-
console.log(`${
|
|
10122
|
+
console.log(`${BOLD10}Summary:${RESET17}`);
|
|
9953
10123
|
console.log(` Essence version: ${report.summary.essenceVersion ?? "missing"}`);
|
|
9954
10124
|
console.log(` Pages defined: ${report.summary.pageCount}`);
|
|
9955
10125
|
console.log(` Pack manifest: ${report.summary.packManifestPresent ? "present" : "missing"}`);
|
|
@@ -9978,23 +10148,23 @@ function printProjectAuditReport(report) {
|
|
|
9978
10148
|
` Findings: ${report.summary.errorCount} error(s), ${report.summary.warnCount} warn(s), ${report.summary.infoCount} info`
|
|
9979
10149
|
);
|
|
9980
10150
|
console.log("");
|
|
9981
|
-
console.log(`${
|
|
10151
|
+
console.log(`${BOLD10}Findings:${RESET17}`);
|
|
9982
10152
|
printVerificationFindings(report.findings);
|
|
9983
10153
|
}
|
|
9984
10154
|
function printFileCritiqueReport(report) {
|
|
9985
10155
|
console.log(success3(`Critiqued ${report.file}`));
|
|
9986
10156
|
console.log("");
|
|
9987
|
-
console.log(`${
|
|
10157
|
+
console.log(`${BOLD10}Summary:${RESET17}`);
|
|
9988
10158
|
console.log(` Overall score: ${report.overall}/5`);
|
|
9989
10159
|
console.log(` Focus areas: ${report.focusAreas.join(", ")}`);
|
|
9990
10160
|
console.log(` Review pack: ${report.reviewPack ? "present" : "missing"}`);
|
|
9991
10161
|
console.log("");
|
|
9992
|
-
console.log(`${
|
|
10162
|
+
console.log(`${BOLD10}Scores:${RESET17}`);
|
|
9993
10163
|
for (const score of report.scores) {
|
|
9994
10164
|
console.log(` ${cyan3(score.category.padEnd(20))} ${score.score}/5 ${dim3(score.details)}`);
|
|
9995
10165
|
}
|
|
9996
10166
|
console.log("");
|
|
9997
|
-
console.log(`${
|
|
10167
|
+
console.log(`${BOLD10}Findings:${RESET17}`);
|
|
9998
10168
|
printVerificationFindings(report.findings);
|
|
9999
10169
|
}
|
|
10000
10170
|
async function cmdAudit(filePath) {
|
|
@@ -10035,7 +10205,7 @@ async function cmdAudit(filePath) {
|
|
|
10035
10205
|
console.log(dim3("Project audit completed with advisory findings."));
|
|
10036
10206
|
}
|
|
10037
10207
|
} catch (e) {
|
|
10038
|
-
console.log(`${
|
|
10208
|
+
console.log(`${RED13}Error: ${e.message}${RESET17}`);
|
|
10039
10209
|
process.exitCode = 1;
|
|
10040
10210
|
}
|
|
10041
10211
|
}
|
|
@@ -10043,9 +10213,9 @@ async function cmdTheme(args, projectRoot = process.cwd()) {
|
|
|
10043
10213
|
const subcommand = args[0];
|
|
10044
10214
|
if (!subcommand || subcommand === "help") {
|
|
10045
10215
|
console.log(`
|
|
10046
|
-
${
|
|
10216
|
+
${BOLD10}decantr theme${RESET17} \u2014 Manage custom themes
|
|
10047
10217
|
|
|
10048
|
-
${
|
|
10218
|
+
${BOLD10}Commands:${RESET17}
|
|
10049
10219
|
${cyan3("create")} <name> Create a new custom theme
|
|
10050
10220
|
${cyan3("create")} <name> --guided Interactive theme creation
|
|
10051
10221
|
${cyan3("list")} List custom themes
|
|
@@ -10053,7 +10223,7 @@ ${BOLD9}Commands:${RESET16}
|
|
|
10053
10223
|
${cyan3("delete")} <name> Delete a custom theme
|
|
10054
10224
|
${cyan3("import")} <path> Import theme from JSON file
|
|
10055
10225
|
|
|
10056
|
-
${
|
|
10226
|
+
${BOLD10}Examples:${RESET17}
|
|
10057
10227
|
decantr theme create mytheme
|
|
10058
10228
|
decantr theme list
|
|
10059
10229
|
decantr theme validate mytheme
|
|
@@ -10102,21 +10272,21 @@ ${BOLD9}Examples:${RESET16}
|
|
|
10102
10272
|
process.exitCode = 1;
|
|
10103
10273
|
return;
|
|
10104
10274
|
}
|
|
10105
|
-
const themePath =
|
|
10106
|
-
if (!
|
|
10275
|
+
const themePath = join31(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
|
|
10276
|
+
if (!existsSync29(themePath)) {
|
|
10107
10277
|
console.error(error2(`Theme "${name}" not found at ${themePath}`));
|
|
10108
10278
|
process.exitCode = 1;
|
|
10109
10279
|
return;
|
|
10110
10280
|
}
|
|
10111
10281
|
try {
|
|
10112
|
-
const theme = JSON.parse(
|
|
10282
|
+
const theme = JSON.parse(readFileSync22(themePath, "utf-8"));
|
|
10113
10283
|
const result = validateCustomTheme(theme);
|
|
10114
10284
|
if (result.valid) {
|
|
10115
10285
|
console.log(success3(`Custom theme "${name}" is valid`));
|
|
10116
10286
|
} else {
|
|
10117
10287
|
console.error(error2("Validation failed:"));
|
|
10118
10288
|
for (const err of result.errors) {
|
|
10119
|
-
console.error(` ${
|
|
10289
|
+
console.error(` ${RED13}${err}${RESET17}`);
|
|
10120
10290
|
}
|
|
10121
10291
|
process.exitCode = 1;
|
|
10122
10292
|
}
|
|
@@ -10156,7 +10326,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
10156
10326
|
} else {
|
|
10157
10327
|
console.error(error2("Import failed:"));
|
|
10158
10328
|
for (const err of result.errors || []) {
|
|
10159
|
-
console.error(` ${
|
|
10329
|
+
console.error(` ${RED13}${err}${RESET17}`);
|
|
10160
10330
|
}
|
|
10161
10331
|
process.exitCode = 1;
|
|
10162
10332
|
}
|
|
@@ -10241,7 +10411,7 @@ function withProject(command, projectArg) {
|
|
|
10241
10411
|
return projectArg ? `${command} --project ${projectArg}` : command;
|
|
10242
10412
|
}
|
|
10243
10413
|
function displayProjectPath(workspaceInfo, projectPath) {
|
|
10244
|
-
const absolutePath =
|
|
10414
|
+
const absolutePath = join31(workspaceInfo.appRoot, projectPath);
|
|
10245
10415
|
const relativePath = relative6(workspaceInfo.cwd, absolutePath).replace(/\\/g, "/");
|
|
10246
10416
|
if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
|
|
10247
10417
|
return relativePath;
|
|
@@ -10249,7 +10419,7 @@ function displayProjectPath(workspaceInfo, projectPath) {
|
|
|
10249
10419
|
return absolutePath;
|
|
10250
10420
|
}
|
|
10251
10421
|
function projectRelativeGraphPath(projectRoot, filePath) {
|
|
10252
|
-
const relativePath = relative6(projectRoot, isAbsolute3(filePath) ? filePath :
|
|
10422
|
+
const relativePath = relative6(projectRoot, isAbsolute3(filePath) ? filePath : resolve5(filePath));
|
|
10253
10423
|
if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
|
|
10254
10424
|
return relativePath.replace(/\\/g, "/");
|
|
10255
10425
|
}
|
|
@@ -10265,7 +10435,7 @@ function graphSourceNodeIdForTaskFile(projectRoot, snapshot, filePath) {
|
|
|
10265
10435
|
candidates.add(trimmed.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
10266
10436
|
const cwdRelative = projectRelativeGraphPath(projectRoot, trimmed);
|
|
10267
10437
|
if (cwdRelative) candidates.add(cwdRelative);
|
|
10268
|
-
const projectRelative = projectRelativeGraphPath(projectRoot,
|
|
10438
|
+
const projectRelative = projectRelativeGraphPath(projectRoot, join31(projectRoot, trimmed));
|
|
10269
10439
|
if (projectRelative) candidates.add(projectRelative);
|
|
10270
10440
|
for (const candidate of candidates) {
|
|
10271
10441
|
const nodeId = `src:${candidate}`;
|
|
@@ -10319,7 +10489,7 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
|
|
|
10319
10489
|
const noun = commandName === "adopt" ? "Brownfield adoption" : `decantr ${commandName}`;
|
|
10320
10490
|
console.log(error2(`${noun} needs an app path.`));
|
|
10321
10491
|
console.log("");
|
|
10322
|
-
console.log(`${
|
|
10492
|
+
console.log(`${BOLD10}This looks like a monorepo.${RESET17}`);
|
|
10323
10493
|
console.log("Install Decantr at the workspace root, then attach it to one app with --project.");
|
|
10324
10494
|
console.log("");
|
|
10325
10495
|
console.log("App candidates:");
|
|
@@ -10339,11 +10509,11 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
|
|
|
10339
10509
|
function printMonorepoSetupGuidance(workspaceInfo) {
|
|
10340
10510
|
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
10341
10511
|
const attachedProjects = workspaceInfo.appCandidates.filter(
|
|
10342
|
-
(appCandidate) =>
|
|
10512
|
+
(appCandidate) => existsSync29(join31(workspaceInfo.workspaceRoot, appCandidate, "decantr.essence.json"))
|
|
10343
10513
|
);
|
|
10344
10514
|
const firstAttached = attachedProjects[0];
|
|
10345
10515
|
console.log(heading2("Decantr Setup"));
|
|
10346
|
-
console.log(`${
|
|
10516
|
+
console.log(`${BOLD10}This looks like a monorepo.${RESET17}`);
|
|
10347
10517
|
console.log(` Workspace root: ${workspaceInfo.workspaceRoot}`);
|
|
10348
10518
|
console.log("");
|
|
10349
10519
|
if (firstAttached) {
|
|
@@ -10354,7 +10524,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10354
10524
|
console.log(` ${project}`);
|
|
10355
10525
|
}
|
|
10356
10526
|
console.log("");
|
|
10357
|
-
console.log(`${
|
|
10527
|
+
console.log(`${BOLD10}Next:${RESET17}`);
|
|
10358
10528
|
console.log(
|
|
10359
10529
|
` ${cyan3(`decantr doctor --project ${firstAttached}`)} Explain current state and next command`
|
|
10360
10530
|
);
|
|
@@ -10388,7 +10558,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10388
10558
|
console.log(` ${appCandidate}`);
|
|
10389
10559
|
}
|
|
10390
10560
|
console.log("");
|
|
10391
|
-
console.log(`${
|
|
10561
|
+
console.log(`${BOLD10}Start here:${RESET17}`);
|
|
10392
10562
|
console.log(
|
|
10393
10563
|
` ${cyan3("decantr workspace list")} Show attached projects and app candidates`
|
|
10394
10564
|
);
|
|
@@ -10399,7 +10569,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10399
10569
|
` ${cyan3(`decantr codify --from-audit --style-bridge --project ${candidate}`)} Propose project-owned UI law and style bridge`
|
|
10400
10570
|
);
|
|
10401
10571
|
console.log("");
|
|
10402
|
-
console.log(`${
|
|
10572
|
+
console.log(`${BOLD10}Optional visual evidence:${RESET17}`);
|
|
10403
10573
|
console.log(
|
|
10404
10574
|
` ${cyan3(`decantr verify --project ${candidate} --base-url http://localhost:3000 --evidence`)}`
|
|
10405
10575
|
);
|
|
@@ -10407,7 +10577,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10407
10577
|
function resolveWorkflowProject(flags, commandName = "command", options = {}) {
|
|
10408
10578
|
const projectArg = flagString(flags, "project");
|
|
10409
10579
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
10410
|
-
if (projectArg && options.requireExisting !== false && !
|
|
10580
|
+
if (projectArg && options.requireExisting !== false && !existsSync29(workspaceInfo.appRoot)) {
|
|
10411
10581
|
printProjectNotFound(projectArg, commandName);
|
|
10412
10582
|
process.exitCode = 1;
|
|
10413
10583
|
return null;
|
|
@@ -10457,7 +10627,7 @@ function studioCommandForProject(projectArg) {
|
|
|
10457
10627
|
}
|
|
10458
10628
|
function formatWhichCommandFirst(projectArg) {
|
|
10459
10629
|
return [
|
|
10460
|
-
`${
|
|
10630
|
+
`${BOLD10}Which command first?${RESET17}`,
|
|
10461
10631
|
` ${cyan3(withProject("decantr scan", projectArg))} Existing app, read-only preview`,
|
|
10462
10632
|
` ${cyan3(withProject("decantr adopt --yes", projectArg))} Existing app, attach Decantr`,
|
|
10463
10633
|
` ${cyan3("decantr new my-app --blueprint=<slug>")} New runnable app`,
|
|
@@ -10467,19 +10637,19 @@ function formatWhichCommandFirst(projectArg) {
|
|
|
10467
10637
|
function scanSeverityColor(finding) {
|
|
10468
10638
|
if (finding.severity === "success") return success3("ok");
|
|
10469
10639
|
if (finding.severity === "error") return error2("error");
|
|
10470
|
-
if (finding.severity === "warn") return `${
|
|
10640
|
+
if (finding.severity === "warn") return `${YELLOW13}warn${RESET17}`;
|
|
10471
10641
|
return cyan3("info");
|
|
10472
10642
|
}
|
|
10473
10643
|
function formatScanApplicability(status) {
|
|
10474
10644
|
if (status === "strong_fit") return success3("strong fit");
|
|
10475
|
-
if (status === "partial_fit") return `${
|
|
10645
|
+
if (status === "partial_fit") return `${YELLOW13}partial fit${RESET17}`;
|
|
10476
10646
|
if (status === "not_applicable") return dim3("not applicable");
|
|
10477
10647
|
return dim3("unknown");
|
|
10478
10648
|
}
|
|
10479
10649
|
function formatScanGraphPreviewStatus(status) {
|
|
10480
10650
|
if (status === "current") return success3("current");
|
|
10481
|
-
if (status === "stale") return `${
|
|
10482
|
-
if (status === "needs_migration") return `${
|
|
10651
|
+
if (status === "stale") return `${YELLOW13}stale or missing${RESET17}`;
|
|
10652
|
+
if (status === "needs_migration") return `${YELLOW13}needs migration${RESET17}`;
|
|
10483
10653
|
if (status === "not_attached") return dim3("not attached");
|
|
10484
10654
|
return dim3("unavailable");
|
|
10485
10655
|
}
|
|
@@ -10561,7 +10731,7 @@ function buildScanGraphPreview(workspaceInfo, projectArg) {
|
|
|
10561
10731
|
}
|
|
10562
10732
|
function printScanGraphPreview(preview) {
|
|
10563
10733
|
if (!preview) return;
|
|
10564
|
-
console.log(`${
|
|
10734
|
+
console.log(`${BOLD10}Typed Contract Graph${RESET17}`);
|
|
10565
10735
|
console.log(` Status: ${formatScanGraphPreviewStatus(preview.status)}`);
|
|
10566
10736
|
console.log(` Read-only: ${preview.readOnly ? "yes" : "no"}`);
|
|
10567
10737
|
if (preview.snapshot && preview.capsule) {
|
|
@@ -10603,7 +10773,7 @@ function printScanReport(report, projectArg) {
|
|
|
10603
10773
|
console.log(heading2("Decantr Scan"));
|
|
10604
10774
|
console.log(dim3("Read-only Brownfield reconnaissance. No files were written."));
|
|
10605
10775
|
console.log("");
|
|
10606
|
-
console.log(`${
|
|
10776
|
+
console.log(`${BOLD10}Verdict${RESET17}`);
|
|
10607
10777
|
console.log(
|
|
10608
10778
|
` ${formatScanApplicability(report.applicability.status)} ${report.applicability.label}`
|
|
10609
10779
|
);
|
|
@@ -10614,7 +10784,7 @@ function printScanReport(report, projectArg) {
|
|
|
10614
10784
|
console.log(` ${dim3("-")} ${reason}`);
|
|
10615
10785
|
}
|
|
10616
10786
|
console.log("");
|
|
10617
|
-
console.log(`${
|
|
10787
|
+
console.log(`${BOLD10}Project${RESET17}`);
|
|
10618
10788
|
console.log(
|
|
10619
10789
|
` Framework: ${cyan3(report.project.framework)}${report.project.frameworkVersion ? ` ${report.project.frameworkVersion}` : ""}`
|
|
10620
10790
|
);
|
|
@@ -10624,7 +10794,7 @@ function printScanReport(report, projectArg) {
|
|
|
10624
10794
|
console.log(` Decantr: ${report.project.hasDecantr ? "present" : "not attached"}`);
|
|
10625
10795
|
console.log("");
|
|
10626
10796
|
printScanGraphPreview(report.graphPreview);
|
|
10627
|
-
console.log(`${
|
|
10797
|
+
console.log(`${BOLD10}Routes And Styling${RESET17}`);
|
|
10628
10798
|
console.log(` Routes: ${report.routes.count} (${report.routes.strategy})`);
|
|
10629
10799
|
for (const route of report.routes.items.slice(0, 8)) {
|
|
10630
10800
|
console.log(` ${cyan3(route.path.padEnd(18))} ${dim3(route.file)}`);
|
|
@@ -10640,7 +10810,7 @@ function printScanReport(report, projectArg) {
|
|
|
10640
10810
|
console.log(` Dark mode: ${report.styling.darkMode ? "yes" : "no"}`);
|
|
10641
10811
|
console.log("");
|
|
10642
10812
|
if (report.staticHosting.githubPagesLikely || report.pagesProbe) {
|
|
10643
|
-
console.log(`${
|
|
10813
|
+
console.log(`${BOLD10}Published Surface${RESET17}`);
|
|
10644
10814
|
console.log(
|
|
10645
10815
|
` GitHub Pages: ${report.staticHosting.githubPagesLikely ? "likely" : "not detected"}`
|
|
10646
10816
|
);
|
|
@@ -10649,7 +10819,7 @@ function printScanReport(report, projectArg) {
|
|
|
10649
10819
|
}
|
|
10650
10820
|
if (report.pagesProbe?.checked) {
|
|
10651
10821
|
console.log(
|
|
10652
|
-
` HTTP probe: ${report.pagesProbe.reachable ? success3("reachable") : `${
|
|
10822
|
+
` HTTP probe: ${report.pagesProbe.reachable ? success3("reachable") : `${YELLOW13}unreachable${RESET17}`} ${report.pagesProbe.status ?? ""}`
|
|
10653
10823
|
);
|
|
10654
10824
|
if (report.pagesProbe.title) console.log(` Title: ${report.pagesProbe.title}`);
|
|
10655
10825
|
}
|
|
@@ -10658,14 +10828,14 @@ function printScanReport(report, projectArg) {
|
|
|
10658
10828
|
}
|
|
10659
10829
|
console.log("");
|
|
10660
10830
|
}
|
|
10661
|
-
console.log(`${
|
|
10831
|
+
console.log(`${BOLD10}Findings${RESET17}`);
|
|
10662
10832
|
for (const finding of report.findings.slice(0, 8)) {
|
|
10663
10833
|
console.log(` [${scanSeverityColor(finding)}] ${finding.title}`);
|
|
10664
10834
|
console.log(` ${finding.message}`);
|
|
10665
10835
|
if (finding.recommendation) console.log(` ${dim3(finding.recommendation)}`);
|
|
10666
10836
|
}
|
|
10667
10837
|
console.log("");
|
|
10668
|
-
console.log(`${
|
|
10838
|
+
console.log(`${BOLD10}Next Commands${RESET17}`);
|
|
10669
10839
|
for (const command of report.recommendedCommands) {
|
|
10670
10840
|
console.log(` ${cyan3(command)}`);
|
|
10671
10841
|
}
|
|
@@ -10724,11 +10894,11 @@ async function cmdSetupWorkflow(args) {
|
|
|
10724
10894
|
console.log(` Detected: ${formatDetection(detected)}`);
|
|
10725
10895
|
console.log("");
|
|
10726
10896
|
if (detected.existingEssence) {
|
|
10727
|
-
const hasLocalPatterns =
|
|
10728
|
-
const hasLocalRules =
|
|
10729
|
-
const hasStyleBridge =
|
|
10897
|
+
const hasLocalPatterns = existsSync29(localPatternsPath(workspaceInfo.appRoot));
|
|
10898
|
+
const hasLocalRules = existsSync29(localRulesPath(workspaceInfo.appRoot));
|
|
10899
|
+
const hasStyleBridge = existsSync29(styleBridgePath(workspaceInfo.appRoot));
|
|
10730
10900
|
const verifyCommand = hasLocalPatterns || hasLocalRules ? "decantr verify --brownfield --local-patterns" : "decantr verify --brownfield";
|
|
10731
|
-
console.log(`${
|
|
10901
|
+
console.log(`${BOLD10}Recommended path:${RESET17} maintain an attached Decantr project`);
|
|
10732
10902
|
console.log(
|
|
10733
10903
|
` ${cyan3(withProject("decantr doctor", projectArg))} Explain current state and next command`
|
|
10734
10904
|
);
|
|
@@ -10750,7 +10920,7 @@ async function cmdSetupWorkflow(args) {
|
|
|
10750
10920
|
return;
|
|
10751
10921
|
}
|
|
10752
10922
|
if (hasFootprint) {
|
|
10753
|
-
console.log(`${
|
|
10923
|
+
console.log(`${BOLD10}Recommended path:${RESET17} brownfield adoption`);
|
|
10754
10924
|
console.log(
|
|
10755
10925
|
` ${cyan3(withProject("decantr adopt --yes", projectArg))} Analyze, attach, and verify`
|
|
10756
10926
|
);
|
|
@@ -10758,13 +10928,13 @@ async function cmdSetupWorkflow(args) {
|
|
|
10758
10928
|
` ${cyan3(withProject("decantr codify --from-audit --style-bridge", projectArg))} Propose local UI law and style bridge`
|
|
10759
10929
|
);
|
|
10760
10930
|
console.log("");
|
|
10761
|
-
console.log(`${
|
|
10931
|
+
console.log(`${BOLD10}Optional visual evidence after the app is running:${RESET17}`);
|
|
10762
10932
|
console.log(
|
|
10763
10933
|
` ${cyan3(withProject("decantr verify --base-url http://localhost:3000 --evidence", projectArg))}`
|
|
10764
10934
|
);
|
|
10765
10935
|
return;
|
|
10766
10936
|
}
|
|
10767
|
-
console.log(`${
|
|
10937
|
+
console.log(`${BOLD10}Recommended path:${RESET17} greenfield start`);
|
|
10768
10938
|
console.log(` ${cyan3("decantr new my-app --blueprint=<slug>")}`);
|
|
10769
10939
|
console.log(` ${cyan3("decantr init --workflow=greenfield --adoption=contract-only")}`);
|
|
10770
10940
|
}
|
|
@@ -10814,7 +10984,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10814
10984
|
const hydratePacks = flagBoolean(flags, "packs", true) && !flagBoolean(flags, "skip-packs") && !flagBoolean(flags, "offline") && process.env.DECANTR_OFFLINE !== "true";
|
|
10815
10985
|
const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
|
|
10816
10986
|
const assistantBridge = flagString(flags, "assistant-bridge");
|
|
10817
|
-
const hasEssence =
|
|
10987
|
+
const hasEssence = existsSync29(join31(projectRoot, "decantr.essence.json"));
|
|
10818
10988
|
const proposalFlag = flagBoolean(flags, "replace-essence") ? "--replace-essence" : flagBoolean(flags, "merge-proposal") || hasEssence ? "--merge-proposal" : "--accept-proposal";
|
|
10819
10989
|
const steps = [
|
|
10820
10990
|
"analyze current app and write .decantr/brownfield intelligence",
|
|
@@ -10863,7 +11033,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10863
11033
|
if (hydratePacks) {
|
|
10864
11034
|
try {
|
|
10865
11035
|
const { bundle, contextDir } = await compileHostedExecutionPackBundle(
|
|
10866
|
-
|
|
11036
|
+
join31(projectRoot, "decantr.essence.json")
|
|
10867
11037
|
);
|
|
10868
11038
|
const written = writeHostedExecutionPackContextArtifacts(
|
|
10869
11039
|
contextDir,
|
|
@@ -10875,7 +11045,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10875
11045
|
)
|
|
10876
11046
|
);
|
|
10877
11047
|
} catch (e) {
|
|
10878
|
-
console.log(`${
|
|
11048
|
+
console.log(`${YELLOW13}Pack hydration skipped:${RESET17} ${e.message}`);
|
|
10879
11049
|
console.log(
|
|
10880
11050
|
dim3(
|
|
10881
11051
|
`Run ${compilePacksCommandForProject(projectArg)} after adoption if you want hosted page/review packs.`
|
|
@@ -10888,7 +11058,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10888
11058
|
await cmdGraph(projectRoot, { displayRoot: process.cwd() });
|
|
10889
11059
|
if (process.exitCode && process.exitCode !== 0) return;
|
|
10890
11060
|
if (runVerify) {
|
|
10891
|
-
const { cmdHealth } = await import("./health-
|
|
11061
|
+
const { cmdHealth } = await import("./health-5S2L44SX.js");
|
|
10892
11062
|
await cmdHealth(projectRoot, {
|
|
10893
11063
|
browser: runBrowser,
|
|
10894
11064
|
browserBaseUrl: baseUrl,
|
|
@@ -10904,7 +11074,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
10904
11074
|
await cmdCi(ciArgs, process.cwd());
|
|
10905
11075
|
}
|
|
10906
11076
|
console.log("");
|
|
10907
|
-
console.log(`${
|
|
11077
|
+
console.log(`${BOLD10}Brownfield operating loop:${RESET17}`);
|
|
10908
11078
|
console.log(
|
|
10909
11079
|
` ${cyan3(withProject("decantr codify --from-audit --style-bridge", projectArg))} Propose project-owned UI law and style bridge`
|
|
10910
11080
|
);
|
|
@@ -10962,7 +11132,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10962
11132
|
return;
|
|
10963
11133
|
}
|
|
10964
11134
|
if (workspaceMode) {
|
|
10965
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
11135
|
+
const { cmdWorkspace } = await import("./workspace-UIKTIWUN.js");
|
|
10966
11136
|
await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
|
|
10967
11137
|
return;
|
|
10968
11138
|
}
|
|
@@ -10995,7 +11165,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
10995
11165
|
}
|
|
10996
11166
|
let guardExitCode;
|
|
10997
11167
|
if (brownfield) {
|
|
10998
|
-
const { cmdHeal, collectCheckIssues } = await import("./heal-
|
|
11168
|
+
const { cmdHeal, collectCheckIssues } = await import("./heal-YXWB6LTI.js");
|
|
10999
11169
|
if (quietOutput) {
|
|
11000
11170
|
const result = collectCheckIssues(workspaceInfo.appRoot, { brownfield: true });
|
|
11001
11171
|
guardExitCode = result.issues.some((issue) => issue.type === "error") ? 1 : void 0;
|
|
@@ -11005,7 +11175,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11005
11175
|
process.exitCode = void 0;
|
|
11006
11176
|
}
|
|
11007
11177
|
}
|
|
11008
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
11178
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-5S2L44SX.js");
|
|
11009
11179
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
|
|
11010
11180
|
if (localPatterns) {
|
|
11011
11181
|
const validation = validateLocalLaw(workspaceInfo.appRoot);
|
|
@@ -11013,7 +11183,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11013
11183
|
if (!quietOutput) {
|
|
11014
11184
|
console.log("");
|
|
11015
11185
|
console.log(
|
|
11016
|
-
`${
|
|
11186
|
+
`${YELLOW13}Local pattern pack missing.${RESET17} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))}, review the proposal, then run ${cyan3(withProject("decantr codify --accept", projectArg))}.`
|
|
11017
11187
|
);
|
|
11018
11188
|
}
|
|
11019
11189
|
process.exitCode = process.exitCode || 1;
|
|
@@ -11024,23 +11194,23 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11024
11194
|
const blockingWarnings = failOn === "warn" ? validation.warnings : [];
|
|
11025
11195
|
if (!quietOutput) {
|
|
11026
11196
|
console.log("");
|
|
11027
|
-
console.log(`${
|
|
11197
|
+
console.log(`${GREEN17}Local pattern pack found:${RESET17} ${validation.patternsPath}`);
|
|
11028
11198
|
if (validation.ruleManifestPresent) {
|
|
11029
|
-
console.log(`${
|
|
11199
|
+
console.log(`${GREEN17}Local rule manifest found:${RESET17} ${validation.rulesPath}`);
|
|
11030
11200
|
console.log(
|
|
11031
|
-
`${
|
|
11201
|
+
`${DIM17}Enforcement: accepted .decantr/rules.json is the Decantr-scanned layer; --fail-on controls whether findings block.${RESET17}`
|
|
11032
11202
|
);
|
|
11033
11203
|
} else {
|
|
11034
11204
|
console.log(
|
|
11035
|
-
`${
|
|
11205
|
+
`${YELLOW13}Local rule manifest missing.${RESET17} Run ${cyan3("decantr codify --from-audit")} to propose .decantr/rules.json.`
|
|
11036
11206
|
);
|
|
11037
11207
|
}
|
|
11038
11208
|
for (const warning of validation.warnings.slice(0, 8)) {
|
|
11039
|
-
console.log(`${
|
|
11209
|
+
console.log(`${YELLOW13}warn${RESET17} ${warning}`);
|
|
11040
11210
|
}
|
|
11041
11211
|
if (validation.findings.length > 0) {
|
|
11042
11212
|
console.log("");
|
|
11043
|
-
console.log(`${
|
|
11213
|
+
console.log(`${BOLD10}Local law findings:${RESET17}`);
|
|
11044
11214
|
for (const finding of validation.findings.slice(0, 20)) {
|
|
11045
11215
|
console.log(
|
|
11046
11216
|
` ${finding.severity.toUpperCase()} ${finding.ruleId} ${finding.file}:${finding.line}:${finding.column} ${finding.message}`
|
|
@@ -11050,7 +11220,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11050
11220
|
console.log(dim3(` ...${validation.findings.length - 20} more finding(s)`));
|
|
11051
11221
|
}
|
|
11052
11222
|
} else if (validation.ruleManifestPresent) {
|
|
11053
|
-
console.log(`${
|
|
11223
|
+
console.log(`${GREEN17}Local rule checks passed.${RESET17}`);
|
|
11054
11224
|
}
|
|
11055
11225
|
}
|
|
11056
11226
|
if (blockingFindings.length > 0 || blockingWarnings.length > 0) {
|
|
@@ -11061,12 +11231,12 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11061
11231
|
const styleBridge = createStyleBridgeTaskSummary(workspaceInfo.appRoot);
|
|
11062
11232
|
if (!quietOutput && styleBridge.path) {
|
|
11063
11233
|
console.log("");
|
|
11064
|
-
console.log(`${
|
|
11234
|
+
console.log(`${GREEN17}Style bridge found:${RESET17} ${styleBridge.path}`);
|
|
11065
11235
|
console.log(
|
|
11066
|
-
`${
|
|
11236
|
+
`${DIM17}${styleBridge.mappingCount} mapping(s), ${styleBridge.stylingApproach ?? "unknown"} styling${styleBridge.themeModes.length > 0 ? `, themes: ${styleBridge.themeModes.join(", ")}` : ""}${RESET17}`
|
|
11067
11237
|
);
|
|
11068
11238
|
console.log(
|
|
11069
|
-
`${
|
|
11239
|
+
`${DIM17}Enforcement: advisory style-intent mapping; pair with accepted local rules, lint, tests, or visual regression when it should block.${RESET17}`
|
|
11070
11240
|
);
|
|
11071
11241
|
}
|
|
11072
11242
|
if (guardExitCode && guardExitCode !== 0 && (!process.exitCode || process.exitCode === 0)) {
|
|
@@ -11074,9 +11244,9 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11074
11244
|
}
|
|
11075
11245
|
}
|
|
11076
11246
|
function readJsonIfPresent(path) {
|
|
11077
|
-
if (!
|
|
11247
|
+
if (!existsSync29(path)) return null;
|
|
11078
11248
|
try {
|
|
11079
|
-
return JSON.parse(
|
|
11249
|
+
return JSON.parse(readFileSync22(path, "utf-8"));
|
|
11080
11250
|
} catch {
|
|
11081
11251
|
return null;
|
|
11082
11252
|
}
|
|
@@ -11228,7 +11398,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11228
11398
|
}
|
|
11229
11399
|
const route = routeInput.startsWith("/") ? routeInput : `/${routeInput}`;
|
|
11230
11400
|
const taskSummary = positional.slice(1).join(" ").trim();
|
|
11231
|
-
const essencePath =
|
|
11401
|
+
const essencePath = join31(workspaceInfo.appRoot, "decantr.essence.json");
|
|
11232
11402
|
const essence = readJsonIfPresent(essencePath);
|
|
11233
11403
|
if (!essence) {
|
|
11234
11404
|
console.error(
|
|
@@ -11252,19 +11422,19 @@ async function cmdTaskWorkflow(args) {
|
|
|
11252
11422
|
}
|
|
11253
11423
|
const section = essence.blueprint.sections.find((entry) => entry.id === target.section);
|
|
11254
11424
|
const page = section?.pages.find((entry) => entry.id === target.page);
|
|
11255
|
-
const contextDir =
|
|
11256
|
-
const manifest = readJsonIfPresent(
|
|
11257
|
-
const projectJson = readJsonIfPresent(
|
|
11425
|
+
const contextDir = join31(workspaceInfo.appRoot, ".decantr", "context");
|
|
11426
|
+
const manifest = readJsonIfPresent(join31(contextDir, "pack-manifest.json"));
|
|
11427
|
+
const projectJson = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "project.json"));
|
|
11258
11428
|
const pagePack = manifest?.pages?.find((entry) => entry.id === target.page);
|
|
11259
11429
|
const sectionPack = manifest?.sections?.find((entry) => entry.id === target.section);
|
|
11260
|
-
const visualManifest = readJsonIfPresent(
|
|
11430
|
+
const visualManifest = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
|
|
11261
11431
|
const screenshot = visualManifest?.routes?.find((entry) => entry.route === route)?.screenshot;
|
|
11262
11432
|
const localPatternPackPath = localPatternsPath(workspaceInfo.appRoot);
|
|
11263
11433
|
const localRuleManifestPath = localRulesPath(workspaceInfo.appRoot);
|
|
11264
11434
|
const acceptedStyleBridgePath = styleBridgePath(workspaceInfo.appRoot);
|
|
11265
|
-
const graphDir =
|
|
11266
|
-
const contractCapsulePath =
|
|
11267
|
-
const graphSnapshotPath =
|
|
11435
|
+
const graphDir = join31(workspaceInfo.appRoot, ".decantr", "graph");
|
|
11436
|
+
const contractCapsulePath = join31(graphDir, "contract-capsule.json");
|
|
11437
|
+
const graphSnapshotPath = join31(graphDir, "graph.snapshot.json");
|
|
11268
11438
|
const contractCapsule = readJsonIfPresent(contractCapsulePath);
|
|
11269
11439
|
const graphSnapshot = readJsonIfPresent(graphSnapshotPath);
|
|
11270
11440
|
const routeGraphContext = buildGraphRouteContext(graphSnapshot, route, { task: taskSummary });
|
|
@@ -11307,12 +11477,96 @@ async function cmdTaskWorkflow(args) {
|
|
|
11307
11477
|
projectRoot: workspaceInfo.appRoot,
|
|
11308
11478
|
workflowMode: projectJson?.initialized?.workflowMode ?? null,
|
|
11309
11479
|
adoptionMode: projectJson?.initialized?.adoptionMode ?? null,
|
|
11310
|
-
hasLocalPatterns:
|
|
11311
|
-
hasLocalRules:
|
|
11480
|
+
hasLocalPatterns: existsSync29(localPatternPackPath),
|
|
11481
|
+
hasLocalRules: existsSync29(localRuleManifestPath),
|
|
11312
11482
|
hasPackManifest: Boolean(manifest),
|
|
11313
11483
|
taskSummary,
|
|
11314
|
-
hasStyleBridge:
|
|
11484
|
+
hasStyleBridge: existsSync29(acceptedStyleBridgePath)
|
|
11315
11485
|
});
|
|
11486
|
+
const readTargets = [
|
|
11487
|
+
pagePack ? displayProjectPath(workspaceInfo, join31(".decantr/context", pagePack.markdown)) : null,
|
|
11488
|
+
sectionPack ? displayProjectPath(workspaceInfo, join31(".decantr/context", sectionPack.markdown)) : null,
|
|
11489
|
+
manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join31(".decantr/context", manifest.scaffold.markdown)) : null,
|
|
11490
|
+
displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
|
|
11491
|
+
displayProjectPath(workspaceInfo, "DECANTR.md"),
|
|
11492
|
+
existsSync29(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
|
|
11493
|
+
existsSync29(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null,
|
|
11494
|
+
existsSync29(acceptedStyleBridgePath) ? displayProjectPath(workspaceInfo, ".decantr/style-bridge.json") : null,
|
|
11495
|
+
contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json") : null,
|
|
11496
|
+
routeGraphContext && !contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json") : null
|
|
11497
|
+
].filter((value) => Boolean(value));
|
|
11498
|
+
const taskLoopState = readTargets.length === 0 ? "blocked_missing_context" : !routeGraphContext ? "blocked_missing_graph" : "ready_to_edit";
|
|
11499
|
+
const taskLoop = {
|
|
11500
|
+
$schema: LOOP_READINESS_V2_SCHEMA_URL,
|
|
11501
|
+
schemaVersion: 2,
|
|
11502
|
+
state: taskLoopState,
|
|
11503
|
+
status: taskLoopState === "ready_to_edit" ? "healthy" : "blocked",
|
|
11504
|
+
verdict: taskLoopState === "ready_to_edit" ? "Task context is ready for an agent edit." : "Task context is missing required context or graph evidence.",
|
|
11505
|
+
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).`,
|
|
11506
|
+
authority: {
|
|
11507
|
+
activeLane: projectJson?.initialized?.workflowMode === "brownfield-attach" ? "production-source" : "essence-contract",
|
|
11508
|
+
summary: `${authority.lane}: ${authority.sourceAuthority}`,
|
|
11509
|
+
stopRule: "If runtime source and Decantr context disagree, stop and report drift instead of guessing."
|
|
11510
|
+
},
|
|
11511
|
+
evidenceTier: {
|
|
11512
|
+
schemaVersion: 2,
|
|
11513
|
+
stage: routeGraphContext ? "graph" : "static",
|
|
11514
|
+
status: taskLoopState === "ready_to_edit" ? "healthy" : "incomplete",
|
|
11515
|
+
capabilities: routeGraphContext ? ["static-audit", "project-health", "typed-graph"] : ["static-audit", "project-health"],
|
|
11516
|
+
coverage: {
|
|
11517
|
+
declaredRoutes: 1,
|
|
11518
|
+
runtimeRoutesChecked: 0,
|
|
11519
|
+
findingsAnchored: routeGraphContext?.summary.openFindings ?? 0,
|
|
11520
|
+
findingsWithRepairPlan: 0,
|
|
11521
|
+
runtimeProbeCount: 0,
|
|
11522
|
+
visualArtifactCount: screenshot ? 1 : 0
|
|
11523
|
+
},
|
|
11524
|
+
confidence: {
|
|
11525
|
+
level: routeGraphContext ? "moderate" : "low",
|
|
11526
|
+
score: routeGraphContext ? 0.64 : 0.32,
|
|
11527
|
+
reasons: [
|
|
11528
|
+
routeGraphContext ? "route graph context is present" : "route graph context is missing",
|
|
11529
|
+
screenshot ? "visual evidence reference is available" : "no visual evidence reference was found"
|
|
11530
|
+
]
|
|
11531
|
+
}
|
|
11532
|
+
},
|
|
11533
|
+
blockingReasons: taskLoopState === "ready_to_edit" ? [] : [
|
|
11534
|
+
taskLoopState === "blocked_missing_graph" ? "Route graph context is missing or stale." : "Route context read targets are missing."
|
|
11535
|
+
],
|
|
11536
|
+
nextActions: taskLoopState === "ready_to_edit" ? ["Edit only after reading the listed context, then run the verify command."] : [
|
|
11537
|
+
taskLoopState === "blocked_missing_graph" ? "Run `decantr graph`, then rerun `decantr task`." : "Run `decantr refresh`, then rerun `decantr task`."
|
|
11538
|
+
],
|
|
11539
|
+
maker: {
|
|
11540
|
+
title: "Maker instructions",
|
|
11541
|
+
instructions: [
|
|
11542
|
+
"Read the listed route, section, scaffold, DECANTR, local-law, and graph targets before editing.",
|
|
11543
|
+
"Preserve the active authority lane and existing production behavior outside this task.",
|
|
11544
|
+
"Stop and report drift if source, graph, and contract context disagree."
|
|
11545
|
+
]
|
|
11546
|
+
},
|
|
11547
|
+
checker: {
|
|
11548
|
+
title: "Checker instructions",
|
|
11549
|
+
instructions: [
|
|
11550
|
+
"Rerun the verify command after edits.",
|
|
11551
|
+
"Use changed-file graph impact and route findings to decide whether more routes need review.",
|
|
11552
|
+
"Do not treat advisory critique as blocking without T1/T2 evidence."
|
|
11553
|
+
]
|
|
11554
|
+
},
|
|
11555
|
+
readTargets,
|
|
11556
|
+
graphImpact: {
|
|
11557
|
+
status: routeGraphContext ? "ready" : graphSnapshot ? "stale" : "missing",
|
|
11558
|
+
snapshotId: routeGraphContext?.snapshotId ?? graphSnapshot?.id ?? null,
|
|
11559
|
+
sourceHash: routeGraphContext?.sourceHash ?? graphSnapshot?.source_hash ?? null,
|
|
11560
|
+
sourceArtifactCount: routeGraphContext?.summary.sourceArtifacts ?? 0,
|
|
11561
|
+
staleArtifacts: []
|
|
11562
|
+
},
|
|
11563
|
+
stopConditions: [
|
|
11564
|
+
"Runtime source and Decantr context disagree.",
|
|
11565
|
+
"The route graph cannot resolve a source file affected by the edit.",
|
|
11566
|
+
"A fix requires contract/source/local-law mutation outside the explicit workflow."
|
|
11567
|
+
],
|
|
11568
|
+
verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
|
|
11569
|
+
};
|
|
11316
11570
|
const context = {
|
|
11317
11571
|
route,
|
|
11318
11572
|
task: taskSummary || null,
|
|
@@ -11320,18 +11574,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11320
11574
|
page: target.page,
|
|
11321
11575
|
shell: page?.shell ?? section?.shell ?? null,
|
|
11322
11576
|
patterns: routePatterns,
|
|
11323
|
-
read:
|
|
11324
|
-
pagePack ? displayProjectPath(workspaceInfo, join30(".decantr/context", pagePack.markdown)) : null,
|
|
11325
|
-
sectionPack ? displayProjectPath(workspaceInfo, join30(".decantr/context", sectionPack.markdown)) : null,
|
|
11326
|
-
manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join30(".decantr/context", manifest.scaffold.markdown)) : null,
|
|
11327
|
-
displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
|
|
11328
|
-
displayProjectPath(workspaceInfo, "DECANTR.md"),
|
|
11329
|
-
existsSync28(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
|
|
11330
|
-
existsSync28(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null,
|
|
11331
|
-
existsSync28(acceptedStyleBridgePath) ? displayProjectPath(workspaceInfo, ".decantr/style-bridge.json") : null,
|
|
11332
|
-
contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json") : null,
|
|
11333
|
-
routeGraphContext && !contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json") : null
|
|
11334
|
-
].filter(Boolean),
|
|
11577
|
+
read: readTargets,
|
|
11335
11578
|
graph: contractCapsule || graphSnapshot ? {
|
|
11336
11579
|
capsule: contractCapsule ? {
|
|
11337
11580
|
path: displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json"),
|
|
@@ -11374,6 +11617,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11374
11617
|
styleBridge: displayedStyleBridge,
|
|
11375
11618
|
changedFiles: currentChangedFiles,
|
|
11376
11619
|
changedRoutes,
|
|
11620
|
+
loop: taskLoop,
|
|
11377
11621
|
verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
|
|
11378
11622
|
};
|
|
11379
11623
|
if (flagBoolean(flags, "json")) {
|
|
@@ -11387,18 +11631,18 @@ async function cmdTaskWorkflow(args) {
|
|
|
11387
11631
|
if (context.patterns.length > 0) console.log(` Patterns: ${context.patterns.join(", ")}`);
|
|
11388
11632
|
if (taskSummary) console.log(` Task: ${taskSummary}`);
|
|
11389
11633
|
console.log("");
|
|
11390
|
-
console.log(`${
|
|
11634
|
+
console.log(`${BOLD10}Read before editing:${RESET17}`);
|
|
11391
11635
|
for (const path of context.read) {
|
|
11392
11636
|
console.log(` ${cyan3(path)}`);
|
|
11393
11637
|
}
|
|
11394
11638
|
if (context.screenshot) {
|
|
11395
11639
|
console.log("");
|
|
11396
|
-
console.log(`${
|
|
11640
|
+
console.log(`${BOLD10}Visual evidence:${RESET17}`);
|
|
11397
11641
|
console.log(` ${cyan3(context.screenshot)}`);
|
|
11398
11642
|
}
|
|
11399
11643
|
if (context.graph?.capsule || context.graph?.snapshot) {
|
|
11400
11644
|
console.log("");
|
|
11401
|
-
console.log(`${
|
|
11645
|
+
console.log(`${BOLD10}Typed contract graph:${RESET17}`);
|
|
11402
11646
|
if (context.graph.capsule) {
|
|
11403
11647
|
console.log(` Capsule: ${cyan3(context.graph.capsule.path)}`);
|
|
11404
11648
|
if (context.graph.capsule.cacheKey) {
|
|
@@ -11446,18 +11690,18 @@ async function cmdTaskWorkflow(args) {
|
|
|
11446
11690
|
}
|
|
11447
11691
|
}
|
|
11448
11692
|
console.log("");
|
|
11449
|
-
console.log(`${
|
|
11693
|
+
console.log(`${BOLD10}Authority for this task:${RESET17}`);
|
|
11450
11694
|
console.log(` Lane: ${context.authority.lane}`);
|
|
11451
11695
|
console.log(` Source: ${context.authority.sourceAuthority}`);
|
|
11452
11696
|
console.log(` Style: ${context.authority.styleAuthority}`);
|
|
11453
11697
|
console.log(` Active: ${context.authority.activeAuthorities.join(", ")}`);
|
|
11454
11698
|
console.log(` Runtime: ${context.authority.runtimeBoundary}`);
|
|
11455
11699
|
for (const warning of context.authority.warnings) {
|
|
11456
|
-
console.log(` ${
|
|
11700
|
+
console.log(` ${YELLOW13}Boundary:${RESET17} ${warning}`);
|
|
11457
11701
|
}
|
|
11458
11702
|
if (context.localLaw.patternCount > 0 || context.localLaw.ruleCount > 0) {
|
|
11459
11703
|
console.log("");
|
|
11460
|
-
console.log(`${
|
|
11704
|
+
console.log(`${BOLD10}Project-owned local law:${RESET17}`);
|
|
11461
11705
|
if (context.localLaw.patternsPath) {
|
|
11462
11706
|
console.log(
|
|
11463
11707
|
` Patterns: ${cyan3(context.localLaw.patternsPath)} (${context.localLaw.patternCount})`
|
|
@@ -11479,7 +11723,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11479
11723
|
}
|
|
11480
11724
|
if (context.localLaw.behaviorObligations.length > 0) {
|
|
11481
11725
|
console.log("");
|
|
11482
|
-
console.log(`${
|
|
11726
|
+
console.log(`${BOLD10}Behavior obligations:${RESET17}`);
|
|
11483
11727
|
for (const behavior of context.localLaw.behaviorObligations.slice(0, 3)) {
|
|
11484
11728
|
const obligations = behavior.obligations.slice(0, 3).map((obligation) => obligation.label).join("; ");
|
|
11485
11729
|
const reasons = behavior.relevance.reasons.slice(0, 3).join(", ");
|
|
@@ -11496,14 +11740,14 @@ async function cmdTaskWorkflow(args) {
|
|
|
11496
11740
|
}
|
|
11497
11741
|
} else {
|
|
11498
11742
|
console.log("");
|
|
11499
|
-
console.log(`${
|
|
11743
|
+
console.log(`${BOLD10}Project-owned local law:${RESET17}`);
|
|
11500
11744
|
console.log(
|
|
11501
|
-
` ${
|
|
11745
|
+
` ${YELLOW13}Not codified yet.${RESET17} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
|
|
11502
11746
|
);
|
|
11503
11747
|
}
|
|
11504
11748
|
if (context.styleBridge.path) {
|
|
11505
11749
|
console.log("");
|
|
11506
|
-
console.log(`${
|
|
11750
|
+
console.log(`${BOLD10}Project-owned style bridge:${RESET17}`);
|
|
11507
11751
|
console.log(
|
|
11508
11752
|
` Bridge: ${cyan3(context.styleBridge.path)} (${context.styleBridge.mappingCount} mappings, ${context.styleBridge.stylingApproach ?? "unknown"} styling)`
|
|
11509
11753
|
);
|
|
@@ -11520,7 +11764,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11520
11764
|
}
|
|
11521
11765
|
if (context.changedFiles.length > 0) {
|
|
11522
11766
|
console.log("");
|
|
11523
|
-
console.log(`${
|
|
11767
|
+
console.log(`${BOLD10}Changed-file context:${RESET17}`);
|
|
11524
11768
|
for (const file of context.changedFiles.slice(0, 8)) {
|
|
11525
11769
|
console.log(` ${file}`);
|
|
11526
11770
|
}
|
|
@@ -11532,7 +11776,14 @@ async function cmdTaskWorkflow(args) {
|
|
|
11532
11776
|
}
|
|
11533
11777
|
}
|
|
11534
11778
|
console.log("");
|
|
11535
|
-
console.log(`${
|
|
11779
|
+
console.log(`${BOLD10}Control loop:${RESET17}`);
|
|
11780
|
+
console.log(
|
|
11781
|
+
` State: ${context.loop.state} | evidence ${context.loop.evidenceTier.confidence.level}`
|
|
11782
|
+
);
|
|
11783
|
+
console.log(` Next: ${context.loop.nextActions[0]}`);
|
|
11784
|
+
console.log(` Stop: ${context.loop.stopConditions[0]}`);
|
|
11785
|
+
console.log("");
|
|
11786
|
+
console.log(`${BOLD10}LLM instruction:${RESET17}`);
|
|
11536
11787
|
console.log(
|
|
11537
11788
|
" Preserve the active authority above. Use the route pack, section context, typed route graph, local laws, changed-file impact, and visual evidence as the task contract before changing code."
|
|
11538
11789
|
);
|
|
@@ -11560,7 +11811,7 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11560
11811
|
const workspaceInfo = resolveWorkflowProject(flags, "codify");
|
|
11561
11812
|
if (!workspaceInfo) return;
|
|
11562
11813
|
if (flagBoolean(flags, "accept")) {
|
|
11563
|
-
if (!
|
|
11814
|
+
if (!existsSync29(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync29(localRulesProposalPath(workspaceInfo.appRoot)) && !existsSync29(styleBridgeProposalPath(workspaceInfo.appRoot))) {
|
|
11564
11815
|
console.error(
|
|
11565
11816
|
error2(
|
|
11566
11817
|
"No codify proposal found. Run `decantr codify --from-audit`, `decantr codify --style-bridge`, or `decantr codify` first."
|
|
@@ -11594,14 +11845,14 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11594
11845
|
}
|
|
11595
11846
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
11596
11847
|
const essence = readJsonIfPresent(
|
|
11597
|
-
|
|
11848
|
+
join31(workspaceInfo.appRoot, "decantr.essence.json")
|
|
11598
11849
|
);
|
|
11599
11850
|
const fromAudit = flagBoolean(flags, "from-audit") || flagBoolean(flags, "discover-local-patterns") || flagBoolean(flags, "codify-local-patterns");
|
|
11600
11851
|
const wantsStyleBridge = flagBoolean(flags, "style-bridge");
|
|
11601
11852
|
const mapPatternSlug = flagString(flags, "map-pattern") ?? flagString(flags, "hosted-pattern");
|
|
11602
11853
|
if (mapPatternSlug) {
|
|
11603
11854
|
const registryClient = new RegistryClient({
|
|
11604
|
-
cacheDir:
|
|
11855
|
+
cacheDir: join31(workspaceInfo.appRoot, ".decantr", "cache")
|
|
11605
11856
|
});
|
|
11606
11857
|
const candidates = await loadPatternDiscoveryCandidates(registryClient);
|
|
11607
11858
|
const candidate = findPatternCandidateBySlug(candidates, mapPatternSlug);
|
|
@@ -11725,15 +11976,16 @@ async function cmdContentWorkflow(args) {
|
|
|
11725
11976
|
}
|
|
11726
11977
|
function cmdHelp() {
|
|
11727
11978
|
console.log(`
|
|
11728
|
-
${
|
|
11979
|
+
${BOLD10}decantr${RESET17} \u2014 AI Frontend Governance for codebases touched by AI agents
|
|
11729
11980
|
|
|
11730
|
-
${
|
|
11981
|
+
${BOLD10}Usage:${RESET17}
|
|
11731
11982
|
decantr setup [--project <path>]
|
|
11732
11983
|
decantr scan [--project <path>] [--json]
|
|
11733
11984
|
decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
|
|
11734
11985
|
decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--no-packs] [--yes]
|
|
11735
11986
|
decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
|
|
11736
11987
|
decantr verify [--project <path>] [--brownfield] [--local-patterns] [health options]
|
|
11988
|
+
decantr resolve [--project <path>] [--json] [--defer <finding-id>] [--mark-advisory <finding-id>]
|
|
11737
11989
|
decantr graph [--project <path>] [--route <route>] [--node <id>] [--file <path>] [--task <text>] [--snapshot-id <id>] [--compare-to <id>] [--capsule-source-limit <count>] [--check] [--json]
|
|
11738
11990
|
decantr ci [--project <path>] [--workspace] [--fail-on error|warn|none]
|
|
11739
11991
|
decantr doctor [--project <path>] [--workspace] [--json]
|
|
@@ -11742,7 +11994,7 @@ ${BOLD9}Usage:${RESET16}
|
|
|
11742
11994
|
|
|
11743
11995
|
${formatWhichCommandFirst()}
|
|
11744
11996
|
|
|
11745
|
-
${
|
|
11997
|
+
${BOLD10}Advanced primitives:${RESET17}
|
|
11746
11998
|
decantr init [options]
|
|
11747
11999
|
decantr analyze
|
|
11748
12000
|
decantr magic <prompt> [--dry-run]
|
|
@@ -11753,6 +12005,7 @@ ${BOLD9}Advanced primitives:${RESET16}
|
|
|
11753
12005
|
decantr check
|
|
11754
12006
|
decantr check --brownfield
|
|
11755
12007
|
decantr sync-drift
|
|
12008
|
+
decantr resolve [--json]
|
|
11756
12009
|
decantr graph [--project <path>] [--route <route>] [--node <id>] [--file <path>] [--task <text>] [--snapshot-id <id>] [--compare-to <id>] [--capsule-source-limit <count>] [--check] [--json]
|
|
11757
12010
|
decantr search <query> [--type <type>] [--sort <recommended|recent|name>] [--recommended] [--source <authored|benchmark|hybrid>]
|
|
11758
12011
|
decantr suggest <query> [--type <type>] [--route <route>] [--file <path>] [--from-code]
|
|
@@ -11787,7 +12040,7 @@ ${BOLD9}Advanced primitives:${RESET16}
|
|
|
11787
12040
|
decantr logout
|
|
11788
12041
|
decantr help
|
|
11789
12042
|
|
|
11790
|
-
${
|
|
12043
|
+
${BOLD10}Init Options:${RESET17}
|
|
11791
12044
|
--blueprint, -b Blueprint ID
|
|
11792
12045
|
--theme Theme ID
|
|
11793
12046
|
--mode Color mode: dark | light | auto
|
|
@@ -11809,13 +12062,14 @@ ${BOLD9}Init Options:${RESET16}
|
|
|
11809
12062
|
--registry Custom registry URL
|
|
11810
12063
|
--telemetry Opt this project into privacy-filtered CLI product telemetry
|
|
11811
12064
|
|
|
11812
|
-
${
|
|
12065
|
+
${BOLD10}Commands:${RESET17}
|
|
11813
12066
|
${cyan3("setup")} Detect project state and recommend the right Decantr workflow
|
|
11814
12067
|
${cyan3("scan")} Read-only Brownfield reconnaissance; no files written
|
|
11815
12068
|
${cyan3("new")} Create a new greenfield workspace and bootstrap the available starter adapter
|
|
11816
12069
|
${cyan3("adopt")} Brownfield one-liner: analyze, attach, verify, and show next steps
|
|
11817
12070
|
${cyan3("task")} Prepare route/task context, local law, behavior obligations, evidence, and changed-file impact for an AI coding assistant
|
|
11818
12071
|
${cyan3("verify")} One reliability gate over Project Health, Brownfield checks, baselines, and evidence
|
|
12072
|
+
${cyan3("resolve")} Read authority conflicts and explicitly defer/advisory-mark drift
|
|
11819
12073
|
${cyan3("graph")} Build typed Contract graph artifacts and the agent cache capsule
|
|
11820
12074
|
${cyan3("ci")} Non-mutating CI gate and CI integration generator
|
|
11821
12075
|
${cyan3("doctor")} Explain Decantr state, artifact ownership, and the next command
|
|
@@ -11823,7 +12077,7 @@ ${BOLD9}Commands:${RESET16}
|
|
|
11823
12077
|
${cyan3("studio")} Open a local Project Health dashboard backed by the same report
|
|
11824
12078
|
${cyan3("content")} Content-author namespace: check, create, publish
|
|
11825
12079
|
|
|
11826
|
-
${
|
|
12080
|
+
${BOLD10}Advanced commands:${RESET17}
|
|
11827
12081
|
${cyan3("magic")} Greenfield-first intent flow; steers existing apps into analyze + init
|
|
11828
12082
|
${cyan3("init")} Attach Decantr contract/context files to an existing project or empty workspace
|
|
11829
12083
|
${cyan3("status")} Show project status, DNA axioms, and blueprint info
|
|
@@ -11835,6 +12089,7 @@ ${BOLD9}Advanced commands:${RESET16}
|
|
|
11835
12089
|
${cyan3("migrate")} Migrate older essence files to v4 format (with .pre-v4.backup.json backup)
|
|
11836
12090
|
${cyan3("check")} Detect drift issues (validate + guard rules) [--telemetry] [--brownfield]
|
|
11837
12091
|
${cyan3("sync-drift")} Review and resolve drift log entries
|
|
12092
|
+
${cyan3("resolve")} Group source-vs-contract conflicts and print exact resolution actions
|
|
11838
12093
|
${cyan3("graph")} Generate .decantr/graph snapshot, history, manifest, diff, and contract capsule
|
|
11839
12094
|
${cyan3("search")} Search official/community vocabulary
|
|
11840
12095
|
${cyan3("suggest")} Suggest patterns or alternatives for a query
|
|
@@ -11855,7 +12110,7 @@ ${BOLD9}Advanced commands:${RESET16}
|
|
|
11855
12110
|
${cyan3("upgrade")} Check for content updates from registry
|
|
11856
12111
|
${cyan3("help")} Show this help
|
|
11857
12112
|
|
|
11858
|
-
${
|
|
12113
|
+
${BOLD10}Examples:${RESET17}
|
|
11859
12114
|
decantr setup
|
|
11860
12115
|
decantr scan
|
|
11861
12116
|
decantr scan --json
|
|
@@ -11864,6 +12119,7 @@ ${BOLD9}Examples:${RESET16}
|
|
|
11864
12119
|
decantr adopt --project apps/web --yes
|
|
11865
12120
|
decantr task /feed "add saved recipe actions"
|
|
11866
12121
|
decantr verify --brownfield --local-patterns
|
|
12122
|
+
decantr resolve
|
|
11867
12123
|
decantr graph --project apps/web
|
|
11868
12124
|
decantr graph --project apps/web --route /feed --task "improve loading" --json
|
|
11869
12125
|
decantr graph --project apps/web --file src/app/page.tsx --impact --json
|
|
@@ -11919,35 +12175,36 @@ ${BOLD9}Examples:${RESET16}
|
|
|
11919
12175
|
decantr registry audit-project --namespace @official --dist dist --sources src
|
|
11920
12176
|
decantr create pattern my-card
|
|
11921
12177
|
|
|
11922
|
-
${
|
|
12178
|
+
${BOLD10}Workflow Model:${RESET17}
|
|
11923
12179
|
${cyan3("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=decantr-css
|
|
11924
12180
|
${cyan3("Greenfield contract")} decantr init --workflow=greenfield --adoption=contract-only
|
|
11925
12181
|
${cyan3("Brownfield adoption")} decantr adopt --yes
|
|
11926
12182
|
${cyan3("Brownfield preview")} decantr scan -> decantr adopt --yes
|
|
11927
12183
|
${cyan3("Brownfield monorepo")} decantr adopt --project apps/web --yes
|
|
11928
12184
|
${cyan3("Daily LLM work")} decantr task <route> "<change>" -> decantr verify --brownfield --local-patterns
|
|
12185
|
+
${cyan3("Drift resolution")} decantr resolve -> codify/init/graph/repair source explicitly
|
|
11929
12186
|
${cyan3("Typed contract graph")} decantr graph -> agent session loads .decantr/graph/contract-capsule.json
|
|
11930
12187
|
${cyan3("Project-owned law")} decantr codify --from-audit -> edit proposal -> decantr codify --accept
|
|
11931
12188
|
${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
|
|
11932
12189
|
|
|
11933
|
-
${
|
|
12190
|
+
${BOLD10}Bootstrap adapters:${RESET17}
|
|
11934
12191
|
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}, ${cyan3("vanilla-vite")}, ${cyan3("vue-vite")}, ${cyan3("sveltekit")}, ${cyan3("angular")}, ${cyan3("solid-vite")}
|
|
11935
12192
|
Unsupported targets resolve through ${cyan3("generic-web")} contract-only mode until their starter adapters land.
|
|
11936
12193
|
`);
|
|
11937
12194
|
}
|
|
11938
12195
|
function cmdRulesHelp() {
|
|
11939
12196
|
console.log(`
|
|
11940
|
-
${
|
|
12197
|
+
${BOLD10}decantr rules${RESET17} \u2014 Preview or apply assistant bridge snippets
|
|
11941
12198
|
|
|
11942
|
-
${
|
|
12199
|
+
${BOLD10}Usage:${RESET17}
|
|
11943
12200
|
decantr rules preview [--project=<path>]
|
|
11944
12201
|
decantr rules apply [--project=<path>]
|
|
11945
12202
|
|
|
11946
|
-
${
|
|
12203
|
+
${BOLD10}Subcommands:${RESET17}
|
|
11947
12204
|
${cyan3("preview")} Print target-specific Decantr bridge guidance without mutating rule files
|
|
11948
12205
|
${cyan3("apply")} Idempotently write Decantr bridge blocks to supported assistant rule files
|
|
11949
12206
|
|
|
11950
|
-
${
|
|
12207
|
+
${BOLD10}Examples:${RESET17}
|
|
11951
12208
|
decantr rules preview
|
|
11952
12209
|
decantr rules preview --project=apps/web
|
|
11953
12210
|
decantr rules apply --project=apps/web
|
|
@@ -11955,23 +12212,23 @@ ${BOLD9}Examples:${RESET16}
|
|
|
11955
12212
|
}
|
|
11956
12213
|
function cmdScanHelp() {
|
|
11957
12214
|
console.log(`
|
|
11958
|
-
${
|
|
12215
|
+
${BOLD10}decantr scan${RESET17} \u2014 Read-only Brownfield reconnaissance
|
|
11959
12216
|
|
|
11960
|
-
${
|
|
12217
|
+
${BOLD10}Usage:${RESET17}
|
|
11961
12218
|
decantr scan [--project <path>] [--json]
|
|
11962
12219
|
|
|
11963
|
-
${
|
|
12220
|
+
${BOLD10}Options:${RESET17}
|
|
11964
12221
|
--project App path inside a workspace/monorepo
|
|
11965
12222
|
--json Emit the ScanReportV1 JSON to stdout
|
|
11966
12223
|
|
|
11967
|
-
${
|
|
12224
|
+
${BOLD10}Behavior:${RESET17}
|
|
11968
12225
|
Reads local project files, detects frontend framework/routes/styling/static-hosting signals,
|
|
11969
12226
|
and prints a terminal report. It does not write .decantr files, install dependencies,
|
|
11970
12227
|
build the app, execute scripts, upload source, or open pull requests.
|
|
11971
12228
|
|
|
11972
12229
|
${formatWhichCommandFirst()}
|
|
11973
12230
|
|
|
11974
|
-
${
|
|
12231
|
+
${BOLD10}Examples:${RESET17}
|
|
11975
12232
|
decantr scan
|
|
11976
12233
|
decantr scan --project apps/web
|
|
11977
12234
|
decantr scan --json
|
|
@@ -11982,9 +12239,9 @@ function isCommandHelpRequest(args) {
|
|
|
11982
12239
|
}
|
|
11983
12240
|
function cmdHealthHelp() {
|
|
11984
12241
|
console.log(`
|
|
11985
|
-
${
|
|
12242
|
+
${BOLD10}decantr health${RESET17} \u2014 Generate a local Project Health report
|
|
11986
12243
|
|
|
11987
|
-
${
|
|
12244
|
+
${BOLD10}Usage:${RESET17}
|
|
11988
12245
|
decantr health [--format text|json|markdown] [--output <file>]
|
|
11989
12246
|
decantr health --json
|
|
11990
12247
|
decantr health --markdown
|
|
@@ -11997,7 +12254,7 @@ ${BOLD9}Usage:${RESET16}
|
|
|
11997
12254
|
decantr health --since-baseline
|
|
11998
12255
|
decantr health init-ci [legacy alias for decantr ci init]
|
|
11999
12256
|
|
|
12000
|
-
${
|
|
12257
|
+
${BOLD10}Options:${RESET17}
|
|
12001
12258
|
--format Output format: text, json, or markdown
|
|
12002
12259
|
--json Emit JSON report
|
|
12003
12260
|
--markdown Emit markdown report
|
|
@@ -12013,7 +12270,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
12013
12270
|
--since-baseline Compare this run to .decantr/health-baseline.json
|
|
12014
12271
|
--design-tokens Compare against a Figma/Tokens Studio JSON export
|
|
12015
12272
|
|
|
12016
|
-
${
|
|
12273
|
+
${BOLD10}Examples:${RESET17}
|
|
12017
12274
|
decantr health
|
|
12018
12275
|
decantr health --json
|
|
12019
12276
|
decantr health --markdown --output decantr-health.md
|
|
@@ -12027,14 +12284,14 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12027
12284
|
}
|
|
12028
12285
|
function cmdWorkspaceHelp() {
|
|
12029
12286
|
console.log(`
|
|
12030
|
-
${
|
|
12287
|
+
${BOLD10}decantr workspace${RESET17} \u2014 Inspect Decantr projects and app candidates across a monorepo
|
|
12031
12288
|
|
|
12032
|
-
${
|
|
12289
|
+
${BOLD10}Usage:${RESET17}
|
|
12033
12290
|
decantr workspace list [--json]
|
|
12034
12291
|
decantr workspace health [--json|--markdown] [--output <file>]
|
|
12035
12292
|
decantr workspace health --changed --since origin/main
|
|
12036
12293
|
|
|
12037
|
-
${
|
|
12294
|
+
${BOLD10}Examples:${RESET17}
|
|
12038
12295
|
decantr workspace list
|
|
12039
12296
|
decantr adopt --project apps/web --yes
|
|
12040
12297
|
decantr workspace health
|
|
@@ -12044,16 +12301,16 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12044
12301
|
}
|
|
12045
12302
|
function cmdContentHealthHelp() {
|
|
12046
12303
|
console.log(`
|
|
12047
|
-
${
|
|
12304
|
+
${BOLD10}decantr content-health${RESET17} \u2014 Generate a local official-vocabulary health report
|
|
12048
12305
|
|
|
12049
|
-
${
|
|
12306
|
+
${BOLD10}Usage:${RESET17}
|
|
12050
12307
|
decantr content-health [--format text|json|markdown] [--output <file>]
|
|
12051
12308
|
decantr content-health --json
|
|
12052
12309
|
decantr content-health --markdown
|
|
12053
12310
|
decantr content-health --ci [--fail-on error|warn|none]
|
|
12054
12311
|
decantr content-health --prompt <finding-id>
|
|
12055
12312
|
|
|
12056
|
-
${
|
|
12313
|
+
${BOLD10}Options:${RESET17}
|
|
12057
12314
|
--format Output format: text, json, or markdown
|
|
12058
12315
|
--json Emit JSON report
|
|
12059
12316
|
--markdown Emit markdown report
|
|
@@ -12062,7 +12319,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
12062
12319
|
--fail-on CI threshold: error, warn, or none
|
|
12063
12320
|
--prompt Print an AI-ready remediation prompt for a finding
|
|
12064
12321
|
|
|
12065
|
-
${
|
|
12322
|
+
${BOLD10}Examples:${RESET17}
|
|
12066
12323
|
decantr content-health
|
|
12067
12324
|
decantr content-health --json
|
|
12068
12325
|
decantr content-health --markdown --output content-health.md
|
|
@@ -12071,23 +12328,29 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12071
12328
|
}
|
|
12072
12329
|
function cmdStudioHelp() {
|
|
12073
12330
|
console.log(`
|
|
12074
|
-
${
|
|
12331
|
+
${BOLD10}decantr studio${RESET17} \u2014 Run a local Project Health dashboard
|
|
12075
12332
|
|
|
12076
|
-
${
|
|
12333
|
+
${BOLD10}Usage:${RESET17}
|
|
12077
12334
|
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
|
|
12078
12335
|
|
|
12079
|
-
${
|
|
12336
|
+
${BOLD10}Options:${RESET17}
|
|
12080
12337
|
--port Local port to bind; defaults to 4319
|
|
12081
12338
|
--host Local host to bind; defaults to 127.0.0.1
|
|
12082
12339
|
--report Serve a read-only Project Health JSON artifact instead of scanning the current project
|
|
12083
12340
|
--workspace Serve a monorepo workspace health dashboard
|
|
12084
12341
|
|
|
12085
|
-
${
|
|
12342
|
+
${BOLD10}Endpoints:${RESET17}
|
|
12086
12343
|
GET /
|
|
12087
12344
|
GET /api/health
|
|
12345
|
+
GET /api/control-room
|
|
12346
|
+
GET /api/resolve
|
|
12347
|
+
GET /api/evidence
|
|
12348
|
+
GET /api/graph-impact
|
|
12349
|
+
GET /api/task-preview
|
|
12350
|
+
GET /api/proof
|
|
12088
12351
|
POST /api/refresh
|
|
12089
12352
|
|
|
12090
|
-
${
|
|
12353
|
+
${BOLD10}Examples:${RESET17}
|
|
12091
12354
|
decantr studio
|
|
12092
12355
|
decantr studio --port 4320
|
|
12093
12356
|
decantr studio --host 127.0.0.1 --port 4319
|
|
@@ -12098,9 +12361,9 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12098
12361
|
}
|
|
12099
12362
|
function cmdRegistryHelp() {
|
|
12100
12363
|
console.log(`
|
|
12101
|
-
${
|
|
12364
|
+
${BOLD10}decantr registry${RESET17} \u2014 Read hosted execution packs and registry intelligence
|
|
12102
12365
|
|
|
12103
|
-
${
|
|
12366
|
+
${BOLD10}Usage:${RESET17}
|
|
12104
12367
|
decantr registry summary [--namespace <namespace>] [--json]
|
|
12105
12368
|
decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
|
|
12106
12369
|
decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
|
|
@@ -12111,9 +12374,9 @@ ${BOLD9}Usage:${RESET16}
|
|
|
12111
12374
|
}
|
|
12112
12375
|
function cmdThemeHelp() {
|
|
12113
12376
|
console.log(`
|
|
12114
|
-
${
|
|
12377
|
+
${BOLD10}decantr theme${RESET17} \u2014 Manage custom themes
|
|
12115
12378
|
|
|
12116
|
-
${
|
|
12379
|
+
${BOLD10}Usage:${RESET17}
|
|
12117
12380
|
decantr theme create <name>
|
|
12118
12381
|
decantr theme create <name> --guided
|
|
12119
12382
|
decantr theme list
|
|
@@ -12124,27 +12387,27 @@ ${BOLD9}Usage:${RESET16}
|
|
|
12124
12387
|
}
|
|
12125
12388
|
function cmdSetupHelp() {
|
|
12126
12389
|
console.log(`
|
|
12127
|
-
${
|
|
12390
|
+
${BOLD10}decantr setup${RESET17} \u2014 Detect the project state and recommend the right Decantr path
|
|
12128
12391
|
|
|
12129
|
-
${
|
|
12392
|
+
${BOLD10}Usage:${RESET17}
|
|
12130
12393
|
decantr setup [--project <path>]
|
|
12131
12394
|
|
|
12132
12395
|
${formatWhichCommandFirst()}
|
|
12133
12396
|
|
|
12134
|
-
${
|
|
12397
|
+
${BOLD10}Examples:${RESET17}
|
|
12135
12398
|
decantr setup
|
|
12136
12399
|
decantr setup --project apps/web
|
|
12137
12400
|
`);
|
|
12138
12401
|
}
|
|
12139
12402
|
function cmdAdoptHelp() {
|
|
12140
12403
|
console.log(`
|
|
12141
|
-
${
|
|
12404
|
+
${BOLD10}decantr adopt${RESET17} \u2014 Brownfield one-liner: analyze, attach, hydrate packs, verify, and show the operating loop
|
|
12142
12405
|
|
|
12143
|
-
${
|
|
12406
|
+
${BOLD10}Usage:${RESET17}
|
|
12144
12407
|
decantr adopt [--project <path>] [--yes] [--dry-run] [--no-packs]
|
|
12145
12408
|
decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes] [--no-packs]
|
|
12146
12409
|
|
|
12147
|
-
${
|
|
12410
|
+
${BOLD10}Options:${RESET17}
|
|
12148
12411
|
--project App path inside a workspace/monorepo
|
|
12149
12412
|
--yes, -y Run without confirmation
|
|
12150
12413
|
--dry-run Show the workflow without writing files
|
|
@@ -12159,7 +12422,7 @@ ${BOLD9}Options:${RESET16}
|
|
|
12159
12422
|
--merge-proposal Merge the observed proposal into an existing essence
|
|
12160
12423
|
--replace-essence Replace an existing essence with backup
|
|
12161
12424
|
|
|
12162
|
-
${
|
|
12425
|
+
${BOLD10}Examples:${RESET17}
|
|
12163
12426
|
decantr adopt --yes
|
|
12164
12427
|
decantr adopt --project apps/web --yes
|
|
12165
12428
|
decantr adopt --project apps/web --base-url http://localhost:3000 --evidence --yes
|
|
@@ -12169,16 +12432,16 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12169
12432
|
}
|
|
12170
12433
|
function cmdVerifyHelp() {
|
|
12171
12434
|
console.log(`
|
|
12172
|
-
${
|
|
12435
|
+
${BOLD10}decantr verify${RESET17} \u2014 One reliability command for local work and LLM agent loops
|
|
12173
12436
|
|
|
12174
|
-
${
|
|
12437
|
+
${BOLD10}Usage:${RESET17}
|
|
12175
12438
|
decantr verify [--project <path>] [--brownfield] [--local-patterns]
|
|
12176
12439
|
decantr verify --base-url <url> --evidence
|
|
12177
12440
|
decantr verify --since-baseline
|
|
12178
12441
|
decantr verify --workspace [--changed --since origin/main]
|
|
12179
12442
|
decantr verify init-ci [legacy alias for decantr ci init]
|
|
12180
12443
|
|
|
12181
|
-
${
|
|
12444
|
+
${BOLD10}Examples:${RESET17}
|
|
12182
12445
|
decantr verify
|
|
12183
12446
|
decantr verify --brownfield --local-patterns
|
|
12184
12447
|
decantr verify --brownfield --local-patterns --project apps/web
|
|
@@ -12190,32 +12453,54 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12190
12453
|
}
|
|
12191
12454
|
function cmdTaskHelp() {
|
|
12192
12455
|
console.log(`
|
|
12193
|
-
${
|
|
12456
|
+
${BOLD10}decantr task${RESET17} \u2014 Prepare compact route/task context for an AI coding assistant
|
|
12194
12457
|
|
|
12195
|
-
${
|
|
12458
|
+
${BOLD10}Usage:${RESET17}
|
|
12196
12459
|
decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
|
|
12197
12460
|
|
|
12198
|
-
${
|
|
12461
|
+
${BOLD10}Behavior:${RESET17}
|
|
12199
12462
|
Includes accepted local law and behavior obligations, plus the typed contract capsule path when
|
|
12200
12463
|
.decantr/graph exists. Run decantr graph first when you want graph-backed agent context in
|
|
12201
12464
|
CLI-only workflows.
|
|
12202
12465
|
|
|
12203
|
-
${
|
|
12466
|
+
${BOLD10}Examples:${RESET17}
|
|
12204
12467
|
decantr task /feed "add saved recipe actions"
|
|
12205
12468
|
decantr task /feed "add saved recipe actions" --since origin/main
|
|
12206
12469
|
decantr task /profile --json
|
|
12207
12470
|
`);
|
|
12208
12471
|
}
|
|
12472
|
+
function cmdResolveHelp() {
|
|
12473
|
+
console.log(`
|
|
12474
|
+
${BOLD10}decantr resolve${RESET17} \u2014 Explain source-vs-contract authority conflicts
|
|
12475
|
+
|
|
12476
|
+
${BOLD10}Usage:${RESET17}
|
|
12477
|
+
decantr resolve [--project <path>] [--json]
|
|
12478
|
+
decantr resolve --defer <finding-id>
|
|
12479
|
+
decantr resolve --mark-advisory <finding-id>
|
|
12480
|
+
|
|
12481
|
+
${BOLD10}Behavior:${RESET17}
|
|
12482
|
+
Read-only by default. Writes are limited to .decantr/drift-log.json and require
|
|
12483
|
+
--defer or --mark-advisory. Contract, source, local-law, and style-bridge changes
|
|
12484
|
+
still go through explicit commands such as codify, init --existing --merge-proposal,
|
|
12485
|
+
graph, or contract_write over MCP.
|
|
12486
|
+
|
|
12487
|
+
${BOLD10}Examples:${RESET17}
|
|
12488
|
+
decantr resolve
|
|
12489
|
+
decantr resolve --json
|
|
12490
|
+
decantr resolve --project apps/web
|
|
12491
|
+
decantr resolve --defer brownfield-route-drift
|
|
12492
|
+
`);
|
|
12493
|
+
}
|
|
12209
12494
|
function cmdCodifyHelp() {
|
|
12210
12495
|
console.log(`
|
|
12211
|
-
${
|
|
12496
|
+
${BOLD10}decantr codify${RESET17} \u2014 Propose or accept project-owned Brownfield UI law, behavior obligations, and style bridges
|
|
12212
12497
|
|
|
12213
|
-
${
|
|
12498
|
+
${BOLD10}Usage:${RESET17}
|
|
12214
12499
|
decantr codify [--from-audit] [--style-bridge] [--project <path>]
|
|
12215
12500
|
decantr codify --map-pattern <registry-pattern-slug> [--project <path>]
|
|
12216
12501
|
decantr codify --accept [--project <path>]
|
|
12217
12502
|
|
|
12218
|
-
${
|
|
12503
|
+
${BOLD10}Examples:${RESET17}
|
|
12219
12504
|
decantr codify
|
|
12220
12505
|
decantr codify --from-audit
|
|
12221
12506
|
decantr codify --style-bridge
|
|
@@ -12227,14 +12512,14 @@ ${BOLD9}Examples:${RESET16}
|
|
|
12227
12512
|
}
|
|
12228
12513
|
function cmdContentHelp() {
|
|
12229
12514
|
console.log(`
|
|
12230
|
-
${
|
|
12515
|
+
${BOLD10}decantr content${RESET17} \u2014 Content-author namespace for official-vocabulary repositories
|
|
12231
12516
|
|
|
12232
|
-
${
|
|
12517
|
+
${BOLD10}Usage:${RESET17}
|
|
12233
12518
|
decantr content check [content-health options]
|
|
12234
12519
|
decantr content create <type> <name>
|
|
12235
12520
|
decantr content publish <type> <name>
|
|
12236
12521
|
|
|
12237
|
-
${
|
|
12522
|
+
${BOLD10}Examples:${RESET17}
|
|
12238
12523
|
decantr content check --ci --fail-on error
|
|
12239
12524
|
decantr content create pattern my-card
|
|
12240
12525
|
decantr content publish pattern my-card
|
|
@@ -12267,6 +12552,9 @@ function printCommandHelp(command, args) {
|
|
|
12267
12552
|
case "task":
|
|
12268
12553
|
cmdTaskHelp();
|
|
12269
12554
|
return true;
|
|
12555
|
+
case "resolve":
|
|
12556
|
+
cmdResolveHelp();
|
|
12557
|
+
return true;
|
|
12270
12558
|
case "codify":
|
|
12271
12559
|
cmdCodifyHelp();
|
|
12272
12560
|
return true;
|
|
@@ -12308,11 +12596,11 @@ async function main() {
|
|
|
12308
12596
|
}
|
|
12309
12597
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
12310
12598
|
try {
|
|
12311
|
-
const here =
|
|
12312
|
-
const candidates = [
|
|
12599
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
12600
|
+
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
12313
12601
|
for (const candidate of candidates) {
|
|
12314
|
-
if (
|
|
12315
|
-
const pkg = JSON.parse(
|
|
12602
|
+
if (existsSync29(candidate)) {
|
|
12603
|
+
const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
|
|
12316
12604
|
if (pkg.version) {
|
|
12317
12605
|
console.log(pkg.version);
|
|
12318
12606
|
return;
|
|
@@ -12351,6 +12639,16 @@ async function main() {
|
|
|
12351
12639
|
await cmdVerifyWorkflow(args);
|
|
12352
12640
|
break;
|
|
12353
12641
|
}
|
|
12642
|
+
case "resolve": {
|
|
12643
|
+
const { flags } = parseLooseArgs(args);
|
|
12644
|
+
if (!ensureAllowedFlags(flags, ["project", "json", "defer", "mark-advisory"], "resolve")) {
|
|
12645
|
+
break;
|
|
12646
|
+
}
|
|
12647
|
+
const workspaceInfo = resolveWorkflowProject(flags, "resolve");
|
|
12648
|
+
if (!workspaceInfo) break;
|
|
12649
|
+
await cmdResolve(workspaceInfo.appRoot, args);
|
|
12650
|
+
break;
|
|
12651
|
+
}
|
|
12354
12652
|
case "graph": {
|
|
12355
12653
|
const { flags } = parseLooseArgs(args);
|
|
12356
12654
|
if (!ensureAllowedFlags(
|
|
@@ -12511,10 +12809,10 @@ async function main() {
|
|
|
12511
12809
|
case "heal": {
|
|
12512
12810
|
if (command === "heal") {
|
|
12513
12811
|
console.log(
|
|
12514
|
-
`${
|
|
12812
|
+
`${YELLOW13}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET17}`
|
|
12515
12813
|
);
|
|
12516
12814
|
}
|
|
12517
|
-
const { cmdHeal } = await import("./heal-
|
|
12815
|
+
const { cmdHeal } = await import("./heal-YXWB6LTI.js");
|
|
12518
12816
|
const { flags } = parseLooseArgs(args);
|
|
12519
12817
|
const workspaceInfo = resolveWorkflowProject(flags, "check");
|
|
12520
12818
|
if (!workspaceInfo) break;
|
|
@@ -12539,7 +12837,7 @@ async function main() {
|
|
|
12539
12837
|
const { flags } = parseLooseArgs(args);
|
|
12540
12838
|
const workspaceInfo = resolveWorkflowProject(flags, "health");
|
|
12541
12839
|
if (!workspaceInfo) break;
|
|
12542
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
12840
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-5S2L44SX.js");
|
|
12543
12841
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
|
|
12544
12842
|
} catch (e) {
|
|
12545
12843
|
console.error(error2(e.message));
|
|
@@ -12567,7 +12865,7 @@ async function main() {
|
|
|
12567
12865
|
cmdStudioHelp();
|
|
12568
12866
|
break;
|
|
12569
12867
|
}
|
|
12570
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
12868
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-EN347SLA.js");
|
|
12571
12869
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
12572
12870
|
} catch (e) {
|
|
12573
12871
|
console.error(error2(e.message));
|
|
@@ -12581,7 +12879,7 @@ async function main() {
|
|
|
12581
12879
|
cmdWorkspaceHelp();
|
|
12582
12880
|
break;
|
|
12583
12881
|
}
|
|
12584
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
12882
|
+
const { cmdWorkspace } = await import("./workspace-UIKTIWUN.js");
|
|
12585
12883
|
await cmdWorkspace(process.cwd(), args);
|
|
12586
12884
|
} catch (e) {
|
|
12587
12885
|
console.error(error2(e.message));
|
|
@@ -12890,7 +13188,7 @@ async function main() {
|
|
|
12890
13188
|
let id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
|
|
12891
13189
|
if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
|
|
12892
13190
|
console.error(
|
|
12893
|
-
`${
|
|
13191
|
+
`${RED13}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET17}`
|
|
12894
13192
|
);
|
|
12895
13193
|
process.exitCode = 1;
|
|
12896
13194
|
break;
|
|
@@ -12900,7 +13198,7 @@ async function main() {
|
|
|
12900
13198
|
break;
|
|
12901
13199
|
}
|
|
12902
13200
|
if (packType === "page" && route && !id) {
|
|
12903
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
13201
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
12904
13202
|
id = resolvePagePackIdForRoute(resolvedPath, route);
|
|
12905
13203
|
}
|
|
12906
13204
|
await printHostedSelectedExecutionPack(
|
|
@@ -12922,7 +13220,7 @@ async function main() {
|
|
|
12922
13220
|
const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
12923
13221
|
if (!sourcePath) {
|
|
12924
13222
|
console.error(
|
|
12925
|
-
`${
|
|
13223
|
+
`${RED13}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET17}`
|
|
12926
13224
|
);
|
|
12927
13225
|
process.exitCode = 1;
|
|
12928
13226
|
break;
|
|
@@ -12947,7 +13245,7 @@ async function main() {
|
|
|
12947
13245
|
await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
|
|
12948
13246
|
} else {
|
|
12949
13247
|
console.error(
|
|
12950
|
-
`${
|
|
13248
|
+
`${RED13}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${RESET17}`
|
|
12951
13249
|
);
|
|
12952
13250
|
process.exitCode = 1;
|
|
12953
13251
|
}
|
|
@@ -13119,7 +13417,7 @@ async function main() {
|
|
|
13119
13417
|
console.error("");
|
|
13120
13418
|
console.error(" Example:");
|
|
13121
13419
|
console.error(
|
|
13122
|
-
` ${CYAN9}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${
|
|
13420
|
+
` ${CYAN9}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${RESET17}`
|
|
13123
13421
|
);
|
|
13124
13422
|
process.exitCode = 1;
|
|
13125
13423
|
break;
|