@decantr/cli 2.9.0 → 2.9.2

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 CHANGED
@@ -19,8 +19,9 @@ npx @decantr/cli new my-app --blueprint=esports-hq
19
19
 
20
20
  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 next command.
21
21
  Use `decantr new` for a greenfield workspace in a fresh directory. With a blueprint/archetype it uses the runnable adapter and Decantr CSS; without registry content it creates a contract-only workspace unless you explicitly pass `--adoption=decantr-css`.
22
- 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, and only applies it when you explicitly accept or merge it.
22
+ 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 hosted execution packs when online, and only applies the contract when you explicitly accept or merge it.
23
23
  Use `decantr doctor` when the next step is unclear, `decantr task` before asking an LLM to modify a route, `decantr verify` after the edit, and `decantr ci` in required automation. Use `decantr codify --from-audit` when you want project-owned UI patterns and local rules such as button/card/shell/theme standards to appear in future task context and verification.
24
+ In monorepos, app-scoped commands accept `--project <app-path>`. Hosted pack hydration also follows the essence path: `decantr registry compile-packs apps/web/decantr.essence.json --write-context` writes into `apps/web/.decantr/context`.
24
25
  Use `decantr init`, `decantr analyze`, `decantr check`, and `decantr health` as advanced primitives when you need direct control over one step.
25
26
 
26
27
  Current starter adapter availability:
@@ -137,7 +138,7 @@ decantr showcase verification --json
137
138
 
138
139
  `decantr doctor` explains project/workspace state, adoption mode, generated artifacts, local law, visual evidence, design authority signals, CI wiring, and the next command to run. It is the command to reach for when an app is in a monorepo, has stale Decantr files, or someone is not sure what Decantr expects next.
139
140
 
140
- `decantr ci` is the blessed non-mutating automation gate. It runs the Project Health surface with adoption-mode-aware local law checks and emits a schema-backed CI report. `decantr ci init` writes root GitHub workflows or portable generic snippets using the detected package manager and pinned local CLI command instead of `@latest`.
141
+ `decantr ci` is the blessed non-mutating automation gate. It runs the Project Health surface with adoption-mode-aware local law checks and emits a schema-backed CI report. `decantr ci init` writes root GitHub workflows or portable generic snippets using the detected package manager and pinned local CLI command instead of `@latest`; if the root manifest has not pinned Decantr yet, it prints the exact install command first.
141
142
 
142
143
  `decantr health` remains the advanced project observability primitive. It composes the existing verifier audit, guard checks, brownfield route drift checks, runtime evidence, and execution-pack files into a `ProjectHealthReport` with a status, score, route summary, pack summary, findings, and AI-ready remediation prompts.
143
144
 
@@ -172,7 +173,7 @@ decantr export --to figma-tokens
172
173
 
173
174
  Use `--json` for machines and schema validation, `--markdown` for summaries, `--evidence` for the privacy-redacted Evidence Bundle, and `--prompt <finding-id>` when you want a scoped remediation prompt for an AI assistant. The prompt command prints instructions only; it does not modify source files. `--browser` uses a project-local Playwright install and a supplied base URL to capture local route screenshots under `.decantr/evidence/screenshots/` and write `.decantr/evidence/visual-manifest.json`; missing Playwright becomes a setup finding, not a crash. `--save-baseline` writes `.decantr/health-baseline.json`; `--since-baseline` writes `.decantr/health-baseline-diff.json` with changed files, route impact, finding deltas, screenshot hash drift, and contract drift. `--design-tokens <path>` compares a Tokens Studio/Figma token JSON export against Decantr CSS token names. `decantr ci --fail-on error` fails only when blocking errors exist; `decantr ci --fail-on warn` also fails on warnings.
174
175
 
175
- `decantr ci init` installs `.github/workflows/decantr-ci.yml` for GitHub Actions. The generated workflow installs dependencies at the workspace root, writes JSON/markdown CI artifacts, gates with `decantr ci`, appends the markdown report to the GitHub step summary, and uploads both files as artifacts. Use `--force` to replace an existing workflow or `--fail-on warn` for stricter repositories. In monorepos, add `--project <path>` from the repository root; dependency install stays at the root while CI evaluates the app contract and uploads app-scoped artifacts. Use `--workspace` to generate an aggregate gate. Use `--provider generic` for Jenkins, Please, Buildkite, GitLab, Azure DevOps, or internal deployment tools. Generated CI uses the pinned local package-manager command and does not depend on `@latest`.
176
+ `decantr ci init` installs `.github/workflows/decantr-ci.yml` for GitHub Actions. The generated workflow installs dependencies at the workspace root, writes JSON/markdown CI artifacts, gates with `decantr ci`, appends the markdown report to the GitHub step summary, and uploads both files as artifacts. Use `--force` to replace an existing workflow or `--fail-on warn` for stricter repositories. In monorepos, add `--project <path>` from the repository root; dependency install stays at the root while CI evaluates the app contract and uploads app-scoped artifacts. Use `--workspace` to generate an aggregate gate. Use `--provider generic` for Jenkins, Please, Buildkite, GitLab, Azure DevOps, or internal deployment tools. Generated CI uses the pinned local package-manager command and does not depend on `@latest`. Project Health remediation prompts are also monorepo-aware, so missing-pack fixes use `apps/web/decantr.essence.json` and CI recommendations include `--project apps/web`.
176
177
 
177
178
  `decantr workspace` is the monorepo reliability namespace. Before attach, `workspace list` shows app candidates. After attach, it also discovers Decantr projects from `.decantr/workspace.json` or by finding `decantr.essence.json` files. Workspace health runs projects with deterministic ordering, concurrency, per-project timeout, failure isolation, and aggregate JSON, and can limit a run to changed projects:
178
179
 
package/dist/bin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-N7A3WUZ2.js";
3
- import "./chunk-V3XAQWKD.js";
4
- import "./chunk-T5INVSOP.js";
5
- import "./chunk-TMOCTDYY.js";
2
+ import "./chunk-AXMGQ5IB.js";
3
+ import "./chunk-RXF7ZYGK.js";
4
+ import "./chunk-R57DMFLF.js";
5
+ import "./chunk-DX2UDORT.js";
6
6
  import "./chunk-34TZXWIF.js";
