@topogram/cli 0.3.78 → 0.3.80

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 (100) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +2 -2
  3. package/src/agent-brief.js +29 -23
  4. package/src/agent-ops/query-builders/change-risk/{import-plan.js → extract-plan.js} +1 -1
  5. package/src/agent-ops/query-builders/change-risk/review-packets.js +5 -5
  6. package/src/agent-ops/query-builders/change-risk.js +1 -1
  7. package/src/agent-ops/query-builders/common.js +2 -2
  8. package/src/agent-ops/query-builders/multi-agent.js +1 -1
  9. package/src/agent-ops/query-builders/workflow-context-shared.js +4 -4
  10. package/src/catalog/provenance.js +1 -1
  11. package/src/cli/catalog-alias.d.ts +2 -0
  12. package/src/cli/catalog-alias.js +2 -2
  13. package/src/cli/command-parser.js +2 -0
  14. package/src/cli/command-parsers/core.js +9 -5
  15. package/src/cli/command-parsers/extractor.js +40 -0
  16. package/src/cli/command-parsers/import.js +11 -17
  17. package/src/cli/command-parsers/project.js +0 -3
  18. package/src/cli/commands/catalog/copy.js +3 -3
  19. package/src/cli/commands/catalog/help.js +1 -2
  20. package/src/cli/commands/catalog/list.js +7 -4
  21. package/src/cli/commands/catalog/show.js +4 -4
  22. package/src/cli/commands/copy.js +356 -0
  23. package/src/cli/commands/doctor.js +1 -1
  24. package/src/cli/commands/extractor.js +451 -0
  25. package/src/cli/commands/import/adopt.js +9 -9
  26. package/src/cli/commands/import/check.js +15 -15
  27. package/src/cli/commands/import/diff.js +6 -6
  28. package/src/cli/commands/import/help.js +45 -34
  29. package/src/cli/commands/import/paths.js +3 -3
  30. package/src/cli/commands/import/plan.js +8 -8
  31. package/src/cli/commands/import/refresh.js +25 -24
  32. package/src/cli/commands/import/status-history.js +4 -4
  33. package/src/cli/commands/import/workspace.js +24 -18
  34. package/src/cli/commands/import-runner.js +10 -7
  35. package/src/cli/commands/import.js +4 -1
  36. package/src/cli/commands/init.js +67 -0
  37. package/src/cli/commands/query/{import-adopt.js → extract-adopt.js} +2 -2
  38. package/src/cli/commands/query/runner/change.js +2 -2
  39. package/src/cli/commands/query/runner/{import-adopt.js → extract-adopt.js} +9 -9
  40. package/src/cli/commands/query/runner/index.js +1 -1
  41. package/src/cli/commands/query/runner/workflow.js +7 -7
  42. package/src/cli/commands/query/workspace.js +4 -4
  43. package/src/cli/commands/release-status.js +2 -2
  44. package/src/cli/commands/source.js +2 -2
  45. package/src/cli/commands/template/check.js +2 -2
  46. package/src/cli/commands/template/list-show.js +4 -4
  47. package/src/cli/dispatcher.js +32 -3
  48. package/src/cli/help-dispatch.js +33 -8
  49. package/src/cli/help.js +79 -52
  50. package/src/cli/migration-guidance.js +9 -0
  51. package/src/cli/options.js +17 -0
  52. package/src/extractor/check.js +155 -0
  53. package/src/extractor/packages.js +295 -0
  54. package/src/extractor/registry.js +196 -0
  55. package/src/extractor-policy.js +249 -0
  56. package/src/generator/check.js +24 -87
  57. package/src/generator/context/bundle.js +14 -7
  58. package/src/generator/context/diff.js +8 -1
  59. package/src/generator/context/digest.js +10 -1
  60. package/src/generator/context/shared/domain-sdlc.js +5 -1
  61. package/src/generator/context/shared/relationships.js +20 -5
  62. package/src/generator/context/shared/summaries.js +26 -0
  63. package/src/generator/context/shared.d.ts +1 -0
  64. package/src/generator/context/shared.js +1 -0
  65. package/src/generator/context/slice/core.js +9 -5
  66. package/src/generator/context/slice/sdlc.js +31 -2
  67. package/src/generator/context/task-mode.js +3 -3
  68. package/src/generator/registry/index.js +16 -75
  69. package/src/generator-policy.js +9 -57
  70. package/src/import/core/registry.d.ts +3 -0
  71. package/src/import/core/registry.js +82 -8
  72. package/src/import/core/runner/reports.js +4 -4
  73. package/src/import/core/runner/run.js +2 -0
  74. package/src/import/core/runner/tracks.js +66 -4
  75. package/src/import/provenance.js +18 -17
  76. package/src/init-project.js +215 -0
  77. package/src/new-project/constants.js +1 -1
  78. package/src/new-project/create.js +2 -2
  79. package/src/new-project/project-files.js +7 -7
  80. package/src/package-adapters/adapter.js +64 -0
  81. package/src/package-adapters/file-map.js +30 -0
  82. package/src/package-adapters/index.js +27 -0
  83. package/src/package-adapters/manifest.js +108 -0
  84. package/src/package-adapters/policy.js +81 -0
  85. package/src/package-adapters/spec.js +51 -0
  86. package/src/reconcile/journeys.js +8 -3
  87. package/src/record-blocks.js +125 -0
  88. package/src/resolver/index.js +3 -0
  89. package/src/resolver/journeys.js +74 -0
  90. package/src/resolver/normalize.js +25 -0
  91. package/src/sdlc/adopt.js +1 -1
  92. package/src/validator/common.js +34 -1
  93. package/src/validator/index.js +4 -0
  94. package/src/validator/kinds.d.ts +2 -0
  95. package/src/validator/kinds.js +34 -1
  96. package/src/validator/per-kind/journey.js +233 -0
  97. package/src/workflows/docs-generate.js +4 -1
  98. package/src/workflows/reconcile/bundle-core/index.js +4 -2
  99. package/src/workflows/reconcile/canonical-surface.js +4 -1
  100. package/src/cli/commands/new.js +0 -94
package/src/cli/help.js CHANGED
@@ -35,17 +35,18 @@ export function printUsage(options = {}) {
35
35
  console.log(" or: topogram catalog show <id> [--json] [--catalog <path-or-source>]");
36
36
  console.log(" or: topogram catalog doctor [--json] [--catalog <path-or-source>]");
37
37
  console.log(" or: topogram catalog check <path-or-url> [--json]");
38
- console.log(" or: topogram catalog copy <id> <target> [--version <version>] [--json] [--catalog <path-or-source>]");
39
38
  console.log(" or: topogram package update-cli <version|--latest> [--json]");
40
- console.log(" or: topogram import <app-path> --out <target> [--from <track[,track]>] [--json]");
41
- console.log(" or: topogram import refresh [path] [--from <app-path>] [--dry-run] [--json]");
42
- console.log(" or: topogram import diff [path] [--json]");
43
- console.log(" or: topogram import check [path] [--json]");
44
- console.log(" or: topogram import plan [path] [--json]");
45
- console.log(" or: topogram import adopt --list [path] [--json]");
46
- console.log(" or: topogram import adopt <selector> [path] [--dry-run|--write] [--force --reason <text>] [--json]");
47
- console.log(" or: topogram import status [path] [--json]");
48
- console.log(" or: topogram import history [path] [--verify] [--json]");
39
+ console.log(" or: topogram copy <source> <target> [--version <version>] [--catalog <path-or-source>] [--json]");
40
+ console.log(" or: topogram copy --list [--json] [--catalog <path-or-source>]");
41
+ console.log(" or: topogram extract <app-path> --out <target> [--from <track[,track]>] [--extractor <id-or-package-or-path>] [--json]");
42
+ console.log(" or: topogram extract refresh [path] [--from <app-path>] [--dry-run] [--json]");
43
+ console.log(" or: topogram extract diff [path] [--json]");
44
+ console.log(" or: topogram extract check [path] [--json]");
45
+ console.log(" or: topogram extract plan [path] [--json]");
46
+ console.log(" or: topogram adopt --list [path] [--json]");
47
+ console.log(" or: topogram adopt <selector> [path] [--dry-run|--write] [--force --reason <text>] [--json]");
48
+ console.log(" or: topogram extract status [path] [--json]");
49
+ console.log(" or: topogram extract history [path] [--verify] [--json]");
49
50
  console.log(" or: topogram source status [path] [--local|--remote] [--json]");
50
51
  console.log(" or: topogram template list [--json]");
51
52
  console.log(" or: topogram template explain [path] [--json]");
@@ -66,9 +67,15 @@ export function printUsage(options = {}) {
66
67
  console.log(" or: topogram generator policy check [path] [--json]");
67
68
  console.log(" or: topogram generator policy explain [path] [--json]");
68
69
  console.log(" or: topogram generator policy pin [package@version] [path] [--json]");
69
- console.log(" or: topogram new <path> [--template hello-web|todo|./local-template|@scope/template]");
70
- console.log(" or: topogram new <path> --template <package> --allow-local-npmrc");
71
- console.log(" or: topogram new --list-templates [--json] [--catalog <path-or-source>]");
70
+ console.log(" or: topogram extractor list [--json]");
71
+ console.log(" or: topogram extractor show <id-or-package> [--json]");
72
+ console.log(" or: topogram extractor check <path-or-package> [--json]");
73
+ console.log(" or: topogram extractor policy init [path] [--json]");
74
+ console.log(" or: topogram extractor policy status [path] [--json]");
75
+ console.log(" or: topogram extractor policy check [path] [--json]");
76
+ console.log(" or: topogram extractor policy explain [path] [--json]");
77
+ console.log(" or: topogram extractor policy pin [package@version] [path] [--json]");
78
+ console.log(" or: topogram init [path] [--with-sdlc] [--json]");
72
79
  console.log("");
73
80
  console.log("Common commands:");
74
81
  console.log(" topogram version");
@@ -76,9 +83,10 @@ export function printUsage(options = {}) {
76
83
  console.log(" topogram setup package-auth");
77
84
  console.log(" topogram release status");
78
85
  console.log(" topogram release roll-consumers --latest");
79
- console.log(" topogram new ./my-app");
80
- console.log(" topogram new --list-templates");
81
- console.log(" topogram new ./my-app --template todo");
86
+ console.log(" topogram init .");
87
+ console.log(" topogram copy --list");
88
+ console.log(" topogram copy hello-web ./my-app");
89
+ console.log(" topogram copy todo ./todo-app");
82
90
  console.log(" topogram check");
83
91
  console.log(" topogram check --json");
84
92
  console.log(" topogram widget check --projection proj_web_surface");
@@ -98,22 +106,26 @@ export function printUsage(options = {}) {
98
106
  console.log(" topogram generator show @topogram/generator-react-web");
99
107
  console.log(" topogram generator check ./generator-package");
100
108
  console.log(" topogram generator policy check");
109
+ console.log(" topogram extractor list");
110
+ console.log(" topogram extractor check ./extractor-package");
111
+ console.log(" topogram extractor policy check");
101
112
  console.log(" topogram generate");
102
- console.log(" topogram import ./existing-app --out ./imported-topogram");
103
- console.log(" topogram import diff ./imported-topogram");
104
- console.log(" topogram import refresh ./imported-topogram --from ./existing-app --dry-run");
105
- console.log(" topogram import check ./imported-topogram");
106
- console.log(" topogram import plan ./imported-topogram");
107
- console.log(" topogram import adopt --list ./imported-topogram");
108
- console.log(" topogram import adopt bundle:task ./imported-topogram --dry-run");
109
- console.log(" topogram import status ./imported-topogram");
110
- console.log(" topogram import history ./imported-topogram --verify");
113
+ console.log(" topogram extract ./existing-app --out ./extracted-topogram");
114
+ console.log(" topogram extract diff ./extracted-topogram");
115
+ console.log(" topogram extract refresh ./extracted-topogram --from ./existing-app --dry-run");
116
+ console.log(" topogram extract check ./extracted-topogram");
117
+ console.log(" topogram extract plan ./extracted-topogram");
118
+ console.log(" topogram adopt --list ./extracted-topogram");
119
+ console.log(" topogram adopt bundle:task ./extracted-topogram --dry-run");
120
+ console.log(" topogram extract status ./extracted-topogram");
121
+ console.log(" topogram extract history ./extracted-topogram --verify");
111
122
  console.log("");
112
123
  console.log("Fresh install:");
113
124
  console.log(" npm install --save-dev @topogram/cli");
114
125
  console.log(" npx topogram doctor");
115
126
  console.log(" npx topogram template list");
116
- console.log(" npx topogram new ./my-app --template hello-web");
127
+ console.log(" npx topogram init .");
128
+ console.log(" npx topogram copy hello-web ./my-app");
117
129
  console.log(" cd ./my-app && npm install && npm run check && npm run generate");
118
130
  console.log(" npm --prefix app run compile");
119
131
  console.log("");
@@ -123,7 +135,7 @@ export function printUsage(options = {}) {
123
135
  console.log(" topogram catalog show todo");
124
136
  console.log(" topogram catalog doctor");
125
137
  console.log(" topogram catalog check topograms.catalog.json");
126
- console.log(" topogram catalog copy hello ./hello-topogram");
138
+ console.log(" topogram copy hello ./hello-topogram");
127
139
  console.log(" topogram source status --local");
128
140
  console.log(" topogram source status --remote");
129
141
  console.log("");
@@ -149,7 +161,7 @@ export function printUsage(options = {}) {
149
161
  console.log(" topogram template update --apply");
150
162
  console.log("");
151
163
  console.log("Defaults: check/generate use ./topo, and generate writes ./app.");
152
- console.log("Default starter: hello-web from the catalog. Run `topogram template list` for catalog aliases.");
164
+ console.log("Default starter: hello-web from the catalog. Run `topogram copy --list` for catalog aliases.");
153
165
  console.log("Generated app commands are emitted into the output package.json.");
154
166
  console.log("Run `topogram help <command>` for command-specific help.");
155
167
  console.log("Run `topogram help all` for legacy and agent-facing commands.");
@@ -157,16 +169,12 @@ export function printUsage(options = {}) {
157
169
  return;
158
170
  }
159
171
  console.log("");
160
- console.log("Legacy and internal commands:");
161
- console.log("Usage: topogram create <path> [--template hello-web|todo|./local-template|@scope/template]");
172
+ console.log("Internal commands:");
162
173
  console.log(" or: topogram template show <id> [--json] [--catalog <path-or-source>]");
163
- console.log(" or: topogram import app <path> [--from <track[,track]>] [--write]");
164
174
  console.log(" or: topogram validate <path>");
165
- console.log(" or: node ./src/cli.js query work-packet <path> --mode import-adopt --lane <id>");
175
+ console.log(" or: node ./src/cli.js query work-packet <path> --mode extract-adopt --lane <id>");
166
176
  console.log(" or: node ./src/cli.js <path> [--json] [--validate] [--resolve] [--workflow <name>] [--mode <id>] [--from <track[,track]>] [--adopt <selector>] [--refresh-adopted] [--shape <id>] [--capability <id>] [--widget <id>] [--projection <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--task <id>] [--profile <id>] [--from-snapshot <path>] [--from-topogram <path>] [--write] [--out-dir <path>]");
167
177
  console.log(" or: node ./src/cli.js emit <target> [path] [--json] [--write] [--out-dir <path>]");
168
- console.log(" or: node ./src/cli.js import app <path> [--from <track[,track]>] [--write]");
169
- console.log(" or: node ./src/cli.js import docs <path> [--write]");
170
178
  console.log(" or: node ./src/cli.js generate journeys <path> [--write]");
171
179
  console.log(" or: node ./src/cli.js report gaps <path> [--write]");
172
180
  console.log(" or: node ./src/cli.js query task-mode <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--from-topogram <path>]");
@@ -184,56 +192,75 @@ export function printUsage(options = {}) {
184
192
  console.log(" or: node ./src/cli.js query verification-targets <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--from-topogram <path>]");
185
193
  console.log(" or: node ./src/cli.js query widget-behavior <path> [--projection <id>] [--widget <id>] [--json]");
186
194
  console.log(" or: node ./src/cli.js query change-plan <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--from-topogram <path>]");
187
- console.log(" or: node ./src/cli.js query import-plan <path>");
195
+ console.log(" or: node ./src/cli.js query extract-plan <path>");
188
196
  console.log(" or: node ./src/cli.js query risk-summary <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--from-topogram <path>]");
189
197
  console.log(" or: node ./src/cli.js query canonical-writes <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--from-topogram <path>]");
190
198
  console.log(" or: node ./src/cli.js query proceed-decision <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--from-topogram <path>]");
191
199
  console.log(" or: node ./src/cli.js query review-packet <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--from-topogram <path>]");
192
200
  console.log(" or: node ./src/cli.js query next-action <path> [--mode <id>] [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--from-topogram <path>]");
193
201
  console.log(" or: node ./src/cli.js query single-agent-plan <path> --mode <id> [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--task <id>] [--plan <id>] [--bug <id>] [--from-topogram <path>]");
194
- console.log(" or: node ./src/cli.js query multi-agent-plan <path> --mode import-adopt");
202
+ console.log(" or: node ./src/cli.js query multi-agent-plan <path> --mode extract-adopt");
195
203
  console.log(" or: node ./src/cli.js query resolved-workflow-context <path> --mode <id> [--capability <id>] [--workflow <id>] [--projection <id>] [--widget <id>] [--entity <id>] [--journey <id>] [--surface <id>] [--provider <id>] [--preset <id>] [--from-topogram <path>]");
196
204
  console.log(" or: node ./src/cli.js query workflow-preset-activation <path> --mode <id> [--provider <id>] [--preset <id>] [--from-topogram <path>]");
197
205
  console.log(" or: node ./src/cli.js query workflow-preset-diff <path> --provider <id> [--preset <id>]");
198
206
  console.log(" or: node ./src/cli.js query workflow-preset-customization <path> --provider <id> --preset <id>");
199
207
  console.log(" or: node ./src/cli.js workflow-preset customize <path> --provider <id> --preset <id> [--out <path>] [--write]");
200
- console.log(" or: node ./src/cli.js query lane-status <path> --mode import-adopt");
201
- console.log(" or: node ./src/cli.js query handoff-status <path> --mode import-adopt");
208
+ console.log(" or: node ./src/cli.js query lane-status <path> --mode extract-adopt");
209
+ console.log(" or: node ./src/cli.js query handoff-status <path> --mode extract-adopt");
202
210
  console.log(" or: node ./src/cli.js query auth-hints <path>");
203
211
  console.log(" or: node ./src/cli.js query auth-review-packet <path> --bundle <slug>");
204
212
  console.log(" or: node ./src/cli.js reconcile <path> [--write]");
205
213
  console.log(" or: node ./src/cli.js reconcile adopt <selector> <path> [--refresh-adopted] [--write]");
206
214
  console.log(" or: node ./src/cli.js adoption status <path> [--write]");
207
215
  console.log("Targets: json-schema, docs, docs-index, verification-plan, verification-checklist, shape-transform-graph, shape-transform-debug, api-contract-graph, api-contract-debug, ui-contract-graph, ui-contract-debug, ui-widget-contract, widget-conformance-report, widget-behavior-report, ui-surface-contract, ui-surface-debug, sveltekit-app, swiftui-app, db-contract-graph, db-contract-debug, db-schema-snapshot, db-migration-plan, db-lifecycle-plan, db-lifecycle-bundle, environment-plan, environment-bundle, deployment-plan, deployment-bundle, runtime-smoke-plan, runtime-smoke-bundle, runtime-check-plan, runtime-check-bundle, compile-check-plan, compile-check-bundle, app-bundle-plan, app-bundle, native-parity-plan, native-parity-bundle, sql-migration, sql-schema, prisma-schema, drizzle-schema, persistence-scaffold, server-contract, hono-server, openapi, context-digest, context-diff, context-slice, context-bundle, context-report, context-task-mode");
208
- console.log("Workflows: import-app, scan-docs, reconcile, adoption-status, generate-docs, generate-journeys, refresh-docs, report-gaps");
209
- console.log("Import tracks: db, api, ui, workflows, verification");
216
+ console.log("Workflows: scan-docs, reconcile, adoption-status, generate-docs, generate-journeys, refresh-docs, report-gaps");
217
+ console.log("Extract tracks: db, api, ui, cli, workflows, verification");
210
218
  console.log("Reconcile adopt selectors: from-plan, actors, roles, enums, shapes, entities, capabilities, widgets, docs, journeys, workflows, ui, bundle:<slug>, projection-review:<id>, ui-review:<id>, workflow-review:<id>, bundle-review:<slug>");
211
219
  }
212
220
 
213
221
  /**
214
222
  * @returns {void}
215
223
  */
216
- export function printNewHelp() {
217
- console.log("Usage: topogram new <path> [--template <alias|package|path>] [--catalog <path-or-source>]");
218
- console.log(" or: topogram new --list-templates [--json] [--catalog <path-or-source>]");
224
+ export function printCopyHelp() {
225
+ console.log("Usage: topogram copy <source> <target> [--version <version>] [--catalog <path-or-source>] [--json]");
226
+ console.log(" or: topogram copy --list [--json] [--catalog <path-or-source>]");
219
227
  console.log("");
220
- console.log("Creates a new editable Topogram workspace from a template package or local template path.");
228
+ console.log("Copies a catalog template, template package/path, or pure Topogram source into a new project directory.");
221
229
  console.log("");
222
230
  console.log("Fresh install flow:");
223
231
  console.log(" npm install --save-dev @topogram/cli");
224
- console.log(" npx topogram template list");
225
- console.log(" npx topogram new ./my-app --template hello-web");
232
+ console.log(" npx topogram copy --list");
233
+ console.log(" npx topogram copy hello-web ./my-app");
226
234
  console.log(" cd ./my-app && npm install && npm run check && npm run generate");
227
235
  console.log(" npm --prefix app run compile");
228
236
  console.log("");
229
237
  console.log("Examples:");
230
- console.log(" topogram new ./my-app");
231
- console.log(" topogram new --list-templates");
232
- console.log(" topogram new ./my-app --template hello-web");
233
- console.log(" topogram new ./my-app --template ./local-template");
234
- console.log(" topogram new ./my-app --template @scope/topogram-template");
238
+ console.log(" topogram copy --list");
239
+ console.log(" topogram copy hello-web ./my-app");
240
+ console.log(" topogram copy todo ./todo-app");
241
+ console.log(" topogram copy ./local-template ./my-app");
242
+ console.log(" topogram copy @scope/topogram-template ./my-app");
243
+ console.log("");
244
+ console.log("Template entries create starter projects. Topogram entries copy editable topo/ source.");
245
+ }
246
+
247
+ /**
248
+ * @returns {void}
249
+ */
250
+ export function printInitHelp() {
251
+ console.log("Usage: topogram init [path] [--with-sdlc] [--json]");
252
+ console.log("");
253
+ console.log("Initializes an empty Topogram workspace in an existing or new repository without copying a template.");
235
254
  console.log("");
236
- console.log("Default template: hello-web from the configured catalog.");
255
+ console.log("Defaults: path is the current directory. Init creates topo/, topogram.project.json, and starter guidance files only when they are missing.");
256
+ console.log("The default output is maintained ownership for '.', so Topogram will not overwrite app source.");
257
+ console.log("--with-sdlc also writes topogram.sdlc-policy.json with adopted/enforced defaults.");
258
+ console.log("");
259
+ console.log("Examples:");
260
+ console.log(" topogram init");
261
+ console.log(" topogram init . --with-sdlc");
262
+ console.log(" topogram init . --json");
263
+ console.log(" topogram init ./existing-app");
237
264
  }
238
265
 
239
266
  /**
@@ -30,6 +30,15 @@ export function cliMigrationError(args) {
30
30
  if (args[0] === "component") {
31
31
  return "Command 'topogram component' was renamed to 'topogram widget'.";
32
32
  }
33
+ if (args[0] === "new" || args[0] === "create") {
34
+ return "Command 'topogram new' was replaced by 'topogram copy <source> <target>'. For example: topogram copy hello-web ./my-app.";
35
+ }
36
+ if (args[0] === "import") {
37
+ return "Command 'topogram import' was replaced by 'topogram extract' and top-level 'topogram adopt'.";
38
+ }
39
+ if (args[0] === "catalog" && args[1] === "copy") {
40
+ return "Command 'topogram catalog copy' was replaced by 'topogram copy <source> <target>'.";
41
+ }
33
42
  if (args[0] === "migrate") {
34
43
  return "Command 'topogram migrate workspace-folder' was removed. Use topo/ workspaces or configure topogram.project.json workspace to a non-legacy relative path.";
35
44
  }
@@ -22,6 +22,21 @@ export function optionValueIfPresent(args, flag) {
22
22
  return value && !value.startsWith("-") ? value : null;
23
23
  }
24
24
 
25
+ /**
26
+ * @param {string[]} args
27
+ * @param {string} flag
28
+ * @returns {string[]}
29
+ */
30
+ export function optionValues(args, flag) {
31
+ const values = [];
32
+ for (let index = 0; index < args.length; index += 1) {
33
+ if (args[index] === flag && args[index + 1] && !args[index + 1].startsWith("-")) {
34
+ values.push(args[index + 1]);
35
+ }
36
+ }
37
+ return values;
38
+ }
39
+
25
40
  /**
26
41
  * @param {string[]} args
27
42
  * @param {string} flag
@@ -51,6 +66,8 @@ export function parseCliOptions(args, commandArgs) {
51
66
  workflowName: commandArgs?.workflowName || (!generateTarget && workflowFlagValue ? workflowFlagValue : null),
52
67
  workflowId: generateTarget ? workflowFlagValue : null,
53
68
  fromValue: optionValue(args, "--from"),
69
+ extractorSpecs: optionValues(args, "--extractor"),
70
+ extractorPolicyPath: optionValueIfPresent(args, "--extractor-policy"),
54
71
  adoptValue: commandArgs?.adoptValue || optionValue(args, "--adopt"),
55
72
  reasonValue: optionValueIfPresent(args, "--reason"),
56
73
  modeId: optionValue(args, "--mode"),
@@ -0,0 +1,155 @@
1
+ // @ts-check
2
+
3
+ import {
4
+ createExtractorSmokeContext,
5
+ loadExtractorPackageAdapterForSpec,
6
+ validateExtractorAdapter
7
+ } from "./packages.js";
8
+
9
+ /**
10
+ * @typedef {import("./registry.js").ExtractorManifest} ExtractorManifest
11
+ */
12
+
13
+ /**
14
+ * @typedef {Object} ExtractorCheckResult
15
+ * @property {boolean} ok
16
+ * @property {string} sourceSpec
17
+ * @property {"path"|"package"} source
18
+ * @property {string|null} packageName
19
+ * @property {string|null} packageRoot
20
+ * @property {string|null} manifestPath
21
+ * @property {ExtractorManifest|null} manifest
22
+ * @property {Array<{ name: string, ok: boolean, message: string }>} checks
23
+ * @property {string[]} errors
24
+ * @property {{ extractors: number, findings: number, candidateKeys: number, diagnostics: number }|null} smoke
25
+ * @property {boolean} executesPackageCode
26
+ */
27
+
28
+ /**
29
+ * @param {any} result
30
+ * @returns {{ ok: boolean, message: string, smoke: { findings: number, candidateKeys: number, diagnostics: number }|null }}
31
+ */
32
+ function validateExtractResult(result) {
33
+ if (!result || typeof result !== "object" || Array.isArray(result)) {
34
+ return { ok: false, message: "extract(context) must return an object", smoke: null };
35
+ }
36
+ if (result.findings != null && !Array.isArray(result.findings)) {
37
+ return { ok: false, message: "extract(context) findings must be an array when present", smoke: null };
38
+ }
39
+ if (result.diagnostics != null && !Array.isArray(result.diagnostics)) {
40
+ return { ok: false, message: "extract(context) diagnostics must be an array when present", smoke: null };
41
+ }
42
+ if (!result.candidates || typeof result.candidates !== "object" || Array.isArray(result.candidates)) {
43
+ return { ok: false, message: "extract(context) result must include a candidates object", smoke: null };
44
+ }
45
+ for (const [key, value] of Object.entries(result.candidates)) {
46
+ if (!Array.isArray(value)) {
47
+ return { ok: false, message: `extract(context) candidates.${key} must be an array`, smoke: null };
48
+ }
49
+ }
50
+ return {
51
+ ok: true,
52
+ message: `extract(context) returned ${Object.keys(result.candidates).length} candidate bucket(s)`,
53
+ smoke: {
54
+ findings: Array.isArray(result.findings) ? result.findings.length : 0,
55
+ candidateKeys: Object.keys(result.candidates).length,
56
+ diagnostics: Array.isArray(result.diagnostics) ? result.diagnostics.length : 0
57
+ }
58
+ };
59
+ }
60
+
61
+ /**
62
+ * @param {string} sourceSpec
63
+ * @param {{ cwd?: string }} [options]
64
+ * @returns {ExtractorCheckResult}
65
+ */
66
+ export function checkExtractorPack(sourceSpec, options = {}) {
67
+ /** @type {ExtractorCheckResult} */
68
+ const payload = {
69
+ ok: false,
70
+ sourceSpec,
71
+ source: "package",
72
+ packageName: null,
73
+ packageRoot: null,
74
+ manifestPath: null,
75
+ manifest: null,
76
+ checks: [],
77
+ errors: [],
78
+ smoke: null,
79
+ executesPackageCode: true
80
+ };
81
+ if (!sourceSpec || sourceSpec.startsWith("-")) {
82
+ payload.errors.push("Usage: topogram extractor check <path-or-package>");
83
+ payload.checks.push({ name: "source", ok: false, message: payload.errors[0] });
84
+ return payload;
85
+ }
86
+
87
+ const loaded = loadExtractorPackageAdapterForSpec(sourceSpec, options);
88
+ payload.source = loaded.source;
89
+ payload.packageName = loaded.packageName;
90
+ payload.packageRoot = loaded.packageRoot;
91
+ payload.manifestPath = loaded.manifestPath;
92
+ payload.manifest = loaded.manifest;
93
+ if (!loaded.manifest) {
94
+ payload.errors.push(...loaded.errors);
95
+ payload.checks.push({ name: "manifest-load", ok: false, message: loaded.errors.join(" ") || "Could not load extractor manifest." });
96
+ return payload;
97
+ }
98
+ payload.checks.push({ name: "manifest-load", ok: true, message: loaded.manifestPath || sourceSpec });
99
+ if (!loaded.adapter || loaded.errors.length > 0) {
100
+ payload.errors.push(...loaded.errors);
101
+ payload.checks.push({ name: "adapter-load", ok: false, message: loaded.errors.join(" ") || "Could not load extractor adapter." });
102
+ return payload;
103
+ }
104
+ payload.checks.push({ name: "adapter-load", ok: true, message: "Adapter export loaded." });
105
+
106
+ const adapterValidation = validateExtractorAdapter(loaded.adapter, loaded.manifest);
107
+ payload.checks.push({
108
+ name: "adapter-shape",
109
+ ok: adapterValidation.errors.length === 0,
110
+ message: adapterValidation.errors.length === 0 ? "Adapter shape is valid." : adapterValidation.errors.join(" ")
111
+ });
112
+ if (adapterValidation.errors.length > 0) {
113
+ payload.errors.push(...adapterValidation.errors);
114
+ return payload;
115
+ }
116
+
117
+ const context = createExtractorSmokeContext();
118
+ let totalFindings = 0;
119
+ let totalCandidateKeys = 0;
120
+ let totalDiagnostics = 0;
121
+ for (const extractor of adapterValidation.extractors) {
122
+ try {
123
+ const detection = extractor.detect(context) || { score: 0, reasons: [] };
124
+ if (!detection || typeof detection !== "object" || typeof detection.score !== "number") {
125
+ payload.errors.push(`Extractor '${extractor.id}' detect(context) must return { score, reasons }.`);
126
+ continue;
127
+ }
128
+ const result = extractor.extract(context) || { findings: [], candidates: {} };
129
+ const validation = validateExtractResult(result);
130
+ if (!validation.ok || !validation.smoke) {
131
+ payload.errors.push(`Extractor '${extractor.id}' ${validation.message}.`);
132
+ continue;
133
+ }
134
+ totalFindings += validation.smoke.findings;
135
+ totalCandidateKeys += validation.smoke.candidateKeys;
136
+ totalDiagnostics += validation.smoke.diagnostics;
137
+ } catch (error) {
138
+ payload.errors.push(`Extractor '${extractor.id}' smoke failed: ${error instanceof Error ? error.message : String(error)}`);
139
+ }
140
+ }
141
+ payload.checks.push({
142
+ name: "smoke-extract",
143
+ ok: payload.errors.length === 0,
144
+ message: payload.errors.length === 0 ? `Ran ${adapterValidation.extractors.length} extractor smoke check(s).` : payload.errors.join(" ")
145
+ });
146
+ payload.smoke = {
147
+ extractors: adapterValidation.extractors.length,
148
+ findings: totalFindings,
149
+ candidateKeys: totalCandidateKeys,
150
+ diagnostics: totalDiagnostics
151
+ };
152
+ payload.ok = payload.errors.length === 0;
153
+ return payload;
154
+ }
155
+