@decantr/cli 3.8.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 +9 -9
- package/dist/bin.js +5 -5
- package/dist/{chunk-24JR4ZNG.js → chunk-2UC6YYVZ.js} +25 -11
- package/dist/{chunk-VULJMJJP.js → chunk-CI2R5W36.js} +112 -78
- package/dist/{chunk-IP2CCX2W.js → chunk-JK3DYOHA.js} +47 -32
- package/dist/{chunk-WAGVDMJV.js → chunk-PFFNEN7L.js} +19 -19
- package/dist/{chunk-56HUEUO3.js → chunk-W242I6CS.js} +1 -1
- package/dist/{content-health-TDV4LP2C.js → content-health-PYGEZZOV.js} +2 -2
- 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-NN7NTA4L.js → upgrade-5ZE4VR3R.js} +1 -1
- package/dist/{workspace-QAZ3F4VT.js → workspace-EDP7QG7T.js} +3 -3
- package/package.json +7 -7
- package/src/bundled/blueprints/default.json +1 -1
- package/src/templates/DECANTR.md.template +1 -1
package/README.md
CHANGED
|
@@ -21,8 +21,8 @@ npx @decantr/cli new my-app --blueprint=esports-hq
|
|
|
21
21
|
Use `decantr setup` when you are unsure which path applies. It detects whether the repo is empty, already attached, or a Brownfield app and recommends the right entry path.
|
|
22
22
|
Use `decantr scan` when you want a zero-commit Brownfield preview. It reads local files through the shared verifier discovery substrate, detects workspace/app scope, package manager, framework, language, route signals, taskable routes, component inventory confidence, styling/static-hosting/assistant-rule signals, previews typed Contract graph readiness in memory when a Decantr contract already exists, reports the contract capsule source-handle count and limit, prints a terminal report, and writes no `.decantr` files or report artifacts. Add `--json` when automation needs the `ScanReportV2` payload.
|
|
23
23
|
Use `decantr new` for a greenfield workspace in a fresh directory. With a blueprint or archetype it creates a contract-only Decantr workspace by default; runnable legacy Decantr CSS adapters require explicit `--adoption=decantr-css`.
|
|
24
|
-
Use `decantr adopt` when you already have an app and want Decantr governance without adopting a blueprint. Brownfield attach is proposal-driven: Decantr inventories the app, writes an observed essence proposal, hydrates
|
|
25
|
-
Use `decantr studio` after adoption when you want a local Control Room for routes, findings, evidence, authority, and next actions. Use `decantr connect cursor` when the opened workspace should get Cursor Agent MCP and project-rule activation; in monorepos use `decantr connect cursor --project apps/web` so the rule keeps the app scope. Use `decantr doctor` when the next step is unclear, `decantr task <route> "<intent>"` before asking an LLM to modify a route, `decantr verify` after the edit, `decantr resolve` when source and contract disagree, and `decantr ci` in required automation. If runtime source and Decantr context disagree, report the drift instead of guessing; in Brownfield the existing source is observed truth, accepted local law/style bridge is project authority where present, Essence V4 is the structural contract, and
|
|
24
|
+
Use `decantr adopt` when you already have an app and want Decantr governance without adopting a blueprint. Brownfield attach is proposal-driven: Decantr inventories the app, writes an observed essence proposal, hydrates content API execution packs when online, and only applies the contract when you explicitly accept or merge it.
|
|
25
|
+
Use `decantr studio` after adoption when you want a local Control Room for routes, findings, evidence, authority, and next actions. Use `decantr connect cursor` when the opened workspace should get Cursor Agent MCP and project-rule activation; in monorepos use `decantr connect cursor --project apps/web` so the rule keeps the app scope. Use `decantr doctor` when the next step is unclear, `decantr task <route> "<intent>"` before asking an LLM to modify a route, `decantr verify` after the edit, `decantr resolve` when source and contract disagree, and `decantr ci` in required automation. If runtime source and Decantr context disagree, report the drift instead of guessing; in Brownfield the existing source is observed truth, accepted local law/style bridge is project authority where present, Essence V4 is the structural contract, and content packs stay advisory until mapped into local law. Use `decantr graph` when you want the Decantr 3 typed Contract graph, typed graph diff summary, manifest, content-addressed snapshot history, and cache-friendly contract capsule written under `.decantr/graph`; the capsule includes a bounded SourceArtifact path index so agents can discover valid file-impact handles without reading the full snapshot, and `--capsule-source-limit <count>` can tune that index for large repos. Add `--route /feed --task "improve loading" --json` when you want the exact task-ranked route-scoped subgraph an agent should inspect before editing, `--node cmp:button --impact --json` when you need the graph-shaped blast radius for a component, token, rule, finding, or source artifact, or `--file src/app/page.tsx --impact --json` when the agent knows the source file it is about to change. Route and impact ranking use deterministic weighted traversal plus local personalized PageRank and task boosts. Use `--snapshot-id <id>` to inspect a replayable history snapshot and `--compare-to <id> --include-diff-ops --json` to compare the selected/current graph against a prior snapshot. Use `decantr codify --from-audit --style-bridge` when you want project-owned UI patterns, optional `behavior_obligations`, local rules, and token/class bridge mappings such as button/card/shell/theme standards to appear in future task context and verification. Once accepted, that local law is the first Hybrid lane: the app still owns source and styling, but Decantr treats accepted local patterns, behavior obligations, rules, and style bridge mappings as project authority.
|
|
26
26
|
In monorepos, app-scoped commands accept `--project <app-path>`. `setup` shows attach guidance before adoption and the day-two loop after adoption. Candidate discovery ranks product UI apps ahead of docs, Storybook, API, MCP helper, workbench, and package surfaces; `decantr workspace list --json` includes rank, category, score, and reason metadata so automation can explain why `apps/web`, `apps/remix`, or `apps/dashboard` was suggested first. Once an app path is selected, scan/setup/adopt/doctor/task/verify/ci/connect preserve that app scope and inherit package-manager evidence from the workspace root, so a React app inside a pnpm Angular/React monorepo is reported as the React app, not the root or sibling app. Content pack hydration also follows the essence path: `decantr content compile-packs apps/web/decantr.essence.json --write-context` writes into `apps/web/.decantr/context`. In contract-only/offline Brownfield, deferred packs are optional context unless a present manifest references missing files.
|
|
27
27
|
Use `decantr init`, `decantr analyze`, `decantr check`, and `decantr health` as advanced primitives when you need direct control over one step.
|
|
28
28
|
|
|
@@ -166,7 +166,7 @@ decantr check
|
|
|
166
166
|
decantr studio --port 4319 --host 127.0.0.1
|
|
167
167
|
decantr telemetry status
|
|
168
168
|
decantr telemetry explain
|
|
169
|
-
decantr telemetry link --
|
|
169
|
+
decantr telemetry link --api-url https://telemetry.example/v1 --api-key <key>
|
|
170
170
|
decantr content check --ci --fail-on error
|
|
171
171
|
decantr content summary --namespace @official --json
|
|
172
172
|
decantr list blueprints --blueprint-set featured
|
|
@@ -259,22 +259,22 @@ decantr health --json --output decantr-health.json
|
|
|
259
259
|
decantr studio --report decantr-health.json
|
|
260
260
|
```
|
|
261
261
|
|
|
262
|
-
If
|
|
262
|
+
If a project has explicitly enabled Decantr CLI telemetry and configured `DECANTR_TELEMETRY_ENDPOINT`, `new --telemetry`, `init --telemetry`, `analyze`, `check --telemetry`, `health`, and `studio` may emit only aggregate product-activation metadata to that caller-controlled private sink. They never upload the health report, finding evidence, local paths, route names, source code, package names, or prompt text. Without the endpoint, opt-in remains a local preference and no events or opaque identifiers are created.
|
|
263
263
|
|
|
264
|
-
##
|
|
264
|
+
## Private Telemetry Identity
|
|
265
265
|
|
|
266
|
-
`decantr telemetry`
|
|
266
|
+
`decantr telemetry` reports whether a caller-controlled event sink is configured and exposes the aggregate event contract for review. Decantr does not operate a hosted telemetry sink or identity service.
|
|
267
267
|
|
|
268
268
|
```bash
|
|
269
269
|
decantr telemetry status
|
|
270
270
|
decantr telemetry status --json
|
|
271
271
|
decantr telemetry explain
|
|
272
272
|
decantr telemetry explain --json
|
|
273
|
-
decantr
|
|
274
|
-
decantr telemetry link --
|
|
273
|
+
DECANTR_TELEMETRY_ENDPOINT=https://telemetry.example/v1/events decantr init --telemetry
|
|
274
|
+
decantr telemetry link --api-url https://telemetry.example/v1 --api-key <key> --org <org-slug>
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
-
`telemetry link`
|
|
277
|
+
`telemetry link` is retained for private deployments only. It requires an explicit `--api-url` or `DECANTR_TELEMETRY_IDENTITY_API_URL` plus an API key; it never falls back to `api.decantr.ai` or `DECANTR_API_URL`. Only after those values are validated can it create and send opaque install/project ids, optional org slug, and optional label.
|
|
278
278
|
|
|
279
279
|
`telemetry explain` prints the CLI event catalog subset, aggregate field categories, current opaque ids if they already exist, and the explicit never-collected list. It is designed for security review and customer trust conversations before a team opts in.
|
|
280
280
|
|
package/dist/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
3
|
-
import "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-CI2R5W36.js";
|
|
3
|
+
import "./chunk-JK3DYOHA.js";
|
|
4
|
+
import "./chunk-W242I6CS.js";
|
|
5
|
+
import "./chunk-PFFNEN7L.js";
|
|
6
|
+
import "./chunk-2UC6YYVZ.js";
|
|
@@ -1731,22 +1731,24 @@ import {
|
|
|
1731
1731
|
createTelemetryClient,
|
|
1732
1732
|
isTelemetryActorType
|
|
1733
1733
|
} from "@decantr/telemetry";
|
|
1734
|
-
var TELEMETRY_ENDPOINT = "https://api.decantr.ai/v1/telemetry/guard";
|
|
1735
|
-
var DEFAULT_TELEMETRY_EVENTS_ENDPOINT = "https://api.decantr.ai/v1/telemetry/events";
|
|
1736
1734
|
var TELEMETRY_TIMEOUT_MS = 3e3;
|
|
1737
1735
|
var DNA_RULES = /* @__PURE__ */ new Set(["theme", "style", "density", "accessibility", "theme-mode"]);
|
|
1738
1736
|
async function sendGuardMetrics(metrics) {
|
|
1737
|
+
const endpoint = readConfiguredEndpoint("DECANTR_TELEMETRY_GUARD_ENDPOINT");
|
|
1738
|
+
if (!endpoint) return;
|
|
1739
|
+
let timer;
|
|
1739
1740
|
try {
|
|
1740
1741
|
const controller = new AbortController();
|
|
1741
|
-
|
|
1742
|
-
await fetch(
|
|
1742
|
+
timer = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
|
|
1743
|
+
await fetch(endpoint, {
|
|
1743
1744
|
method: "POST",
|
|
1744
1745
|
headers: { "Content-Type": "application/json" },
|
|
1745
1746
|
body: JSON.stringify(metrics),
|
|
1746
1747
|
signal: controller.signal
|
|
1747
1748
|
});
|
|
1748
|
-
clearTimeout(timer);
|
|
1749
1749
|
} catch {
|
|
1750
|
+
} finally {
|
|
1751
|
+
if (timer) clearTimeout(timer);
|
|
1750
1752
|
}
|
|
1751
1753
|
}
|
|
1752
1754
|
function isOptedIn(projectRoot) {
|
|
@@ -1780,6 +1782,10 @@ async function captureCliTelemetryEvent(input) {
|
|
|
1780
1782
|
if (!isOptedIn(projectRoot)) {
|
|
1781
1783
|
return;
|
|
1782
1784
|
}
|
|
1785
|
+
const endpoint = getTelemetryEventsEndpoint();
|
|
1786
|
+
if (!endpoint) {
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1783
1789
|
const identities = ensureTelemetryIdentities(projectRoot);
|
|
1784
1790
|
if (!identities) {
|
|
1785
1791
|
return;
|
|
@@ -1787,7 +1793,7 @@ async function captureCliTelemetryEvent(input) {
|
|
|
1787
1793
|
const registrySource = input.registrySource ?? getRegistrySourceProperty(input.properties) ?? inferRegistrySource(input.args ?? []);
|
|
1788
1794
|
const client = createTelemetryClient({
|
|
1789
1795
|
sink: createFetchTelemetrySink({
|
|
1790
|
-
endpoint
|
|
1796
|
+
endpoint,
|
|
1791
1797
|
timeoutMs: TELEMETRY_TIMEOUT_MS
|
|
1792
1798
|
})
|
|
1793
1799
|
});
|
|
@@ -2057,8 +2063,11 @@ function getCliTelemetryIdentityStatus(projectRoot, options = {}) {
|
|
|
2057
2063
|
const hasProjectConfig = existsSync9(projectJsonPath);
|
|
2058
2064
|
const identities = options.create ? ensureTelemetryIdentities(projectRoot) : null;
|
|
2059
2065
|
const projectData = readProjectJson2(projectRoot);
|
|
2066
|
+
const endpoint = getTelemetryEventsEndpoint();
|
|
2060
2067
|
return {
|
|
2061
2068
|
enabled: projectData?.telemetry === true,
|
|
2069
|
+
endpoint,
|
|
2070
|
+
endpointConfigured: Boolean(endpoint),
|
|
2062
2071
|
hasProjectConfig,
|
|
2063
2072
|
installId: identities?.installId ?? readExistingInstallId(),
|
|
2064
2073
|
projectId: identities?.projectId ?? readStringProperty(projectData, "telemetryProjectId"),
|
|
@@ -2124,7 +2133,12 @@ function getConfigDir() {
|
|
|
2124
2133
|
return process.env.DECANTR_CONFIG_DIR || join9(homedir(), ".config", "decantr");
|
|
2125
2134
|
}
|
|
2126
2135
|
function getTelemetryEventsEndpoint() {
|
|
2127
|
-
return
|
|
2136
|
+
return readConfiguredEndpoint("DECANTR_TELEMETRY_ENDPOINT");
|
|
2137
|
+
}
|
|
2138
|
+
function readConfiguredEndpoint(name) {
|
|
2139
|
+
const value = process.env[name]?.trim();
|
|
2140
|
+
if (!value) return void 0;
|
|
2141
|
+
return value.replace(/\/+$/, "");
|
|
2128
2142
|
}
|
|
2129
2143
|
function getTelemetryActorType() {
|
|
2130
2144
|
const configured = process.env.DECANTR_TELEMETRY_ACTOR_TYPE;
|
|
@@ -2398,10 +2412,10 @@ ${YELLOW}Warnings found. Review the issues above or set stricter gates in CI.${R
|
|
|
2398
2412
|
async function maybeSendTelemetry(projectRoot, essence, issues, options) {
|
|
2399
2413
|
if (options.telemetry && !isOptedIn(projectRoot)) {
|
|
2400
2414
|
optIn(projectRoot);
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2415
|
+
const telemetry = getCliTelemetryIdentityStatus(projectRoot);
|
|
2416
|
+
const message = telemetry.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.";
|
|
2417
|
+
console.log(`
|
|
2418
|
+
${CYAN}Telemetry preference enabled.${RESET} ${message}`);
|
|
2405
2419
|
console.log(`${DIM}Set "telemetry": false in .decantr/project.json to opt out.${RESET}`);
|
|
2406
2420
|
}
|
|
2407
2421
|
if (isOptedIn(projectRoot)) {
|