@topogram/cli 0.3.62 → 0.3.64

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 (121) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan.d.ts +6 -0
  3. package/src/adoption/reporting.d.ts +10 -0
  4. package/src/adoption/review-groups.d.ts +6 -0
  5. package/src/agent-brief.d.ts +3 -0
  6. package/src/agent-brief.js +495 -0
  7. package/src/agent-ops/query-builders.d.ts +26 -0
  8. package/src/archive/archive.d.ts +2 -0
  9. package/src/archive/compact.d.ts +1 -0
  10. package/src/archive/unarchive.d.ts +1 -0
  11. package/src/catalog.d.ts +10 -0
  12. package/src/catalog.js +62 -66
  13. package/src/cli/catalog-alias.d.ts +1 -0
  14. package/src/cli/command-parser.js +38 -0
  15. package/src/cli/command-parsers/core.js +102 -0
  16. package/src/cli/command-parsers/generator.js +39 -0
  17. package/src/cli/command-parsers/import.js +44 -0
  18. package/src/cli/command-parsers/legacy-workflow.js +21 -0
  19. package/src/cli/command-parsers/project.js +47 -0
  20. package/src/cli/command-parsers/sdlc.js +47 -0
  21. package/src/cli/command-parsers/shared.js +51 -0
  22. package/src/cli/command-parsers/template.js +48 -0
  23. package/src/cli/commands/agent.js +47 -0
  24. package/src/cli/commands/catalog.js +617 -0
  25. package/src/cli/commands/check.js +268 -0
  26. package/src/cli/commands/doctor.js +268 -0
  27. package/src/cli/commands/emit.js +149 -0
  28. package/src/cli/commands/generate.js +96 -0
  29. package/src/cli/commands/generator-policy.js +785 -0
  30. package/src/cli/commands/generator.js +443 -0
  31. package/src/cli/commands/import-runner.js +157 -0
  32. package/src/cli/commands/import.js +1734 -0
  33. package/src/cli/commands/inspect.js +55 -0
  34. package/src/cli/commands/new.js +94 -0
  35. package/src/cli/commands/package.js +815 -0
  36. package/src/cli/commands/query.js +1302 -0
  37. package/src/cli/commands/release-rollout.js +257 -0
  38. package/src/cli/commands/release-shared.js +528 -0
  39. package/src/cli/commands/release-status.js +429 -0
  40. package/src/cli/commands/release.js +107 -0
  41. package/src/cli/commands/sdlc.js +168 -0
  42. package/src/cli/commands/setup.js +76 -0
  43. package/src/cli/commands/source.js +291 -0
  44. package/src/cli/commands/template-runner.js +198 -0
  45. package/src/cli/commands/template.js +2145 -0
  46. package/src/cli/commands/trust.js +219 -0
  47. package/src/cli/commands/version.js +40 -0
  48. package/src/cli/commands/widget.js +168 -0
  49. package/src/cli/commands/workflow.js +63 -0
  50. package/src/cli/dispatcher.js +392 -0
  51. package/src/cli/help-dispatch.js +188 -0
  52. package/src/cli/help.js +296 -0
  53. package/src/cli/migration-guidance.js +59 -0
  54. package/src/cli/options.js +96 -0
  55. package/src/cli/output-safety.js +107 -0
  56. package/src/cli/path-normalization.js +29 -0
  57. package/src/cli.js +47 -11711
  58. package/src/example-implementation.d.ts +2 -0
  59. package/src/format.d.ts +1 -0
  60. package/src/generator/check.d.ts +1 -0
  61. package/src/generator/context/bundle.d.ts +1 -0
  62. package/src/generator/context/shared.d.ts +2 -0
  63. package/src/generator/native/parity-bundle.js +2 -1
  64. package/src/generator/surfaces/web/html-escape.js +22 -0
  65. package/src/generator/surfaces/web/react.js +10 -8
  66. package/src/generator/surfaces/web/sveltekit.js +7 -5
  67. package/src/generator/surfaces/web/vanilla.js +8 -4
  68. package/src/generator.d.ts +2 -0
  69. package/src/github-client.js +520 -0
  70. package/src/import/core/shared.js +20 -62
  71. package/src/import/extractors/api/flutter-dio.js +4 -8
  72. package/src/import/extractors/api/react-native-repository.js +4 -8
  73. package/src/import/index.d.ts +4 -0
  74. package/src/import/provenance.d.ts +4 -0
  75. package/src/new-project.js +100 -11
  76. package/src/npm-safety.js +79 -0
  77. package/src/parser.d.ts +1 -0
  78. package/src/path-helpers.d.ts +1 -0
  79. package/src/path-helpers.js +20 -0
  80. package/src/project-config.js +1 -0
  81. package/src/reconcile/docs.d.ts +8 -0
  82. package/src/reconcile/journeys.d.ts +1 -0
  83. package/src/resolver.d.ts +1 -0
  84. package/src/runtime-support.js +29 -0
  85. package/src/sdlc/adopt.d.ts +1 -0
  86. package/src/sdlc/check.d.ts +1 -0
  87. package/src/sdlc/explain.d.ts +1 -0
  88. package/src/sdlc/release.d.ts +1 -0
  89. package/src/sdlc/scaffold.d.ts +1 -0
  90. package/src/sdlc/transition.d.ts +1 -0
  91. package/src/text-helpers.d.ts +6 -0
  92. package/src/text-helpers.js +245 -0
  93. package/src/topogram-config.js +306 -0
  94. package/src/validator.d.ts +2 -0
  95. package/src/workflows/adoption/index.js +26 -0
  96. package/src/workflows/docs-generate.js +262 -0
  97. package/src/workflows/docs-scan.js +703 -0
  98. package/src/workflows/docs.js +15 -0
  99. package/src/workflows/import-app/api.js +799 -0
  100. package/src/workflows/import-app/db.js +538 -0
  101. package/src/workflows/import-app/index.js +30 -0
  102. package/src/workflows/import-app/shared.js +218 -0
  103. package/src/workflows/import-app/ui.js +443 -0
  104. package/src/workflows/import-app/workflow.js +159 -0
  105. package/src/workflows/reconcile/adoption-plan.js +742 -0
  106. package/src/workflows/reconcile/auth.js +692 -0
  107. package/src/workflows/reconcile/bundle-core.js +600 -0
  108. package/src/workflows/reconcile/bundle-shared.js +75 -0
  109. package/src/workflows/reconcile/candidate-model.js +477 -0
  110. package/src/workflows/reconcile/canonical-surface.js +264 -0
  111. package/src/workflows/reconcile/gap-report.js +333 -0
  112. package/src/workflows/reconcile/ids.js +6 -0
  113. package/src/workflows/reconcile/impacts.js +625 -0
  114. package/src/workflows/reconcile/index.js +7 -0
  115. package/src/workflows/reconcile/renderers.js +461 -0
  116. package/src/workflows/reconcile/summary.js +90 -0
  117. package/src/workflows/reconcile/workflow.js +309 -0
  118. package/src/workflows/shared.js +189 -0
  119. package/src/workflows/types.d.ts +93 -0
  120. package/src/workflows.d.ts +1 -0
  121. package/src/workflows.js +10 -7652
@@ -0,0 +1,257 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ import {
7
+ buildPackageUpdateCliPayload,
8
+ CLI_PACKAGE_NAME,
9
+ isPackageVersion,
10
+ latestTopogramCliVersion
11
+ } from "./package.js";
12
+ import {
13
+ commandDiagnostic,
14
+ currentGitHead,
15
+ discoverTopogramCliVersionConsumers,
16
+ expectedConsumerWorkflowName,
17
+ hasStagedGitChanges,
18
+ inspectConsumerCi,
19
+ inspectGitWorktreeClean,
20
+ messageFromError,
21
+ runGit,
22
+ waitForConsumerCi
23
+ } from "./release-shared.js";
24
+
25
+ /**
26
+ * @typedef {Record<string, any>} AnyRecord
27
+ */
28
+
29
+ /**
30
+ * @param {string} requested
31
+ * @param {{ cwd?: string, push?: boolean, watch?: boolean }} [options]
32
+ * @returns {{ ok: boolean, packageName: string, requestedVersion: string, requestedLatest: boolean, pushed: boolean, watched: boolean, consumers: Array<AnyRecord>, diagnostics: Array<AnyRecord>, errors: string[] }}
33
+ */
34
+ export function buildReleaseRollConsumersPayload(requested, options = {}) {
35
+ const cwd = options.cwd || process.cwd();
36
+ const push = options.push !== false;
37
+ const watch = Boolean(options.watch);
38
+ const requestedLatest = requested === "latest" || requested === "--latest";
39
+ /** @type {Array<AnyRecord>} */
40
+ const diagnostics = [];
41
+ if (watch && !push) {
42
+ diagnostics.push({
43
+ code: "release_roll_watch_requires_push",
44
+ severity: "error",
45
+ message: "`topogram release roll-consumers --watch` requires pushing consumer commits.",
46
+ path: "release roll-consumers",
47
+ suggestedFix: "Remove --no-push or run without --watch and verify consumer CI separately."
48
+ });
49
+ return {
50
+ ok: false,
51
+ packageName: CLI_PACKAGE_NAME,
52
+ requestedVersion: requestedLatest ? "latest" : requested,
53
+ requestedLatest,
54
+ pushed: push,
55
+ watched: watch,
56
+ consumers: [],
57
+ diagnostics,
58
+ errors: diagnostics.map((diagnostic) => diagnostic.message)
59
+ };
60
+ }
61
+ const version = requestedLatest
62
+ ? latestTopogramCliVersion(cwd)
63
+ : requested;
64
+ if (!isPackageVersion(version)) {
65
+ throw new Error("topogram release roll-consumers requires <version> or --latest.");
66
+ }
67
+ /** @type {Array<AnyRecord>} */
68
+ const consumers = [];
69
+ for (const consumer of discoverTopogramCliVersionConsumers(cwd)) {
70
+ const workflow = expectedConsumerWorkflowName(consumer.name);
71
+ /** @type {AnyRecord} */
72
+ const item = {
73
+ name: consumer.name,
74
+ root: consumer.root,
75
+ workflow,
76
+ updated: false,
77
+ committed: false,
78
+ pushed: false,
79
+ commit: null,
80
+ update: null,
81
+ ci: null,
82
+ diagnostics: []
83
+ };
84
+ consumers.push(item);
85
+ if (!consumer.root || !fs.existsSync(consumer.root)) {
86
+ item.diagnostics.push({
87
+ code: "release_consumer_repo_missing",
88
+ severity: "error",
89
+ message: `First-party consumer repo ${consumer.name} was not found.`,
90
+ path: consumer.path,
91
+ suggestedFix: `Clone ${consumer.name} beside the topogram repo, then rerun roll-consumers.`
92
+ });
93
+ diagnostics.push(...item.diagnostics);
94
+ continue;
95
+ }
96
+ const packagePath = path.join(consumer.root, "package.json");
97
+ if (!fs.existsSync(packagePath)) {
98
+ item.diagnostics.push({
99
+ code: "release_consumer_package_missing",
100
+ severity: "error",
101
+ message: `First-party consumer repo ${consumer.name} does not contain package.json.`,
102
+ path: packagePath,
103
+ suggestedFix: "Only package-backed first-party consumers can be rolled by this command."
104
+ });
105
+ diagnostics.push(...item.diagnostics);
106
+ continue;
107
+ }
108
+ const clean = inspectGitWorktreeClean(consumer.root);
109
+ if (clean.ok !== true) {
110
+ item.diagnostics.push({
111
+ code: "release_consumer_worktree_dirty",
112
+ severity: "error",
113
+ message: clean.error || `First-party consumer repo ${consumer.name} has uncommitted changes.`,
114
+ path: consumer.root,
115
+ suggestedFix: "Commit, stash, or discard unrelated consumer changes before rolling the CLI version."
116
+ });
117
+ diagnostics.push(...item.diagnostics);
118
+ continue;
119
+ }
120
+ try {
121
+ item.update = buildPackageUpdateCliPayload(version, { cwd: consumer.root });
122
+ item.updated = true;
123
+ } catch (error) {
124
+ item.diagnostics.push({
125
+ code: "release_consumer_update_failed",
126
+ severity: "error",
127
+ message: `Failed to update ${consumer.name}: ${messageFromError(error)}`,
128
+ path: consumer.root,
129
+ suggestedFix: "Fix the consumer update/check failure, then rerun roll-consumers."
130
+ });
131
+ diagnostics.push(...item.diagnostics);
132
+ continue;
133
+ }
134
+ const filesToStage = ["package.json", "package-lock.json", "topogram-cli.version"]
135
+ .filter((file) => fs.existsSync(path.join(consumer.root || "", file)));
136
+ const addResult = runGit(["add", ...filesToStage], consumer.root);
137
+ if (addResult.status !== 0) {
138
+ item.diagnostics.push(commandDiagnostic({
139
+ code: "release_consumer_git_add_failed",
140
+ severity: "error",
141
+ message: `Failed to stage ${consumer.name} CLI update.`,
142
+ path: consumer.root,
143
+ suggestedFix: "Inspect git output, stage the changed files manually, then commit and push.",
144
+ result: addResult
145
+ }));
146
+ diagnostics.push(...item.diagnostics);
147
+ continue;
148
+ }
149
+ const staged = hasStagedGitChanges(consumer.root);
150
+ if (!staged.ok) {
151
+ item.diagnostics.push(commandDiagnostic({
152
+ code: "release_consumer_git_diff_failed",
153
+ severity: "error",
154
+ message: `Could not inspect staged changes for ${consumer.name}.`,
155
+ path: consumer.root,
156
+ suggestedFix: "Inspect git status manually before committing.",
157
+ result: staged.result
158
+ }));
159
+ diagnostics.push(...item.diagnostics);
160
+ continue;
161
+ }
162
+ if (!staged.changed) {
163
+ item.ci = watch
164
+ ? waitForConsumerCi(consumer)
165
+ : inspectConsumerCi(consumer, { strict: false });
166
+ item.diagnostics.push(...item.ci.diagnostics);
167
+ diagnostics.push(...item.ci.diagnostics);
168
+ continue;
169
+ }
170
+ const commitResult = runGit(["commit", "-m", `Update Topogram CLI to ${version}`], consumer.root);
171
+ if (commitResult.status !== 0) {
172
+ item.diagnostics.push(commandDiagnostic({
173
+ code: "release_consumer_git_commit_failed",
174
+ severity: "error",
175
+ message: `Failed to commit ${consumer.name} CLI update.`,
176
+ path: consumer.root,
177
+ suggestedFix: "Inspect git output, commit the consumer update manually, then push.",
178
+ result: commitResult
179
+ }));
180
+ diagnostics.push(...item.diagnostics);
181
+ continue;
182
+ }
183
+ item.committed = true;
184
+ item.commit = currentGitHead(consumer.root);
185
+ if (push) {
186
+ const pushResult = runGit(["push", "origin", "main"], consumer.root);
187
+ if (pushResult.status !== 0) {
188
+ item.diagnostics.push(commandDiagnostic({
189
+ code: "release_consumer_git_push_failed",
190
+ severity: "error",
191
+ message: `Failed to push ${consumer.name} CLI update.`,
192
+ path: consumer.root,
193
+ suggestedFix: "Push the consumer update manually, then confirm its verification workflow passes.",
194
+ result: pushResult
195
+ }));
196
+ diagnostics.push(...item.diagnostics);
197
+ continue;
198
+ }
199
+ item.pushed = true;
200
+ }
201
+ item.ci = watch
202
+ ? waitForConsumerCi(consumer)
203
+ : inspectConsumerCi(consumer, { strict: false });
204
+ item.diagnostics.push(...item.ci.diagnostics);
205
+ diagnostics.push(...item.ci.diagnostics);
206
+ }
207
+ const errors = diagnostics
208
+ .filter((diagnostic) => diagnostic.severity === "error")
209
+ .map((diagnostic) => diagnostic.message);
210
+ return {
211
+ ok: errors.length === 0,
212
+ packageName: CLI_PACKAGE_NAME,
213
+ requestedVersion: version,
214
+ requestedLatest,
215
+ pushed: push,
216
+ watched: watch,
217
+ consumers,
218
+ diagnostics,
219
+ errors
220
+ };
221
+ }
222
+
223
+ /**
224
+ * @param {ReturnType<typeof buildReleaseRollConsumersPayload>} payload
225
+ * @returns {void}
226
+ */
227
+ export function printReleaseRollConsumers(payload) {
228
+ console.log(payload.ok ? "Topogram consumer rollout completed." : "Topogram consumer rollout found issues.");
229
+ if (payload.requestedLatest) {
230
+ console.log(`Resolved latest version: ${payload.requestedVersion}`);
231
+ }
232
+ console.log(`Package: ${payload.packageName}@${payload.requestedVersion}`);
233
+ console.log(`Push: ${payload.pushed ? "enabled" : "disabled"}`);
234
+ console.log(`Watch: ${payload.watched ? "enabled" : "disabled"}`);
235
+ for (const consumer of payload.consumers) {
236
+ const state = consumer.committed
237
+ ? consumer.pushed ? "pushed" : "committed"
238
+ : consumer.updated ? "updated" : "skipped";
239
+ console.log(`- ${consumer.name}: ${state}`);
240
+ if (consumer.update) {
241
+ console.log(` Checks run: ${consumer.update.scriptsRun.join(", ") || "none"}`);
242
+ }
243
+ if (consumer.commit) {
244
+ console.log(` Commit: ${consumer.commit}`);
245
+ }
246
+ if (consumer.ci?.run?.url) {
247
+ const run = consumer.ci.run;
248
+ console.log(` CI: ${run.workflowName || consumer.workflow} ${run.status || "unknown"}/${run.conclusion || "unknown"} ${run.url}`);
249
+ } else if (consumer.workflow) {
250
+ console.log(` CI: ${consumer.workflow} not found`);
251
+ }
252
+ for (const diagnostic of consumer.diagnostics || []) {
253
+ const label = diagnostic.severity === "error" ? "Error" : diagnostic.severity === "warning" ? "Warning" : "Note";
254
+ console.log(` ${label}: ${diagnostic.message}`);
255
+ }
256
+ }
257
+ }