@topogram/cli 0.3.64 → 0.3.66

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 (278) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +716 -0
  3. package/src/adoption/plan.js +12 -703
  4. package/src/adoption/reporting.js +1 -1
  5. package/src/agent-brief.js +7 -21
  6. package/src/agent-ops/query-builders/auth.js +375 -0
  7. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  8. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  9. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  10. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  11. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  12. package/src/agent-ops/query-builders/change-risk.js +25 -0
  13. package/src/agent-ops/query-builders/common.js +149 -0
  14. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  15. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  16. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  17. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  18. package/src/agent-ops/query-builders/work-packets.js +417 -0
  19. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  20. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  21. package/src/agent-ops/query-builders/workflow-presets-core.js +677 -0
  22. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  23. package/src/agent-ops/query-builders.d.ts +26 -26
  24. package/src/agent-ops/query-builders.js +42 -5021
  25. package/src/archive/jsonl.js +2 -2
  26. package/src/archive/resolver-bridge.js +1 -1
  27. package/src/archive/unarchive.js +2 -1
  28. package/src/catalog/constants.js +10 -0
  29. package/src/catalog/copy.js +65 -0
  30. package/src/catalog/diagnostics.js +15 -0
  31. package/src/catalog/entries.js +42 -0
  32. package/src/catalog/files.js +67 -0
  33. package/src/catalog/provenance.js +123 -0
  34. package/src/catalog/source.js +150 -0
  35. package/src/catalog/validation.js +252 -0
  36. package/src/catalog.d.ts +2 -0
  37. package/src/catalog.js +18 -746
  38. package/src/cli/command-parsers/project.js +3 -0
  39. package/src/cli/command-parsers/shared.js +1 -1
  40. package/src/cli/commands/agent.js +2 -2
  41. package/src/cli/commands/catalog/check.js +31 -0
  42. package/src/cli/commands/catalog/copy.js +59 -0
  43. package/src/cli/commands/catalog/doctor.js +248 -0
  44. package/src/cli/commands/catalog/help.js +21 -0
  45. package/src/cli/commands/catalog/list.js +52 -0
  46. package/src/cli/commands/catalog/runner.js +92 -0
  47. package/src/cli/commands/catalog/shared.js +17 -0
  48. package/src/cli/commands/catalog/show.js +134 -0
  49. package/src/cli/commands/catalog.js +30 -615
  50. package/src/cli/commands/check.js +3 -3
  51. package/src/cli/commands/doctor.js +2 -9
  52. package/src/cli/commands/generator-policy/package-info.js +162 -0
  53. package/src/cli/commands/generator-policy/payloads.js +372 -0
  54. package/src/cli/commands/generator-policy/printers.js +159 -0
  55. package/src/cli/commands/generator-policy/runner.js +81 -0
  56. package/src/cli/commands/generator-policy/shared.js +39 -0
  57. package/src/cli/commands/generator-policy.js +15 -783
  58. package/src/cli/commands/import/adopt.js +170 -0
  59. package/src/cli/commands/import/check.js +91 -0
  60. package/src/cli/commands/import/diff.js +84 -0
  61. package/src/cli/commands/import/help.js +47 -0
  62. package/src/cli/commands/import/paths.js +269 -0
  63. package/src/cli/commands/import/plan.js +292 -0
  64. package/src/cli/commands/import/refresh.js +471 -0
  65. package/src/cli/commands/import/status-history.js +196 -0
  66. package/src/cli/commands/import/workspace.js +233 -0
  67. package/src/cli/commands/import.js +33 -1732
  68. package/src/cli/commands/migrate.js +153 -0
  69. package/src/cli/commands/package/constants.js +17 -0
  70. package/src/cli/commands/package/doctor.js +240 -0
  71. package/src/cli/commands/package/help.js +27 -0
  72. package/src/cli/commands/package/lockfile.js +135 -0
  73. package/src/cli/commands/package/npm.js +97 -0
  74. package/src/cli/commands/package/reporting.js +35 -0
  75. package/src/cli/commands/package/runner.js +33 -0
  76. package/src/cli/commands/package/shared.js +9 -0
  77. package/src/cli/commands/package/update-cli.js +252 -0
  78. package/src/cli/commands/package/versions.js +35 -0
  79. package/src/cli/commands/package.js +29 -813
  80. package/src/cli/commands/query/change-plan.js +68 -0
  81. package/src/cli/commands/query/definitions.js +202 -0
  82. package/src/cli/commands/query/import-adopt.js +121 -0
  83. package/src/cli/commands/query/runner/artifacts.js +102 -0
  84. package/src/cli/commands/query/runner/boundaries.js +211 -0
  85. package/src/cli/commands/query/runner/change.js +182 -0
  86. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  87. package/src/cli/commands/query/runner/index.js +31 -0
  88. package/src/cli/commands/query/runner/output.js +12 -0
  89. package/src/cli/commands/query/runner/workflow.js +241 -0
  90. package/src/cli/commands/query/runner.js +3 -0
  91. package/src/cli/commands/query/workflow-context.js +5 -0
  92. package/src/cli/commands/query/workspace.js +270 -0
  93. package/src/cli/commands/query.js +9 -1300
  94. package/src/cli/commands/source.js +3 -12
  95. package/src/cli/commands/template/baseline.js +100 -0
  96. package/src/cli/commands/template/check.js +467 -0
  97. package/src/cli/commands/template/constants.js +8 -0
  98. package/src/cli/commands/template/diagnostics.js +26 -0
  99. package/src/cli/commands/template/help.js +28 -0
  100. package/src/cli/commands/template/lifecycle.js +404 -0
  101. package/src/cli/commands/template/list-show.js +287 -0
  102. package/src/cli/commands/template/policy.js +422 -0
  103. package/src/cli/commands/template/shared.js +127 -0
  104. package/src/cli/commands/template/updates.js +352 -0
  105. package/src/cli/commands/template-runner.js +6 -6
  106. package/src/cli/commands/template.js +41 -2143
  107. package/src/cli/commands/trust.js +1 -1
  108. package/src/cli/commands/workflow.js +6 -1
  109. package/src/cli/dispatcher.js +6 -1
  110. package/src/cli/help.js +15 -14
  111. package/src/cli/migration-guidance.js +1 -1
  112. package/src/cli/output-safety.js +2 -1
  113. package/src/cli/path-normalization.js +3 -13
  114. package/src/generator/api/contracts.js +497 -0
  115. package/src/generator/api/metadata.js +221 -0
  116. package/src/generator/api/openapi.js +559 -0
  117. package/src/generator/api/schema.js +124 -0
  118. package/src/generator/api/types.d.ts +98 -0
  119. package/src/generator/api.js +3 -1195
  120. package/src/generator/context/domain-page.js +1 -1
  121. package/src/generator/context/shared/domain-sdlc.js +282 -0
  122. package/src/generator/context/shared/maintained-boundary.js +665 -0
  123. package/src/generator/context/shared/metrics.js +85 -0
  124. package/src/generator/context/shared/primitives.js +64 -0
  125. package/src/generator/context/shared/relationships.js +453 -0
  126. package/src/generator/context/shared/summaries.js +263 -0
  127. package/src/generator/context/shared/types.d.ts +207 -0
  128. package/src/generator/context/shared.d.ts +42 -0
  129. package/src/generator/context/shared.js +80 -1390
  130. package/src/generator/context/slice/core.js +397 -0
  131. package/src/generator/context/slice/sdlc.js +417 -0
  132. package/src/generator/context/slice/ui-packets.js +183 -0
  133. package/src/generator/context/slice.js +2 -859
  134. package/src/generator/context/task-mode.js +2 -2
  135. package/src/generator/registry/index.js +507 -0
  136. package/src/generator/registry.js +18 -504
  137. package/src/generator/runtime/environment/index.js +666 -0
  138. package/src/generator/runtime/environment.js +4 -666
  139. package/src/generator/runtime/runtime-check/index.js +554 -0
  140. package/src/generator/runtime/runtime-check.js +4 -554
  141. package/src/generator/runtime/shared/index.js +572 -0
  142. package/src/generator/runtime/shared.js +19 -570
  143. package/src/generator/sdlc/doc-page.js +1 -1
  144. package/src/generator/shared.d.ts +2 -0
  145. package/src/generator/surfaces/databases/lifecycle-shared.js +1 -1
  146. package/src/generator/surfaces/native/swiftui-templates/README.generated.md +1 -1
  147. package/src/generator/surfaces/shared.d.ts +3 -0
  148. package/src/generator/widget-conformance/behavior-report.js +258 -0
  149. package/src/generator/widget-conformance/checks.js +371 -0
  150. package/src/generator/widget-conformance/projection-context.js +200 -0
  151. package/src/generator/widget-conformance/report.js +166 -0
  152. package/src/generator/widget-conformance/types.d.ts +121 -0
  153. package/src/generator/widget-conformance.js +3 -824
  154. package/src/import/core/context.d.ts +3 -0
  155. package/src/import/core/context.js +5 -7
  156. package/src/import/core/contracts.d.ts +1 -0
  157. package/src/import/core/registry.d.ts +4 -0
  158. package/src/import/core/runner/candidates.js +337 -0
  159. package/src/import/core/runner/options.js +22 -0
  160. package/src/import/core/runner/reports.js +51 -0
  161. package/src/import/core/runner/run.js +79 -0
  162. package/src/import/core/runner/tracks.js +150 -0
  163. package/src/import/core/runner/ui-drafts.js +393 -0
  164. package/src/import/core/runner.js +3 -698
  165. package/src/import/core/shared/api-routes.js +221 -0
  166. package/src/import/core/shared/candidates.js +97 -0
  167. package/src/import/core/shared/files.js +177 -0
  168. package/src/import/core/shared/next-app.js +389 -0
  169. package/src/import/core/shared/types.d.ts +51 -0
  170. package/src/import/core/shared/ui-routes.js +230 -0
  171. package/src/import/core/shared.js +60 -861
  172. package/src/new-project/constants.js +128 -0
  173. package/src/new-project/create.js +90 -0
  174. package/src/new-project/json.js +28 -0
  175. package/src/new-project/metadata.js +96 -0
  176. package/src/new-project/package-spec.js +161 -0
  177. package/src/new-project/project-files.js +351 -0
  178. package/src/new-project/template-policy.js +269 -0
  179. package/src/new-project/template-resolution.js +370 -0
  180. package/src/new-project/template-snapshots.js +442 -0
  181. package/src/new-project/template-updates.js +512 -0
  182. package/src/new-project/types.d.ts +83 -0
  183. package/src/new-project.js +6 -2277
  184. package/src/parser.d.ts +87 -1
  185. package/src/parser.js +118 -0
  186. package/src/policy/review-boundaries.d.ts +15 -0
  187. package/src/project-config/index.js +591 -0
  188. package/src/project-config.js +19 -561
  189. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  190. package/src/resolver/enrich/bug.js +2 -0
  191. package/src/resolver/enrich/pitch.js +2 -0
  192. package/src/resolver/enrich/requirement.js +2 -0
  193. package/src/resolver/enrich/task.js +2 -0
  194. package/src/resolver/index.js +19 -2089
  195. package/src/resolver/normalize.js +384 -1
  196. package/src/resolver/plans.js +168 -0
  197. package/src/resolver/projections-api.js +494 -0
  198. package/src/resolver/projections-db.js +133 -0
  199. package/src/resolver/projections-ui.js +317 -0
  200. package/src/resolver/shapes.js +251 -0
  201. package/src/resolver/shared.js +278 -0
  202. package/src/resolver/widgets.js +132 -0
  203. package/src/sdlc/adopt.js +6 -5
  204. package/src/sdlc/paths.js +3 -5
  205. package/src/sdlc/scaffold.js +2 -1
  206. package/src/template-trust/constants.js +62 -0
  207. package/src/template-trust/content.js +258 -0
  208. package/src/template-trust/diff.js +92 -0
  209. package/src/template-trust/policy.js +61 -0
  210. package/src/template-trust/record.js +90 -0
  211. package/src/template-trust/status.js +182 -0
  212. package/src/template-trust.js +24 -687
  213. package/src/text-helpers.d.ts +1 -0
  214. package/src/topogram-types.d.ts +69 -0
  215. package/src/validator/common.js +488 -0
  216. package/src/validator/data-model.js +237 -0
  217. package/src/validator/docs.js +167 -0
  218. package/src/validator/expressions.js +146 -1
  219. package/src/validator/index.d.ts +23 -0
  220. package/src/validator/index.js +32 -3585
  221. package/src/validator/kinds.d.ts +41 -0
  222. package/src/validator/kinds.js +2 -0
  223. package/src/validator/model-helpers.js +46 -0
  224. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  225. package/src/validator/per-kind/bug.js +6 -0
  226. package/src/validator/per-kind/domain.js +15 -2
  227. package/src/validator/per-kind/pitch.js +7 -0
  228. package/src/validator/per-kind/requirement.js +5 -0
  229. package/src/validator/per-kind/task.js +7 -0
  230. package/src/validator/per-kind/widget.js +14 -0
  231. package/src/validator/projections/api-http-async.js +410 -0
  232. package/src/validator/projections/api-http-authz.js +88 -0
  233. package/src/validator/projections/api-http-core.js +205 -0
  234. package/src/validator/projections/api-http-policies.js +339 -0
  235. package/src/validator/projections/api-http-responses.js +233 -0
  236. package/src/validator/projections/api-http.js +44 -0
  237. package/src/validator/projections/db.js +353 -0
  238. package/src/validator/projections/generator-defaults.js +45 -0
  239. package/src/validator/projections/helpers.js +87 -0
  240. package/src/validator/projections/ui-helpers.js +214 -0
  241. package/src/validator/projections/ui-navigation.js +344 -0
  242. package/src/validator/projections/ui-structure.js +364 -0
  243. package/src/validator/projections/ui-widgets.js +493 -0
  244. package/src/validator/projections/ui.js +46 -0
  245. package/src/validator/registry.js +48 -1
  246. package/src/validator/utils.d.ts +20 -0
  247. package/src/validator/utils.js +115 -12
  248. package/src/widget-behavior.d.ts +1 -0
  249. package/src/workflows/import-app/api/collect.js +221 -0
  250. package/src/workflows/import-app/api/openapi.js +257 -0
  251. package/src/workflows/import-app/api/routes.js +327 -0
  252. package/src/workflows/import-app/api/sources.js +22 -0
  253. package/src/workflows/import-app/api.js +2 -797
  254. package/src/workflows/reconcile/adoption-plan/build.js +212 -0
  255. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  256. package/src/workflows/reconcile/adoption-plan/outputs.js +153 -0
  257. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  258. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  259. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  260. package/src/workflows/reconcile/adoption-plan.js +30 -740
  261. package/src/workflows/reconcile/auth/closures.js +115 -0
  262. package/src/workflows/reconcile/auth/formatters.js +142 -0
  263. package/src/workflows/reconcile/auth/inference.js +330 -0
  264. package/src/workflows/reconcile/auth/roles.js +122 -0
  265. package/src/workflows/reconcile/auth.js +35 -690
  266. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  267. package/src/workflows/reconcile/bundle-core.js +12 -598
  268. package/src/workflows/reconcile/candidate-model.js +18 -2
  269. package/src/workflows/reconcile/canonical-surface.js +1 -1
  270. package/src/workflows/reconcile/impacts/adoption-plan.js +196 -0
  271. package/src/workflows/reconcile/impacts/indexes.js +105 -0
  272. package/src/workflows/reconcile/impacts/patches.js +252 -0
  273. package/src/workflows/reconcile/impacts/reports.js +80 -0
  274. package/src/workflows/reconcile/impacts.js +14 -623
  275. package/src/workflows/reconcile/renderers.js +41 -6
  276. package/src/workflows/shared.js +5 -11
  277. package/src/workspace-docs.d.ts +29 -0
  278. package/src/workspace-paths.js +328 -0
