@topogram/cli 0.3.64 → 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 (245) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +703 -0
  3. package/src/adoption/plan.js +12 -703
  4. package/src/agent-ops/query-builders/auth.js +375 -0
  5. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  6. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  7. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  8. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  9. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  10. package/src/agent-ops/query-builders/change-risk.js +25 -0
  11. package/src/agent-ops/query-builders/common.js +149 -0
  12. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  13. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  14. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  15. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  16. package/src/agent-ops/query-builders/work-packets.js +417 -0
  17. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  18. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  19. package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
  20. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  21. package/src/agent-ops/query-builders.d.ts +26 -26
  22. package/src/agent-ops/query-builders.js +42 -5021
  23. package/src/catalog/constants.js +10 -0
  24. package/src/catalog/copy.js +60 -0
  25. package/src/catalog/diagnostics.js +15 -0
  26. package/src/catalog/entries.js +42 -0
  27. package/src/catalog/files.js +67 -0
  28. package/src/catalog/provenance.js +122 -0
  29. package/src/catalog/source.js +150 -0
  30. package/src/catalog/validation.js +252 -0
  31. package/src/catalog.d.ts +2 -0
  32. package/src/catalog.js +18 -746
  33. package/src/cli/commands/catalog/check.js +31 -0
  34. package/src/cli/commands/catalog/copy.js +59 -0
  35. package/src/cli/commands/catalog/doctor.js +248 -0
  36. package/src/cli/commands/catalog/help.js +21 -0
  37. package/src/cli/commands/catalog/list.js +52 -0
  38. package/src/cli/commands/catalog/runner.js +92 -0
  39. package/src/cli/commands/catalog/shared.js +17 -0
  40. package/src/cli/commands/catalog/show.js +134 -0
  41. package/src/cli/commands/catalog.js +30 -615
  42. package/src/cli/commands/generator-policy/package-info.js +162 -0
  43. package/src/cli/commands/generator-policy/payloads.js +372 -0
  44. package/src/cli/commands/generator-policy/printers.js +159 -0
  45. package/src/cli/commands/generator-policy/runner.js +81 -0
  46. package/src/cli/commands/generator-policy/shared.js +39 -0
  47. package/src/cli/commands/generator-policy.js +15 -783
  48. package/src/cli/commands/import/adopt.js +170 -0
  49. package/src/cli/commands/import/check.js +91 -0
  50. package/src/cli/commands/import/diff.js +84 -0
  51. package/src/cli/commands/import/help.js +47 -0
  52. package/src/cli/commands/import/paths.js +277 -0
  53. package/src/cli/commands/import/plan.js +284 -0
  54. package/src/cli/commands/import/refresh.js +470 -0
  55. package/src/cli/commands/import/status-history.js +196 -0
  56. package/src/cli/commands/import/workspace.js +230 -0
  57. package/src/cli/commands/import.js +33 -1732
  58. package/src/cli/commands/package/constants.js +17 -0
  59. package/src/cli/commands/package/doctor.js +240 -0
  60. package/src/cli/commands/package/help.js +27 -0
  61. package/src/cli/commands/package/lockfile.js +135 -0
  62. package/src/cli/commands/package/npm.js +97 -0
  63. package/src/cli/commands/package/reporting.js +35 -0
  64. package/src/cli/commands/package/runner.js +33 -0
  65. package/src/cli/commands/package/shared.js +9 -0
  66. package/src/cli/commands/package/update-cli.js +252 -0
  67. package/src/cli/commands/package/versions.js +35 -0
  68. package/src/cli/commands/package.js +29 -813
  69. package/src/cli/commands/query/change-plan.js +68 -0
  70. package/src/cli/commands/query/definitions.js +202 -0
  71. package/src/cli/commands/query/import-adopt.js +121 -0
  72. package/src/cli/commands/query/runner/artifacts.js +102 -0
  73. package/src/cli/commands/query/runner/boundaries.js +211 -0
  74. package/src/cli/commands/query/runner/change.js +182 -0
  75. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  76. package/src/cli/commands/query/runner/index.js +31 -0
  77. package/src/cli/commands/query/runner/output.js +12 -0
  78. package/src/cli/commands/query/runner/workflow.js +241 -0
  79. package/src/cli/commands/query/runner.js +3 -0
  80. package/src/cli/commands/query/workflow-context.js +5 -0
  81. package/src/cli/commands/query/workspace.js +274 -0
  82. package/src/cli/commands/query.js +9 -1300
  83. package/src/cli/commands/template/baseline.js +100 -0
  84. package/src/cli/commands/template/check.js +466 -0
  85. package/src/cli/commands/template/constants.js +8 -0
  86. package/src/cli/commands/template/diagnostics.js +26 -0
  87. package/src/cli/commands/template/help.js +28 -0
  88. package/src/cli/commands/template/lifecycle.js +404 -0
  89. package/src/cli/commands/template/list-show.js +287 -0
  90. package/src/cli/commands/template/policy.js +422 -0
  91. package/src/cli/commands/template/shared.js +127 -0
  92. package/src/cli/commands/template/updates.js +352 -0
  93. package/src/cli/commands/template.js +41 -2143
  94. package/src/generator/api/contracts.js +497 -0
  95. package/src/generator/api/metadata.js +221 -0
  96. package/src/generator/api/openapi.js +559 -0
  97. package/src/generator/api/schema.js +124 -0
  98. package/src/generator/api/types.d.ts +98 -0
  99. package/src/generator/api.js +3 -1195
  100. package/src/generator/context/shared/domain-sdlc.js +282 -0
  101. package/src/generator/context/shared/maintained-boundary.js +665 -0
  102. package/src/generator/context/shared/metrics.js +85 -0
  103. package/src/generator/context/shared/primitives.js +64 -0
  104. package/src/generator/context/shared/relationships.js +453 -0
  105. package/src/generator/context/shared/summaries.js +263 -0
  106. package/src/generator/context/shared/types.d.ts +207 -0
  107. package/src/generator/context/shared.d.ts +42 -0
  108. package/src/generator/context/shared.js +80 -1390
  109. package/src/generator/context/slice/core.js +397 -0
  110. package/src/generator/context/slice/sdlc.js +417 -0
  111. package/src/generator/context/slice/ui-packets.js +183 -0
  112. package/src/generator/context/slice.js +2 -859
  113. package/src/generator/registry/index.js +507 -0
  114. package/src/generator/registry.js +18 -504
  115. package/src/generator/runtime/environment/index.js +666 -0
  116. package/src/generator/runtime/environment.js +4 -666
  117. package/src/generator/runtime/runtime-check/index.js +554 -0
  118. package/src/generator/runtime/runtime-check.js +4 -554
  119. package/src/generator/runtime/shared/index.js +572 -0
  120. package/src/generator/runtime/shared.js +19 -570
  121. package/src/generator/shared.d.ts +2 -0
  122. package/src/generator/surfaces/shared.d.ts +3 -0
  123. package/src/generator/widget-conformance/behavior-report.js +258 -0
  124. package/src/generator/widget-conformance/checks.js +371 -0
  125. package/src/generator/widget-conformance/projection-context.js +200 -0
  126. package/src/generator/widget-conformance/report.js +166 -0
  127. package/src/generator/widget-conformance/types.d.ts +121 -0
  128. package/src/generator/widget-conformance.js +3 -824
  129. package/src/import/core/context.d.ts +3 -0
  130. package/src/import/core/contracts.d.ts +1 -0
  131. package/src/import/core/registry.d.ts +4 -0
  132. package/src/import/core/runner/candidates.js +217 -0
  133. package/src/import/core/runner/options.js +22 -0
  134. package/src/import/core/runner/reports.js +50 -0
  135. package/src/import/core/runner/run.js +79 -0
  136. package/src/import/core/runner/tracks.js +150 -0
  137. package/src/import/core/runner/ui-drafts.js +337 -0
  138. package/src/import/core/runner.js +3 -698
  139. package/src/import/core/shared/api-routes.js +221 -0
  140. package/src/import/core/shared/candidates.js +97 -0
  141. package/src/import/core/shared/files.js +177 -0
  142. package/src/import/core/shared/next-app.js +389 -0
  143. package/src/import/core/shared/types.d.ts +51 -0
  144. package/src/import/core/shared/ui-routes.js +230 -0
  145. package/src/import/core/shared.js +60 -861
  146. package/src/new-project/constants.js +128 -0
  147. package/src/new-project/create.js +83 -0
  148. package/src/new-project/json.js +28 -0
  149. package/src/new-project/metadata.js +96 -0
  150. package/src/new-project/package-spec.js +161 -0
  151. package/src/new-project/project-files.js +348 -0
  152. package/src/new-project/template-policy.js +269 -0
  153. package/src/new-project/template-resolution.js +368 -0
  154. package/src/new-project/template-snapshots.js +430 -0
  155. package/src/new-project/template-updates.js +512 -0
  156. package/src/new-project/types.d.ts +83 -0
  157. package/src/new-project.js +6 -2277
  158. package/src/parser.d.ts +87 -1
  159. package/src/parser.js +118 -0
  160. package/src/policy/review-boundaries.d.ts +15 -0
  161. package/src/project-config/index.js +564 -0
  162. package/src/project-config.js +19 -561
  163. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  164. package/src/resolver/enrich/bug.js +2 -0
  165. package/src/resolver/enrich/pitch.js +2 -0
  166. package/src/resolver/enrich/requirement.js +2 -0
  167. package/src/resolver/enrich/task.js +2 -0
  168. package/src/resolver/index.js +19 -2089
  169. package/src/resolver/normalize.js +384 -1
  170. package/src/resolver/plans.js +168 -0
  171. package/src/resolver/projections-api.js +494 -0
  172. package/src/resolver/projections-db.js +133 -0
  173. package/src/resolver/projections-ui.js +317 -0
  174. package/src/resolver/shapes.js +251 -0
  175. package/src/resolver/shared.js +278 -0
  176. package/src/resolver/widgets.js +132 -0
  177. package/src/template-trust/constants.js +62 -0
  178. package/src/template-trust/content.js +258 -0
  179. package/src/template-trust/diff.js +92 -0
  180. package/src/template-trust/policy.js +61 -0
  181. package/src/template-trust/record.js +90 -0
  182. package/src/template-trust/status.js +182 -0
  183. package/src/template-trust.js +24 -687
  184. package/src/text-helpers.d.ts +1 -0
  185. package/src/topogram-types.d.ts +69 -0
  186. package/src/validator/common.js +488 -0
  187. package/src/validator/data-model.js +237 -0
  188. package/src/validator/docs.js +167 -0
  189. package/src/validator/expressions.js +146 -1
  190. package/src/validator/index.d.ts +23 -0
  191. package/src/validator/index.js +32 -3585
  192. package/src/validator/kinds.d.ts +41 -0
  193. package/src/validator/kinds.js +2 -0
  194. package/src/validator/model-helpers.js +46 -0
  195. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  196. package/src/validator/per-kind/bug.js +6 -0
  197. package/src/validator/per-kind/domain.js +15 -2
  198. package/src/validator/per-kind/pitch.js +7 -0
  199. package/src/validator/per-kind/requirement.js +5 -0
  200. package/src/validator/per-kind/task.js +7 -0
  201. package/src/validator/per-kind/widget.js +14 -0
  202. package/src/validator/projections/api-http-async.js +410 -0
  203. package/src/validator/projections/api-http-authz.js +88 -0
  204. package/src/validator/projections/api-http-core.js +205 -0
  205. package/src/validator/projections/api-http-policies.js +339 -0
  206. package/src/validator/projections/api-http-responses.js +233 -0
  207. package/src/validator/projections/api-http.js +44 -0
  208. package/src/validator/projections/db.js +353 -0
  209. package/src/validator/projections/generator-defaults.js +45 -0
  210. package/src/validator/projections/helpers.js +87 -0
  211. package/src/validator/projections/ui-helpers.js +214 -0
  212. package/src/validator/projections/ui-navigation.js +344 -0
  213. package/src/validator/projections/ui-structure.js +364 -0
  214. package/src/validator/projections/ui-widgets.js +493 -0
  215. package/src/validator/projections/ui.js +46 -0
  216. package/src/validator/registry.js +48 -1
  217. package/src/validator/utils.d.ts +20 -0
  218. package/src/validator/utils.js +115 -12
  219. package/src/widget-behavior.d.ts +1 -0
  220. package/src/workflows/import-app/api/collect.js +221 -0
  221. package/src/workflows/import-app/api/openapi.js +257 -0
  222. package/src/workflows/import-app/api/routes.js +327 -0
  223. package/src/workflows/import-app/api/sources.js +22 -0
  224. package/src/workflows/import-app/api.js +2 -797
  225. package/src/workflows/reconcile/adoption-plan/build.js +208 -0
  226. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  227. package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
  228. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  229. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  230. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  231. package/src/workflows/reconcile/adoption-plan.js +30 -740
  232. package/src/workflows/reconcile/auth/closures.js +115 -0
  233. package/src/workflows/reconcile/auth/formatters.js +142 -0
  234. package/src/workflows/reconcile/auth/inference.js +330 -0
  235. package/src/workflows/reconcile/auth/roles.js +122 -0
  236. package/src/workflows/reconcile/auth.js +35 -690
  237. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  238. package/src/workflows/reconcile/bundle-core.js +12 -598
  239. package/src/workflows/reconcile/canonical-surface.js +1 -1
  240. package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
  241. package/src/workflows/reconcile/impacts/indexes.js +101 -0
  242. package/src/workflows/reconcile/impacts/patches.js +252 -0
  243. package/src/workflows/reconcile/impacts/reports.js +80 -0
  244. package/src/workflows/reconcile/impacts.js +14 -623
  245. package/src/workspace-docs.d.ts +29 -0
