@decantr/cli 2.1.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/dist/bin.js +2 -2
- package/dist/{chunk-DPFORHLL.js → chunk-3H3HWDJA.js} +2 -2
- package/dist/{chunk-3SULF2JT.js → chunk-FSZ6OIAC.js} +290 -127
- package/dist/{chunk-JYEEXSUX.js → chunk-IEW2QFYI.js} +53 -0
- package/dist/{chunk-LLQCXOHK.js → chunk-NBJCO4G5.js} +1 -1
- package/dist/{heal-NWQNJ6PU.js → heal-M6PRCIIF.js} +2 -2
- package/dist/{health-WJJ55W3H.js → health-EENY3BFS.js} +3 -3
- package/dist/index.js +2 -2
- package/dist/{studio-7XAXWRVN.js → studio-TBJPZZHA.js} +3 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -81,6 +81,8 @@ decantr audit
|
|
|
81
81
|
decantr check
|
|
82
82
|
decantr health --ci --fail-on error
|
|
83
83
|
decantr studio --port 4319 --host 127.0.0.1
|
|
84
|
+
decantr telemetry status
|
|
85
|
+
decantr telemetry link --enable --org <org-slug>
|
|
84
86
|
decantr content-health --ci --fail-on error
|
|
85
87
|
decantr registry summary --namespace @official --json
|
|
86
88
|
decantr showcase verification --json
|
|
@@ -124,7 +126,20 @@ decantr health --json --output decantr-health.json
|
|
|
124
126
|
decantr studio --report decantr-health.json
|
|
125
127
|
```
|
|
126
128
|
|
|
127
|
-
If the project has explicitly enabled Decantr CLI telemetry, `new --telemetry`, `init --telemetry`, `check --telemetry`, `health`, and `studio` emit only aggregate product-activation metadata such as lifecycle command outcome, status, score, finding counts, CI failure outcome, Studio usage, and remediation prompt requests. They never upload the health report, finding evidence, local paths, route names, source code, or prompt text.
|
|
129
|
+
If the project has explicitly enabled Decantr CLI telemetry, `new --telemetry`, `init --telemetry`, `analyze`, `check --telemetry`, `health`, and `studio` emit only aggregate product-activation metadata such as lifecycle command outcome, analyze counts, status, score, finding counts, CI failure outcome, Studio usage, and remediation prompt requests. They never upload the health report, finding evidence, local paths, route names, source code, package names, or prompt text.
|
|
130
|
+
|
|
131
|
+
## Opted-In Telemetry Identity
|
|
132
|
+
|
|
133
|
+
`decantr telemetry` lets users inspect and link the opaque install/project ids used by opted-in CLI telemetry. This is how customer org attribution becomes durable without collecting repository names, local paths, source code, prompts, private package slugs, emails, or secrets.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
decantr telemetry status
|
|
137
|
+
decantr telemetry status --json
|
|
138
|
+
decantr login --api-key=<key>
|
|
139
|
+
decantr telemetry link --enable --org <org-slug>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`telemetry link` calls the hosted `/v1/me/telemetry-link` endpoint with only opaque ids, optional org slug, and optional label. The API verifies org membership, writes `telemetry_identity_aliases`, clears the actor-resolution cache, audit logs the change, and emits `telemetry.identity_linked`.
|
|
128
143
|
|
|
129
144
|
## Content Health
|
|
130
145
|
|
package/dist/bin.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
collectCheckIssues
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NBJCO4G5.js";
|
|
4
4
|
import {
|
|
5
5
|
sendProjectHealthCiFailedTelemetry,
|
|
6
6
|
sendProjectHealthPromptTelemetry,
|
|
7
7
|
sendProjectHealthReportTelemetry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IEW2QFYI.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/health.ts
|
|
11
11
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -18,15 +18,18 @@ import {
|
|
|
18
18
|
import {
|
|
19
19
|
buildGuardRegistryContext,
|
|
20
20
|
createDoctrineMap,
|
|
21
|
+
getCliTelemetryIdentityStatus,
|
|
22
|
+
isOptedIn,
|
|
21
23
|
optIn,
|
|
22
24
|
scanAmbientContext,
|
|
23
25
|
scanProjectInteractions,
|
|
24
26
|
scanRoutes,
|
|
25
27
|
scanStyling,
|
|
28
|
+
sendAnalyzeCompletedTelemetry,
|
|
26
29
|
sendCliCommandTelemetry,
|
|
27
30
|
sendNewProjectCompletedTelemetry,
|
|
28
31
|
writeDoctrineMap
|
|
29
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-IEW2QFYI.js";
|
|
30
33
|
|
|
31
34
|
// src/index.ts
|
|
32
35
|
import { existsSync as existsSync26, mkdirSync as mkdirSync12, readdirSync as readdirSync6, readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "fs";
|
|
@@ -2125,7 +2128,8 @@ var RESET2 = "\x1B[0m";
|
|
|
2125
2128
|
var GREEN2 = "\x1B[32m";
|
|
2126
2129
|
var CYAN = "\x1B[36m";
|
|
2127
2130
|
var YELLOW = "\x1B[33m";
|
|
2128
|
-
function cmdAnalyze(projectRoot = process.cwd(), workspace) {
|
|
2131
|
+
async function cmdAnalyze(projectRoot = process.cwd(), workspace) {
|
|
2132
|
+
const startedAt = Date.now();
|
|
2129
2133
|
console.log(`
|
|
2130
2134
|
${BOLD}Analyzing project...${RESET2}
|
|
2131
2135
|
`);
|
|
@@ -2275,6 +2279,22 @@ ${DIM2}Written to:${RESET2} ${outputPath}`);
|
|
|
2275
2279
|
${YELLOW}Next step:${RESET2} Review ${BOLD}.decantr/brownfield-report.md${RESET2}, then run ${BOLD}decantr init --existing --accept-proposal${RESET2} to attach Decantr using the observed proposal.
|
|
2276
2280
|
`
|
|
2277
2281
|
);
|
|
2282
|
+
await sendAnalyzeCompletedTelemetry({
|
|
2283
|
+
componentCount: components.componentCount,
|
|
2284
|
+
dependencyCategoryCount: [
|
|
2285
|
+
dependencies.auth,
|
|
2286
|
+
dependencies.db,
|
|
2287
|
+
dependencies.state,
|
|
2288
|
+
dependencies.styling,
|
|
2289
|
+
dependencies.ui
|
|
2290
|
+
].filter((items) => items.length > 0).length,
|
|
2291
|
+
durationMs: Date.now() - startedAt,
|
|
2292
|
+
pageCount: components.pageCount,
|
|
2293
|
+
projectRoot,
|
|
2294
|
+
routeCount: routes.routes.length,
|
|
2295
|
+
success: true,
|
|
2296
|
+
targetFramework: project.framework
|
|
2297
|
+
});
|
|
2278
2298
|
}
|
|
2279
2299
|
|
|
2280
2300
|
// src/commands/create.ts
|
|
@@ -2948,7 +2968,7 @@ async function cmdMagic(prompt, projectRoot, options) {
|
|
|
2948
2968
|
console.log(
|
|
2949
2969
|
dim(" Running brownfield analysis instead so you can attach Decantr deliberately.\n")
|
|
2950
2970
|
);
|
|
2951
|
-
cmdAnalyze(projectRoot);
|
|
2971
|
+
await cmdAnalyze(projectRoot);
|
|
2952
2972
|
console.log(
|
|
2953
2973
|
`${BOLD2}Recommended next step:${RESET4} ${cyan("decantr init --existing --accept-proposal")}`
|
|
2954
2974
|
);
|
|
@@ -4163,28 +4183,162 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
4163
4183
|
}
|
|
4164
4184
|
}
|
|
4165
4185
|
|
|
4186
|
+
// src/commands/telemetry.ts
|
|
4187
|
+
var BOLD5 = "\x1B[1m";
|
|
4188
|
+
var CYAN6 = "\x1B[36m";
|
|
4189
|
+
var DIM11 = "\x1B[2m";
|
|
4190
|
+
var GREEN11 = "\x1B[32m";
|
|
4191
|
+
var RESET11 = "\x1B[0m";
|
|
4192
|
+
var DEFAULT_API_URL = "https://api.decantr.ai/v1";
|
|
4193
|
+
async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
4194
|
+
const subcommand = args[0] ?? "status";
|
|
4195
|
+
const options = parseTelemetryOptions(args.slice(1));
|
|
4196
|
+
if (subcommand === "--help" || subcommand === "-h" || subcommand === "help") {
|
|
4197
|
+
printTelemetryHelp();
|
|
4198
|
+
return;
|
|
4199
|
+
}
|
|
4200
|
+
if (subcommand === "status") {
|
|
4201
|
+
printTelemetryStatus(projectRoot, options);
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
if (subcommand === "link") {
|
|
4205
|
+
await linkTelemetryIdentity(projectRoot, options);
|
|
4206
|
+
return;
|
|
4207
|
+
}
|
|
4208
|
+
throw new Error(`Unknown telemetry command: ${subcommand}`);
|
|
4209
|
+
}
|
|
4210
|
+
function printTelemetryHelp() {
|
|
4211
|
+
console.log(`
|
|
4212
|
+
${BOLD5}decantr telemetry${RESET11} \u2014 Inspect and link privacy-filtered CLI telemetry identity
|
|
4213
|
+
|
|
4214
|
+
${BOLD5}Usage:${RESET11}
|
|
4215
|
+
decantr telemetry status [--json]
|
|
4216
|
+
decantr telemetry link [--enable] [--org <slug>] [--label <label>] [--api-key <key>] [--api-url <url>]
|
|
4217
|
+
|
|
4218
|
+
${BOLD5}Examples:${RESET11}
|
|
4219
|
+
decantr init --telemetry
|
|
4220
|
+
decantr telemetry status
|
|
4221
|
+
decantr login --api-key=<your-key>
|
|
4222
|
+
decantr telemetry link --org my-team --label "CI runner"
|
|
4223
|
+
`);
|
|
4224
|
+
}
|
|
4225
|
+
function printTelemetryStatus(projectRoot, options) {
|
|
4226
|
+
const status = getCliTelemetryIdentityStatus(projectRoot, { create: false });
|
|
4227
|
+
if (options.json) {
|
|
4228
|
+
console.log(JSON.stringify(status, null, 2));
|
|
4229
|
+
return;
|
|
4230
|
+
}
|
|
4231
|
+
console.log(`
|
|
4232
|
+
${BOLD5}Decantr telemetry${RESET11}`);
|
|
4233
|
+
console.log(` Enabled: ${status.enabled ? `${GREEN11}yes${RESET11}` : "no"}`);
|
|
4234
|
+
console.log(` Project: ${status.hasProjectConfig ? status.projectRoot : "not initialized"}`);
|
|
4235
|
+
console.log(` Install ID: ${status.installId ?? `${DIM11}not created yet${RESET11}`}`);
|
|
4236
|
+
console.log(` Project ID: ${status.projectId ?? `${DIM11}not created yet${RESET11}`}`);
|
|
4237
|
+
if (status.enabled) {
|
|
4238
|
+
console.log(
|
|
4239
|
+
DIM11 + "Run `decantr telemetry link` after login to attach these opaque IDs to your Decantr account/org." + RESET11
|
|
4240
|
+
);
|
|
4241
|
+
} else {
|
|
4242
|
+
console.log(DIM11 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET11);
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
async function linkTelemetryIdentity(projectRoot, options) {
|
|
4246
|
+
if (options.enable && !isOptedIn(projectRoot)) {
|
|
4247
|
+
optIn(projectRoot);
|
|
4248
|
+
}
|
|
4249
|
+
if (!isOptedIn(projectRoot)) {
|
|
4250
|
+
throw new Error("This project has not opted into telemetry. Re-run with --enable or use `decantr init --telemetry`.");
|
|
4251
|
+
}
|
|
4252
|
+
const identity = getCliTelemetryIdentityStatus(projectRoot, { create: true });
|
|
4253
|
+
if (!identity.installId && !identity.projectId) {
|
|
4254
|
+
throw new Error("No telemetry identity could be created for this project.");
|
|
4255
|
+
}
|
|
4256
|
+
const apiKey = options.apiKey ?? getApiKeyOrToken();
|
|
4257
|
+
if (!apiKey) {
|
|
4258
|
+
throw new Error("Run `decantr login --api-key=<key>` or pass `--api-key <key>` before linking telemetry.");
|
|
4259
|
+
}
|
|
4260
|
+
const apiUrl = trimTrailingSlashes(options.apiUrl ?? process.env.DECANTR_API_URL ?? DEFAULT_API_URL);
|
|
4261
|
+
const response = await fetch(`${apiUrl}/me/telemetry-link`, {
|
|
4262
|
+
method: "POST",
|
|
4263
|
+
headers: {
|
|
4264
|
+
Authorization: `Bearer ${apiKey}`,
|
|
4265
|
+
"Content-Type": "application/json"
|
|
4266
|
+
},
|
|
4267
|
+
body: JSON.stringify({
|
|
4268
|
+
install_id: identity.installId,
|
|
4269
|
+
project_id: identity.projectId,
|
|
4270
|
+
org_slug: options.org,
|
|
4271
|
+
label: options.label
|
|
4272
|
+
})
|
|
4273
|
+
});
|
|
4274
|
+
if (!response.ok) {
|
|
4275
|
+
const body2 = await response.json().catch(() => null);
|
|
4276
|
+
throw new Error(body2?.error ?? `Telemetry link failed with HTTP ${response.status}.`);
|
|
4277
|
+
}
|
|
4278
|
+
const body = await response.json().catch(() => ({ linked: 0 }));
|
|
4279
|
+
console.log(`${GREEN11}Telemetry identity linked.${RESET11}`);
|
|
4280
|
+
console.log(` Linked: ${body.linked ?? 0}`);
|
|
4281
|
+
console.log(` Install ID: ${identity.installId ?? `${DIM11}none${RESET11}`}`);
|
|
4282
|
+
console.log(` Project ID: ${identity.projectId ?? `${DIM11}none${RESET11}`}`);
|
|
4283
|
+
if (options.org) console.log(` Org: ${CYAN6}${options.org}${RESET11}`);
|
|
4284
|
+
console.log(DIM11 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET11);
|
|
4285
|
+
}
|
|
4286
|
+
function parseTelemetryOptions(args) {
|
|
4287
|
+
const options = {};
|
|
4288
|
+
for (let i = 0; i < args.length; i++) {
|
|
4289
|
+
const arg = args[i];
|
|
4290
|
+
if (arg === "--enable") {
|
|
4291
|
+
options.enable = true;
|
|
4292
|
+
} else if (arg === "--json") {
|
|
4293
|
+
options.json = true;
|
|
4294
|
+
} else if (arg === "--org" && args[i + 1]) {
|
|
4295
|
+
options.org = args[++i];
|
|
4296
|
+
} else if (arg.startsWith("--org=")) {
|
|
4297
|
+
options.org = arg.slice("--org=".length);
|
|
4298
|
+
} else if (arg === "--label" && args[i + 1]) {
|
|
4299
|
+
options.label = args[++i];
|
|
4300
|
+
} else if (arg.startsWith("--label=")) {
|
|
4301
|
+
options.label = arg.slice("--label=".length);
|
|
4302
|
+
} else if (arg === "--api-key" && args[i + 1]) {
|
|
4303
|
+
options.apiKey = args[++i];
|
|
4304
|
+
} else if (arg.startsWith("--api-key=")) {
|
|
4305
|
+
options.apiKey = arg.slice("--api-key=".length);
|
|
4306
|
+
} else if (arg === "--api-url" && args[i + 1]) {
|
|
4307
|
+
options.apiUrl = args[++i];
|
|
4308
|
+
} else if (arg.startsWith("--api-url=")) {
|
|
4309
|
+
options.apiUrl = arg.slice("--api-url=".length);
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
return options;
|
|
4313
|
+
}
|
|
4314
|
+
function trimTrailingSlashes(value) {
|
|
4315
|
+
let end = value.length;
|
|
4316
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;
|
|
4317
|
+
return value.slice(0, end);
|
|
4318
|
+
}
|
|
4319
|
+
|
|
4166
4320
|
// src/commands/theme-switch.ts
|
|
4167
4321
|
import { existsSync as existsSync23, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "fs";
|
|
4168
4322
|
import { join as join24 } from "path";
|
|
4169
4323
|
import { isV4 as isV46 } from "@decantr/essence-spec";
|
|
4170
|
-
var
|
|
4324
|
+
var GREEN12 = "\x1B[32m";
|
|
4171
4325
|
var RED10 = "\x1B[31m";
|
|
4172
4326
|
var YELLOW7 = "\x1B[33m";
|
|
4173
|
-
var
|
|
4174
|
-
var
|
|
4327
|
+
var DIM12 = "\x1B[2m";
|
|
4328
|
+
var RESET12 = "\x1B[0m";
|
|
4175
4329
|
var VALID_THEME_SHAPES = ["sharp", "rounded", "pill"];
|
|
4176
4330
|
var VALID_THEME_MODES = ["light", "dark", "auto"];
|
|
4177
4331
|
async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
4178
4332
|
if (!themeName) {
|
|
4179
4333
|
console.error(
|
|
4180
|
-
`${RED10}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${
|
|
4334
|
+
`${RED10}Usage: decantr theme switch <themeName> [--shape <s>] [--mode <m>]${RESET12}`
|
|
4181
4335
|
);
|
|
4182
4336
|
process.exitCode = 1;
|
|
4183
4337
|
return;
|
|
4184
4338
|
}
|
|
4185
4339
|
const essencePath = join24(projectRoot, "decantr.essence.json");
|
|
4186
4340
|
if (!existsSync23(essencePath)) {
|
|
4187
|
-
console.error(`${RED10}No decantr.essence.json found. Run \`decantr init\` first.${
|
|
4341
|
+
console.error(`${RED10}No decantr.essence.json found. Run \`decantr init\` first.${RESET12}`);
|
|
4188
4342
|
process.exitCode = 1;
|
|
4189
4343
|
return;
|
|
4190
4344
|
}
|
|
@@ -4192,13 +4346,13 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
4192
4346
|
try {
|
|
4193
4347
|
parsed = JSON.parse(readFileSync16(essencePath, "utf-8"));
|
|
4194
4348
|
} catch (e) {
|
|
4195
|
-
console.error(`${RED10}Could not read essence: ${e.message}${
|
|
4349
|
+
console.error(`${RED10}Could not read essence: ${e.message}${RESET12}`);
|
|
4196
4350
|
process.exitCode = 1;
|
|
4197
4351
|
return;
|
|
4198
4352
|
}
|
|
4199
4353
|
if (!isV46(parsed)) {
|
|
4200
4354
|
console.error(
|
|
4201
|
-
`${RED10}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${
|
|
4355
|
+
`${RED10}Active workflows require Essence v4.0.0. Run \`decantr migrate --to v4\` first.${RESET12}`
|
|
4202
4356
|
);
|
|
4203
4357
|
process.exitCode = 1;
|
|
4204
4358
|
return;
|
|
@@ -4220,14 +4374,14 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
4220
4374
|
}
|
|
4221
4375
|
if (shape && !VALID_THEME_SHAPES.includes(shape)) {
|
|
4222
4376
|
console.error(
|
|
4223
|
-
`${RED10}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${
|
|
4377
|
+
`${RED10}Invalid shape "${shape}". Must be one of: ${VALID_THEME_SHAPES.join(", ")}.${RESET12}`
|
|
4224
4378
|
);
|
|
4225
4379
|
process.exitCode = 1;
|
|
4226
4380
|
return;
|
|
4227
4381
|
}
|
|
4228
4382
|
if (mode && !VALID_THEME_MODES.includes(mode)) {
|
|
4229
4383
|
console.error(
|
|
4230
|
-
`${RED10}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${
|
|
4384
|
+
`${RED10}Invalid mode "${mode}". Must be one of: ${VALID_THEME_MODES.join(", ")}.${RESET12}`
|
|
4231
4385
|
);
|
|
4232
4386
|
process.exitCode = 1;
|
|
4233
4387
|
return;
|
|
@@ -4257,27 +4411,27 @@ async function cmdThemeSwitch(themeName, args, projectRoot = process.cwd()) {
|
|
|
4257
4411
|
} catch {
|
|
4258
4412
|
}
|
|
4259
4413
|
writeFileSync13(essencePath, JSON.stringify(essence, null, 2) + "\n");
|
|
4260
|
-
console.log(`${
|
|
4261
|
-
if (shape) console.log(` ${
|
|
4262
|
-
if (mode) console.log(` ${
|
|
4414
|
+
console.log(`${GREEN12}Switched theme: ${oldThemeId} \u2192 ${themeName}${RESET12}`);
|
|
4415
|
+
if (shape) console.log(` ${DIM12}Shape: ${shape}${RESET12}`);
|
|
4416
|
+
if (mode) console.log(` ${DIM12}Mode: ${mode}${RESET12}`);
|
|
4263
4417
|
await refreshDerivedFiles(projectRoot, essence, registryClient);
|
|
4264
4418
|
console.log(
|
|
4265
|
-
`${
|
|
4419
|
+
`${GREEN12}Derived files refreshed (tokens.css, treatments.css, all contexts).${RESET12}`
|
|
4266
4420
|
);
|
|
4267
|
-
console.log(`${YELLOW7}Guard will flag code using old tokens. Run \`decantr check\`.${
|
|
4421
|
+
console.log(`${YELLOW7}Guard will flag code using old tokens. Run \`decantr check\`.${RESET12}`);
|
|
4268
4422
|
}
|
|
4269
4423
|
|
|
4270
4424
|
// src/prompts.ts
|
|
4271
4425
|
import { createInterface } from "readline";
|
|
4272
|
-
var
|
|
4273
|
-
var
|
|
4274
|
-
var
|
|
4275
|
-
var
|
|
4426
|
+
var BOLD6 = "\x1B[1m";
|
|
4427
|
+
var DIM13 = "\x1B[2m";
|
|
4428
|
+
var RESET13 = "\x1B[0m";
|
|
4429
|
+
var GREEN13 = "\x1B[32m";
|
|
4276
4430
|
var YELLOW8 = "\x1B[33m";
|
|
4277
|
-
var
|
|
4431
|
+
var CYAN7 = "\x1B[36m";
|
|
4278
4432
|
function ask(question, defaultValue) {
|
|
4279
4433
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
4280
|
-
const prompt = defaultValue ? `${question} ${
|
|
4434
|
+
const prompt = defaultValue ? `${question} ${DIM13}(${defaultValue})${RESET13}: ` : `${question}: `;
|
|
4281
4435
|
return new Promise((resolve5) => {
|
|
4282
4436
|
rl.question(prompt, (answer) => {
|
|
4283
4437
|
rl.close();
|
|
@@ -4287,14 +4441,14 @@ function ask(question, defaultValue) {
|
|
|
4287
4441
|
}
|
|
4288
4442
|
async function select(question, options, defaultIdx = 0, allowOther = false) {
|
|
4289
4443
|
console.log(`
|
|
4290
|
-
${
|
|
4444
|
+
${BOLD6}${question}${RESET13}`);
|
|
4291
4445
|
for (let i = 0; i < options.length; i++) {
|
|
4292
|
-
const marker = i === defaultIdx ? `${
|
|
4293
|
-
const desc = options[i].description ? ` ${
|
|
4446
|
+
const marker = i === defaultIdx ? `${GREEN13}>${RESET13}` : " ";
|
|
4447
|
+
const desc = options[i].description ? ` ${DIM13}\u2014 ${options[i].description}${RESET13}` : "";
|
|
4294
4448
|
console.log(` ${marker} ${i + 1}. ${options[i].label}${desc}`);
|
|
4295
4449
|
}
|
|
4296
4450
|
if (allowOther) {
|
|
4297
|
-
console.log(` ${options.length + 1}. ${
|
|
4451
|
+
console.log(` ${options.length + 1}. ${DIM13}other (enter custom value)${RESET13}`);
|
|
4298
4452
|
}
|
|
4299
4453
|
const maxIdx = allowOther ? options.length + 1 : options.length;
|
|
4300
4454
|
const answer = await ask(`Choose (1-${maxIdx})`, String(defaultIdx + 1));
|
|
@@ -4313,11 +4467,11 @@ async function confirm(question, defaultYes = true) {
|
|
|
4313
4467
|
}
|
|
4314
4468
|
function warn(message) {
|
|
4315
4469
|
console.log(`
|
|
4316
|
-
${YELLOW8} Warning: ${message}${
|
|
4470
|
+
${YELLOW8} Warning: ${message}${RESET13}`);
|
|
4317
4471
|
}
|
|
4318
4472
|
function showDetection(detected) {
|
|
4319
4473
|
console.log(`
|
|
4320
|
-
${
|
|
4474
|
+
${CYAN7}Detected project configuration:${RESET13}`);
|
|
4321
4475
|
if (detected.framework !== "unknown") {
|
|
4322
4476
|
const version = detected.version ? ` ${detected.version}` : "";
|
|
4323
4477
|
console.log(` Framework: ${detected.framework}${version}`);
|
|
@@ -4326,13 +4480,13 @@ ${CYAN6}Detected project configuration:${RESET12}`);
|
|
|
4326
4480
|
console.log(` Package manager: ${detected.packageManager}`);
|
|
4327
4481
|
}
|
|
4328
4482
|
if (detected.hasTypeScript) {
|
|
4329
|
-
console.log(` TypeScript: ${
|
|
4483
|
+
console.log(` TypeScript: ${GREEN13}yes${RESET13}`);
|
|
4330
4484
|
}
|
|
4331
4485
|
if (detected.hasTailwind) {
|
|
4332
|
-
console.log(` Tailwind CSS: ${
|
|
4486
|
+
console.log(` Tailwind CSS: ${GREEN13}yes${RESET13}`);
|
|
4333
4487
|
}
|
|
4334
4488
|
if (detected.existingEssence) {
|
|
4335
|
-
console.log(` Existing essence: ${YELLOW8}yes${
|
|
4489
|
+
console.log(` Existing essence: ${YELLOW8}yes${RESET13}`);
|
|
4336
4490
|
}
|
|
4337
4491
|
}
|
|
4338
4492
|
async function runInteractivePrompts(detected, archetypes, blueprints, themes, workflowSeed) {
|
|
@@ -4406,7 +4560,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes, w
|
|
|
4406
4560
|
warn(`This project appears to be ${detected.framework} but you selected ${target}.`);
|
|
4407
4561
|
const proceed = await confirm("Continue anyway?", false);
|
|
4408
4562
|
if (!proceed) {
|
|
4409
|
-
console.log(`${
|
|
4563
|
+
console.log(`${DIM13}Using detected framework: ${detected.framework}${RESET13}`);
|
|
4410
4564
|
}
|
|
4411
4565
|
}
|
|
4412
4566
|
const guardMode = await select(
|
|
@@ -4797,29 +4951,29 @@ function resolveWorkspaceInfo(cwd, projectArg) {
|
|
|
4797
4951
|
}
|
|
4798
4952
|
|
|
4799
4953
|
// src/index.ts
|
|
4800
|
-
var
|
|
4801
|
-
var
|
|
4802
|
-
var
|
|
4954
|
+
var BOLD7 = "\x1B[1m";
|
|
4955
|
+
var DIM14 = "\x1B[2m";
|
|
4956
|
+
var RESET14 = "\x1B[0m";
|
|
4803
4957
|
var RED11 = "\x1B[31m";
|
|
4804
|
-
var
|
|
4805
|
-
var
|
|
4958
|
+
var GREEN14 = "\x1B[32m";
|
|
4959
|
+
var CYAN8 = "\x1B[36m";
|
|
4806
4960
|
var YELLOW9 = "\x1B[33m";
|
|
4807
4961
|
function heading2(text) {
|
|
4808
4962
|
return `
|
|
4809
|
-
${
|
|
4963
|
+
${BOLD7}${text}${RESET14}
|
|
4810
4964
|
`;
|
|
4811
4965
|
}
|
|
4812
4966
|
function success3(text) {
|
|
4813
|
-
return `${
|
|
4967
|
+
return `${GREEN14}${text}${RESET14}`;
|
|
4814
4968
|
}
|
|
4815
4969
|
function error3(text) {
|
|
4816
|
-
return `${RED11}${text}${
|
|
4970
|
+
return `${RED11}${text}${RESET14}`;
|
|
4817
4971
|
}
|
|
4818
4972
|
function dim3(text) {
|
|
4819
|
-
return `${
|
|
4973
|
+
return `${DIM14}${text}${RESET14}`;
|
|
4820
4974
|
}
|
|
4821
4975
|
function cyan3(text) {
|
|
4822
|
-
return `${
|
|
4976
|
+
return `${CYAN8}${text}${RESET14}`;
|
|
4823
4977
|
}
|
|
4824
4978
|
function formatIntelligenceSummary(intelligence) {
|
|
4825
4979
|
if (!intelligence) {
|
|
@@ -5542,7 +5696,7 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
|
|
|
5542
5696
|
console.log(` Files written: ${writtenContextPaths.length}`);
|
|
5543
5697
|
}
|
|
5544
5698
|
console.log("");
|
|
5545
|
-
console.log(`${
|
|
5699
|
+
console.log(`${BOLD7}Route Plan:${RESET14}`);
|
|
5546
5700
|
for (const route of typedBundle.scaffold.data.routes) {
|
|
5547
5701
|
const patterns = route.patternIds.length > 0 ? route.patternIds.join(", ") : "none";
|
|
5548
5702
|
const pageLabel = route.sectionId ? `${route.sectionId}/${route.pageId}` : route.pageId;
|
|
@@ -5781,7 +5935,7 @@ async function cmdSearch(query, type, sort, recommended, intelligenceSource) {
|
|
|
5781
5935
|
}
|
|
5782
5936
|
console.log(heading2(`${results.length} result(s) for "${query}"`));
|
|
5783
5937
|
for (const r of results) {
|
|
5784
|
-
console.log(` ${cyan3(r.type.padEnd(12))} ${
|
|
5938
|
+
console.log(` ${cyan3(r.type.padEnd(12))} ${BOLD7}${r.slug}${RESET14}`);
|
|
5785
5939
|
console.log(` ${dim3(r.description || "")}`);
|
|
5786
5940
|
const intelligenceSummary = formatIntelligenceSummary(r.intelligence);
|
|
5787
5941
|
if (intelligenceSummary) {
|
|
@@ -5812,14 +5966,14 @@ async function cmdSuggest(query, type) {
|
|
|
5812
5966
|
const exact = results.filter((r) => r.slug.toLowerCase().includes(queryLower));
|
|
5813
5967
|
const related = results.filter((r) => !r.slug.toLowerCase().includes(queryLower));
|
|
5814
5968
|
if (exact.length > 0) {
|
|
5815
|
-
console.log(`${
|
|
5969
|
+
console.log(`${BOLD7}Direct matches:${RESET14}`);
|
|
5816
5970
|
for (const r of exact.slice(0, 3)) {
|
|
5817
5971
|
console.log(` ${cyan3(r.slug)} - ${r.description || ""}`);
|
|
5818
5972
|
}
|
|
5819
5973
|
console.log("");
|
|
5820
5974
|
}
|
|
5821
5975
|
if (related.length > 0) {
|
|
5822
|
-
console.log(`${
|
|
5976
|
+
console.log(`${BOLD7}Related:${RESET14}`);
|
|
5823
5977
|
for (const r of related.slice(0, 5)) {
|
|
5824
5978
|
console.log(` ${cyan3(r.slug)} - ${r.description || ""}`);
|
|
5825
5979
|
}
|
|
@@ -5883,14 +6037,14 @@ async function cmdValidate(path) {
|
|
|
5883
6037
|
return;
|
|
5884
6038
|
}
|
|
5885
6039
|
const detectedVersion = isV47(essence) ? "v4" : "legacy";
|
|
5886
|
-
console.log(`${
|
|
6040
|
+
console.log(`${DIM14}Detected essence version: ${detectedVersion}${RESET14}`);
|
|
5887
6041
|
const result = validateEssence2(essence);
|
|
5888
6042
|
if (result.valid) {
|
|
5889
6043
|
console.log(success3(`Essence is valid (${detectedVersion}).`));
|
|
5890
6044
|
} else {
|
|
5891
6045
|
console.error(error3("Validation failed:"));
|
|
5892
6046
|
for (const err of result.errors) {
|
|
5893
|
-
console.error(` ${RED11}${err}${
|
|
6047
|
+
console.error(` ${RED11}${err}${RESET14}`);
|
|
5894
6048
|
}
|
|
5895
6049
|
process.exitCode = 1;
|
|
5896
6050
|
return;
|
|
@@ -5911,9 +6065,9 @@ async function cmdValidate(path) {
|
|
|
5911
6065
|
console.log(heading2("Guard violations:"));
|
|
5912
6066
|
for (const v of violations) {
|
|
5913
6067
|
const vr = v;
|
|
5914
|
-
console.log(` ${YELLOW9}[${vr.rule}]${
|
|
6068
|
+
console.log(` ${YELLOW9}[${vr.rule}]${RESET14} ${vr.message}`);
|
|
5915
6069
|
if (vr.suggestion) {
|
|
5916
|
-
console.log(` ${
|
|
6070
|
+
console.log(` ${DIM14}Suggestion: ${vr.suggestion}${RESET14}`);
|
|
5917
6071
|
}
|
|
5918
6072
|
}
|
|
5919
6073
|
const hasError = violations.some((v) => v.severity === "error");
|
|
@@ -5985,9 +6139,9 @@ function enableCliTelemetry(projectRoot) {
|
|
|
5985
6139
|
optIn(projectRoot);
|
|
5986
6140
|
console.log(
|
|
5987
6141
|
`
|
|
5988
|
-
${
|
|
6142
|
+
${CYAN8}Telemetry enabled.${RESET14} Decantr will send privacy-filtered CLI product telemetry for this project.`
|
|
5989
6143
|
);
|
|
5990
|
-
console.log(`${
|
|
6144
|
+
console.log(`${DIM14}Set "telemetry": false in .decantr/project.json to opt out.${RESET14}`);
|
|
5991
6145
|
}
|
|
5992
6146
|
function readCliPackageVersion() {
|
|
5993
6147
|
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
@@ -6109,7 +6263,7 @@ async function applyAcceptedBrownfieldProposal(input) {
|
|
|
6109
6263
|
error3("Brownfield proposal produced an invalid Decantr essence. No files were changed.")
|
|
6110
6264
|
);
|
|
6111
6265
|
for (const validationError of validation.errors) {
|
|
6112
|
-
console.log(` ${RED11}${validationError}${
|
|
6266
|
+
console.log(` ${RED11}${validationError}${RESET14}`);
|
|
6113
6267
|
}
|
|
6114
6268
|
process.exitCode = 1;
|
|
6115
6269
|
return;
|
|
@@ -6200,7 +6354,7 @@ async function cmdInit(args) {
|
|
|
6200
6354
|
console.log(dim3(" Found .decantr/init-seed.json brownfield guidance."));
|
|
6201
6355
|
}
|
|
6202
6356
|
if (detected.existingEssence && !args.existing) {
|
|
6203
|
-
console.log(`${YELLOW9}Warning: decantr.essence.json already exists.${
|
|
6357
|
+
console.log(`${YELLOW9}Warning: decantr.essence.json already exists.${RESET14}`);
|
|
6204
6358
|
const overwrite = await confirm("Overwrite existing configuration?", false);
|
|
6205
6359
|
if (!overwrite) {
|
|
6206
6360
|
console.log(dim3("Cancelled."));
|
|
@@ -6302,7 +6456,7 @@ async function cmdInit(args) {
|
|
|
6302
6456
|
} else if (shouldUseRegistry && !apiAvailable) {
|
|
6303
6457
|
if (!args.blueprint) {
|
|
6304
6458
|
console.log(`
|
|
6305
|
-
${YELLOW9}You're offline. Scaffolding minimal Decantr project.${
|
|
6459
|
+
${YELLOW9}You're offline. Scaffolding minimal Decantr project.${RESET14}`);
|
|
6306
6460
|
console.log(
|
|
6307
6461
|
dim3("Run `decantr sync` or `decantr upgrade` when online to pull full registry content.\n")
|
|
6308
6462
|
);
|
|
@@ -6350,7 +6504,7 @@ ${YELLOW9}You're offline. Scaffolding minimal Decantr project.${RESET13}`);
|
|
|
6350
6504
|
return;
|
|
6351
6505
|
}
|
|
6352
6506
|
console.log(`
|
|
6353
|
-
${YELLOW9}You're offline. Scaffolding Decantr default.${
|
|
6507
|
+
${YELLOW9}You're offline. Scaffolding Decantr default.${RESET14}`);
|
|
6354
6508
|
console.log(dim3("Run `decantr upgrade` when online, or visit decantr.ai/registry\n"));
|
|
6355
6509
|
selectedBlueprint = "default";
|
|
6356
6510
|
} else if (shouldUseRegistry) {
|
|
@@ -6531,7 +6685,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
6531
6685
|
return;
|
|
6532
6686
|
}
|
|
6533
6687
|
console.log(
|
|
6534
|
-
`${YELLOW9} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${
|
|
6688
|
+
`${YELLOW9} Warning: Could not fetch blueprint "${options.blueprint}". Using defaults.${RESET14}`
|
|
6535
6689
|
);
|
|
6536
6690
|
}
|
|
6537
6691
|
} else if (shouldUseRegistry && options.archetype) {
|
|
@@ -6546,7 +6700,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
6546
6700
|
return;
|
|
6547
6701
|
}
|
|
6548
6702
|
console.log(
|
|
6549
|
-
`${YELLOW9} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${
|
|
6703
|
+
`${YELLOW9} Warning: Could not fetch archetype "${options.archetype}". Using defaults.${RESET14}`
|
|
6550
6704
|
);
|
|
6551
6705
|
}
|
|
6552
6706
|
}
|
|
@@ -6563,7 +6717,7 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET13}`);
|
|
|
6563
6717
|
return;
|
|
6564
6718
|
}
|
|
6565
6719
|
console.log(
|
|
6566
|
-
`${YELLOW9} Warning: Could not fetch theme "${options.theme}". Using defaults.${
|
|
6720
|
+
`${YELLOW9} Warning: Could not fetch theme "${options.theme}". Using defaults.${RESET14}`
|
|
6567
6721
|
);
|
|
6568
6722
|
}
|
|
6569
6723
|
}
|
|
@@ -6689,7 +6843,7 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
6689
6843
|
};
|
|
6690
6844
|
const curatedPrompt = generateCuratedPrompt(promptCtx);
|
|
6691
6845
|
console.log("");
|
|
6692
|
-
console.log(`${
|
|
6846
|
+
console.log(`${BOLD7}Prompt for your AI assistant:${RESET14}`);
|
|
6693
6847
|
console.log(dim3("\u2500".repeat(50)));
|
|
6694
6848
|
console.log("");
|
|
6695
6849
|
console.log(curatedPrompt);
|
|
@@ -6706,7 +6860,7 @@ async function cmdStatus() {
|
|
|
6706
6860
|
const projectJsonPath = join27(projectRoot, ".decantr", "project.json");
|
|
6707
6861
|
console.log(heading2("Decantr Project Status"));
|
|
6708
6862
|
if (!existsSync26(essencePath)) {
|
|
6709
|
-
console.log(`${RED11}No decantr.essence.json found.${
|
|
6863
|
+
console.log(`${RED11}No decantr.essence.json found.${RESET14}`);
|
|
6710
6864
|
console.log(dim3('Run "decantr init" to create one.'));
|
|
6711
6865
|
return;
|
|
6712
6866
|
}
|
|
@@ -6714,11 +6868,11 @@ async function cmdStatus() {
|
|
|
6714
6868
|
const essence = JSON.parse(readFileSync19(essencePath, "utf-8"));
|
|
6715
6869
|
const validation = validateEssence2(essence);
|
|
6716
6870
|
const essenceVersion = isV47(essence) ? "v4" : "legacy";
|
|
6717
|
-
console.log(`${
|
|
6871
|
+
console.log(`${BOLD7}Essence:${RESET14}`);
|
|
6718
6872
|
if (validation.valid) {
|
|
6719
|
-
console.log(` ${
|
|
6873
|
+
console.log(` ${GREEN14}Valid${RESET14} (${essenceVersion})`);
|
|
6720
6874
|
} else {
|
|
6721
|
-
console.log(` ${RED11}Invalid: ${validation.errors.join(", ")}${
|
|
6875
|
+
console.log(` ${RED11}Invalid: ${validation.errors.join(", ")}${RESET14}`);
|
|
6722
6876
|
}
|
|
6723
6877
|
if (isV47(essence)) {
|
|
6724
6878
|
const v4 = essence;
|
|
@@ -6726,7 +6880,7 @@ async function cmdStatus() {
|
|
|
6726
6880
|
const flatPages = sections.flatMap((section) => section.pages ?? []);
|
|
6727
6881
|
const resolvedShell = sections.find((section) => section.role === "primary")?.shell || sections[0]?.shell || v4.blueprint.shell || "unknown";
|
|
6728
6882
|
const resolvedFeatures = v4.blueprint.features ?? [];
|
|
6729
|
-
console.log(` ${
|
|
6883
|
+
console.log(` ${BOLD7}DNA:${RESET14}`);
|
|
6730
6884
|
console.log(` Theme: ${v4.dna.theme.id} (${v4.dna.theme.mode})`);
|
|
6731
6885
|
console.log(
|
|
6732
6886
|
` Spacing: ${v4.dna.spacing.density} density, ${v4.dna.spacing.content_gap} gap`
|
|
@@ -6738,42 +6892,42 @@ async function cmdStatus() {
|
|
|
6738
6892
|
);
|
|
6739
6893
|
console.log(` Accessibility: WCAG ${v4.dna.accessibility.wcag_level}`);
|
|
6740
6894
|
console.log(` Personality: ${v4.dna.personality.join(", ")}`);
|
|
6741
|
-
console.log(` ${
|
|
6895
|
+
console.log(` ${BOLD7}Blueprint:${RESET14}`);
|
|
6742
6896
|
console.log(` Shell: ${resolvedShell}`);
|
|
6743
6897
|
console.log(` Pages: ${flatPages.length}`);
|
|
6744
6898
|
console.log(` Sections: ${sections.length}`);
|
|
6745
6899
|
console.log(
|
|
6746
6900
|
` Features: ${resolvedFeatures.length > 0 ? resolvedFeatures.join(", ") : "none"}`
|
|
6747
6901
|
);
|
|
6748
|
-
console.log(` ${
|
|
6902
|
+
console.log(` ${BOLD7}Meta:${RESET14}`);
|
|
6749
6903
|
console.log(` Archetype: ${v4.meta.archetype}`);
|
|
6750
6904
|
console.log(` Target: ${v4.meta.target}`);
|
|
6751
6905
|
console.log(
|
|
6752
6906
|
` Guard: ${v4.meta.guard.mode} (DNA: ${v4.meta.guard.dna_enforcement}, Blueprint: ${v4.meta.guard.blueprint_enforcement})`
|
|
6753
6907
|
);
|
|
6754
6908
|
} else {
|
|
6755
|
-
console.log(` ${YELLOW9}Run \`decantr migrate --to v4\` to upgrade this project.${
|
|
6909
|
+
console.log(` ${YELLOW9}Run \`decantr migrate --to v4\` to upgrade this project.${RESET14}`);
|
|
6756
6910
|
}
|
|
6757
6911
|
} catch (e) {
|
|
6758
|
-
console.log(` ${RED11}Error reading essence: ${e.message}${
|
|
6912
|
+
console.log(` ${RED11}Error reading essence: ${e.message}${RESET14}`);
|
|
6759
6913
|
}
|
|
6760
6914
|
console.log("");
|
|
6761
|
-
console.log(`${
|
|
6915
|
+
console.log(`${BOLD7}Sync Status:${RESET14}`);
|
|
6762
6916
|
if (existsSync26(projectJsonPath)) {
|
|
6763
6917
|
try {
|
|
6764
6918
|
const projectJson = JSON.parse(readFileSync19(projectJsonPath, "utf-8"));
|
|
6765
6919
|
const syncStatus = projectJson.sync?.status || "unknown";
|
|
6766
6920
|
const lastSync = projectJson.sync?.lastSync || "never";
|
|
6767
6921
|
const source = projectJson.sync?.registrySource || "unknown";
|
|
6768
|
-
const statusColor = syncStatus === "synced" ?
|
|
6769
|
-
console.log(` Status: ${statusColor}${syncStatus}${
|
|
6922
|
+
const statusColor = syncStatus === "synced" ? GREEN14 : YELLOW9;
|
|
6923
|
+
console.log(` Status: ${statusColor}${syncStatus}${RESET14}`);
|
|
6770
6924
|
console.log(` Last sync: ${dim3(lastSync)}`);
|
|
6771
6925
|
console.log(` Source: ${dim3(source)}`);
|
|
6772
6926
|
} catch {
|
|
6773
|
-
console.log(` ${YELLOW9}Could not read project.json${
|
|
6927
|
+
console.log(` ${YELLOW9}Could not read project.json${RESET14}`);
|
|
6774
6928
|
}
|
|
6775
6929
|
} else {
|
|
6776
|
-
console.log(` ${YELLOW9}No .decantr/project.json found${
|
|
6930
|
+
console.log(` ${YELLOW9}No .decantr/project.json found${RESET14}`);
|
|
6777
6931
|
console.log(dim3(' Run "decantr init" to create project files.'));
|
|
6778
6932
|
}
|
|
6779
6933
|
}
|
|
@@ -6786,12 +6940,12 @@ async function cmdSync() {
|
|
|
6786
6940
|
console.log(success3("Sync completed successfully."));
|
|
6787
6941
|
console.log(` Synced: ${result.synced.join(", ")}`);
|
|
6788
6942
|
if (result.failed.length > 0) {
|
|
6789
|
-
console.log(` ${YELLOW9}Failed: ${result.failed.join(", ")}${
|
|
6943
|
+
console.log(` ${YELLOW9}Failed: ${result.failed.join(", ")}${RESET14}`);
|
|
6790
6944
|
}
|
|
6791
6945
|
} else {
|
|
6792
|
-
console.log(`${YELLOW9}Could not sync: API unavailable${
|
|
6946
|
+
console.log(`${YELLOW9}Could not sync: API unavailable${RESET14}`);
|
|
6793
6947
|
if (result.failed.length > 0) {
|
|
6794
|
-
console.log(` ${YELLOW9}Failed: ${result.failed.join(", ")}${
|
|
6948
|
+
console.log(` ${YELLOW9}Failed: ${result.failed.join(", ")}${RESET14}`);
|
|
6795
6949
|
}
|
|
6796
6950
|
}
|
|
6797
6951
|
}
|
|
@@ -6801,15 +6955,15 @@ function printVerificationFindings(findings) {
|
|
|
6801
6955
|
return;
|
|
6802
6956
|
}
|
|
6803
6957
|
for (const finding of findings) {
|
|
6804
|
-
const color = finding.severity === "error" ? RED11 : finding.severity === "warn" ? YELLOW9 :
|
|
6958
|
+
const color = finding.severity === "error" ? RED11 : finding.severity === "warn" ? YELLOW9 : CYAN8;
|
|
6805
6959
|
console.log(
|
|
6806
|
-
` ${color}[${finding.severity.toUpperCase()}]${
|
|
6960
|
+
` ${color}[${finding.severity.toUpperCase()}]${RESET14} ${finding.category}: ${finding.message}`
|
|
6807
6961
|
);
|
|
6808
6962
|
for (const evidence of finding.evidence) {
|
|
6809
|
-
console.log(` ${
|
|
6963
|
+
console.log(` ${DIM14}${evidence}${RESET14}`);
|
|
6810
6964
|
}
|
|
6811
6965
|
if (finding.suggestedFix) {
|
|
6812
|
-
console.log(` ${
|
|
6966
|
+
console.log(` ${DIM14}Fix: ${finding.suggestedFix}${RESET14}`);
|
|
6813
6967
|
}
|
|
6814
6968
|
}
|
|
6815
6969
|
}
|
|
@@ -6817,10 +6971,10 @@ function printProjectAuditReport(report) {
|
|
|
6817
6971
|
if (report.valid) {
|
|
6818
6972
|
console.log(success3("Project contract is valid."));
|
|
6819
6973
|
} else {
|
|
6820
|
-
console.log(`${RED11}Project audit found blocking issues.${
|
|
6974
|
+
console.log(`${RED11}Project audit found blocking issues.${RESET14}`);
|
|
6821
6975
|
}
|
|
6822
6976
|
console.log("");
|
|
6823
|
-
console.log(`${
|
|
6977
|
+
console.log(`${BOLD7}Summary:${RESET14}`);
|
|
6824
6978
|
console.log(` Essence version: ${report.summary.essenceVersion ?? "missing"}`);
|
|
6825
6979
|
console.log(` Pages defined: ${report.summary.pageCount}`);
|
|
6826
6980
|
console.log(` Pack manifest: ${report.summary.packManifestPresent ? "present" : "missing"}`);
|
|
@@ -6849,23 +7003,23 @@ function printProjectAuditReport(report) {
|
|
|
6849
7003
|
` Findings: ${report.summary.errorCount} error(s), ${report.summary.warnCount} warn(s), ${report.summary.infoCount} info`
|
|
6850
7004
|
);
|
|
6851
7005
|
console.log("");
|
|
6852
|
-
console.log(`${
|
|
7006
|
+
console.log(`${BOLD7}Findings:${RESET14}`);
|
|
6853
7007
|
printVerificationFindings(report.findings);
|
|
6854
7008
|
}
|
|
6855
7009
|
function printFileCritiqueReport(report) {
|
|
6856
7010
|
console.log(success3(`Critiqued ${report.file}`));
|
|
6857
7011
|
console.log("");
|
|
6858
|
-
console.log(`${
|
|
7012
|
+
console.log(`${BOLD7}Summary:${RESET14}`);
|
|
6859
7013
|
console.log(` Overall score: ${report.overall}/5`);
|
|
6860
7014
|
console.log(` Focus areas: ${report.focusAreas.join(", ")}`);
|
|
6861
7015
|
console.log(` Review pack: ${report.reviewPack ? "present" : "missing"}`);
|
|
6862
7016
|
console.log("");
|
|
6863
|
-
console.log(`${
|
|
7017
|
+
console.log(`${BOLD7}Scores:${RESET14}`);
|
|
6864
7018
|
for (const score of report.scores) {
|
|
6865
7019
|
console.log(` ${cyan3(score.category.padEnd(20))} ${score.score}/5 ${dim3(score.details)}`);
|
|
6866
7020
|
}
|
|
6867
7021
|
console.log("");
|
|
6868
|
-
console.log(`${
|
|
7022
|
+
console.log(`${BOLD7}Findings:${RESET14}`);
|
|
6869
7023
|
printVerificationFindings(report.findings);
|
|
6870
7024
|
}
|
|
6871
7025
|
async function cmdAudit(filePath) {
|
|
@@ -6906,7 +7060,7 @@ async function cmdAudit(filePath) {
|
|
|
6906
7060
|
console.log(dim3("Project audit completed with advisory findings."));
|
|
6907
7061
|
}
|
|
6908
7062
|
} catch (e) {
|
|
6909
|
-
console.log(`${RED11}Error: ${e.message}${
|
|
7063
|
+
console.log(`${RED11}Error: ${e.message}${RESET14}`);
|
|
6910
7064
|
process.exitCode = 1;
|
|
6911
7065
|
}
|
|
6912
7066
|
}
|
|
@@ -6915,9 +7069,9 @@ async function cmdTheme(args) {
|
|
|
6915
7069
|
const projectRoot = process.cwd();
|
|
6916
7070
|
if (!subcommand || subcommand === "help") {
|
|
6917
7071
|
console.log(`
|
|
6918
|
-
${
|
|
7072
|
+
${BOLD7}decantr theme${RESET14} \u2014 Manage custom themes
|
|
6919
7073
|
|
|
6920
|
-
${
|
|
7074
|
+
${BOLD7}Commands:${RESET14}
|
|
6921
7075
|
${cyan3("create")} <name> Create a new custom theme
|
|
6922
7076
|
${cyan3("create")} <name> --guided Interactive theme creation
|
|
6923
7077
|
${cyan3("list")} List custom themes
|
|
@@ -6925,7 +7079,7 @@ ${BOLD6}Commands:${RESET13}
|
|
|
6925
7079
|
${cyan3("delete")} <name> Delete a custom theme
|
|
6926
7080
|
${cyan3("import")} <path> Import theme from JSON file
|
|
6927
7081
|
|
|
6928
|
-
${
|
|
7082
|
+
${BOLD7}Examples:${RESET14}
|
|
6929
7083
|
decantr theme create mytheme
|
|
6930
7084
|
decantr theme list
|
|
6931
7085
|
decantr theme validate mytheme
|
|
@@ -6988,7 +7142,7 @@ ${BOLD6}Examples:${RESET13}
|
|
|
6988
7142
|
} else {
|
|
6989
7143
|
console.error(error3("Validation failed:"));
|
|
6990
7144
|
for (const err of result.errors) {
|
|
6991
|
-
console.error(` ${RED11}${err}${
|
|
7145
|
+
console.error(` ${RED11}${err}${RESET14}`);
|
|
6992
7146
|
}
|
|
6993
7147
|
process.exitCode = 1;
|
|
6994
7148
|
}
|
|
@@ -7028,7 +7182,7 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7028
7182
|
} else {
|
|
7029
7183
|
console.error(error3("Import failed:"));
|
|
7030
7184
|
for (const err of result.errors || []) {
|
|
7031
|
-
console.error(` ${RED11}${err}${
|
|
7185
|
+
console.error(` ${RED11}${err}${RESET14}`);
|
|
7032
7186
|
}
|
|
7033
7187
|
process.exitCode = 1;
|
|
7034
7188
|
}
|
|
@@ -7051,9 +7205,9 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7051
7205
|
}
|
|
7052
7206
|
function cmdHelp() {
|
|
7053
7207
|
console.log(`
|
|
7054
|
-
${
|
|
7208
|
+
${BOLD7}decantr${RESET14} \u2014 Design intelligence for AI-generated UI
|
|
7055
7209
|
|
|
7056
|
-
${
|
|
7210
|
+
${BOLD7}Usage:${RESET14}
|
|
7057
7211
|
decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
|
|
7058
7212
|
decantr magic <prompt> [--dry-run]
|
|
7059
7213
|
decantr init [options]
|
|
@@ -7078,6 +7232,8 @@ ${BOLD6}Usage:${RESET13}
|
|
|
7078
7232
|
decantr health init-ci [--force] [--project <path>] [--fail-on <error|warn|none>] [--cli-version <version|latest>]
|
|
7079
7233
|
decantr content-health [--json] [--markdown] [--ci]
|
|
7080
7234
|
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
|
|
7235
|
+
decantr telemetry status [--json]
|
|
7236
|
+
decantr telemetry link [--enable] [--org <slug>]
|
|
7081
7237
|
decantr rules preview [--project=<path>]
|
|
7082
7238
|
decantr rules apply [--project=<path>]
|
|
7083
7239
|
decantr validate [path]
|
|
@@ -7089,7 +7245,7 @@ ${BOLD6}Usage:${RESET13}
|
|
|
7089
7245
|
decantr logout
|
|
7090
7246
|
decantr help
|
|
7091
7247
|
|
|
7092
|
-
${
|
|
7248
|
+
${BOLD7}Init Options:${RESET14}
|
|
7093
7249
|
--blueprint, -b Blueprint ID
|
|
7094
7250
|
--theme Theme ID
|
|
7095
7251
|
--mode Color mode: dark | light | auto
|
|
@@ -7111,7 +7267,7 @@ ${BOLD6}Init Options:${RESET13}
|
|
|
7111
7267
|
--registry Custom registry URL
|
|
7112
7268
|
--telemetry Opt this project into privacy-filtered CLI product telemetry
|
|
7113
7269
|
|
|
7114
|
-
${
|
|
7270
|
+
${BOLD7}Commands:${RESET14}
|
|
7115
7271
|
${cyan3("new")} Create a new greenfield workspace and bootstrap the available starter adapter
|
|
7116
7272
|
${cyan3("magic")} Greenfield-first intent flow; steers existing apps into analyze + init
|
|
7117
7273
|
${cyan3("init")} Attach Decantr contract/context files to an existing project or empty workspace
|
|
@@ -7136,13 +7292,14 @@ ${BOLD6}Commands:${RESET13}
|
|
|
7136
7292
|
${cyan3("login")} Authenticate with the Decantr registry
|
|
7137
7293
|
${cyan3("logout")} Remove stored credentials
|
|
7138
7294
|
${cyan3("analyze")} Brownfield entrypoint: scan an existing project and emit attach guidance
|
|
7295
|
+
${cyan3("telemetry")} Inspect or link this project's opted-in CLI telemetry identity
|
|
7139
7296
|
${cyan3("export")} Export design tokens to framework format (shadcn, tailwind, css-vars)
|
|
7140
7297
|
${cyan3("registry")} Registry management and intelligence summary
|
|
7141
7298
|
${cyan3("rules")} Preview/apply Decantr assistant bridge blocks to repo rule files
|
|
7142
7299
|
${cyan3("upgrade")} Check for content updates from registry
|
|
7143
7300
|
${cyan3("help")} Show this help
|
|
7144
7301
|
|
|
7145
|
-
${
|
|
7302
|
+
${BOLD7}Examples:${RESET14}
|
|
7146
7303
|
decantr new my-app --blueprint=carbon-ai-portal
|
|
7147
7304
|
decantr magic "AI chatbot with dark cyber theme \u2014 bold and futuristic"
|
|
7148
7305
|
decantr init
|
|
@@ -7162,6 +7319,8 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7162
7319
|
decantr content-health --ci --fail-on error
|
|
7163
7320
|
decantr studio
|
|
7164
7321
|
decantr studio --report decantr-health.json
|
|
7322
|
+
decantr telemetry status
|
|
7323
|
+
decantr telemetry link --enable --org my-team
|
|
7165
7324
|
decantr audit
|
|
7166
7325
|
decantr audit src/pages/HomePage.tsx
|
|
7167
7326
|
decantr migrate --to v4
|
|
@@ -7182,30 +7341,30 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7182
7341
|
decantr registry audit-project --namespace @official --dist dist --sources src
|
|
7183
7342
|
decantr create pattern my-card
|
|
7184
7343
|
|
|
7185
|
-
${
|
|
7344
|
+
${BOLD7}Workflow Model:${RESET14}
|
|
7186
7345
|
${cyan3("Greenfield blueprint")} decantr new my-app --blueprint=X --workflow=greenfield --adoption=decantr-css
|
|
7187
7346
|
${cyan3("Greenfield contract")} decantr init --workflow=greenfield --adoption=contract-only
|
|
7188
7347
|
${cyan3("Brownfield adoption")} decantr analyze -> decantr init --existing --accept-proposal -> decantr check --brownfield
|
|
7189
7348
|
${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
|
|
7190
7349
|
|
|
7191
|
-
${
|
|
7350
|
+
${BOLD7}Bootstrap adapters:${RESET14}
|
|
7192
7351
|
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}
|
|
7193
7352
|
Unsupported targets resolve through ${cyan3("generic-web")} contract-only mode until their starter adapters land.
|
|
7194
7353
|
`);
|
|
7195
7354
|
}
|
|
7196
7355
|
function cmdRulesHelp() {
|
|
7197
7356
|
console.log(`
|
|
7198
|
-
${
|
|
7357
|
+
${BOLD7}decantr rules${RESET14} \u2014 Preview or apply assistant bridge snippets
|
|
7199
7358
|
|
|
7200
|
-
${
|
|
7359
|
+
${BOLD7}Usage:${RESET14}
|
|
7201
7360
|
decantr rules preview [--project=<path>]
|
|
7202
7361
|
decantr rules apply [--project=<path>]
|
|
7203
7362
|
|
|
7204
|
-
${
|
|
7363
|
+
${BOLD7}Subcommands:${RESET14}
|
|
7205
7364
|
${cyan3("preview")} Print target-specific Decantr bridge guidance without mutating rule files
|
|
7206
7365
|
${cyan3("apply")} Idempotently write Decantr bridge blocks to supported assistant rule files
|
|
7207
7366
|
|
|
7208
|
-
${
|
|
7367
|
+
${BOLD7}Examples:${RESET14}
|
|
7209
7368
|
decantr rules preview
|
|
7210
7369
|
decantr rules preview --project=apps/web
|
|
7211
7370
|
decantr rules apply --project=apps/web
|
|
@@ -7216,9 +7375,9 @@ function isCommandHelpRequest(args) {
|
|
|
7216
7375
|
}
|
|
7217
7376
|
function cmdHealthHelp() {
|
|
7218
7377
|
console.log(`
|
|
7219
|
-
${
|
|
7378
|
+
${BOLD7}decantr health${RESET14} \u2014 Generate a local Project Health report
|
|
7220
7379
|
|
|
7221
|
-
${
|
|
7380
|
+
${BOLD7}Usage:${RESET14}
|
|
7222
7381
|
decantr health [--format text|json|markdown] [--output <file>]
|
|
7223
7382
|
decantr health --json
|
|
7224
7383
|
decantr health --markdown
|
|
@@ -7226,7 +7385,7 @@ ${BOLD6}Usage:${RESET13}
|
|
|
7226
7385
|
decantr health --prompt <finding-id>
|
|
7227
7386
|
decantr health init-ci [--force] [--project <path>] [--fail-on error|warn|none] [--cli-version <version|latest>]
|
|
7228
7387
|
|
|
7229
|
-
${
|
|
7388
|
+
${BOLD7}Options:${RESET14}
|
|
7230
7389
|
--format Output format: text, json, or markdown
|
|
7231
7390
|
--json Emit JSON report
|
|
7232
7391
|
--markdown Emit markdown report
|
|
@@ -7235,7 +7394,7 @@ ${BOLD6}Options:${RESET13}
|
|
|
7235
7394
|
--fail-on CI threshold: error, warn, or none
|
|
7236
7395
|
--prompt Print an AI-ready remediation prompt for a finding
|
|
7237
7396
|
|
|
7238
|
-
${
|
|
7397
|
+
${BOLD7}Examples:${RESET14}
|
|
7239
7398
|
decantr health
|
|
7240
7399
|
decantr health --json
|
|
7241
7400
|
decantr health --markdown --output decantr-health.md
|
|
@@ -7246,16 +7405,16 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7246
7405
|
}
|
|
7247
7406
|
function cmdContentHealthHelp() {
|
|
7248
7407
|
console.log(`
|
|
7249
|
-
${
|
|
7408
|
+
${BOLD7}decantr content-health${RESET14} \u2014 Generate a local registry content health report
|
|
7250
7409
|
|
|
7251
|
-
${
|
|
7410
|
+
${BOLD7}Usage:${RESET14}
|
|
7252
7411
|
decantr content-health [--format text|json|markdown] [--output <file>]
|
|
7253
7412
|
decantr content-health --json
|
|
7254
7413
|
decantr content-health --markdown
|
|
7255
7414
|
decantr content-health --ci [--fail-on error|warn|none]
|
|
7256
7415
|
decantr content-health --prompt <finding-id>
|
|
7257
7416
|
|
|
7258
|
-
${
|
|
7417
|
+
${BOLD7}Options:${RESET14}
|
|
7259
7418
|
--format Output format: text, json, or markdown
|
|
7260
7419
|
--json Emit JSON report
|
|
7261
7420
|
--markdown Emit markdown report
|
|
@@ -7264,7 +7423,7 @@ ${BOLD6}Options:${RESET13}
|
|
|
7264
7423
|
--fail-on CI threshold: error, warn, or none
|
|
7265
7424
|
--prompt Print an AI-ready remediation prompt for a finding
|
|
7266
7425
|
|
|
7267
|
-
${
|
|
7426
|
+
${BOLD7}Examples:${RESET14}
|
|
7268
7427
|
decantr content-health
|
|
7269
7428
|
decantr content-health --json
|
|
7270
7429
|
decantr content-health --markdown --output content-health.md
|
|
@@ -7273,22 +7432,22 @@ ${BOLD6}Examples:${RESET13}
|
|
|
7273
7432
|
}
|
|
7274
7433
|
function cmdStudioHelp() {
|
|
7275
7434
|
console.log(`
|
|
7276
|
-
${
|
|
7435
|
+
${BOLD7}decantr studio${RESET14} \u2014 Run a local Project Health dashboard
|
|
7277
7436
|
|
|
7278
|
-
${
|
|
7437
|
+
${BOLD7}Usage:${RESET14}
|
|
7279
7438
|
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
|
|
7280
7439
|
|
|
7281
|
-
${
|
|
7440
|
+
${BOLD7}Options:${RESET14}
|
|
7282
7441
|
--port Local port to bind; defaults to 4319
|
|
7283
7442
|
--host Local host to bind; defaults to 127.0.0.1
|
|
7284
7443
|
--report Serve a read-only Project Health JSON artifact instead of scanning the current project
|
|
7285
7444
|
|
|
7286
|
-
${
|
|
7445
|
+
${BOLD7}Endpoints:${RESET14}
|
|
7287
7446
|
GET /
|
|
7288
7447
|
GET /api/health
|
|
7289
7448
|
POST /api/refresh
|
|
7290
7449
|
|
|
7291
|
-
${
|
|
7450
|
+
${BOLD7}Examples:${RESET14}
|
|
7292
7451
|
decantr studio
|
|
7293
7452
|
decantr studio --port 4320
|
|
7294
7453
|
decantr studio --host 127.0.0.1 --port 4319
|
|
@@ -7418,10 +7577,10 @@ async function main() {
|
|
|
7418
7577
|
case "heal": {
|
|
7419
7578
|
if (command === "heal") {
|
|
7420
7579
|
console.log(
|
|
7421
|
-
`${YELLOW9}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${
|
|
7580
|
+
`${YELLOW9}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET14}`
|
|
7422
7581
|
);
|
|
7423
7582
|
}
|
|
7424
|
-
const { cmdHeal } = await import("./heal-
|
|
7583
|
+
const { cmdHeal } = await import("./heal-M6PRCIIF.js");
|
|
7425
7584
|
const telemetryFlag = args.includes("--telemetry");
|
|
7426
7585
|
const brownfieldFlag = args.includes("--brownfield");
|
|
7427
7586
|
await cmdHeal(process.cwd(), { telemetry: telemetryFlag, brownfield: brownfieldFlag });
|
|
@@ -7433,7 +7592,7 @@ async function main() {
|
|
|
7433
7592
|
cmdHealthHelp();
|
|
7434
7593
|
break;
|
|
7435
7594
|
}
|
|
7436
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
7595
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-EENY3BFS.js");
|
|
7437
7596
|
await cmdHealth(process.cwd(), parseHealthArgs(args));
|
|
7438
7597
|
} catch (e) {
|
|
7439
7598
|
console.error(error3(e.message));
|
|
@@ -7461,7 +7620,7 @@ async function main() {
|
|
|
7461
7620
|
cmdStudioHelp();
|
|
7462
7621
|
break;
|
|
7463
7622
|
}
|
|
7464
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
7623
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-TBJPZZHA.js");
|
|
7465
7624
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
7466
7625
|
} catch (e) {
|
|
7467
7626
|
console.error(error3(e.message));
|
|
@@ -7634,6 +7793,10 @@ async function main() {
|
|
|
7634
7793
|
console.log(success3("Logged out. Credentials removed."));
|
|
7635
7794
|
break;
|
|
7636
7795
|
}
|
|
7796
|
+
case "telemetry": {
|
|
7797
|
+
await cmdTelemetry(args.slice(1), process.cwd());
|
|
7798
|
+
break;
|
|
7799
|
+
}
|
|
7637
7800
|
case "create": {
|
|
7638
7801
|
const type = args[1];
|
|
7639
7802
|
const name = args[2];
|
|
@@ -7692,7 +7855,7 @@ async function main() {
|
|
|
7692
7855
|
const id = args[3] && !args[3].startsWith("--") ? args[3] : void 0;
|
|
7693
7856
|
if (!packType || !["manifest", "scaffold", "review", "section", "page", "mutation"].includes(packType)) {
|
|
7694
7857
|
console.error(
|
|
7695
|
-
`${RED11}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${
|
|
7858
|
+
`${RED11}Usage: decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context]${RESET14}`
|
|
7696
7859
|
);
|
|
7697
7860
|
process.exitCode = 1;
|
|
7698
7861
|
break;
|
|
@@ -7720,7 +7883,7 @@ async function main() {
|
|
|
7720
7883
|
const sourcePath = args[2] && !args[2].startsWith("--") ? args[2] : void 0;
|
|
7721
7884
|
if (!sourcePath) {
|
|
7722
7885
|
console.error(
|
|
7723
|
-
`${RED11}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${
|
|
7886
|
+
`${RED11}Usage: decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]${RESET14}`
|
|
7724
7887
|
);
|
|
7725
7888
|
process.exitCode = 1;
|
|
7726
7889
|
break;
|
|
@@ -7745,7 +7908,7 @@ async function main() {
|
|
|
7745
7908
|
await printHostedProjectAudit(namespace, jsonOutput, essencePath, distPath, sourcesPath);
|
|
7746
7909
|
} else {
|
|
7747
7910
|
console.error(
|
|
7748
|
-
`${RED11}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${
|
|
7911
|
+
`${RED11}Usage: decantr registry mirror [--type <type>] | decantr registry summary [--namespace <namespace>] [--json] | decantr registry compile-packs [path] [--namespace <namespace>] [--json] [--write-context] | decantr registry get-pack <manifest|scaffold|review|section|page|mutation> [id] [--namespace <namespace>] [--json] [--essence <path>] [--write-context] | decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>] | decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]${RESET14}`
|
|
7749
7912
|
);
|
|
7750
7913
|
process.exitCode = 1;
|
|
7751
7914
|
}
|
|
@@ -7861,7 +8024,7 @@ async function main() {
|
|
|
7861
8024
|
process.exitCode = 1;
|
|
7862
8025
|
break;
|
|
7863
8026
|
}
|
|
7864
|
-
cmdAnalyze(workspaceInfo.appRoot, workspaceInfo);
|
|
8027
|
+
await cmdAnalyze(workspaceInfo.appRoot, workspaceInfo);
|
|
7865
8028
|
break;
|
|
7866
8029
|
}
|
|
7867
8030
|
case "rules": {
|
|
@@ -7925,7 +8088,7 @@ async function main() {
|
|
|
7925
8088
|
console.error("");
|
|
7926
8089
|
console.error(" Example:");
|
|
7927
8090
|
console.error(
|
|
7928
|
-
` ${
|
|
8091
|
+
` ${CYAN8}decantr magic "AI agent dashboard \u2014 dark, neon, confident"${RESET14}`
|
|
7929
8092
|
);
|
|
7930
8093
|
process.exitCode = 1;
|
|
7931
8094
|
break;
|
|
@@ -134,6 +134,30 @@ async function sendProjectHealthReportTelemetry(input) {
|
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
async function sendAnalyzeCompletedTelemetry(input) {
|
|
138
|
+
const projectRoot = input.projectRoot ?? process.cwd();
|
|
139
|
+
const metadata = readProjectTelemetryMetadata(projectRoot);
|
|
140
|
+
const properties = {
|
|
141
|
+
command: "analyze",
|
|
142
|
+
success: input.success,
|
|
143
|
+
durationMs: input.durationMs,
|
|
144
|
+
adoptionMode: metadata.adoptionMode ?? "contract-only",
|
|
145
|
+
componentCount: input.componentCount,
|
|
146
|
+
dependencyCategoryCount: input.dependencyCategoryCount,
|
|
147
|
+
errorCode: input.success ? void 0 : "analyze_failed",
|
|
148
|
+
pageCount: input.pageCount,
|
|
149
|
+
projectScope: metadata.projectScope ?? inferProjectScope(projectRoot),
|
|
150
|
+
routeCount: input.routeCount,
|
|
151
|
+
targetFramework: input.targetFramework,
|
|
152
|
+
workflowMode: metadata.workflowMode ?? "brownfield-attach"
|
|
153
|
+
};
|
|
154
|
+
await captureCliTelemetryEvent({
|
|
155
|
+
args: ["analyze"],
|
|
156
|
+
name: "decantr.analyze.completed",
|
|
157
|
+
projectRoot,
|
|
158
|
+
properties
|
|
159
|
+
});
|
|
160
|
+
}
|
|
137
161
|
async function sendNewProjectCompletedTelemetry(input) {
|
|
138
162
|
const projectRoot = input.projectRoot ?? process.cwd();
|
|
139
163
|
const args = input.args ?? ["new"];
|
|
@@ -303,6 +327,19 @@ function collectMetrics(essence, issues) {
|
|
|
303
327
|
theme: theme.id ?? "unknown"
|
|
304
328
|
};
|
|
305
329
|
}
|
|
330
|
+
function getCliTelemetryIdentityStatus(projectRoot, options = {}) {
|
|
331
|
+
const projectJsonPath = join(projectRoot, ".decantr", "project.json");
|
|
332
|
+
const hasProjectConfig = existsSync(projectJsonPath);
|
|
333
|
+
const identities = options.create ? ensureTelemetryIdentities(projectRoot) : null;
|
|
334
|
+
const projectData = readProjectJson(projectRoot);
|
|
335
|
+
return {
|
|
336
|
+
enabled: projectData?.telemetry === true,
|
|
337
|
+
hasProjectConfig,
|
|
338
|
+
installId: identities?.installId ?? readExistingInstallId(),
|
|
339
|
+
projectId: identities?.projectId ?? readStringProperty(projectData, "telemetryProjectId"),
|
|
340
|
+
projectRoot
|
|
341
|
+
};
|
|
342
|
+
}
|
|
306
343
|
function ensureTelemetryIdentities(projectRoot) {
|
|
307
344
|
const installId = getOrCreateInstallId();
|
|
308
345
|
const projectJsonPath = join(projectRoot, ".decantr", "project.json");
|
|
@@ -348,6 +385,16 @@ function getOrCreateInstallId() {
|
|
|
348
385
|
return `install_${randomUUID()}`;
|
|
349
386
|
}
|
|
350
387
|
}
|
|
388
|
+
function readExistingInstallId() {
|
|
389
|
+
const configPath = join(getConfigDir(), "config.json");
|
|
390
|
+
if (!existsSync(configPath)) return void 0;
|
|
391
|
+
try {
|
|
392
|
+
const data = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
393
|
+
return readStringProperty(data, "telemetryInstallId");
|
|
394
|
+
} catch {
|
|
395
|
+
return void 0;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
351
398
|
function getConfigDir() {
|
|
352
399
|
return process.env.DECANTR_CONFIG_DIR || join(homedir(), ".config", "decantr");
|
|
353
400
|
}
|
|
@@ -386,6 +433,10 @@ function readProjectJson(projectRoot) {
|
|
|
386
433
|
return null;
|
|
387
434
|
}
|
|
388
435
|
}
|
|
436
|
+
function readStringProperty(value, key) {
|
|
437
|
+
const property = value?.[key];
|
|
438
|
+
return typeof property === "string" && property.trim() ? property : void 0;
|
|
439
|
+
}
|
|
389
440
|
function isRecord(value) {
|
|
390
441
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
391
442
|
}
|
|
@@ -1650,12 +1701,14 @@ export {
|
|
|
1650
1701
|
optIn,
|
|
1651
1702
|
sendCliCommandTelemetry,
|
|
1652
1703
|
sendProjectHealthReportTelemetry,
|
|
1704
|
+
sendAnalyzeCompletedTelemetry,
|
|
1653
1705
|
sendNewProjectCompletedTelemetry,
|
|
1654
1706
|
sendProjectHealthPromptTelemetry,
|
|
1655
1707
|
sendProjectHealthCiFailedTelemetry,
|
|
1656
1708
|
sendStudioStartedTelemetry,
|
|
1657
1709
|
sendStudioHealthRefreshedTelemetry,
|
|
1658
1710
|
collectMetrics,
|
|
1711
|
+
getCliTelemetryIdentityStatus,
|
|
1659
1712
|
buildGuardRegistryContext,
|
|
1660
1713
|
scanProjectInteractions
|
|
1661
1714
|
};
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
renderProjectHealthCiWorkflow,
|
|
9
9
|
shouldFailHealth,
|
|
10
10
|
writeProjectHealthCiWorkflow
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-3H3HWDJA.js";
|
|
12
|
+
import "./chunk-NBJCO4G5.js";
|
|
13
|
+
import "./chunk-IEW2QFYI.js";
|
|
14
14
|
export {
|
|
15
15
|
cmdHealth,
|
|
16
16
|
createProjectHealthReport,
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-FSZ6OIAC.js";
|
|
2
2
|
import "./chunk-WDA4SHIQ.js";
|
|
3
|
-
import "./chunk-
|
|
3
|
+
import "./chunk-IEW2QFYI.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createProjectHealthReport
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-3H3HWDJA.js";
|
|
4
|
+
import "./chunk-NBJCO4G5.js";
|
|
5
5
|
import {
|
|
6
6
|
sendStudioHealthRefreshedTelemetry,
|
|
7
7
|
sendStudioStartedTelemetry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IEW2QFYI.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/studio.ts
|
|
11
11
|
import { readFileSync } from "fs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Decantr CLI - scaffold, audit, inspect Project Health, and maintain Decantr projects from the terminal",
|
|
5
5
|
"author": "Decantr AI",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"ajv": "^8.20.0",
|
|
34
34
|
"@decantr/core": "2.0.0",
|
|
35
|
-
"@decantr/
|
|
35
|
+
"@decantr/telemetry": "2.2.0",
|
|
36
36
|
"@decantr/registry": "2.0.0",
|
|
37
37
|
"@decantr/verifier": "2.0.0",
|
|
38
|
-
"@decantr/
|
|
38
|
+
"@decantr/essence-spec": "2.0.1"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsup",
|