@topogram/cli 0.3.78 → 0.3.79

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 (79) 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-parsers/core.js +9 -5
  14. package/src/cli/command-parsers/import.js +11 -17
  15. package/src/cli/command-parsers/project.js +0 -3
  16. package/src/cli/commands/catalog/copy.js +3 -3
  17. package/src/cli/commands/catalog/help.js +1 -2
  18. package/src/cli/commands/catalog/list.js +7 -4
  19. package/src/cli/commands/catalog/show.js +4 -4
  20. package/src/cli/commands/copy.js +356 -0
  21. package/src/cli/commands/doctor.js +1 -1
  22. package/src/cli/commands/import/adopt.js +9 -9
  23. package/src/cli/commands/import/check.js +15 -15
  24. package/src/cli/commands/import/diff.js +6 -6
  25. package/src/cli/commands/import/help.js +43 -34
  26. package/src/cli/commands/import/paths.js +3 -3
  27. package/src/cli/commands/import/plan.js +8 -8
  28. package/src/cli/commands/import/refresh.js +25 -24
  29. package/src/cli/commands/import/status-history.js +4 -4
  30. package/src/cli/commands/import/workspace.js +16 -16
  31. package/src/cli/commands/import-runner.js +6 -5
  32. package/src/cli/commands/import.js +4 -1
  33. package/src/cli/commands/init.js +67 -0
  34. package/src/cli/commands/query/{import-adopt.js → extract-adopt.js} +2 -2
  35. package/src/cli/commands/query/runner/change.js +2 -2
  36. package/src/cli/commands/query/runner/{import-adopt.js → extract-adopt.js} +9 -9
  37. package/src/cli/commands/query/runner/index.js +1 -1
  38. package/src/cli/commands/query/runner/workflow.js +7 -7
  39. package/src/cli/commands/query/workspace.js +4 -4
  40. package/src/cli/commands/release-status.js +2 -2
  41. package/src/cli/commands/source.js +2 -2
  42. package/src/cli/commands/template/check.js +2 -2
  43. package/src/cli/commands/template/list-show.js +4 -4
  44. package/src/cli/dispatcher.js +18 -3
  45. package/src/cli/help-dispatch.js +22 -8
  46. package/src/cli/help.js +68 -52
  47. package/src/cli/migration-guidance.js +9 -0
  48. package/src/generator/context/bundle.js +14 -7
  49. package/src/generator/context/diff.js +8 -1
  50. package/src/generator/context/digest.js +10 -1
  51. package/src/generator/context/shared/domain-sdlc.js +5 -1
  52. package/src/generator/context/shared/relationships.js +20 -5
  53. package/src/generator/context/shared/summaries.js +26 -0
  54. package/src/generator/context/shared.d.ts +1 -0
  55. package/src/generator/context/shared.js +1 -0
  56. package/src/generator/context/slice/core.js +9 -5
  57. package/src/generator/context/slice/sdlc.js +31 -2
  58. package/src/generator/context/task-mode.js +3 -3
  59. package/src/import/core/runner/reports.js +4 -4
  60. package/src/import/provenance.js +16 -16
  61. package/src/init-project.js +215 -0
  62. package/src/new-project/constants.js +1 -1
  63. package/src/new-project/create.js +2 -2
  64. package/src/new-project/project-files.js +7 -7
  65. package/src/reconcile/journeys.js +8 -3
  66. package/src/record-blocks.js +125 -0
  67. package/src/resolver/index.js +3 -0
  68. package/src/resolver/journeys.js +74 -0
  69. package/src/resolver/normalize.js +25 -0
  70. package/src/sdlc/adopt.js +1 -1
  71. package/src/validator/common.js +34 -1
  72. package/src/validator/index.js +4 -0
  73. package/src/validator/kinds.d.ts +2 -0
  74. package/src/validator/kinds.js +34 -1
  75. package/src/validator/per-kind/journey.js +233 -0
  76. package/src/workflows/docs-generate.js +4 -1
  77. package/src/workflows/reconcile/bundle-core/index.js +4 -2
  78. package/src/workflows/reconcile/canonical-surface.js +4 -1
  79. package/src/cli/commands/new.js +0 -94
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - No changes yet.
6
+
7
+ ## 0.3.79 - 2026-05-12
8
+
9
+ - Add graph-native `journey` statements with ordered `step` and `alternate`
10
+ record blocks, resolver/query support, and canonical dogfood journey records.
11
+ - Add `topogram init` as the primary command for starting an empty maintained
12
+ Topogram workspace, including optional SDLC policy initialization.
13
+ - Replace the public creation/extraction vocabulary with `copy`, `extract`, and
14
+ top-level `adopt`: `topogram copy <source> <target>` copies templates or pure
15
+ Topogram packages, `topogram extract` reads brownfield apps into reviewable
16
+ candidates, and `topogram adopt` promotes selected candidates.
17
+ - Rename public extraction provenance and guidance to extract/adopt terms,
18
+ including generated starter docs, agent brief output, package smoke scripts,
19
+ and dogfood CLI surface records.
20
+ - Keep `generate` scoped to app/runtime output and `emit` scoped to contracts,
21
+ reports, snapshots, and plans.
22
+
23
+ ## 0.3.78 - 2026-05-12
24
+
5
25
  - Install package-backed generator dependencies during `topogram template check`
