@topogram/cli 0.3.63 → 0.3.65

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.
Files changed (344) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +703 -0
  3. package/src/adoption/plan.d.ts +6 -0
  4. package/src/adoption/plan.js +12 -703
  5. package/src/adoption/reporting.d.ts +10 -0
  6. package/src/adoption/review-groups.d.ts +6 -0
  7. package/src/agent-brief.d.ts +3 -0
  8. package/src/agent-brief.js +495 -0
  9. package/src/agent-ops/query-builders/auth.js +375 -0
  10. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  11. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  12. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  13. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  14. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  15. package/src/agent-ops/query-builders/change-risk.js +25 -0
  16. package/src/agent-ops/query-builders/common.js +149 -0
  17. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  18. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  19. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  20. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  21. package/src/agent-ops/query-builders/work-packets.js +417 -0
  22. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  23. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  24. package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
  25. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  26. package/src/agent-ops/query-builders.d.ts +26 -0
  27. package/src/agent-ops/query-builders.js +42 -5021
  28. package/src/archive/archive.d.ts +2 -0
  29. package/src/archive/compact.d.ts +1 -0
  30. package/src/archive/unarchive.d.ts +1 -0
  31. package/src/catalog/constants.js +10 -0
  32. package/src/catalog/copy.js +60 -0
  33. package/src/catalog/diagnostics.js +15 -0
  34. package/src/catalog/entries.js +42 -0
  35. package/src/catalog/files.js +67 -0
  36. package/src/catalog/provenance.js +122 -0
  37. package/src/catalog/source.js +150 -0
  38. package/src/catalog/validation.js +252 -0
  39. package/src/catalog.d.ts +12 -0
  40. package/src/catalog.js +18 -750
  41. package/src/cli/catalog-alias.d.ts +1 -0
  42. package/src/cli/command-parser.js +38 -0
  43. package/src/cli/command-parsers/core.js +102 -0
  44. package/src/cli/command-parsers/generator.js +39 -0
  45. package/src/cli/command-parsers/import.js +44 -0
  46. package/src/cli/command-parsers/legacy-workflow.js +21 -0
  47. package/src/cli/command-parsers/project.js +47 -0
  48. package/src/cli/command-parsers/sdlc.js +47 -0
  49. package/src/cli/command-parsers/shared.js +51 -0
  50. package/src/cli/command-parsers/template.js +48 -0
  51. package/src/cli/commands/agent.js +47 -0
  52. package/src/cli/commands/catalog/check.js +31 -0
  53. package/src/cli/commands/catalog/copy.js +59 -0
  54. package/src/cli/commands/catalog/doctor.js +248 -0
  55. package/src/cli/commands/catalog/help.js +21 -0
  56. package/src/cli/commands/catalog/list.js +52 -0
  57. package/src/cli/commands/catalog/runner.js +92 -0
  58. package/src/cli/commands/catalog/shared.js +17 -0
  59. package/src/cli/commands/catalog/show.js +134 -0
  60. package/src/cli/commands/catalog.js +32 -0
  61. package/src/cli/commands/check.js +268 -0
  62. package/src/cli/commands/doctor.js +268 -0
  63. package/src/cli/commands/emit.js +149 -0
  64. package/src/cli/commands/generate.js +96 -0
  65. package/src/cli/commands/generator-policy/package-info.js +162 -0
  66. package/src/cli/commands/generator-policy/payloads.js +372 -0
  67. package/src/cli/commands/generator-policy/printers.js +159 -0
  68. package/src/cli/commands/generator-policy/runner.js +81 -0
  69. package/src/cli/commands/generator-policy/shared.js +39 -0
  70. package/src/cli/commands/generator-policy.js +17 -0
  71. package/src/cli/commands/generator.js +443 -0
  72. package/src/cli/commands/import/adopt.js +170 -0
  73. package/src/cli/commands/import/check.js +91 -0
  74. package/src/cli/commands/import/diff.js +84 -0
  75. package/src/cli/commands/import/help.js +47 -0
  76. package/src/cli/commands/import/paths.js +277 -0
  77. package/src/cli/commands/import/plan.js +284 -0
  78. package/src/cli/commands/import/refresh.js +470 -0
  79. package/src/cli/commands/import/status-history.js +196 -0
  80. package/src/cli/commands/import/workspace.js +230 -0
  81. package/src/cli/commands/import-runner.js +157 -0
  82. package/src/cli/commands/import.js +35 -0
  83. package/src/cli/commands/inspect.js +55 -0
  84. package/src/cli/commands/new.js +94 -0
  85. package/src/cli/commands/package/constants.js +17 -0
  86. package/src/cli/commands/package/doctor.js +240 -0
  87. package/src/cli/commands/package/help.js +27 -0
  88. package/src/cli/commands/package/lockfile.js +135 -0
  89. package/src/cli/commands/package/npm.js +97 -0
  90. package/src/cli/commands/package/reporting.js +35 -0
  91. package/src/cli/commands/package/runner.js +33 -0
  92. package/src/cli/commands/package/shared.js +9 -0
  93. package/src/cli/commands/package/update-cli.js +252 -0
  94. package/src/cli/commands/package/versions.js +35 -0
  95. package/src/cli/commands/package.js +31 -0
  96. package/src/cli/commands/query/change-plan.js +68 -0
  97. package/src/cli/commands/query/definitions.js +202 -0
  98. package/src/cli/commands/query/import-adopt.js +121 -0
  99. package/src/cli/commands/query/runner/artifacts.js +102 -0
  100. package/src/cli/commands/query/runner/boundaries.js +211 -0
  101. package/src/cli/commands/query/runner/change.js +182 -0
  102. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  103. package/src/cli/commands/query/runner/index.js +31 -0
  104. package/src/cli/commands/query/runner/output.js +12 -0
  105. package/src/cli/commands/query/runner/workflow.js +241 -0
  106. package/src/cli/commands/query/runner.js +3 -0
  107. package/src/cli/commands/query/workflow-context.js +5 -0
  108. package/src/cli/commands/query/workspace.js +274 -0
  109. package/src/cli/commands/query.js +11 -0
  110. package/src/cli/commands/release-rollout.js +257 -0
  111. package/src/cli/commands/release-shared.js +528 -0
  112. package/src/cli/commands/release-status.js +429 -0
  113. package/src/cli/commands/release.js +107 -0
  114. package/src/cli/commands/sdlc.js +168 -0
  115. package/src/cli/commands/setup.js +76 -0
  116. package/src/cli/commands/source.js +291 -0
  117. package/src/cli/commands/template/baseline.js +100 -0
  118. package/src/cli/commands/template/check.js +466 -0
  119. package/src/cli/commands/template/constants.js +8 -0
  120. package/src/cli/commands/template/diagnostics.js +26 -0
  121. package/src/cli/commands/template/help.js +28 -0
  122. package/src/cli/commands/template/lifecycle.js +404 -0
  123. package/src/cli/commands/template/list-show.js +287 -0
  124. package/src/cli/commands/template/policy.js +422 -0
  125. package/src/cli/commands/template/shared.js +127 -0
  126. package/src/cli/commands/template/updates.js +352 -0
  127. package/src/cli/commands/template-runner.js +198 -0
  128. package/src/cli/commands/template.js +43 -0
  129. package/src/cli/commands/trust.js +219 -0
  130. package/src/cli/commands/version.js +40 -0
  131. package/src/cli/commands/widget.js +168 -0
  132. package/src/cli/commands/workflow.js +63 -0
  133. package/src/cli/dispatcher.js +392 -0
  134. package/src/cli/help-dispatch.js +188 -0
  135. package/src/cli/help.js +296 -0
  136. package/src/cli/migration-guidance.js +59 -0
  137. package/src/cli/options.js +96 -0
  138. package/src/cli/output-safety.js +107 -0
  139. package/src/cli/path-normalization.js +29 -0
  140. package/src/cli.js +47 -11711
  141. package/src/example-implementation.d.ts +2 -0
  142. package/src/format.d.ts +1 -0
  143. package/src/generator/api/contracts.js +497 -0
  144. package/src/generator/api/metadata.js +221 -0
  145. package/src/generator/api/openapi.js +559 -0
  146. package/src/generator/api/schema.js +124 -0
  147. package/src/generator/api/types.d.ts +98 -0
  148. package/src/generator/api.js +3 -1195
  149. package/src/generator/check.d.ts +1 -0
  150. package/src/generator/context/bundle.d.ts +1 -0
  151. package/src/generator/context/shared/domain-sdlc.js +282 -0
  152. package/src/generator/context/shared/maintained-boundary.js +665 -0
  153. package/src/generator/context/shared/metrics.js +85 -0
  154. package/src/generator/context/shared/primitives.js +64 -0
  155. package/src/generator/context/shared/relationships.js +453 -0
  156. package/src/generator/context/shared/summaries.js +263 -0
  157. package/src/generator/context/shared/types.d.ts +207 -0
  158. package/src/generator/context/shared.d.ts +44 -0
  159. package/src/generator/context/shared.js +80 -1390
  160. package/src/generator/context/slice/core.js +397 -0
  161. package/src/generator/context/slice/sdlc.js +417 -0
  162. package/src/generator/context/slice/ui-packets.js +183 -0
  163. package/src/generator/context/slice.js +2 -859
  164. package/src/generator/native/parity-bundle.js +2 -1
  165. package/src/generator/registry/index.js +507 -0
  166. package/src/generator/registry.js +18 -504
  167. package/src/generator/runtime/environment/index.js +666 -0
  168. package/src/generator/runtime/environment.js +4 -666
  169. package/src/generator/runtime/runtime-check/index.js +554 -0
  170. package/src/generator/runtime/runtime-check.js +4 -554
  171. package/src/generator/runtime/shared/index.js +572 -0
  172. package/src/generator/runtime/shared.js +19 -570
  173. package/src/generator/shared.d.ts +2 -0
  174. package/src/generator/surfaces/shared.d.ts +3 -0
  175. package/src/generator/surfaces/web/html-escape.js +22 -0
  176. package/src/generator/surfaces/web/react.js +10 -8
  177. package/src/generator/surfaces/web/sveltekit.js +7 -5
  178. package/src/generator/surfaces/web/vanilla.js +8 -4
  179. package/src/generator/widget-conformance/behavior-report.js +258 -0
  180. package/src/generator/widget-conformance/checks.js +371 -0
  181. package/src/generator/widget-conformance/projection-context.js +200 -0
  182. package/src/generator/widget-conformance/report.js +166 -0
  183. package/src/generator/widget-conformance/types.d.ts +121 -0
  184. package/src/generator/widget-conformance.js +3 -824
  185. package/src/generator.d.ts +2 -0
  186. package/src/github-client.js +520 -0
  187. package/src/import/core/context.d.ts +3 -0
  188. package/src/import/core/contracts.d.ts +1 -0
  189. package/src/import/core/registry.d.ts +4 -0
  190. package/src/import/core/runner/candidates.js +217 -0
  191. package/src/import/core/runner/options.js +22 -0
  192. package/src/import/core/runner/reports.js +50 -0
  193. package/src/import/core/runner/run.js +79 -0
  194. package/src/import/core/runner/tracks.js +150 -0
  195. package/src/import/core/runner/ui-drafts.js +337 -0
  196. package/src/import/core/runner.js +3 -698
  197. package/src/import/core/shared/api-routes.js +221 -0
  198. package/src/import/core/shared/candidates.js +97 -0
  199. package/src/import/core/shared/files.js +177 -0
  200. package/src/import/core/shared/next-app.js +389 -0
  201. package/src/import/core/shared/types.d.ts +51 -0
  202. package/src/import/core/shared/ui-routes.js +230 -0
  203. package/src/import/core/shared.js +67 -910
  204. package/src/import/extractors/api/flutter-dio.js +4 -8
  205. package/src/import/extractors/api/react-native-repository.js +4 -8
  206. package/src/import/index.d.ts +4 -0
  207. package/src/import/provenance.d.ts +4 -0
  208. package/src/new-project/constants.js +128 -0
  209. package/src/new-project/create.js +83 -0
  210. package/src/new-project/json.js +28 -0
  211. package/src/new-project/metadata.js +96 -0
  212. package/src/new-project/package-spec.js +161 -0
  213. package/src/new-project/project-files.js +348 -0
  214. package/src/new-project/template-policy.js +269 -0
  215. package/src/new-project/template-resolution.js +368 -0
  216. package/src/new-project/template-snapshots.js +430 -0
  217. package/src/new-project/template-updates.js +512 -0
  218. package/src/new-project/types.d.ts +83 -0
  219. package/src/new-project.js +6 -2188
  220. package/src/npm-safety.js +79 -0
  221. package/src/parser.d.ts +87 -0
  222. package/src/parser.js +118 -0
  223. package/src/path-helpers.d.ts +1 -0
  224. package/src/path-helpers.js +20 -0
  225. package/src/policy/review-boundaries.d.ts +15 -0
  226. package/src/project-config/index.js +564 -0
  227. package/src/project-config.js +19 -560
  228. package/src/reconcile/docs.d.ts +8 -0
  229. package/src/reconcile/journeys.d.ts +1 -0
  230. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  231. package/src/resolver/enrich/bug.js +2 -0
  232. package/src/resolver/enrich/pitch.js +2 -0
  233. package/src/resolver/enrich/requirement.js +2 -0
  234. package/src/resolver/enrich/task.js +2 -0
  235. package/src/resolver/index.js +19 -2089
  236. package/src/resolver/normalize.js +384 -1
  237. package/src/resolver/plans.js +168 -0
  238. package/src/resolver/projections-api.js +494 -0
  239. package/src/resolver/projections-db.js +133 -0
  240. package/src/resolver/projections-ui.js +317 -0
  241. package/src/resolver/shapes.js +251 -0
  242. package/src/resolver/shared.js +278 -0
  243. package/src/resolver/widgets.js +132 -0
  244. package/src/resolver.d.ts +1 -0
  245. package/src/runtime-support.js +29 -0
  246. package/src/sdlc/adopt.d.ts +1 -0
  247. package/src/sdlc/check.d.ts +1 -0
  248. package/src/sdlc/explain.d.ts +1 -0
  249. package/src/sdlc/release.d.ts +1 -0
  250. package/src/sdlc/scaffold.d.ts +1 -0
  251. package/src/sdlc/transition.d.ts +1 -0
  252. package/src/template-trust/constants.js +62 -0
  253. package/src/template-trust/content.js +258 -0
  254. package/src/template-trust/diff.js +92 -0
  255. package/src/template-trust/policy.js +61 -0
  256. package/src/template-trust/record.js +90 -0
  257. package/src/template-trust/status.js +182 -0
  258. package/src/template-trust.js +24 -687
  259. package/src/text-helpers.d.ts +7 -0
  260. package/src/text-helpers.js +245 -0
  261. package/src/topogram-config.js +306 -0
  262. package/src/topogram-types.d.ts +69 -0
  263. package/src/validator/common.js +488 -0
  264. package/src/validator/data-model.js +237 -0
  265. package/src/validator/docs.js +167 -0
  266. package/src/validator/expressions.js +146 -1
  267. package/src/validator/index.d.ts +23 -0
  268. package/src/validator/index.js +32 -3585
  269. package/src/validator/kinds.d.ts +41 -0
  270. package/src/validator/kinds.js +2 -0
  271. package/src/validator/model-helpers.js +46 -0
  272. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  273. package/src/validator/per-kind/bug.js +6 -0
  274. package/src/validator/per-kind/domain.js +15 -2
  275. package/src/validator/per-kind/pitch.js +7 -0
  276. package/src/validator/per-kind/requirement.js +5 -0
  277. package/src/validator/per-kind/task.js +7 -0
  278. package/src/validator/per-kind/widget.js +14 -0
  279. package/src/validator/projections/api-http-async.js +410 -0
  280. package/src/validator/projections/api-http-authz.js +88 -0
  281. package/src/validator/projections/api-http-core.js +205 -0
  282. package/src/validator/projections/api-http-policies.js +339 -0
  283. package/src/validator/projections/api-http-responses.js +233 -0
  284. package/src/validator/projections/api-http.js +44 -0
  285. package/src/validator/projections/db.js +353 -0
  286. package/src/validator/projections/generator-defaults.js +45 -0
  287. package/src/validator/projections/helpers.js +87 -0
  288. package/src/validator/projections/ui-helpers.js +214 -0
  289. package/src/validator/projections/ui-navigation.js +344 -0
  290. package/src/validator/projections/ui-structure.js +364 -0
  291. package/src/validator/projections/ui-widgets.js +493 -0
  292. package/src/validator/projections/ui.js +46 -0
  293. package/src/validator/registry.js +48 -1
  294. package/src/validator/utils.d.ts +20 -0
  295. package/src/validator/utils.js +115 -12
  296. package/src/validator.d.ts +2 -0
  297. package/src/widget-behavior.d.ts +1 -0
  298. package/src/workflows/adoption/index.js +26 -0
  299. package/src/workflows/docs-generate.js +262 -0
  300. package/src/workflows/docs-scan.js +703 -0
  301. package/src/workflows/docs.js +15 -0
  302. package/src/workflows/import-app/api/collect.js +221 -0
  303. package/src/workflows/import-app/api/openapi.js +257 -0
  304. package/src/workflows/import-app/api/routes.js +327 -0
  305. package/src/workflows/import-app/api/sources.js +22 -0
  306. package/src/workflows/import-app/api.js +4 -0
  307. package/src/workflows/import-app/db.js +538 -0
  308. package/src/workflows/import-app/index.js +30 -0
  309. package/src/workflows/import-app/shared.js +218 -0
  310. package/src/workflows/import-app/ui.js +443 -0
  311. package/src/workflows/import-app/workflow.js +159 -0
  312. package/src/workflows/reconcile/adoption-plan/build.js +208 -0
  313. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  314. package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
  315. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  316. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  317. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  318. package/src/workflows/reconcile/adoption-plan.js +32 -0
  319. package/src/workflows/reconcile/auth/closures.js +115 -0
  320. package/src/workflows/reconcile/auth/formatters.js +142 -0
  321. package/src/workflows/reconcile/auth/inference.js +330 -0
  322. package/src/workflows/reconcile/auth/roles.js +122 -0
  323. package/src/workflows/reconcile/auth.js +37 -0
  324. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  325. package/src/workflows/reconcile/bundle-core.js +14 -0
  326. package/src/workflows/reconcile/bundle-shared.js +75 -0
  327. package/src/workflows/reconcile/candidate-model.js +477 -0
  328. package/src/workflows/reconcile/canonical-surface.js +264 -0
  329. package/src/workflows/reconcile/gap-report.js +333 -0
  330. package/src/workflows/reconcile/ids.js +6 -0
  331. package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
  332. package/src/workflows/reconcile/impacts/indexes.js +101 -0
  333. package/src/workflows/reconcile/impacts/patches.js +252 -0
  334. package/src/workflows/reconcile/impacts/reports.js +80 -0
  335. package/src/workflows/reconcile/impacts.js +16 -0
  336. package/src/workflows/reconcile/index.js +7 -0
  337. package/src/workflows/reconcile/renderers.js +461 -0
  338. package/src/workflows/reconcile/summary.js +90 -0
  339. package/src/workflows/reconcile/workflow.js +309 -0
  340. package/src/workflows/shared.js +189 -0
  341. package/src/workflows/types.d.ts +93 -0
  342. package/src/workflows.d.ts +1 -0
  343. package/src/workflows.js +10 -7652
  344. package/src/workspace-docs.d.ts +29 -0