@@ -0,0 +1,241 @@
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 { resolveWorkspace } from "../../../../resolver.js";
9
+ import {
10
+ buildImportPlanPayload,
11
+ buildResolvedWorkflowContextPayload,
12
+ buildSingleAgentPlanPayload,
13
+ buildWorkflowPresetActivationPayload,
14
+ buildWorkflowPresetCustomizationPayload,
15
+ buildWorkflowPresetDiffPayload,
16
+ buildWorkflowPresetState
17
+ } from "../../../../agent-ops/query-builders.js";
18
+ import {
19
+ adoptionPlanPath,
20
+ artifactOrNull,
21
+ buildMaintainedBundle,
22
+ buildSlice,
23
+ buildTaskMode,
24
+ generatorTargetsForWorkflowContext,
25
+ hasSelectors,
26
+ normalizeTopogramPath,
27
+ printValidationFailure,
28
+ readJson,
29
+ resultOk,
30
+ selectorOptions,
31
+ workflowPresetSelectors
32
+ } from "../workspace.js";
33
+ import { resolveRecommendedQueryFamily } from "../workflow-context.js";
34
+ import { printJson } from "./output.js";
35
+
36
+ /**
37
+ * @typedef {Record<string, any>} AnyRecord
38
+ */
39
+
40
+ /**
41
+ * @param {AnyRecord} context
42
+ * @returns {number|null}
43
+ */
44
+ export function runWorkflowQuery(context) {
45
+ const queryName = context.commandArgs?.queryName;
46
+ const selectors = selectorOptions(context);
47
+
48
+ if (queryName === "next-action") {
49
+ const result = buildTaskMode(parsePath(context.inputPath), selectors, context.modeId || "import-adopt", context.fromTopogramPath);
50
+ if (!resultOk(result)) return printValidationFailure(result);
51
+ return printJson({
52
+ type: "next_action_query",
53
+ mode: result.artifact.mode,
54
+ summary: result.artifact.summary || null,
55
+ next_action: result.artifact.next_action || null,
56
+ recommended_query_family: resolveRecommendedQueryFamily(result.artifact.next_action || null, result.artifact.mode),
57
+ immediate_artifacts: (result.artifact.preferred_context_artifacts || []).slice(0, 2),
58
+ preferred_context_artifacts: result.artifact.preferred_context_artifacts || [],
59
+ review_emphasis: result.artifact.review_emphasis || [],
60
+ write_scope: result.artifact.write_scope || null,
61
+ verification_targets: result.artifact.verification_targets || null
62
+ });
63
+ }
64
+
65
+ if (queryName === "single-agent-plan") {
66
+ return runSingleAgentPlan(context, selectors);
67
+ }
68
+
69
+ if (queryName === "resolved-workflow-context") {
70
+ return runResolvedWorkflowContext(context, selectors);
71
+ }
72
+
73
+ if (queryName === "workflow-preset-activation") {
74
+ if (!context.modeId) {
75
+ throw new Error("query workflow-preset-activation requires --mode <modeling|maintained-app-edit|import-adopt|diff-review|verification>.");
76
+ }
77
+ const topogramRoot = normalizeTopogramPath(context.inputPath);
78
+ const taskModeResult = buildTaskMode(parsePath(context.inputPath), selectors, context.modeId, context.fromTopogramPath);
79
+ if (!resultOk(taskModeResult)) return printValidationFailure(taskModeResult);
80
+ let importPlan = null;
81
+ if (context.modeId === "import-adopt" && fs.existsSync(adoptionPlanPath(topogramRoot))) {
82
+ const workflowPresets = buildWorkflowPresetState({
83
+ workspace: topogramRoot,
84
+ selectors: workflowPresetSelectors(taskModeResult.artifact, context.providerId, context.presetId, "workflow-preset-activation")
85
+ });
86
+ importPlan = buildImportPlanPayload(readJson(adoptionPlanPath(topogramRoot)), taskModeResult.artifact, null, workflowPresets);
87
+ }
88
+ return printJson(buildWorkflowPresetActivationPayload({
89
+ workspace: topogramRoot,
90
+ taskModeArtifact: taskModeResult.artifact,
91
+ importPlan,
92
+ selectors: workflowPresetSelectors(taskModeResult.artifact, context.providerId, context.presetId, "workflow-preset-activation")
93
+ }));
94
+ }
95
+
96
+ if (queryName === "workflow-preset-diff") {
97
+ if (!context.providerId) {
98
+ throw new Error("query workflow-preset-diff requires --provider <id>.");
99
+ }
100
+ return printJson(buildWorkflowPresetDiffPayload({
101
+ workspace: normalizeTopogramPath(context.inputPath),
102
+ providerId: context.providerId,
103
+ presetId: context.presetId
104
+ }));
105
+ }
106
+
107
+ if (queryName === "workflow-preset-customization" || context.commandArgs?.workflowPresetCommand === "customize") {
108
+ return runWorkflowPresetCustomization(context, queryName);
109
+ }
110
+
111
+ return null;
112
+ }
113
+
114
+ /**
115
+ * @param {AnyRecord} context
116
+ * @param {AnyRecord} selectors
117
+ * @returns {number}
118
+ */
119
+ function runSingleAgentPlan(context, selectors) {
120
+ if (!context.modeId) {
121
+ throw new Error("query single-agent-plan requires --mode <modeling|maintained-app-edit|import-adopt|diff-review|verification>.");
122
+ }
123
+ const ast = parsePath(context.inputPath);
124
+ const result = buildTaskMode(ast, selectors, context.modeId, context.fromTopogramPath);
125
+ if (!resultOk(result)) return printValidationFailure(result);
126
+ const sliceResult = hasSelectors(context) ? buildSlice(ast, selectors) : null;
127
+ if (sliceResult && !resultOk(sliceResult)) return printValidationFailure(sliceResult);
128
+ const resolved = resolveWorkspace(ast);
129
+ if (!resultOk(resolved)) return printValidationFailure(resolved);
130
+ const generatorTargets = generatorTargetsForWorkflowContext({
131
+ graph: resolved.graph,
132
+ taskModeArtifact: result.artifact,
133
+ sliceArtifact: artifactOrNull(sliceResult)
134
+ });
135
+ const topogramRoot = normalizeTopogramPath(context.inputPath);
136
+ let importPlan = null;
137
+ if (context.modeId === "import-adopt" && fs.existsSync(adoptionPlanPath(topogramRoot))) {
138
+ const workflowPresets = buildWorkflowPresetState({
139
+ workspace: topogramRoot,
140
+ selectors: workflowPresetSelectors(result.artifact, context.providerId, context.presetId, "single-agent-plan")
141
+ });
142
+ importPlan = buildImportPlanPayload(readJson(adoptionPlanPath(topogramRoot)), result.artifact, null, workflowPresets);
143
+ }
144
+ const resolvedWorkflowContext = buildResolvedWorkflowContextPayload({
145
+ workspace: topogramRoot,
146
+ taskModeArtifact: result.artifact,
147
+ generatorTargets,
148
+ selectors: workflowPresetSelectors(result.artifact, context.providerId, context.presetId, "single-agent-plan"),
149
+ importPlan
150
+ });
151
+ return printJson(buildSingleAgentPlanPayload({
152
+ workspace: topogramRoot,
153
+ taskModeArtifact: result.artifact,
154
+ importPlan,
155
+ resolvedWorkflowContext
156
+ }));
157
+ }
158
+
159
+ /**
160
+ * @param {AnyRecord} context
161
+ * @param {AnyRecord} selectors
162
+ * @returns {number}
163
+ */
164
+ function runResolvedWorkflowContext(context, selectors) {
165
+ if (!context.modeId) {
166
+ throw new Error("query resolved-workflow-context requires --mode <modeling|maintained-app-edit|import-adopt|diff-review|verification>.");
167
+ }
168
+ const topogramRoot = normalizeTopogramPath(context.inputPath);
169
+ const ast = parsePath(context.inputPath);
170
+ const taskModeResult = buildTaskMode(ast, selectors, context.modeId, context.fromTopogramPath);
171
+ if (!resultOk(taskModeResult)) return printValidationFailure(taskModeResult);
172
+ const resolved = resolveWorkspace(ast);
173
+ if (!resultOk(resolved)) return printValidationFailure(resolved);
174
+ const sliceResult = hasSelectors(context) ? buildSlice(ast, selectors) : null;
175
+ if (sliceResult && !resultOk(sliceResult)) return printValidationFailure(sliceResult);
176
+ const includeMaintainedBoundary =
177
+ context.modeId === "maintained-app-edit" ||
178
+ context.surfaceId === "maintained-boundary" ||
179
+ context.fromTopogramPath;
180
+ const maintainedBundleResult = includeMaintainedBoundary ? buildMaintainedBundle(ast) : null;
181
+ if (maintainedBundleResult && !resultOk(maintainedBundleResult)) return printValidationFailure(maintainedBundleResult);
182
+ const generatorTargets = generatorTargetsForWorkflowContext({
183
+ graph: resolved.graph,
184
+ taskModeArtifact: taskModeResult.artifact,
185
+ sliceArtifact: artifactOrNull(sliceResult),
186
+ maintainedBoundaryArtifact: maintainedBundleResult?.artifact?.maintained_boundary || null
187
+ });
188
+ let importPlan = null;
189
+ if (context.modeId === "import-adopt" && fs.existsSync(adoptionPlanPath(topogramRoot))) {
190
+ const workflowPresets = buildWorkflowPresetState({
191
+ workspace: topogramRoot,
192
+ selectors: workflowPresetSelectors(taskModeResult.artifact, context.providerId, context.presetId, "resolved-workflow-context")
193
+ });
194
+ importPlan = buildImportPlanPayload(
195
+ readJson(adoptionPlanPath(topogramRoot)),
196
+ taskModeResult.artifact,
197
+ maintainedBundleResult?.artifact?.maintained_boundary || null,
198
+ workflowPresets
199
+ );
200
+ }
201
+ return printJson(buildResolvedWorkflowContextPayload({
202
+ workspace: topogramRoot,
203
+ taskModeArtifact: taskModeResult.artifact,
204
+ importPlan,
205
+ reviewBoundary: sliceResult?.artifact?.review_boundary || null,
206
+ maintainedBoundary: maintainedBundleResult?.artifact?.maintained_boundary || null,
207
+ generatorTargets,
208
+ selectors: workflowPresetSelectors(taskModeResult.artifact, context.providerId, context.presetId, "resolved-workflow-context")
209
+ }));
210
+ }
211
+
212
+ /**
213
+ * @param {AnyRecord} context
214
+ * @param {string|undefined} queryName
215
+ * @returns {number}
216
+ */
217
+ function runWorkflowPresetCustomization(context, queryName) {
218
+ if (!context.providerId || !context.presetId) {
219
+ throw new Error(`${queryName ? "query workflow-preset-customization" : "workflow-preset customize"} requires --provider <id> and --preset <id>.`);
220
+ }
221
+ const topogramRoot = normalizeTopogramPath(context.inputPath);
222
+ const payload = buildWorkflowPresetCustomizationPayload({
223
+ workspace: topogramRoot,
224
+ providerId: context.providerId,
225
+ presetId: context.presetId
226
+ });
227
+ if (queryName === "workflow-preset-customization" || !context.shouldWrite) {
228
+ return printJson(payload);
229
+ }
230
+ const targetPath = path.resolve(topogramRoot, context.outPath || payload.recommended_local_path);
231
+ if (fs.existsSync(targetPath)) {
232
+ throw new Error(`Refusing to overwrite existing workflow preset customization at '${targetPath}'.`);
233
+ }
234
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
235
+ fs.writeFileSync(targetPath, `${stableStringify(payload.customization_template)}\n`);
236
+ return printJson({
237
+ ...payload,
238
+ written: true,
239
+ written_path: targetPath
240
+ });
241
+ }
@@ -0,0 +1,3 @@
1
+ // @ts-check
2
+
3
+ export { runQueryCommand } from "./runner/index.js";
@@ -0,0 +1,5 @@
1
+ // @ts-check
2
+
3
+ export { resolveRecommendedQueryFamily } from "./workspace.js";
4
+
5
+
@@ -0,0 +1,274 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ import { generateWorkspace } from "../../../generator.js";
7
+ import { formatValidationErrors } from "../../../validator.js";
8
+ import { buildChangePlanPayload } from "../../../agent-ops/query-builders.js";
9
+
10
+ /**
11
+ * @typedef {Record<string, any>} AnyRecord
12
+ */
13
+
14
+ /**
15
+ * @param {string} inputPath
16
+ * @returns {string}
17
+ */
18
+ export function normalizeTopogramPath(inputPath) {
19
+ const absolute = path.resolve(inputPath);
20
+ if (path.basename(absolute) === "topogram") {
21
+ return absolute;
22
+ }
23
+ const candidate = path.join(absolute, "topogram");
24
+ return fs.existsSync(candidate) ? candidate : absolute;
25
+ }
26
+
27
+ /**
28
+ * @param {AnyRecord} taskModeArtifact
29
+ * @param {string|null} providerId
30
+ * @param {string|null} presetId
31
+ * @param {string|null} queryFamily
32
+ * @returns {AnyRecord}
33
+ */
34
+ export function workflowPresetSelectors(taskModeArtifact, providerId = null, presetId = null, queryFamily = null) {
35
+ const categories = [];
36
+ if (taskModeArtifact?.mode === "import-adopt") categories.push("provider_adoption");
37
+ if (taskModeArtifact?.mode === "maintained-app-edit") categories.push("maintained_app");
38
+ if ((taskModeArtifact?.verification_targets?.maintained_app_checks || []).length > 0) categories.push("maintained_boundary");
39
+ return {
40
+ mode: taskModeArtifact?.mode || null,
41
+ task_class: taskModeArtifact?.mode || null,
42
+ provider_id: providerId,
43
+ preset_id: presetId,
44
+ query_family: queryFamily,
45
+ integration_categories: categories
46
+ };
47
+ }
48
+
49
+ /**
50
+ * @param {AnyRecord} options
51
+ * @returns {AnyRecord[]}
52
+ */
53
+ export function generatorTargetsForWorkflowContext(options = {}) {
54
+ const { graph, taskModeArtifact, sliceArtifact = null, diffArtifact = null, maintainedBoundaryArtifact = null } = options;
55
+ if (!graph || !taskModeArtifact) {
56
+ return [];
57
+ }
58
+ return buildChangePlanPayload({
59
+ graph,
60
+ taskModeArtifact,
61
+ sliceArtifact,
62
+ diffArtifact,
63
+ maintainedBoundaryArtifact
64
+ }).generator_targets || [];
65
+ }
66
+
67
+ /**
68
+ * @param {AnyRecord} options
69
+ * @returns {boolean}
70
+ */
71
+ export function importAdoptOnlyRequested(options = {}) {
72
+ return options.modeId === "import-adopt" && !(
73
+ options.capabilityId ||
74
+ options.workflowId ||
75
+ options.projectionId ||
76
+ options.componentId ||
77
+ options.entityId ||
78
+ options.journeyId ||
79
+ options.surfaceId ||
80
+ options.domainId ||
81
+ options.fromTopogramPath
82
+ );
83
+ }
84
+
85
+ /**
86
+ * @param {AnyRecord} result
87
+ * @returns {boolean}
88
+ */
89
+ export function resultOk(result) {
90
+ return Boolean(result?.ok);
91
+ }
92
+
93
+ /**
94
+ * @param {AnyRecord} result
95
+ * @returns {number}
96
+ */
97
+ export function printValidationFailure(result) {
98
+ console.error(formatValidationErrors(result.validation));
99
+ return 1;
100
+ }
101
+
102
+ /**
103
+ * @param {AnyRecord} ast
104
+ * @param {AnyRecord} selectors
105
+ * @param {string} modeId
106
+ * @param {string|null} fromTopogramPath
107
+ * @returns {AnyRecord}
108
+ */
109
+ export function buildTaskMode(ast, selectors, modeId, fromTopogramPath = null) {
110
+ return generateWorkspace(ast, {
111
+ target: "context-task-mode",
112
+ modeId,
113
+ ...selectors,
114
+ widgetId: selectors.componentId,
115
+ fromTopogramPath
116
+ });
117
+ }
118
+
119
+ /**
120
+ * @param {AnyRecord} ast
121
+ * @param {AnyRecord} selectors
122
+ * @returns {AnyRecord}
123
+ */
124
+ export function buildSlice(ast, selectors) {
125
+ return generateWorkspace(ast, {
126
+ target: "context-slice",
127
+ ...selectors,
128
+ widgetId: selectors.componentId
129
+ });
130
+ }
131
+
132
+ /**
133
+ * @param {AnyRecord} ast
134
+ * @returns {AnyRecord}
135
+ */
136
+ export function buildMaintainedBundle(ast) {
137
+ return generateWorkspace(ast, {
138
+ target: "context-bundle",
139
+ taskId: "maintained-app"
140
+ });
141
+ }
142
+
143
+ /**
144
+ * @param {AnyRecord} ast
145
+ * @param {string|null} fromTopogramPath
146
+ * @returns {AnyRecord|null}
147
+ */
148
+ export function buildDiff(ast, fromTopogramPath) {
149
+ return fromTopogramPath
150
+ ? generateWorkspace(ast, {
151
+ target: "context-diff",
152
+ fromTopogramPath
153
+ })
154
+ : null;
155
+ }
156
+
157
+ /**
158
+ * @param {AnyRecord|null} result
159
+ * @returns {AnyRecord|null}
160
+ */
161
+ export function artifactOrNull(result) {
162
+ return result?.artifact || null;
163
+ }
164
+
165
+ /**
166
+ * @param {string} topogramRoot
167
+ * @returns {string}
168
+ */
169
+ export function adoptionPlanPath(topogramRoot) {
170
+ return path.join(topogramRoot, "candidates", "reconcile", "adoption-plan.agent.json");
171
+ }
172
+
173
+ /**
174
+ * @param {string} topogramRoot
175
+ * @param {string} label
176
+ * @returns {{ reportPath: string, adoptionStatusPath: string, adoptionPlanPath: string }}
177
+ */
178
+ export function requireReconcileArtifacts(topogramRoot, label) {
179
+ const reportPath = path.join(topogramRoot, "candidates", "reconcile", "report.json");
180
+ const adoptionStatusPath = path.join(topogramRoot, "candidates", "reconcile", "adoption-status.json");
181
+ const planPath = adoptionPlanPath(topogramRoot);
182
+ if (!fs.existsSync(reportPath) || !fs.existsSync(adoptionStatusPath) || !fs.existsSync(planPath)) {
183
+ throw new Error(`No reconcile ${label} artifacts found under '${path.join(topogramRoot, "candidates", "reconcile")}'. Run 'node ./src/cli.js reconcile ${topogramRoot}' first.`);
184
+ }
185
+ return { reportPath, adoptionStatusPath, adoptionPlanPath: planPath };
186
+ }
187
+
188
+ /**
189
+ * @param {string} filePath
190
+ * @returns {AnyRecord}
191
+ */
192
+ export function readJson(filePath) {
193
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
194
+ }
195
+
196
+ /**
197
+ * @param {AnyRecord} options
198
+ * @returns {boolean}
199
+ */
200
+ export function hasSelectors(options) {
201
+ return Boolean(
202
+ options.capabilityId ||
203
+ options.workflowId ||
204
+ options.projectionId ||
205
+ options.componentId ||
206
+ options.entityId ||
207
+ options.journeyId ||
208
+ options.surfaceId ||
209
+ options.domainId
210
+ );
211
+ }
212
+
213
+ /**
214
+ * @param {AnyRecord} options
215
+ * @returns {boolean}
216
+ */
217
+ export function shouldUseImportAdoptPath(options) {
218
+ const selectorOrDiff = hasSelectors(options) || Boolean(options.fromTopogramPath);
219
+ return importAdoptOnlyRequested(options) || (!selectorOrDiff && !options.modeId);
220
+ }
221
+
222
+ /**
223
+ * @param {AnyRecord} options
224
+ * @returns {AnyRecord}
225
+ */
226
+ export function selectorOptions(options) {
227
+ return {
228
+ capabilityId: options.capabilityId,
229
+ workflowId: options.workflowId,
230
+ projectionId: options.projectionId,
231
+ componentId: options.componentId,
232
+ entityId: options.entityId,
233
+ journeyId: options.journeyId,
234
+ surfaceId: options.surfaceId,
235
+ domainId: options.domainId
236
+ };
237
+ }
238
+
239
+ /**
240
+ * @param {AnyRecord} nextAction
241
+ * @param {string|null} mode
242
+ * @returns {string}
243
+ */
244
+ export function resolveRecommendedQueryFamily(nextAction, mode) {
245
+ switch (nextAction?.kind) {
246
+ case "review_staged":
247
+ case "review_bundle":
248
+ case "inspect_review_group":
249
+ case "inspect_proposal_surface":
250
+ case "customize_workflow_preset":
251
+ case "refresh_workflow_preset_customization":
252
+ case "import_declared_workflow_preset":
253
+ return "import-plan";
254
+ case "review_diff_impact":
255
+ case "inspect_projection":
256
+ case "inspect_diff":
257
+ case "review_diff_boundaries":
258
+ return "change-plan";
259
+ case "inspect_maintained_impact":
260
+ case "inspect_boundary_before_edit":
261
+ case "run_maintained_checks":
262
+ return "maintained-boundary";
263
+ case "inspect_verification_targets":
264
+ return "verification-targets";
265
+ case "inspect_workspace_digest":
266
+ return "single-agent-plan";
267
+ default:
268
+ break;
269
+ }
270
+ if (mode === "import-adopt") return "import-plan";
271
+ if (mode === "maintained-app-edit") return "maintained-boundary";
272
+ if (mode === "verification") return "verification-targets";
273
+ return "change-plan";
274
+ }