@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
@@ -1,703 +1,12 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
-
4
- import {
5
- ADOPTION_STATE_VOCABULARY,
6
- reviewBoundaryForImportProposal
7
- } from "../policy/review-boundaries.js";
8
-
9
- const ADOPT_SELECTORS = new Set(["from-plan", "actors", "roles", "enums", "shapes", "entities", "capabilities", "widgets", "docs", "journeys", "workflows", "verification", "ui"]);
10
-
11
- function stableSortedStrings(values) {
12
- return [...new Set((values || []).filter(Boolean))].sort();
13
- }
14
-
15
- function severityRank(status) {
16
- if (status === "no_go") return 3;
17
- if (status === "manual_decision") return 2;
18
- if (status === "review_required") return 1;
19
- return 0;
20
- }
21
-
22
- function importProposalDependencyIds(proposalSurface = {}) {
23
- return stableSortedStrings([
24
- proposalSurface.item,
25
- ...(proposalSurface.requirements?.related_capabilities || []),
26
- ...(proposalSurface.requirements?.related_rules || []),
27
- ...(proposalSurface.requirements?.related_workflows || []),
28
- ...(proposalSurface.requirements?.related_docs || []),
29
- ...((proposalSurface.projection_impacts || []).map((impact) => impact.projection_id)),
30
- ...((proposalSurface.ui_impacts || []).map((impact) => impact.projection_id)),
31
- ...((proposalSurface.workflow_impacts || []).map((impact) => impact.id))
32
- ]);
33
- }
34
-
35
- function normalizePath(input) {
36
- return String(input || "")
37
- .replaceAll("\\", "/")
38
- .replace(/^\.\//, "")
39
- .replace(/\/+/g, "/");
40
- }
41
-
42
- function trimGlobSuffix(pathValue) {
43
- return normalizePath(pathValue).replace(/\/\*\*$/, "").replace(/\/\*$/, "");
44
- }
45
-
46
- function pathPrefixMatches(filePath, rootPath) {
47
- if (!filePath || !rootPath) return false;
48
- const normalizedFile = normalizePath(filePath);
49
- const normalizedRoot = trimGlobSuffix(rootPath);
50
- return normalizedRoot.length > 0 && normalizedFile.startsWith(normalizedRoot);
51
- }
52
-
53
- function pathTokens(pathValue) {
54
- const normalized = normalizePath(pathValue).replace(/\.[^.\/]+$/, "");
55
- const camelExpanded = normalized.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
56
- const tokens = camelExpanded
57
- .toLowerCase()
58
- .split(/[^a-z0-9]+/)
59
- .filter((token) =>
60
- token.length > 1 &&
61
- !["app", "src", "docs", "model", "bundles", "candidates", "topogram", "cap", "tg", "md"].includes(token)
62
- );
63
-
64
- return stableSortedStrings(tokens.flatMap((token) => {
65
- const variants = [token];
66
- if (token.endsWith("ies") && token.length > 4) {
67
- variants.push(`${token.slice(0, -3)}y`);
68
- } else if (token.endsWith("s") && token.length > 3) {
69
- variants.push(token.slice(0, -1));
70
- }
71
- return variants;
72
- }));
73
- }
74
-
75
- function sharedTokens(left, right) {
76
- const rightSet = new Set(right || []);
77
- return stableSortedStrings((left || []).filter((token) => rightSet.has(token)));
78
- }
79
-
80
- function semanticEvidenceForProposal(proposalSurface, seam) {
81
- const dependencyIds = importProposalDependencyIds(proposalSurface);
82
- const seamDependencies = stableSortedStrings(seam.emitted_dependencies || []);
83
- const matchedDependencies = seamDependencies.filter((dependency) => dependencyIds.includes(dependency));
84
-
85
- if (matchedDependencies.length === 0) {
86
- return {
87
- matched_dependencies: [],
88
- score: 0,
89
- reasons: []
90
- };
91
- }
92
-
93
- const specificity = matchedDependencies.length / Math.max(
94
- matchedDependencies.length,
95
- seamDependencies.length || 1,
96
- dependencyIds.length || 1
97
- );
98
- const score = 0.22 + Math.min(0.16, matchedDependencies.length * 0.08) + Math.min(0.2, specificity * 0.24) + (matchedDependencies.length >= 2 ? 0.04 : 0);
99
- return {
100
- matched_dependencies: matchedDependencies,
101
- score,
102
- reasons: [
103
- `semantic overlap: ${matchedDependencies.map((dependency) => `\`${dependency}\``).join(", ")}`
104
- ]
105
- };
106
- }
107
-
108
- function pathEvidenceForProposal(proposalSurface, seam) {
109
- const proposalPaths = stableSortedStrings([
110
- proposalSurface.source_path,
111
- proposalSurface.canonical_rel_path
112
- ]);
113
- const proposalTokenSet = stableSortedStrings(proposalPaths.flatMap((candidatePath) => pathTokens(candidatePath)));
114
- const maintainedModules = stableSortedStrings(seam.maintained_modules || []);
115
-
116
- let exactModuleMatches = [];
117
- let prefixModuleMatches = [];
118
- let tokenMatchedModules = [];
119
- let tokenMatchCount = 0;
120
-
121
- for (const modulePath of maintainedModules) {
122
- const moduleTokens = pathTokens(modulePath);
123
- const matchedTokens = sharedTokens(proposalTokenSet, moduleTokens);
124
- if (proposalPaths.some((candidatePath) => normalizePath(candidatePath) === normalizePath(modulePath))) {
125
- exactModuleMatches.push(modulePath);
126
- continue;
127
- }
128
- if (proposalPaths.some((candidatePath) =>
129
- pathPrefixMatches(candidatePath, modulePath) || pathPrefixMatches(modulePath, candidatePath)
130
- )) {
131
- prefixModuleMatches.push(modulePath);
132
- }
133
- if (matchedTokens.length > 0) {
134
- tokenMatchedModules.push({ modulePath, matchedTokens });
135
- tokenMatchCount = Math.max(tokenMatchCount, matchedTokens.length);
136
- }
137
- }
138
-
139
- const reasons = [];
140
- let score = 0;
141
-
142
- if (exactModuleMatches.length > 0) {
143
- score += 0.28;
144
- reasons.push(
145
- `exact maintained module match: ${stableSortedStrings(exactModuleMatches).map((modulePath) => `\`${modulePath}\``).join(", ")}`
146
- );
147
- }
148
- if (prefixModuleMatches.length > 0) {
149
- score += 0.18;
150
- reasons.push(
151
- `maintained module path proximity: ${stableSortedStrings(prefixModuleMatches).map((modulePath) => `\`${modulePath}\``).join(", ")}`
152
- );
153
- }
154
- if (tokenMatchCount > 0) {
155
- score += Math.min(0.18, 0.08 + (tokenMatchCount * 0.04));
156
- reasons.push(
157
- `path token corroboration: ${stableSortedStrings(tokenMatchedModules.flatMap((entry) => entry.matchedTokens)).map((token) => `\`${token}\``).join(", ")}`
158
- );
159
- }
160
-
161
- return {
162
- score,
163
- reasons,
164
- token_match_count: tokenMatchCount
165
- };
166
- }
167
-
168
- function outputEvidenceForProposal(proposalSurface, seam, outputRecord = null) {
169
- const proposalPaths = stableSortedStrings([
170
- proposalSurface.source_path,
171
- proposalSurface.canonical_rel_path
172
- ]);
173
- const proposalTokenSet = stableSortedStrings(proposalPaths.flatMap((candidatePath) => pathTokens(candidatePath)));
174
- const matchedOutputRoots = stableSortedStrings((outputRecord?.root_paths || []).filter((rootPath) =>
175
- proposalPaths.some((candidatePath) => pathPrefixMatches(candidatePath, rootPath))
176
- ));
177
- const outputTokenMatches = stableSortedStrings((outputRecord?.root_paths || []).flatMap((rootPath) =>
178
- sharedTokens(proposalTokenSet, pathTokens(rootPath))
179
- ));
180
-
181
- let score = 0;
182
- const reasons = [];
183
-
184
- if (matchedOutputRoots.length > 0) {
185
- score += 0.16;
186
- reasons.push(
187
- `output root alignment: ${matchedOutputRoots.map((rootPath) => `\`${rootPath}\``).join(", ")}`
188
- );
189
- } else if (outputTokenMatches.length > 0) {
190
- score += Math.min(0.1, 0.04 + (outputTokenMatches.length * 0.02));
191
- reasons.push(
192
- `output path corroboration: ${outputTokenMatches.map((token) => `\`${token}\``).join(", ")}`
193
- );
194
- }
195
-
196
- const proposalTrack = proposalSurface.track || null;
197
- const proposalKind = proposalSurface.kind || null;
198
- const seamKind = seam.kind || null;
199
- const kindAligned =
200
- ((proposalTrack === "ui" || proposalKind === "ui") && ["ui_presenter", "route_glue", "workflow_affordance"].includes(seamKind)) ||
201
- ((proposalTrack === "model" || proposalTrack === "capability" || proposalKind === "capability") && ["api_adapter", "route_glue", "policy_interpretation", "workflow_affordance"].includes(seamKind)) ||
202
- ((proposalTrack === "workflows" || proposalKind === "decision") && seamKind === "workflow_affordance");
203
-
204
- if (kindAligned) {
205
- score += 0.08;
206
- reasons.push(`proposal/seam kind alignment: \`${proposalTrack || proposalKind}\` -> \`${seamKind}\``);
207
- }
208
-
209
- return {
210
- score,
211
- reasons
212
- };
213
- }
214
-
215
- function dedupeReasons(reasons = []) {
216
- return stableSortedStrings(reasons);
217
- }
218
-
219
- function inferMaintainedSeamCandidates(proposalSurface, maintainedBoundaryArtifact = null) {
220
- if (!maintainedBoundaryArtifact || !Array.isArray(maintainedBoundaryArtifact.seams) || maintainedBoundaryArtifact.seams.length === 0) {
221
- return [];
222
- }
223
-
224
- const outputsById = new Map((maintainedBoundaryArtifact.outputs || []).map((output) => [output.output_id, output]));
225
-
226
- const provisionalCandidates = maintainedBoundaryArtifact.seams.map((seam) => {
227
- const outputRecord = outputsById.get(seam.output_id) || null;
228
- const semanticEvidence = semanticEvidenceForProposal(proposalSurface, seam);
229
- const pathEvidence = pathEvidenceForProposal(proposalSurface, seam);
230
- const outputEvidence = outputEvidenceForProposal(proposalSurface, seam, outputRecord);
231
- const rawScore = semanticEvidence.score + pathEvidence.score + outputEvidence.score;
232
-
233
- return {
234
- seam,
235
- rawScore,
236
- semantic_match_count: semanticEvidence.matched_dependencies.length,
237
- seam_id: seam.seam_id,
238
- output_id: seam.output_id || null,
239
- label: seam.label || null,
240
- kind: seam.kind || null,
241
- ownership_class: seam.ownership_class || null,
242
- status: seam.status || null,
243
- maintained_modules: stableSortedStrings(seam.maintained_modules || []),
244
- emitted_dependencies: stableSortedStrings(seam.emitted_dependencies || []),
245
- allowed_change_classes: stableSortedStrings(seam.allowed_change_classes || []),
246
- drift_signals: stableSortedStrings(seam.drift_signals || []),
247
- match_reasons: dedupeReasons([
248
- ...semanticEvidence.reasons,
249
- ...pathEvidence.reasons,
250
- ...outputEvidence.reasons
251
- ]),
252
- confidence: Math.min(1, Number(rawScore.toFixed(2)))
253
- };
254
- });
255
-
256
- const candidates = provisionalCandidates
257
- .map((candidate) => {
258
- const siblingCandidates = provisionalCandidates.filter((entry) =>
259
- entry.output_id &&
260
- entry.output_id === candidate.output_id &&
261
- entry.seam_id !== candidate.seam_id
262
- );
263
- const ambiguousSibling = siblingCandidates.find((sibling) =>
264
- sibling.rawScore >= 0.48 &&
265
- Math.abs(sibling.rawScore - candidate.rawScore) <= 0.12 &&
266
- Math.max(candidate.semantic_match_count, sibling.semantic_match_count) <= 1
267
- );
268
- const penalty = ambiguousSibling ? 0.18 : 0;
269
-
270
- return {
271
- ...candidate,
272
- match_reasons: ambiguousSibling
273
- ? [...candidate.match_reasons, `ambiguity penalty: sibling seam evidence in \`${candidate.output_id}\` is too similar`]
274
- : candidate.match_reasons,
275
- confidence: Math.max(0, Number((candidate.rawScore - penalty).toFixed(2)))
276
- };
277
- })
278
- .filter((candidate) => candidate.confidence >= 0.6 && candidate.match_reasons.length > 0)
279
- .sort((a, b) => {
280
- const severityCompare = severityRank(b.status) - severityRank(a.status);
281
- if (severityCompare !== 0) return severityCompare;
282
- if (b.confidence !== a.confidence) return b.confidence - a.confidence;
283
- return String(a.seam_id || "").localeCompare(String(b.seam_id || ""));
284
- });
285
-
286
- return candidates.map(({ seam, rawScore, semantic_match_count, ...candidate }) => candidate);
287
- }
288
-
289
- export function selectorReviewGroupId(selector) {
290
- if (!selector) {
291
- return null;
292
- }
293
- if (selector.startsWith("projection-review:")) {
294
- return `projection_review:${selector.slice("projection-review:".length)}`;
295
- }
296
- if (selector.startsWith("ui-review:")) {
297
- return `ui_review:${selector.slice("ui-review:".length)}`;
298
- }
299
- if (selector.startsWith("workflow-review:")) {
300
- return `workflow_review:${selector.slice("workflow-review:".length)}`;
301
- }
302
- return null;
303
- }
304
-
305
- export function selectorBundleReviewSlug(selector) {
306
- if (!selector) {
307
- return null;
308
- }
309
- if (selector.startsWith("bundle-review:")) {
310
- const slug = selector.slice("bundle-review:".length);
311
- return slug || null;
312
- }
313
- return null;
314
- }
315
-
316
- export function parseAdoptSelector(value) {
317
- if (!value) {
318
- return null;
319
- }
320
- const selector = String(value).trim();
321
- if (ADOPT_SELECTORS.has(selector)) {
322
- return selector;
323
- }
324
- if (selectorReviewGroupId(selector)) {
325
- return selector;
326
- }
327
- if (selectorBundleReviewSlug(selector)) {
328
- return selector;
329
- }
330
- if (selector.startsWith("bundle:") && selector.length > "bundle:".length) {
331
- return selector;
332
- }
333
- throw new Error(`Unsupported adopt selector '${selector}'`);
334
- }
335
-
336
- export function adoptionItemKey(item) {
337
- return `${item.bundle}:${item.kind}:${item.item}`;
338
- }
339
-
340
- export function selectorMatchesItem(selector, item) {
341
- if (!selector) {
342
- return false;
343
- }
344
- const reviewGroupId = selectorReviewGroupId(selector);
345
- const bundleReviewSlug = selectorBundleReviewSlug(selector);
346
- if (reviewGroupId) {
347
- return (item.blocking_dependencies || []).some((dependency) => dependency.id === reviewGroupId);
348
- }
349
- if (bundleReviewSlug) {
350
- return item.bundle === bundleReviewSlug;
351
- }
352
- if (selector === "actors") return item.kind === "actor";
353
- if (selector === "roles") return item.kind === "role";
354
- if (selector === "enums") return item.kind === "enum";
355
- if (selector === "shapes") return item.kind === "shape";
356
- if (selector === "entities") return item.kind === "entity";
357
- if (selector === "capabilities") return item.kind === "capability";
358
- if (selector === "widgets") return item.kind === "widget";
359
- if (selector === "docs") return item.track === "docs";
360
- if (selector === "journeys") return item.track === "docs" && String(item.canonical_rel_path || "").startsWith("docs/journeys/");
361
- if (selector === "workflows") return item.track === "workflows" || item.kind === "decision";
362
- if (selector === "verification") return item.kind === "verification";
363
- if (selector === "ui") return item.track === "ui";
364
- if (selector.startsWith("bundle:")) return item.bundle === selector.slice("bundle:".length);
365
- return false;
366
- }
367
-
368
- function blockedStatusForItem(item) {
369
- if ((item.projection_impacts || []).length > 0) {
370
- return "needs_projection_review";
371
- }
372
- if ((item.blocking_dependencies || []).some((dependency) => dependency.type === "projection_review")) {
373
- return "needs_projection_review";
374
- }
375
- if ((item.ui_impacts || []).length > 0) {
376
- return "needs_ui_review";
377
- }
378
- if ((item.blocking_dependencies || []).some((dependency) => dependency.type === "ui_review")) {
379
- return "needs_ui_review";
380
- }
381
- if ((item.workflow_impacts || []).length > 0) {
382
- return "needs_workflow_review";
383
- }
384
- if ((item.blocking_dependencies || []).some((dependency) => dependency.type === "workflow_review")) {
385
- return "needs_workflow_review";
386
- }
387
- return "pending";
388
- }
389
-
390
- export function refreshDerivedStatuses(items, approvedReviewGroups = []) {
391
- const approvedSet = new Set(approvedReviewGroups || []);
392
- return items.map((item) => {
393
- if (item.status === "applied" || item.status === "skipped" || item.status === "approved") {
394
- return item;
395
- }
396
- const blockingDependencies = item.blocking_dependencies || [];
397
- if (blockingDependencies.length === 0) {
398
- return { ...item, status: item.status === "pending" ? "pending" : blockedStatusForItem(item) };
399
- }
400
- const fullyApproved = blockingDependencies.every((dependency) => approvedSet.has(dependency.id));
401
- return {
402
- ...item,
403
- status: fullyApproved ? "approved" : blockedStatusForItem(item)
404
- };
405
- });
406
- }
407
-
408
- export function mergeAdoptionPlanState(baseItems, existingPlan, topogramRoot) {
409
- const existingItems = new Map(
410
- (existingPlan?.items || []).map((item) => [`${item.bundle}:${item.kind}:${item.item}`, item])
411
- );
412
- const merged = baseItems.map((item) => {
413
- const existing = existingItems.get(`${item.bundle}:${item.kind}:${item.item}`);
414
- const mergedItem = existing ? { ...item, status: existing.status || item.status } : item;
415
- if (
416
- mergedItem.status !== "applied" &&
417
- mergedItem.status !== "skipped" &&
418
- mergedItem.suggested_action !== "apply_doc_link_patch" &&
419
- mergedItem.suggested_action !== "apply_doc_metadata_patch" &&
420
- mergedItem.suggested_action !== "apply_projection_permission_patch" &&
421
- mergedItem.suggested_action !== "apply_projection_auth_patch" &&
422
- mergedItem.suggested_action !== "apply_projection_ownership_patch" &&
423
- mergedItem.canonical_rel_path &&
424
- topogramRoot &&
425
- fs.existsSync(path.join(topogramRoot, mergedItem.canonical_rel_path))
426
- ) {
427
- return { ...mergedItem, status: "applied" };
428
- }
429
- return mergedItem;
430
- });
431
- for (const existing of existingPlan?.items || []) {
432
- const key = `${existing.bundle}:${existing.kind}:${existing.item}`;
433
- if (!merged.some((item) => adoptionItemKey(item) === key) && existing.status === "applied") {
434
- merged.push({ ...existing });
435
- }
436
- }
437
- return refreshDerivedStatuses(merged, existingPlan?.approved_review_groups || []);
438
- }
439
-
440
- function reviewGroupIdsForBundle(items, bundleSlug) {
441
- const ids = new Set();
442
- for (const item of items) {
443
- if (item.bundle !== bundleSlug) {
444
- continue;
445
- }
446
- for (const dependency of item.blocking_dependencies || []) {
447
- ids.add(dependency.id);
448
- }
449
- }
450
- return [...ids].sort();
451
- }
452
-
453
- export function applyAdoptionSelector(adoptionPlan, selector, writeMode) {
454
- const appliedItems = [];
455
- const approvedItems = [];
456
- const skippedItems = [];
457
- const blockedItems = [];
458
- const selectedItems = [];
459
- const reviewGroupId = selectorReviewGroupId(selector);
460
- const bundleReviewSlug = selectorBundleReviewSlug(selector);
461
- const updatedPlan = {
462
- ...adoptionPlan,
463
- approved_review_groups: [...new Set(adoptionPlan.approved_review_groups || [])],
464
- items: adoptionPlan.items.map((item) => ({ ...item }))
465
- };
466
- let updatedItems = updatedPlan.items;
467
-
468
- const expandSelectedItemsForDependentShapes = (keys) => {
469
- const expanded = new Set(keys);
470
- const selectedCapabilityBundles = new Set(
471
- [...expanded]
472
- .map((key) => updatedItems.find((item) => adoptionItemKey(item) === key))
473
- .filter((item) => item?.kind === "capability")
474
- .map((item) => item.bundle)
475
- );
476
- for (const item of updatedItems) {
477
- if (item.kind === "shape" && item.status !== "skipped" && selectedCapabilityBundles.has(item.bundle)) {
478
- expanded.add(adoptionItemKey(item));
479
- }
480
- }
481
- return [...expanded];
482
- };
483
-
484
- if (!selector) {
485
- return { plan: updatedPlan, appliedItems, approvedItems, skippedItems, blockedItems, selectedItems };
486
- }
487
-
488
- if (reviewGroupId || bundleReviewSlug) {
489
- const reviewGroupIds = reviewGroupId
490
- ? [reviewGroupId]
491
- : reviewGroupIdsForBundle(updatedItems, bundleReviewSlug);
492
- for (const id of reviewGroupIds) {
493
- if (!updatedPlan.approved_review_groups.includes(id)) {
494
- updatedPlan.approved_review_groups.push(id);
495
- }
496
- }
497
- updatedItems = refreshDerivedStatuses(updatedItems, updatedPlan.approved_review_groups);
498
- updatedPlan.items = updatedItems;
499
- for (const item of updatedItems) {
500
- if (!selectorMatchesItem(selector, item)) {
501
- continue;
502
- }
503
- if (item.status === "approved") {
504
- approvedItems.push(item.item);
505
- } else if (["needs_projection_review", "needs_ui_review", "needs_workflow_review"].includes(item.status)) {
506
- blockedItems.push(item.item);
507
- }
508
- }
509
- return { plan: updatedPlan, appliedItems, approvedItems, skippedItems, blockedItems, selectedItems };
510
- }
511
-
512
- if (selector === "from-plan") {
513
- const initiallySelected = [];
514
- for (const item of updatedItems) {
515
- if (item.status === "approved" || item.status === "pending") {
516
- initiallySelected.push(adoptionItemKey(item));
517
- } else if (item.status === "skipped") {
518
- skippedItems.push(item.item);
519
- } else if (["needs_projection_review", "needs_ui_review", "needs_workflow_review"].includes(item.status)) {
520
- blockedItems.push(item.item);
521
- }
522
- }
523
- const expandedSelected = expandSelectedItemsForDependentShapes(initiallySelected);
524
- for (const key of expandedSelected) {
525
- const item = updatedItems.find((entry) => adoptionItemKey(entry) === key);
526
- if (!item || item.status === "skipped") continue;
527
- selectedItems.push(key);
528
- appliedItems.push(item.item);
529
- if (writeMode) {
530
- item.status = "applied";
531
- }
532
- }
533
- updatedPlan.items = updatedItems;
534
- return { plan: updatedPlan, appliedItems, approvedItems, skippedItems, blockedItems, selectedItems };
535
- }
536
-
537
- const initiallySelected = [];
538
- for (const item of updatedItems) {
539
- if (item.status === "skipped") {
540
- skippedItems.push(item.item);
541
- continue;
542
- }
543
- if (["needs_projection_review", "needs_ui_review", "needs_workflow_review"].includes(item.status)) {
544
- if (selectorMatchesItem(selector, item)) {
545
- blockedItems.push(item.item);
546
- }
547
- continue;
548
- }
549
- if (selectorMatchesItem(selector, item)) {
550
- initiallySelected.push(adoptionItemKey(item));
551
- }
552
- }
553
- const expandedSelected = expandSelectedItemsForDependentShapes(initiallySelected);
554
- for (const key of expandedSelected) {
555
- const item = updatedItems.find((entry) => adoptionItemKey(entry) === key);
556
- if (!item || item.status === "skipped") {
557
- continue;
558
- }
559
- selectedItems.push(key);
560
- appliedItems.push(item.item);
561
- if (writeMode) {
562
- item.status = "applied";
563
- }
564
- }
565
- updatedPlan.items = updatedItems;
566
- return { plan: updatedPlan, appliedItems, approvedItems, skippedItems, blockedItems, selectedItems };
567
- }
568
-
569
- export function summarizeAdoptionPlanItems(items) {
570
- const summary = {
571
- approved_items: [],
572
- applied_items: [],
573
- skipped_items: [],
574
- blocked_items: []
575
- };
576
- for (const item of items || []) {
577
- if (item.status === "approved") {
578
- summary.approved_items.push(item.item);
579
- } else if (item.status === "applied") {
580
- summary.applied_items.push(item.item);
581
- } else if (item.status === "skipped") {
582
- summary.skipped_items.push(item.item);
583
- } else if (["needs_projection_review", "needs_ui_review", "needs_workflow_review"].includes(item.status)) {
584
- summary.blocked_items.push(item.item);
585
- }
586
- }
587
- for (const key of Object.keys(summary)) {
588
- summary[key] = [...new Set(summary[key])].sort();
589
- }
590
- return summary;
591
- }
592
-
593
- function inferRecommendedAdoptionState(item) {
594
- if (item.status === "skipped") {
595
- return "reject";
596
- }
597
- if (item.status === "applied") {
598
- return "accept";
599
- }
600
- if ((item.projection_impacts || []).length > 0 || (item.ui_impacts || []).length > 0 || (item.workflow_impacts || []).length > 0) {
601
- return "customize";
602
- }
603
- if (item.suggested_action && String(item.suggested_action).includes("_patch")) {
604
- return "customize";
605
- }
606
- return "accept";
607
- }
608
-
609
- function inferCurrentAdoptionState(item) {
610
- if (item.status === "skipped") {
611
- return "reject";
612
- }
613
- if (item.status === "applied") {
614
- return "accept";
615
- }
616
- return "stage";
617
- }
618
-
619
- function mappingSuggestionsForItem(item) {
620
- const suggestions = [];
621
- for (const dependency of item.blocking_dependencies || []) {
622
- suggestions.push({
623
- type: dependency.type || "review",
624
- id: dependency.id,
625
- reason: dependency.reason || null
626
- });
627
- }
628
- return suggestions;
629
- }
630
-
631
- export function buildAgentAdoptionPlan(adoptionPlan, maintainedBoundaryArtifact = null) {
632
- const items = (adoptionPlan?.items || []).map((item) => {
633
- const currentState = inferCurrentAdoptionState(item);
634
- const maintainedSeamCandidates = inferMaintainedSeamCandidates({
635
- item: item.item || null,
636
- kind: item.kind || null,
637
- track: item.track || null,
638
- source_path: item.source_path || null,
639
- canonical_rel_path: item.canonical_rel_path || null,
640
- requirements: {
641
- related_docs: [...new Set(item.related_docs || [])].sort(),
642
- related_capabilities: [...new Set(item.related_capabilities || [])].sort(),
643
- related_rules: [...new Set(item.related_rules || [])].sort(),
644
- related_workflows: [...new Set(item.related_workflows || [])].sort()
645
- },
646
- projection_impacts: [...(item.projection_impacts || [])],
647
- ui_impacts: [...(item.ui_impacts || [])],
648
- workflow_impacts: [...(item.workflow_impacts || [])]
649
- }, maintainedBoundaryArtifact);
650
- return {
651
- id: adoptionItemKey(item),
652
- bundle: item.bundle,
653
- item: item.item,
654
- kind: item.kind,
655
- track: item.track || null,
656
- source_path: item.source_path || null,
657
- canonical_rel_path: item.canonical_rel_path || null,
658
- review_boundary: reviewBoundaryForImportProposal(item),
659
- current_state: currentState,
660
- recommended_state: inferRecommendedAdoptionState(item),
661
- supported_states: ADOPTION_STATE_VOCABULARY,
662
- human_review_required:
663
- currentState === "stage" ||
664
- ["needs_projection_review", "needs_ui_review", "needs_workflow_review"].includes(item.status),
665
- provenance: {
666
- bundle: item.bundle,
667
- source_path: item.source_path || null,
668
- canonical_rel_path: item.canonical_rel_path || null
669
- },
670
- requirements: {
671
- related_docs: [...new Set(item.related_docs || [])].sort(),
672
- related_capabilities: [...new Set(item.related_capabilities || [])].sort(),
673
- related_rules: [...new Set(item.related_rules || [])].sort(),
674
- related_workflows: [...new Set(item.related_workflows || [])].sort(),
675
- blocking_dependencies: [...(item.blocking_dependencies || [])]
676
- },
677
- projection_impacts: [...(item.projection_impacts || [])],
678
- ui_impacts: [...(item.ui_impacts || [])],
679
- workflow_impacts: [...(item.workflow_impacts || [])],
680
- maintained_seam_candidates: maintainedSeamCandidates,
681
- mapping_suggestions: mappingSuggestionsForItem(item),
682
- available_actions: ADOPTION_STATE_VOCABULARY
683
- };
684
- });
685
-
686
- return {
687
- type: "agent_adoption_plan",
688
- version: 1,
689
- workspace: adoptionPlan?.workspace || null,
690
- source_plan_type: adoptionPlan?.type || null,
691
- adoption_state_vocabulary: ADOPTION_STATE_VOCABULARY,
692
- terminology: {
693
- candidate_workspace_term: "candidate",
694
- non_canonical_adoption_state: "stage"
695
- },
696
- approved_review_groups: [...new Set(adoptionPlan?.approved_review_groups || [])].sort(),
697
- imported_proposal_surfaces: items,
698
- staged_items: items.filter((item) => item.current_state === "stage").map((item) => item.id),
699
- accepted_items: items.filter((item) => item.current_state === "accept").map((item) => item.id),
700
- rejected_items: items.filter((item) => item.current_state === "reject").map((item) => item.id),
701
- requires_human_review: items.filter((item) => item.human_review_required).map((item) => item.id)
702
- };
703
- }
1
+ export {
2
+ adoptionItemKey,
3
+ applyAdoptionSelector,
4
+ buildAgentAdoptionPlan,
5
+ mergeAdoptionPlanState,
6
+ parseAdoptSelector,
7
+ refreshDerivedStatuses,
8
+ selectorBundleReviewSlug,
9
+ selectorMatchesItem,
10
+ selectorReviewGroupId,
11
+ summarizeAdoptionPlanItems
12
+ } from "./plan/index.js";