@topogram/cli 0.3.77 → 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 (129) 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/core/shared/files.js +21 -2
  61. package/src/import/core/shared.js +2 -1
  62. package/src/import/enrichers/django-rest.js +4 -4
  63. package/src/import/enrichers/rails-controllers.js +3 -3
  64. package/src/import/enrichers/rails-models.js +3 -3
  65. package/src/import/extractors/api/aspnet-core.js +5 -5
  66. package/src/import/extractors/api/django-routes.js +5 -5
  67. package/src/import/extractors/api/express.js +4 -4
  68. package/src/import/extractors/api/fastify.js +7 -7
  69. package/src/import/extractors/api/flutter-dio.js +4 -4
  70. package/src/import/extractors/api/generic-route-fallback.js +2 -2
  71. package/src/import/extractors/api/graphql-code-first.js +3 -3
  72. package/src/import/extractors/api/graphql-sdl.js +5 -5
  73. package/src/import/extractors/api/jaxrs.js +3 -3
  74. package/src/import/extractors/api/micronaut.js +3 -3
  75. package/src/import/extractors/api/openapi-code.js +4 -4
  76. package/src/import/extractors/api/openapi.js +3 -3
  77. package/src/import/extractors/api/rails-routes.js +3 -3
  78. package/src/import/extractors/api/react-native-repository.js +3 -3
  79. package/src/import/extractors/api/retrofit.js +3 -3
  80. package/src/import/extractors/api/spring-web.js +3 -3
  81. package/src/import/extractors/api/swift-webapi.js +3 -3
  82. package/src/import/extractors/api/trpc.js +4 -4
  83. package/src/import/extractors/cli/generic.js +3 -3
  84. package/src/import/extractors/db/django-models.js +4 -4
  85. package/src/import/extractors/db/dotnet-models.js +4 -4
  86. package/src/import/extractors/db/drizzle.js +9 -7
  87. package/src/import/extractors/db/ef-core.js +5 -5
  88. package/src/import/extractors/db/flutter-entities.js +3 -3
  89. package/src/import/extractors/db/jpa.js +3 -3
  90. package/src/import/extractors/db/liquibase.js +3 -3
  91. package/src/import/extractors/db/maintained-seams.js +4 -4
  92. package/src/import/extractors/db/mybatis-xml.js +4 -4
  93. package/src/import/extractors/db/prisma.js +3 -3
  94. package/src/import/extractors/db/rails-schema.js +3 -3
  95. package/src/import/extractors/db/react-native-entities.js +3 -3
  96. package/src/import/extractors/db/room.js +5 -5
  97. package/src/import/extractors/db/snapshot.js +3 -3
  98. package/src/import/extractors/db/sql.js +3 -3
  99. package/src/import/extractors/db/swiftdata.js +3 -3
  100. package/src/import/extractors/ui/android-compose.js +4 -4
  101. package/src/import/extractors/ui/backend-only.js +3 -3
  102. package/src/import/extractors/ui/blazor.js +3 -3
  103. package/src/import/extractors/ui/flutter-screens.js +3 -3
  104. package/src/import/extractors/ui/maui-xaml.js +4 -4
  105. package/src/import/extractors/ui/next-pages-router.js +3 -3
  106. package/src/import/extractors/ui/razor-pages.js +3 -3
  107. package/src/import/extractors/ui/react-native-screens.js +4 -4
  108. package/src/import/extractors/ui/swiftui.js +3 -3
  109. package/src/import/extractors/ui/uikit.js +3 -3
  110. package/src/import/provenance.js +16 -16
  111. package/src/init-project.js +215 -0
  112. package/src/new-project/constants.js +1 -1
  113. package/src/new-project/create.js +2 -2
  114. package/src/new-project/project-files.js +7 -7
  115. package/src/reconcile/journeys.js +8 -3
  116. package/src/record-blocks.js +125 -0
  117. package/src/resolver/index.js +3 -0
  118. package/src/resolver/journeys.js +74 -0
  119. package/src/resolver/normalize.js +25 -0
  120. package/src/sdlc/adopt.js +1 -1
  121. package/src/validator/common.js +34 -1
  122. package/src/validator/index.js +4 -0
  123. package/src/validator/kinds.d.ts +2 -0
  124. package/src/validator/kinds.js +34 -1
  125. package/src/validator/per-kind/journey.js +233 -0
  126. package/src/workflows/docs-generate.js +4 -1
  127. package/src/workflows/reconcile/bundle-core/index.js +4 -2
  128. package/src/workflows/reconcile/canonical-surface.js +4 -1
  129. package/src/cli/commands/new.js +0 -94