@@ -14,22 +14,22 @@ import {
14
14
  scaffoldProject,
15
15
  syncRegistry,
16
16
  writeExecutionPackBundleArtifacts
17
- } from "./chunk-V3XAQWKD.js";
17
+ } from "./chunk-RXF7ZYGK.js";
18
18
  import {
19
19
  createWorkspaceHealthReport,
20
20
  formatWorkspaceHealthMarkdown,
21
21
  formatWorkspaceHealthText,
22
22
  listWorkspaceCandidates,
23
23
  listWorkspaceProjects,
24
- resolveWorkspaceInfo,
25
24
  shouldFailWorkspaceHealth
26
- } from "./chunk-T5INVSOP.js";
25
+ } from "./chunk-R57DMFLF.js";
27
26
  import {
28
27
  createProjectHealthReport,
29
28
  formatProjectHealthMarkdown,
30
29
  formatProjectHealthText,
30
+ resolveWorkspaceInfo,
31
31
  shouldFailHealth
32
- } from "./chunk-TMOCTDYY.js";
32
+ } from "./chunk-DX2UDORT.js";
33
33
  import {
34
34
  buildGuardRegistryContext,
35
35
  createDoctrineMap,
@@ -3667,6 +3667,12 @@ function detectPackageManager(root) {
3667
3667
  if (existsSync14(join16(root, "bun.lock")) || existsSync14(join16(root, "bun.lockb"))) return "bun";
3668
3668
  return "unknown";
3669
3669
  }
3670
+ function hasWorkspaceMarker(root) {
3671
+ const pkg = readJson(join16(root, "package.json"));
3672
+ return Boolean(
3673
+ existsSync14(join16(root, "pnpm-workspace.yaml")) || existsSync14(join16(root, "turbo.json")) || existsSync14(join16(root, "nx.json")) || pkg?.workspaces
3674
+ );
3675
+ }
3670
3676
  function installCommand(packageManager) {
3671
3677
  switch (packageManager) {
3672
3678
  case "pnpm":
@@ -3681,6 +3687,20 @@ function installCommand(packageManager) {
3681
3687
  return "npm install";
3682
3688
  }
3683
3689
  }
3690
+ function pinCliCommand(packageManager, root) {
3691
+ switch (packageManager) {
3692
+ case "pnpm":
3693
+ return hasWorkspaceMarker(root) ? "pnpm add -D -w @decantr/cli" : "pnpm add -D @decantr/cli";
3694
+ case "yarn":
3695
+ return "yarn add -D @decantr/cli";
3696
+ case "bun":
3697
+ return "bun add -d @decantr/cli";
3698
+ case "npm":
3699
+ return "npm install -D @decantr/cli";
3700
+ default:
3701
+ return "npm install -D @decantr/cli";
3702
+ }
3703
+ }
3684
3704
  function decantrCommand(packageManager) {
3685
3705
  switch (packageManager) {
3686
3706
  case "pnpm":
@@ -3837,7 +3857,7 @@ function writeCiInit(root, options) {
3837
3857
  const provider = options.provider ?? "github";
3838
3858
  if (!localCliPinned(outputRoot)) {
3839
3859
  console.log(
3840
- `${DIM3}No @decantr/cli dependency was found in the workspace root package.json. The generated command still uses the local package-manager binary path; pin @decantr/cli in devDependencies before relying on CI.${RESET3}`
3860
+ `${DIM3}No @decantr/cli dependency was found in the workspace root package.json. Before relying on CI, pin it with: ${pinCliCommand(packageManager, outputRoot)}${RESET3}`
3841
3861
  );
3842
3862
  }
3843
3863
  if (provider === "generic") {
@@ -4194,6 +4214,7 @@ import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync a
4194
4214
  import { dirname as dirname3, join as join18, relative as relative4 } from "path";
4195
4215
  import { fileURLToPath } from "url";
4196
4216
  import { isV4 as isV44 } from "@decantr/essence-spec";
4217
+ import { collectMissingPackManifestFiles } from "@decantr/verifier";
4197
4218
  var BOLD3 = "\x1B[1m";
4198
4219
  var DIM4 = "\x1B[2m";
4199
4220
  var GREEN4 = "\x1B[32m";
@@ -4339,6 +4360,19 @@ function buildDoctorReport(root, args) {
4339
4360
  const ciFiles = findCiFiles(workspaceRoot);
4340
4361
  const workflowMode = projectJson?.initialized?.workflowMode ?? null;
4341
4362
  const adoptionMode = projectJson?.initialized?.adoptionMode ?? null;
4363
+ const missingPackReferences = workspaceMode ? projects.flatMap(
4364
+ (project) => collectMissingPackManifestFiles(join18(workspaceRoot, project.path)).map(
4365
+ (missing) => `${project.path}/${missing.relativePath}`
4366
+ )
4367
+ ) : collectMissingPackManifestFiles(appRoot).map((missing) => missing.relativePath);
4368
+ const workspaceProjectsMissingManifest = workspaceMode ? projects.map((project) => project.path).filter((projectPath2) => {
4369
+ const projectContextDir = join18(workspaceRoot, projectPath2, ".decantr", "context");
4370
+ return !existsSync16(join18(projectContextDir, "pack-manifest.json"));
4371
+ }) : [];
4372
+ const workspaceProjectsMissingReviewPack = workspaceMode ? projects.map((project) => project.path).filter((projectPath2) => {
4373
+ const projectContextDir = join18(workspaceRoot, projectPath2, ".decantr", "context");
4374
+ return !existsSync16(join18(projectContextDir, "review-pack.json"));
4375
+ }) : [];
4342
4376
  const issues = [];
4343
4377
  if (!essenceVersion && !workspaceMode && !workspaceInfo.requiresProjectSelection) {
4344
4378
  issues.push({
@@ -4384,7 +4418,23 @@ function buildDoctorReport(root, args) {
4384
4418
  category: "generated-artifact",
4385
4419
  severity: "warn",
4386
4420
  message: "Generated context packs are missing or incomplete.",
4387
- nextCommand: projectPath ? `decantr refresh --project ${projectPath}` : "decantr refresh"
4421
+ nextCommand: projectPath ? `decantr registry compile-packs ${projectPath}/decantr.essence.json --write-context` : "decantr registry compile-packs decantr.essence.json --write-context"
4422
+ });
4423
+ }
4424
+ if (essenceVersion === "4.0.0" && missingPackReferences.length > 0) {
4425
+ issues.push({
4426
+ category: "generated-artifact",
4427
+ severity: "warn",
4428
+ message: `Generated pack manifest references ${missingPackReferences.length} missing file(s).`,
4429
+ nextCommand: projectPath ? `decantr registry compile-packs ${projectPath}/decantr.essence.json --write-context` : "decantr registry compile-packs decantr.essence.json --write-context"
4430
+ });
4431
+ }
4432
+ if (workspaceMode && (workspaceProjectsMissingManifest.length > 0 || workspaceProjectsMissingReviewPack.length > 0 || missingPackReferences.length > 0)) {
4433
+ issues.push({
4434
+ category: "generated-artifact",
4435
+ severity: "warn",
4436
+ message: "One or more attached workspace projects have missing or incomplete generated context packs.",
4437
+ nextCommand: "decantr registry compile-packs <app-path>/decantr.essence.json --write-context"
4388
4438
  });
4389
4439
  }
4390
4440
  if (workflowMode === "brownfield-attach" && !existsSync16(localPatternsPath(appRoot))) {
@@ -4439,9 +4489,12 @@ function buildDoctorReport(root, args) {
4439
4489
  appCandidates: candidates
4440
4490
  },
4441
4491
  generatedArtifacts: {
4442
- contextDirPresent: existsSync16(contextDir),
4443
- packManifestPresent,
4444
- reviewPackPresent
4492
+ contextDirPresent: workspaceMode ? projects.some(
4493
+ (project) => existsSync16(join18(workspaceRoot, project.path, ".decantr", "context"))
4494
+ ) : existsSync16(contextDir),
4495
+ packManifestPresent: workspaceMode ? projects.length > 0 && workspaceProjectsMissingManifest.length === 0 : packManifestPresent,
4496
+ reviewPackPresent: workspaceMode ? projects.length > 0 && workspaceProjectsMissingReviewPack.length === 0 : reviewPackPresent,
4497
+ missingReferencedFiles: missingPackReferences.slice(0, 25)
4445
4498
  },
4446
4499
  localLaw: {
4447
4500
  patternsPresent: existsSync16(localPatternsPath(appRoot)),
@@ -4481,6 +4534,7 @@ function formatDoctorText(report) {
4481
4534
  ` Context directory: ${report.generatedArtifacts.contextDirPresent ? "present" : "missing"}`,
4482
4535
  ` Pack manifest: ${report.generatedArtifacts.packManifestPresent ? "present" : "missing"}`,
4483
4536
  ` Review pack: ${report.generatedArtifacts.reviewPackPresent ? "present" : "missing"}`,
4537
+ ` Manifest references: ${report.generatedArtifacts.missingReferencedFiles.length === 0 ? "complete" : `${report.generatedArtifacts.missingReferencedFiles.length} missing`}`,
4484
4538
  ` Artifact guide: ${report.project.artifactReadmePresent ? "present" : "missing"}`,
4485
4539
  "",
4486
4540
  `${BOLD3}Local Law:${RESET4}`,
@@ -5829,6 +5883,7 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
5829
5883
  import { createHash } from "crypto";
5830
5884
  import { existsSync as existsSync23, readdirSync as readdirSync7, readFileSync as readFileSync17, statSync as statSync6 } from "fs";
5831
5885
  import { join as join25 } from "path";
5886
+ import { collectMissingPackManifestFiles as collectMissingPackManifestFiles2 } from "@decantr/verifier";
5832
5887
  import { isV4 as isV46 } from "@decantr/essence-spec";
5833
5888
  var GREEN9 = "\x1B[32m";
5834
5889
  var RED8 = "\x1B[31m";
@@ -5891,6 +5946,16 @@ function checkRefreshFreshness(projectRoot) {
5891
5946
  if (!existsSync23(join25(contextDir, "scaffold.md"))) {
5892
5947
  reasons.push(".decantr/context/scaffold.md is missing.");
5893
5948
  }
5949
+ if (!existsSync23(join25(contextDir, "pack-manifest.json"))) {
5950
+ reasons.push(".decantr/context/pack-manifest.json is missing.");
5951
+ } else {
5952
+ const missingPackFiles = collectMissingPackManifestFiles2(projectRoot);
5953
+ if (missingPackFiles.length > 0) {
5954
+ reasons.push(
5955
+ `pack-manifest.json references missing files: ${missingPackFiles.slice(0, 5).map((missing) => missing.relativePath).join(", ")}${missingPackFiles.length > 5 ? "..." : ""}`
5956
+ );
5957
+ }
5958
+ }
5894
5959
  const newestInput = newestInputMtime(projectRoot);
5895
5960
  const staleFiles = generated.filter((path) => fileMtimeMs(path) > 0 && fileMtimeMs(path) < newestInput).map((path) => path.replace(`${projectRoot}/`, ""));
5896
5961
  if (staleFiles.length > 0) {
@@ -7899,18 +7964,13 @@ async function printRegistryIntelligenceSummary(namespace, jsonOutput = false) {
7899
7964
  }
7900
7965
  }
7901
7966
  async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput = false, writeContext = false) {
7902
- const client = getPublicAPIClient();
7903
- const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
7904
- if (!existsSync29(resolvedPath)) {
7905
- throw new Error(`Essence file not found at ${resolvedPath}`);
7906
- }
7907
- const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
7908
- const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
7967
+ const { resolvedPath, bundle, contextDir } = await compileHostedExecutionPackBundle(
7968
+ essencePath,
7969
+ namespace
7970
+ );
7909
7971
  let writtenContextPaths = [];
7910
7972
  if (writeContext) {
7911
- const contextDir = join31(process.cwd(), ".decantr", "context");
7912
- mkdirSync16(contextDir, { recursive: true });
7913
- const written = writeExecutionPackBundleArtifacts(
7973
+ const written = writeHostedExecutionPackContextArtifacts(
7914
7974
  contextDir,
7915
7975
  bundle
7916
7976
  );
@@ -7934,7 +7994,7 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
7934
7994
  console.log(` Sections: ${typedBundle.sections.length}`);
7935
7995
  console.log(` Mutations: ${typedBundle.mutations.length}`);
7936
7996
  if (writeContext) {
7937
- console.log(` Context bundle: ${join31(process.cwd(), ".decantr", "context")}`);
7997
+ console.log(` Context bundle: ${contextDir}`);
7938
7998
  console.log(` Files written: ${writtenContextPaths.length}`);
7939
7999
  }
7940
8000
  console.log("");
@@ -7945,6 +8005,21 @@ async function printHostedExecutionPackBundle(essencePath, namespace, jsonOutput
7945
8005
  console.log(` ${cyan3(route.path)} -> ${pageLabel} [${patterns}]`);
7946
8006
  }
7947
8007
  }
8008
+ async function compileHostedExecutionPackBundle(essencePath, namespace) {
8009
+ const client = getPublicAPIClient();
8010
+ const resolvedPath = essencePath ? resolveUserPath(essencePath) : join31(process.cwd(), "decantr.essence.json");
8011
+ if (!existsSync29(resolvedPath)) {
8012
+ throw new Error(`Essence file not found at ${resolvedPath}`);
8013
+ }
8014
+ const essence = JSON.parse(readFileSync22(resolvedPath, "utf-8"));
8015
+ const bundle = await client.compileExecutionPacks(essence, namespace ? { namespace } : void 0);
8016
+ const contextDir = join31(dirname5(resolvedPath), ".decantr", "context");
8017
+ return { resolvedPath, bundle, contextDir };
8018
+ }
8019
+ function writeHostedExecutionPackContextArtifacts(contextDir, bundle) {
8020
+ mkdirSync16(contextDir, { recursive: true });
8021
+ return writeExecutionPackBundleArtifacts(contextDir, bundle);
8022
+ }
7948
8023
  function resolvePagePackIdForRoute(essencePath, route) {
7949
8024
  if (!existsSync29(essencePath)) {
7950
8025
  throw new Error(`Essence file not found at ${essencePath}`);
@@ -7982,7 +8057,7 @@ async function printHostedSelectedExecutionPack(packType, id, essencePath, names
7982
8057
  );
7983
8058
  let writtenContextDir = null;
7984
8059
  if (writeContext) {
7985
- const contextDir = join31(process.cwd(), ".decantr", "context");
8060
+ const contextDir = join31(dirname5(resolvedPath), ".decantr", "context");
7986
8061
  mkdirSync16(contextDir, { recursive: true });
7987
8062
  writeFileSync19(
7988
8063
  join31(contextDir, "pack-manifest.json"),
@@ -8028,7 +8103,7 @@ async function printHostedExecutionPackManifest(essencePath, namespace, jsonOutp
8028
8103
  );
8029
8104
  let writtenContextDir = null;
8030
8105
  if (writeContext) {
8031
- const contextDir = join31(process.cwd(), ".decantr", "context");
8106
+ const contextDir = join31(dirname5(resolvedPath), ".decantr", "context");
8032
8107
  mkdirSync16(contextDir, { recursive: true });
8033
8108
  writeFileSync19(join31(contextDir, "pack-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
8034
8109
  writtenContextDir = contextDir;
@@ -9716,6 +9791,10 @@ function withoutWorkflowOnlyFlags(args) {
9716
9791
  function withProject(command, projectArg) {
9717
9792
  return projectArg ? `${command} --project ${projectArg}` : command;
9718
9793
  }
9794
+ function compilePacksCommandForProject(projectArg) {
9795
+ const essencePath = projectArg ? `${projectArg}/decantr.essence.json` : "decantr.essence.json";
9796
+ return `decantr registry compile-packs ${essencePath} --write-context`;
9797
+ }
9719
9798
  function firstWorkspaceCandidate(workspaceInfo) {
9720
9799
  return workspaceInfo.appCandidates[0] ?? "apps/web";
9721
9800
  }
@@ -9853,6 +9932,7 @@ async function cmdAdoptWorkflow(args) {
9853
9932
  const runBrowser = flagBoolean(flags, "browser") || Boolean(baseUrl);
9854
9933
  const evidence = flagBoolean(flags, "evidence") || runBrowser;
9855
9934
  const saveBaseline = flagBoolean(flags, "baseline", true) || flagBoolean(flags, "save-baseline");
9935
+ const hydratePacks = flagBoolean(flags, "packs", true) && !flagBoolean(flags, "skip-packs") && !flagBoolean(flags, "offline") && process.env.DECANTR_OFFLINE !== "true";
9856
9936
  const initCi = flagBoolean(flags, "ci") || flagBoolean(flags, "init-ci");
9857
9937
  const assistantBridge = flagString(flags, "assistant-bridge");
9858
9938
  const hasEssence = existsSync29(join31(projectRoot, "decantr.essence.json"));
@@ -9861,6 +9941,9 @@ async function cmdAdoptWorkflow(args) {
9861
9941
  "analyze current app and write .decantr/brownfield intelligence",
9862
9942
  `init --existing ${proposalFlag} as contract-only Brownfield`
9863
9943
  ];
9944
+ if (hydratePacks) {
9945
+ steps.push("hydrate hosted execution packs into the app context");
9946
+ }
9864
9947
  if (runVerify) {
9865
9948
  steps.push(
9866
9949
  runBrowser ? "verify with Project Health, browser evidence, visual manifest, and baseline" : "verify with Project Health and baseline"
@@ -9894,8 +9977,35 @@ async function cmdAdoptWorkflow(args) {
9894
9977
  telemetry: flagBoolean(flags, "telemetry")
9895
9978
  });
9896
9979
  if (process.exitCode && process.exitCode !== 0) return;
9980
+ if (hydratePacks) {
9981
+ try {
9982
+ const { bundle, contextDir } = await compileHostedExecutionPackBundle(
9983
+ join31(projectRoot, "decantr.essence.json")
9984
+ );
9985
+ const written = writeHostedExecutionPackContextArtifacts(
9986
+ contextDir,
9987
+ bundle
9988
+ );
9989
+ console.log(
9990
+ success3(
9991
+ `Hydrated Decantr execution packs (${written.paths.length} files) into ${contextDir}.`
9992
+ )
9993
+ );
9994
+ } catch (e) {
9995
+ console.log(
9996
+ `${YELLOW10}Pack hydration skipped:${RESET16} ${e.message}`
9997
+ );
9998
+ console.log(
9999
+ dim3(
10000
+ `Run ${compilePacksCommandForProject(projectArg)} after adoption if you want hosted page/review packs.`
10001
+ )
10002
+ );
10003
+ }
10004
+ } else if (flagBoolean(flags, "offline") || process.env.DECANTR_OFFLINE === "true") {
10005
+ console.log(dim3("Skipping hosted pack hydration in offline mode."));
10006
+ }
9897
10007
  if (runVerify) {
9898
- const { cmdHealth } = await import("./health-Q7XF3I5Z.js");
10008
+ const { cmdHealth } = await import("./health-LTDSTNOV.js");
9899
10009
  await cmdHealth(projectRoot, {
9900
10010
  browser: runBrowser,
9901
10011
  browserBaseUrl: baseUrl,
@@ -9936,7 +10046,7 @@ async function cmdVerifyWorkflow(args) {
9936
10046
  return;
9937
10047
  }
9938
10048
  if (workspaceMode) {
9939
- const { cmdWorkspace } = await import("./workspace-H5QQJCCI.js");
10049
+ const { cmdWorkspace } = await import("./workspace-53EIHUXB.js");
9940
10050
  await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
9941
10051
  return;
9942
10052
  }
@@ -9979,7 +10089,7 @@ async function cmdVerifyWorkflow(args) {
9979
10089
  process.exitCode = void 0;
9980
10090
  }
9981
10091
  }
9982
- const { cmdHealth, parseHealthArgs } = await import("./health-Q7XF3I5Z.js");
10092
+ const { cmdHealth, parseHealthArgs } = await import("./health-LTDSTNOV.js");
9983
10093
  await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
9984
10094
  if (localPatterns) {
9985
10095
  const validation = validateLocalLaw(workspaceInfo.appRoot);
@@ -10045,6 +10155,7 @@ async function cmdTaskWorkflow(args) {
10045
10155
  const { flags, positional } = parseLooseArgs(args);
10046
10156
  const workspaceInfo = resolveWorkflowProject(flags, "task");
10047
10157
  if (!workspaceInfo) return;
10158
+ const projectArg = flagString(flags, "project");
10048
10159
  const routeInput = positional[0];
10049
10160
  if (!routeInput) {
10050
10161
  console.error(
@@ -10113,7 +10224,7 @@ async function cmdTaskWorkflow(args) {
10113
10224
  localLaw,
10114
10225
  changedFiles: currentChangedFiles,
10115
10226
  changedRoutes,
10116
- verifyCommand: "decantr verify --brownfield --local-patterns"
10227
+ verifyCommand: withProject("decantr verify --brownfield --local-patterns", projectArg)
10117
10228
  };
10118
10229
  if (flagBoolean(flags, "json")) {
10119
10230
  console.log(JSON.stringify(context, null, 2));
@@ -10154,7 +10265,7 @@ async function cmdTaskWorkflow(args) {
10154
10265
  console.log("");
10155
10266
  console.log(`${BOLD9}Project-owned local law:${RESET16}`);
10156
10267
  console.log(
10157
- ` ${YELLOW10}Not codified yet.${RESET16} Run ${cyan3("decantr codify --from-audit")} after adoption.`
10268
+ ` ${YELLOW10}Not codified yet.${RESET16} Run ${cyan3(withProject("decantr codify --from-audit", projectArg))} after adoption.`
10158
10269
  );
10159
10270
  }
10160
10271
  if (context.changedFiles.length > 0) {
@@ -10268,7 +10379,7 @@ ${BOLD9}decantr${RESET16} \u2014 Design intelligence for AI-generated UI
10268
10379
  ${BOLD9}Usage:${RESET16}
10269
10380
  decantr setup [--project <path>]
10270
10381
  decantr new <name> [--blueprint=X] [--archetype=X] [--theme=X] [--workflow=greenfield] [--adoption=decantr-css] [--telemetry]
10271
- decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--yes]
10382
+ decantr adopt [--project <path>] [--base-url <url>] [--evidence] [--ci] [--no-packs] [--yes]
10272
10383
  decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
10273
10384
  decantr verify [--project <path>] [--brownfield] [--local-patterns] [health options]
10274
10385
  decantr ci [--project <path>] [--workspace] [--fail-on error|warn|none]
@@ -10628,11 +10739,11 @@ ${BOLD9}Examples:${RESET16}
10628
10739
  }
10629
10740
  function cmdAdoptHelp() {
10630
10741
  console.log(`
10631
- ${BOLD9}decantr adopt${RESET16} \u2014 Brownfield one-liner: analyze, attach, verify, and show the operating loop
10742
+ ${BOLD9}decantr adopt${RESET16} \u2014 Brownfield one-liner: analyze, attach, hydrate packs, verify, and show the operating loop
10632
10743
 
10633
10744
  ${BOLD9}Usage:${RESET16}
10634
- decantr adopt [--project <path>] [--yes] [--dry-run]
10635
- decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes]
10745
+ decantr adopt [--project <path>] [--yes] [--dry-run] [--no-packs]
10746
+ decantr adopt [--project <path>] --base-url <url> [--evidence] [--ci] [--yes] [--no-packs]
10636
10747
 
10637
10748
  ${BOLD9}Options:${RESET16}
10638
10749
  --project App path inside a workspace/monorepo
@@ -10643,6 +10754,7 @@ ${BOLD9}Options:${RESET16}
10643
10754
  --baseline Save a health baseline (default)
10644
10755
  --no-baseline Skip baseline save
10645
10756
  --no-verify Skip the verification step
10757
+ --no-packs Skip hosted execution-pack hydration
10646
10758
  --ci, --init-ci Install the Decantr CI gate after adoption
10647
10759
  --telemetry Opt this project into privacy-filtered CLI product telemetry
10648
10760
  --merge-proposal Merge the observed proposal into an existing essence
@@ -10921,7 +11033,7 @@ async function main() {
10921
11033
  break;
10922
11034
  }
10923
11035
  case "upgrade": {
10924
- const { cmdUpgrade } = await import("./upgrade-U2BTWJJJ.js");
11036
+ const { cmdUpgrade } = await import("./upgrade-VON7Y3LG.js");
10925
11037
  const applyFlag = args.includes("--apply");
10926
11038
  await cmdUpgrade(process.cwd(), { apply: applyFlag });
10927
11039
  break;
@@ -10934,9 +11046,12 @@ async function main() {
10934
11046
  );
10935
11047
  }
10936
11048
  const { cmdHeal } = await import("./heal-2BDT7TR5.js");
11049
+ const { flags } = parseLooseArgs(args);
11050
+ const workspaceInfo = resolveWorkflowProject(flags, "check");
11051
+ if (!workspaceInfo) break;
10937
11052
  const telemetryFlag = args.includes("--telemetry");
10938
11053
  const brownfieldFlag = args.includes("--brownfield");
10939
- await cmdHeal(process.cwd(), { telemetry: telemetryFlag, brownfield: brownfieldFlag });
11054
+ await cmdHeal(workspaceInfo.appRoot, { telemetry: telemetryFlag, brownfield: brownfieldFlag });
10940
11055
  break;
10941
11056
  }
10942
11057
  case "health": {
@@ -10945,7 +11060,7 @@ async function main() {
10945
11060
  cmdHealthHelp();
10946
11061
  break;
10947
11062
  }
10948
- const { cmdHealth, parseHealthArgs } = await import("./health-Q7XF3I5Z.js");
11063
+ const { cmdHealth, parseHealthArgs } = await import("./health-LTDSTNOV.js");
10949
11064
  await cmdHealth(process.cwd(), parseHealthArgs(args));
10950
11065
  } catch (e) {
10951
11066
  console.error(error3(e.message));
@@ -10973,7 +11088,7 @@ async function main() {
10973
11088
  cmdStudioHelp();
10974
11089
  break;
10975
11090
  }
10976
- const { cmdStudio, parseStudioArgs } = await import("./studio-B2Y4TKZ5.js");
11091
+ const { cmdStudio, parseStudioArgs } = await import("./studio-7E2LJS3A.js");
10977
11092
  await cmdStudio(process.cwd(), parseStudioArgs(args));
10978
11093
  } catch (e) {
10979
11094
  console.error(error3(e.message));
@@ -10987,7 +11102,7 @@ async function main() {
10987
11102
  cmdWorkspaceHelp();
10988
11103
  break;
10989
11104
  }
10990
- const { cmdWorkspace } = await import("./workspace-H5QQJCCI.js");
11105
+ const { cmdWorkspace } = await import("./workspace-53EIHUXB.js");
10991
11106
  await cmdWorkspace(process.cwd(), args);
10992
11107
  } catch (e) {
10993
11108
  console.error(error3(e.message));
@@ -8,15 +8,105 @@ import {
8
8
  // src/commands/health.ts
9
9
  import { execFileSync } from "child_process";
10
10
  import { createHash } from "crypto";
11
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
11
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
12
12
  import { createRequire } from "module";
13
- import { dirname, isAbsolute, join, resolve } from "path";
13
+ import { dirname as dirname2, isAbsolute, join as join2, relative, resolve as resolve2 } from "path";
14
14
  import { fileURLToPath } from "url";
15
15
  import {
16
16
  auditProject,
17
17
  createContractAssertions,
18
18
  createEvidenceBundle
19
19
  } from "@decantr/verifier";
20
+
21
+ // src/workspace.ts
22
+ import { existsSync, readdirSync, readFileSync } from "fs";
23
+ import { dirname, join, resolve } from "path";
24
+ function readPackageJson(dir) {
25
+ const path = join(dir, "package.json");
26
+ if (!existsSync(path)) return null;
27
+ try {
28
+ return JSON.parse(readFileSync(path, "utf-8"));
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+ function hasWorkspaceMarker(dir) {
34
+ if (existsSync(join(dir, "pnpm-workspace.yaml")) || existsSync(join(dir, "turbo.json")) || existsSync(join(dir, "nx.json"))) {
35
+ return true;
36
+ }
37
+ const pkg = readPackageJson(dir);
38
+ return Boolean(pkg?.workspaces);
39
+ }
40
+ function findWorkspaceRoot(startDir) {
41
+ let current = resolve(startDir);
42
+ while (true) {
43
+ if (hasWorkspaceMarker(current)) return current;
44
+ const parent = dirname(current);
45
+ if (parent === current) return null;
46
+ current = parent;
47
+ }
48
+ }
49
+ function looksLikeApp(dir, options = {}) {
50
+ const allowSourceDirs = options.allowSourceDirs ?? true;
51
+ const allowPackageDeps = options.allowPackageDeps ?? true;
52
+ const pkg = readPackageJson(dir);
53
+ const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
54
+ const hasFrontendDependency = Boolean(
55
+ deps.react || deps["react-dom"] || deps.next || deps.vue || deps.svelte || deps["@angular/core"] || deps.astro || deps.nuxt
56
+ );
57
+ const hasServerOnlyDependency = Boolean(
58
+ deps.hono || deps.express || deps.fastify || deps.koa || deps["@hapi/hapi"]
59
+ );
60
+ if (existsSync(join(dir, "next.config.js")) || existsSync(join(dir, "next.config.ts")) || existsSync(join(dir, "next.config.mjs")) || existsSync(join(dir, "vite.config.ts")) || existsSync(join(dir, "vite.config.js")) || existsSync(join(dir, "angular.json")) || existsSync(join(dir, "svelte.config.js")) || existsSync(join(dir, "svelte.config.ts")) || existsSync(join(dir, "astro.config.mjs"))) {
61
+ return true;
62
+ }
63
+ if (allowSourceDirs && (existsSync(join(dir, "src")) || existsSync(join(dir, "app")) || existsSync(join(dir, "pages")))) {
64
+ if (hasFrontendDependency) return true;
65
+ if (hasServerOnlyDependency) return false;
66
+ return true;
67
+ }
68
+ if (!allowPackageDeps) return false;
69
+ return hasFrontendDependency;
70
+ }
71
+ function listWorkspaceApps(workspaceRoot) {
72
+ const candidates = [];
73
+ for (const base of ["apps", "packages"]) {
74
+ const baseDir = join(workspaceRoot, base);
75
+ if (!existsSync(baseDir)) continue;
76
+ for (const entry of readdirSync(baseDir, { withFileTypes: true })) {
77
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
78
+ const candidate = join(baseDir, entry.name);
79
+ if (looksLikeApp(candidate, {
80
+ allowSourceDirs: base === "apps",
81
+ allowPackageDeps: base === "apps"
82
+ })) {
83
+ candidates.push(`${base}/${entry.name}`);
84
+ }
85
+ }
86
+ }
87
+ return candidates.sort();
88
+ }
89
+ function listWorkspaceAppCandidates(workspaceRoot) {
90
+ return listWorkspaceApps(resolve(workspaceRoot));
91
+ }
92
+ function resolveWorkspaceInfo(cwd, projectArg) {
93
+ const absoluteCwd = resolve(cwd);
94
+ const workspaceRoot = findWorkspaceRoot(absoluteCwd) ?? absoluteCwd;
95
+ const appRoot = projectArg ? resolve(absoluteCwd, projectArg) : absoluteCwd;
96
+ const appCandidates = listWorkspaceApps(workspaceRoot);
97
+ const projectScope = workspaceRoot !== appRoot || appCandidates.length > 0 ? "workspace-app" : "single-app";
98
+ const requiresProjectSelection = !projectArg && workspaceRoot === absoluteCwd && appCandidates.length > 0;
99
+ return {
100
+ cwd: absoluteCwd,
101
+ workspaceRoot,
102
+ appRoot,
103
+ projectScope,
104
+ appCandidates,
105
+ requiresProjectSelection
106
+ };
107
+ }
108
+
109
+ // src/commands/health.ts
20
110
  var BOLD = "\x1B[1m";
21
111
  var DIM = "\x1B[2m";
22
112
  var RESET = "\x1B[0m";
@@ -29,14 +119,14 @@ var DEFAULT_HEALTH_CI_WORKFLOW_PATH = ".github/workflows/decantr-health.yml";
29
119
  var DEFAULT_HEALTH_CI_REPORT_PATH = "decantr-health.md";
30
120
  var DEFAULT_HEALTH_CI_JSON_PATH = "decantr-health.json";
31
121
  var DEFAULT_HEALTH_CI_CLI_VERSION = "latest";
32
- var __dirname = dirname(fileURLToPath(import.meta.url));
122
+ var __dirname = dirname2(fileURLToPath(import.meta.url));
33
123
  function readProjectMetadata(projectRoot) {
34
- const projectJsonPath = join(projectRoot, ".decantr", "project.json");
35
- if (!existsSync(projectJsonPath)) {
124
+ const projectJsonPath = join2(projectRoot, ".decantr", "project.json");
125
+ if (!existsSync2(projectJsonPath)) {
36
126
  return { workflowMode: null, adoptionMode: null, autoBrownfield: false };
37
127
  }
38
128
  try {
39
- const data = JSON.parse(readFileSync(projectJsonPath, "utf-8"));
129
+ const data = JSON.parse(readFileSync2(projectJsonPath, "utf-8"));
40
130
  const workflowMode = typeof data.initialized?.workflowMode === "string" ? data.initialized.workflowMode : null;
41
131
  const adoptionMode = typeof data.initialized?.adoptionMode === "string" ? data.initialized.adoptionMode : null;
42
132
  return {
@@ -49,12 +139,12 @@ function readProjectMetadata(projectRoot) {
49
139
  }
50
140
  }
51
141
  function loadHealthTemplate(name) {
52
- const fromDist = join(__dirname, "..", "src", "templates", name);
53
- if (existsSync(fromDist)) return readFileSync(fromDist, "utf-8");
54
- const fromSrc = join(__dirname, "..", "templates", name);
55
- if (existsSync(fromSrc)) return readFileSync(fromSrc, "utf-8");
56
- const fromCommandSrc = join(__dirname, "..", "..", "templates", name);
57
- if (existsSync(fromCommandSrc)) return readFileSync(fromCommandSrc, "utf-8");
142
+ const fromDist = join2(__dirname, "..", "src", "templates", name);
143
+ if (existsSync2(fromDist)) return readFileSync2(fromDist, "utf-8");
144
+ const fromSrc = join2(__dirname, "..", "templates", name);
145
+ if (existsSync2(fromSrc)) return readFileSync2(fromSrc, "utf-8");
146
+ const fromCommandSrc = join2(__dirname, "..", "..", "templates", name);
147
+ if (existsSync2(fromCommandSrc)) return readFileSync2(fromCommandSrc, "utf-8");
58
148
  throw new Error(`Template not found: ${name}`);
59
149
  }
60
150
  function renderTemplate(template, vars) {
@@ -149,14 +239,14 @@ function writeProjectHealthCiWorkflow(projectRoot, options = {}) {
149
239
  const workflowRelativePath = validateWorkflowPath(
150
240
  options.workflowPath || DEFAULT_HEALTH_CI_WORKFLOW_PATH
151
241
  );
152
- const workflowPath = join(projectRoot, workflowRelativePath);
153
- const alreadyExists = existsSync(workflowPath);
242
+ const workflowPath = join2(projectRoot, workflowRelativePath);
243
+ const alreadyExists = existsSync2(workflowPath);
154
244
  if (alreadyExists && !options.force) {
155
245
  throw new Error(
156
246
  `${workflowRelativePath} already exists. Re-run with --force to replace it, or use --workflow-path <file>.`
157
247
  );
158
248
  }
159
- mkdirSync(dirname(workflowPath), { recursive: true });
249
+ mkdirSync(dirname2(workflowPath), { recursive: true });
160
250
  writeFileSync(workflowPath, renderProjectHealthCiWorkflow(options), "utf-8");
161
251
  const projectPath = options.workspace ? void 0 : validateProjectPath(options.projectPath);
162
252
  const result = {
@@ -249,17 +339,17 @@ function slugify(value) {
249
339
  return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
250
340
  }
251
341
  function hashFile(path) {
252
- if (!existsSync(path)) return null;
342
+ if (!existsSync2(path)) return null;
253
343
  try {
254
- return createHash("sha256").update(readFileSync(path)).digest("hex");
344
+ return createHash("sha256").update(readFileSync2(path)).digest("hex");
255
345
  } catch {
256
346
  return null;
257
347
  }
258
348
  }
259
349
  function readJsonFile(path) {
260
- if (!existsSync(path)) return null;
350
+ if (!existsSync2(path)) return null;
261
351
  try {
262
- return JSON.parse(readFileSync(path, "utf-8"));
352
+ return JSON.parse(readFileSync2(path, "utf-8"));
263
353
  } catch {
264
354
  return null;
265
355
  }
@@ -290,6 +380,80 @@ function commandsForFinding(source) {
290
380
  return ["decantr audit", "decantr health"];
291
381
  }
292
382
  }
383
+ function commandContextForProject(projectRoot) {
384
+ const workspaceInfo = resolveWorkspaceInfo(projectRoot);
385
+ const relativeProjectPath = relative(workspaceInfo.workspaceRoot, projectRoot).replace(/\\/g, "/");
386
+ const projectPath = relativeProjectPath && !relativeProjectPath.startsWith("..") && !isAbsolute(relativeProjectPath) ? relativeProjectPath : null;
387
+ const projectFlag = projectPath ? ` --project ${projectPath}` : "";
388
+ const essencePath = projectPath ? `${projectPath}/decantr.essence.json` : "decantr.essence.json";
389
+ return {
390
+ projectPath,
391
+ compilePacksCommand: `decantr registry compile-packs ${essencePath} --write-context`,
392
+ verifyCommand: `decantr verify${projectFlag}`,
393
+ ciCommand: `decantr ci${projectFlag} --fail-on error`
394
+ };
395
+ }
396
+ function rewriteHealthCommand(command, context) {
397
+ let rewritten = command.replace(
398
+ /decantr registry compile-packs decantr\.essence\.json --write-context/g,
399
+ context.compilePacksCommand
400
+ );
401
+ if (!context.projectPath) return rewritten;
402
+ rewritten = rewritten.replace(
403
+ /^decantr init --existing\b/,
404
+ `decantr init --project ${context.projectPath} --existing`
405
+ );
406
+ rewritten = rewritten.replace(/^decantr analyze\b/, `decantr analyze --project ${context.projectPath}`);
407
+ rewritten = rewritten.replace(/^decantr check\b/, `decantr check --project ${context.projectPath}`);
408
+ rewritten = rewritten.replace(/^decantr audit\b/, context.verifyCommand);
409
+ rewritten = rewritten.replace(/^decantr health\b/, context.verifyCommand);
410
+ return rewritten;
411
+ }
412
+ function rewriteSuggestedFixForProject(suggestedFix, context) {
413
+ if (!suggestedFix) return suggestedFix;
414
+ return suggestedFix.replace(
415
+ /decantr registry compile-packs decantr\.essence\.json --write-context/g,
416
+ context.compilePacksCommand
417
+ );
418
+ }
419
+ function commandsForProjectFinding(finding, context) {
420
+ const isPackHydrationFinding = finding.source === "pack" || /pack-manifest|review-pack|compile-packs/i.test(
421
+ `${finding.id} ${finding.rule ?? ""} ${finding.suggestedFix ?? ""}`
422
+ );
423
+ if (isPackHydrationFinding) {
424
+ return [context.compilePacksCommand, context.verifyCommand];
425
+ }
426
+ return [
427
+ ...new Set(
428
+ finding.remediation.commands.map((command) => rewriteHealthCommand(command, context))
429
+ )
430
+ ];
431
+ }
432
+ function scopeHealthFindingsToProject(projectRoot, findings) {
433
+ const context = commandContextForProject(projectRoot);
434
+ return findings.map((finding) => {
435
+ const suggestedFix = rewriteSuggestedFixForProject(finding.suggestedFix, context);
436
+ const commands = commandsForProjectFinding(finding, context);
437
+ return {
438
+ ...finding,
439
+ suggestedFix,
440
+ remediation: {
441
+ summary: suggestedFix || finding.remediation.summary,
442
+ commands,
443
+ prompt: buildRemediationPrompt({
444
+ id: finding.id,
445
+ source: finding.source,
446
+ category: finding.category,
447
+ severity: finding.severity,
448
+ message: finding.message,
449
+ evidence: finding.evidence,
450
+ suggestedFix,
451
+ commands
452
+ })
453
+ }
454
+ };
455
+ });
456
+ }
293
457
  function buildRemediationPrompt(input) {
294
458
  return [
295
459
  "You are fixing one Decantr Project Health finding in this local workspace.",
@@ -377,16 +541,16 @@ function isDuplicateFinding(existing, finding) {
377
541
  }
378
542
  function resolveOptionalPath(projectRoot, path) {
379
543
  if (!path) return void 0;
380
- return isAbsolute(path) ? path : resolve(projectRoot, path);
544
+ return isAbsolute(path) ? path : resolve2(projectRoot, path);
381
545
  }
382
546
  function hasProjectPlaywright(projectRoot) {
383
547
  try {
384
- const requireFromProject = createRequire(join(projectRoot, "package.json"));
548
+ const requireFromProject = createRequire(join2(projectRoot, "package.json"));
385
549
  requireFromProject.resolve("playwright");
386
550
  return true;
387
551
  } catch {
388
552
  try {
389
- const requireFromProject = createRequire(join(projectRoot, "package.json"));
553
+ const requireFromProject = createRequire(join2(projectRoot, "package.json"));
390
554
  requireFromProject.resolve("@playwright/test");
391
555
  return true;
392
556
  } catch {
@@ -395,7 +559,7 @@ function hasProjectPlaywright(projectRoot) {
395
559
  }
396
560
  }
397
561
  function loadProjectPlaywright(projectRoot) {
398
- const requireFromProject = createRequire(join(projectRoot, "package.json"));
562
+ const requireFromProject = createRequire(join2(projectRoot, "package.json"));
399
563
  for (const packageName of ["playwright", "@playwright/test"]) {
400
564
  try {
401
565
  const loaded = requireFromProject(packageName);
@@ -485,7 +649,7 @@ async function collectBrowserVerification(projectRoot, options, declaredRoutes)
485
649
  const screenshots = [];
486
650
  const browserFindings = [];
487
651
  const visualRoutes = [];
488
- const screenshotDir = join(projectRoot, ".decantr", "evidence", "screenshots");
652
+ const screenshotDir = join2(projectRoot, ".decantr", "evidence", "screenshots");
489
653
  mkdirSync(screenshotDir, { recursive: true });
490
654
  let browser = null;
491
655
  try {
@@ -496,7 +660,7 @@ async function collectBrowserVerification(projectRoot, options, declaredRoutes)
496
660
  const relativePath = browserScreenshotRelativePath(route);
497
661
  try {
498
662
  await page.goto(url, { waitUntil: "networkidle", timeout: 15e3 });
499
- const absoluteScreenshotPath = join(projectRoot, relativePath);
663
+ const absoluteScreenshotPath = join2(projectRoot, relativePath);
500
664
  await page.screenshot({ path: absoluteScreenshotPath, fullPage: true });
501
665
  screenshots.push(relativePath);
502
666
  visualRoutes.push({
@@ -531,8 +695,8 @@ async function collectBrowserVerification(projectRoot, options, declaredRoutes)
531
695
  baseUrl: options.browserBaseUrl,
532
696
  routes: visualRoutes
533
697
  };
534
- const visualManifestPath = join(projectRoot, ".decantr", "evidence", "visual-manifest.json");
535
- mkdirSync(dirname(visualManifestPath), { recursive: true });
698
+ const visualManifestPath = join2(projectRoot, ".decantr", "evidence", "visual-manifest.json");
699
+ mkdirSync(dirname2(visualManifestPath), { recursive: true });
536
700
  writeFileSync(visualManifestPath, JSON.stringify(visualManifest, null, 2) + "\n", "utf-8");
537
701
  if (browserFindings.length > 0) {
538
702
  const finding = createHealthFinding({
@@ -582,9 +746,9 @@ function flattenDesignTokenKeys(value, prefix = "") {
582
746
  return keys;
583
747
  }
584
748
  function parseDecantrCssTokenNames(projectRoot) {
585
- const tokensPath = join(projectRoot, "src", "styles", "tokens.css");
586
- if (!existsSync(tokensPath)) return [];
587
- const css = readFileSync(tokensPath, "utf-8");
749
+ const tokensPath = join2(projectRoot, "src", "styles", "tokens.css");
750
+ if (!existsSync2(tokensPath)) return [];
751
+ const css = readFileSync2(tokensPath, "utf-8");
588
752
  const names = /* @__PURE__ */ new Set();
589
753
  for (const match of css.matchAll(/(--d-[\w-]+)\s*:/g)) {
590
754
  names.add(match[1]);
@@ -595,7 +759,7 @@ function collectDesignTokenEvidence(projectRoot, designTokensPath) {
595
759
  const resolved = resolveOptionalPath(projectRoot, designTokensPath);
596
760
  if (!resolved) return void 0;
597
761
  const sourceLabel = isAbsolute(designTokensPath ?? "") ? "<design-tokens>" : designTokensPath ?? "<design-tokens>";
598
- if (!existsSync(resolved)) {
762
+ if (!existsSync2(resolved)) {
599
763
  return {
600
764
  source: sourceLabel,
601
765
  status: "error",
@@ -605,7 +769,7 @@ function collectDesignTokenEvidence(projectRoot, designTokensPath) {
605
769
  };
606
770
  }
607
771
  const decantrTokens = parseDecantrCssTokenNames(projectRoot);
608
- const parsed = JSON.parse(readFileSync(resolved, "utf-8"));
772
+ const parsed = JSON.parse(readFileSync2(resolved, "utf-8"));
609
773
  const designKeys = flattenDesignTokenKeys(parsed);
610
774
  const missing = decantrTokens.filter((token) => {
611
775
  const bare = token.replace(/^--/, "");
@@ -648,19 +812,19 @@ function collectDesignTokenFinding(projectRoot, designTokensPath) {
648
812
  });
649
813
  }
650
814
  function baselinePath(projectRoot) {
651
- return join(projectRoot, ".decantr", "health-baseline.json");
815
+ return join2(projectRoot, ".decantr", "health-baseline.json");
652
816
  }
653
817
  function baselineDiffPath(projectRoot) {
654
- return join(projectRoot, ".decantr", "health-baseline-diff.json");
818
+ return join2(projectRoot, ".decantr", "health-baseline-diff.json");
655
819
  }
656
820
  function screenshotHashes(projectRoot) {
657
821
  const manifest = readJsonFile(
658
- join(projectRoot, ".decantr", "evidence", "visual-manifest.json")
822
+ join2(projectRoot, ".decantr", "evidence", "visual-manifest.json")
659
823
  );
660
824
  if (manifest?.routes) {
661
825
  return manifest.routes.filter((route) => typeof route.screenshot === "string").map((route) => ({
662
826
  path: route.screenshot,
663
- hash: route.screenshotHash ?? hashFile(join(projectRoot, route.screenshot))
827
+ hash: route.screenshotHash ?? hashFile(join2(projectRoot, route.screenshot))
664
828
  }));
665
829
  }
666
830
  return [];
@@ -688,7 +852,7 @@ function changedFilesSinceBaseline(projectRoot) {
688
852
  }
689
853
  function routeImpactsFromChangedFiles(report, changedFiles) {
690
854
  const analysis = readJsonFile(
691
- join(report.projectRoot, ".decantr", "analysis.json")
855
+ join2(report.projectRoot, ".decantr", "analysis.json")
692
856
  );
693
857
  const routeEntries = analysis?.routes?.routes ?? [];
694
858
  const impacted = /* @__PURE__ */ new Set();
@@ -721,7 +885,7 @@ function createHealthBaseline(projectRoot, report) {
721
885
  }
722
886
  function saveHealthBaseline(projectRoot, report) {
723
887
  const path = baselinePath(projectRoot);
724
- mkdirSync(dirname(path), { recursive: true });
888
+ mkdirSync(dirname2(path), { recursive: true });
725
889
  writeFileSync(
726
890
  path,
727
891
  JSON.stringify(createHealthBaseline(projectRoot, report), null, 2) + "\n",
@@ -760,7 +924,7 @@ function compareHealthBaseline(projectRoot, report) {
760
924
  }
761
925
  function saveHealthBaselineComparison(projectRoot, comparison) {
762
926
  const path = baselineDiffPath(projectRoot);
763
- mkdirSync(dirname(path), { recursive: true });
927
+ mkdirSync(dirname2(path), { recursive: true });
764
928
  writeFileSync(path, JSON.stringify(comparison, null, 2) + "\n", "utf-8");
765
929
  return path;
766
930
  }
@@ -877,7 +1041,9 @@ async function createProjectHealthReport(projectRoot = process.cwd(), options =
877
1041
  if (browserVerification?.finding && !isDuplicateFinding(seen, browserVerification.finding)) {
878
1042
  findings.push(browserVerification.finding);
879
1043
  }
880
- const finalCounts = countFindings(findings);
1044
+ const scopedFindings = scopeHealthFindingsToProject(projectRoot, findings);
1045
+ const finalCounts = countFindings(scopedFindings);
1046
+ const commandContext = commandContextForProject(projectRoot);
881
1047
  return {
882
1048
  $schema: PROJECT_HEALTH_SCHEMA_URL,
883
1049
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -901,7 +1067,7 @@ async function createProjectHealthReport(projectRoot = process.cwd(), options =
901
1067
  runtimeChecked: audit.runtimeAudit.routeHintsChecked,
902
1068
  runtimeMatched: audit.runtimeAudit.routeHintsMatched,
903
1069
  runtimeCoverageOk: audit.summary.runtimeAuditChecked ? audit.runtimeAudit.routeHintsCoverageOk : null,
904
- issues: routeIssuesFromFindings(findings)
1070
+ issues: routeIssuesFromFindings(scopedFindings)
905
1071
  },
906
1072
  packs: {
907
1073
  manifestPresent: Boolean(manifest),
@@ -913,10 +1079,10 @@ async function createProjectHealthReport(projectRoot = process.cwd(), options =
913
1079
  generatedAt: typeof manifest?.generatedAt === "string" ? manifest.generatedAt : null
914
1080
  },
915
1081
  ci: {
916
- recommendedCommand: "decantr ci --fail-on error",
1082
+ recommendedCommand: commandContext.ciCommand,
917
1083
  failOn: "error"
918
1084
  },
919
- findings
1085
+ findings: scopedFindings
920
1086
  };
921
1087
  }
922
1088
  function colorForStatus(status) {
@@ -1014,7 +1180,7 @@ async function createProjectEvidenceBundle(projectRoot, report, options = {}) {
1014
1180
  report,
1015
1181
  audit,
1016
1182
  assertions,
1017
- workspaceConfigPath: existsSync(join(projectRoot, ".decantr", "workspace.json")) ? join(projectRoot, ".decantr", "workspace.json") : null,
1183
+ workspaceConfigPath: existsSync2(join2(projectRoot, ".decantr", "workspace.json")) ? join2(projectRoot, ".decantr", "workspace.json") : null,
1018
1184
  designTokensPath: resolveOptionalPath(projectRoot, options.designTokensPath) ?? null,
1019
1185
  browser: await browserEvidenceFromOptions(projectRoot, options, report.routes.declared),
1020
1186
  designTokens: collectDesignTokenEvidence(projectRoot, options.designTokensPath)
@@ -1090,8 +1256,8 @@ async function cmdHealth(projectRoot = process.cwd(), options = {}) {
1090
1256
  ` : format === "json" ? formatProjectHealthJson(report) : format === "markdown" ? formatProjectHealthMarkdown(report) : formatProjectHealthText(report);
1091
1257
  const payload = baselineComparison && !options.evidence && format === "text" ? `${basePayload}${formatBaselineComparisonText(baselineComparison)}` : basePayload;
1092
1258
  if (options.output) {
1093
- const outputPath = isAbsolute(options.output) ? options.output : join(projectRoot, options.output);
1094
- mkdirSync(dirname(outputPath), { recursive: true });
1259
+ const outputPath = isAbsolute(options.output) ? options.output : join2(projectRoot, options.output);
1260
+ mkdirSync(dirname2(outputPath), { recursive: true });
1095
1261
  writeFileSync(outputPath, payload, "utf-8");
1096
1262
  if (!options.ci) {
1097
1263
  console.log(
@@ -1236,6 +1402,8 @@ function parseHealthArgs(args) {
1236
1402
  }
1237
1403
 
1238
1404
  export {
1405
+ listWorkspaceAppCandidates,
1406
+ resolveWorkspaceInfo,
1239
1407
  renderProjectHealthCiWorkflow,
1240
1408
  writeProjectHealthCiWorkflow,
1241
1409
  collectDesignTokenEvidence,
@@ -1,87 +1,12 @@
1
1
  import {
2
- createProjectHealthReport
3
- } from "./chunk-TMOCTDYY.js";
2
+ createProjectHealthReport,
3
+ listWorkspaceAppCandidates
4
+ } from "./chunk-DX2UDORT.js";
4
5
 
5
6
  // src/commands/workspace.ts
6
7
  import { execFileSync } from "child_process";
7
- import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
8
- import { dirname as dirname2, join as join2, relative, resolve as resolve2 } from "path";
9
-
10
- // src/workspace.ts
11
- import { existsSync, readdirSync, readFileSync } from "fs";
12
- import { dirname, join, resolve } from "path";
13
- function readPackageJson(dir) {
14
- const path = join(dir, "package.json");
15
- if (!existsSync(path)) return null;
16
- try {
17
- return JSON.parse(readFileSync(path, "utf-8"));
18
- } catch {
19
- return null;
20
- }
21
- }
22
- function hasWorkspaceMarker(dir) {
23
- if (existsSync(join(dir, "pnpm-workspace.yaml")) || existsSync(join(dir, "turbo.json")) || existsSync(join(dir, "nx.json"))) {
24
- return true;
25
- }
26
- const pkg = readPackageJson(dir);
27
- return Boolean(pkg?.workspaces);
28
- }
29
- function findWorkspaceRoot(startDir) {
30
- let current = resolve(startDir);
31
- while (true) {
32
- if (hasWorkspaceMarker(current)) return current;
33
- const parent = dirname(current);
34
- if (parent === current) return null;
35
- current = parent;
36
- }
37
- }
38
- function looksLikeApp(dir, options = {}) {
39
- const allowSourceDirs = options.allowSourceDirs ?? true;
40
- if (existsSync(join(dir, "next.config.js")) || existsSync(join(dir, "next.config.ts")) || existsSync(join(dir, "next.config.mjs")) || existsSync(join(dir, "vite.config.ts")) || existsSync(join(dir, "vite.config.js")) || existsSync(join(dir, "angular.json")) || existsSync(join(dir, "svelte.config.js")) || existsSync(join(dir, "svelte.config.ts")) || existsSync(join(dir, "astro.config.mjs")) || allowSourceDirs && (existsSync(join(dir, "src")) || existsSync(join(dir, "app")) || existsSync(join(dir, "pages")))) {
41
- return true;
42
- }
43
- const pkg = readPackageJson(dir);
44
- const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
45
- return Boolean(
46
- deps.react || deps.next || deps.vue || deps.svelte || deps["@angular/core"] || deps.astro || deps.nuxt
47
- );
48
- }
49
- function listWorkspaceApps(workspaceRoot) {
50
- const candidates = [];
51
- for (const base of ["apps", "packages"]) {
52
- const baseDir = join(workspaceRoot, base);
53
- if (!existsSync(baseDir)) continue;
54
- for (const entry of readdirSync(baseDir, { withFileTypes: true })) {
55
- if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
56
- const candidate = join(baseDir, entry.name);
57
- if (looksLikeApp(candidate, { allowSourceDirs: base === "apps" })) {
58
- candidates.push(`${base}/${entry.name}`);
59
- }
60
- }
61
- }
62
- return candidates.sort();
63
- }
64
- function listWorkspaceAppCandidates(workspaceRoot) {
65
- return listWorkspaceApps(resolve(workspaceRoot));
66
- }
67
- function resolveWorkspaceInfo(cwd, projectArg) {
68
- const absoluteCwd = resolve(cwd);
69
- const workspaceRoot = findWorkspaceRoot(absoluteCwd) ?? absoluteCwd;
70
- const appRoot = projectArg ? resolve(absoluteCwd, projectArg) : absoluteCwd;
71
- const appCandidates = listWorkspaceApps(workspaceRoot);
72
- const projectScope = workspaceRoot !== appRoot || appCandidates.length > 0 ? "workspace-app" : "single-app";
73
- const requiresProjectSelection = !projectArg && workspaceRoot === absoluteCwd && appCandidates.length > 0;
74
- return {
75
- cwd: absoluteCwd,
76
- workspaceRoot,
77
- appRoot,
78
- projectScope,
79
- appCandidates,
80
- requiresProjectSelection
81
- };
82
- }
83
-
84
- // src/commands/workspace.ts
8
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "fs";
9
+ import { dirname, join, relative, resolve } from "path";
85
10
  var BOLD = "\x1B[1m";
86
11
  var DIM = "\x1B[2m";
87
12
  var GREEN = "\x1B[32m";
@@ -100,12 +25,12 @@ var DEFAULT_IGNORES = /* @__PURE__ */ new Set([
100
25
  "playwright-report"
101
26
  ]);
102
27
  function workspaceConfigPath(root) {
103
- return join2(root, ".decantr", "workspace.json");
28
+ return join(root, ".decantr", "workspace.json");
104
29
  }
105
30
  function readWorkspaceConfig(root) {
106
31
  const path = workspaceConfigPath(root);
107
- if (!existsSync2(path)) return null;
108
- return JSON.parse(readFileSync2(path, "utf-8"));
32
+ if (!existsSync(path)) return null;
33
+ return JSON.parse(readFileSync(path, "utf-8"));
109
34
  }
110
35
  function normalizeProjectPath(raw) {
111
36
  const normalized = raw.replace(/^\.\/+/, "").replace(/\/+$/, "");
@@ -124,21 +49,21 @@ function discoverProjectPaths(root, config) {
124
49
  if (depth > 6) return;
125
50
  const rel = relative(root, dir).replace(/\\/g, "/");
126
51
  if (rel && [...ignored].some((entry) => rel === entry || rel.startsWith(`${entry}/`))) return;
127
- if (existsSync2(join2(dir, "decantr.essence.json"))) {
52
+ if (existsSync(join(dir, "decantr.essence.json"))) {
128
53
  results.add(rel || ".");
129
54
  return;
130
55
  }
131
- for (const entry of readdirSync2(dir, { withFileTypes: true })) {
56
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
132
57
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
133
58
  if (ignored.has(entry.name)) continue;
134
- walk(join2(dir, entry.name), depth + 1);
59
+ walk(join(dir, entry.name), depth + 1);
135
60
  }
136
61
  }
137
62
  walk(root, 0);
138
63
  return [...results].sort();
139
64
  }
140
65
  function listWorkspaceProjects(root = process.cwd()) {
141
- const workspaceRoot = resolve2(root);
66
+ const workspaceRoot = resolve(root);
142
67
  const config = readWorkspaceConfig(workspaceRoot);
143
68
  const byPath = /* @__PURE__ */ new Map();
144
69
  for (const project of config?.projects ?? []) {
@@ -146,7 +71,7 @@ function listWorkspaceProjects(root = process.cwd()) {
146
71
  byPath.set(path, {
147
72
  id: project.id ?? projectIdFromPath(path),
148
73
  path,
149
- absolutePath: resolve2(workspaceRoot, path),
74
+ absolutePath: resolve(workspaceRoot, path),
150
75
  owner: project.owner ?? null,
151
76
  tags: project.tags ?? [],
152
77
  criticality: project.criticality ?? "normal",
@@ -159,7 +84,7 @@ function listWorkspaceProjects(root = process.cwd()) {
159
84
  byPath.set(path, {
160
85
  id: projectIdFromPath(path),
161
86
  path,
162
- absolutePath: resolve2(workspaceRoot, path),
87
+ absolutePath: resolve(workspaceRoot, path),
163
88
  owner: null,
164
89
  tags: [],
165
90
  criticality: "normal",
@@ -226,7 +151,7 @@ async function mapLimited(items, concurrency, fn) {
226
151
  return results;
227
152
  }
228
153
  async function createWorkspaceHealthReport(root = process.cwd(), options = {}) {
229
- const workspaceRoot = resolve2(root);
154
+ const workspaceRoot = resolve(root);
230
155
  const config = readWorkspaceConfig(workspaceRoot);
231
156
  const since = options.since ?? "origin/main";
232
157
  const changed = options.changedOnly ? changedPaths(workspaceRoot, since) : /* @__PURE__ */ new Set();
@@ -406,8 +331,8 @@ async function cmdWorkspace(workspaceRoot = process.cwd(), args = ["workspace"])
406
331
  const payload = options.json ? `${JSON.stringify(report, null, 2)}
407
332
  ` : options.markdown ? formatWorkspaceHealthMarkdown(report) : formatWorkspaceHealthText(report);
408
333
  if (options.output) {
409
- mkdirSync(dirname2(resolve2(workspaceRoot, options.output)), { recursive: true });
410
- writeFileSync(resolve2(workspaceRoot, options.output), payload, "utf-8");
334
+ mkdirSync(dirname(resolve(workspaceRoot, options.output)), { recursive: true });
335
+ writeFileSync(resolve(workspaceRoot, options.output), payload, "utf-8");
411
336
  if (!options.ci)
412
337
  console.log(`${GREEN}Wrote Decantr workspace health:${RESET} ${options.output}`);
413
338
  } else {
@@ -419,7 +344,6 @@ async function cmdWorkspace(workspaceRoot = process.cwd(), args = ["workspace"])
419
344
  }
420
345
 
421
346
  export {
422
- resolveWorkspaceInfo,
423
347
  listWorkspaceProjects,
424
348
  listWorkspaceCandidates,
425
349
  createWorkspaceHealthReport,
@@ -4989,7 +4989,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
4989
4989
  themeData,
4990
4990
  themeMode: mode,
4991
4991
  voiceTone: storedVoice?.tone ? storedVoice.tone.split(".")[0] + "." : void 0,
4992
- spatialHints: sectionSpatialHints
4992
+ spatialHints: sectionSpatialHints,
4993
+ adoptionMode: effectiveAdoptionMode
4993
4994
  });
4994
4995
  const sectionContextPath = join2(contextDir, `section-${section.id}.md`);
4995
4996
  writeFileSync2(sectionContextPath, contextContent);
@@ -5345,7 +5346,8 @@ function generateSectionContext(input) {
5345
5346
  themeHints,
5346
5347
  constraints,
5347
5348
  shellInfo,
5348
- spatialHints
5349
+ spatialHints,
5350
+ adoptionMode
5349
5351
  } = input;
5350
5352
  const lines = [];
5351
5353
  lines.push(`# Section: ${section.id}`);
@@ -5429,9 +5431,15 @@ function generateSectionContext(input) {
5429
5431
  const decoratorDefs = input.themeData?.decorator_definitions;
5430
5432
  const totalDecoratorCount = decoratorDefs && Object.keys(decoratorDefs).length || decorators.length;
5431
5433
  if (totalDecoratorCount > 0) {
5432
- lines.push(
5433
- `**Theme decorators:** ${totalDecoratorCount} \`${themeName}-*\` classes \u2014 full Class/Intent/Apply-to table in \`section-${section.id}-pack.md\` (preferred) and DECANTR.md "Decorator Quick Reference". MUST apply.`
5434
- );
5434
+ if (adoptionMode === "contract-only") {
5435
+ lines.push(
5436
+ `**Theme intent:** ${totalDecoratorCount} \`${themeName}-*\` decorator reference(s) exist, but this project is contract-only. Translate the intent into the app's current styling system instead of applying Decantr decorator classes directly.`
5437
+ );
5438
+ } else {
5439
+ lines.push(
5440
+ `**Theme decorators:** ${totalDecoratorCount} \`${themeName}-*\` classes \u2014 full Class/Intent/Apply-to table in \`section-${section.id}-pack.md\` (preferred) and DECANTR.md "Decorator Quick Reference". MUST apply.`
5441
+ );
5442
+ }
5435
5443
  lines.push("");
5436
5444
  }
5437
5445
  if (themeHints) {
@@ -5454,9 +5462,15 @@ function generateSectionContext(input) {
5454
5462
  }
5455
5463
  const themePrefix = themeName.split("-")[0] || themeName;
5456
5464
  lines.push("");
5457
- lines.push(
5458
- `Usage: \`className={css('_flex _col _gap4') + ' d-surface ${themePrefix}-glass'}\` \u2014 atoms via css(), treatments and theme decorators as plain class strings.`
5459
- );
5465
+ if (adoptionMode === "contract-only") {
5466
+ lines.push(
5467
+ "Usage: implement this section through the app's existing styling authority (design-system components, Tailwind/Sass/theme tokens, CVA variants, or accepted local rules). Do not add `@decantr/css`, `css(...)`, `d-*` treatments, or Decantr token CSS unless adoption mode changes."
5468
+ );
5469
+ } else {
5470
+ lines.push(
5471
+ `Usage: \`className={css('_flex _col _gap4') + ' d-surface ${themePrefix}-glass'}\` \u2014 atoms via css(), treatments and theme decorators as plain class strings.`
5472
+ );
5473
+ }
5460
5474
  lines.push("");
5461
5475
  lines.push("---");
5462
5476
  lines.push("");
@@ -10,7 +10,7 @@ import {
10
10
  renderProjectHealthCiWorkflow,
11
11
  shouldFailHealth,
12
12
  writeProjectHealthCiWorkflow
13
- } from "./chunk-TMOCTDYY.js";
13
+ } from "./chunk-DX2UDORT.js";
14
14
  import "./chunk-34TZXWIF.js";
15
15
  export {
16
16
  cmdHealth,
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import "./chunk-N7A3WUZ2.js";
2
- import "./chunk-V3XAQWKD.js";
3
- import "./chunk-T5INVSOP.js";
4
- import "./chunk-TMOCTDYY.js";
1
+ import "./chunk-AXMGQ5IB.js";
2
+ import "./chunk-RXF7ZYGK.js";
3
+ import "./chunk-R57DMFLF.js";
4
+ import "./chunk-DX2UDORT.js";
5
5
  import "./chunk-34TZXWIF.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createWorkspaceHealthReport
3
- } from "./chunk-T5INVSOP.js";
3
+ } from "./chunk-R57DMFLF.js";
4
4
  import {
5
5
  createProjectHealthReport
6
- } from "./chunk-TMOCTDYY.js";
6
+ } from "./chunk-DX2UDORT.js";
7
7
  import {
8
8
  sendStudioHealthRefreshedTelemetry,
9
9
  sendStudioStartedTelemetry
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RegistryClient,
3
3
  refreshDerivedFiles
4
- } from "./chunk-V3XAQWKD.js";
4
+ } from "./chunk-RXF7ZYGK.js";
5
5
 
6
6
  // src/commands/upgrade.ts
7
7
  import { existsSync, readFileSync, writeFileSync } from "fs";
@@ -7,8 +7,8 @@ import {
7
7
  listWorkspaceProjects,
8
8
  parseWorkspaceArgs,
9
9
  shouldFailWorkspaceHealth
10
- } from "./chunk-T5INVSOP.js";
11
- import "./chunk-TMOCTDYY.js";
10
+ } from "./chunk-R57DMFLF.js";
11
+ import "./chunk-DX2UDORT.js";
12
12
  import "./chunk-34TZXWIF.js";
13
13
  export {
14
14
  cmdWorkspace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decantr/cli",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "description": "Decantr CLI - scaffold, audit, inspect Project Health, and maintain Decantr projects from the terminal",
5
5
  "keywords": [
6
6
  "decantr",
@@ -49,10 +49,10 @@
49
49
  "dependencies": {
50
50
  "ajv": "^8.20.0",
51
51
  "@decantr/core": "2.1.0",
52
- "@decantr/registry": "2.2.0",
53
52
  "@decantr/essence-spec": "2.0.1",
53
+ "@decantr/registry": "2.2.0",
54
54
  "@decantr/telemetry": "2.2.1",
55
- "@decantr/verifier": "2.3.0"
55
+ "@decantr/verifier": "2.3.2"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsup",