@decantr/cli 3.7.0 → 3.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -30
- package/dist/bin.js +5 -5
- package/dist/{chunk-24JR4ZNG.js → chunk-2UC6YYVZ.js} +25 -11
- package/dist/{chunk-O7N4CCWS.js → chunk-CI2R5W36.js} +477 -604
- package/dist/{chunk-NDH3BDXY.js → chunk-JK3DYOHA.js} +49 -34
- package/dist/{chunk-WAGVDMJV.js → chunk-PFFNEN7L.js} +19 -19
- package/dist/{chunk-56HUEUO3.js → chunk-W242I6CS.js} +1 -1
- package/dist/{content-health-4KP2EGTI.js → content-health-PYGEZZOV.js} +4 -4
- package/dist/{heal-2FK63EQE.js → heal-AEMYO7T2.js} +1 -1
- package/dist/{health-KUPBUU3B.js → health-WZ562PRA.js} +2 -2
- package/dist/index.js +5 -5
- package/dist/{studio-J6Z3AUAR.js → studio-6Q2G4PTT.js} +3 -3
- package/dist/{upgrade-4BUQAYBU.js → upgrade-5ZE4VR3R.js} +1 -1
- package/dist/{workspace-QAZ3F4VT.js → workspace-EDP7QG7T.js} +3 -3
- package/package.json +7 -6
- package/src/bundled/blueprints/default.json +1 -1
- package/src/templates/DECANTR.md.template +1 -1
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
scaffoldProject,
|
|
15
15
|
syncRegistry,
|
|
16
16
|
writeExecutionPackBundleArtifacts
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JK3DYOHA.js";
|
|
18
18
|
import {
|
|
19
19
|
createWorkspaceHealthReport,
|
|
20
20
|
formatWorkspaceHealthMarkdown,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
listWorkspaceCandidates,
|
|
23
23
|
listWorkspaceProjects,
|
|
24
24
|
shouldFailWorkspaceHealth
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-W242I6CS.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-PFFNEN7L.js";
|
|
56
56
|
import {
|
|
57
57
|
buildGuardRegistryContext,
|
|
58
58
|
createDoctrineMap,
|
|
@@ -69,12 +69,12 @@ import {
|
|
|
69
69
|
sendCliCommandTelemetry,
|
|
70
70
|
sendNewProjectCompletedTelemetry,
|
|
71
71
|
writeDoctrineMap
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-2UC6YYVZ.js";
|
|
73
73
|
|
|
74
74
|
// src/index.ts
|
|
75
|
-
import { existsSync as
|
|
76
|
-
import { basename as basename2, dirname as
|
|
77
|
-
import { fileURLToPath as
|
|
75
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readdirSync as readdirSync8, readFileSync as readFileSync21, writeFileSync as writeFileSync20 } from "fs";
|
|
76
|
+
import { basename as basename2, dirname as dirname8, isAbsolute as isAbsolute4, join as join31, relative as relative7, resolve as resolve5 } from "path";
|
|
77
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
78
78
|
import {
|
|
79
79
|
buildGraphImpactContext,
|
|
80
80
|
buildGraphRouteContext,
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
} from "@decantr/core";
|
|
84
84
|
import { evaluateGuard, isV4 as isV48, validateEssence as validateEssence2 } from "@decantr/essence-spec";
|
|
85
85
|
import {
|
|
86
|
-
CONTENT_TYPE_TO_API_CONTENT_TYPE as
|
|
86
|
+
CONTENT_TYPE_TO_API_CONTENT_TYPE as CONTENT_TYPE_TO_API_CONTENT_TYPE2,
|
|
87
87
|
CONTENT_TYPES as GET_CONTENT_TYPES,
|
|
88
88
|
getBlueprintPortfolioMetadata,
|
|
89
89
|
isApiContentType,
|
|
@@ -92,7 +92,7 @@ import {
|
|
|
92
92
|
isPublicBlueprintSet,
|
|
93
93
|
API_CONTENT_TYPES as LIST_CONTENT_TYPES,
|
|
94
94
|
patternToDiscoveryCandidate,
|
|
95
|
-
RegistryAPIClient as
|
|
95
|
+
RegistryAPIClient as RegistryAPIClient2,
|
|
96
96
|
rankPatternCandidates
|
|
97
97
|
} from "@decantr/registry";
|
|
98
98
|
import {
|
|
@@ -1751,7 +1751,7 @@ function generateBrownfieldReport(proposal, ambient, doctrine) {
|
|
|
1751
1751
|
lines.push("## Non-Goals By Default");
|
|
1752
1752
|
lines.push("");
|
|
1753
1753
|
lines.push(
|
|
1754
|
-
"- Does not install Decantr CSS, switch themes, replace layouts, rewrite docs, mutate assistant rules, or import
|
|
1754
|
+
"- Does not install Decantr CSS, switch themes, replace layouts, rewrite docs, mutate assistant rules, or import official corpus patterns unless explicitly requested."
|
|
1755
1755
|
);
|
|
1756
1756
|
lines.push(
|
|
1757
1757
|
"- Does not treat stale migration or completion summaries as current doctrine without verification."
|
|
@@ -1763,7 +1763,7 @@ function generateBrownfieldReport(proposal, ambient, doctrine) {
|
|
|
1763
1763
|
"- Existing framework, routes, layout shell, feature names, styling signals, and ambient doctrine were used as evidence for the proposal."
|
|
1764
1764
|
);
|
|
1765
1765
|
lines.push(
|
|
1766
|
-
"- Decantr
|
|
1766
|
+
"- Decantr official corpus content, Decantr CSS, and default Decantr themes were not accepted as brownfield defaults."
|
|
1767
1767
|
);
|
|
1768
1768
|
lines.push("");
|
|
1769
1769
|
lines.push("## Uncertain Evidence");
|
|
@@ -3018,7 +3018,7 @@ function resolveWorkflowPolicy(input) {
|
|
|
3018
3018
|
} else {
|
|
3019
3019
|
workflowMode = hasRegistryContent ? "greenfield-scaffold" : "greenfield-contract-only";
|
|
3020
3020
|
}
|
|
3021
|
-
const adoptionMode = requestedAdoption ?? input.workflowSeed?.adoptionMode ??
|
|
3021
|
+
const adoptionMode = requestedAdoption ?? input.workflowSeed?.adoptionMode ?? "contract-only";
|
|
3022
3022
|
const contentSource = hasRegistryContent ? input.offline ? "cache" : "official" : "none";
|
|
3023
3023
|
const assistantBridge = requestedAssistantBridge ?? input.workflowSeed?.assistantBridge ?? (workflowMode === "brownfield-attach" && input.detected.existingRuleFiles.length > 0 ? "preview" : "none");
|
|
3024
3024
|
return {
|
|
@@ -3051,7 +3051,7 @@ function createBrownfieldInitSeed(detected, layout, styling) {
|
|
|
3051
3051
|
existing: true,
|
|
3052
3052
|
notes: [
|
|
3053
3053
|
"Use decantr init --existing to attach Decantr contract and context files to this project.",
|
|
3054
|
-
"
|
|
3054
|
+
"Official corpus content is optional during brownfield adoption.",
|
|
3055
3055
|
"Use decantr add/remove, decantr theme switch, and registry commands later for hybrid composition."
|
|
3056
3056
|
]
|
|
3057
3057
|
};
|
|
@@ -4109,7 +4109,7 @@ decantr theme validate mytheme
|
|
|
4109
4109
|
|
|
4110
4110
|
## Reference
|
|
4111
4111
|
|
|
4112
|
-
See
|
|
4112
|
+
See official corpus themes for examples:
|
|
4113
4113
|
|
|
4114
4114
|
\`\`\`bash
|
|
4115
4115
|
decantr get theme auradecantism
|
|
@@ -5885,11 +5885,12 @@ async function cmdMigrate(projectRoot = process.cwd(), args = []) {
|
|
|
5885
5885
|
import { spawnSync } from "child_process";
|
|
5886
5886
|
import { existsSync as existsSync21, mkdirSync as mkdirSync13 } from "fs";
|
|
5887
5887
|
import { join as join23, resolve as resolve3 } from "path";
|
|
5888
|
-
import { fileURLToPath as
|
|
5888
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5889
5889
|
|
|
5890
5890
|
// src/offline-content.ts
|
|
5891
5891
|
import { cpSync, existsSync as existsSync20, mkdirSync as mkdirSync12 } from "fs";
|
|
5892
|
-
import { join as join22, resolve as resolve2 } from "path";
|
|
5892
|
+
import { dirname as dirname6, join as join22, resolve as resolve2 } from "path";
|
|
5893
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5893
5894
|
var CONTENT_TYPES2 = ["archetypes", "blueprints", "patterns", "themes", "shells"];
|
|
5894
5895
|
function copyIfExists(source, target) {
|
|
5895
5896
|
if (!existsSync20(source)) return false;
|
|
@@ -5931,12 +5932,24 @@ function seedOfflineRegistry(projectDir, workspaceRoot) {
|
|
|
5931
5932
|
if (copiedCache || copiedCustom) {
|
|
5932
5933
|
return { seeded: true, strategy: "workspace-cache" };
|
|
5933
5934
|
}
|
|
5934
|
-
const
|
|
5935
|
-
if (hydrateContentRoot(projectDir,
|
|
5936
|
-
return { seeded: true, strategy: "
|
|
5935
|
+
const workspaceContentRoot = resolve2(workspaceRoot, "packages", "content");
|
|
5936
|
+
if (hydrateContentRoot(projectDir, workspaceContentRoot)) {
|
|
5937
|
+
return { seeded: true, strategy: "workspace-content-root" };
|
|
5938
|
+
}
|
|
5939
|
+
const installedContentRoot = resolveInstalledContentRoot();
|
|
5940
|
+
if (installedContentRoot && hydrateContentRoot(projectDir, installedContentRoot)) {
|
|
5941
|
+
return { seeded: true, strategy: "installed-content-package" };
|
|
5937
5942
|
}
|
|
5938
5943
|
return { seeded: false, strategy: null };
|
|
5939
5944
|
}
|
|
5945
|
+
function resolveInstalledContentRoot() {
|
|
5946
|
+
try {
|
|
5947
|
+
const entry = fileURLToPath2(import.meta.resolve("@decantr/content"));
|
|
5948
|
+
return resolve2(dirname6(entry), "..");
|
|
5949
|
+
} catch {
|
|
5950
|
+
return null;
|
|
5951
|
+
}
|
|
5952
|
+
}
|
|
5940
5953
|
|
|
5941
5954
|
// src/commands/new-project.ts
|
|
5942
5955
|
var BOLD6 = "\x1B[1m";
|
|
@@ -6041,7 +6054,7 @@ function runArgvCommand(command, args, cwd) {
|
|
|
6041
6054
|
}
|
|
6042
6055
|
}
|
|
6043
6056
|
function resolveInitCommand(initFlags) {
|
|
6044
|
-
const bundledCliEntrypoint =
|
|
6057
|
+
const bundledCliEntrypoint = fileURLToPath3(new URL("./bin.js", import.meta.url));
|
|
6045
6058
|
const cliEntrypoint = existsSync21(bundledCliEntrypoint) ? bundledCliEntrypoint : process.argv[1] && existsSync21(process.argv[1]) ? process.argv[1] : null;
|
|
6046
6059
|
if (cliEntrypoint) {
|
|
6047
6060
|
return {
|
|
@@ -6060,8 +6073,7 @@ async function cmdNewProject(projectName, options) {
|
|
|
6060
6073
|
const projectDir = resolve3(workspaceRoot, projectName);
|
|
6061
6074
|
const bootstrapTarget = resolveBootstrapTarget(options.target);
|
|
6062
6075
|
const bootstrapAdapter = getBootstrapAdapter(bootstrapTarget);
|
|
6063
|
-
const
|
|
6064
|
-
const inferredAdoption = options.adoption || (registryBackedScaffold ? "decantr-css" : "contract-only");
|
|
6076
|
+
const inferredAdoption = options.adoption || "contract-only";
|
|
6065
6077
|
const shouldBootstrapRuntime = Boolean(bootstrapAdapter && inferredAdoption === "decantr-css");
|
|
6066
6078
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(projectName)) {
|
|
6067
6079
|
console.error(
|
|
@@ -6123,14 +6135,14 @@ ${YELLOW6}Dependency install failed. Run \`${packageManager} install\` manually.
|
|
|
6123
6135
|
);
|
|
6124
6136
|
const seeded = options.offline ? seedOfflineRegistry(projectDir, workspaceRoot) : { seeded: false, strategy: null };
|
|
6125
6137
|
if (seeded.seeded) {
|
|
6126
|
-
console.log(dim3(` Seeded offline
|
|
6138
|
+
console.log(dim3(` Seeded offline official content from ${seeded.strategy}.`));
|
|
6127
6139
|
} else if (requiresOfflineContent) {
|
|
6128
6140
|
console.log(
|
|
6129
|
-
`${YELLOW6} Offline blueprint/archetype resolution requires local
|
|
6141
|
+
`${YELLOW6} Offline blueprint/archetype resolution requires local content corpus data.${RESET9}`
|
|
6130
6142
|
);
|
|
6131
6143
|
console.log(
|
|
6132
6144
|
dim3(
|
|
6133
|
-
" No parent workspace cache/custom content or
|
|
6145
|
+
" No parent workspace cache/custom content, configured content source, or installed @decantr/content corpus was found."
|
|
6134
6146
|
)
|
|
6135
6147
|
);
|
|
6136
6148
|
console.log("");
|
|
@@ -6141,7 +6153,7 @@ ${YELLOW6}Dependency install failed. Run \`${packageManager} install\` manually.
|
|
|
6141
6153
|
console.log(` ${cyan3(packageManager + " run dev")}`);
|
|
6142
6154
|
console.log(` ${cyan3("decantr sync")} ${dim3("# when online, then rerun decantr init")}`);
|
|
6143
6155
|
console.log(
|
|
6144
|
-
` ${cyan3("DECANTR_CONTENT_DIR=/path/to/
|
|
6156
|
+
` ${cyan3("DECANTR_CONTENT_DIR=/path/to/content decantr init --existing --offline")} ${dim3("# or seed a local content source")}`
|
|
6145
6157
|
);
|
|
6146
6158
|
console.log("");
|
|
6147
6159
|
return;
|
|
@@ -6196,73 +6208,18 @@ function detectPackageManager3() {
|
|
|
6196
6208
|
}
|
|
6197
6209
|
|
|
6198
6210
|
// src/commands/publish.ts
|
|
6199
|
-
import { existsSync as existsSync22, readFileSync as readFileSync15 } from "fs";
|
|
6200
|
-
import { join as join24 } from "path";
|
|
6201
|
-
import {
|
|
6202
|
-
API_CONTENT_TYPE_TO_CONTENT_TYPE,
|
|
6203
|
-
CONTENT_TYPE_TO_API_CONTENT_TYPE as CONTENT_TYPE_TO_API_CONTENT_TYPE2,
|
|
6204
|
-
RegistryAPIClient,
|
|
6205
|
-
RegistryAPIError
|
|
6206
|
-
} from "@decantr/registry";
|
|
6207
6211
|
async function cmdPublish(type, name, projectRoot = process.cwd()) {
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
}
|
|
6214
|
-
const singularType = API_CONTENT_TYPE_TO_CONTENT_TYPE[type] || type;
|
|
6215
|
-
const pluralType = CONTENT_TYPE_TO_API_CONTENT_TYPE2[type] || CONTENT_TYPE_TO_API_CONTENT_TYPE2[singularType] || `${type}s`;
|
|
6216
|
-
const customPath = join24(projectRoot, ".decantr", "custom", pluralType, `${name}.json`);
|
|
6217
|
-
if (!existsSync22(customPath)) {
|
|
6218
|
-
console.error(`Custom ${singularType} "${name}" not found at ${customPath}`);
|
|
6219
|
-
console.error(`Create one first: decantr create ${singularType} ${name}`);
|
|
6220
|
-
process.exitCode = 1;
|
|
6221
|
-
return;
|
|
6222
|
-
}
|
|
6223
|
-
let data;
|
|
6224
|
-
try {
|
|
6225
|
-
data = JSON.parse(readFileSync15(customPath, "utf-8"));
|
|
6226
|
-
} catch {
|
|
6227
|
-
console.error(`Failed to parse ${customPath}`);
|
|
6228
|
-
process.exitCode = 1;
|
|
6229
|
-
return;
|
|
6230
|
-
}
|
|
6231
|
-
const client = new RegistryAPIClient({
|
|
6232
|
-
apiKey: token
|
|
6233
|
-
});
|
|
6234
|
-
try {
|
|
6235
|
-
const result = await client.publishContent({
|
|
6236
|
-
type: pluralType,
|
|
6237
|
-
slug: name,
|
|
6238
|
-
version: data.version || "1.0.0",
|
|
6239
|
-
data,
|
|
6240
|
-
namespace: "@community",
|
|
6241
|
-
visibility: "public"
|
|
6242
|
-
});
|
|
6243
|
-
console.log(`Published ${singularType}/${name} to @community`);
|
|
6244
|
-
console.log(`Status: ${result.status}`);
|
|
6245
|
-
} catch (err) {
|
|
6246
|
-
if (err instanceof RegistryAPIError) {
|
|
6247
|
-
console.error(`Failed to publish: ${err.message}`);
|
|
6248
|
-
const details = err.details;
|
|
6249
|
-
if (Array.isArray(details?.validationErrors) && details.validationErrors.length > 0) {
|
|
6250
|
-
console.error("Validation errors:");
|
|
6251
|
-
for (const validationError of details.validationErrors) {
|
|
6252
|
-
console.error(` - ${String(validationError)}`);
|
|
6253
|
-
}
|
|
6254
|
-
}
|
|
6255
|
-
} else {
|
|
6256
|
-
console.error(`Failed to publish: ${err.message}`);
|
|
6257
|
-
}
|
|
6258
|
-
process.exitCode = 1;
|
|
6259
|
-
}
|
|
6212
|
+
void projectRoot;
|
|
6213
|
+
console.error(
|
|
6214
|
+
`Hosted community publishing has been retired. Keep ${type}/${name} in the official corpus under packages/content and run \`decantr content check\`.`
|
|
6215
|
+
);
|
|
6216
|
+
process.exitCode = 1;
|
|
6260
6217
|
}
|
|
6261
6218
|
|
|
6262
6219
|
// src/commands/refresh.ts
|
|
6263
6220
|
import { createHash } from "crypto";
|
|
6264
|
-
import { existsSync as
|
|
6265
|
-
import { isAbsolute as isAbsolute3, join as
|
|
6221
|
+
import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
|
|
6222
|
+
import { isAbsolute as isAbsolute3, join as join24, relative as relative6 } from "path";
|
|
6266
6223
|
import { isV4 as isV45 } from "@decantr/essence-spec";
|
|
6267
6224
|
import { collectMissingPackManifestFiles as collectMissingPackManifestFiles2 } from "@decantr/verifier";
|
|
6268
6225
|
var GREEN10 = "\x1B[32m";
|
|
@@ -6270,13 +6227,13 @@ var RED7 = "\x1B[31m";
|
|
|
6270
6227
|
var DIM10 = "\x1B[2m";
|
|
6271
6228
|
var RESET10 = "\x1B[0m";
|
|
6272
6229
|
function hashFile(path) {
|
|
6273
|
-
return createHash("sha256").update(
|
|
6230
|
+
return createHash("sha256").update(readFileSync15(path)).digest("hex");
|
|
6274
6231
|
}
|
|
6275
6232
|
function walkFiles(dir) {
|
|
6276
|
-
if (!
|
|
6233
|
+
if (!existsSync22(dir)) return [];
|
|
6277
6234
|
const files = [];
|
|
6278
6235
|
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
6279
|
-
const path =
|
|
6236
|
+
const path = join24(dir, entry.name);
|
|
6280
6237
|
if (entry.isDirectory()) {
|
|
6281
6238
|
files.push(...walkFiles(path));
|
|
6282
6239
|
} else if (entry.isFile()) {
|
|
@@ -6287,15 +6244,15 @@ function walkFiles(dir) {
|
|
|
6287
6244
|
}
|
|
6288
6245
|
function trackedGeneratedFiles(projectRoot) {
|
|
6289
6246
|
const files = [
|
|
6290
|
-
|
|
6291
|
-
...walkFiles(
|
|
6247
|
+
join24(projectRoot, "DECANTR.md"),
|
|
6248
|
+
...walkFiles(join24(projectRoot, ".decantr", "context"))
|
|
6292
6249
|
];
|
|
6293
6250
|
if (!isContractOnlyProject2(projectRoot)) {
|
|
6294
6251
|
files.push(
|
|
6295
|
-
...["global.css", "tokens.css", "treatments.css", "decantr-bridge.css"].map((file) =>
|
|
6252
|
+
...["global.css", "tokens.css", "treatments.css", "decantr-bridge.css"].map((file) => join24(projectRoot, "src", "styles", file)).filter((path) => existsSync22(path))
|
|
6296
6253
|
);
|
|
6297
6254
|
}
|
|
6298
|
-
return files.filter((path) =>
|
|
6255
|
+
return files.filter((path) => existsSync22(path));
|
|
6299
6256
|
}
|
|
6300
6257
|
function snapshotGeneratedFiles(projectRoot) {
|
|
6301
6258
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -6318,33 +6275,33 @@ function fileMtimeMs(path) {
|
|
|
6318
6275
|
}
|
|
6319
6276
|
function newestInputMtime(projectRoot) {
|
|
6320
6277
|
return Math.max(
|
|
6321
|
-
fileMtimeMs(
|
|
6322
|
-
fileMtimeMs(
|
|
6278
|
+
fileMtimeMs(join24(projectRoot, "decantr.essence.json")),
|
|
6279
|
+
fileMtimeMs(join24(projectRoot, ".decantr", "project.json"))
|
|
6323
6280
|
);
|
|
6324
6281
|
}
|
|
6325
6282
|
function isContractOnlyProject2(projectRoot) {
|
|
6326
|
-
const projectJsonPath =
|
|
6327
|
-
if (!
|
|
6283
|
+
const projectJsonPath = join24(projectRoot, ".decantr", "project.json");
|
|
6284
|
+
if (!existsSync22(projectJsonPath)) return false;
|
|
6328
6285
|
try {
|
|
6329
|
-
const projectJson = JSON.parse(
|
|
6286
|
+
const projectJson = JSON.parse(readFileSync15(projectJsonPath, "utf-8"));
|
|
6330
6287
|
return projectJson.initialized?.adoptionMode === "contract-only";
|
|
6331
6288
|
} catch {
|
|
6332
6289
|
return false;
|
|
6333
6290
|
}
|
|
6334
6291
|
}
|
|
6335
6292
|
function checkRefreshFreshness(projectRoot) {
|
|
6336
|
-
const contextDir =
|
|
6293
|
+
const contextDir = join24(projectRoot, ".decantr", "context");
|
|
6337
6294
|
const generated = trackedGeneratedFiles(projectRoot);
|
|
6338
6295
|
const reasons = [];
|
|
6339
6296
|
const packHydrationOptional = isContractOnlyProject2(projectRoot);
|
|
6340
|
-
if (!
|
|
6341
|
-
if (!
|
|
6342
|
-
if (!
|
|
6297
|
+
if (!existsSync22(join24(projectRoot, "DECANTR.md"))) reasons.push("DECANTR.md is missing.");
|
|
6298
|
+
if (!existsSync22(contextDir)) reasons.push(".decantr/context is missing.");
|
|
6299
|
+
if (!existsSync22(join24(contextDir, "scaffold.md"))) {
|
|
6343
6300
|
reasons.push(".decantr/context/scaffold.md is missing.");
|
|
6344
6301
|
}
|
|
6345
|
-
if (!packHydrationOptional && !
|
|
6302
|
+
if (!packHydrationOptional && !existsSync22(join24(contextDir, "pack-manifest.json"))) {
|
|
6346
6303
|
reasons.push(".decantr/context/pack-manifest.json is missing.");
|
|
6347
|
-
} else if (
|
|
6304
|
+
} else if (existsSync22(join24(contextDir, "pack-manifest.json"))) {
|
|
6348
6305
|
const missingPackFiles = collectMissingPackManifestFiles2(projectRoot);
|
|
6349
6306
|
if (missingPackFiles.length > 0) {
|
|
6350
6307
|
reasons.push(
|
|
@@ -6397,7 +6354,7 @@ function summarizeChanges(projectRoot, before, after) {
|
|
|
6397
6354
|
}
|
|
6398
6355
|
function displayGeneratedPath(summary, file, displayRoot) {
|
|
6399
6356
|
if (!displayRoot) return file;
|
|
6400
|
-
const absolutePath =
|
|
6357
|
+
const absolutePath = join24(summary.projectRoot, file);
|
|
6401
6358
|
const relativePath = relative6(displayRoot, absolutePath).replace(/\\/g, "/");
|
|
6402
6359
|
if (relativePath && !relativePath.startsWith("..") && !isAbsolute3(relativePath)) {
|
|
6403
6360
|
return relativePath;
|
|
@@ -6432,15 +6389,15 @@ function printRefreshSummary(summary, displayRoot) {
|
|
|
6432
6389
|
}
|
|
6433
6390
|
}
|
|
6434
6391
|
async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
6435
|
-
const essencePath =
|
|
6436
|
-
if (!
|
|
6392
|
+
const essencePath = join24(projectRoot, "decantr.essence.json");
|
|
6393
|
+
if (!existsSync22(essencePath)) {
|
|
6437
6394
|
console.error(`${RED7}No decantr.essence.json found. Run \`decantr init\` first.${RESET10}`);
|
|
6438
6395
|
process.exitCode = 1;
|
|
6439
6396
|
return;
|
|
6440
6397
|
}
|
|
6441
6398
|
let essence;
|
|
6442
6399
|
try {
|
|
6443
|
-
const raw =
|
|
6400
|
+
const raw = readFileSync15(essencePath, "utf-8");
|
|
6444
6401
|
const parsed = JSON.parse(raw);
|
|
6445
6402
|
if (!isV45(parsed)) {
|
|
6446
6403
|
console.error(
|
|
@@ -6466,7 +6423,7 @@ async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
|
6466
6423
|
return;
|
|
6467
6424
|
}
|
|
6468
6425
|
const registryClient = new RegistryClient({
|
|
6469
|
-
cacheDir:
|
|
6426
|
+
cacheDir: join24(projectRoot, ".decantr", "cache"),
|
|
6470
6427
|
offline: options.offline
|
|
6471
6428
|
});
|
|
6472
6429
|
console.log("Regenerating derived files...\n");
|
|
@@ -6498,8 +6455,8 @@ async function cmdRefresh(projectRoot = process.cwd(), options = {}) {
|
|
|
6498
6455
|
|
|
6499
6456
|
// src/commands/registry-mirror.ts
|
|
6500
6457
|
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync14 } from "fs";
|
|
6501
|
-
import { join as
|
|
6502
|
-
import { API_CONTENT_TYPES, RegistryAPIClient
|
|
6458
|
+
import { join as join25 } from "path";
|
|
6459
|
+
import { API_CONTENT_TYPES, RegistryAPIClient } from "@decantr/registry";
|
|
6503
6460
|
var GREEN11 = "\x1B[32m";
|
|
6504
6461
|
var RED8 = "\x1B[31m";
|
|
6505
6462
|
var DIM11 = "\x1B[2m";
|
|
@@ -6509,7 +6466,7 @@ var RESET11 = "\x1B[0m";
|
|
|
6509
6466
|
var ALL_CONTENT_TYPES = [...API_CONTENT_TYPES];
|
|
6510
6467
|
async function cmdRegistryMirror(projectRoot, options = {}) {
|
|
6511
6468
|
const apiUrl = process.env.DECANTR_API_URL || "https://api.decantr.ai/v1";
|
|
6512
|
-
const apiClient = new
|
|
6469
|
+
const apiClient = new RegistryAPIClient({
|
|
6513
6470
|
baseUrl: apiUrl,
|
|
6514
6471
|
apiKey: process.env.DECANTR_API_KEY || void 0
|
|
6515
6472
|
});
|
|
@@ -6526,29 +6483,29 @@ async function cmdRegistryMirror(projectRoot, options = {}) {
|
|
|
6526
6483
|
process.exitCode = 1;
|
|
6527
6484
|
return;
|
|
6528
6485
|
}
|
|
6529
|
-
const cacheDir =
|
|
6486
|
+
const cacheDir = join25(projectRoot, ".decantr", "cache");
|
|
6530
6487
|
const counts = {};
|
|
6531
6488
|
const failed = [];
|
|
6532
6489
|
console.log(`
|
|
6533
|
-
Mirroring
|
|
6490
|
+
Mirroring official content to ${DIM11}.decantr/cache/${RESET11}
|
|
6534
6491
|
`);
|
|
6535
6492
|
for (const type of types) {
|
|
6536
6493
|
try {
|
|
6537
6494
|
const result = await apiClient.listContent(type, { namespace: "@official" });
|
|
6538
6495
|
const items = result.items;
|
|
6539
|
-
const typeDir =
|
|
6496
|
+
const typeDir = join25(cacheDir, "@official", type);
|
|
6540
6497
|
mkdirSync14(typeDir, { recursive: true });
|
|
6541
|
-
writeFileSync14(
|
|
6498
|
+
writeFileSync14(join25(typeDir, "index.json"), JSON.stringify(result, null, 2));
|
|
6542
6499
|
let itemCount = 0;
|
|
6543
6500
|
for (const item of items) {
|
|
6544
6501
|
const slug = item.slug || item.id;
|
|
6545
6502
|
if (!slug) continue;
|
|
6546
6503
|
try {
|
|
6547
6504
|
const fullItem = await apiClient.getContent(type, "@official", slug);
|
|
6548
|
-
writeFileSync14(
|
|
6505
|
+
writeFileSync14(join25(typeDir, `${slug}.json`), JSON.stringify(fullItem, null, 2));
|
|
6549
6506
|
itemCount++;
|
|
6550
6507
|
} catch {
|
|
6551
|
-
writeFileSync14(
|
|
6508
|
+
writeFileSync14(join25(typeDir, `${slug}.json`), JSON.stringify(item, null, 2));
|
|
6552
6509
|
itemCount++;
|
|
6553
6510
|
}
|
|
6554
6511
|
}
|
|
@@ -6563,8 +6520,8 @@ Mirroring registry content to ${DIM11}.decantr/cache/${RESET11}
|
|
|
6563
6520
|
mirrored_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6564
6521
|
counts
|
|
6565
6522
|
};
|
|
6566
|
-
mkdirSync14(
|
|
6567
|
-
writeFileSync14(
|
|
6523
|
+
mkdirSync14(join25(cacheDir), { recursive: true });
|
|
6524
|
+
writeFileSync14(join25(cacheDir, "mirror-manifest.json"), JSON.stringify(manifest, null, 2));
|
|
6568
6525
|
const totalItems = Object.values(counts).reduce((a, b) => a + b, 0);
|
|
6569
6526
|
console.log("");
|
|
6570
6527
|
if (failed.length > 0) {
|
|
@@ -6581,8 +6538,8 @@ Mirroring registry content to ${DIM11}.decantr/cache/${RESET11}
|
|
|
6581
6538
|
}
|
|
6582
6539
|
|
|
6583
6540
|
// src/commands/remove.ts
|
|
6584
|
-
import { existsSync as
|
|
6585
|
-
import { join as
|
|
6541
|
+
import { existsSync as existsSync23, readFileSync as readFileSync16, rmSync as rmSync2, writeFileSync as writeFileSync15 } from "fs";
|
|
6542
|
+
import { join as join26 } from "path";
|
|
6586
6543
|
import { isV4 as isV46 } from "@decantr/essence-spec";
|
|
6587
6544
|
var GREEN12 = "\x1B[32m";
|
|
6588
6545
|
var RED9 = "\x1B[31m";
|
|
@@ -6590,15 +6547,15 @@ var YELLOW8 = "\x1B[33m";
|
|
|
6590
6547
|
var DIM12 = "\x1B[2m";
|
|
6591
6548
|
var RESET12 = "\x1B[0m";
|
|
6592
6549
|
function readV4Essence2(projectRoot) {
|
|
6593
|
-
const essencePath =
|
|
6594
|
-
if (!
|
|
6550
|
+
const essencePath = join26(projectRoot, "decantr.essence.json");
|
|
6551
|
+
if (!existsSync23(essencePath)) {
|
|
6595
6552
|
console.error(`${RED9}No decantr.essence.json found. Run \`decantr init\` first.${RESET12}`);
|
|
6596
6553
|
process.exitCode = 1;
|
|
6597
6554
|
return null;
|
|
6598
6555
|
}
|
|
6599
6556
|
let parsed;
|
|
6600
6557
|
try {
|
|
6601
|
-
parsed = JSON.parse(
|
|
6558
|
+
parsed = JSON.parse(readFileSync16(essencePath, "utf-8"));
|
|
6602
6559
|
} catch (e) {
|
|
6603
6560
|
console.error(`${RED9}Could not read essence: ${e.message}${RESET12}`);
|
|
6604
6561
|
process.exitCode = 1;
|
|
@@ -6686,14 +6643,14 @@ async function cmdRemoveSection(sectionId, args, projectRoot = process.cwd()) {
|
|
|
6686
6643
|
sections.splice(idx, 1);
|
|
6687
6644
|
recomputeGlobalFeatures(essence);
|
|
6688
6645
|
removeRoutes(essence, sectionId);
|
|
6689
|
-
const contextFile =
|
|
6690
|
-
if (
|
|
6646
|
+
const contextFile = join26(projectRoot, ".decantr", "context", `${sectionId}.md`);
|
|
6647
|
+
if (existsSync23(contextFile)) {
|
|
6691
6648
|
rmSync2(contextFile);
|
|
6692
6649
|
}
|
|
6693
6650
|
writeEssence2(essencePath, essence);
|
|
6694
6651
|
console.log(`${GREEN12}Removed section "${sectionId}".${RESET12}`);
|
|
6695
6652
|
const registryClient = new RegistryClient({
|
|
6696
|
-
cacheDir:
|
|
6653
|
+
cacheDir: join26(projectRoot, ".decantr", "cache")
|
|
6697
6654
|
});
|
|
6698
6655
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
6699
6656
|
console.log(`${GREEN12}Derived files refreshed.${RESET12}`);
|
|
@@ -6736,7 +6693,7 @@ async function cmdRemovePage(path, args, projectRoot = process.cwd()) {
|
|
|
6736
6693
|
}
|
|
6737
6694
|
console.log(`${GREEN12}Removed page "${pageId}" from section "${resolvedSectionId}".${RESET12}`);
|
|
6738
6695
|
const registryClient = new RegistryClient({
|
|
6739
|
-
cacheDir:
|
|
6696
|
+
cacheDir: join26(projectRoot, ".decantr", "cache")
|
|
6740
6697
|
});
|
|
6741
6698
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
6742
6699
|
console.log(`${GREEN12}Derived files refreshed.${RESET12}`);
|
|
@@ -6779,15 +6736,15 @@ async function cmdRemoveFeature(feature, args, projectRoot = process.cwd()) {
|
|
|
6779
6736
|
const target = sectionId ? `section "${sectionId}" and global` : "global";
|
|
6780
6737
|
console.log(`${GREEN12}Removed feature "${feature}" from ${target} features.${RESET12}`);
|
|
6781
6738
|
const registryClient = new RegistryClient({
|
|
6782
|
-
cacheDir:
|
|
6739
|
+
cacheDir: join26(projectRoot, ".decantr", "cache")
|
|
6783
6740
|
});
|
|
6784
6741
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
6785
6742
|
console.log(`${GREEN12}Derived files refreshed.${RESET12}`);
|
|
6786
6743
|
}
|
|
6787
6744
|
|
|
6788
6745
|
// src/commands/resolve.ts
|
|
6789
|
-
import { existsSync as
|
|
6790
|
-
import { dirname as
|
|
6746
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync15, readFileSync as readFileSync17, writeFileSync as writeFileSync16 } from "fs";
|
|
6747
|
+
import { dirname as dirname7, join as join27, resolve as resolve4 } from "path";
|
|
6791
6748
|
var BOLD7 = "\x1B[1m";
|
|
6792
6749
|
var DIM13 = "\x1B[2m";
|
|
6793
6750
|
var GREEN13 = "\x1B[32m";
|
|
@@ -6795,13 +6752,13 @@ var RED10 = "\x1B[31m";
|
|
|
6795
6752
|
var YELLOW9 = "\x1B[33m";
|
|
6796
6753
|
var RESET13 = "\x1B[0m";
|
|
6797
6754
|
function driftLogPath(projectRoot) {
|
|
6798
|
-
return
|
|
6755
|
+
return join27(projectRoot, ".decantr", "drift-log.json");
|
|
6799
6756
|
}
|
|
6800
6757
|
function readDriftLog(projectRoot) {
|
|
6801
6758
|
const path = driftLogPath(projectRoot);
|
|
6802
|
-
if (!
|
|
6759
|
+
if (!existsSync24(path)) return { version: 1, entries: [] };
|
|
6803
6760
|
try {
|
|
6804
|
-
const parsed = JSON.parse(
|
|
6761
|
+
const parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
6805
6762
|
return {
|
|
6806
6763
|
version: 1,
|
|
6807
6764
|
entries: Array.isArray(parsed.entries) ? parsed.entries : []
|
|
@@ -6812,7 +6769,7 @@ function readDriftLog(projectRoot) {
|
|
|
6812
6769
|
}
|
|
6813
6770
|
function writeDriftLog(projectRoot, log) {
|
|
6814
6771
|
const path = driftLogPath(projectRoot);
|
|
6815
|
-
mkdirSync15(
|
|
6772
|
+
mkdirSync15(dirname7(path), { recursive: true });
|
|
6816
6773
|
writeFileSync16(path, `${JSON.stringify(log, null, 2)}
|
|
6817
6774
|
`, "utf-8");
|
|
6818
6775
|
}
|
|
@@ -6932,8 +6889,8 @@ async function cmdResolve(projectRoot = process.cwd(), args = ["resolve"]) {
|
|
|
6932
6889
|
}
|
|
6933
6890
|
|
|
6934
6891
|
// src/commands/sync-drift.ts
|
|
6935
|
-
import { existsSync as
|
|
6936
|
-
import { join as
|
|
6892
|
+
import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
6893
|
+
import { join as join28 } from "path";
|
|
6937
6894
|
var GREEN14 = "\x1B[32m";
|
|
6938
6895
|
var RED11 = "\x1B[31m";
|
|
6939
6896
|
var YELLOW10 = "\x1B[33m";
|
|
@@ -6942,8 +6899,8 @@ var DIM14 = "\x1B[2m";
|
|
|
6942
6899
|
var BOLD8 = "\x1B[1m";
|
|
6943
6900
|
var CYAN7 = "\x1B[36m";
|
|
6944
6901
|
async function cmdSyncDrift(projectRoot = process.cwd()) {
|
|
6945
|
-
const driftLogPath2 =
|
|
6946
|
-
if (!
|
|
6902
|
+
const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
|
|
6903
|
+
if (!existsSync25(driftLogPath2)) {
|
|
6947
6904
|
console.log(`${GREEN14}No drift log found \u2014 no drift recorded.${RESET14}`);
|
|
6948
6905
|
console.log(
|
|
6949
6906
|
`${DIM14}Drift is logged when guard violations are detected during development.${RESET14}`
|
|
@@ -6952,7 +6909,7 @@ async function cmdSyncDrift(projectRoot = process.cwd()) {
|
|
|
6952
6909
|
}
|
|
6953
6910
|
let entries;
|
|
6954
6911
|
try {
|
|
6955
|
-
entries = JSON.parse(
|
|
6912
|
+
entries = JSON.parse(readFileSync18(driftLogPath2, "utf-8"));
|
|
6956
6913
|
} catch {
|
|
6957
6914
|
console.error(`${RED11}Could not parse drift-log.json${RESET14}`);
|
|
6958
6915
|
process.exitCode = 1;
|
|
@@ -6998,8 +6955,8 @@ ${BOLD8}Unresolved Drift Entries (${unresolved.length})${RESET14}
|
|
|
6998
6955
|
console.log("");
|
|
6999
6956
|
}
|
|
7000
6957
|
function resolveDriftEntries(projectRoot, options) {
|
|
7001
|
-
const driftLogPath2 =
|
|
7002
|
-
if (!
|
|
6958
|
+
const driftLogPath2 = join28(projectRoot, ".decantr", "drift-log.json");
|
|
6959
|
+
if (!existsSync25(driftLogPath2)) {
|
|
7003
6960
|
return { success: true };
|
|
7004
6961
|
}
|
|
7005
6962
|
if (options.clear) {
|
|
@@ -7012,7 +6969,7 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
7012
6969
|
}
|
|
7013
6970
|
let entries;
|
|
7014
6971
|
try {
|
|
7015
|
-
entries = JSON.parse(
|
|
6972
|
+
entries = JSON.parse(readFileSync18(driftLogPath2, "utf-8"));
|
|
7016
6973
|
} catch {
|
|
7017
6974
|
return { success: false, error: "Could not parse drift-log.json" };
|
|
7018
6975
|
}
|
|
@@ -7045,7 +7002,6 @@ var CYAN8 = "\x1B[36m";
|
|
|
7045
7002
|
var DIM15 = "\x1B[2m";
|
|
7046
7003
|
var GREEN15 = "\x1B[32m";
|
|
7047
7004
|
var RESET15 = "\x1B[0m";
|
|
7048
|
-
var DEFAULT_API_URL = "https://api.decantr.ai/v1";
|
|
7049
7005
|
async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
7050
7006
|
const subcommand = args[0] ?? "status";
|
|
7051
7007
|
const options = parseTelemetryOptions(args.slice(1));
|
|
@@ -7069,7 +7025,7 @@ async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
|
7069
7025
|
}
|
|
7070
7026
|
function printTelemetryHelp() {
|
|
7071
7027
|
console.log(`
|
|
7072
|
-
${BOLD9}decantr telemetry${RESET15} \u2014 Inspect
|
|
7028
|
+
${BOLD9}decantr telemetry${RESET15} \u2014 Inspect caller-configured private CLI telemetry
|
|
7073
7029
|
|
|
7074
7030
|
${BOLD9}Usage:${RESET15}
|
|
7075
7031
|
decantr telemetry status [--json]
|
|
@@ -7077,11 +7033,13 @@ ${BOLD9}Usage:${RESET15}
|
|
|
7077
7033
|
decantr telemetry link [--enable] [--org <slug>] [--label <label>] [--api-key <key>] [--api-url <url>]
|
|
7078
7034
|
|
|
7079
7035
|
${BOLD9}Examples:${RESET15}
|
|
7080
|
-
decantr init --telemetry
|
|
7036
|
+
DECANTR_TELEMETRY_ENDPOINT=https://telemetry.example/v1/events decantr init --telemetry
|
|
7081
7037
|
decantr telemetry status
|
|
7082
7038
|
decantr telemetry explain
|
|
7083
|
-
decantr
|
|
7084
|
-
|
|
7039
|
+
decantr telemetry link --api-url https://telemetry.example/v1 --api-key <key> --org my-team
|
|
7040
|
+
|
|
7041
|
+
Decantr does not operate a hosted telemetry sink. Delivery and identity linking are
|
|
7042
|
+
available only for caller-configured private infrastructure.
|
|
7085
7043
|
`);
|
|
7086
7044
|
}
|
|
7087
7045
|
function printTelemetryStatus(projectRoot, options) {
|
|
@@ -7093,12 +7051,20 @@ function printTelemetryStatus(projectRoot, options) {
|
|
|
7093
7051
|
console.log(`
|
|
7094
7052
|
${BOLD9}Decantr telemetry${RESET15}`);
|
|
7095
7053
|
console.log(` Enabled: ${status.enabled ? `${GREEN15}yes${RESET15}` : "no"}`);
|
|
7054
|
+
console.log(
|
|
7055
|
+
` Delivery: ${status.endpointConfigured ? `${GREEN15}configured${RESET15}` : `${DIM15}inactive${RESET15}`}`
|
|
7056
|
+
);
|
|
7057
|
+
if (status.endpoint) console.log(` Endpoint: ${status.endpoint}`);
|
|
7096
7058
|
console.log(` Project: ${status.hasProjectConfig ? status.projectRoot : "not initialized"}`);
|
|
7097
7059
|
console.log(` Install ID: ${status.installId ?? `${DIM15}not created yet${RESET15}`}`);
|
|
7098
7060
|
console.log(` Project ID: ${status.projectId ?? `${DIM15}not created yet${RESET15}`}`);
|
|
7099
|
-
if (status.enabled) {
|
|
7061
|
+
if (status.enabled && status.endpointConfigured) {
|
|
7062
|
+
console.log(
|
|
7063
|
+
DIM15 + "Events can be sent only to the caller-configured endpoint shown above." + RESET15
|
|
7064
|
+
);
|
|
7065
|
+
} else if (status.enabled) {
|
|
7100
7066
|
console.log(
|
|
7101
|
-
DIM15 + "
|
|
7067
|
+
DIM15 + "The local preference is enabled, but no events are sent until DECANTR_TELEMETRY_ENDPOINT is configured." + RESET15
|
|
7102
7068
|
);
|
|
7103
7069
|
} else {
|
|
7104
7070
|
console.log(
|
|
@@ -7120,13 +7086,14 @@ function printTelemetryExplain(projectRoot, options) {
|
|
|
7120
7086
|
const report = {
|
|
7121
7087
|
source: "cli",
|
|
7122
7088
|
enabled: status.enabled,
|
|
7089
|
+
delivery: status.endpointConfigured ? "caller-configured" : "inactive",
|
|
7123
7090
|
hasProjectConfig: status.hasProjectConfig,
|
|
7124
7091
|
identifiers: {
|
|
7125
7092
|
installId: status.installId ?? null,
|
|
7126
7093
|
projectId: status.projectId ?? null,
|
|
7127
7094
|
meaning: "Opaque Decantr-generated ids used only when this project has opted into CLI telemetry."
|
|
7128
7095
|
},
|
|
7129
|
-
endpoint:
|
|
7096
|
+
endpoint: status.endpoint ?? null,
|
|
7130
7097
|
events: cliEvents,
|
|
7131
7098
|
aggregateFields: [
|
|
7132
7099
|
"command name",
|
|
@@ -7134,7 +7101,7 @@ function printTelemetryExplain(projectRoot, options) {
|
|
|
7134
7101
|
"duration",
|
|
7135
7102
|
"workflow and adoption mode",
|
|
7136
7103
|
"project scope",
|
|
7137
|
-
"
|
|
7104
|
+
"content source",
|
|
7138
7105
|
"aggregate analyze counts",
|
|
7139
7106
|
"Project Health status, score, and finding counts",
|
|
7140
7107
|
"CI gate outcome",
|
|
@@ -7156,7 +7123,8 @@ function printTelemetryExplain(projectRoot, options) {
|
|
|
7156
7123
|
controls: {
|
|
7157
7124
|
optIn: "Run decantr init --telemetry, decantr new --telemetry, or decantr telemetry link --enable.",
|
|
7158
7125
|
optOut: 'Set "telemetry": false in .decantr/project.json.',
|
|
7159
|
-
|
|
7126
|
+
delivery: "Set DECANTR_TELEMETRY_ENDPOINT to a caller-controlled private event sink. Decantr has no hosted telemetry sink.",
|
|
7127
|
+
link: "Private deployments may run decantr telemetry link with --api-url and --api-key to attach opaque ids."
|
|
7160
7128
|
}
|
|
7161
7129
|
};
|
|
7162
7130
|
if (options.json) {
|
|
@@ -7167,6 +7135,8 @@ function printTelemetryExplain(projectRoot, options) {
|
|
|
7167
7135
|
${BOLD9}Decantr telemetry explanation${RESET15}`);
|
|
7168
7136
|
console.log(` Source: cli`);
|
|
7169
7137
|
console.log(` Enabled: ${status.enabled ? `${GREEN15}yes${RESET15}` : "no"}`);
|
|
7138
|
+
console.log(` Delivery: ${report.delivery}`);
|
|
7139
|
+
if (status.endpoint) console.log(` Endpoint: ${status.endpoint}`);
|
|
7170
7140
|
console.log(` Install ID: ${status.installId ?? `${DIM15}not created yet${RESET15}`}`);
|
|
7171
7141
|
console.log(` Project ID: ${status.projectId ?? `${DIM15}not created yet${RESET15}`}`);
|
|
7172
7142
|
console.log(` Events: ${cliEvents.length} CLI event types in the public catalog`);
|
|
@@ -7182,9 +7152,21 @@ ${BOLD9}Never collected${RESET15}`);
|
|
|
7182
7152
|
}
|
|
7183
7153
|
console.log(`
|
|
7184
7154
|
${DIM15}${report.controls.optOut}${RESET15}`);
|
|
7155
|
+
console.log(`${DIM15}${report.controls.delivery}${RESET15}`);
|
|
7185
7156
|
console.log(`${DIM15}${report.controls.link}${RESET15}`);
|
|
7186
7157
|
}
|
|
7187
7158
|
async function linkTelemetryIdentity(projectRoot, options) {
|
|
7159
|
+
const configuredApiUrl = options.apiUrl ?? process.env.DECANTR_TELEMETRY_IDENTITY_API_URL?.trim();
|
|
7160
|
+
if (!configuredApiUrl) {
|
|
7161
|
+
throw new Error(
|
|
7162
|
+
"Decantr hosted telemetry identity linking is retired. Private deployments must pass --api-url or set DECANTR_TELEMETRY_IDENTITY_API_URL."
|
|
7163
|
+
);
|
|
7164
|
+
}
|
|
7165
|
+
const apiUrl = normalizePrivateApiUrl(configuredApiUrl);
|
|
7166
|
+
const apiKey = options.apiKey ?? getApiKeyOrToken();
|
|
7167
|
+
if (!apiKey) {
|
|
7168
|
+
throw new Error("Pass --api-key <key> for the caller-configured private telemetry API.");
|
|
7169
|
+
}
|
|
7188
7170
|
if (options.enable && !isOptedIn(projectRoot)) {
|
|
7189
7171
|
optIn(projectRoot);
|
|
7190
7172
|
}
|
|
@@ -7197,15 +7179,6 @@ async function linkTelemetryIdentity(projectRoot, options) {
|
|
|
7197
7179
|
if (!identity.installId && !identity.projectId) {
|
|
7198
7180
|
throw new Error("No telemetry identity could be created for this project.");
|
|
7199
7181
|
}
|
|
7200
|
-
const apiKey = options.apiKey ?? getApiKeyOrToken();
|
|
7201
|
-
if (!apiKey) {
|
|
7202
|
-
throw new Error(
|
|
7203
|
-
"Run `decantr login --api-key=<key>` or pass `--api-key <key>` before linking telemetry."
|
|
7204
|
-
);
|
|
7205
|
-
}
|
|
7206
|
-
const apiUrl = trimTrailingSlashes(
|
|
7207
|
-
options.apiUrl ?? process.env.DECANTR_API_URL ?? DEFAULT_API_URL
|
|
7208
|
-
);
|
|
7209
7182
|
const response = await fetch(`${apiUrl}/me/telemetry-link`, {
|
|
7210
7183
|
method: "POST",
|
|
7211
7184
|
headers: {
|
|
@@ -7266,10 +7239,20 @@ function trimTrailingSlashes(value) {
|
|
|
7266
7239
|
while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;
|
|
7267
7240
|
return value.slice(0, end);
|
|
7268
7241
|
}
|
|
7242
|
+
function normalizePrivateApiUrl(value) {
|
|
7243
|
+
const normalized = trimTrailingSlashes(value.trim());
|
|
7244
|
+
try {
|
|
7245
|
+
const url = new URL(normalized);
|
|
7246
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error();
|
|
7247
|
+
} catch {
|
|
7248
|
+
throw new Error("Telemetry identity API URL must be an absolute HTTP(S) URL.");
|
|
7249
|
+
}
|
|
7250
|
+
return normalized;
|
|
7251
|
+
}
|
|
7269
7252
|
|
|
7270
7253
|
// src/commands/theme-switch.ts
|
|
7271
|
-
import { existsSync as
|
|
7272
|
-
import { join as
|
|
7254
|
+
import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync18 } from "fs";
|
|
7255
|
+
import { join as join29 } from "path";
|
|
7273
7256
|
import { isV4 as isV47 } from "@decantr/essence-spec";
|
|
7274
7257
|
var GREEN16 = "\x1B[32m";
|
|
7275
7258
|
var RED12 = "\x1B[31m";
|
|
@@ -7286,15 +7269,15 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7286
7269
|
process.exitCode = 1;
|
|
7287
7270
|
return;
|
|
7288
7271
|
}
|
|
7289
|
-
const essencePath =
|
|
7290
|
-
if (!
|
|
7272
|
+
const essencePath = join29(projectRoot, "decantr.essence.json");
|
|
7273
|
+
if (!existsSync26(essencePath)) {
|
|
7291
7274
|
console.error(`${RED12}No decantr.essence.json found. Run \`decantr init\` first.${RESET16}`);
|
|
7292
7275
|
process.exitCode = 1;
|
|
7293
7276
|
return;
|
|
7294
7277
|
}
|
|
7295
7278
|
let parsed;
|
|
7296
7279
|
try {
|
|
7297
|
-
parsed = JSON.parse(
|
|
7280
|
+
parsed = JSON.parse(readFileSync19(essencePath, "utf-8"));
|
|
7298
7281
|
} catch (e) {
|
|
7299
7282
|
console.error(`${RED12}Could not read essence: ${e.message}${RESET16}`);
|
|
7300
7283
|
process.exitCode = 1;
|
|
@@ -7345,7 +7328,7 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
7345
7328
|
essence.dna.theme.mode = mode;
|
|
7346
7329
|
}
|
|
7347
7330
|
const registryClient = new RegistryClient({
|
|
7348
|
-
cacheDir:
|
|
7331
|
+
cacheDir: join29(projectRoot, ".decantr", "cache")
|
|
7349
7332
|
});
|
|
7350
7333
|
try {
|
|
7351
7334
|
const themeResult = await registryClient.fetchTheme(themeName);
|
|
@@ -7639,7 +7622,7 @@ async function runSimplifiedInit(blueprints) {
|
|
|
7639
7622
|
const question = (q) => new Promise((resolve6) => rl.question(q, resolve6));
|
|
7640
7623
|
console.log("\n? What blueprint would you like to scaffold?\n");
|
|
7641
7624
|
console.log(" 1. Decantr default (recommended)");
|
|
7642
|
-
console.log(" 2. Search
|
|
7625
|
+
console.log(" 2. Search official content...\n");
|
|
7643
7626
|
const choice = await question("Enter choice (1 or 2): ");
|
|
7644
7627
|
if (choice === "1" || choice === "") {
|
|
7645
7628
|
rl.close();
|
|
@@ -7668,8 +7651,8 @@ async function runSimplifiedInit(blueprints) {
|
|
|
7668
7651
|
}
|
|
7669
7652
|
|
|
7670
7653
|
// src/theme-commands.ts
|
|
7671
|
-
import { existsSync as
|
|
7672
|
-
import { join as
|
|
7654
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readdirSync as readdirSync7, readFileSync as readFileSync20, rmSync as rmSync3, writeFileSync as writeFileSync19 } from "fs";
|
|
7655
|
+
import { join as join30 } from "path";
|
|
7673
7656
|
var REQUIRED_FIELDS = [
|
|
7674
7657
|
"$schema",
|
|
7675
7658
|
"id",
|
|
@@ -7729,11 +7712,11 @@ function validateCustomTheme(theme) {
|
|
|
7729
7712
|
};
|
|
7730
7713
|
}
|
|
7731
7714
|
function createTheme(projectRoot, id, name) {
|
|
7732
|
-
const customThemesDir =
|
|
7733
|
-
const themePath =
|
|
7734
|
-
const howToPath =
|
|
7715
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7716
|
+
const themePath = join30(customThemesDir, `${id}.json`);
|
|
7717
|
+
const howToPath = join30(customThemesDir, "how-to-theme.md");
|
|
7735
7718
|
mkdirSync16(customThemesDir, { recursive: true });
|
|
7736
|
-
if (
|
|
7719
|
+
if (existsSync27(themePath)) {
|
|
7737
7720
|
return {
|
|
7738
7721
|
success: false,
|
|
7739
7722
|
error: `Theme "${id}" already exists at ${themePath}`
|
|
@@ -7741,7 +7724,7 @@ function createTheme(projectRoot, id, name) {
|
|
|
7741
7724
|
}
|
|
7742
7725
|
const skeleton = getThemeSkeleton(id, name);
|
|
7743
7726
|
writeFileSync19(themePath, JSON.stringify(skeleton, null, 2));
|
|
7744
|
-
if (!
|
|
7727
|
+
if (!existsSync27(howToPath)) {
|
|
7745
7728
|
writeFileSync19(howToPath, getHowToThemeDoc());
|
|
7746
7729
|
}
|
|
7747
7730
|
return {
|
|
@@ -7750,17 +7733,17 @@ function createTheme(projectRoot, id, name) {
|
|
|
7750
7733
|
};
|
|
7751
7734
|
}
|
|
7752
7735
|
function listCustomThemes(projectRoot) {
|
|
7753
|
-
const customThemesDir =
|
|
7754
|
-
if (!
|
|
7736
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7737
|
+
if (!existsSync27(customThemesDir)) {
|
|
7755
7738
|
return [];
|
|
7756
7739
|
}
|
|
7757
7740
|
const themes = [];
|
|
7758
7741
|
try {
|
|
7759
7742
|
const files = readdirSync7(customThemesDir).filter((f) => f.endsWith(".json"));
|
|
7760
7743
|
for (const file of files) {
|
|
7761
|
-
const filePath =
|
|
7744
|
+
const filePath = join30(customThemesDir, file);
|
|
7762
7745
|
try {
|
|
7763
|
-
const data = JSON.parse(
|
|
7746
|
+
const data = JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
7764
7747
|
themes.push({
|
|
7765
7748
|
id: data.id || file.replace(".json", ""),
|
|
7766
7749
|
name: data.name || data.id,
|
|
@@ -7775,8 +7758,8 @@ function listCustomThemes(projectRoot) {
|
|
|
7775
7758
|
return themes;
|
|
7776
7759
|
}
|
|
7777
7760
|
function deleteTheme(projectRoot, id) {
|
|
7778
|
-
const themePath =
|
|
7779
|
-
if (!
|
|
7761
|
+
const themePath = join30(projectRoot, ".decantr", "custom", "themes", `${id}.json`);
|
|
7762
|
+
if (!existsSync27(themePath)) {
|
|
7780
7763
|
return {
|
|
7781
7764
|
success: false,
|
|
7782
7765
|
error: `Theme "${id}" not found at ${themePath}`
|
|
@@ -7793,7 +7776,7 @@ function deleteTheme(projectRoot, id) {
|
|
|
7793
7776
|
}
|
|
7794
7777
|
}
|
|
7795
7778
|
function importTheme(projectRoot, sourcePath) {
|
|
7796
|
-
if (!
|
|
7779
|
+
if (!existsSync27(sourcePath)) {
|
|
7797
7780
|
return {
|
|
7798
7781
|
success: false,
|
|
7799
7782
|
errors: [`Source file not found: ${sourcePath}`]
|
|
@@ -7801,7 +7784,7 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7801
7784
|
}
|
|
7802
7785
|
let theme;
|
|
7803
7786
|
try {
|
|
7804
|
-
theme = JSON.parse(
|
|
7787
|
+
theme = JSON.parse(readFileSync20(sourcePath, "utf-8"));
|
|
7805
7788
|
} catch (e) {
|
|
7806
7789
|
return {
|
|
7807
7790
|
success: false,
|
|
@@ -7817,11 +7800,11 @@ function importTheme(projectRoot, sourcePath) {
|
|
|
7817
7800
|
}
|
|
7818
7801
|
theme.source = "custom";
|
|
7819
7802
|
const id = theme.id;
|
|
7820
|
-
const customThemesDir =
|
|
7821
|
-
const destPath =
|
|
7803
|
+
const customThemesDir = join30(projectRoot, ".decantr", "custom", "themes");
|
|
7804
|
+
const destPath = join30(customThemesDir, `${id}.json`);
|
|
7822
7805
|
mkdirSync16(customThemesDir, { recursive: true });
|
|
7823
|
-
const howToPath =
|
|
7824
|
-
if (!
|
|
7806
|
+
const howToPath = join30(customThemesDir, "how-to-theme.md");
|
|
7807
|
+
if (!existsSync27(howToPath)) {
|
|
7825
7808
|
writeFileSync19(howToPath, getHowToThemeDoc());
|
|
7826
7809
|
}
|
|
7827
7810
|
writeFileSync19(destPath, JSON.stringify(theme, null, 2));
|
|
@@ -8304,7 +8287,7 @@ function generateBrownfieldPrompt(ctx) {
|
|
|
8304
8287
|
);
|
|
8305
8288
|
}
|
|
8306
8289
|
lines.push(
|
|
8307
|
-
ctx.workflow === "hybrid-compose" ? "-
|
|
8290
|
+
ctx.workflow === "hybrid-compose" ? "- Official corpus content is part of this task. Layer it onto the current app through existing route/component anchors before creating new runtime structure." : "- Official corpus content is optional in this workflow unless the task explicitly asks for blueprint/theme/pattern enrichment."
|
|
8308
8291
|
);
|
|
8309
8292
|
lines.push(
|
|
8310
8293
|
"- Do not invent routes, sections, shells, themes, or features that are not present in the compiled packs."
|
|
@@ -8347,86 +8330,19 @@ function generateCuratedPrompt(ctx) {
|
|
|
8347
8330
|
return ctx.workflow === "brownfield-attach" || ctx.workflow === "hybrid-compose" ? generateBrownfieldPrompt(ctx) : generateGreenfieldPrompt(ctx);
|
|
8348
8331
|
}
|
|
8349
8332
|
function getAPIClient() {
|
|
8350
|
-
return new
|
|
8351
|
-
baseUrl: process.env.DECANTR_API_URL || void 0,
|
|
8333
|
+
return new RegistryAPIClient2({
|
|
8334
|
+
baseUrl: process.env.DECANTR_API_URL || process.env.REGISTRY_URL || void 0,
|
|
8352
8335
|
apiKey: process.env.DECANTR_API_KEY || void 0
|
|
8353
8336
|
});
|
|
8354
8337
|
}
|
|
8355
8338
|
function getPublicAPIClient() {
|
|
8356
|
-
return new
|
|
8357
|
-
baseUrl: process.env.DECANTR_API_URL || void 0
|
|
8339
|
+
return new RegistryAPIClient2({
|
|
8340
|
+
baseUrl: process.env.DECANTR_API_URL || process.env.REGISTRY_URL || void 0
|
|
8358
8341
|
});
|
|
8359
8342
|
}
|
|
8360
8343
|
function resolveUserPath(inputPath, cwd = process.cwd()) {
|
|
8361
8344
|
return isAbsolute4(inputPath) ? inputPath : resolve5(cwd, inputPath);
|
|
8362
8345
|
}
|
|
8363
|
-
function extractHostedAssetPaths(indexHtml) {
|
|
8364
|
-
const assetPaths = /* @__PURE__ */ new Set();
|
|
8365
|
-
for (const match of indexHtml.matchAll(/<(?:script|link)[^>]+(?:src|href)="([^"]+)"/g)) {
|
|
8366
|
-
const assetPath = match[1];
|
|
8367
|
-
const assetsIndex = assetPath.indexOf("/assets/");
|
|
8368
|
-
if (assetsIndex === -1) continue;
|
|
8369
|
-
assetPaths.add(assetPath.slice(assetsIndex));
|
|
8370
|
-
}
|
|
8371
|
-
return [...assetPaths];
|
|
8372
|
-
}
|
|
8373
|
-
function readHostedDistSnapshot(distPath) {
|
|
8374
|
-
const resolvedDistPath = distPath ? resolveUserPath(distPath) : join32(process.cwd(), "dist");
|
|
8375
|
-
const indexPath = join32(resolvedDistPath, "index.html");
|
|
8376
|
-
if (!existsSync29(indexPath)) {
|
|
8377
|
-
return void 0;
|
|
8378
|
-
}
|
|
8379
|
-
const indexHtml = readFileSync22(indexPath, "utf-8");
|
|
8380
|
-
const assetPaths = extractHostedAssetPaths(indexHtml);
|
|
8381
|
-
const assets = {};
|
|
8382
|
-
for (const assetPath of assetPaths) {
|
|
8383
|
-
const assetFilePath = join32(resolvedDistPath, assetPath.replace(/^[/\\]+/, ""));
|
|
8384
|
-
if (existsSync29(assetFilePath)) {
|
|
8385
|
-
assets[assetPath] = readFileSync22(assetFilePath, "utf-8");
|
|
8386
|
-
}
|
|
8387
|
-
}
|
|
8388
|
-
return {
|
|
8389
|
-
indexHtml,
|
|
8390
|
-
assets
|
|
8391
|
-
};
|
|
8392
|
-
}
|
|
8393
|
-
function isHostedSourceSnapshotFile(path) {
|
|
8394
|
-
if (/\.d\.ts$/i.test(path)) return false;
|
|
8395
|
-
return /\.(?:[cm]?[jt]sx?)$/i.test(path);
|
|
8396
|
-
}
|
|
8397
|
-
function readHostedSourceSnapshot(sourcePath) {
|
|
8398
|
-
if (!sourcePath) return void 0;
|
|
8399
|
-
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
8400
|
-
if (!existsSync29(resolvedSourcePath)) {
|
|
8401
|
-
return void 0;
|
|
8402
|
-
}
|
|
8403
|
-
const files = {};
|
|
8404
|
-
const ignoredDirNames = /* @__PURE__ */ new Set([
|
|
8405
|
-
"node_modules",
|
|
8406
|
-
".git",
|
|
8407
|
-
".decantr",
|
|
8408
|
-
"dist",
|
|
8409
|
-
"build",
|
|
8410
|
-
"coverage"
|
|
8411
|
-
]);
|
|
8412
|
-
const rootPrefix = basename2(resolvedSourcePath);
|
|
8413
|
-
const walk = (absoluteDir, relativeDir) => {
|
|
8414
|
-
for (const entry of readdirSync8(absoluteDir, { withFileTypes: true })) {
|
|
8415
|
-
if (ignoredDirNames.has(entry.name)) continue;
|
|
8416
|
-
const absolutePath = join32(absoluteDir, entry.name);
|
|
8417
|
-
const relativePath = join32(relativeDir, entry.name).replace(/\\/g, "/");
|
|
8418
|
-
if (entry.isDirectory()) {
|
|
8419
|
-
walk(absolutePath, relativePath);
|
|
8420
|
-
continue;
|
|
8421
|
-
}
|
|
8422
|
-
if (!entry.isFile()) continue;
|
|
8423
|
-
if (!isHostedSourceSnapshotFile(relativePath)) continue;
|
|
8424
|
-
files[relativePath] = readFileSync22(absolutePath, "utf-8");
|
|
8425
|
-
}
|
|
8426
|
-
};
|
|
8427
|
-
walk(resolvedSourcePath, rootPrefix);
|
|
8428
|
-
return Object.keys(files).length > 0 ? { files } : void 0;
|
|
8429
|
-
}
|
|
8430
8346
|
async function getShowcaseBenchmarkView(view = "shortlist") {
|
|
8431
8347
|
const client = getPublicAPIClient();
|
|
8432
8348
|
if (view === "manifest") {
|
|
@@ -8551,7 +8467,7 @@ async function printRegistryIntelligenceSummary(namespace, jsonOutput = false) {
|
|
|
8551
8467
|
return;
|
|
8552
8468
|
}
|
|
8553
8469
|
const typedSummary = summary;
|
|
8554
|
-
console.log(heading2("
|
|
8470
|
+
console.log(heading2("Content Intelligence Summary"));
|
|
8555
8471
|
console.log(` Namespace: ${typedSummary.namespace ?? "all public content"}`);
|
|
8556
8472
|
console.log(` Generated: ${typedSummary.generated_at}`);
|
|
8557
8473
|
console.log(` Public items: ${typedSummary.totals.total_public_items}`);
|
|
@@ -8614,13 +8530,13 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
8614
8530
|
}
|
|
8615
8531
|
async function compileHostedExecutionPackBundle(essencePath, namespace) {
|
|
8616
8532
|
const client = getPublicAPIClient();
|
|
8617
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8618
|
-
if (!
|
|
8533
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8534
|
+
if (!existsSync28(resolvedPath)) {
|
|
8619
8535
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8620
8536
|
}
|
|
8621
|
-
const essence = JSON.parse(
|
|
8537
|
+
const essence = JSON.parse(readFileSync21(resolvedPath, "utf-8"));
|
|
8622
8538
|
const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
|
|
8623
|
-
const contextDir =
|
|
8539
|
+
const contextDir = join31(dirname8(resolvedPath), ".decantr", "context");
|
|
8624
8540
|
return { resolvedPath, bundle, contextDir };
|
|
8625
8541
|
}
|
|
8626
8542
|
function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
|
|
@@ -8628,10 +8544,10 @@ function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
|
|
|
8628
8544
|
return writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
8629
8545
|
}
|
|
8630
8546
|
function resolvePagePackIdForRoute(essencePath, route) {
|
|
8631
|
-
if (!
|
|
8547
|
+
if (!existsSync28(essencePath)) {
|
|
8632
8548
|
throw new Error(`Essence file not found at ${essencePath}`);
|
|
8633
8549
|
}
|
|
8634
|
-
const essence = JSON.parse(
|
|
8550
|
+
const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
|
|
8635
8551
|
if (!isV48(essence)) {
|
|
8636
8552
|
throw new Error("Route-based pack resolution requires Essence v4.0.0.");
|
|
8637
8553
|
}
|
|
@@ -8646,14 +8562,14 @@ function resolvePagePackIdForRoute(essencePath, route) {
|
|
|
8646
8562
|
}
|
|
8647
8563
|
async function printHostedSelectedExecutionPack(packType, id, essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
8648
8564
|
const client = getPublicAPIClient();
|
|
8649
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8650
|
-
if (!
|
|
8565
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8566
|
+
if (!existsSync28(resolvedPath)) {
|
|
8651
8567
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8652
8568
|
}
|
|
8653
8569
|
if ((packType === "section" || packType === "page" || packType === "mutation") && !id) {
|
|
8654
8570
|
throw new Error(`Pack type "${packType}" requires an id.`);
|
|
8655
8571
|
}
|
|
8656
|
-
const essence = JSON.parse(
|
|
8572
|
+
const essence = JSON.parse(readFileSync21(resolvedPath, "utf-8"));
|
|
8657
8573
|
const selected = await client.selectExecutionPack(
|
|
8658
8574
|
{
|
|
8659
8575
|
essence,
|
|
@@ -8664,17 +8580,17 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8664
8580
|
);
|
|
8665
8581
|
let writtenContextDir = null;
|
|
8666
8582
|
if (writeContext) {
|
|
8667
|
-
const contextDir =
|
|
8583
|
+
const contextDir = join31(dirname8(resolvedPath), ".decantr", "context");
|
|
8668
8584
|
mkdirSync17(contextDir, { recursive: true });
|
|
8669
8585
|
writeFileSync20(
|
|
8670
|
-
|
|
8586
|
+
join31(contextDir, "pack-manifest.json"),
|
|
8671
8587
|
JSON.stringify(selected.manifest, null, 2) + "\n"
|
|
8672
8588
|
);
|
|
8673
8589
|
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);
|
|
8674
8590
|
const markdownFile = manifestEntry?.markdown ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.md`;
|
|
8675
8591
|
const jsonFile = manifestEntry?.json ?? `${selected.selector.packType}${selected.selector.id ? `-${selected.selector.id}` : ""}-pack.json`;
|
|
8676
|
-
writeFileSync20(
|
|
8677
|
-
writeFileSync20(
|
|
8592
|
+
writeFileSync20(join31(contextDir, markdownFile), selected.pack.renderedMarkdown);
|
|
8593
|
+
writeFileSync20(join31(contextDir, jsonFile), JSON.stringify(selected.pack, null, 2) + "\n");
|
|
8678
8594
|
writtenContextDir = contextDir;
|
|
8679
8595
|
}
|
|
8680
8596
|
if (jsonOutput) {
|
|
@@ -8699,20 +8615,20 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
|
|
|
8699
8615
|
}
|
|
8700
8616
|
async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutput = false, writeContext = false) {
|
|
8701
8617
|
const client = getPublicAPIClient();
|
|
8702
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) :
|
|
8703
|
-
if (!
|
|
8618
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
8619
|
+
if (!existsSync28(resolvedPath)) {
|
|
8704
8620
|
throw new Error(`Essence file not found at ${resolvedPath}`);
|
|
8705
8621
|
}
|
|
8706
|
-
const essence = JSON.parse(
|
|
8622
|
+
const essence = JSON.parse(readFileSync21(resolvedPath, "utf-8"));
|
|
8707
8623
|
const manifest = await client.getExecutionPackManifest(
|
|
8708
8624
|
essence,
|
|
8709
8625
|
namespace ? { namespace } : void 0
|
|
8710
8626
|
);
|
|
8711
8627
|
let writtenContextDir = null;
|
|
8712
8628
|
if (writeContext) {
|
|
8713
|
-
const contextDir =
|
|
8629
|
+
const contextDir = join31(dirname8(resolvedPath), ".decantr", "context");
|
|
8714
8630
|
mkdirSync17(contextDir, { recursive: true });
|
|
8715
|
-
writeFileSync20(
|
|
8631
|
+
writeFileSync20(join31(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
8716
8632
|
writtenContextDir = contextDir;
|
|
8717
8633
|
}
|
|
8718
8634
|
if (jsonOutput) {
|
|
@@ -8733,14 +8649,14 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
|
|
|
8733
8649
|
}
|
|
8734
8650
|
}
|
|
8735
8651
|
async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@official") {
|
|
8736
|
-
const contextDir =
|
|
8737
|
-
const reviewPackPath =
|
|
8738
|
-
const manifestPath =
|
|
8739
|
-
if (
|
|
8652
|
+
const contextDir = join31(projectRoot, ".decantr", "context");
|
|
8653
|
+
const reviewPackPath = join31(contextDir, "review-pack.json");
|
|
8654
|
+
const manifestPath = join31(contextDir, "pack-manifest.json");
|
|
8655
|
+
if (existsSync28(reviewPackPath) && existsSync28(manifestPath)) {
|
|
8740
8656
|
return { attempted: false, hydrated: false };
|
|
8741
8657
|
}
|
|
8742
|
-
const essencePath =
|
|
8743
|
-
if (!
|
|
8658
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
8659
|
+
if (!existsSync28(essencePath)) {
|
|
8744
8660
|
return { attempted: false, hydrated: false };
|
|
8745
8661
|
}
|
|
8746
8662
|
const reviewHydration = await hydrateHostedReviewPackIfMissing(projectRoot, namespace);
|
|
@@ -8749,7 +8665,7 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
8749
8665
|
}
|
|
8750
8666
|
try {
|
|
8751
8667
|
const client = getPublicAPIClient();
|
|
8752
|
-
const essence = JSON.parse(
|
|
8668
|
+
const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
|
|
8753
8669
|
const bundle = await client.compileExecutionPacks(essence, { namespace });
|
|
8754
8670
|
mkdirSync17(contextDir, { recursive: true });
|
|
8755
8671
|
writeExecutionPackBundleArtifacts(contextDir, bundle);
|
|
@@ -8759,19 +8675,19 @@ async function hydrateHostedExecutionPacksIfMissing(projectRoot, namespace = "@o
|
|
|
8759
8675
|
}
|
|
8760
8676
|
}
|
|
8761
8677
|
async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@official") {
|
|
8762
|
-
const contextDir =
|
|
8763
|
-
const reviewPackPath =
|
|
8764
|
-
const manifestPath =
|
|
8765
|
-
if (
|
|
8678
|
+
const contextDir = join31(projectRoot, ".decantr", "context");
|
|
8679
|
+
const reviewPackPath = join31(contextDir, "review-pack.json");
|
|
8680
|
+
const manifestPath = join31(contextDir, "pack-manifest.json");
|
|
8681
|
+
if (existsSync28(reviewPackPath) && existsSync28(manifestPath)) {
|
|
8766
8682
|
return { attempted: false, hydrated: false };
|
|
8767
8683
|
}
|
|
8768
|
-
const essencePath =
|
|
8769
|
-
if (!
|
|
8684
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
8685
|
+
if (!existsSync28(essencePath)) {
|
|
8770
8686
|
return { attempted: false, hydrated: false };
|
|
8771
8687
|
}
|
|
8772
8688
|
try {
|
|
8773
8689
|
const client = getPublicAPIClient();
|
|
8774
|
-
const essence = JSON.parse(
|
|
8690
|
+
const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
|
|
8775
8691
|
const selected = await client.selectExecutionPack(
|
|
8776
8692
|
{
|
|
8777
8693
|
essence,
|
|
@@ -8780,12 +8696,12 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
8780
8696
|
{ namespace }
|
|
8781
8697
|
);
|
|
8782
8698
|
mkdirSync17(contextDir, { recursive: true });
|
|
8783
|
-
writeFileSync20(
|
|
8699
|
+
writeFileSync20(join31(contextDir, "review-pack.md"), selected.pack.renderedMarkdown);
|
|
8784
8700
|
writeFileSync20(
|
|
8785
|
-
|
|
8701
|
+
join31(contextDir, "review-pack.json"),
|
|
8786
8702
|
JSON.stringify(selected.pack, null, 2) + "\n"
|
|
8787
8703
|
);
|
|
8788
|
-
if (!
|
|
8704
|
+
if (!existsSync28(manifestPath)) {
|
|
8789
8705
|
writeFileSync20(manifestPath, JSON.stringify(selected.manifest, null, 2) + "\n");
|
|
8790
8706
|
}
|
|
8791
8707
|
return { attempted: true, hydrated: true, scope: "review" };
|
|
@@ -8793,72 +8709,6 @@ async function hydrateHostedReviewPackIfMissing(projectRoot, namespace = "@offic
|
|
|
8793
8709
|
return { attempted: true, hydrated: false };
|
|
8794
8710
|
}
|
|
8795
8711
|
}
|
|
8796
|
-
async function printHostedFileCritique(sourcePath, namespace, jsonOutput = false, essencePath, treatmentsPath) {
|
|
8797
|
-
const client = getPublicAPIClient();
|
|
8798
|
-
const resolvedSourcePath = resolveUserPath(sourcePath);
|
|
8799
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join32(process.cwd(), "decantr.essence.json");
|
|
8800
|
-
const resolvedTreatmentsPath = treatmentsPath ? resolveUserPath(treatmentsPath) : join32(process.cwd(), "src", "styles", "treatments.css");
|
|
8801
|
-
if (!existsSync29(resolvedSourcePath)) {
|
|
8802
|
-
throw new Error(`Source file not found at ${resolvedSourcePath}`);
|
|
8803
|
-
}
|
|
8804
|
-
if (!existsSync29(resolvedEssencePath)) {
|
|
8805
|
-
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
8806
|
-
}
|
|
8807
|
-
const code = readFileSync22(resolvedSourcePath, "utf-8");
|
|
8808
|
-
const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
|
|
8809
|
-
const treatmentsCss = existsSync29(resolvedTreatmentsPath) ? readFileSync22(resolvedTreatmentsPath, "utf-8") : void 0;
|
|
8810
|
-
const report = await client.critiqueFile(
|
|
8811
|
-
{
|
|
8812
|
-
essence,
|
|
8813
|
-
filePath: sourcePath,
|
|
8814
|
-
code,
|
|
8815
|
-
treatmentsCss
|
|
8816
|
-
},
|
|
8817
|
-
namespace ? { namespace } : void 0
|
|
8818
|
-
);
|
|
8819
|
-
if (jsonOutput) {
|
|
8820
|
-
console.log(JSON.stringify(report, null, 2));
|
|
8821
|
-
return;
|
|
8822
|
-
}
|
|
8823
|
-
console.log(heading2("Hosted File Critique"));
|
|
8824
|
-
console.log(` Source file: ${resolvedSourcePath}`);
|
|
8825
|
-
console.log(` Essence: ${resolvedEssencePath}`);
|
|
8826
|
-
if (treatmentsCss) {
|
|
8827
|
-
console.log(` Treatments: ${resolvedTreatmentsPath}`);
|
|
8828
|
-
}
|
|
8829
|
-
printFileCritiqueReport(report);
|
|
8830
|
-
}
|
|
8831
|
-
async function printHostedProjectAudit(namespace, jsonOutput = false, essencePath, distPath, sourcesPath) {
|
|
8832
|
-
const client = getPublicAPIClient();
|
|
8833
|
-
const resolvedEssencePath = essencePath ? resolveUserPath(essencePath) : join32(process.cwd(), "decantr.essence.json");
|
|
8834
|
-
if (!existsSync29(resolvedEssencePath)) {
|
|
8835
|
-
throw new Error(`Essence file not found at ${resolvedEssencePath}`);
|
|
8836
|
-
}
|
|
8837
|
-
const essence = JSON.parse(readFileSync22(resolvedEssencePath, "utf-8"));
|
|
8838
|
-
const dist = readHostedDistSnapshot(distPath);
|
|
8839
|
-
const sources = readHostedSourceSnapshot(sourcesPath);
|
|
8840
|
-
const report = await client.auditProject(
|
|
8841
|
-
{
|
|
8842
|
-
essence,
|
|
8843
|
-
dist,
|
|
8844
|
-
sources
|
|
8845
|
-
},
|
|
8846
|
-
namespace ? { namespace } : void 0
|
|
8847
|
-
);
|
|
8848
|
-
if (jsonOutput) {
|
|
8849
|
-
console.log(JSON.stringify(report, null, 2));
|
|
8850
|
-
return;
|
|
8851
|
-
}
|
|
8852
|
-
console.log(heading2("Hosted Project Audit"));
|
|
8853
|
-
console.log(` Essence: ${resolvedEssencePath}`);
|
|
8854
|
-
console.log(
|
|
8855
|
-
` Dist snapshot: ${dist ? distPath ? resolveUserPath(distPath) : join32(process.cwd(), "dist") : "none"}`
|
|
8856
|
-
);
|
|
8857
|
-
console.log(
|
|
8858
|
-
` Source snapshot: ${sources && sourcesPath ? resolveUserPath(sourcesPath) : "none"}`
|
|
8859
|
-
);
|
|
8860
|
-
printProjectAuditReport(report);
|
|
8861
|
-
}
|
|
8862
8712
|
function formatBlueprintPortfolioSummary(value) {
|
|
8863
8713
|
const portfolio = getBlueprintPortfolioMetadata(value);
|
|
8864
8714
|
if (!portfolio) return null;
|
|
@@ -8974,21 +8824,21 @@ function findPatternCandidateBySlug(candidates, slug) {
|
|
|
8974
8824
|
function readSuggestCodeContext(projectRoot, route, file) {
|
|
8975
8825
|
const pieces = [];
|
|
8976
8826
|
if (file) {
|
|
8977
|
-
const resolved = isAbsolute4(file) ? file :
|
|
8978
|
-
if (
|
|
8979
|
-
pieces.push(
|
|
8827
|
+
const resolved = isAbsolute4(file) ? file : join31(projectRoot, file);
|
|
8828
|
+
if (existsSync28(resolved)) {
|
|
8829
|
+
pieces.push(readFileSync21(resolved, "utf-8"));
|
|
8980
8830
|
}
|
|
8981
8831
|
}
|
|
8982
8832
|
if (route) {
|
|
8983
|
-
const analysisPath =
|
|
8984
|
-
if (
|
|
8833
|
+
const analysisPath = join31(projectRoot, ".decantr", "analysis.json");
|
|
8834
|
+
if (existsSync28(analysisPath)) {
|
|
8985
8835
|
try {
|
|
8986
|
-
const analysis = JSON.parse(
|
|
8836
|
+
const analysis = JSON.parse(readFileSync21(analysisPath, "utf-8"));
|
|
8987
8837
|
const routeEntry = analysis.routes?.routes?.find((entry) => entry.path === route);
|
|
8988
8838
|
if (routeEntry?.file) {
|
|
8989
|
-
const resolved =
|
|
8990
|
-
if (
|
|
8991
|
-
pieces.push(
|
|
8839
|
+
const resolved = join31(projectRoot, routeEntry.file);
|
|
8840
|
+
if (existsSync28(resolved)) {
|
|
8841
|
+
pieces.push(readFileSync21(resolved, "utf-8"));
|
|
8992
8842
|
}
|
|
8993
8843
|
}
|
|
8994
8844
|
} catch {
|
|
@@ -9074,7 +8924,7 @@ async function cmdSuggest(query, options = {}) {
|
|
|
9074
8924
|
}
|
|
9075
8925
|
}
|
|
9076
8926
|
const registryClient = new RegistryClient({
|
|
9077
|
-
cacheDir:
|
|
8927
|
+
cacheDir: join31(projectRoot, ".decantr", "cache")
|
|
9078
8928
|
});
|
|
9079
8929
|
const code = options.fromCode || options.file ? readSuggestCodeContext(projectRoot, options.route, options.file) : "";
|
|
9080
8930
|
const localMatches = localPatternMatches(projectRoot, [query, code].filter(Boolean).join("\n"));
|
|
@@ -9124,13 +8974,13 @@ async function cmdSuggest(query, options = {}) {
|
|
|
9124
8974
|
console.log(` ${cyan4(match.id)}${details ? ` ${dim4(details)}` : ""}`);
|
|
9125
8975
|
}
|
|
9126
8976
|
console.log("");
|
|
9127
|
-
console.log(`${BOLD11}
|
|
8977
|
+
console.log(`${BOLD11}Official content patterns:${RESET18}`);
|
|
9128
8978
|
}
|
|
9129
8979
|
if (matches.length === 0) {
|
|
9130
|
-
console.log(dim4("No
|
|
8980
|
+
console.log(dim4("No official or bundled content patterns matched this query."));
|
|
9131
8981
|
console.log("");
|
|
9132
8982
|
console.log(
|
|
9133
|
-
dim4('Use local law first, or run "decantr list patterns" to browse
|
|
8983
|
+
dim4('Use local law first, or run "decantr list patterns" to browse official content.')
|
|
9134
8984
|
);
|
|
9135
8985
|
return;
|
|
9136
8986
|
}
|
|
@@ -9161,9 +9011,9 @@ async function cmdGet(type, id) {
|
|
|
9161
9011
|
process.exitCode = 1;
|
|
9162
9012
|
return;
|
|
9163
9013
|
}
|
|
9164
|
-
const apiType =
|
|
9014
|
+
const apiType = CONTENT_TYPE_TO_API_CONTENT_TYPE2[type];
|
|
9165
9015
|
const registryClient = new RegistryClient({
|
|
9166
|
-
cacheDir:
|
|
9016
|
+
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
9167
9017
|
});
|
|
9168
9018
|
const result = await registryClient.fetchContentItem(apiType, id);
|
|
9169
9019
|
if (result) {
|
|
@@ -9180,10 +9030,10 @@ async function cmdGet(type, id) {
|
|
|
9180
9030
|
return;
|
|
9181
9031
|
}
|
|
9182
9032
|
async function cmdValidate(path) {
|
|
9183
|
-
const essencePath = path ||
|
|
9033
|
+
const essencePath = path || join31(process.cwd(), "decantr.essence.json");
|
|
9184
9034
|
let raw;
|
|
9185
9035
|
try {
|
|
9186
|
-
raw =
|
|
9036
|
+
raw = readFileSync21(essencePath, "utf-8");
|
|
9187
9037
|
} catch {
|
|
9188
9038
|
console.error(error2(`Could not read ${essencePath}`));
|
|
9189
9039
|
process.exitCode = 1;
|
|
@@ -9250,7 +9100,7 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
|
|
|
9250
9100
|
return;
|
|
9251
9101
|
}
|
|
9252
9102
|
const registryClient = new RegistryClient({
|
|
9253
|
-
cacheDir:
|
|
9103
|
+
cacheDir: join31(process.cwd(), ".decantr", "cache")
|
|
9254
9104
|
});
|
|
9255
9105
|
const result = await registryClient.fetchContentList(
|
|
9256
9106
|
type,
|
|
@@ -9275,7 +9125,7 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
|
|
|
9275
9125
|
const customItems = registryClient.listCustomContent("themes");
|
|
9276
9126
|
const customIds = new Set(customItems.map((c) => c.id));
|
|
9277
9127
|
const registryItems = items.filter((i) => !customIds.has(i.id));
|
|
9278
|
-
console.log(heading2(`
|
|
9128
|
+
console.log(heading2(`Official themes (${registryItems.length}):`));
|
|
9279
9129
|
for (const item of registryItems) {
|
|
9280
9130
|
console.log(` ${cyan4(item.id)} ${dim4(item.description || item.name || "")}`);
|
|
9281
9131
|
}
|
|
@@ -9325,18 +9175,18 @@ async function cmdList(type, sort, recommended, intelligenceSource, blueprintSet
|
|
|
9325
9175
|
}
|
|
9326
9176
|
function enableCliTelemetry(projectRoot) {
|
|
9327
9177
|
optIn(projectRoot);
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9178
|
+
const status = getCliTelemetryIdentityStatus(projectRoot);
|
|
9179
|
+
const message = status.endpointConfigured ? "Privacy-filtered CLI telemetry can be sent to the configured private endpoint." : "The local preference is enabled, but no events are sent until DECANTR_TELEMETRY_ENDPOINT is configured.";
|
|
9180
|
+
console.log(`
|
|
9181
|
+
${CYAN10}Telemetry preference enabled.${RESET18} ${message}`);
|
|
9332
9182
|
console.log(`${DIM18}Set "telemetry": false in .decantr/project.json to opt out.${RESET18}`);
|
|
9333
9183
|
}
|
|
9334
9184
|
function readCliPackageVersion2() {
|
|
9335
|
-
const here =
|
|
9336
|
-
const candidates = [
|
|
9185
|
+
const here = dirname8(fileURLToPath4(import.meta.url));
|
|
9186
|
+
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
9337
9187
|
for (const candidate of candidates) {
|
|
9338
9188
|
try {
|
|
9339
|
-
const pkg = JSON.parse(
|
|
9189
|
+
const pkg = JSON.parse(readFileSync21(candidate, "utf-8"));
|
|
9340
9190
|
if (pkg.version) return pkg.version;
|
|
9341
9191
|
} catch {
|
|
9342
9192
|
}
|
|
@@ -9347,19 +9197,19 @@ function timestampForFile() {
|
|
|
9347
9197
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9348
9198
|
}
|
|
9349
9199
|
function backupExistingEssence(projectRoot, label) {
|
|
9350
|
-
const essencePath =
|
|
9351
|
-
if (!
|
|
9352
|
-
const backupPath =
|
|
9200
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
9201
|
+
if (!existsSync28(essencePath)) return null;
|
|
9202
|
+
const backupPath = join31(
|
|
9353
9203
|
projectRoot,
|
|
9354
9204
|
`decantr.essence.${label}.${timestampForFile()}.backup.json`
|
|
9355
9205
|
);
|
|
9356
|
-
writeFileSync20(backupPath,
|
|
9206
|
+
writeFileSync20(backupPath, readFileSync21(essencePath, "utf-8"), "utf-8");
|
|
9357
9207
|
return backupPath;
|
|
9358
9208
|
}
|
|
9359
9209
|
function writeBrownfieldProjectJson(input) {
|
|
9360
|
-
const decantrDir =
|
|
9361
|
-
mkdirSync17(
|
|
9362
|
-
mkdirSync17(
|
|
9210
|
+
const decantrDir = join31(input.projectRoot, ".decantr");
|
|
9211
|
+
mkdirSync17(join31(decantrDir, "context"), { recursive: true });
|
|
9212
|
+
mkdirSync17(join31(decantrDir, "cache"), { recursive: true });
|
|
9363
9213
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9364
9214
|
const projectJson = {
|
|
9365
9215
|
detected: {
|
|
@@ -9400,7 +9250,7 @@ function writeBrownfieldProjectJson(input) {
|
|
|
9400
9250
|
}
|
|
9401
9251
|
}
|
|
9402
9252
|
};
|
|
9403
|
-
writeFileSync20(
|
|
9253
|
+
writeFileSync20(join31(decantrDir, "project.json"), JSON.stringify(projectJson, null, 2) + "\n");
|
|
9404
9254
|
}
|
|
9405
9255
|
async function applyAcceptedBrownfieldProposal(input) {
|
|
9406
9256
|
const proposal = readBrownfieldProposal(input.projectRoot);
|
|
@@ -9416,8 +9266,8 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9416
9266
|
process.exitCode = 1;
|
|
9417
9267
|
return;
|
|
9418
9268
|
}
|
|
9419
|
-
const essencePath =
|
|
9420
|
-
const hasEssence =
|
|
9269
|
+
const essencePath = join31(input.projectRoot, "decantr.essence.json");
|
|
9270
|
+
const hasEssence = existsSync28(essencePath);
|
|
9421
9271
|
let essence;
|
|
9422
9272
|
let backupPath = null;
|
|
9423
9273
|
if (input.mode === "accept" && hasEssence) {
|
|
@@ -9431,7 +9281,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9431
9281
|
return;
|
|
9432
9282
|
}
|
|
9433
9283
|
if (input.mode === "merge" && hasEssence) {
|
|
9434
|
-
const existing = JSON.parse(
|
|
9284
|
+
const existing = JSON.parse(readFileSync21(essencePath, "utf-8"));
|
|
9435
9285
|
if (!isV48(existing)) {
|
|
9436
9286
|
console.log(
|
|
9437
9287
|
error2(
|
|
@@ -9470,7 +9320,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
9470
9320
|
});
|
|
9471
9321
|
writeFileSync20(essencePath, JSON.stringify(essence, null, 2) + "\n", "utf-8");
|
|
9472
9322
|
const registryClient = new RegistryClient({
|
|
9473
|
-
cacheDir:
|
|
9323
|
+
cacheDir: join31(input.projectRoot, ".decantr", "cache"),
|
|
9474
9324
|
offline: true,
|
|
9475
9325
|
projectRoot: input.projectRoot
|
|
9476
9326
|
});
|
|
@@ -9634,7 +9484,7 @@ async function cmdInit(args) {
|
|
|
9634
9484
|
if (args.offline && shouldUseRegistry) {
|
|
9635
9485
|
offlineSeed = seedOfflineRegistry(projectRoot, projectRoot);
|
|
9636
9486
|
if (offlineSeed.seeded) {
|
|
9637
|
-
console.log(dim4(` Seeded offline
|
|
9487
|
+
console.log(dim4(` Seeded offline official content from ${offlineSeed.strategy}.`));
|
|
9638
9488
|
} else if (requestedBlueprint || requestedArchetype) {
|
|
9639
9489
|
console.log(
|
|
9640
9490
|
error2("\nOffline blueprint/archetype scaffolding requires a local Decantr content source.")
|
|
@@ -9649,7 +9499,7 @@ async function cmdInit(args) {
|
|
|
9649
9499
|
}
|
|
9650
9500
|
}
|
|
9651
9501
|
const registryClient = new RegistryClient({
|
|
9652
|
-
cacheDir:
|
|
9502
|
+
cacheDir: join31(projectRoot, ".decantr", "cache"),
|
|
9653
9503
|
apiUrl: args.registry,
|
|
9654
9504
|
offline: args.offline,
|
|
9655
9505
|
projectRoot
|
|
@@ -9671,7 +9521,9 @@ async function cmdInit(args) {
|
|
|
9671
9521
|
console.log(`
|
|
9672
9522
|
${YELLOW13}You're offline. Scaffolding minimal Decantr project.${RESET18}`);
|
|
9673
9523
|
console.log(
|
|
9674
|
-
dim4(
|
|
9524
|
+
dim4(
|
|
9525
|
+
"Run `decantr sync` or `decantr upgrade` when online to pull the latest official content.\n"
|
|
9526
|
+
)
|
|
9675
9527
|
);
|
|
9676
9528
|
const result2 = scaffoldMinimal(projectRoot, {
|
|
9677
9529
|
workflowMode: policy.workflowMode,
|
|
@@ -9706,12 +9558,12 @@ ${YELLOW13}You're offline. Scaffolding minimal Decantr project.${RESET18}`);
|
|
|
9706
9558
|
if (requestedBlueprint || requestedArchetype) {
|
|
9707
9559
|
console.log(
|
|
9708
9560
|
error2(
|
|
9709
|
-
"\nThe requested blueprint/archetype could not be resolved from the
|
|
9561
|
+
"\nThe requested blueprint/archetype could not be resolved from the official content API or local cache."
|
|
9710
9562
|
)
|
|
9711
9563
|
);
|
|
9712
9564
|
console.log(
|
|
9713
9565
|
dim4(
|
|
9714
|
-
"Run `decantr sync`, set DECANTR_CONTENT_DIR, or retry when the
|
|
9566
|
+
"Run `decantr sync`, set DECANTR_CONTENT_DIR, or retry when the content API is reachable."
|
|
9715
9567
|
)
|
|
9716
9568
|
);
|
|
9717
9569
|
process.exitCode = 1;
|
|
@@ -9719,10 +9571,12 @@ ${YELLOW13}You're offline. Scaffolding minimal Decantr project.${RESET18}`);
|
|
|
9719
9571
|
}
|
|
9720
9572
|
console.log(`
|
|
9721
9573
|
${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
9722
|
-
console.log(
|
|
9574
|
+
console.log(
|
|
9575
|
+
dim4("Run `decantr upgrade` when online, or see decantr.ai/reference/content-health.md\n")
|
|
9576
|
+
);
|
|
9723
9577
|
selectedBlueprint = "default";
|
|
9724
9578
|
} else if (shouldUseRegistry) {
|
|
9725
|
-
console.log(dim4("Fetching
|
|
9579
|
+
console.log(dim4("Fetching official content..."));
|
|
9726
9580
|
const blueprintsResult2 = await registryClient.fetchBlueprints();
|
|
9727
9581
|
registrySource = blueprintsResult2.source.type === "api" ? "api" : "cache";
|
|
9728
9582
|
const { selectedBlueprint: selected } = await runSimplifiedInit(blueprintsResult2.data.items);
|
|
@@ -9895,7 +9749,7 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
9895
9749
|
} else {
|
|
9896
9750
|
if (requestedBlueprint) {
|
|
9897
9751
|
console.log(error2(` Error: Could not fetch blueprint "${options.blueprint}".`));
|
|
9898
|
-
console.log(dim4("Resolve local
|
|
9752
|
+
console.log(dim4("Resolve local corpus content or retry against the content API."));
|
|
9899
9753
|
process.exitCode = 1;
|
|
9900
9754
|
return;
|
|
9901
9755
|
}
|
|
@@ -9910,7 +9764,7 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
9910
9764
|
} else {
|
|
9911
9765
|
if (requestedArchetype) {
|
|
9912
9766
|
console.log(error2(` Error: Could not fetch archetype "${options.archetype}".`));
|
|
9913
|
-
console.log(dim4("Resolve local
|
|
9767
|
+
console.log(dim4("Resolve local corpus content or retry against the content API."));
|
|
9914
9768
|
process.exitCode = 1;
|
|
9915
9769
|
return;
|
|
9916
9770
|
}
|
|
@@ -9927,7 +9781,7 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
9927
9781
|
} else {
|
|
9928
9782
|
if (requestedTheme) {
|
|
9929
9783
|
console.log(error2(` Error: Could not fetch theme "${options.theme}".`));
|
|
9930
|
-
console.log(dim4("Resolve local
|
|
9784
|
+
console.log(dim4("Resolve local corpus content or retry against the content API."));
|
|
9931
9785
|
process.exitCode = 1;
|
|
9932
9786
|
return;
|
|
9933
9787
|
}
|
|
@@ -9981,7 +9835,7 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
9981
9835
|
if (appliedRuleFiles.length > 0) {
|
|
9982
9836
|
console.log(` ${dim4(`Rule bridge applied: ${appliedRuleFiles.join(", ")}`)}`);
|
|
9983
9837
|
}
|
|
9984
|
-
if (!
|
|
9838
|
+
if (!existsSync28(join31(projectRoot, "package.json"))) {
|
|
9985
9839
|
console.log("");
|
|
9986
9840
|
console.log(
|
|
9987
9841
|
dim4(` Note: ${cyan4("decantr init")} created Decantr contract/context files only.`)
|
|
@@ -9992,7 +9846,7 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
9992
9846
|
)
|
|
9993
9847
|
);
|
|
9994
9848
|
}
|
|
9995
|
-
const hasCompiledPacks =
|
|
9849
|
+
const hasCompiledPacks = existsSync28(join31(projectRoot, ".decantr", "context", "scaffold-pack.md"));
|
|
9996
9850
|
console.log("");
|
|
9997
9851
|
console.log(" Next steps:");
|
|
9998
9852
|
if (hasCompiledPacks) {
|
|
@@ -10008,7 +9862,7 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
10008
9862
|
);
|
|
10009
9863
|
console.log(" 5. Build the shell and route structure first, then implement the pages");
|
|
10010
9864
|
console.log(" 6. Run decantr check and decantr audit after implementation");
|
|
10011
|
-
console.log(" 7.
|
|
9865
|
+
console.log(" 7. Review the official corpus at decantr.ai/reference/content-health.md");
|
|
10012
9866
|
} else {
|
|
10013
9867
|
console.log(" 1. Fix the validation issue reported above");
|
|
10014
9868
|
console.log(" 2. Run decantr refresh to restore compiled execution packs");
|
|
@@ -10024,15 +9878,15 @@ ${YELLOW13}You're offline. Scaffolding Decantr default.${RESET18}`);
|
|
|
10024
9878
|
console.log(" Commands:");
|
|
10025
9879
|
console.log(` ${cyan4("decantr status")} Project health`);
|
|
10026
9880
|
console.log(` ${cyan4("decantr health")} Contract health report`);
|
|
10027
|
-
console.log(` ${cyan4("decantr content-health")}
|
|
9881
|
+
console.log(` ${cyan4("decantr content-health")} Official content health report`);
|
|
10028
9882
|
console.log(` ${cyan4("decantr studio")} Local health dashboard`);
|
|
10029
|
-
console.log(` ${cyan4("decantr search")} Search
|
|
9883
|
+
console.log(` ${cyan4("decantr search")} Search official content`);
|
|
10030
9884
|
console.log(` ${cyan4("decantr get")} Fetch content details`);
|
|
10031
9885
|
console.log(` ${cyan4("decantr validate")} Check essence file`);
|
|
10032
9886
|
console.log(` ${cyan4("decantr upgrade")} Update to latest patterns`);
|
|
10033
9887
|
console.log(` ${cyan4("decantr check")} Detect drift issues`);
|
|
10034
9888
|
console.log(` ${cyan4("decantr migrate --to v4")} Migrate older essence files to v4`);
|
|
10035
|
-
const essenceContent =
|
|
9889
|
+
const essenceContent = readFileSync21(result.essencePath, "utf-8");
|
|
10036
9890
|
const essence = JSON.parse(essenceContent);
|
|
10037
9891
|
const validation = validateEssence2(essence);
|
|
10038
9892
|
if (!validation.valid) {
|
|
@@ -10083,20 +9937,20 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
10083
9937
|
console.log(dim4("\u2500".repeat(50)));
|
|
10084
9938
|
console.log("");
|
|
10085
9939
|
if (registrySource === "cache") {
|
|
10086
|
-
console.log(dim4('Run "decantr sync" when online to get the latest
|
|
9940
|
+
console.log(dim4('Run "decantr sync" when online to get the latest official content.'));
|
|
10087
9941
|
}
|
|
10088
9942
|
}
|
|
10089
9943
|
async function cmdStatus(projectRoot = process.cwd()) {
|
|
10090
|
-
const essencePath =
|
|
10091
|
-
const projectJsonPath =
|
|
9944
|
+
const essencePath = join31(projectRoot, "decantr.essence.json");
|
|
9945
|
+
const projectJsonPath = join31(projectRoot, ".decantr", "project.json");
|
|
10092
9946
|
console.log(heading2("Decantr Project Status"));
|
|
10093
|
-
if (!
|
|
9947
|
+
if (!existsSync28(essencePath)) {
|
|
10094
9948
|
console.log(`${RED13}No decantr.essence.json found.${RESET18}`);
|
|
10095
9949
|
console.log(dim4('Run "decantr init" to create one.'));
|
|
10096
9950
|
return;
|
|
10097
9951
|
}
|
|
10098
9952
|
try {
|
|
10099
|
-
const essence = JSON.parse(
|
|
9953
|
+
const essence = JSON.parse(readFileSync21(essencePath, "utf-8"));
|
|
10100
9954
|
const validation = validateEssence2(essence);
|
|
10101
9955
|
const essenceVersion = isV48(essence) ? "v4" : "legacy";
|
|
10102
9956
|
console.log(`${BOLD11}Essence:${RESET18}`);
|
|
@@ -10144,9 +9998,9 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
10144
9998
|
}
|
|
10145
9999
|
console.log("");
|
|
10146
10000
|
console.log(`${BOLD11}Sync Status:${RESET18}`);
|
|
10147
|
-
if (
|
|
10001
|
+
if (existsSync28(projectJsonPath)) {
|
|
10148
10002
|
try {
|
|
10149
|
-
const projectJson = JSON.parse(
|
|
10003
|
+
const projectJson = JSON.parse(readFileSync21(projectJsonPath, "utf-8"));
|
|
10150
10004
|
const syncStatus = projectJson.sync?.status || "unknown";
|
|
10151
10005
|
const lastSync = projectJson.sync?.lastSync || "never";
|
|
10152
10006
|
const source = projectJson.sync?.registrySource || "unknown";
|
|
@@ -10164,8 +10018,8 @@ async function cmdStatus(projectRoot = process.cwd()) {
|
|
|
10164
10018
|
}
|
|
10165
10019
|
async function cmdSync() {
|
|
10166
10020
|
const projectRoot = process.cwd();
|
|
10167
|
-
const cacheDir =
|
|
10168
|
-
console.log(heading2("Syncing
|
|
10021
|
+
const cacheDir = join31(projectRoot, ".decantr", "cache");
|
|
10022
|
+
console.log(heading2("Syncing official content..."));
|
|
10169
10023
|
const result = await syncRegistry(cacheDir);
|
|
10170
10024
|
if (result.synced.length > 0) {
|
|
10171
10025
|
console.log(success4("Sync completed successfully."));
|
|
@@ -10253,42 +10107,57 @@ function printFileCritiqueReport(report) {
|
|
|
10253
10107
|
console.log(`${BOLD11}Findings:${RESET18}`);
|
|
10254
10108
|
printVerificationFindings(report.findings);
|
|
10255
10109
|
}
|
|
10256
|
-
async function cmdAudit(filePath) {
|
|
10110
|
+
async function cmdAudit(filePath, options = {}) {
|
|
10257
10111
|
const projectRoot = process.cwd();
|
|
10112
|
+
const jsonOutput = options.json === true;
|
|
10258
10113
|
try {
|
|
10259
10114
|
if (filePath) {
|
|
10260
10115
|
const hydration2 = await hydrateHostedReviewPackIfMissing(projectRoot);
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
|
|
10116
|
+
if (!jsonOutput) {
|
|
10117
|
+
console.log(heading2(`Critiquing ${filePath}...`));
|
|
10118
|
+
}
|
|
10119
|
+
if (hydration2.hydrated && !jsonOutput) {
|
|
10120
|
+
console.log(dim4("Hydrated missing review pack from the content API."));
|
|
10264
10121
|
console.log("");
|
|
10265
10122
|
}
|
|
10266
10123
|
const report2 = await critiqueProjectFile(filePath, projectRoot);
|
|
10267
|
-
|
|
10124
|
+
if (jsonOutput) {
|
|
10125
|
+
console.log(JSON.stringify(report2, null, 2));
|
|
10126
|
+
} else {
|
|
10127
|
+
printFileCritiqueReport(report2);
|
|
10128
|
+
}
|
|
10268
10129
|
if (report2.findings.some((finding) => finding.severity === "error")) {
|
|
10269
10130
|
process.exitCode = 1;
|
|
10270
10131
|
}
|
|
10271
10132
|
return;
|
|
10272
10133
|
}
|
|
10273
10134
|
const hydration = await hydrateHostedExecutionPacksIfMissing(projectRoot);
|
|
10274
|
-
|
|
10275
|
-
|
|
10135
|
+
if (!jsonOutput) {
|
|
10136
|
+
console.log(heading2("Auditing project..."));
|
|
10137
|
+
}
|
|
10138
|
+
if (hydration.hydrated && !jsonOutput) {
|
|
10276
10139
|
console.log(
|
|
10277
10140
|
dim4(
|
|
10278
|
-
hydration.scope === "bundle" ? "Hydrated missing execution packs from
|
|
10141
|
+
hydration.scope === "bundle" ? "Hydrated missing execution packs from the content API." : "Hydrated missing review pack and manifest from the content API."
|
|
10279
10142
|
)
|
|
10280
10143
|
);
|
|
10281
10144
|
console.log("");
|
|
10282
10145
|
}
|
|
10283
10146
|
const report = await auditProject(projectRoot);
|
|
10284
|
-
|
|
10147
|
+
if (jsonOutput) {
|
|
10148
|
+
console.log(JSON.stringify(report, null, 2));
|
|
10149
|
+
} else {
|
|
10150
|
+
printProjectAuditReport(report);
|
|
10151
|
+
}
|
|
10285
10152
|
if (!report.valid) {
|
|
10286
10153
|
process.exitCode = 1;
|
|
10287
10154
|
return;
|
|
10288
10155
|
}
|
|
10289
10156
|
if (report.findings.length > 0) {
|
|
10290
|
-
|
|
10291
|
-
|
|
10157
|
+
if (!jsonOutput) {
|
|
10158
|
+
console.log("");
|
|
10159
|
+
console.log(dim4("Project audit completed with advisory findings."));
|
|
10160
|
+
}
|
|
10292
10161
|
}
|
|
10293
10162
|
} catch (e) {
|
|
10294
10163
|
console.log(`${RED13}Error: ${e.message}${RESET18}`);
|
|
@@ -10358,14 +10227,14 @@ ${BOLD11}Examples:${RESET18}
|
|
|
10358
10227
|
process.exitCode = 1;
|
|
10359
10228
|
return;
|
|
10360
10229
|
}
|
|
10361
|
-
const themePath =
|
|
10362
|
-
if (!
|
|
10230
|
+
const themePath = join31(projectRoot, ".decantr", "custom", "themes", `${name}.json`);
|
|
10231
|
+
if (!existsSync28(themePath)) {
|
|
10363
10232
|
console.error(error2(`Theme "${name}" not found at ${themePath}`));
|
|
10364
10233
|
process.exitCode = 1;
|
|
10365
10234
|
return;
|
|
10366
10235
|
}
|
|
10367
10236
|
try {
|
|
10368
|
-
const theme = JSON.parse(
|
|
10237
|
+
const theme = JSON.parse(readFileSync21(themePath, "utf-8"));
|
|
10369
10238
|
const result = validateCustomTheme(theme);
|
|
10370
10239
|
if (result.valid) {
|
|
10371
10240
|
console.log(success4(`Custom theme "${name}" is valid`));
|
|
@@ -10497,7 +10366,7 @@ function withProject(command, projectArg) {
|
|
|
10497
10366
|
return projectArg ? `${command} --project ${projectArg}` : command;
|
|
10498
10367
|
}
|
|
10499
10368
|
function displayProjectPath(workspaceInfo, projectPath) {
|
|
10500
|
-
const absolutePath =
|
|
10369
|
+
const absolutePath = join31(workspaceInfo.appRoot, projectPath);
|
|
10501
10370
|
const relativePath = relative7(workspaceInfo.cwd, absolutePath).replace(/\\/g, "/");
|
|
10502
10371
|
if (relativePath && !relativePath.startsWith("..") && !isAbsolute4(relativePath)) {
|
|
10503
10372
|
return relativePath;
|
|
@@ -10521,7 +10390,7 @@ function graphSourceNodeIdForTaskFile(projectRoot, snapshot, filePath) {
|
|
|
10521
10390
|
candidates.add(trimmed.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
10522
10391
|
const cwdRelative = projectRelativeGraphPath(projectRoot, trimmed);
|
|
10523
10392
|
if (cwdRelative) candidates.add(cwdRelative);
|
|
10524
|
-
const projectRelative = projectRelativeGraphPath(projectRoot,
|
|
10393
|
+
const projectRelative = projectRelativeGraphPath(projectRoot, join31(projectRoot, trimmed));
|
|
10525
10394
|
if (projectRelative) candidates.add(projectRelative);
|
|
10526
10395
|
for (const candidate of candidates) {
|
|
10527
10396
|
const nodeId = `src:${candidate}`;
|
|
@@ -10595,7 +10464,7 @@ function printWorkspaceProjectSelection(workspaceInfo, commandName = "command")
|
|
|
10595
10464
|
function printMonorepoSetupGuidance(workspaceInfo) {
|
|
10596
10465
|
const candidate = firstWorkspaceCandidate(workspaceInfo);
|
|
10597
10466
|
const attachedProjects = workspaceInfo.appCandidates.filter(
|
|
10598
|
-
(appCandidate) =>
|
|
10467
|
+
(appCandidate) => existsSync28(join31(workspaceInfo.workspaceRoot, appCandidate, "decantr.essence.json"))
|
|
10599
10468
|
);
|
|
10600
10469
|
const firstAttached = attachedProjects[0];
|
|
10601
10470
|
console.log(heading2("Decantr Setup"));
|
|
@@ -10663,7 +10532,7 @@ function printMonorepoSetupGuidance(workspaceInfo) {
|
|
|
10663
10532
|
function resolveWorkflowProject(flags, commandName = "command", options = {}) {
|
|
10664
10533
|
const projectArg = flagString(flags, "project");
|
|
10665
10534
|
const workspaceInfo = resolveWorkspaceInfo(process.cwd(), projectArg);
|
|
10666
|
-
if (projectArg && options.requireExisting !== false && !
|
|
10535
|
+
if (projectArg && options.requireExisting !== false && !existsSync28(workspaceInfo.appRoot)) {
|
|
10667
10536
|
printProjectNotFound(projectArg, commandName);
|
|
10668
10537
|
process.exitCode = 1;
|
|
10669
10538
|
return null;
|
|
@@ -11003,9 +10872,9 @@ async function cmdSetupWorkflow(args) {
|
|
|
11003
10872
|
console.log(` Detected: ${formatDetection(detected)}`);
|
|
11004
10873
|
console.log("");
|
|
11005
10874
|
if (detected.existingEssence) {
|
|
11006
|
-
const hasLocalPatterns =
|
|
11007
|
-
const hasLocalRules =
|
|
11008
|
-
const hasStyleBridge =
|
|
10875
|
+
const hasLocalPatterns = existsSync28(localPatternsPath(workspaceInfo.appRoot));
|
|
10876
|
+
const hasLocalRules = existsSync28(localRulesPath(workspaceInfo.appRoot));
|
|
10877
|
+
const hasStyleBridge = existsSync28(styleBridgePath(workspaceInfo.appRoot));
|
|
11009
10878
|
const verifyCommand = hasLocalPatterns || hasLocalRules ? "decantr verify --brownfield --local-patterns" : "decantr verify --brownfield";
|
|
11010
10879
|
console.log(`${BOLD11}Recommended path:${RESET18} maintain an attached Decantr project`);
|
|
11011
10880
|
console.log(
|
|
@@ -11093,7 +10962,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
11093
10962
|
const hydratePacks = flagBoolean(flags, "packs", true) && !flagBoolean(flags, "skip-packs") && !flagBoolean(flags, "offline") && process.env.DECANTR_OFFLINE !== "true";
|
|
11094
10963
|
const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
|
|
11095
10964
|
const assistantBridge = flagString(flags, "assistant-bridge");
|
|
11096
|
-
const hasEssence =
|
|
10965
|
+
const hasEssence = existsSync28(join31(projectRoot, "decantr.essence.json"));
|
|
11097
10966
|
const proposalFlag = flagBoolean(flags, "replace-essence") ? "--replace-essence" : flagBoolean(flags, "merge-proposal") || hasEssence ? "--merge-proposal" : "--accept-proposal";
|
|
11098
10967
|
const steps = [
|
|
11099
10968
|
"analyze current app and write .decantr/brownfield intelligence",
|
|
@@ -11142,7 +11011,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
11142
11011
|
if (hydratePacks) {
|
|
11143
11012
|
try {
|
|
11144
11013
|
const { bundle, contextDir } = await compileHostedExecutionPackBundle(
|
|
11145
|
-
|
|
11014
|
+
join31(projectRoot, "decantr.essence.json")
|
|
11146
11015
|
);
|
|
11147
11016
|
const written = writeHostedExecutionPackContextArtifacts(
|
|
11148
11017
|
contextDir,
|
|
@@ -11167,7 +11036,7 @@ async function cmdAdoptWorkflow(args) {
|
|
|
11167
11036
|
await cmdGraph(projectRoot, { displayRoot: process.cwd() });
|
|
11168
11037
|
if (process.exitCode && process.exitCode !== 0) return;
|
|
11169
11038
|
if (runVerify) {
|
|
11170
|
-
const { cmdHealth } = await import("./health-
|
|
11039
|
+
const { cmdHealth } = await import("./health-WZ562PRA.js");
|
|
11171
11040
|
await cmdHealth(projectRoot, {
|
|
11172
11041
|
browser: runBrowser,
|
|
11173
11042
|
browserBaseUrl: baseUrl,
|
|
@@ -11241,7 +11110,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11241
11110
|
return;
|
|
11242
11111
|
}
|
|
11243
11112
|
if (workspaceMode) {
|
|
11244
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
11113
|
+
const { cmdWorkspace } = await import("./workspace-EDP7QG7T.js");
|
|
11245
11114
|
await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
|
|
11246
11115
|
return;
|
|
11247
11116
|
}
|
|
@@ -11274,7 +11143,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11274
11143
|
}
|
|
11275
11144
|
let guardExitCode;
|
|
11276
11145
|
if (brownfield) {
|
|
11277
|
-
const { cmdHeal, collectCheckIssues } = await import("./heal-
|
|
11146
|
+
const { cmdHeal, collectCheckIssues } = await import("./heal-AEMYO7T2.js");
|
|
11278
11147
|
if (quietOutput) {
|
|
11279
11148
|
const result = collectCheckIssues(workspaceInfo.appRoot, { brownfield: true });
|
|
11280
11149
|
guardExitCode = result.issues.some((issue) => issue.type === "error") ? 1 : void 0;
|
|
@@ -11284,7 +11153,7 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11284
11153
|
process.exitCode = void 0;
|
|
11285
11154
|
}
|
|
11286
11155
|
}
|
|
11287
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
11156
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-WZ562PRA.js");
|
|
11288
11157
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
|
|
11289
11158
|
if (localPatterns) {
|
|
11290
11159
|
const validation = validateLocalLaw(workspaceInfo.appRoot);
|
|
@@ -11353,9 +11222,9 @@ async function cmdVerifyWorkflow(args) {
|
|
|
11353
11222
|
}
|
|
11354
11223
|
}
|
|
11355
11224
|
function readJsonIfPresent(path) {
|
|
11356
|
-
if (!
|
|
11225
|
+
if (!existsSync28(path)) return null;
|
|
11357
11226
|
try {
|
|
11358
|
-
return JSON.parse(
|
|
11227
|
+
return JSON.parse(readFileSync21(path, "utf-8"));
|
|
11359
11228
|
} catch {
|
|
11360
11229
|
return null;
|
|
11361
11230
|
}
|
|
@@ -11507,7 +11376,7 @@ async function cmdTaskWorkflow(args) {
|
|
|
11507
11376
|
}
|
|
11508
11377
|
const route = routeInput.startsWith("/") ? routeInput : `/${routeInput}`;
|
|
11509
11378
|
const taskSummary = positional.slice(1).join(" ").trim();
|
|
11510
|
-
const essencePath =
|
|
11379
|
+
const essencePath = join31(workspaceInfo.appRoot, "decantr.essence.json");
|
|
11511
11380
|
const essence = readJsonIfPresent(essencePath);
|
|
11512
11381
|
if (!essence) {
|
|
11513
11382
|
console.error(
|
|
@@ -11531,19 +11400,19 @@ async function cmdTaskWorkflow(args) {
|
|
|
11531
11400
|
}
|
|
11532
11401
|
const section = essence.blueprint.sections.find((entry) => entry.id === target.section);
|
|
11533
11402
|
const page = section?.pages.find((entry) => entry.id === target.page);
|
|
11534
|
-
const contextDir =
|
|
11535
|
-
const manifest = readJsonIfPresent(
|
|
11536
|
-
const projectJson = readJsonIfPresent(
|
|
11403
|
+
const contextDir = join31(workspaceInfo.appRoot, ".decantr", "context");
|
|
11404
|
+
const manifest = readJsonIfPresent(join31(contextDir, "pack-manifest.json"));
|
|
11405
|
+
const projectJson = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "project.json"));
|
|
11537
11406
|
const pagePack = manifest?.pages?.find((entry) => entry.id === target.page);
|
|
11538
11407
|
const sectionPack = manifest?.sections?.find((entry) => entry.id === target.section);
|
|
11539
|
-
const visualManifest = readJsonIfPresent(
|
|
11408
|
+
const visualManifest = readJsonIfPresent(join31(workspaceInfo.appRoot, ".decantr", "evidence", "visual-manifest.json"));
|
|
11540
11409
|
const screenshot = visualManifest?.routes?.find((entry) => entry.route === route)?.screenshot;
|
|
11541
11410
|
const localPatternPackPath = localPatternsPath(workspaceInfo.appRoot);
|
|
11542
11411
|
const localRuleManifestPath = localRulesPath(workspaceInfo.appRoot);
|
|
11543
11412
|
const acceptedStyleBridgePath = styleBridgePath(workspaceInfo.appRoot);
|
|
11544
|
-
const graphDir =
|
|
11545
|
-
const contractCapsulePath =
|
|
11546
|
-
const graphSnapshotPath =
|
|
11413
|
+
const graphDir = join31(workspaceInfo.appRoot, ".decantr", "graph");
|
|
11414
|
+
const contractCapsulePath = join31(graphDir, "contract-capsule.json");
|
|
11415
|
+
const graphSnapshotPath = join31(graphDir, "graph.snapshot.json");
|
|
11547
11416
|
const contractCapsule = readJsonIfPresent(contractCapsulePath);
|
|
11548
11417
|
const graphSnapshot = readJsonIfPresent(graphSnapshotPath);
|
|
11549
11418
|
const routeGraphContext = buildGraphRouteContext(graphSnapshot, route, { task: taskSummary });
|
|
@@ -11586,21 +11455,21 @@ async function cmdTaskWorkflow(args) {
|
|
|
11586
11455
|
projectRoot: workspaceInfo.appRoot,
|
|
11587
11456
|
workflowMode: projectJson?.initialized?.workflowMode ?? null,
|
|
11588
11457
|
adoptionMode: projectJson?.initialized?.adoptionMode ?? null,
|
|
11589
|
-
hasLocalPatterns:
|
|
11590
|
-
hasLocalRules:
|
|
11458
|
+
hasLocalPatterns: existsSync28(localPatternPackPath),
|
|
11459
|
+
hasLocalRules: existsSync28(localRuleManifestPath),
|
|
11591
11460
|
hasPackManifest: Boolean(manifest),
|
|
11592
11461
|
taskSummary,
|
|
11593
|
-
hasStyleBridge:
|
|
11462
|
+
hasStyleBridge: existsSync28(acceptedStyleBridgePath)
|
|
11594
11463
|
});
|
|
11595
11464
|
const readTargets = [
|
|
11596
|
-
pagePack ? displayProjectPath(workspaceInfo,
|
|
11597
|
-
sectionPack ? displayProjectPath(workspaceInfo,
|
|
11598
|
-
manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo,
|
|
11465
|
+
pagePack ? displayProjectPath(workspaceInfo, join31(".decantr/context", pagePack.markdown)) : null,
|
|
11466
|
+
sectionPack ? displayProjectPath(workspaceInfo, join31(".decantr/context", sectionPack.markdown)) : null,
|
|
11467
|
+
manifest?.scaffold?.markdown ? displayProjectPath(workspaceInfo, join31(".decantr/context", manifest.scaffold.markdown)) : null,
|
|
11599
11468
|
displayProjectPath(workspaceInfo, ".decantr/context/scaffold.md"),
|
|
11600
11469
|
displayProjectPath(workspaceInfo, "DECANTR.md"),
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11470
|
+
existsSync28(localPatternPackPath) ? displayProjectPath(workspaceInfo, ".decantr/local-patterns.json") : null,
|
|
11471
|
+
existsSync28(localRuleManifestPath) ? displayProjectPath(workspaceInfo, ".decantr/rules.json") : null,
|
|
11472
|
+
existsSync28(acceptedStyleBridgePath) ? displayProjectPath(workspaceInfo, ".decantr/style-bridge.json") : null,
|
|
11604
11473
|
contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/contract-capsule.json") : null,
|
|
11605
11474
|
routeGraphContext && !contractCapsule ? displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json") : null
|
|
11606
11475
|
].filter((value) => Boolean(value));
|
|
@@ -11920,7 +11789,7 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11920
11789
|
const workspaceInfo = resolveWorkflowProject(flags, "codify");
|
|
11921
11790
|
if (!workspaceInfo) return;
|
|
11922
11791
|
if (flagBoolean(flags, "accept")) {
|
|
11923
|
-
if (!
|
|
11792
|
+
if (!existsSync28(localPatternsProposalPath(workspaceInfo.appRoot)) && !existsSync28(localRulesProposalPath(workspaceInfo.appRoot)) && !existsSync28(styleBridgeProposalPath(workspaceInfo.appRoot))) {
|
|
11924
11793
|
console.error(
|
|
11925
11794
|
error2(
|
|
11926
11795
|
"No codify proposal found. Run `decantr codify --from-audit`, `decantr codify --style-bridge`, or `decantr codify` first."
|
|
@@ -11954,14 +11823,14 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11954
11823
|
}
|
|
11955
11824
|
const detected = detectProject(workspaceInfo.appRoot);
|
|
11956
11825
|
const essence = readJsonIfPresent(
|
|
11957
|
-
|
|
11826
|
+
join31(workspaceInfo.appRoot, "decantr.essence.json")
|
|
11958
11827
|
);
|
|
11959
11828
|
const fromAudit = flagBoolean(flags, "from-audit") || flagBoolean(flags, "discover-local-patterns") || flagBoolean(flags, "codify-local-patterns");
|
|
11960
11829
|
const wantsStyleBridge = flagBoolean(flags, "style-bridge");
|
|
11961
11830
|
const mapPatternSlug = flagString(flags, "map-pattern") ?? flagString(flags, "hosted-pattern");
|
|
11962
11831
|
if (mapPatternSlug) {
|
|
11963
11832
|
const registryClient = new RegistryClient({
|
|
11964
|
-
cacheDir:
|
|
11833
|
+
cacheDir: join31(workspaceInfo.appRoot, ".decantr", "cache")
|
|
11965
11834
|
});
|
|
11966
11835
|
const candidates = await loadPatternDiscoveryCandidates(registryClient);
|
|
11967
11836
|
const candidate = findPatternCandidateBySlug(candidates, mapPatternSlug);
|
|
@@ -11969,7 +11838,7 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11969
11838
|
const suggestions = rankPatternCandidates({ query: mapPatternSlug, limit: 5 }, candidates);
|
|
11970
11839
|
console.error(error2(`Could not find pattern "${mapPatternSlug}" to map into local law.`));
|
|
11971
11840
|
if (suggestions.length > 0) {
|
|
11972
|
-
console.error(dim4("Closest
|
|
11841
|
+
console.error(dim4("Closest official content patterns:"));
|
|
11973
11842
|
for (const suggestion of suggestions) {
|
|
11974
11843
|
const slug2 = suggestion.candidate.slug || suggestion.candidate.id;
|
|
11975
11844
|
console.error(dim4(` ${slug2} - ${suggestion.candidate.name ?? slug2}`));
|
|
@@ -11985,12 +11854,12 @@ async function cmdCodifyWorkflow(args) {
|
|
|
11985
11854
|
const slug = candidate.slug || candidate.id;
|
|
11986
11855
|
console.log(
|
|
11987
11856
|
success4(
|
|
11988
|
-
`${result.replacedExisting ? "Updated" : "Wrote"}
|
|
11857
|
+
`${result.replacedExisting ? "Updated" : "Wrote"} content pattern mapping proposal: ${result.patternPath}`
|
|
11989
11858
|
)
|
|
11990
11859
|
);
|
|
11991
11860
|
console.log(
|
|
11992
11861
|
dim4(
|
|
11993
|
-
`Mapped
|
|
11862
|
+
`Mapped official content pattern "${slug}" into local pattern "${result.localPatternId}" as advisory Hybrid law. No source files were changed.`
|
|
11994
11863
|
)
|
|
11995
11864
|
);
|
|
11996
11865
|
console.log(
|
|
@@ -12046,8 +11915,12 @@ async function cmdCodifyWorkflow(args) {
|
|
|
12046
11915
|
}
|
|
12047
11916
|
async function cmdContentWorkflow(args) {
|
|
12048
11917
|
const subcommand = args[1] ?? "check";
|
|
11918
|
+
if (subcommand === "summary" || subcommand === "compile-packs" || subcommand === "get-pack") {
|
|
11919
|
+
await cmdContentCorpusWorkflow(args, "content");
|
|
11920
|
+
return;
|
|
11921
|
+
}
|
|
12049
11922
|
if (subcommand === "check" || subcommand === "health") {
|
|
12050
|
-
const { cmdContentHealth, parseContentHealthArgs } = await import("./content-health-
|
|
11923
|
+
const { cmdContentHealth, parseContentHealthArgs } = await import("./content-health-PYGEZZOV.js");
|
|
12051
11924
|
await cmdContentHealth(
|
|
12052
11925
|
process.cwd(),
|
|
12053
11926
|
parseContentHealthArgs(["content-health", ...args.slice(2)])
|
|
@@ -12068,19 +11941,74 @@ async function cmdContentWorkflow(args) {
|
|
|
12068
11941
|
return;
|
|
12069
11942
|
}
|
|
12070
11943
|
if (subcommand === "publish") {
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
11944
|
+
console.error(
|
|
11945
|
+
error2(
|
|
11946
|
+
"Hosted community publishing has been retired. Add official corpus changes under packages/content and run decantr content check."
|
|
11947
|
+
)
|
|
11948
|
+
);
|
|
11949
|
+
process.exitCode = 1;
|
|
11950
|
+
return;
|
|
11951
|
+
}
|
|
11952
|
+
console.error(error2("Usage: decantr content <check|create|summary|compile-packs|get-pack>"));
|
|
11953
|
+
process.exitCode = 1;
|
|
11954
|
+
}
|
|
11955
|
+
async function cmdContentCorpusWorkflow(args, commandName) {
|
|
11956
|
+
const subcommand = args[1];
|
|
11957
|
+
if (subcommand === "summary") {
|
|
11958
|
+
const namespaceIdx = args.indexOf("--namespace");
|
|
11959
|
+
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
11960
|
+
const jsonOutput = args.includes("--json");
|
|
11961
|
+
await printRegistryIntelligenceSummary(namespace, jsonOutput);
|
|
11962
|
+
return;
|
|
11963
|
+
}
|
|
11964
|
+
if (subcommand === "compile-packs") {
|
|
11965
|
+
const namespaceIdx = args.indexOf("--namespace");
|
|
11966
|
+
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
11967
|
+
const jsonOutput = args.includes("--json");
|
|
11968
|
+
const writeContext = args.includes("--write-context");
|
|
11969
|
+
const essencePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
11970
|
+
await printHostedExecutionPackBundle(essencePath, namespace, jsonOutput, writeContext);
|
|
11971
|
+
return;
|
|
11972
|
+
}
|
|
11973
|
+
if (subcommand === "get-pack") {
|
|
11974
|
+
const namespaceIdx = args.indexOf("--namespace");
|
|
11975
|
+
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
11976
|
+
const jsonOutput = args.includes("--json");
|
|
11977
|
+
const writeContext = args.includes("--write-context");
|
|
11978
|
+
const essenceIdx = args.indexOf("--essence");
|
|
11979
|
+
const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
|
|
11980
|
+
const packType = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
11981
|
+
const routeIdx = args.indexOf("--route");
|
|
11982
|
+
const route = routeIdx !== -1 ? args[routeIdx + 1] : void 0;
|
|
11983
|
+
let id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
|
|
11984
|
+
if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
|
|
11985
|
+
console.error(
|
|
11986
|
+
`${RED13}Usage: decantr ${commandName} get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET18}`
|
|
11987
|
+
);
|
|
12077
11988
|
process.exitCode = 1;
|
|
12078
11989
|
return;
|
|
12079
11990
|
}
|
|
12080
|
-
|
|
11991
|
+
if (packType === "manifest") {
|
|
11992
|
+
await printHostedExecutionPackManifest(essencePath, namespace, jsonOutput, writeContext);
|
|
11993
|
+
return;
|
|
11994
|
+
}
|
|
11995
|
+
if (packType === "page" && route && !id) {
|
|
11996
|
+
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
|
|
11997
|
+
id = resolvePagePackIdForRoute(resolvedPath, route);
|
|
11998
|
+
}
|
|
11999
|
+
await printHostedSelectedExecutionPack(
|
|
12000
|
+
packType,
|
|
12001
|
+
id,
|
|
12002
|
+
essencePath,
|
|
12003
|
+
namespace,
|
|
12004
|
+
jsonOutput,
|
|
12005
|
+
writeContext
|
|
12006
|
+
);
|
|
12081
12007
|
return;
|
|
12082
12008
|
}
|
|
12083
|
-
console.error(
|
|
12009
|
+
console.error(
|
|
12010
|
+
`${RED13}Usage: decantr ${commandName} summary [--namespace <namespace>] [--json] | decantr ${commandName} compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr ${commandName} get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET18}`
|
|
12011
|
+
);
|
|
12084
12012
|
process.exitCode = 1;
|
|
12085
12013
|
}
|
|
12086
12014
|
function cmdHelp() {
|
|
@@ -12090,7 +12018,7 @@ ${BOLD11}decantr${RESET18} \u2014 AI Frontend Governance for codebases touched b
|
|
|
12090
12018
|
${BOLD11}Usage:${RESET18}
|
|
12091
12019
|
decantr setup [--project <path>]
|
|
12092
12020
|
decantr scan [--project <path>] [--json]
|
|
12093
|
-
decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
|
|
12021
|
+
decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=contract-only|decantr-css] [--telemetry]
|
|
12094
12022
|
decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--no-packs] [--yes]
|
|
12095
12023
|
decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
|
|
12096
12024
|
decantr verify [--project <path>] [--brownfield] [--local-patterns] [health options]
|
|
@@ -12122,11 +12050,9 @@ ${BOLD11}Advanced primitives:${RESET18}
|
|
|
12122
12050
|
decantr get <type> <id>
|
|
12123
12051
|
decantr list <type> [--sort <recommended|recent|name>] [--recommended] [--source <authored|benchmark|hybrid>]
|
|
12124
12052
|
decantr showcase [manifest|shortlist|verification] [--json]
|
|
12125
|
-
decantr
|
|
12126
|
-
decantr
|
|
12127
|
-
decantr
|
|
12128
|
-
decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]
|
|
12129
|
-
decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]
|
|
12053
|
+
decantr content summary [--namespace <namespace>] [--json]
|
|
12054
|
+
decantr content compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
|
|
12055
|
+
decantr content get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
|
|
12130
12056
|
decantr health [--format text|json|markdown] [--ci] [--fail-on error|warn|none]
|
|
12131
12057
|
decantr health --evidence [--browser] [--base-url <url>] [--design-tokens <path>]
|
|
12132
12058
|
decantr health --diagnostics [--json|--markdown]
|
|
@@ -12140,7 +12066,7 @@ ${BOLD11}Advanced primitives:${RESET18}
|
|
|
12140
12066
|
decantr content-health [--json] [--markdown] [--ci]
|
|
12141
12067
|
decantr telemetry status [--json]
|
|
12142
12068
|
decantr telemetry explain [--json]
|
|
12143
|
-
decantr telemetry link [--enable] [--org <slug>]
|
|
12069
|
+
decantr telemetry link --api-url <private-url> --api-key <key> [--enable] [--org <slug>]
|
|
12144
12070
|
decantr rules preview [--project=<path>]
|
|
12145
12071
|
decantr rules apply [--project=<path>]
|
|
12146
12072
|
decantr validate [path]
|
|
@@ -12170,8 +12096,8 @@ ${BOLD11}Init Options:${RESET18}
|
|
|
12170
12096
|
--existing Initialize in existing project
|
|
12171
12097
|
--offline Force offline mode
|
|
12172
12098
|
--yes, -y Accept defaults, skip confirmations
|
|
12173
|
-
--registry Custom
|
|
12174
|
-
--telemetry
|
|
12099
|
+
--registry Custom API URL (legacy alias; prefer DECANTR_API_URL)
|
|
12100
|
+
--telemetry Enable the local preference; delivery requires DECANTR_TELEMETRY_ENDPOINT
|
|
12175
12101
|
|
|
12176
12102
|
${BOLD11}Commands:${RESET18}
|
|
12177
12103
|
${cyan4("setup")} Detect project state and recommend the right Decantr workflow
|
|
@@ -12187,7 +12113,7 @@ ${BOLD11}Commands:${RESET18}
|
|
|
12187
12113
|
${cyan4("connect")} Connect Decantr to AI coding tools such as Cursor
|
|
12188
12114
|
${cyan4("codify")} Propose or accept project-owned Brownfield UI patterns, behavior obligations, and rules
|
|
12189
12115
|
${cyan4("studio")} Open a local Project Health dashboard backed by the same report
|
|
12190
|
-
${cyan4("content")}
|
|
12116
|
+
${cyan4("content")} Official content-corpus namespace: check, summary, packs, create
|
|
12191
12117
|
|
|
12192
12118
|
${BOLD11}Advanced commands:${RESET18}
|
|
12193
12119
|
${cyan4("magic")} Greenfield-first intent flow; steers existing apps into analyze + init
|
|
@@ -12203,7 +12129,7 @@ ${BOLD11}Advanced commands:${RESET18}
|
|
|
12203
12129
|
${cyan4("sync-drift")} Review and resolve drift log entries
|
|
12204
12130
|
${cyan4("resolve")} Group source-vs-contract conflicts and print exact resolution actions
|
|
12205
12131
|
${cyan4("graph")} Generate .decantr/graph snapshot, history, manifest, diff, and contract capsule
|
|
12206
|
-
${cyan4("search")} Search official
|
|
12132
|
+
${cyan4("search")} Search official content-corpus vocabulary
|
|
12207
12133
|
${cyan4("suggest")} Suggest patterns or alternatives for a query
|
|
12208
12134
|
${cyan4("get")} Get full details of a vocabulary item
|
|
12209
12135
|
${cyan4("list")} List items by type
|
|
@@ -12211,16 +12137,16 @@ ${BOLD11}Advanced commands:${RESET18}
|
|
|
12211
12137
|
${cyan4("validate")} Validate an Essence v4 file
|
|
12212
12138
|
${cyan4("theme")} Manage custom themes (create, list, validate, delete, import)
|
|
12213
12139
|
${cyan4("create")} Create a custom content item (pattern, theme, blueprint, etc.)
|
|
12214
|
-
${cyan4("publish")}
|
|
12215
|
-
${cyan4("login")}
|
|
12216
|
-
${cyan4("logout")} Remove stored credentials
|
|
12140
|
+
${cyan4("publish")} Legacy retired hosted publishing command
|
|
12141
|
+
${cyan4("login")} Legacy API-key helper for compatibility scripts
|
|
12142
|
+
${cyan4("logout")} Remove stored legacy credentials
|
|
12217
12143
|
${cyan4("analyze")} Brownfield entrypoint: scan an existing project and emit attach guidance
|
|
12218
|
-
${cyan4("telemetry")} Inspect
|
|
12144
|
+
${cyan4("telemetry")} Inspect caller-configured private CLI telemetry
|
|
12219
12145
|
${cyan4("export")} Export design tokens to framework format (shadcn, tailwind, css-vars)
|
|
12220
|
-
${cyan4("registry")}
|
|
12146
|
+
${cyan4("registry")} Legacy alias for content-corpus and pack helpers
|
|
12221
12147
|
${cyan4("rules")} Preview/apply Decantr assistant bridge blocks to repo rule files
|
|
12222
12148
|
${cyan4("connect")} Configure editor-specific Decantr rules and MCP where supported
|
|
12223
|
-
${cyan4("upgrade")} Check for content updates
|
|
12149
|
+
${cyan4("upgrade")} Check for official content updates
|
|
12224
12150
|
${cyan4("help")} Show this help
|
|
12225
12151
|
|
|
12226
12152
|
${BOLD11}Examples:${RESET18}
|
|
@@ -12228,6 +12154,7 @@ ${BOLD11}Examples:${RESET18}
|
|
|
12228
12154
|
decantr scan
|
|
12229
12155
|
decantr scan --json
|
|
12230
12156
|
decantr new my-app --blueprint=carbon-ai-portal
|
|
12157
|
+
decantr new my-app --blueprint=carbon-ai-portal --adoption=decantr-css
|
|
12231
12158
|
decantr adopt --yes
|
|
12232
12159
|
decantr adopt --project apps/web --yes
|
|
12233
12160
|
decantr task /feed "add saved recipe actions"
|
|
@@ -12269,7 +12196,7 @@ ${BOLD11}Examples:${RESET18}
|
|
|
12269
12196
|
decantr studio --report decantr-health.json
|
|
12270
12197
|
decantr telemetry status
|
|
12271
12198
|
decantr telemetry explain
|
|
12272
|
-
decantr telemetry link --
|
|
12199
|
+
decantr telemetry link --api-url https://telemetry.example/v1 --api-key <key>
|
|
12273
12200
|
decantr audit
|
|
12274
12201
|
decantr audit src/pages/HomePage.tsx
|
|
12275
12202
|
decantr migrate --to v4
|
|
@@ -12280,18 +12207,16 @@ ${BOLD11}Examples:${RESET18}
|
|
|
12280
12207
|
decantr list patterns
|
|
12281
12208
|
decantr showcase shortlist
|
|
12282
12209
|
decantr showcase verification --json
|
|
12283
|
-
decantr
|
|
12284
|
-
decantr
|
|
12285
|
-
decantr
|
|
12286
|
-
decantr
|
|
12287
|
-
decantr
|
|
12288
|
-
decantr registry critique-file src/pages/Home.tsx --namespace @official --json
|
|
12289
|
-
decantr registry audit-project --namespace @official --json
|
|
12290
|
-
decantr registry audit-project --namespace @official --dist dist --sources src
|
|
12210
|
+
decantr content summary --namespace @official
|
|
12211
|
+
decantr content compile-packs decantr.essence.json --json
|
|
12212
|
+
decantr content compile-packs decantr.essence.json --write-context
|
|
12213
|
+
decantr content get-pack manifest --namespace @official --json
|
|
12214
|
+
decantr content get-pack review --namespace @official --write-context
|
|
12291
12215
|
decantr create pattern my-card
|
|
12292
12216
|
|
|
12293
12217
|
${BOLD11}Workflow Model:${RESET18}
|
|
12294
|
-
${cyan4("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=
|
|
12218
|
+
${cyan4("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=contract-only
|
|
12219
|
+
${cyan4("Legacy CSS adapter")} decantr new my-app --blueprint=X --adoption=decantr-css
|
|
12295
12220
|
${cyan4("Greenfield contract")} decantr init --workflow=greenfield --adoption=contract-only
|
|
12296
12221
|
${cyan4("Brownfield adoption")} decantr adopt --yes
|
|
12297
12222
|
${cyan4("Brownfield preview")} decantr scan -> decantr adopt --yes
|
|
@@ -12301,10 +12226,10 @@ ${BOLD11}Workflow Model:${RESET18}
|
|
|
12301
12226
|
${cyan4("Drift resolution")} decantr resolve -> codify/init/graph/repair source explicitly
|
|
12302
12227
|
${cyan4("Typed contract graph")} decantr graph -> agent session loads .decantr/graph/contract-capsule.json
|
|
12303
12228
|
${cyan4("Project-owned law")} decantr codify --from-audit -> edit proposal -> decantr codify --accept
|
|
12304
|
-
${cyan4("Hybrid composition")} decantr add/remove, decantr theme switch, decantr
|
|
12229
|
+
${cyan4("Hybrid composition")} decantr add/remove, decantr theme switch, decantr content, decantr upgrade
|
|
12305
12230
|
|
|
12306
12231
|
${BOLD11}Bootstrap adapters:${RESET18}
|
|
12307
|
-
Runnable starter adapters: ${cyan4("react-vite")}, ${cyan4("next-app")}, ${cyan4("vanilla-vite")}, ${cyan4("vue-vite")}, ${cyan4("sveltekit")}, ${cyan4("angular")}, ${cyan4("solid-vite")}
|
|
12232
|
+
Runnable starter adapters are legacy opt-in via ${cyan4("--adoption=decantr-css")}: ${cyan4("react-vite")}, ${cyan4("next-app")}, ${cyan4("vanilla-vite")}, ${cyan4("vue-vite")}, ${cyan4("sveltekit")}, ${cyan4("angular")}, ${cyan4("solid-vite")}
|
|
12308
12233
|
Unsupported targets resolve through ${cyan4("generic-web")} contract-only mode until their starter adapters land.
|
|
12309
12234
|
`);
|
|
12310
12235
|
}
|
|
@@ -12477,15 +12402,15 @@ ${BOLD11}Examples:${RESET18}
|
|
|
12477
12402
|
}
|
|
12478
12403
|
function cmdRegistryHelp() {
|
|
12479
12404
|
console.log(`
|
|
12480
|
-
${BOLD11}decantr registry${RESET18} \u2014
|
|
12405
|
+
${BOLD11}decantr registry${RESET18} \u2014 Legacy compatibility alias for content-corpus helpers
|
|
12481
12406
|
|
|
12482
12407
|
${BOLD11}Usage:${RESET18}
|
|
12483
12408
|
decantr registry summary [--namespace <namespace>] [--json]
|
|
12484
12409
|
decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
|
|
12485
12410
|
decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
|
|
12486
12411
|
decantr registry get-pack page --route <route> [--namespace <namespace>] [--json] [--essence <path>]
|
|
12487
|
-
|
|
12488
|
-
|
|
12412
|
+
|
|
12413
|
+
Prefer the equivalent decantr content commands for new scripts.
|
|
12489
12414
|
`);
|
|
12490
12415
|
}
|
|
12491
12416
|
function cmdThemeHelp() {
|
|
@@ -12534,7 +12459,7 @@ ${BOLD11}Options:${RESET18}
|
|
|
12534
12459
|
--no-verify Skip the verification step
|
|
12535
12460
|
--no-packs Skip hosted execution-pack hydration
|
|
12536
12461
|
--ci, --init-ci Install the Decantr CI gate after adoption
|
|
12537
|
-
--telemetry
|
|
12462
|
+
--telemetry Enable the local preference; delivery requires DECANTR_TELEMETRY_ENDPOINT
|
|
12538
12463
|
--merge-proposal Merge the observed proposal into an existing essence
|
|
12539
12464
|
--replace-essence Replace an existing essence with backup
|
|
12540
12465
|
|
|
@@ -12628,17 +12553,20 @@ ${BOLD11}Examples:${RESET18}
|
|
|
12628
12553
|
}
|
|
12629
12554
|
function cmdContentHelp() {
|
|
12630
12555
|
console.log(`
|
|
12631
|
-
${BOLD11}decantr content${RESET18} \u2014
|
|
12556
|
+
${BOLD11}decantr content${RESET18} \u2014 Official content-corpus namespace
|
|
12632
12557
|
|
|
12633
12558
|
${BOLD11}Usage:${RESET18}
|
|
12634
12559
|
decantr content check [content-health options]
|
|
12560
|
+
decantr content summary [--namespace <namespace>] [--json]
|
|
12561
|
+
decantr content compile-packs [path] [--namespace <namespace>] [--json] [--write-context]
|
|
12562
|
+
decantr content get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]
|
|
12635
12563
|
decantr content create <type> <name>
|
|
12636
|
-
decantr content publish <type> <name>
|
|
12637
12564
|
|
|
12638
12565
|
${BOLD11}Examples:${RESET18}
|
|
12639
12566
|
decantr content check --ci --fail-on error
|
|
12567
|
+
decantr content summary --namespace @official --json
|
|
12568
|
+
decantr content compile-packs decantr.essence.json --write-context
|
|
12640
12569
|
decantr content create pattern my-card
|
|
12641
|
-
decantr content publish pattern my-card
|
|
12642
12570
|
`);
|
|
12643
12571
|
}
|
|
12644
12572
|
function printCommandHelp(command, args) {
|
|
@@ -12715,11 +12643,11 @@ async function main() {
|
|
|
12715
12643
|
}
|
|
12716
12644
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
12717
12645
|
try {
|
|
12718
|
-
const here =
|
|
12719
|
-
const candidates = [
|
|
12646
|
+
const here = dirname8(fileURLToPath4(import.meta.url));
|
|
12647
|
+
const candidates = [join31(here, "..", "package.json"), join31(here, "..", "..", "package.json")];
|
|
12720
12648
|
for (const candidate of candidates) {
|
|
12721
|
-
if (
|
|
12722
|
-
const pkg = JSON.parse(
|
|
12649
|
+
if (existsSync28(candidate)) {
|
|
12650
|
+
const pkg = JSON.parse(readFileSync21(candidate, "utf-8"));
|
|
12723
12651
|
if (pkg.version) {
|
|
12724
12652
|
console.log(pkg.version);
|
|
12725
12653
|
return;
|
|
@@ -12916,7 +12844,7 @@ async function main() {
|
|
|
12916
12844
|
break;
|
|
12917
12845
|
}
|
|
12918
12846
|
case "upgrade": {
|
|
12919
|
-
const { cmdUpgrade } = await import("./upgrade-
|
|
12847
|
+
const { cmdUpgrade } = await import("./upgrade-5ZE4VR3R.js");
|
|
12920
12848
|
const { flags } = parseLooseArgs(args);
|
|
12921
12849
|
const workspaceInfo = resolveWorkflowProject(flags, "upgrade");
|
|
12922
12850
|
if (!workspaceInfo) break;
|
|
@@ -12931,7 +12859,7 @@ async function main() {
|
|
|
12931
12859
|
`${YELLOW13}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET18}`
|
|
12932
12860
|
);
|
|
12933
12861
|
}
|
|
12934
|
-
const { cmdHeal } = await import("./heal-
|
|
12862
|
+
const { cmdHeal } = await import("./heal-AEMYO7T2.js");
|
|
12935
12863
|
const { flags } = parseLooseArgs(args);
|
|
12936
12864
|
const workspaceInfo = resolveWorkflowProject(flags, "check");
|
|
12937
12865
|
if (!workspaceInfo) break;
|
|
@@ -12956,7 +12884,7 @@ async function main() {
|
|
|
12956
12884
|
const { flags } = parseLooseArgs(args);
|
|
12957
12885
|
const workspaceInfo = resolveWorkflowProject(flags, "health");
|
|
12958
12886
|
if (!workspaceInfo) break;
|
|
12959
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
12887
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-WZ562PRA.js");
|
|
12960
12888
|
await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
|
|
12961
12889
|
} catch (e) {
|
|
12962
12890
|
console.error(error2(e.message));
|
|
@@ -12970,7 +12898,7 @@ async function main() {
|
|
|
12970
12898
|
cmdContentHealthHelp();
|
|
12971
12899
|
break;
|
|
12972
12900
|
}
|
|
12973
|
-
const { cmdContentHealth, parseContentHealthArgs } = await import("./content-health-
|
|
12901
|
+
const { cmdContentHealth, parseContentHealthArgs } = await import("./content-health-PYGEZZOV.js");
|
|
12974
12902
|
await cmdContentHealth(process.cwd(), parseContentHealthArgs(args));
|
|
12975
12903
|
} catch (e) {
|
|
12976
12904
|
console.error(error2(e.message));
|
|
@@ -12984,7 +12912,7 @@ async function main() {
|
|
|
12984
12912
|
cmdStudioHelp();
|
|
12985
12913
|
break;
|
|
12986
12914
|
}
|
|
12987
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
12915
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-6Q2G4PTT.js");
|
|
12988
12916
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
12989
12917
|
} catch (e) {
|
|
12990
12918
|
console.error(error2(e.message));
|
|
@@ -12998,7 +12926,7 @@ async function main() {
|
|
|
12998
12926
|
cmdWorkspaceHelp();
|
|
12999
12927
|
break;
|
|
13000
12928
|
}
|
|
13001
|
-
const { cmdWorkspace } = await import("./workspace-
|
|
12929
|
+
const { cmdWorkspace } = await import("./workspace-EDP7QG7T.js");
|
|
13002
12930
|
await cmdWorkspace(process.cwd(), args);
|
|
13003
12931
|
} catch (e) {
|
|
13004
12932
|
console.error(error2(e.message));
|
|
@@ -13033,7 +12961,8 @@ async function main() {
|
|
|
13033
12961
|
break;
|
|
13034
12962
|
}
|
|
13035
12963
|
case "audit": {
|
|
13036
|
-
|
|
12964
|
+
const filePath = args[1] && !args[1].startsWith("--") ? args[1] : void 0;
|
|
12965
|
+
await cmdAudit(filePath, { json: args.includes("--json") });
|
|
13037
12966
|
break;
|
|
13038
12967
|
}
|
|
13039
12968
|
case "search": {
|
|
@@ -13283,59 +13212,12 @@ async function main() {
|
|
|
13283
13212
|
const mirrorType = typeIdx !== -1 ? args[typeIdx + 1] : void 0;
|
|
13284
13213
|
await cmdRegistryMirror(process.cwd(), { type: mirrorType });
|
|
13285
13214
|
} else if (subcommand === "summary") {
|
|
13286
|
-
|
|
13287
|
-
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
13288
|
-
const jsonOutput = args.includes("--json");
|
|
13289
|
-
await printRegistryIntelligenceSummary(namespace, jsonOutput);
|
|
13215
|
+
await cmdContentCorpusWorkflow(args, "registry");
|
|
13290
13216
|
} else if (subcommand === "compile-packs") {
|
|
13291
|
-
|
|
13292
|
-
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
13293
|
-
const jsonOutput = args.includes("--json");
|
|
13294
|
-
const writeContext = args.includes("--write-context");
|
|
13295
|
-
const essencePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
13296
|
-
await printHostedExecutionPackBundle(essencePath, namespace, jsonOutput, writeContext);
|
|
13217
|
+
await cmdContentCorpusWorkflow(args, "registry");
|
|
13297
13218
|
} else if (subcommand === "get-pack") {
|
|
13298
|
-
|
|
13299
|
-
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
13300
|
-
const jsonOutput = args.includes("--json");
|
|
13301
|
-
const writeContext = args.includes("--write-context");
|
|
13302
|
-
const essenceIdx = args.indexOf("--essence");
|
|
13303
|
-
const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
|
|
13304
|
-
const packType = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
13305
|
-
const routeIdx = args.indexOf("--route");
|
|
13306
|
-
const route = routeIdx !== -1 ? args[routeIdx + 1] : void 0;
|
|
13307
|
-
let id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
|
|
13308
|
-
if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
|
|
13309
|
-
console.error(
|
|
13310
|
-
`${RED13}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET18}`
|
|
13311
|
-
);
|
|
13312
|
-
process.exitCode = 1;
|
|
13313
|
-
break;
|
|
13314
|
-
}
|
|
13315
|
-
if (packType === "manifest") {
|
|
13316
|
-
await printHostedExecutionPackManifest(essencePath, namespace, jsonOutput, writeContext);
|
|
13317
|
-
break;
|
|
13318
|
-
}
|
|
13319
|
-
if (packType === "page" && route && !id) {
|
|
13320
|
-
const resolvedPath = essencePath ? resolveUserPath(essencePath) : join32(process.cwd(), "decantr.essence.json");
|
|
13321
|
-
id = resolvePagePackIdForRoute(resolvedPath, route);
|
|
13322
|
-
}
|
|
13323
|
-
await printHostedSelectedExecutionPack(
|
|
13324
|
-
packType,
|
|
13325
|
-
id,
|
|
13326
|
-
essencePath,
|
|
13327
|
-
namespace,
|
|
13328
|
-
jsonOutput,
|
|
13329
|
-
writeContext
|
|
13330
|
-
);
|
|
13219
|
+
await cmdContentCorpusWorkflow(args, "registry");
|
|
13331
13220
|
} else if (subcommand === "critique-file") {
|
|
13332
|
-
const namespaceIdx = args.indexOf("--namespace");
|
|
13333
|
-
const namespace = namespaceIdx !== -1 ? args[namespaceIdx + 1] : void 0;
|
|
13334
|
-
const jsonOutput = args.includes("--json");
|
|
13335
|
-
const essenceIdx = args.indexOf("--essence");
|
|
13336
|
-
const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
|
|
13337
|
-
const treatmentsIdx = args.indexOf("--treatments");
|
|
13338
|
-
const treatmentsPath = treatmentsIdx !== -1 ? args[treatmentsIdx + 1] : void 0;
|
|
13339
13221
|
const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
13340
13222
|
if (!sourcePath) {
|
|
13341
13223
|
console.error(
|
|
@@ -13344,27 +13226,18 @@ async function main() {
|
|
|
13344
13226
|
process.exitCode = 1;
|
|
13345
13227
|
break;
|
|
13346
13228
|
}
|
|
13347
|
-
|
|
13348
|
-
|
|
13349
|
-
namespace,
|
|
13350
|
-
jsonOutput,
|
|
13351
|
-
essencePath,
|
|
13352
|
-
treatmentsPath
|
|
13229
|
+
console.error(
|
|
13230
|
+
dim4("Hosted registry critique is retired; running local decantr audit instead.")
|
|
13353
13231
|
);
|
|
13232
|
+
await cmdAudit(sourcePath, { json: args.includes("--json") });
|
|
13354
13233
|
} else if (subcommand === "audit-project") {
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
const essencePath = essenceIdx !== -1 ? args[essenceIdx + 1] : void 0;
|
|
13360
|
-
const distIdx = args.indexOf("--dist");
|
|
13361
|
-
const distPath = distIdx !== -1 ? args[distIdx + 1] : void 0;
|
|
13362
|
-
const sourcesIdx = args.indexOf("--sources");
|
|
13363
|
-
const sourcesPath = sourcesIdx !== -1 ? args[sourcesIdx + 1] : void 0;
|
|
13364
|
-
await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
|
|
13234
|
+
console.error(
|
|
13235
|
+
dim4("Hosted registry project audit is retired; running local decantr audit instead.")
|
|
13236
|
+
);
|
|
13237
|
+
await cmdAudit(void 0, { json: args.includes("--json") });
|
|
13365
13238
|
} else {
|
|
13366
13239
|
console.error(
|
|
13367
|
-
`${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]
|
|
13240
|
+
`${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]${RESET18}`
|
|
13368
13241
|
);
|
|
13369
13242
|
process.exitCode = 1;
|
|
13370
13243
|
}
|
|
@@ -13515,7 +13388,7 @@ async function main() {
|
|
|
13515
13388
|
mcpOnly: flagBoolean(flags, "mcp-only"),
|
|
13516
13389
|
rulesOnly: flagBoolean(flags, "rules-only"),
|
|
13517
13390
|
routeHint,
|
|
13518
|
-
attached:
|
|
13391
|
+
attached: existsSync28(join31(workspaceInfo.appRoot, "decantr.essence.json"))
|
|
13519
13392
|
});
|
|
13520
13393
|
break;
|
|
13521
13394
|
}
|