@@ -0,0 +1,233 @@
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 {
8
+ collectImportSourceFileRecords,
9
+ TOPOGRAM_IMPORT_FILE,
10
+ writeTopogramImportRecord
11
+ } from "../../../import/provenance.js";
12
+ import { runWorkflow } from "../../../workflows.js";
13
+ import { DEFAULT_TOPO_FOLDER_NAME, DEFAULT_WORKSPACE_PATH } from "../../../workspace-paths.js";
14
+ import { shellCommandArg } from "../catalog.js";
15
+
16
+ /**
17
+ * @typedef {Record<string, any>} AnyRecord
18
+ */
19
+
20
+ /**
21
+ * @param {string} targetPath
22
+ * @returns {void}
23
+ */
24
+ export function ensureEmptyImportTarget(targetPath) {
25
+ if (!fs.existsSync(targetPath)) {
26
+ fs.mkdirSync(targetPath, { recursive: true });
27
+ return;
28
+ }
29
+ if (!fs.statSync(targetPath).isDirectory()) {
30
+ throw new Error(`Cannot import into non-directory path '${targetPath}'.`);
31
+ }
32
+ const entries = fs.readdirSync(targetPath).filter((/** @type {string} */ entry) => entry !== ".DS_Store");
33
+ if (entries.length > 0) {
34
+ throw new Error(`Refusing to import into non-empty directory '${targetPath}'.`);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * @param {string} outDir
40
+ * @param {Record<string, any>} files
41
+ * @returns {string[]}
42
+ */
43
+ export function writeRelativeFiles(outDir, files) {
44
+ const written = [];
45
+ for (const [relativePath, contents] of Object.entries(files || {})) {
46
+ const normalizedRelativePath = relativePath.replaceAll(path.sep, "/");
47
+ const destination = path.join(outDir, normalizedRelativePath);
48
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
49
+ fs.writeFileSync(destination, typeof contents === "string" ? contents : `${stableStringify(contents)}\n`, "utf8");
50
+ written.push(normalizedRelativePath);
51
+ }
52
+ return written.sort((a, b) => a.localeCompare(b));
53
+ }
54
+
55
+ /**
56
+ * @returns {Record<string, any>}
57
+ */
58
+ function importedProjectConfig() {
59
+ return {
60
+ version: "0.1",
61
+ workspace: DEFAULT_WORKSPACE_PATH,
62
+ outputs: {
63
+ maintained_app: {
64
+ path: "./app",
65
+ ownership: "maintained"
66
+ }
67
+ },
68
+ topology: {
69
+ runtimes: []
70
+ }
71
+ };
72
+ }
73
+
74
+ /**
75
+ * @param {string} sourceRoot
76
+ * @param {string} targetRoot
77
+ * @param {ReturnType<typeof runWorkflow>["summary"]} importSummary
78
+ * @returns {string}
79
+ */
80
+ function importedWorkspaceReadme(sourceRoot, targetRoot, importSummary) {
81
+ return [
82
+ "# Imported Topogram Workspace",
83
+ "",
84
+ "This workspace was created from a brownfield app import.",
85
+ "",
86
+ `- Imported source: \`${sourceRoot}\``,
87
+ `- Target workspace: \`${targetRoot}\``,
88
+ `- Tracks: ${(importSummary.tracks || []).join(", ") || "none"}`,
89
+ `- Provenance: \`${TOPOGRAM_IMPORT_FILE}\``,
90
+ "",
91
+ "Imported Topogram artifacts are project-owned after creation. Edit them directly, promote candidates deliberately, and run `topogram check` before generation or maintained-app work.",
92
+ "",
93
+ "Useful commands:",
94
+ "",
95
+ "```sh",
96
+ "topogram import check",
97
+ "topogram check",
98
+ `topogram query import-plan ./${DEFAULT_TOPO_FOLDER_NAME}`,
99
+ "```",
100
+ ""
101
+ ].join("\n");
102
+ }
103
+
104
+ /**
105
+ * @param {Record<string, any>} summary
106
+ * @returns {Record<string, number>}
107
+ */
108
+ export function importCandidateCounts(summary) {
109
+ const candidates = summary.candidates || {};
110
+ return {
111
+ dbEntities: candidates.db?.entities?.length || 0,
112
+ dbEnums: candidates.db?.enums?.length || 0,
113
+ apiCapabilities: candidates.api?.capabilities?.length || 0,
114
+ apiRoutes: candidates.api?.routes?.length || 0,
115
+ uiScreens: candidates.ui?.screens?.length || 0,
116
+ uiRoutes: candidates.ui?.routes?.length || 0,
117
+ uiWidgets: candidates.ui?.widgets?.length || candidates.ui?.components?.length || 0,
118
+ uiShapes: candidates.ui?.shapes?.length || 0,
119
+ workflows: candidates.workflows?.workflows?.length || 0,
120
+ verifications: candidates.verification?.verifications?.length || 0
121
+ };
122
+ }
123
+
124
+ /**
125
+ * @param {string} rootPath
126
+ * @returns {number}
127
+ */
128
+ export function countFilesRecursive(rootPath) {
129
+ if (!fs.existsSync(rootPath)) {
130
+ return 0;
131
+ }
132
+ let count = 0;
133
+ for (const entry of fs.readdirSync(rootPath, { withFileTypes: true })) {
134
+ const childPath = path.join(rootPath, entry.name);
135
+ if (entry.isDirectory()) {
136
+ count += countFilesRecursive(childPath);
137
+ } else if (entry.isFile()) {
138
+ count += 1;
139
+ }
140
+ }
141
+ return count;
142
+ }
143
+
144
+ /**
145
+ * @param {string} sourcePath
146
+ * @param {string} targetPath
147
+ * @param {{ from?: string|null }} [options]
148
+ * @returns {{ ok: boolean, sourcePath: string, targetPath: string, topogramRoot: string, projectConfigPath: string, provenancePath: string, tracks: string[], sourceFiles: number, rawCandidateFiles: number, reconcileFiles: number, writtenFiles: string[], candidateCounts: Record<string, number>, nextCommands: string[] }}
149
+ */
150
+ export function buildBrownfieldImportWorkspacePayload(sourcePath, targetPath, options = {}) {
151
+ const sourceRoot = path.resolve(sourcePath);
152
+ const targetRoot = path.resolve(targetPath);
153
+ if (!fs.existsSync(sourceRoot) || !fs.statSync(sourceRoot).isDirectory()) {
154
+ throw new Error(`Cannot import missing app directory '${sourcePath}'.`);
155
+ }
156
+ if (sourceRoot === targetRoot) {
157
+ throw new Error("Refusing to import into the same directory as the brownfield app.");
158
+ }
159
+ ensureEmptyImportTarget(targetRoot);
160
+
161
+ const topogramRoot = path.join(targetRoot, DEFAULT_TOPO_FOLDER_NAME);
162
+ fs.mkdirSync(topogramRoot, { recursive: true });
163
+ const sourceFiles = collectImportSourceFileRecords(sourceRoot, { excludeRoots: [targetRoot] });
164
+ const importResult = runWorkflow("import-app", sourceRoot, { from: options.from || null });
165
+ const rawCandidateFiles = writeRelativeFiles(topogramRoot, importResult.files || {});
166
+
167
+ const projectConfigPath = path.join(targetRoot, "topogram.project.json");
168
+ fs.writeFileSync(projectConfigPath, `${stableStringify(importedProjectConfig())}\n`, "utf8");
169
+ fs.writeFileSync(path.join(targetRoot, "README.md"), importedWorkspaceReadme(sourceRoot, targetRoot, importResult.summary), "utf8");
170
+
171
+ const reconcileResult = runWorkflow("reconcile", targetRoot, {});
172
+ const reconcileFiles = writeRelativeFiles(topogramRoot, reconcileResult.files || {});
173
+ const candidateCounts = importCandidateCounts(importResult.summary);
174
+ const provenance = writeTopogramImportRecord(targetRoot, {
175
+ sourceRoot,
176
+ ignoredRoots: [targetRoot],
177
+ tracks: importResult.summary.tracks || [],
178
+ findingsCount: importResult.summary.findings_count || 0,
179
+ candidateCounts,
180
+ files: sourceFiles
181
+ });
182
+ const writtenFiles = [
183
+ "README.md",
184
+ "topogram.project.json",
185
+ TOPOGRAM_IMPORT_FILE,
186
+ ...rawCandidateFiles.map((filePath) => `${DEFAULT_TOPO_FOLDER_NAME}/${filePath}`),
187
+ ...reconcileFiles.map((filePath) => `${DEFAULT_TOPO_FOLDER_NAME}/${filePath}`)
188
+ ].sort((a, b) => a.localeCompare(b));
189
+ return {
190
+ ok: true,
191
+ sourcePath: sourceRoot,
192
+ targetPath: targetRoot,
193
+ topogramRoot,
194
+ projectConfigPath,
195
+ provenancePath: provenance.path,
196
+ tracks: importResult.summary.tracks || [],
197
+ sourceFiles: sourceFiles.length,
198
+ rawCandidateFiles: rawCandidateFiles.length,
199
+ reconcileFiles: reconcileFiles.length,
200
+ writtenFiles,
201
+ candidateCounts,
202
+ nextCommands: [
203
+ "topogram import check",
204
+ "topogram import plan",
205
+ "topogram import adopt bundle:task --dry-run",
206
+ "topogram import status",
207
+ "topogram check",
208
+ `topogram query import-plan ./${DEFAULT_TOPO_FOLDER_NAME}`
209
+ ]
210
+ };
211
+ }
212
+
213
+ /**
214
+ * @param {ReturnType<typeof buildBrownfieldImportWorkspacePayload>} payload
215
+ * @returns {void}
216
+ */
217
+ export function printBrownfieldImportWorkspace(payload) {
218
+ console.log(`Imported brownfield app to ${payload.targetPath}.`);
219
+ console.log(`Source: ${payload.sourcePath}`);
220
+ console.log(`Topogram: ${payload.topogramRoot}`);
221
+ console.log(`Project config: ${payload.projectConfigPath}`);
222
+ console.log(`Import provenance: ${payload.provenancePath}`);
223
+ console.log(`Tracked source files: ${payload.sourceFiles}`);
224
+ console.log(`Raw candidate files: ${payload.rawCandidateFiles}`);
225
+ console.log(`Reconcile proposal files: ${payload.reconcileFiles}`);
226
+ console.log("Imported Topogram artifacts are project-owned after creation; source hashes record the app evidence trusted at import time.");
227
+ console.log("");
228
+ console.log("Next steps:");
229
+ console.log(` cd ${shellCommandArg(path.relative(process.cwd(), payload.targetPath) || ".")}`);
230
+ for (const command of payload.nextCommands) {
231
+ console.log(` ${command}`);
232
+ }
233
+ }