6
26
  before starter validation.
7
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topogram/cli",
3
- "version": "0.3.78",
3
+ "version": "0.3.79",
4
4
  "description": "Topogram CLI for checking Topogram workspaces and generating app bundles.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -27,7 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "scripts": {
30
- "new": "node ./src/cli.js new",
30
+ "copy": "node ./src/cli.js copy",
31
31
  "check": "npm test",
32
32
  "fixture:check": "node ./src/cli.js check ./tests/fixtures/workspaces/app-basic",
33
33
  "fixture:check:json": "node ./src/cli.js check ./tests/fixtures/workspaces/app-basic --json",
@@ -155,11 +155,17 @@ function readImportSummary(projectRoot) {
155
155
  path: TOPOGRAM_IMPORT_FILE,
156
156
  workspaceRoot: resolveTopoRoot(projectRoot),
157
157
  source: typeof record?.source?.path === "string" ? record.source.path : null,
158
- tracks: Array.isArray(record?.import?.tracks) ? record.import.tracks.map(String) : [],
159
- candidateCounts: record?.import?.candidateCounts && typeof record.import.candidateCounts === "object"
158
+ tracks: Array.isArray(record?.extract?.tracks) ? record.extract.tracks.map(String) : Array.isArray(record?.import?.tracks) ? record.import.tracks.map(String) : [],
159
+ candidateCounts: record?.extract?.candidateCounts && typeof record.extract.candidateCounts === "object"
160
+ ? record.extract.candidateCounts
161
+ : record?.import?.candidateCounts && typeof record.import.candidateCounts === "object"
160
162
  ? record.import.candidateCounts
161
163
  : {},
162
- ownership: typeof record?.ownership?.importedArtifacts === "string" ? record.ownership.importedArtifacts : null
164
+ ownership: typeof record?.ownership?.extractedArtifacts === "string"
165
+ ? record.ownership.extractedArtifacts
166
+ : typeof record?.ownership?.importedArtifacts === "string"
167
+ ? record.ownership.importedArtifacts
168
+ : null
163
169
  };
