@decantr/cli 3.0.0-next.0 → 3.0.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.
@@ -22,7 +22,7 @@ import {
22
22
  listWorkspaceCandidates,
23
23
  listWorkspaceProjects,
24
24
  shouldFailWorkspaceHealth
25
- } from "./chunk-GXC5IJQY.js";
25
+ } from "./chunk-B2PJDAMS.js";
26
26
  import {
27
27
  acceptBrownfieldLocalLaw,
28
28
  acceptStyleBridge,
@@ -52,7 +52,7 @@ import {
52
52
  writeBrownfieldCodifyProposal,
53
53
  writeHostedPatternMappingProposal,
54
54
  writeStyleBridgeProposal
55
- } from "./chunk-WUIFEHWM.js";
55
+ } from "./chunk-4NDOHCYY.js";
56
56
  import {
57
57
  buildGuardRegistryContext,
58
58
  createDoctrineMap,
@@ -69,7 +69,7 @@ import {
69
69
  sendCliCommandTelemetry,
70
70
  sendNewProjectCompletedTelemetry,
71
71
  writeDoctrineMap
72
- } from "./chunk-MNZKOZW7.js";
72
+ } from "./chunk-7Z74ETDR.js";
73
73
 
74
74
  // src/index.ts
75
75
  import { existsSync as existsSync28, mkdirSync as mkdirSync15, readdirSync as readdirSync8, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "fs";
@@ -567,7 +567,10 @@ var solidPackagePlan = {
567
567
  function writeReactViteProject(projectDir, title, routingMode) {
568
568
  const srcDir = join4(projectDir, "src");
569
569
  const routerImport = routingMode === "hash" ? "HashRouter" : "BrowserRouter";
570
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-app", reactVitePackagePlan));
570
+ writeJson(
571
+ join4(projectDir, "package.json"),
572
+ packagePlanPackageJson(projectDir, "decantr-app", reactVitePackagePlan)
573
+ );
571
574
  writeFileSync4(
572
575
  join4(projectDir, "vite.config.ts"),
573
576
  `import { defineConfig } from 'vite';
@@ -579,7 +582,10 @@ export default defineConfig({
579
582
  `
580
583
  );
581
584
  writeViteTsConfig(projectDir, { jsx: "react-jsx" });
582
- writeJson(join4(projectDir, "tsconfig.app.json"), JSON.parse(readFileSync3(join4(projectDir, "tsconfig.json"), "utf-8")));
585
+ writeJson(
586
+ join4(projectDir, "tsconfig.app.json"),
587
+ JSON.parse(readFileSync3(join4(projectDir, "tsconfig.json"), "utf-8"))
588
+ );
583
589
  writeIndexHtml(projectDir, title, "/src/main.tsx");
584
590
  mkdirp(srcDir);
585
591
  writeFileSync4(
@@ -642,9 +648,18 @@ export function App() {
642
648
  function writeNextProject(projectDir, title) {
643
649
  const appDir = join4(projectDir, "app");
644
650
  const stylesDir = join4(projectDir, "src", "styles");
645
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-next-app", nextPackagePlan));
646
- writeFileSync4(join4(projectDir, "next.config.ts"), 'import type { NextConfig } from "next";\n\nconst nextConfig: NextConfig = {};\n\nexport default nextConfig;\n');
647
- writeFileSync4(join4(projectDir, "next-env.d.ts"), '/// <reference types="next" />\n/// <reference types="next/image-types/global" />\n\n// This file is generated by Next.js.\n');
651
+ writeJson(
652
+ join4(projectDir, "package.json"),
653
+ packagePlanPackageJson(projectDir, "decantr-next-app", nextPackagePlan)
654
+ );
655
+ writeFileSync4(
656
+ join4(projectDir, "next.config.ts"),
657
+ 'import type { NextConfig } from "next";\n\nconst nextConfig: NextConfig = {};\n\nexport default nextConfig;\n'
658
+ );
659
+ writeFileSync4(
660
+ join4(projectDir, "next-env.d.ts"),
661
+ '/// <reference types="next" />\n/// <reference types="next/image-types/global" />\n\n// This file is generated by Next.js.\n'
662
+ );
648
663
  writeJson(join4(projectDir, "tsconfig.json"), {
649
664
  compilerOptions: {
650
665
  target: "ES2017",
@@ -711,7 +726,10 @@ export default function HomePage() {
711
726
  }
712
727
  function writeVanillaProject(projectDir, title, routingMode) {
713
728
  const srcDir = join4(projectDir, "src");
714
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-vanilla-app", vanillaPackagePlan));
729
+ writeJson(
730
+ join4(projectDir, "package.json"),
731
+ packagePlanPackageJson(projectDir, "decantr-vanilla-app", vanillaPackagePlan)
732
+ );
715
733
  writeIndexHtml(projectDir, title, "/src/main.js");
716
734
  mkdirp(srcDir);
717
735
  writeFileSync4(
@@ -747,14 +765,23 @@ root.innerHTML = \`
747
765
  function writeVueProject(projectDir, title, routingMode) {
748
766
  const srcDir = join4(projectDir, "src");
749
767
  const historyFactory = routingMode === "hash" ? "createWebHashHistory" : "createWebHistory";
750
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-vue-app", vuePackagePlan));
751
- writeFileSync4(join4(projectDir, "vite.config.ts"), `import { defineConfig } from 'vite';
768
+ writeJson(
769
+ join4(projectDir, "package.json"),
770
+ packagePlanPackageJson(projectDir, "decantr-vue-app", vuePackagePlan)
771
+ );
772
+ writeFileSync4(
773
+ join4(projectDir, "vite.config.ts"),
774
+ `import { defineConfig } from 'vite';
752
775
  import vue from '@vitejs/plugin-vue';
753
776
 
754
777
  export default defineConfig({ plugins: [vue()] });
755
- `);
778
+ `
779
+ );
756
780
  writeViteTsConfig(projectDir);
757
- writeFileSync4(join4(projectDir, "env.d.ts"), '/// <reference types="vite/client" />\n\ndeclare module "*.vue";\n');
781
+ writeFileSync4(
782
+ join4(projectDir, "env.d.ts"),
783
+ '/// <reference types="vite/client" />\n\ndeclare module "*.vue";\n'
784
+ );
758
785
  writeIndexHtml(projectDir, title, "/src/main.ts");
759
786
  mkdirp(srcDir);
760
787
  writeFileSync4(
@@ -802,21 +829,35 @@ import { css } from '@decantr/css';
802
829
  }
803
830
  function writeSvelteProject(projectDir, title) {
804
831
  const routesDir = join4(projectDir, "src", "routes");
805
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-svelte-app", sveltePackagePlan));
806
- writeFileSync4(join4(projectDir, "svelte.config.js"), `import adapter from '@sveltejs/adapter-auto';
832
+ writeJson(
833
+ join4(projectDir, "package.json"),
834
+ packagePlanPackageJson(projectDir, "decantr-svelte-app", sveltePackagePlan)
835
+ );
836
+ writeFileSync4(
837
+ join4(projectDir, "svelte.config.js"),
838
+ `import adapter from '@sveltejs/adapter-auto';
807
839
  import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
808
840
 
809
841
  export default { preprocess: vitePreprocess(), kit: { adapter: adapter() } };
810
- `);
811
- writeFileSync4(join4(projectDir, "vite.config.ts"), `import { sveltekit } from '@sveltejs/kit/vite';
842
+ `
843
+ );
844
+ writeFileSync4(
845
+ join4(projectDir, "vite.config.ts"),
846
+ `import { sveltekit } from '@sveltejs/kit/vite';
812
847
  import { defineConfig } from 'vite';
813
848
 
814
849
  export default defineConfig({ plugins: [sveltekit()] });
815
- `);
850
+ `
851
+ );
816
852
  writeViteTsConfig(projectDir);
817
853
  mkdirp(routesDir);
818
- writeFileSync4(join4(projectDir, "src", "app.html"), '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n %sveltekit.head%\n </head>\n <body data-sveltekit-preload-data="hover">\n <div style="display: contents">%sveltekit.body%</div>\n </body>\n</html>\n');
819
- writeFileSync4(join4(routesDir, "+layout.svelte"), `<script lang="ts">
854
+ writeFileSync4(
855
+ join4(projectDir, "src", "app.html"),
856
+ '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n %sveltekit.head%\n </head>\n <body data-sveltekit-preload-data="hover">\n <div style="display: contents">%sveltekit.body%</div>\n </body>\n</html>\n'
857
+ );
858
+ writeFileSync4(
859
+ join4(routesDir, "+layout.svelte"),
860
+ `<script lang="ts">
820
861
  import '../styles/global.css';
821
862
  import '../styles/tokens.css';
822
863
  import '../styles/treatments.css';
@@ -824,7 +865,8 @@ let { children } = $props();
824
865
  </script>
825
866
 
826
867
  {@render children()}
827
- `);
868
+ `
869
+ );
828
870
  writeFileSync4(
829
871
  join4(routesDir, "+page.svelte"),
830
872
  `<script lang="ts">
@@ -852,7 +894,10 @@ import { css } from '@decantr/css';
852
894
  }
853
895
  function writeAngularProject(projectDir, title) {
854
896
  const appDir = join4(projectDir, "src", "app");
855
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-angular-app", angularPackagePlan));
897
+ writeJson(
898
+ join4(projectDir, "package.json"),
899
+ packagePlanPackageJson(projectDir, "decantr-angular-app", angularPackagePlan)
900
+ );
856
901
  writeJson(join4(projectDir, "angular.json"), {
857
902
  version: 1,
858
903
  projects: {
@@ -891,27 +936,40 @@ function writeAngularProject(projectDir, title) {
891
936
  lib: ["ES2022", "DOM"]
892
937
  }
893
938
  });
894
- writeJson(join4(projectDir, "tsconfig.app.json"), { extends: "./tsconfig.json", files: ["src/main.ts"], include: ["src/**/*.d.ts"] });
939
+ writeJson(join4(projectDir, "tsconfig.app.json"), {
940
+ extends: "./tsconfig.json",
941
+ files: ["src/main.ts"],
942
+ include: ["src/**/*.d.ts"]
943
+ });
895
944
  mkdirp(appDir);
896
- writeFileSync4(join4(projectDir, "src", "index.html"), `<!doctype html>
945
+ writeFileSync4(
946
+ join4(projectDir, "src", "index.html"),
947
+ `<!doctype html>
897
948
  <html lang="en">
898
949
  <head><meta charset="utf-8"><title>${title}</title><meta name="viewport" content="width=device-width, initial-scale=1"></head>
899
950
  <body><app-root></app-root></body>
900
951
  </html>
901
- `);
902
- writeFileSync4(join4(projectDir, "src", "main.ts"), `import { bootstrapApplication } from '@angular/platform-browser';
952
+ `
953
+ );
954
+ writeFileSync4(
955
+ join4(projectDir, "src", "main.ts"),
956
+ `import { bootstrapApplication } from '@angular/platform-browser';
903
957
  import { provideRouter } from '@angular/router';
904
958
  import { AppComponent } from './app/app.component';
905
959
  import { routes } from './app/app.routes';
906
960
 
907
961
  bootstrapApplication(AppComponent, { providers: [provideRouter(routes)] }).catch((err) => console.error(err));
908
- `);
962
+ `
963
+ );
909
964
  writeFileSync4(join4(projectDir, "src", "styles.css"), '@import "./styles/global.css";\n');
910
- writeFileSync4(join4(appDir, "app.routes.ts"), `import type { Routes } from '@angular/router';
965
+ writeFileSync4(
966
+ join4(appDir, "app.routes.ts"),
967
+ `import type { Routes } from '@angular/router';
911
968
  import { AppComponent } from './app.component';
912
969
 
913
970
  export const routes: Routes = [{ path: '', component: AppComponent }];
914
- `);
971
+ `
972
+ );
915
973
  writeFileSync4(
916
974
  join4(appDir, "app.component.ts"),
917
975
  `import { Component } from '@angular/core';
@@ -941,14 +999,23 @@ export class AppComponent {}
941
999
  function writeSolidProject(projectDir, title, routingMode) {
942
1000
  const srcDir = join4(projectDir, "src");
943
1001
  const routerImport = routingMode === "hash" ? "HashRouter" : "Router";
944
- writeJson(join4(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-solid-app", solidPackagePlan));
945
- writeFileSync4(join4(projectDir, "vite.config.ts"), `import { defineConfig } from 'vite';
1002
+ writeJson(
1003
+ join4(projectDir, "package.json"),
1004
+ packagePlanPackageJson(projectDir, "decantr-solid-app", solidPackagePlan)
1005
+ );
1006
+ writeFileSync4(
1007
+ join4(projectDir, "vite.config.ts"),
1008
+ `import { defineConfig } from 'vite';
946
1009
  import solid from 'vite-plugin-solid';
947
1010
 
948
1011
  export default defineConfig({ plugins: [solid()] });
949
- `);
1012
+ `
1013
+ );
950
1014
  writeViteTsConfig(projectDir, { jsx: "preserve" });
951
- writeJson(join4(projectDir, "tsconfig.app.json"), JSON.parse(readFileSync3(join4(projectDir, "tsconfig.json"), "utf-8")));
1015
+ writeJson(
1016
+ join4(projectDir, "tsconfig.app.json"),
1017
+ JSON.parse(readFileSync3(join4(projectDir, "tsconfig.json"), "utf-8"))
1018
+ );
952
1019
  writeIndexHtml(projectDir, title, "/src/main.tsx");
953
1020
  mkdirp(srcDir);
954
1021
  writeFileSync4(
@@ -1019,7 +1086,10 @@ var DECANTR_ADAPTERS = {
1019
1086
  },
1020
1087
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
1021
1088
  packagePlan: reactVitePackagePlan,
1022
- docs: { summary: "React + Vite runnable starter.", notes: ["Uses React Router and @decantr/css."] },
1089
+ docs: {
1090
+ summary: "React + Vite runnable starter.",
1091
+ notes: ["Uses React Router and @decantr/css."]
1092
+ },
1023
1093
  writeProjectFiles: writeReactViteProject
1024
1094
  },
1025
1095
  "next-app": {
@@ -1038,7 +1108,10 @@ var DECANTR_ADAPTERS = {
1038
1108
  },
1039
1109
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: ".next" },
1040
1110
  packagePlan: nextPackagePlan,
1041
- docs: { summary: "Next.js App Router runnable starter.", notes: ["Uses App Router for greenfield bootstraps."] },
1111
+ docs: {
1112
+ summary: "Next.js App Router runnable starter.",
1113
+ notes: ["Uses App Router for greenfield bootstraps."]
1114
+ },
1042
1115
  writeProjectFiles: writeNextProject
1043
1116
  },
1044
1117
  "vanilla-vite": {
@@ -1057,7 +1130,10 @@ var DECANTR_ADAPTERS = {
1057
1130
  },
1058
1131
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
1059
1132
  packagePlan: vanillaPackagePlan,
1060
- docs: { summary: "Plain web runnable starter.", notes: ["Uses DOM APIs and @decantr/css without a UI framework."] },
1133
+ docs: {
1134
+ summary: "Plain web runnable starter.",
1135
+ notes: ["Uses DOM APIs and @decantr/css without a UI framework."]
1136
+ },
1061
1137
  writeProjectFiles: writeVanillaProject
1062
1138
  },
1063
1139
  "vue-vite": {
@@ -1076,7 +1152,10 @@ var DECANTR_ADAPTERS = {
1076
1152
  },
1077
1153
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
1078
1154
  packagePlan: vuePackagePlan,
1079
- docs: { summary: "Vue 3 + Vite runnable starter.", notes: ["Uses Vue Router and @decantr/css."] },
1155
+ docs: {
1156
+ summary: "Vue 3 + Vite runnable starter.",
1157
+ notes: ["Uses Vue Router and @decantr/css."]
1158
+ },
1080
1159
  writeProjectFiles: writeVueProject
1081
1160
  },
1082
1161
  sveltekit: {
@@ -1095,7 +1174,10 @@ var DECANTR_ADAPTERS = {
1095
1174
  },
1096
1175
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: ".svelte-kit" },
1097
1176
  packagePlan: sveltePackagePlan,
1098
- docs: { summary: "SvelteKit runnable starter.", notes: ["Uses SvelteKit file routing and @decantr/css."] },
1177
+ docs: {
1178
+ summary: "SvelteKit runnable starter.",
1179
+ notes: ["Uses SvelteKit file routing and @decantr/css."]
1180
+ },
1099
1181
  writeProjectFiles: writeSvelteProject
1100
1182
  },
1101
1183
  angular: {
@@ -1114,7 +1196,10 @@ var DECANTR_ADAPTERS = {
1114
1196
  },
1115
1197
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
1116
1198
  packagePlan: angularPackagePlan,
1117
- docs: { summary: "Angular standalone runnable starter.", notes: ["Uses Angular Router and global Decantr CSS files."] },
1199
+ docs: {
1200
+ summary: "Angular standalone runnable starter.",
1201
+ notes: ["Uses Angular Router and global Decantr CSS files."]
1202
+ },
1118
1203
  writeProjectFiles: writeAngularProject
1119
1204
  },
1120
1205
  "solid-vite": {
@@ -1133,7 +1218,10 @@ var DECANTR_ADAPTERS = {
1133
1218
  },
1134
1219
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
1135
1220
  packagePlan: solidPackagePlan,
1136
- docs: { summary: "Solid + Vite runnable starter.", notes: ["Uses @solidjs/router and @decantr/css."] },
1221
+ docs: {
1222
+ summary: "Solid + Vite runnable starter.",
1223
+ notes: ["Uses @solidjs/router and @decantr/css."]
1224
+ },
1137
1225
  writeProjectFiles: writeSolidProject
1138
1226
  },
1139
1227
  "generic-web": {
@@ -1151,7 +1239,10 @@ var DECANTR_ADAPTERS = {
1151
1239
  componentRoots: ["src/components", "components"]
1152
1240
  },
1153
1241
  verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
1154
- docs: { summary: "Contract-only fallback for unsupported web targets.", notes: ["Does not write framework runtime files."] }
1242
+ docs: {
1243
+ summary: "Contract-only fallback for unsupported web targets.",
1244
+ notes: ["Does not write framework runtime files."]
1245
+ }
1155
1246
  }
1156
1247
  };
1157
1248
  var TARGET_ALIASES = /* @__PURE__ */ new Map();
@@ -5739,7 +5830,10 @@ function validatePassThroughFlagValue(flag, value) {
5739
5830
  if (value.length > 512) {
5740
5831
  throw new Error(`--${flag} is too long.`);
5741
5832
  }
5742
- if (/[\u0000-\u001f\u007f]/.test(value)) {
5833
+ if (Array.from(value).some((character) => {
5834
+ const code = character.charCodeAt(0);
5835
+ return code <= 31 || code === 127;
5836
+ })) {
5743
5837
  throw new Error(`--${flag} contains unsupported control characters.`);
5744
5838
  }
5745
5839
  return value;
@@ -6029,8 +6123,8 @@ async function cmdPublish(type, name, projectRoot = process.cwd()) {
6029
6123
  import { createHash } from "crypto";
6030
6124
  import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync16, statSync as statSync5 } from "fs";
6031
6125
  import { isAbsolute as isAbsolute2, join as join24, relative as relative5 } from "path";
6032
- import { collectMissingPackManifestFiles as collectMissingPackManifestFiles2 } from "@decantr/verifier";
6033
6126
  import { isV4 as isV45 } from "@decantr/essence-spec";
6127
+ import { collectMissingPackManifestFiles as collectMissingPackManifestFiles2 } from "@decantr/verifier";
6034
6128
  var GREEN9 = "\x1B[32m";
6035
6129
  var RED7 = "\x1B[31m";
6036
6130
  var DIM9 = "\x1B[2m";
@@ -6716,12 +6810,16 @@ ${BOLD7}Decantr telemetry${RESET13}`);
6716
6810
  DIM13 + "Run `decantr telemetry link` after login to attach these opaque IDs to your Decantr account/org." + RESET13
6717
6811
  );
6718
6812
  } else {
6719
- console.log(DIM13 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET13);
6813
+ console.log(
6814
+ DIM13 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET13
6815
+ );
6720
6816
  }
6721
6817
  }
6722
6818
  function printTelemetryExplain(projectRoot, options) {
6723
6819
  const status = getCliTelemetryIdentityStatus(projectRoot, { create: false });
6724
- const cliEvents = DECANTR_TELEMETRY_EVENT_CATALOG.filter((entry) => entry.allowedSources.includes("cli")).map((entry) => ({
6820
+ const cliEvents = DECANTR_TELEMETRY_EVENT_CATALOG.filter(
6821
+ (entry) => entry.allowedSources.includes("cli")
6822
+ ).map((entry) => ({
6725
6823
  name: entry.name,
6726
6824
  bucket: entry.bucket,
6727
6825
  privacy: entry.privacy,
@@ -6800,7 +6898,9 @@ async function linkTelemetryIdentity(projectRoot, options) {
6800
6898
  optIn(projectRoot);
6801
6899
  }
6802
6900
  if (!isOptedIn(projectRoot)) {
6803
- throw new Error("This project has not opted into telemetry. Re-run with --enable or use `decantr init --telemetry`.");
6901
+ throw new Error(
6902
+ "This project has not opted into telemetry. Re-run with --enable or use `decantr init --telemetry`."
6903
+ );
6804
6904
  }
6805
6905
  const identity = getCliTelemetryIdentityStatus(projectRoot, { create: true });
6806
6906
  if (!identity.installId && !identity.projectId) {
@@ -6808,9 +6908,13 @@ async function linkTelemetryIdentity(projectRoot, options) {
6808
6908
  }
6809
6909
  const apiKey = options.apiKey ?? getApiKeyOrToken();
6810
6910
  if (!apiKey) {
6811
- throw new Error("Run `decantr login --api-key=<key>` or pass `--api-key <key>` before linking telemetry.");
6911
+ throw new Error(
6912
+ "Run `decantr login --api-key=<key>` or pass `--api-key <key>` before linking telemetry."
6913
+ );
6812
6914
  }
6813
- const apiUrl = trimTrailingSlashes(options.apiUrl ?? process.env.DECANTR_API_URL ?? DEFAULT_API_URL);
6915
+ const apiUrl = trimTrailingSlashes(
6916
+ options.apiUrl ?? process.env.DECANTR_API_URL ?? DEFAULT_API_URL
6917
+ );
6814
6918
  const response = await fetch(`${apiUrl}/me/telemetry-link`, {
6815
6919
  method: "POST",
6816
6920
  headers: {
@@ -6834,7 +6938,9 @@ async function linkTelemetryIdentity(projectRoot, options) {
6834
6938
  console.log(` Install ID: ${identity.installId ?? `${DIM13}none${RESET13}`}`);
6835
6939
  console.log(` Project ID: ${identity.projectId ?? `${DIM13}none${RESET13}`}`);
6836
6940
  if (options.org) console.log(` Org: ${CYAN7}${options.org}${RESET13}`);
6837
- console.log(DIM13 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET13);
6941
+ console.log(
6942
+ DIM13 + "These opaque IDs now attribute opted-in CLI usage to your Decantr account/org." + RESET13
6943
+ );
6838
6944
  }
6839
6945
  function parseTelemetryOptions(args) {
6840
6946
  const options = {};
@@ -8604,7 +8710,9 @@ function localPatternMatches(projectRoot, query) {
8604
8710
  if (!projectRoot) return [];
8605
8711
  const pack = readLocalPatternPack(projectRoot);
8606
8712
  const patterns = Array.isArray(pack?.patterns) ? pack.patterns : [];
8607
- const queryTerms = query.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 1).flatMap((term) => term.endsWith("s") && term.length > 3 ? [term, term.slice(0, -1)] : [term]);
8713
+ const queryTerms = query.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 1).flatMap(
8714
+ (term) => term.endsWith("s") && term.length > 3 ? [term, term.slice(0, -1)] : [term]
8715
+ );
8608
8716
  if (queryTerms.length === 0) return [];
8609
8717
  return patterns.map((pattern) => {
8610
8718
  const id = typeof pattern.id === "string" ? pattern.id : "local-pattern";
@@ -8730,7 +8838,9 @@ async function cmdSuggest(query, options = {}) {
8730
8838
  if (matches.length === 0) {
8731
8839
  console.log(dim3("No hosted/bundled registry patterns matched this query."));
8732
8840
  console.log("");
8733
- console.log(dim3('Use local law first, or run "decantr list patterns" to browse registry options.'));
8841
+ console.log(
8842
+ dim3('Use local law first, or run "decantr list patterns" to browse registry options.')
8843
+ );
8734
8844
  return;
8735
8845
  }
8736
8846
  for (const match of matches.slice(0, 8)) {
@@ -10447,7 +10557,9 @@ function printScanReport(report) {
10447
10557
  console.log(dim3("Read-only Brownfield reconnaissance. No files were written."));
10448
10558
  console.log("");
10449
10559
  console.log(`${BOLD9}Verdict${RESET16}`);
10450
- console.log(` ${formatScanApplicability(report.applicability.status)} ${report.applicability.label}`);
10560
+ console.log(
10561
+ ` ${formatScanApplicability(report.applicability.status)} ${report.applicability.label}`
10562
+ );
10451
10563
  console.log(
10452
10564
  ` Confidence: ${cyan3(`${report.confidence.score}/100`)} (${report.confidence.level})`
10453
10565
  );
@@ -10456,7 +10568,9 @@ function printScanReport(report) {
10456
10568
  }
10457
10569
  console.log("");
10458
10570
  console.log(`${BOLD9}Project${RESET16}`);
10459
- console.log(` Framework: ${cyan3(report.project.framework)}${report.project.frameworkVersion ? ` ${report.project.frameworkVersion}` : ""}`);
10571
+ console.log(
10572
+ ` Framework: ${cyan3(report.project.framework)}${report.project.frameworkVersion ? ` ${report.project.frameworkVersion}` : ""}`
10573
+ );
10460
10574
  console.log(` Package manager:${" "} ${report.project.packageManager}`);
10461
10575
  console.log(` Language: ${report.project.primaryLanguage}`);
10462
10576
  console.log(` TypeScript: ${report.project.hasTypeScript ? "yes" : "no"}`);
@@ -10480,7 +10594,9 @@ function printScanReport(report) {
10480
10594
  console.log("");
10481
10595
  if (report.staticHosting.githubPagesLikely || report.pagesProbe) {
10482
10596
  console.log(`${BOLD9}Published Surface${RESET16}`);
10483
- console.log(` GitHub Pages: ${report.staticHosting.githubPagesLikely ? "likely" : "not detected"}`);
10597
+ console.log(
10598
+ ` GitHub Pages: ${report.staticHosting.githubPagesLikely ? "likely" : "not detected"}`
10599
+ );
10484
10600
  if (report.source.publishedSiteUrl) {
10485
10601
  console.log(` Site URL: ${report.source.publishedSiteUrl}`);
10486
10602
  }
@@ -10568,7 +10684,9 @@ async function cmdSetupWorkflow(args) {
10568
10684
  console.log(
10569
10685
  ` ${cyan3(withProject(verifyCommand, projectArg))} Run local health and drift checks`
10570
10686
  );
10571
- console.log(` ${cyan3(withProject("decantr ci init", projectArg))} Wire the app into CI`);
10687
+ console.log(
10688
+ ` ${cyan3(withProject("decantr ci init", projectArg))} Wire the app into CI`
10689
+ );
10572
10690
  return;
10573
10691
  }
10574
10692
  if (hasFootprint) {
@@ -10710,7 +10828,7 @@ async function cmdAdoptWorkflow(args) {
10710
10828
  await cmdGraph(projectRoot, { displayRoot: process.cwd() });
10711
10829
  if (process.exitCode && process.exitCode !== 0) return;
10712
10830
  if (runVerify) {
10713
- const { cmdHealth } = await import("./health-ASR7RWZJ.js");
10831
+ const { cmdHealth } = await import("./health-DDT4RABT.js");
10714
10832
  await cmdHealth(projectRoot, {
10715
10833
  browser: runBrowser,
10716
10834
  browserBaseUrl: baseUrl,
@@ -10781,7 +10899,7 @@ async function cmdVerifyWorkflow(args) {
10781
10899
  return;
10782
10900
  }
10783
10901
  if (workspaceMode) {
10784
- const { cmdWorkspace } = await import("./workspace-2FFQEEQQ.js");
10902
+ const { cmdWorkspace } = await import("./workspace-3XNCMZ5L.js");
10785
10903
  await cmdWorkspace(process.cwd(), ["workspace", "health", ...withoutWorkflowOnlyFlags(args)]);
10786
10904
  return;
10787
10905
  }
@@ -10814,7 +10932,7 @@ async function cmdVerifyWorkflow(args) {
10814
10932
  }
10815
10933
  let guardExitCode;
10816
10934
  if (brownfield) {
10817
- const { cmdHeal, collectCheckIssues } = await import("./heal-IRIDB7IZ.js");
10935
+ const { cmdHeal, collectCheckIssues } = await import("./heal-HHVVTVIH.js");
10818
10936
  if (quietOutput) {
10819
10937
  const result = collectCheckIssues(workspaceInfo.appRoot, { brownfield: true });
10820
10938
  guardExitCode = result.issues.some((issue) => issue.type === "error") ? 1 : void 0;
@@ -10824,7 +10942,7 @@ async function cmdVerifyWorkflow(args) {
10824
10942
  process.exitCode = void 0;
10825
10943
  }
10826
10944
  }
10827
- const { cmdHealth, parseHealthArgs } = await import("./health-ASR7RWZJ.js");
10945
+ const { cmdHealth, parseHealthArgs } = await import("./health-DDT4RABT.js");
10828
10946
  await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(healthArgs));
10829
10947
  if (localPatterns) {
10830
10948
  const validation = validateLocalLaw(workspaceInfo.appRoot);
@@ -10976,6 +11094,60 @@ function createTaskAuthoritySummary(input) {
10976
11094
  }
10977
11095
  return { lane, sourceAuthority, styleAuthority, activeAuthorities, runtimeBoundary, warnings };
10978
11096
  }
11097
+ function behaviorTaskKeywords(task) {
11098
+ return [
11099
+ ...new Set(
11100
+ task.toLowerCase().split(/[^a-z0-9_-]+/).map((term) => term.trim()).filter((term) => term.length >= 3)
11101
+ )
11102
+ ];
11103
+ }
11104
+ function rankBehaviorObligationsForTask(obligations, routePatterns, taskSummary) {
11105
+ const routePatternSet = new Set(routePatterns.map((pattern) => pattern.toLowerCase()));
11106
+ const keywords = behaviorTaskKeywords(taskSummary);
11107
+ const ranked = obligations.map((entry) => {
11108
+ const haystack = [
11109
+ entry.patternId,
11110
+ entry.patternRole,
11111
+ entry.intent,
11112
+ ...entry.riskProfile,
11113
+ ...entry.componentPaths,
11114
+ ...entry.obligations.flatMap((obligation) => [obligation.id, obligation.label])
11115
+ ].filter((value) => typeof value === "string").join(" ").toLowerCase();
11116
+ const reasons = [];
11117
+ let score = 0;
11118
+ if (routePatternSet.has(entry.patternId.toLowerCase())) {
11119
+ score += 5;
11120
+ reasons.push("route_pattern");
11121
+ }
11122
+ for (const keyword of keywords) {
11123
+ if (!haystack.includes(keyword)) continue;
11124
+ score += 2;
11125
+ reasons.push(`task:${keyword}`);
11126
+ }
11127
+ if (/dialog|modal|confirm|delete|destructive|remove|account/.test(taskSummary)) {
11128
+ if (/dialog|modal|confirm|destructive/.test(haystack)) {
11129
+ score += 3;
11130
+ reasons.push("interaction_intent");
11131
+ }
11132
+ }
11133
+ if (/form|input|field|label|submit|validation/.test(taskSummary)) {
11134
+ if (/form|input|label|submit|validation/.test(haystack)) {
11135
+ score += 3;
11136
+ reasons.push("form_intent");
11137
+ }
11138
+ }
11139
+ return {
11140
+ ...entry,
11141
+ relevance: {
11142
+ score,
11143
+ reasons: reasons.length > 0 ? [...new Set(reasons)] : ["accepted_local_law"]
11144
+ }
11145
+ };
11146
+ });
11147
+ return ranked.sort(
11148
+ (a, b) => b.relevance.score - a.relevance.score || a.patternId.localeCompare(b.patternId)
11149
+ );
11150
+ }
10979
11151
  async function cmdTaskWorkflow(args) {
10980
11152
  const { flags, positional } = parseLooseArgs(args);
10981
11153
  const workspaceInfo = resolveWorkflowProject(flags, "task");
@@ -11033,7 +11205,13 @@ async function cmdTaskWorkflow(args) {
11033
11205
  const contractCapsule = readJsonIfPresent(contractCapsulePath);
11034
11206
  const graphSnapshot = readJsonIfPresent(graphSnapshotPath);
11035
11207
  const routeGraphContext = buildGraphRouteContext(graphSnapshot, route, { task: taskSummary });
11208
+ const routePatterns = page?.layout?.map(extractPatternName) ?? [];
11036
11209
  const localLaw = createLocalLawTaskSummary(workspaceInfo.appRoot);
11210
+ const rankedBehaviorObligations = rankBehaviorObligationsForTask(
11211
+ localLaw.behaviorObligations,
11212
+ routePatterns,
11213
+ taskSummary
11214
+ );
11037
11215
  const styleBridge = createStyleBridgeTaskSummary(workspaceInfo.appRoot);
11038
11216
  const displayedStyleBridge = {
11039
11217
  ...styleBridge,
@@ -11042,7 +11220,8 @@ async function cmdTaskWorkflow(args) {
11042
11220
  const displayedLocalLaw = {
11043
11221
  ...localLaw,
11044
11222
  patternsPath: localLaw.patternsPath ? displayProjectPath(workspaceInfo, localLaw.patternsPath) : null,
11045
- rulesPath: localLaw.rulesPath ? displayProjectPath(workspaceInfo, localLaw.rulesPath) : null
11223
+ rulesPath: localLaw.rulesPath ? displayProjectPath(workspaceInfo, localLaw.rulesPath) : null,
11224
+ behaviorObligations: rankedBehaviorObligations
11046
11225
  };
11047
11226
  const changedSince = flagString(flags, "since");
11048
11227
  const currentChangedFiles = changedFiles(workspaceInfo.appRoot, changedSince);
@@ -11077,7 +11256,7 @@ async function cmdTaskWorkflow(args) {
11077
11256
  section: target.section,
11078
11257
  page: target.page,
11079
11258
  shell: page?.shell ?? section?.shell ?? null,
11080
- patterns: page?.layout?.map(extractPatternName) ?? [],
11259
+ patterns: routePatterns,
11081
11260
  read: [
11082
11261
  pagePack ? displayProjectPath(workspaceInfo, join30(".decantr/context", pagePack.markdown)) : null,
11083
11262
  sectionPack ? displayProjectPath(workspaceInfo, join30(".decantr/context", sectionPack.markdown)) : null,
@@ -11110,10 +11289,7 @@ async function cmdTaskWorkflow(args) {
11110
11289
  ...routeGraphContext
11111
11290
  } : null,
11112
11291
  changedFileContext: currentChangedFiles.length > 0 ? {
11113
- path: displayProjectPath(
11114
- workspaceInfo,
11115
- ".decantr/graph/graph.snapshot.json"
11116
- ),
11292
+ path: displayProjectPath(workspaceInfo, ".decantr/graph/graph.snapshot.json"),
11117
11293
  changedFiles: currentChangedFiles.slice(0, 40),
11118
11294
  resolvedNodeIds: changedFileSourceNodeIds,
11119
11295
  missingFiles: changedFileMissingFiles.slice(0, 40),
@@ -11238,6 +11414,23 @@ async function cmdTaskWorkflow(args) {
11238
11414
  ].filter(Boolean).join(" | ");
11239
11415
  console.log(` ${pattern.id}: ${authorityHint}${pathHint}`);
11240
11416
  }
11417
+ if (context.localLaw.behaviorObligations.length > 0) {
11418
+ console.log("");
11419
+ console.log(`${BOLD9}Behavior obligations:${RESET16}`);
11420
+ for (const behavior of context.localLaw.behaviorObligations.slice(0, 3)) {
11421
+ const obligations = behavior.obligations.slice(0, 3).map((obligation) => obligation.label).join("; ");
11422
+ const reasons = behavior.relevance.reasons.slice(0, 3).join(", ");
11423
+ console.log(
11424
+ ` ${behavior.patternId}: ${behavior.intent ?? behavior.patternRole ?? "interaction law"} (${reasons})`
11425
+ );
11426
+ console.log(` ${obligations}`);
11427
+ }
11428
+ if (context.localLaw.behaviorObligations.length > 3) {
11429
+ console.log(
11430
+ dim3(` ...${context.localLaw.behaviorObligations.length - 3} more behavior pattern(s)`)
11431
+ );
11432
+ }
11433
+ }
11241
11434
  } else {
11242
11435
  console.log("");
11243
11436
  console.log(`${BOLD9}Project-owned local law:${RESET16}`);
@@ -11556,12 +11749,12 @@ ${BOLD9}Commands:${RESET16}
11556
11749
  ${cyan3("scan")} Read-only Brownfield reconnaissance; no files written
11557
11750
  ${cyan3("new")} Create a new greenfield workspace and bootstrap the available starter adapter
11558
11751
  ${cyan3("adopt")} Brownfield one-liner: analyze, attach, verify, and show next steps
11559
- ${cyan3("task")} Prepare route/task context, local law, evidence, and changed-file impact for an AI coding assistant
11752
+ ${cyan3("task")} Prepare route/task context, local law, behavior obligations, evidence, and changed-file impact for an AI coding assistant
11560
11753
  ${cyan3("verify")} One reliability gate over Project Health, Brownfield checks, baselines, and evidence
11561
11754
  ${cyan3("graph")} Build typed Contract graph artifacts and the agent cache capsule
11562
11755
  ${cyan3("ci")} Non-mutating CI gate and CI integration generator
11563
11756
  ${cyan3("doctor")} Explain Decantr state, artifact ownership, and the next command
11564
- ${cyan3("codify")} Propose or accept project-owned Brownfield UI patterns and rules
11757
+ ${cyan3("codify")} Propose or accept project-owned Brownfield UI patterns, behavior obligations, and rules
11565
11758
  ${cyan3("studio")} Open a local Project Health dashboard backed by the same report
11566
11759
  ${cyan3("content")} Content-author namespace: check, create, publish
11567
11760
 
@@ -11934,8 +12127,9 @@ ${BOLD9}Usage:${RESET16}
11934
12127
  decantr task <route> ["task summary"] [--project <path>] [--since origin/main] [--json]
11935
12128
 
11936
12129
  ${BOLD9}Behavior:${RESET16}
11937
- Includes the typed contract capsule path when .decantr/graph exists. Run decantr graph first
11938
- when you want graph-backed agent context in CLI-only workflows.
12130
+ Includes accepted local law and behavior obligations, plus the typed contract capsule path when
12131
+ .decantr/graph exists. Run decantr graph first when you want graph-backed agent context in
12132
+ CLI-only workflows.
11939
12133
 
11940
12134
  ${BOLD9}Examples:${RESET16}
11941
12135
  decantr task /feed "add saved recipe actions"
@@ -11945,7 +12139,7 @@ ${BOLD9}Examples:${RESET16}
11945
12139
  }
11946
12140
  function cmdCodifyHelp() {
11947
12141
  console.log(`
11948
- ${BOLD9}decantr codify${RESET16} \u2014 Propose or accept project-owned Brownfield UI law and style bridges
12142
+ ${BOLD9}decantr codify${RESET16} \u2014 Propose or accept project-owned Brownfield UI law, behavior obligations, and style bridges
11949
12143
 
11950
12144
  ${BOLD9}Usage:${RESET16}
11951
12145
  decantr codify [--from-audit] [--style-bridge] [--project <path>]
@@ -12251,7 +12445,7 @@ async function main() {
12251
12445
  `${YELLOW12}Note: \`decantr heal\` is deprecated. Use \`decantr check\` instead.${RESET16}`
12252
12446
  );
12253
12447
  }
12254
- const { cmdHeal } = await import("./heal-IRIDB7IZ.js");
12448
+ const { cmdHeal } = await import("./heal-HHVVTVIH.js");
12255
12449
  const { flags } = parseLooseArgs(args);
12256
12450
  const workspaceInfo = resolveWorkflowProject(flags, "check");
12257
12451
  if (!workspaceInfo) break;
@@ -12276,7 +12470,7 @@ async function main() {
12276
12470
  const { flags } = parseLooseArgs(args);
12277
12471
  const workspaceInfo = resolveWorkflowProject(flags, "health");
12278
12472
  if (!workspaceInfo) break;
12279
- const { cmdHealth, parseHealthArgs } = await import("./health-ASR7RWZJ.js");
12473
+ const { cmdHealth, parseHealthArgs } = await import("./health-DDT4RABT.js");
12280
12474
  await cmdHealth(workspaceInfo.appRoot, parseHealthArgs(stripProjectArgs(args)));
12281
12475
  } catch (e) {
12282
12476
  console.error(error2(e.message));
@@ -12304,7 +12498,7 @@ async function main() {
12304
12498
  cmdStudioHelp();
12305
12499
  break;
12306
12500
  }
12307
- const { cmdStudio, parseStudioArgs } = await import("./studio-R65NXPJW.js");
12501
+ const { cmdStudio, parseStudioArgs } = await import("./studio-WDJ3BOCU.js");
12308
12502
  await cmdStudio(process.cwd(), parseStudioArgs(args));
12309
12503
  } catch (e) {
12310
12504
  console.error(error2(e.message));
@@ -12318,7 +12512,7 @@ async function main() {
12318
12512
  cmdWorkspaceHelp();
12319
12513
  break;
12320
12514
  }
12321
- const { cmdWorkspace } = await import("./workspace-2FFQEEQQ.js");
12515
+ const { cmdWorkspace } = await import("./workspace-3XNCMZ5L.js");
12322
12516
  await cmdWorkspace(process.cwd(), args);
12323
12517
  } catch (e) {
12324
12518
  console.error(error2(e.message));