@@ -0,0 +1,219 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ import { stableStringify } from "../../format.js";
7
+ import { loadProjectConfig } from "../../project-config.js";
8
+ import {
9
+ getTemplateTrustDiff,
10
+ getTemplateTrustStatus,
11
+ implementationRequiresTrust,
12
+ TEMPLATE_TRUST_FILE,
13
+ templateTrustRecoveryGuidance,
14
+ writeTemplateTrustRecord
15
+ } from "../../template-trust.js";
16
+ import { writeTemplateFilesManifest } from "../../new-project.js";
17
+
18
+ /**
19
+ * @typedef {Record<string, any>} AnyRecord
20
+ */
21
+
22
+ /**
23
+ * @returns {void}
24
+ */
25
+ export function printTrustHelp() {
26
+ console.log("Usage: topogram trust status [path] [--json]");
27
+ console.log(" or: topogram trust diff [path] [--json]");
28
+ console.log(" or: topogram trust template [path] [--force]");
29
+ console.log("");
30
+ console.log("Inspects or refreshes executable template implementation trust after human review.");
31
+ console.log("");
32
+ console.log("Examples:");
33
+ console.log(" topogram trust status");
34
+ console.log(" topogram trust diff");
35
+ console.log(" topogram trust template");
36
+ }
37
+
38
+ /**
39
+ * @param {AnyRecord} projectConfigInfo
40
+ * @returns {{ config: any, configPath: string, configDir: string }}
41
+ */
42
+ function implementationInfoFromProject(projectConfigInfo) {
43
+ return {
44
+ config: projectConfigInfo.config.implementation,
45
+ configPath: projectConfigInfo.configPath,
46
+ configDir: projectConfigInfo.configDir
47
+ };
48
+ }
49
+
50
+ /**
51
+ * @param {string} inputPath
52
+ * @param {{ force?: boolean }} [options]
53
+ * @returns {number}
54
+ */
55
+ export function runTrustTemplateCommand(inputPath, options = {}) {
56
+ const projectConfigInfo = loadProjectConfig(inputPath);
57
+ if (!projectConfigInfo) {
58
+ throw new Error("Cannot trust template files without topogram.project.json.");
59
+ }
60
+ const templateManifestPath = path.join(projectConfigInfo.configDir, "topogram-template.json");
61
+ if (!projectConfigInfo.config.template && fs.existsSync(templateManifestPath) && !options.force) {
62
+ throw new Error("Cannot write consumer template trust metadata in a template source repo. Template source repos should not contain .topogram-template-files.json or .topogram-template-trust.json. Run this command in a generated project, or pass --force if you intentionally need local trust metadata here.");
63
+ }
64
+ if (!projectConfigInfo.config.template && fs.existsSync(templateManifestPath) && options.force) {
65
+ console.warn("Warning: writing consumer template trust metadata in a template source repo because --force was provided.");
66
+ }
67
+ const fileManifest = writeTemplateFilesManifest(projectConfigInfo.configDir, projectConfigInfo.config);
68
+ console.log(`Wrote .topogram-template-files.json with ${fileManifest.files.length} template-owned file hash(es).`);
69
+ if (projectConfigInfo.config.implementation) {
70
+ const implementationInfo = implementationInfoFromProject(projectConfigInfo);
71
+ if (implementationRequiresTrust(implementationInfo, projectConfigInfo.config)) {
72
+ const trustRecord = writeTemplateTrustRecord(projectConfigInfo.configDir, projectConfigInfo.config);
73
+ console.log(`Wrote ${TEMPLATE_TRUST_FILE} for ${trustRecord.implementation.module}.`);
74
+ if (trustRecord.template.id) {
75
+ console.log(`Trusted template: ${trustRecord.template.id}@${trustRecord.template.version || "unknown"}`);
76
+ }
77
+ console.log(`Trusted implementation digest: ${trustRecord.content.digest}`);
78
+ return 0;
79
+ }
80
+ }
81
+ console.log("No local implementation trust record needed for this project.");
82
+ return 0;
83
+ }
84
+
85
+ /**
86
+ * @param {string} inputPath
87
+ * @param {{ json?: boolean }} [options]
88
+ * @returns {number}
89
+ */
90
+ export function runTrustStatusCommand(inputPath, options = {}) {
91
+ const projectConfigInfo = loadProjectConfig(inputPath);
92
+ if (!projectConfigInfo) {
93
+ throw new Error("Cannot inspect template trust without topogram.project.json.");
94
+ }
95
+ if (!projectConfigInfo.config.implementation) {
96
+ throw new Error("Cannot inspect template trust because topogram.project.json has no implementation config.");
97
+ }
98
+ const status = getTemplateTrustStatus(implementationInfoFromProject(projectConfigInfo), projectConfigInfo.config);
99
+ if (options.json) {
100
+ console.log(stableStringify(status));
101
+ } else if (!status.requiresTrust) {
102
+ console.log("No local implementation trust record needed for this project.");
103
+ } else {
104
+ console.log(status.ok ? "Implementation trust status: trusted" : "Implementation trust status: review required");
105
+ if (status.template.id) {
106
+ console.log(`Template: ${status.template.id}@${status.template.version || "unknown"}`);
107
+ }
108
+ console.log(`Implementation: ${status.implementation.module}`);
109
+ if (status.content.trustedDigest) {
110
+ console.log(`Trusted digest: ${status.content.trustedDigest}`);
111
+ }
112
+ if (status.content.currentDigest) {
113
+ console.log(`Current digest: ${status.content.currentDigest}`);
114
+ }
115
+ for (const issue of status.issues) {
116
+ console.log(`Issue: ${issue}`);
117
+ }
118
+ for (const filePath of status.content.changed) {
119
+ console.log(`Changed: ${filePath}`);
120
+ }
121
+ for (const filePath of status.content.added) {
122
+ console.log(`Added: ${filePath}`);
123
+ }
124
+ for (const filePath of status.content.removed) {
125
+ console.log(`Removed: ${filePath}`);
126
+ }
127
+ if (!status.ok) {
128
+ const guidance = templateTrustRecoveryGuidance(status.issues);
129
+ if (guidance) {
130
+ console.log(guidance);
131
+ }
132
+ }
133
+ }
134
+ return status.ok ? 0 : 1;
135
+ }
136
+
137
+ /**
138
+ * @param {string} inputPath
139
+ * @param {{ json?: boolean }} [options]
140
+ * @returns {number}
141
+ */
142
+ export function runTrustDiffCommand(inputPath, options = {}) {
143
+ const projectConfigInfo = loadProjectConfig(inputPath);
144
+ if (!projectConfigInfo) {
145
+ throw new Error("Cannot inspect template trust diff without topogram.project.json.");
146
+ }
147
+ if (!projectConfigInfo.config.implementation) {
148
+ throw new Error("Cannot inspect template trust diff because topogram.project.json has no implementation config.");
149
+ }
150
+ const diff = getTemplateTrustDiff(implementationInfoFromProject(projectConfigInfo), projectConfigInfo.config);
151
+ if (options.json) {
152
+ console.log(stableStringify(diff));
153
+ } else if (!diff.requiresTrust) {
154
+ console.log("No local implementation trust record needed for this project.");
155
+ } else if (diff.files.length === 0) {
156
+ console.log(diff.ok ? "Template trust diff: no implementation changes." : "Template trust diff: no file-level diff available.");
157
+ for (const issue of diff.status.issues) {
158
+ console.log(`Issue: ${issue}`);
159
+ }
160
+ if (!diff.ok) {
161
+ const guidance = templateTrustRecoveryGuidance(diff.status.issues);
162
+ if (guidance) {
163
+ console.log(guidance);
164
+ }
165
+ }
166
+ } else {
167
+ console.log(diff.ok ? "Template trust diff: no implementation changes." : "Template trust diff: review required");
168
+ for (const file of diff.files) {
169
+ console.log("");
170
+ console.log(`${file.kind.toUpperCase()}: implementation/${file.path}`);
171
+ if (file.trusted) {
172
+ console.log(` trusted sha256: ${file.trusted.sha256}`);
173
+ console.log(` trusted size: ${file.trusted.size}`);
174
+ }
175
+ if (file.current) {
176
+ console.log(` current sha256: ${file.current.sha256}`);
177
+ console.log(` current size: ${file.current.size}`);
178
+ }
179
+ if (file.binary) {
180
+ console.log(" diff: binary file");
181
+ } else if (file.diffOmitted && !file.unifiedDiff) {
182
+ console.log(" diff: hash-only");
183
+ }
184
+ if (file.unifiedDiff) {
185
+ console.log(file.unifiedDiff.trimEnd());
186
+ }
187
+ }
188
+ if (!diff.ok) {
189
+ console.log("");
190
+ const guidance = templateTrustRecoveryGuidance(diff.status.issues);
191
+ if (guidance) {
192
+ console.log(guidance);
193
+ }
194
+ }
195
+ }
196
+ return diff.ok ? 0 : 1;
197
+ }
198
+
199
+ /**
200
+ * @param {{
201
+ * commandArgs: Record<string, any>,
202
+ * inputPath: string|null|undefined,
203
+ * json: boolean
204
+ * }} context
205
+ * @returns {number}
206
+ */
207
+ export function runTrustCommand(context) {
208
+ const inputPath = context.inputPath || "./topogram";
209
+ if (context.commandArgs.trustCommand === "template") {
210
+ return runTrustTemplateCommand(inputPath, { force: Boolean(context.commandArgs.force) });
211
+ }
212
+ if (context.commandArgs.trustCommand === "status") {
213
+ return runTrustStatusCommand(inputPath, { json: context.json });
214
+ }
215
+ if (context.commandArgs.trustCommand === "diff") {
216
+ return runTrustDiffCommand(inputPath, { json: context.json });
217
+ }
218
+ throw new Error(`Unknown trust command '${context.commandArgs.trustCommand}'`);
219
+ }
@@ -0,0 +1,40 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+
5
+ const CLI_PACKAGE_NAME = "@topogram/cli";
6
+ const PACKAGE_JSON_URL = new URL("../../../package.json", import.meta.url);
7
+
8
+ /**
9
+ * @returns {string}
10
+ */
11
+ function readInstalledCliPackageVersion() {
12
+ if (!fs.existsSync(PACKAGE_JSON_URL)) {
13
+ return "0.0.0";
14
+ }
15
+ const pkg = JSON.parse(fs.readFileSync(PACKAGE_JSON_URL, "utf8"));
16
+ return typeof pkg.version === "string" ? pkg.version : "0.0.0";
17
+ }
18
+
19
+ /**
20
+ * @param {{ executablePath?: string }} [options]
21
+ * @returns {{ packageName: string, version: string, executablePath: string, nodeVersion: string }}
22
+ */
23
+ export function buildVersionPayload(options = {}) {
24
+ return {
25
+ packageName: CLI_PACKAGE_NAME,
26
+ version: readInstalledCliPackageVersion(),
27
+ executablePath: options.executablePath || process.argv[1] || "",
28
+ nodeVersion: process.version
29
+ };
30
+ }
31
+
32
+ /**
33
+ * @param {ReturnType<typeof buildVersionPayload>} payload
34
+ * @returns {void}
35
+ */
36
+ export function printVersion(payload) {
37
+ console.log(`Topogram CLI: ${payload.packageName}@${payload.version}`);
38
+ console.log(`Executable: ${payload.executablePath}`);
39
+ console.log(`Node: ${payload.nodeVersion}`);
40
+ }
@@ -0,0 +1,168 @@
1
+ // @ts-check
2
+
3
+ import { stableStringify } from "../../format.js";
4
+ import { generateWorkspace } from "../../generator.js";
5
+ import { parsePath } from "../../parser.js";
6
+ import { formatValidationErrors } from "../../validator.js";
7
+
8
+ /**
9
+ * @typedef {Record<string, any>} AnyRecord
10
+ */
11
+
12
+ /**
13
+ * @param {AnyRecord} report
14
+ * @returns {void}
15
+ */
16
+ export function printWidgetConformanceReport(report) {
17
+ const summary = report.summary || {};
18
+ const ok = (summary.errors || 0) === 0;
19
+ console.log(ok ? "Widget conformance passed." : "Widget conformance found issues.");
20
+ console.log(`Usages: ${summary.total_usages || 0} total, ${summary.passed_usages || 0} passed, ${summary.warning_usages || 0} warning, ${summary.error_usages || 0} error`);
21
+ console.log(`Checks: ${summary.errors || 0} error(s), ${summary.warnings || 0} warning(s)`);
22
+ if (report.filters?.projection) {
23
+ console.log(`Projection filter: ${report.filters.projection}`);
24
+ }
25
+ if (report.filters?.widget) {
26
+ console.log(`Widget filter: ${report.filters.widget}`);
27
+ }
28
+ if ((summary.affected_projections || []).length > 0) {
29
+ console.log(`Affected projections: ${summary.affected_projections.join(", ")}`);
30
+ }
31
+ if ((summary.affected_widgets || []).length > 0) {
32
+ console.log(`Affected widgets: ${summary.affected_widgets.join(", ")}`);
33
+ }
34
+ if ((report.checks || []).length > 0) {
35
+ console.log("");
36
+ console.log("Issues:");
37
+ for (const check of report.checks) {
38
+ const context = [
39
+ check.projection ? `projection ${check.projection}` : null,
40
+ check.widget ? `widget ${check.widget}` : null,
41
+ check.screen ? `screen ${check.screen}` : null,
42
+ check.region ? `region ${check.region}` : null,
43
+ check.prop ? `prop ${check.prop}` : null,
44
+ check.event ? `event ${check.event}` : null,
45
+ check.behavior ? `behavior ${check.behavior}` : null
46
+ ].filter(Boolean).join(", ");
47
+ console.log(`- ${check.severity.toUpperCase()} ${check.code}${context ? ` (${context})` : ""}: ${check.message}`);
48
+ if (check.suggested_fix) {
49
+ console.log(` Fix: ${check.suggested_fix}`);
50
+ }
51
+ }
52
+ }
53
+ const writeScopePaths = report.write_scope?.paths || [];
54
+ if (writeScopePaths.length > 0) {
55
+ console.log("");
56
+ console.log("Write scope:");
57
+ for (const filePath of writeScopePaths) {
58
+ console.log(`- ${filePath}`);
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @param {AnyRecord} report
65
+ * @returns {void}
66
+ */
67
+ export function printWidgetBehaviorReport(report) {
68
+ const summary = report.summary || {};
69
+ const ok = (summary.errors || 0) === 0;
70
+ console.log(ok ? "Widget behavior report passed." : "Widget behavior report found issues.");
71
+ console.log(`Behaviors: ${summary.total_behaviors || 0} total, ${summary.realized || 0} realized, ${summary.partial || 0} partial, ${summary.declared || 0} declared`);
72
+ console.log(`Checks: ${summary.errors || 0} error(s), ${summary.warnings || 0} warning(s)`);
73
+ if (report.filters?.projection) {
74
+ console.log(`Projection filter: ${report.filters.projection}`);
75
+ }
76
+ if (report.filters?.widget) {
77
+ console.log(`Widget filter: ${report.filters.widget}`);
78
+ }
79
+ if ((summary.affected_projections || []).length > 0) {
80
+ console.log(`Affected projections: ${summary.affected_projections.join(", ")}`);
81
+ }
82
+ if ((summary.affected_widgets || []).length > 0) {
83
+ console.log(`Affected widgets: ${summary.affected_widgets.join(", ")}`);
84
+ }
85
+ if ((summary.affected_capabilities || []).length > 0) {
86
+ console.log(`Affected capabilities: ${summary.affected_capabilities.join(", ")}`);
87
+ }
88
+ const highlights = report.highlights || [];
89
+ if (highlights.length > 0) {
90
+ console.log("");
91
+ console.log("Behavior highlights:");
92
+ for (const highlight of highlights) {
93
+ const context = [
94
+ highlight.projection ? `projection ${highlight.projection}` : null,
95
+ highlight.widget ? `widget ${highlight.widget}` : null,
96
+ highlight.screen ? `screen ${highlight.screen}` : null,
97
+ highlight.region ? `region ${highlight.region}` : null,
98
+ highlight.event ? `event ${highlight.event}` : null,
99
+ highlight.capability ? `capability ${highlight.capability}` : null,
100
+ highlight.behavior ? `behavior ${highlight.behavior}` : null
101
+ ].filter(Boolean).join(", ");
102
+ console.log(`- ${highlight.severity.toUpperCase()} ${highlight.code}${context ? ` (${context})` : ""}: ${highlight.message}`);
103
+ if (highlight.suggested_fix) {
104
+ console.log(` Fix: ${highlight.suggested_fix}`);
105
+ }
106
+ }
107
+ }
108
+ const groupSummary = report.groups || {};
109
+ console.log("");
110
+ console.log(`Groups: ${(groupSummary.widgets || []).length} widget(s), ${(groupSummary.screens || []).length} screen(s), ${(groupSummary.capabilities || []).length} capability group(s), ${(groupSummary.effects || []).length} effect group(s)`);
111
+ }
112
+
113
+ /**
114
+ * @param {string} inputPath
115
+ * @param {{ json?: boolean, projectionId?: string|null, widgetId?: string|null }} [options]
116
+ * @returns {number}
117
+ */
118
+ export function runWidgetCheckCommand(inputPath, options = {}) {
119
+ return runWidgetReportCommand(inputPath, {
120
+ json: options.json,
121
+ projectionId: options.projectionId,
122
+ widgetId: options.widgetId,
123
+ target: "widget-conformance-report",
124
+ print: printWidgetConformanceReport
125
+ });
126
+ }
127
+
128
+ /**
129
+ * @param {string} inputPath
130
+ * @param {{ json?: boolean, projectionId?: string|null, widgetId?: string|null }} [options]
131
+ * @returns {number}
132
+ */
133
+ export function runWidgetBehaviorCommand(inputPath, options = {}) {
134
+ return runWidgetReportCommand(inputPath, {
135
+ json: options.json,
136
+ projectionId: options.projectionId,
137
+ widgetId: options.widgetId,
138
+ target: "widget-behavior-report",
139
+ print: printWidgetBehaviorReport
140
+ });
141
+ }
142
+
143
+ /**
144
+ * @param {string} inputPath
145
+ * @param {{ json?: boolean, projectionId?: string|null, widgetId?: string|null, target: string, print: (report: AnyRecord) => void }} options
146
+ * @returns {number}
147
+ */
148
+ function runWidgetReportCommand(inputPath, options) {
149
+ const ast = parsePath(inputPath);
150
+ const result = generateWorkspace(ast, {
151
+ target: options.target,
152
+ projectionId: options.projectionId,
153
+ widgetId: options.widgetId,
154
+ componentId: options.widgetId
155
+ });
156
+ if (!result.ok) {
157
+ console.error(formatValidationErrors(result.validation));
158
+ return 1;
159
+ }
160
+ const report = result.artifact;
161
+ const ok = (report.summary?.errors || 0) === 0;
162
+ if (options.json) {
163
+ console.log(stableStringify(report));
164
+ } else {
165
+ options.print(report);
166
+ }
167
+ return ok ? 0 : 1;
168
+ }
@@ -0,0 +1,63 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ import { stableStringify } from "../../format.js";
7
+ import { parsePath } from "../../parser.js";
8
+ import { formatValidationErrors, validateWorkspace } from "../../validator.js";
9
+ import { runWorkflow } from "../../workflows.js";
10
+
11
+ /**
12
+ * @param {string|null|undefined} inputPath
13
+ * @returns {number}
14
+ */
15
+ export function runValidateCommand(inputPath) {
16
+ const ast = parsePath(inputPath || ".");
17
+ const result = validateWorkspace(ast);
18
+ if (!result.ok) {
19
+ console.error(formatValidationErrors(result));
20
+ return 1;
21
+ }
22
+
23
+ const files = /** @type {Array<{ statements: any[] }>} */ (ast.files || []);
24
+ const statementCount = files.flatMap((file) => file.statements).length;
25
+ console.log(`Validated ${files.length} file(s) and ${statementCount} statement(s) with 0 errors.`);
26
+ return 0;
27
+ }
28
+
29
+ /**
30
+ * @param {{
31
+ * workflowName: string,
32
+ * inputPath: string|null|undefined,
33
+ * from: string|null,
34
+ * adopt: string|null,
35
+ * write: boolean,
36
+ * refreshAdopted: boolean,
37
+ * outDir: string|null
38
+ * }} context
39
+ * @returns {number}
40
+ */
41
+ export function runLegacyWorkflowCommand(context) {
42
+ const result = runWorkflow(context.workflowName, context.inputPath || ".", {
43
+ from: context.from,
44
+ adopt: context.adopt,
45
+ write: context.write,
46
+ refreshAdopted: context.refreshAdopted
47
+ });
48
+
49
+ if (context.write) {
50
+ const resolvedOutDir = path.resolve(context.outDir || result.defaultOutDir || "artifacts");
51
+ fs.mkdirSync(resolvedOutDir, { recursive: true });
52
+ for (const [relativePath, contents] of Object.entries(result.files || {})) {
53
+ const destination = path.join(resolvedOutDir, relativePath);
54
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
55
+ fs.writeFileSync(destination, typeof contents === "string" ? contents : `${stableStringify(contents)}\n`, "utf8");
56
+ }
57
+ console.log(`Wrote ${Object.keys(result.files || {}).length} file(s) to ${resolvedOutDir}`);
58
+ return 0;
59
+ }
60
+
61
+ console.log(stableStringify(result.summary));
62
+ return 0;
63
+ }