164
170
  } catch (error) {
165
171
  return {
@@ -241,16 +247,16 @@ function buildWorkflows(config, hasImportRecord) {
241
247
  }
242
248
  if (hasImportRecord) {
243
249
  workflows.push({
244
- id: "brownfield-import",
245
- title: "Brownfield import adoption loop",
250
+ id: "brownfield-extract",
251
+ title: "Brownfield extract/adopt loop",
246
252
  commands: [
247
- "topogram import check . --json",
248
- "topogram import plan . --json",
249
- "topogram import adopt --list . --json",
250
- "topogram import status . --json",
251
- "topogram import history . --verify --json"
253
+ "topogram extract check . --json",
254
+ "topogram extract plan . --json",
255
+ "topogram adopt --list . --json",
256
+ "topogram extract status . --json",
257
+ "topogram extract history . --verify --json"
252
258
  ],
253
- rule: "Imported Topogram files are editable after adoption; JSON automation should read workspaceRoot for the project-owned workspace path."
259
+ rule: "Extracted Topogram files are editable after adoption; JSON automation should read workspaceRoot for the project-owned workspace path."
254
260
  });
255
261
  }
256
262
  return workflows;
@@ -284,7 +290,7 @@ function buildWarnings(projectRoot, config, trust, importSummary, generatorPolic
284
290
  warnings.push("Generated-owned outputs are replaceable by Topogram; do not make lasting edits under generated output paths.");
285
291
  }
286
292
  if (importSummary) {
287
- warnings.push(`${TOPOGRAM_IMPORT_FILE} is present. Treat imported Topogram artifacts as project-owned after adoption; hashes are import evidence.`);
293
+ warnings.push(`${TOPOGRAM_IMPORT_FILE} is present. Treat extracted Topogram artifacts as project-owned after adoption; hashes are extraction evidence.`);
288
294
  }
289
295
  if (!fs.existsSync(path.join(projectRoot, "AGENTS.md"))) {
290
296
  warnings.push("AGENTS.md is missing. Use this command as the current agent guidance source.");
@@ -365,7 +371,7 @@ export function buildAgentBrief(inputPath, workspaceAst) {
365
371
  readItem(projectRoot, "topogram.template-policy.json", "Template trust/update policy for attached templates.", false),
366
372
  readItem(projectRoot, GENERATOR_POLICY_FILE, "Package-backed generator policy and allowed scopes.", false),
367
373
  readItem(projectRoot, TEMPLATE_TRUST_FILE, "Executable implementation trust record, if the template copied implementation code.", Boolean(config.implementation)),
368
- readItem(projectRoot, TOPOGRAM_IMPORT_FILE, "Brownfield import provenance and source evidence, if this came from import.", Boolean(importSummary)),
374
+ readItem(projectRoot, TOPOGRAM_IMPORT_FILE, "Brownfield extraction provenance and source evidence, if this came from extract.", Boolean(importSummary)),
369
375
  readItem(projectRoot, topogramReadPath, "Canonical Topogram graph source. Use focused query packets for implementation work.", true)
370
376
  ];
371
377
 
@@ -389,11 +395,11 @@ export function buildAgentBrief(inputPath, workspaceAst) {
389
395
  commandItem("npm run generate", "Write generated-owned runtime/app outputs after validation.", "write"),
390
396
  commandItem("npm run verify", "Run generated output verification.", "verify"),
391
397
  ...(importSummary ? [
392
- commandItem("topogram import check . --json", "Validate imported workspace provenance and read workspaceRoot.", "import"),
393
- commandItem("topogram import plan . --json", "Review import adoption plan and workspaceRoot.", "import"),
394
- commandItem("topogram import adopt --list . --json", "List reviewable adoption selectors.", "import"),
395
- commandItem("topogram import status . --json", "Check import/adoption status.", "import"),
396
- commandItem("topogram import history . --verify --json", "Verify import history evidence.", "import")
398
+ commandItem("topogram extract check . --json", "Validate extracted workspace provenance and read workspaceRoot.", "extract"),
399
+ commandItem("topogram extract plan . --json", "Review extraction adoption plan and workspaceRoot.", "extract"),
400
+ commandItem("topogram adopt --list . --json", "List reviewable adoption selectors.", "adopt"),
401
+ commandItem("topogram extract status . --json", "Check extraction/adoption status.", "extract"),
402
+ commandItem("topogram extract history . --verify --json", "Verify adoption history evidence.", "extract")
397
403
  ] : [])
398
404
  ];
399
405
 
@@ -464,7 +470,7 @@ export function buildAgentBrief(inputPath, workspaceAst) {
464
470
  issues: trust.issues || []
465
471
  },
466
472
  generator_policy: generatorPolicy,
467
- import: importSummary,
473
+ extract: importSummary,
468
474
  warnings: []
469
475
  };
470
476
  payload.warnings = buildWarnings(projectRoot, config, payload.trust, importSummary, generatorPolicy, sdlcPolicy);
@@ -520,11 +526,11 @@ export function formatAgentBrief(brief) {
520
526
  for (const workflow of brief.workflows || []) {
521
527
  lines.push(` - ${workflow.title}: ${workflow.rule}`);
522
528
  }
523
- if (brief.import?.workspaceRoot) {
529
+ if (brief.extract?.workspaceRoot) {
524
530
  lines.push("");
525
- lines.push("Import:");
526
- lines.push(` - Workspace root: ${brief.import.workspaceRoot}`);
527
- lines.push(" - JSON import commands expose workspaceRoot; prefer it over compatibility fields.");
531
+ lines.push("Extract:");
532
+ lines.push(` - Workspace root: ${brief.extract.workspaceRoot}`);
533
+ lines.push(" - JSON extract commands expose workspaceRoot; prefer it over compatibility fields.");
528
534
  }
529
535
  lines.push("");
530
536
  lines.push("Verification gates:");
@@ -7,7 +7,7 @@ export function buildImportPlanPayload(adoptionPlan, taskModeArtifact, maintaine
7
7
  const importNextAction = buildImportPlanNextAction(taskModeArtifact.next_action || null, workflowPresetState);
8
8
  const presetGuidanceSummary = buildPresetGuidanceSummary(workflowPresetState, null);
9
9
  return {
10
- type: "import_plan_query",
10
+ type: "extract_plan_query",
11
11
  summary: taskModeArtifact.summary || null,
12
12
  adoption_state_vocabulary: adoptionPlan.adoption_state_vocabulary || [],
13
13
  next_action: importNextAction,
@@ -13,7 +13,7 @@ import { buildPresetGuidanceSummary } from "./risk.js";
13
13
  export function buildCanonicalWritesPayloadForImportPlan(proposalSurfaces = []) {
14
14
  return {
15
15
  type: "canonical_writes_query",
16
- source: "import-plan",
16
+ source: "extract-plan",
17
17
  canonical_writes: proposalSurfaces
18
18
  .filter((surface) => surface.canonical_rel_path)
19
19
  .map((surface) => ({
@@ -40,7 +40,7 @@ export function buildReviewPacketPayloadForImportPlan({ importPlan, risk }) {
40
40
  const presetGuidanceSummary = buildPresetGuidanceSummary(importPlan.workflow_presets || null, null);
41
41
  return {
42
42
  type: "review_packet_query",
43
- source: "import-plan",
43
+ source: "extract-plan",
44
44
  summary: importPlan.summary || null,
45
45
  risk_summary: {
46
46
  overall_risk: risk.overall_risk,
@@ -49,7 +49,7 @@ export function buildReviewPacketPayloadForImportPlan({ importPlan, risk }) {
49
49
  maintained_risk: importPlan.maintained_risk || null
50
50
  },
51
51
  next_action: importPlan.next_action || null,
52
- recommended_query_family: recommendedQueryFamilyForAction(importPlan.next_action, "import-adopt"),
52
+ recommended_query_family: recommendedQueryFamilyForAction(importPlan.next_action, "extract-adopt"),
53
53
  canonical_writes: (importPlan.proposal_surfaces || [])
54
54
  .filter((surface) => surface.canonical_rel_path)
55
55
  .map((surface) => ({
@@ -64,9 +64,9 @@ export function buildReviewPacketPayloadForImportPlan({ importPlan, risk }) {
64
64
  maintained_risk: importPlan.maintained_risk || null,
65
65
  maintained_seam_review_summary: importPlan.maintained_seam_review_summary || null,
66
66
  operator_loop: buildOperatorLoopSummary({
67
- mode: "import-adopt",
67
+ mode: "extract-adopt",
68
68
  nextAction: importPlan.next_action || null,
69
- primaryArtifacts: ["import-plan", "adoption-plan.agent.json"],
69
+ primaryArtifacts: ["extract-plan", "adoption-plan.agent.json"],
70
70
  verificationTargets: importPlan.verification_targets || null,
71
71
  currentSurface: "review-packet"
72
72
  }),
@@ -1,4 +1,4 @@
1
- export { buildImportPlanPayload } from "./change-risk/import-plan.js";
1
+ export { buildImportPlanPayload } from "./change-risk/extract-plan.js";
2
2
  export {
3
3
  buildAlignmentRecommendations,
4
4
  buildChangePlanPayload,
@@ -35,7 +35,7 @@ export function stableSortedStrings(values) {
35
35
  export const CANONICAL_TASK_MODES = new Set([
36
36
  "modeling",
37
37
  "maintained-app-edit",
38
- "import-adopt",
38
+ "extract-adopt",
39
39
  "diff-review",
40
40
  "verification"
41
41
  ]);
@@ -59,7 +59,7 @@ export const PROVIDER_PRESET_MANUAL_DECISION_CATEGORIES = new Set([
59
59
  export const WORKFLOW_QUERY_FAMILIES_BY_MODE = {
60
60
  modeling: ["change-plan", "write-scope", "verification-targets", "risk-summary"],
61
61
  "maintained-app-edit": ["maintained-boundary", "maintained-conformance", "seam-check", "change-plan"],
62
- "import-adopt": ["import-plan", "risk-summary", "proceed-decision", "review-packet"],
62
+ "extract-adopt": ["extract-plan", "risk-summary", "proceed-decision", "review-packet"],
63
63
  "diff-review": ["change-plan", "risk-summary", "review-packet"],
64
64
  verification: ["verification-targets", "proceed-decision", "risk-summary"]
65
65
  };
@@ -518,7 +518,7 @@ export function buildMultiAgentPlanPayload({
518
518
  return {
519
519
  type: "multi_agent_plan",
520
520
  workspace: workspace || null,
521
- mode: "import-adopt",
521
+ mode: "extract-adopt",
522
522
  source_single_agent_plan: singleAgentPlan,
523
523
  summary: buildMultiAgentSummary(lanes, parallelWorkstreams, overlapRules, handoffPackets),
524
524
  coordination_strategy: {
@@ -11,7 +11,7 @@ export function outputIdsForWorkflowContext(taskModeArtifact, maintainedBoundary
11
11
 
12
12
  export function integrationCategoriesForWorkflowContext(taskModeArtifact, importPlan = null) {
13
13
  const categories = [];
14
- if (taskModeArtifact?.mode === "import-adopt") categories.push("provider_adoption");
14
+ if (taskModeArtifact?.mode === "extract-adopt") categories.push("provider_adoption");
15
15
  if (taskModeArtifact?.mode === "maintained-app-edit") categories.push("maintained_app");
16
16
  if ((taskModeArtifact?.verification_targets?.maintained_app_checks || []).length > 0) categories.push("maintained_boundary");
17
17
  if ((importPlan?.requires_human_review || []).length > 0) categories.push("human_review");
@@ -43,7 +43,7 @@ export function recommendedQueryFamilyForAction(nextAction, mode = null) {
43
43
  case "customize_workflow_preset":
44
44
  case "refresh_workflow_preset_customization":
45
45
  case "import_declared_workflow_preset":
46
- return "import-plan";
46
+ return "extract-plan";
47
47
  case "review_diff_impact":
48
48
  case "inspect_projection":
49
49
  case "inspect_diff":
@@ -61,7 +61,7 @@ export function recommendedQueryFamilyForAction(nextAction, mode = null) {
61
61
  break;
62
62
  }
63
63
 
64
- if (mode === "import-adopt") return "import-plan";
64
+ if (mode === "extract-adopt") return "extract-plan";
65
65
  if (mode === "maintained-app-edit") return "maintained-boundary";
66
66
  if (mode === "verification") return "verification-targets";
67
67
  return "change-plan";
@@ -268,7 +268,7 @@ export function buildGenericSequence(taskModeArtifact, {
268
268
 
269
269
  export function buildRecommendedSequence(taskModeArtifact, importPlan = null) {
270
270
  const mode = taskModeArtifact?.mode || null;
271
- if (mode === "import-adopt") {
271
+ if (mode === "extract-adopt") {
272
272
  return buildImportAdoptSequence(taskModeArtifact, importPlan);
273
273
  }
274
274
  if (mode === "maintained-app-edit") {
@@ -56,7 +56,7 @@ export function buildTopogramSourceStatus(projectRoot) {
56
56
  severity: "warning",
57
57
  message: `${TOPOGRAM_SOURCE_FILE} was not found. This project may not have been copied from a catalog topogram entry.`,
58
58
  path: sourcePath,
59
- suggestedFix: "Run `topogram catalog copy <id> <target>` to create a project with source provenance."
59
+ suggestedFix: "Run `topogram copy <id> <target>` to create a project with source provenance."
60
60
  }],
61
61
  errors: []
62
62
  };
@@ -1 +1,3 @@
1
1
  export function resolveCatalogTemplateAlias(templateName: string, catalogSource?: string | null): any;
2
+ export function formatCatalogTemplateAliasError(templateName: string, catalogSource: string | null, error: unknown, options?: { suggestions?: string[] }): string;
3
+ export function suggestCatalogTemplateIds(catalog: any, templateName: string): string[];
@@ -93,7 +93,7 @@ export function formatCatalogTemplateAliasError(templateName, catalogSource, err
93
93
  return [
94
94
  `Catalog template alias '${templateName}' could not be resolved from '${sourceLabel}'.`,
95
95
  reason,
96
- templateName === "hello-web" ? "The default starter 'hello-web' is catalog-backed. Enable catalog access, or pass --template with a local path or full package spec." : null,
96
+ templateName === "hello-web" ? "The default starter 'hello-web' is catalog-backed. Enable catalog access, or use `topogram copy <source> <target>` with a local path or full package spec." : null,
97
97
  suggestions.length > 0 ? `Suggested templates: ${suggestions.join(", ")}.` : null,
98
98
  catalogDisabled ? "Unset TOPOGRAM_CATALOG_SOURCE=none, pass --catalog <source>, or use an explicit local path/package spec." : null,
99
99
  "Run `topogram template list` to see available templates, or `topogram catalog show <id>` to inspect a catalog alias.",
@@ -108,7 +108,7 @@ export function formatCatalogTemplateAliasError(templateName, catalogSource, err
108
108
  * @param {string} templateName
109
109
  * @returns {string[]}
110
110
  */
111
- function suggestCatalogTemplateIds(catalog, templateName) {
111
+ export function suggestCatalogTemplateIds(catalog, templateName) {
112
112
  const queryTokens = tokenizeSuggestionText(templateName);
113
113
  const templates = (catalog.entries || []).filter((entry) => entry.kind === "template");
114
114
  return templates
@@ -18,7 +18,7 @@ const QUERY_NAMES = new Set([
18
18
  "verification-targets",
19
19
  "widget-behavior",
20
20
  "change-plan",
21
- "import-plan",
21
+ "extract-plan",
22
22
  "risk-summary",
23
23
  "canonical-writes",
24
24
  "proceed-decision",
@@ -42,10 +42,14 @@ const QUERY_NAMES = new Set([
42
42
  * @returns {import("./shared.js").SplitCommandArgs|null}
43
43
  */
44
44
  export function parseCoreCommandArgs(args) {
45
- if (args[0] === "new" || args[0] === "create") {
46
- return args.includes("--list-templates")
47
- ? { templateCommand: "list", inputPath: null }
48
- : { newProject: true, inputPath: args[1] };
45
+ if (args[0] === "copy") {
46
+ if (args.includes("--list")) {
47
+ return { copyCommand: "list", inputPath: null };
48
+ }
49
+ return { copyCommand: "copy", copySource: args[1], inputPath: args[2] };
50
+ }
51
+ if (args[0] === "init") {
52
+ return { initProject: true, inputPath: commandPath(args, 1, ".") };
49
53
  }
50
54
  if (args[0] === "generate" && args[1] === "app") {
51
55
  return { generateTarget: "app-bundle", write: true, inputPath: commandPath(args, 2), defaultOutDir: "./app" };
@@ -7,37 +7,31 @@ import { commandOperandFrom, commandPath } from "./shared.js";
7
7
  * @returns {import("./shared.js").SplitCommandArgs|null}
8
8
  */
9
9
  export function parseImportCommandArgs(args) {
10
- if (args[0] === "import" && args[1] === "app") {
11
- return { workflowName: "import-app", inputPath: args[2] };
12
- }
13
- if (args[0] === "import" && args[1] === "docs") {
14
- return { workflowName: "scan-docs", inputPath: args[2] };
15
- }
16
- if (args[0] === "import" && args[1] === "diff") {
10
+ if (args[0] === "extract" && args[1] === "diff") {
17
11
  return { importCommand: "diff", inputPath: commandOperandFrom(args, 2, ".") };
18
12
  }
19
- if (args[0] === "import" && args[1] === "refresh") {
13
+ if (args[0] === "extract" && args[1] === "refresh") {
20
14
  return { importCommand: "refresh", inputPath: commandOperandFrom(args, 2, ".") };
21
15
  }
22
- if (args[0] === "import" && args[1] === "check") {
16
+ if (args[0] === "extract" && args[1] === "check") {
23
17
  return { importCommand: "check", inputPath: commandPath(args, 2, ".") };
24
18
  }
25
- if (args[0] === "import" && args[1] === "plan") {
19
+ if (args[0] === "extract" && args[1] === "plan") {
26
20
  return { importCommand: "plan", inputPath: commandPath(args, 2, ".") };
27
21
  }
28
- if (args[0] === "import" && args[1] === "adopt" && (args[2] === "--list" || args[2] === "list")) {
29
- return { importCommand: "adopt-list", inputPath: commandPath(args, 3, ".") };
22
+ if (args[0] === "adopt" && (args[1] === "--list" || args[1] === "list")) {
23
+ return { importCommand: "adopt-list", inputPath: commandPath(args, 2, ".") };
30
24
  }
31
- if (args[0] === "import" && args[1] === "adopt") {
32
- return { importCommand: "adopt", importAdoptSelector: args[2], inputPath: commandPath(args, 3, ".") };
25
+ if (args[0] === "adopt") {
26
+ return { importCommand: "adopt", importAdoptSelector: args[1], inputPath: commandPath(args, 2, ".") };
33
27
  }
34
- if (args[0] === "import" && args[1] === "status") {
28
+ if (args[0] === "extract" && args[1] === "status") {
35
29
  return { importCommand: "status", inputPath: commandPath(args, 2, ".") };
36
30
  }
37
- if (args[0] === "import" && args[1] === "history") {
31
+ if (args[0] === "extract" && args[1] === "history") {
38
32
  return { importCommand: "history", verify: args.includes("--verify"), inputPath: commandOperandFrom(args, 2, ".") };
39
33
  }
40
- if (args[0] === "import" && args[1] && !args[1].startsWith("-")) {
34
+ if (args[0] === "extract" && args[1] && !args[1].startsWith("-")) {
41
35
  return { importCommand: "workspace", inputPath: args[1] };
42
36
  }
43
37
  return null;
@@ -37,9 +37,6 @@ export function parseProjectCommandArgs(args) {
37
37
  if (args[0] === "catalog" && args[1] === "check") {
38
38
  return { catalogCommand: "check", inputPath: args[2] };
39
39
  }
40
- if (args[0] === "catalog" && args[1] === "copy") {
41
- return { catalogCommand: "copy", catalogId: args[2], inputPath: args[3] };
42
- }
43
40
  if (args[0] === "package" && args[1] === "update-cli") {
44
41
  return { packageCommand: "update-cli", inputPath: args.includes("--latest") ? "latest" : args[2] };
45
42
  }
@@ -18,10 +18,10 @@ import { shellCommandArg } from "./shared.js";
18
18
  */
19
19
  export function buildCatalogCopyPayload(id, targetPath, options) {
20
20
  if (!id || id.startsWith("-")) {
21
- throw new Error("topogram catalog copy requires <id>.");
21
+ throw new Error("topogram copy requires <source>.");
22
22
  }
23
23
  if (!targetPath || targetPath.startsWith("-")) {
24
- throw new Error("topogram catalog copy requires <target>.");
24
+ throw new Error("topogram copy requires <target>.");
25
25
  }
26
26
  const loaded = loadCatalog(options.source || null);
27
27
  const entry = findCatalogEntry(loaded.catalog, id, "topogram");
@@ -49,7 +49,7 @@ export function printCatalogCopy(payload) {
49
49
  console.log(`Package: ${payload.packageSpec}`);
50
50
  console.log(`Source provenance: ${payload.provenancePath}`);
51
51
  console.log(`Files: ${payload.files.length}`);
52
- console.log(`${TOPOGRAM_SOURCE_FILE} records catalog-copy provenance only. Local edits are allowed.`);
52
+ console.log(`${TOPOGRAM_SOURCE_FILE} records copy provenance only. Local edits are allowed.`);
53
53
  console.log("");
54
54
  console.log("Next steps:");
55
55
  console.log(` cd ${shellCommandArg(path.relative(process.cwd(), payload.targetPath) || ".")}`);
@@ -8,7 +8,6 @@ export function printCatalogHelp() {
8
8
  console.log(" or: topogram catalog show <id> [--json] [--catalog <path-or-source>]");
9
9
  console.log(" or: topogram catalog doctor [--json] [--catalog <path-or-source>]");
10
10
  console.log(" or: topogram catalog check <path-or-url> [--json]");
11
- console.log(" or: topogram catalog copy <id> <target> [--version <version>] [--json] [--catalog <path-or-source>]");
12
11
  console.log("");
13
12
  console.log("Catalog commands inspect the shared Topogram index. The catalog is an index; templates and topograms resolve to versioned packages.");
14
13
  console.log("");
@@ -17,5 +16,5 @@ export function printCatalogHelp() {
17
16
  console.log(" topogram catalog show hello-web");
18
17
  console.log(" topogram catalog doctor");
19
18
  console.log(" topogram catalog check topograms.catalog.json");
20
- console.log(" topogram catalog copy hello ./hello-topogram");
19
+ console.log(" topogram copy hello ./hello-topogram");
21
20
  }
@@ -8,7 +8,7 @@ import { shellCommandArg } from "./shared.js";
8
8
 
9
9
  /**
10
10
  * @param {string|null} source
11
- * @returns {{ ok: boolean, source: string, catalog: any, entries: any[], diagnostics: any[], errors: string[] }}
11
+ * @returns {{ ok: boolean, source: string, catalog: any, entries: any[], templates: any[], topograms: any[], diagnostics: any[], errors: string[] }}
12
12
  */
13
13
  export function buildCatalogListPayload(source) {
14
14
  const loaded = loadCatalog(source || null);
@@ -16,10 +16,13 @@ export function buildCatalogListPayload(source) {
16
16
  ok: true,
17
17
  source: loaded.source,
18
18
  catalog: {
19
+ loaded: true,
19
20
  version: loaded.catalog.version,
20
21
  entries: loaded.catalog.entries.length
21
22
  },
22
23
  entries: loaded.catalog.entries,
24
+ templates: loaded.catalog.entries.filter((/** @type {any} */ entry) => entry.kind === "template"),
25
+ topograms: loaded.catalog.entries.filter((/** @type {any} */ entry) => entry.kind === "topogram"),
23
26
  diagnostics: loaded.diagnostics,
24
27
  errors: []
25
28
  };
@@ -31,7 +34,7 @@ export function buildCatalogListPayload(source) {
31
34
  */
32
35
  export function printCatalogList(payload) {
33
36
  console.log("Catalog entries:");
34
- console.log("Template entries create starters with `topogram new`; topogram entries copy editable Topogram source.");
37
+ console.log("Template entries create starters with `topogram copy`; topogram entries copy editable Topogram source.");
35
38
  console.log(`Catalog: ${payload.source}`);
36
39
  console.log(`Version: ${payload.catalog.version}`);
37
40
  const catalogOption = payload.source === catalogSourceOrDefault(null)
@@ -44,9 +47,9 @@ export function printCatalogList(payload) {
44
47
  console.log(` Trust scope: ${entry.trust.scope}`);
45
48
  console.log(` Executable implementation: ${entry.trust.includesExecutableImplementation ? "yes" : "no"}`);
46
49
  if (entry.kind === "template") {
47
- console.log(` New: topogram new ./my-app --template ${shellCommandArg(entry.id)}${catalogOption}`);
50
+ console.log(` Copy: topogram copy ${shellCommandArg(entry.id)} ./my-app${catalogOption}`);
48
51
  } else {
49
- console.log(` Copy: topogram catalog copy ${shellCommandArg(entry.id)} ./${entry.id}-topogram${catalogOption}`);
52
+ console.log(` Copy: topogram copy ${shellCommandArg(entry.id)} ./${entry.id}-topogram${catalogOption}`);
50
53
  }
51
54
  }
52
55
  }
@@ -63,7 +63,7 @@ export function catalogShowCommands(entry, source) {
63
63
  if (entry.kind === "template") {
64
64
  const target = "./my-app";
65
65
  return {
66
- primary: `topogram new ${target} --template ${shellCommandArg(entry.id)}${catalogOption}`,
66
+ primary: `topogram copy ${shellCommandArg(entry.id)} ${target}${catalogOption}`,
67
67
  followUp: [
68
68
  `cd ${target}`,
69
69
  "npm install",
@@ -74,7 +74,7 @@ export function catalogShowCommands(entry, source) {
74
74
  }
75
75
  const target = `./${entry.id}-topogram`;
76
76
  return {
77
- primary: `topogram catalog copy ${shellCommandArg(entry.id)} ${target}${catalogOption}`,
77
+ primary: `topogram copy ${shellCommandArg(entry.id)} ${target}${catalogOption}`,
78
78
  followUp: [
79
79
  `cd ${target}`,
80
80
  "topogram source status --local",
@@ -102,9 +102,9 @@ export function printCatalogShow(payload) {
102
102
  console.log(`Catalog entry: ${entry.id}`);
103
103
  console.log(`Kind: ${entry.kind}`);
104
104
  if (entry.kind === "template") {
105
- console.log("Action: creates a starter app workspace with `topogram new`.");
105
+ console.log("Action: creates a starter app workspace with `topogram copy`.");
106
106
  } else {
107
- console.log("Action: copies editable Topogram source with `topogram catalog copy`.");
107
+ console.log("Action: copies editable Topogram source with `topogram copy`.");
108
108
  console.log("Executable implementation: no (topogram entries cannot include implementation/ in v1).");
109
109
  }
110
110
  console.log(`Catalog: ${payload.source}`);