@@ -8,6 +8,7 @@ export const ACCEPTANCE_CRITERION_IDENTIFIER_PATTERN: RegExp;
8
8
  export const TASK_IDENTIFIER_PATTERN: RegExp;
9
9
  export const PLAN_IDENTIFIER_PATTERN: RegExp;
10
10
  export const BUG_IDENTIFIER_PATTERN: RegExp;
11
+ export const JOURNEY_IDENTIFIER_PATTERN: RegExp;
11
12
  export const DOCUMENT_IDENTIFIER_PATTERN: RegExp;
12
13
  export const GLOBAL_STATUSES: Set<string>;
13
14
  export const DECISION_STATUSES: Set<string>;
@@ -25,6 +26,7 @@ export const TASK_DISPOSITIONS: Set<string>;
25
26
  export const PLAN_STATUSES: Set<string>;
26
27
  export const PLAN_STEP_STATUSES: Set<string>;
27
28
  export const BUG_STATUSES: Set<string>;
29
+ export const JOURNEY_STATUSES: Set<string>;
28
30
  export const PRIORITY_VALUES: Set<string>;
29
31
  export const WORK_TYPES: Set<string>;
30
32
  export const BUG_SEVERITIES: Set<string>;
@@ -16,6 +16,7 @@ export const STATEMENT_KINDS = new Set([
16
16
  "verification",
17
17
  "operation",
18
18
  "domain",
19
+ "journey",
19
20
  "pitch",
20
21
  "requirement",
21
22
  "acceptance_criterion",
@@ -32,6 +33,7 @@ export const ACCEPTANCE_CRITERION_IDENTIFIER_PATTERN = /^ac_[a-z][a-z0-9_]*$/;
32
33
  export const TASK_IDENTIFIER_PATTERN = /^task_[a-z][a-z0-9_]*$/;
33
34
  export const PLAN_IDENTIFIER_PATTERN = /^plan_[a-z][a-z0-9_]*$/;
34
35
  export const BUG_IDENTIFIER_PATTERN = /^bug_[a-z][a-z0-9_]*$/;
36
+ export const JOURNEY_IDENTIFIER_PATTERN = /^journey_[a-z][a-z0-9_]*$/;
35
37
  export const DOCUMENT_IDENTIFIER_PATTERN = /^doc_[a-z][a-z0-9_]*$/;
36
38
 
37
39
  export const GLOBAL_STATUSES = new Set(["draft", "proposed", "active", "deprecated"]);
@@ -46,6 +48,7 @@ export const TASK_STATUSES = new Set(["unclaimed", "claimed", "in-progress", "do
46
48
  export const PLAN_STATUSES = new Set(["draft", "active", "complete", "superseded"]);
47
49
  export const PLAN_STEP_STATUSES = new Set(["pending", "in-progress", "blocked", "done", "skipped"]);
48
50
  export const BUG_STATUSES = new Set(["open", "in-progress", "fixed", "verified", "wont-fix"]);
51
+ export const JOURNEY_STATUSES = new Set(["draft", "canonical", "active", "deprecated"]);
49
52
  export const TASK_DISPOSITIONS = new Set(["active", "follow_up", "deferred", "backlog", "blocker"]);
50
53
 
51
54
  export const PRIORITY_VALUES = new Set(["critical", "high", "medium", "low"]);
@@ -79,7 +82,8 @@ export const STATUS_SETS_BY_KIND = {
79
82
  acceptance_criterion: ACCEPTANCE_CRITERION_STATUSES,
80
83
  task: TASK_STATUSES,
81
84
  plan: PLAN_STATUSES,
82
- bug: BUG_STATUSES
85
+ bug: BUG_STATUSES,
86
+ journey: JOURNEY_STATUSES
83
87
  };
84
88
  export const VERIFICATION_METHODS = new Set(["smoke", "runtime", "contract", "journey", "manual"]);
85
89
  export const CLI_COMMAND_EFFECTS = new Set(["read_only", "writes_workspace", "writes_app", "network", "package_install", "git", "filesystem"]);
@@ -120,6 +124,7 @@ export const DOMAIN_TAGGABLE_KINDS = new Set([
120
124
  "orchestration",
121
125
  "operation",
122
126
  "decision",
127
+ "journey",
123
128
  "pitch",
124
129
  "requirement",
125
130
  "task",
@@ -244,6 +249,34 @@ export const FIELD_SPECS = {
244
249
  required: ["name", "description", "status"],
245
250
  allowed: ["name", "description", "in_scope", "out_of_scope", "owners", "parent_domain", "aliases", "status"]
246
251
  },
252
+ journey: {
253
+ required: ["name", "description", "status", "actors", "goal", "step"],
254
+ allowed: [
255
+ "name",
256
+ "description",
257
+ "status",
258
+ "actors",
259
+ "roles",
260
+ "goal",
261
+ "trigger",
262
+ "step",
263
+ "alternate",
264
+ "success_signals",
265
+ "failure_signals",
266
+ "related_capabilities",
267
+ "related_entities",
268
+ "related_rules",
269
+ "related_workflows",
270
+ "related_projections",
271
+ "related_widgets",
272
+ "related_verifications",
273
+ "related_decisions",
274
+ "related_docs",
275
+ "tags",
276
+ "domain",
277
+ "updated"
278
+ ]
279
+ },
247
280
  pitch: {
248
281
  required: ["name", "description", "status", "priority"],
249
282
  allowed: [
@@ -0,0 +1,233 @@
1
+ // @ts-check
2
+
3
+ import {
4
+ JOURNEY_IDENTIFIER_PATTERN
5
+ } from "../kinds.js";
6
+ import {
7
+ pushError
8
+ } from "../utils.js";
9
+ import {
10
+ parseRecordBlock,
11
+ recordField,
12
+ recordString,
13
+ recordStringList,
14
+ recordSymbol,
15
+ recordSymbolList
16
+ } from "../../record-blocks.js";
17
+
18
+ const STEP_FIELDS = new Set(["id", "intent", "commands", "expects", "after", "notes"]);
19
+ const ALTERNATE_FIELDS = new Set(["id", "from", "condition", "commands", "expects", "notes"]);
20
+
21
+ /**
22
+ * @param {ValidationErrors} errors
23
+ * @param {TopogramStatement} statement
24
+ * @returns {void}
25
+ */
26
+ function validateJourneyIdentifier(errors, statement) {
27
+ if (!JOURNEY_IDENTIFIER_PATTERN.test(statement.id)) {
28
+ pushError(
29
+ errors,
30
+ `Journey identifier '${statement.id}' must match ${JOURNEY_IDENTIFIER_PATTERN.source}`,
31
+ statement.loc
32
+ );
33
+ }
34
+ }
35
+
36
+ /**
37
+ * @param {ValidationErrors} errors
38
+ * @param {TopogramStatement} statement
39
+ * @param {TopogramField} field
40
+ * @param {Set<string>} allowedFields
41
+ * @param {string[]} requiredFields
42
+ * @returns {import("../../record-blocks.js").TopogramRecordBlock | null}
43
+ */
44
+ function validateRecordBlock(errors, statement, field, allowedFields, requiredFields) {
45
+ if (field.value.type !== "block") {
46
+ pushError(errors, `Field '${field.key}' on journey ${statement.id} must be a block`, field.loc);
47
+ return null;
48
+ }
49
+
50
+ const record = parseRecordBlock(/** @type {import("../../parser.js").AstBlock} */ (/** @type {unknown} */ (field.value)));
51
+ for (const recordFieldEntry of record.fieldOrder) {
52
+ if (!recordFieldEntry.key) {
53
+ pushError(errors, `Each '${field.key}' record entry on journey ${statement.id} must start with a field name`, recordFieldEntry.loc);
54
+ continue;
55
+ }
56
+ if (!allowedFields.has(recordFieldEntry.key)) {
57
+ pushError(errors, `Unsupported '${field.key}' field '${recordFieldEntry.key}' on journey ${statement.id}`, recordFieldEntry.loc);
58
+ }
59
+ const entries = record.fields.get(recordFieldEntry.key) || [];
60
+ if (entries.length > 1 && entries[1] === recordFieldEntry) {
61
+ pushError(errors, `Duplicate '${field.key}' field '${recordFieldEntry.key}' on journey ${statement.id}`, recordFieldEntry.loc);
62
+ }
63
+ }
64
+
65
+ for (const required of requiredFields) {
66
+ if (!record.fields.has(required)) {
67
+ pushError(errors, `Journey ${statement.id} ${field.key} record requires '${required}'`, field.loc);
68
+ }
69
+ }
70
+
71
+ return record;
72
+ }
73
+
74
+ /**
75
+ * @param {ValidationErrors} errors
76
+ * @param {TopogramStatement} statement
77
+ * @param {import("../../record-blocks.js").TopogramRecordBlock} record
78
+ * @param {string} fieldName
79
+ * @param {"symbol" | "string" | "symbol_list" | "string_list"} expected
80
+ * @returns {void}
81
+ */
82
+ function validateRecordFieldShape(errors, statement, record, fieldName, expected) {
83
+ const field = recordField(record, fieldName);
84
+ if (!field || !field.value) return;
85
+ if (expected === "symbol" && field.value.type !== "symbol") {
86
+ pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a symbol`, field.loc);
87
+ }
88
+ if (expected === "string" && field.value.type !== "string") {
89
+ pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a string`, field.loc);
90
+ }
91
+ if (expected === "symbol_list" && field.value.type !== "list") {
92
+ pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a list of symbols`, field.loc);
93
+ }
94
+ if (expected === "string_list" && field.value.type !== "list") {
95
+ pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a list of strings`, field.loc);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * @param {ValidationErrors} errors
101
+ * @param {TopogramStatement} statement
102
+ * @param {TopogramFieldMap} fieldMap
103
+ * @returns {Set<string>}
104
+ */
105
+ function validateStepRecords(errors, statement, fieldMap) {
106
+ const fields = fieldMap.get("step") || [];
107
+ /** @type {Set<string>} */
108
+ const stepIds = new Set();
109
+ if (fields.length === 0) {
110
+ pushError(errors, `Journey ${statement.id} must include at least one step`, statement.loc);
111
+ return stepIds;
112
+ }
113
+
114
+ for (const field of fields) {
115
+ const record = validateRecordBlock(errors, statement, field, STEP_FIELDS, ["id", "intent"]);
116
+ if (!record) continue;
117
+ validateRecordFieldShape(errors, statement, record, "id", "symbol");
118
+ validateRecordFieldShape(errors, statement, record, "intent", "string");
119
+ validateRecordFieldShape(errors, statement, record, "commands", "string_list");
120
+ validateRecordFieldShape(errors, statement, record, "expects", "string_list");
121
+ validateRecordFieldShape(errors, statement, record, "after", "symbol_list");
122
+ validateRecordFieldShape(errors, statement, record, "notes", "string");
123
+
124
+ const stepId = recordSymbol(record, "id");
125
+ if (!stepId) continue;
126
+ if (!/^[a-z][a-z0-9_]*$/.test(stepId)) {
127
+ pushError(errors, `Journey ${statement.id} step id must match /^[a-z][a-z0-9_]*$/`, recordField(record, "id")?.loc || field.loc);
128
+ }
129
+ if (stepIds.has(stepId)) {
130
+ pushError(errors, `Journey ${statement.id} has duplicate step '${stepId}'`, recordField(record, "id")?.loc || field.loc);
131
+ }
132
+ stepIds.add(stepId);
133
+ }
134
+
135
+ for (const field of fields) {
136
+ if (field.value.type !== "block") continue;
137
+ const record = parseRecordBlock(/** @type {import("../../parser.js").AstBlock} */ (/** @type {unknown} */ (field.value)));
138
+ const stepId = recordSymbol(record, "id") || "unknown";
139
+ for (const afterId of recordSymbolList(record, "after")) {
140
+ if (!stepIds.has(afterId)) {
141
+ pushError(errors, `Journey ${statement.id} step '${stepId}' after references missing step '${afterId}'`, recordField(record, "after")?.loc || field.loc);
142
+ }
143
+ }
144
+ }
145
+
146
+ return stepIds;
147
+ }
148
+
149
+ /**
150
+ * @param {ValidationErrors} errors
151
+ * @param {TopogramStatement} statement
152
+ * @param {TopogramFieldMap} fieldMap
153
+ * @param {Set<string>} stepIds
154
+ * @returns {void}
155
+ */
156
+ function validateAlternateRecords(errors, statement, fieldMap, stepIds) {
157
+ const fields = fieldMap.get("alternate") || [];
158
+ /** @type {Set<string>} */
159
+ const alternateIds = new Set();
160
+ for (const field of fields) {
161
+ const record = validateRecordBlock(errors, statement, field, ALTERNATE_FIELDS, ["id", "from", "condition"]);
162
+ if (!record) continue;
163
+ validateRecordFieldShape(errors, statement, record, "id", "symbol");
164
+ validateRecordFieldShape(errors, statement, record, "from", "symbol");
165
+ validateRecordFieldShape(errors, statement, record, "condition", "string");
166
+ validateRecordFieldShape(errors, statement, record, "commands", "string_list");
167
+ validateRecordFieldShape(errors, statement, record, "expects", "string_list");
168
+ validateRecordFieldShape(errors, statement, record, "notes", "string");
169
+
170
+ const alternateId = recordSymbol(record, "id");
171
+ if (alternateId) {
172
+ if (!/^[a-z][a-z0-9_]*$/.test(alternateId)) {
173
+ pushError(errors, `Journey ${statement.id} alternate id must match /^[a-z][a-z0-9_]*$/`, recordField(record, "id")?.loc || field.loc);
174
+ }
175
+ if (alternateIds.has(alternateId)) {
176
+ pushError(errors, `Journey ${statement.id} has duplicate alternate '${alternateId}'`, recordField(record, "id")?.loc || field.loc);
177
+ }
178
+ alternateIds.add(alternateId);
179
+ }
180
+
181
+ const fromStep = recordSymbol(record, "from");
182
+ if (fromStep && !stepIds.has(fromStep)) {
183
+ pushError(errors, `Journey ${statement.id} alternate '${alternateId || "unknown"}' from references missing step '${fromStep}'`, recordField(record, "from")?.loc || field.loc);
184
+ }
185
+ }
186
+ }
187
+
188
+ /**
189
+ * @param {ValidationErrors} errors
190
+ * @param {TopogramStatement} statement
191
+ * @param {TopogramFieldMap} fieldMap
192
+ * @returns {void}
193
+ */
194
+ function validateTopLevelListShapes(errors, statement, fieldMap) {
195
+ const stringListFields = ["success_signals", "failure_signals", "tags"];
196
+ for (const key of stringListFields) {
197
+ const field = fieldMap.get(key)?.[0];
198
+ if (!field || field.value.type !== "list") continue;
199
+ for (const item of field.value.items) {
200
+ if (item.type !== "string" && key !== "tags") {
201
+ pushError(errors, `Journey ${statement.id} field '${key}' must contain strings`, item.loc);
202
+ }
203
+ if (key === "tags" && item.type !== "symbol" && item.type !== "string") {
204
+ pushError(errors, `Journey ${statement.id} field '${key}' must contain symbols or strings`, item.loc);
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Keep referenced imports used by checkJs while making the expected record
212
+ * helper vocabulary obvious to future validators.
213
+ */
214
+ void recordString;
215
+ void recordStringList;
216
+
217
+ /**
218
+ * @param {ValidationErrors} errors
219
+ * @param {TopogramStatement} statement
220
+ * @param {TopogramFieldMap} fieldMap
221
+ * @param {TopogramRegistry} registry
222
+ * @returns {void}
223
+ */
224
+ export function validateJourney(errors, statement, fieldMap, registry) {
225
+ void registry;
226
+ if (statement.kind !== "journey") {
227
+ return;
228
+ }
229
+ validateJourneyIdentifier(errors, statement);
230
+ validateTopLevelListShapes(errors, statement, fieldMap);
231
+ const stepIds = validateStepRecords(errors, statement, fieldMap);
232
+ validateAlternateRecords(errors, statement, fieldMap, stepIds);
233
+ }
@@ -215,7 +215,10 @@ export function generateDocsWorkflow(inputPath) {
215
215
  export function generateJourneyDraftsWorkflow(inputPath) {
216
216
  const paths = normalizeWorkspacePaths(inputPath);
217
217
  const graph = loadResolvedGraph(paths.topogramRoot);
218
- const canonicalJourneys = (graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey");
218
+ const canonicalJourneys = [
219
+ ...(graph.byKind?.journey || []),
220
+ ...(graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey")
221
+ ];
219
222
  const { drafts, skippedEntities } = buildJourneyDraftsReconcile(graph);
220
223
  /** @type {WorkflowFiles} */
221
224
  /** @type {WorkflowFiles} */
@@ -62,9 +62,11 @@ export function bundleLabelFromConceptId(conceptId) {
62
62
  /** @param {ResolvedGraph} graph @returns {any} */
63
63
  export function canonicalJourneyCoverage(graph) {
64
64
  const journeyDocs = (graph?.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey");
65
+ const journeyStatements = graph?.byKind?.journey || [];
66
+ const journeys = [...journeyStatements, ...journeyDocs];
65
67
  return {
66
- byEntityId: new Set(journeyDocs.flatMap((/** @type {any} */ doc) => doc.relatedEntities || [])),
67
- byCapabilityId: new Set(journeyDocs.flatMap((/** @type {any} */ doc) => doc.relatedCapabilities || []))
68
+ byEntityId: new Set(journeys.flatMap((/** @type {any} */ journey) => journey.relatedEntities || [])),
69
+ byCapabilityId: new Set(journeys.flatMap((/** @type {any} */ journey) => journey.relatedCapabilities || []))
68
70
  };
69
71
  }
70
72
 
@@ -133,7 +133,10 @@ export function collectCanonicalWorkflowSurface(graph) {
133
133
 
134
134
  /** @param {ResolvedGraph} graph @returns {any} */
135
135
  export function collectCanonicalActorRoleSurface(graph) {
136
- const journeyDocs = (graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey");
136
+ const journeyDocs = [
137
+ ...(graph.byKind?.journey || []),
138
+ ...(graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey")
139
+ ];
137
140
  const workflowDocs = (graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "workflow");
138
141
  return {
139
142
  actor_ids: ((graph.byKind.actor || []).map((/** @type {any} */ entry) => entry.id)).sort(),
@@ -1,94 +0,0 @@
1
- // @ts-check
2
-
3
- import path from "node:path";
4
-
5
- import { resolveCatalogTemplateAlias } from "../catalog-alias.js";
6
- import { GENERATOR_POLICY_FILE } from "../../generator-policy.js";
7
- import { createNewProject } from "../../new-project.js";
8
-
9
- const ENGINE_ROOT = path.resolve(decodeURIComponent(new URL("../../../", import.meta.url).pathname));
10
- const TEMPLATES_ROOT = path.join(ENGINE_ROOT, "templates");
11
-
12
- /**
13
- * @param {ReturnType<typeof createNewProject>} result
14
- * @param {string} cwd
15
- * @returns {string}
16
- */
17
- function displayProjectRootForNewProject(result, cwd) {
18
- const relativeProjectRoot = path.relative(cwd, result.projectRoot);
19
- return !relativeProjectRoot || relativeProjectRoot.startsWith("..")
20
- ? result.projectRoot
21
- : relativeProjectRoot;
22
- }
23
-
24
- /**
25
- * @param {ReturnType<typeof createNewProject>} result
26
- * @param {string} cwd
27
- * @returns {void}
28
- */
29
- export function printNewProjectResult(result, cwd) {
30
- const template = result.template || {};
31
- console.log(`Created Topogram project at ${result.projectRoot}.`);
32
- console.log(`Template: ${result.templateName}`);
33
- console.log(`Source: ${template.source || "unknown"}`);
34
- if (template.sourceSpec) {
35
- console.log(`Source spec: ${template.sourceSpec}`);
36
- }
37
- if (template.catalog) {
38
- console.log(`Catalog: ${template.catalog.id} from ${template.catalog.source}`);
39
- console.log(`Package: ${template.catalog.packageSpec}`);
40
- }
41
- console.log(`Executable implementation: ${template.includesExecutableImplementation ? "yes" : "no"}`);
42
- console.log("Policy: topogram.template-policy.json");
43
- console.log(`Generator policy: ${GENERATOR_POLICY_FILE}`);
44
- console.log("Template files: .topogram-template-files.json");
45
- if (template.includesExecutableImplementation) {
46
- console.log("Trust: .topogram-template-trust.json");
47
- }
48
- for (const warning of result.warnings) {
49
- console.warn(`Warning: ${warning}`);
50
- }
51
- console.log("");
52
- console.log("Next steps:");
53
- console.log(` cd ${displayProjectRootForNewProject(result, cwd)}`);
54
- console.log(" npm install");
55
- console.log(" npm run agent:brief");
56
- console.log(" npm run doctor");
57
- console.log(" npm run source:status");
58
- console.log(" npm run template:explain");
59
- console.log(" npm run check");
60
- console.log(" npm run generator:policy:status");
61
- console.log(" npm run generator:policy:check");
62
- if (template.includesExecutableImplementation) {
63
- console.log(" npm run template:policy:explain");
64
- console.log(" npm run trust:status");
65
- }
66
- console.log(" npm run generate");
67
- console.log(" npm run verify");
68
- }
69
-
70
- /**
71
- * @param {string} inputPath
72
- * @param {{ templateName: string, catalogSource?: string|null, cwd?: string }} options
73
- * @returns {number}
74
- */
75
- export function runNewProjectCommand(inputPath, options) {
76
- const cwd = options.cwd || process.cwd();
77
- const projectRoot = path.resolve(inputPath);
78
- const relativeToEngine = path.relative(ENGINE_ROOT, projectRoot);
79
- if (relativeToEngine === "" || (!relativeToEngine.startsWith("..") && !path.isAbsolute(relativeToEngine))) {
80
- throw new Error(
81
- `Refusing to create a generated project inside the engine directory. Use a path outside engine, for example '../${path.basename(projectRoot)}'.`
82
- );
83
- }
84
- const resolvedTemplate = resolveCatalogTemplateAlias(options.templateName, options.catalogSource || null);
85
- const result = createNewProject({
86
- targetPath: inputPath,
87
- templateName: resolvedTemplate.templateName,
88
- templateProvenance: resolvedTemplate.provenance,
89
- engineRoot: ENGINE_ROOT,
90
- templatesRoot: TEMPLATES_ROOT
91
- });
92
- printNewProjectResult(result, cwd);
93
- return 0;
94
- }