@topogram/cli 0.3.64 → 0.3.65

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 (245) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +703 -0
  3. package/src/adoption/plan.js +12 -703
  4. package/src/agent-ops/query-builders/auth.js +375 -0
  5. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  6. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  7. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  8. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  9. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  10. package/src/agent-ops/query-builders/change-risk.js +25 -0
  11. package/src/agent-ops/query-builders/common.js +149 -0
  12. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  13. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  14. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  15. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  16. package/src/agent-ops/query-builders/work-packets.js +417 -0
  17. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  18. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  19. package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
  20. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  21. package/src/agent-ops/query-builders.d.ts +26 -26
  22. package/src/agent-ops/query-builders.js +42 -5021
  23. package/src/catalog/constants.js +10 -0
  24. package/src/catalog/copy.js +60 -0
  25. package/src/catalog/diagnostics.js +15 -0
  26. package/src/catalog/entries.js +42 -0
  27. package/src/catalog/files.js +67 -0
  28. package/src/catalog/provenance.js +122 -0
  29. package/src/catalog/source.js +150 -0
  30. package/src/catalog/validation.js +252 -0
  31. package/src/catalog.d.ts +2 -0
  32. package/src/catalog.js +18 -746
  33. package/src/cli/commands/catalog/check.js +31 -0
  34. package/src/cli/commands/catalog/copy.js +59 -0
  35. package/src/cli/commands/catalog/doctor.js +248 -0
  36. package/src/cli/commands/catalog/help.js +21 -0
  37. package/src/cli/commands/catalog/list.js +52 -0
  38. package/src/cli/commands/catalog/runner.js +92 -0
  39. package/src/cli/commands/catalog/shared.js +17 -0
  40. package/src/cli/commands/catalog/show.js +134 -0
  41. package/src/cli/commands/catalog.js +30 -615
  42. package/src/cli/commands/generator-policy/package-info.js +162 -0
  43. package/src/cli/commands/generator-policy/payloads.js +372 -0
  44. package/src/cli/commands/generator-policy/printers.js +159 -0
  45. package/src/cli/commands/generator-policy/runner.js +81 -0
  46. package/src/cli/commands/generator-policy/shared.js +39 -0
  47. package/src/cli/commands/generator-policy.js +15 -783
  48. package/src/cli/commands/import/adopt.js +170 -0
  49. package/src/cli/commands/import/check.js +91 -0
  50. package/src/cli/commands/import/diff.js +84 -0
  51. package/src/cli/commands/import/help.js +47 -0
  52. package/src/cli/commands/import/paths.js +277 -0
  53. package/src/cli/commands/import/plan.js +284 -0
  54. package/src/cli/commands/import/refresh.js +470 -0
  55. package/src/cli/commands/import/status-history.js +196 -0
  56. package/src/cli/commands/import/workspace.js +230 -0
  57. package/src/cli/commands/import.js +33 -1732
  58. package/src/cli/commands/package/constants.js +17 -0
  59. package/src/cli/commands/package/doctor.js +240 -0
  60. package/src/cli/commands/package/help.js +27 -0
  61. package/src/cli/commands/package/lockfile.js +135 -0
  62. package/src/cli/commands/package/npm.js +97 -0
  63. package/src/cli/commands/package/reporting.js +35 -0
  64. package/src/cli/commands/package/runner.js +33 -0
  65. package/src/cli/commands/package/shared.js +9 -0
  66. package/src/cli/commands/package/update-cli.js +252 -0
  67. package/src/cli/commands/package/versions.js +35 -0
  68. package/src/cli/commands/package.js +29 -813
  69. package/src/cli/commands/query/change-plan.js +68 -0
  70. package/src/cli/commands/query/definitions.js +202 -0
  71. package/src/cli/commands/query/import-adopt.js +121 -0
  72. package/src/cli/commands/query/runner/artifacts.js +102 -0
  73. package/src/cli/commands/query/runner/boundaries.js +211 -0
  74. package/src/cli/commands/query/runner/change.js +182 -0
  75. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  76. package/src/cli/commands/query/runner/index.js +31 -0
  77. package/src/cli/commands/query/runner/output.js +12 -0
  78. package/src/cli/commands/query/runner/workflow.js +241 -0
  79. package/src/cli/commands/query/runner.js +3 -0
  80. package/src/cli/commands/query/workflow-context.js +5 -0
  81. package/src/cli/commands/query/workspace.js +274 -0
  82. package/src/cli/commands/query.js +9 -1300
  83. package/src/cli/commands/template/baseline.js +100 -0
  84. package/src/cli/commands/template/check.js +466 -0
  85. package/src/cli/commands/template/constants.js +8 -0
  86. package/src/cli/commands/template/diagnostics.js +26 -0
  87. package/src/cli/commands/template/help.js +28 -0
  88. package/src/cli/commands/template/lifecycle.js +404 -0
  89. package/src/cli/commands/template/list-show.js +287 -0
  90. package/src/cli/commands/template/policy.js +422 -0
  91. package/src/cli/commands/template/shared.js +127 -0
  92. package/src/cli/commands/template/updates.js +352 -0
  93. package/src/cli/commands/template.js +41 -2143
  94. package/src/generator/api/contracts.js +497 -0
  95. package/src/generator/api/metadata.js +221 -0
  96. package/src/generator/api/openapi.js +559 -0
  97. package/src/generator/api/schema.js +124 -0
  98. package/src/generator/api/types.d.ts +98 -0
  99. package/src/generator/api.js +3 -1195
  100. package/src/generator/context/shared/domain-sdlc.js +282 -0
  101. package/src/generator/context/shared/maintained-boundary.js +665 -0
  102. package/src/generator/context/shared/metrics.js +85 -0
  103. package/src/generator/context/shared/primitives.js +64 -0
  104. package/src/generator/context/shared/relationships.js +453 -0
  105. package/src/generator/context/shared/summaries.js +263 -0
  106. package/src/generator/context/shared/types.d.ts +207 -0
  107. package/src/generator/context/shared.d.ts +42 -0
  108. package/src/generator/context/shared.js +80 -1390
  109. package/src/generator/context/slice/core.js +397 -0
  110. package/src/generator/context/slice/sdlc.js +417 -0
  111. package/src/generator/context/slice/ui-packets.js +183 -0
  112. package/src/generator/context/slice.js +2 -859
  113. package/src/generator/registry/index.js +507 -0
  114. package/src/generator/registry.js +18 -504
  115. package/src/generator/runtime/environment/index.js +666 -0
  116. package/src/generator/runtime/environment.js +4 -666
  117. package/src/generator/runtime/runtime-check/index.js +554 -0
  118. package/src/generator/runtime/runtime-check.js +4 -554
  119. package/src/generator/runtime/shared/index.js +572 -0
  120. package/src/generator/runtime/shared.js +19 -570
  121. package/src/generator/shared.d.ts +2 -0
  122. package/src/generator/surfaces/shared.d.ts +3 -0
  123. package/src/generator/widget-conformance/behavior-report.js +258 -0
  124. package/src/generator/widget-conformance/checks.js +371 -0
  125. package/src/generator/widget-conformance/projection-context.js +200 -0
  126. package/src/generator/widget-conformance/report.js +166 -0
  127. package/src/generator/widget-conformance/types.d.ts +121 -0
  128. package/src/generator/widget-conformance.js +3 -824
  129. package/src/import/core/context.d.ts +3 -0
  130. package/src/import/core/contracts.d.ts +1 -0
  131. package/src/import/core/registry.d.ts +4 -0
  132. package/src/import/core/runner/candidates.js +217 -0
  133. package/src/import/core/runner/options.js +22 -0
  134. package/src/import/core/runner/reports.js +50 -0
  135. package/src/import/core/runner/run.js +79 -0
  136. package/src/import/core/runner/tracks.js +150 -0
  137. package/src/import/core/runner/ui-drafts.js +337 -0
  138. package/src/import/core/runner.js +3 -698
  139. package/src/import/core/shared/api-routes.js +221 -0
  140. package/src/import/core/shared/candidates.js +97 -0
  141. package/src/import/core/shared/files.js +177 -0
  142. package/src/import/core/shared/next-app.js +389 -0
  143. package/src/import/core/shared/types.d.ts +51 -0
  144. package/src/import/core/shared/ui-routes.js +230 -0
  145. package/src/import/core/shared.js +60 -861
  146. package/src/new-project/constants.js +128 -0
  147. package/src/new-project/create.js +83 -0
  148. package/src/new-project/json.js +28 -0
  149. package/src/new-project/metadata.js +96 -0
  150. package/src/new-project/package-spec.js +161 -0
  151. package/src/new-project/project-files.js +348 -0
  152. package/src/new-project/template-policy.js +269 -0
  153. package/src/new-project/template-resolution.js +368 -0
  154. package/src/new-project/template-snapshots.js +430 -0
  155. package/src/new-project/template-updates.js +512 -0
  156. package/src/new-project/types.d.ts +83 -0
  157. package/src/new-project.js +6 -2277
  158. package/src/parser.d.ts +87 -1
  159. package/src/parser.js +118 -0
  160. package/src/policy/review-boundaries.d.ts +15 -0
  161. package/src/project-config/index.js +564 -0
  162. package/src/project-config.js +19 -561
  163. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  164. package/src/resolver/enrich/bug.js +2 -0
  165. package/src/resolver/enrich/pitch.js +2 -0
  166. package/src/resolver/enrich/requirement.js +2 -0
  167. package/src/resolver/enrich/task.js +2 -0
  168. package/src/resolver/index.js +19 -2089
  169. package/src/resolver/normalize.js +384 -1
  170. package/src/resolver/plans.js +168 -0
  171. package/src/resolver/projections-api.js +494 -0
  172. package/src/resolver/projections-db.js +133 -0
  173. package/src/resolver/projections-ui.js +317 -0
  174. package/src/resolver/shapes.js +251 -0
  175. package/src/resolver/shared.js +278 -0
  176. package/src/resolver/widgets.js +132 -0
  177. package/src/template-trust/constants.js +62 -0
  178. package/src/template-trust/content.js +258 -0
  179. package/src/template-trust/diff.js +92 -0
  180. package/src/template-trust/policy.js +61 -0
  181. package/src/template-trust/record.js +90 -0
  182. package/src/template-trust/status.js +182 -0
  183. package/src/template-trust.js +24 -687
  184. package/src/text-helpers.d.ts +1 -0
  185. package/src/topogram-types.d.ts +69 -0
  186. package/src/validator/common.js +488 -0
  187. package/src/validator/data-model.js +237 -0
  188. package/src/validator/docs.js +167 -0
  189. package/src/validator/expressions.js +146 -1
  190. package/src/validator/index.d.ts +23 -0
  191. package/src/validator/index.js +32 -3585
  192. package/src/validator/kinds.d.ts +41 -0
  193. package/src/validator/kinds.js +2 -0
  194. package/src/validator/model-helpers.js +46 -0
  195. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  196. package/src/validator/per-kind/bug.js +6 -0
  197. package/src/validator/per-kind/domain.js +15 -2
  198. package/src/validator/per-kind/pitch.js +7 -0
  199. package/src/validator/per-kind/requirement.js +5 -0
  200. package/src/validator/per-kind/task.js +7 -0
  201. package/src/validator/per-kind/widget.js +14 -0
  202. package/src/validator/projections/api-http-async.js +410 -0
  203. package/src/validator/projections/api-http-authz.js +88 -0
  204. package/src/validator/projections/api-http-core.js +205 -0
  205. package/src/validator/projections/api-http-policies.js +339 -0
  206. package/src/validator/projections/api-http-responses.js +233 -0
  207. package/src/validator/projections/api-http.js +44 -0
  208. package/src/validator/projections/db.js +353 -0
  209. package/src/validator/projections/generator-defaults.js +45 -0
  210. package/src/validator/projections/helpers.js +87 -0
  211. package/src/validator/projections/ui-helpers.js +214 -0
  212. package/src/validator/projections/ui-navigation.js +344 -0
  213. package/src/validator/projections/ui-structure.js +364 -0
  214. package/src/validator/projections/ui-widgets.js +493 -0
  215. package/src/validator/projections/ui.js +46 -0
  216. package/src/validator/registry.js +48 -1
  217. package/src/validator/utils.d.ts +20 -0
  218. package/src/validator/utils.js +115 -12
  219. package/src/widget-behavior.d.ts +1 -0
  220. package/src/workflows/import-app/api/collect.js +221 -0
  221. package/src/workflows/import-app/api/openapi.js +257 -0
  222. package/src/workflows/import-app/api/routes.js +327 -0
  223. package/src/workflows/import-app/api/sources.js +22 -0
  224. package/src/workflows/import-app/api.js +2 -797
  225. package/src/workflows/reconcile/adoption-plan/build.js +208 -0
  226. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  227. package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
  228. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  229. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  230. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  231. package/src/workflows/reconcile/adoption-plan.js +30 -740
  232. package/src/workflows/reconcile/auth/closures.js +115 -0
  233. package/src/workflows/reconcile/auth/formatters.js +142 -0
  234. package/src/workflows/reconcile/auth/inference.js +330 -0
  235. package/src/workflows/reconcile/auth/roles.js +122 -0
  236. package/src/workflows/reconcile/auth.js +35 -690
  237. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  238. package/src/workflows/reconcile/bundle-core.js +12 -598
  239. package/src/workflows/reconcile/canonical-surface.js +1 -1
  240. package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
  241. package/src/workflows/reconcile/impacts/indexes.js +101 -0
  242. package/src/workflows/reconcile/impacts/patches.js +252 -0
  243. package/src/workflows/reconcile/impacts/reports.js +80 -0
  244. package/src/workflows/reconcile/impacts.js +14 -623
  245. package/src/workspace-docs.d.ts +29 -0
@@ -0,0 +1,417 @@
1
+ import { buildPresetGuidanceSummary } from "./change-risk.js";
2
+ import { buildAuthReviewPacketPayload } from "./auth.js";
3
+ export function handoffTemplateFromLane(lane, mode) {
4
+ if (!lane) return null;
5
+ return {
6
+ packet_id: lane.publishes?.[0] || `handoff:${lane.lane_id}`,
7
+ from_lane: lane.lane_id,
8
+ to_lane: lane.role === "verification_runner" ? null : lane.role === "adoption_operator" ? "verification_runner" : "adoption_operator",
9
+ status: "pending",
10
+ scope: {
11
+ bundle: lane.bundle || null,
12
+ review_groups: lane.owned_targets?.review_groups || []
13
+ },
14
+ decision_summary: {
15
+ completion_condition: lane.completion_condition || null
16
+ },
17
+ canonical_targets: lane.owned_targets?.canonical_targets || [],
18
+ recommended_next_action: {
19
+ action: lane.role === "adoption_operator"
20
+ ? "run_from_plan_write"
21
+ : lane.role === "verification_runner"
22
+ ? "run_proof_targets"
23
+ : "publish_review_state",
24
+ selector: lane.role === "adoption_operator"
25
+ ? "from-plan"
26
+ : (lane.owned_targets?.review_groups || [])[0] || lane.bundle || null
27
+ },
28
+ blocking_reasons: lane.blocking_dependencies || [],
29
+ proof_expectations: lane.proof_targets || null,
30
+ mode
31
+ };
32
+ }
33
+
34
+ export function joinPointsForLane(multiAgentPlan, laneId) {
35
+ return (multiAgentPlan?.join_points || []).filter((joinPoint) =>
36
+ (joinPoint.requires || []).includes(laneId) ||
37
+ (joinPoint.then_enables || []).includes(laneId)
38
+ );
39
+ }
40
+
41
+ export function serializedGatesForLane(multiAgentPlan, laneId) {
42
+ return (multiAgentPlan?.serialized_gates || []).filter((gate) =>
43
+ gate.owner_lane === laneId || (gate.blocks_until || []).includes(laneId)
44
+ );
45
+ }
46
+
47
+ export function overlapRulesForLane(multiAgentPlan, laneId) {
48
+ return (multiAgentPlan?.overlap_rules || []).filter((rule) => (rule.lanes || []).includes(laneId));
49
+ }
50
+
51
+ export function recommendedStepsForLane(multiAgentPlan, lane, publishedHandoffPacket) {
52
+ const resolvedWorkflowContext = multiAgentPlan?.resolved_workflow_context || null;
53
+ const steps = [
54
+ {
55
+ order: 1,
56
+ action: "read_allowed_inputs",
57
+ reason: "Start from the bounded artifacts assigned to this lane before making any recommendation."
58
+ }
59
+ ];
60
+
61
+ if ((lane.blocking_dependencies || []).length > 0) {
62
+ steps.push({
63
+ order: steps.length + 1,
64
+ action: "wait_for_dependencies",
65
+ reason: `This lane is blocked until ${lane.blocking_dependencies.join(", ")} is satisfied.`,
66
+ blocking_dependencies: lane.blocking_dependencies
67
+ });
68
+ }
69
+
70
+ if (["bundle_reviewer", "auth_reviewer", "mapping_reviewer", "doc_promoter"].includes(lane.role)) {
71
+ if ((resolvedWorkflowContext?.effective_review_policy?.escalate_categories || []).length > 0) {
72
+ steps.push({
73
+ order: steps.length + 1,
74
+ action: "apply_resolved_review_policy",
75
+ reason: `This lane should honor resolved review escalations for ${resolvedWorkflowContext.effective_review_policy.escalate_categories.join(", ")}.`
76
+ });
77
+ }
78
+ steps.push({
79
+ order: steps.length + 1,
80
+ action: "review_scoped_work",
81
+ reason: lane.completion_condition,
82
+ selector: (lane.owned_targets?.review_groups || [])[0] || lane.bundle || null
83
+ });
84
+ steps.push({
85
+ order: steps.length + 1,
86
+ action: "publish_handoff_packet",
87
+ reason: "Publish a structured handoff packet instead of coordinating through freeform messaging.",
88
+ packet_id: publishedHandoffPacket?.packet_id || null
89
+ });
90
+ return steps;
91
+ }
92
+
93
+ if (lane.role === "adoption_operator") {
94
+ steps.push({
95
+ order: steps.length + 1,
96
+ action: "collect_review_packets",
97
+ reason: "Wait for review-oriented lanes to publish their handoff packets before canonical adoption."
98
+ });
99
+ steps.push({
100
+ order: steps.length + 1,
101
+ action: "run_from_plan_write",
102
+ reason: "Canonical adoption stays serialized and single-writer.",
103
+ selector: "from-plan"
104
+ });
105
+ steps.push({
106
+ order: steps.length + 1,
107
+ action: "publish_handoff_packet",
108
+ reason: "Publish canonical adoption completion for the verification lane.",
109
+ packet_id: publishedHandoffPacket?.packet_id || null
110
+ });
111
+ return steps;
112
+ }
113
+
114
+ if (lane.role === "verification_runner") {
115
+ steps.push({
116
+ order: steps.length + 1,
117
+ action: "apply_resolved_verification_policy",
118
+ reason: "Use the embedded resolved workflow context before running lane proof targets.",
119
+ verification_requirements: resolvedWorkflowContext?.effective_verification_policy || null
120
+ });
121
+ steps.push({
122
+ order: steps.length + 1,
123
+ action: "run_proof_targets",
124
+ reason: "Run the attached proof set only after canonical adoption completes.",
125
+ proof_targets: lane.proof_targets || null
126
+ });
127
+ steps.push({
128
+ order: steps.length + 1,
129
+ action: "publish_handoff_packet",
130
+ reason: "Publish verification completion for auditability.",
131
+ packet_id: publishedHandoffPacket?.packet_id || null
132
+ });
133
+ }
134
+
135
+ return steps;
136
+ }
137
+
138
+ export function buildWorkPacketPayload({
139
+ workspace,
140
+ multiAgentPlan,
141
+ laneId
142
+ }) {
143
+ const lane = (multiAgentPlan?.lanes || []).find((entry) => entry.lane_id === laneId);
144
+ if (!lane) {
145
+ throw new Error(`Unknown multi-agent lane '${laneId}'.`);
146
+ }
147
+ const publishedHandoffPacket = (multiAgentPlan?.handoff_packets || []).find((packet) => packet.from_lane === laneId)
148
+ || handoffTemplateFromLane(lane, multiAgentPlan?.mode || null);
149
+ const resolvedWorkflowContext = multiAgentPlan?.resolved_workflow_context || null;
150
+ const presetGuidanceSummary = multiAgentPlan?.preset_guidance_summary || buildPresetGuidanceSummary(null, resolvedWorkflowContext);
151
+ const effectiveWriteScope = lane.workflow_context_overrides?.effective_write_scope || lane.write_scope || resolvedWorkflowContext?.effective_write_scope || null;
152
+ const effectiveVerificationPolicy = lane.workflow_context_overrides?.effective_verification_policy || {
153
+ ...(resolvedWorkflowContext?.effective_verification_policy || {}),
154
+ lane_proof_targets: lane.proof_targets || null
155
+ };
156
+ return {
157
+ type: "work_packet",
158
+ workspace: workspace || null,
159
+ mode: multiAgentPlan?.mode || null,
160
+ lane: {
161
+ lane_id: lane.lane_id,
162
+ role: lane.role,
163
+ bundle: lane.bundle || null
164
+ },
165
+ summary: {
166
+ purpose: lane.purpose,
167
+ canonical_writer: lane.role === "adoption_operator",
168
+ review_lane: ["bundle_reviewer", "auth_reviewer", "mapping_reviewer", "doc_promoter"].includes(lane.role),
169
+ completion_condition: lane.completion_condition || null
170
+ },
171
+ allowed_inputs: lane.allowed_inputs || [],
172
+ preset_guidance_summary: presetGuidanceSummary,
173
+ active_preset_ids: presetGuidanceSummary.active_preset_ids,
174
+ recommended_preset_action: presetGuidanceSummary.recommended_preset_action,
175
+ write_scope: lane.write_scope || null,
176
+ effective_write_scope: effectiveWriteScope,
177
+ owned_targets: lane.owned_targets || null,
178
+ blocking_dependencies: lane.blocking_dependencies || [],
179
+ proof_targets: lane.proof_targets || null,
180
+ effective_verification_policy: effectiveVerificationPolicy,
181
+ required_handoff_packets: (multiAgentPlan?.handoff_packets || []).filter((packet) => packet.to_lane === laneId),
182
+ published_handoff_packet: publishedHandoffPacket,
183
+ overlap_rules: overlapRulesForLane(multiAgentPlan, laneId),
184
+ serialized_gates: serializedGatesForLane(multiAgentPlan, laneId),
185
+ join_points: joinPointsForLane(multiAgentPlan, laneId),
186
+ recommended_steps: recommendedStepsForLane(multiAgentPlan, lane, publishedHandoffPacket),
187
+ resolved_workflow_context: resolvedWorkflowContext
188
+ };
189
+ }
190
+
191
+ export function authReviewPacketForBundle(report, adoptionStatus, bundleSlug) {
192
+ try {
193
+ return buildAuthReviewPacketPayload(report, adoptionStatus, bundleSlug);
194
+ } catch {
195
+ return null;
196
+ }
197
+ }
198
+
199
+ export function bundlePriorityForBundle(adoptionStatus, bundleSlug) {
200
+ return (adoptionStatus?.bundle_priorities || []).find((entry) => entry.bundle === bundleSlug) || null;
201
+ }
202
+
203
+ export function laneStatusRecord(lane, { multiAgentPlan, report, adoptionStatus }) {
204
+ if (lane.role === "bundle_reviewer") {
205
+ const bundlePriority = bundlePriorityForBundle(adoptionStatus, lane.bundle);
206
+ const complete = !bundlePriority || (
207
+ (bundlePriority.next_review_groups || []).length === 0 &&
208
+ !bundlePriority.recommend_bundle_review_selector
209
+ );
210
+ return {
211
+ lane_id: lane.lane_id,
212
+ role: lane.role,
213
+ bundle: lane.bundle || null,
214
+ status: complete ? "complete" : "ready",
215
+ ready_for_handoff: complete,
216
+ blocking_dependencies: [],
217
+ reason: complete
218
+ ? "Bundle review requirements for this bundle appear resolved in the current adoption state."
219
+ : "This bundle still has review-oriented work before canonical adoption."
220
+ };
221
+ }
222
+
223
+ if (lane.role === "auth_reviewer") {
224
+ const packet = authReviewPacketForBundle(report, adoptionStatus, lane.bundle);
225
+ const unresolvedCount = (packet?.unresolved_hints || []).length;
226
+ const deferredCount = (packet?.deferred_hints || []).length;
227
+ const roleFollowupCount = (packet?.auth_role_followup || []).length;
228
+ const complete = unresolvedCount === 0 && deferredCount === 0 && roleFollowupCount === 0;
229
+ return {
230
+ lane_id: lane.lane_id,
231
+ role: lane.role,
232
+ bundle: lane.bundle || null,
233
+ status: complete ? "complete" : "ready",
234
+ ready_for_handoff: complete,
235
+ blocking_dependencies: [],
236
+ reason: complete
237
+ ? "Auth hints and auth-relevant role follow-up are resolved for this bundle."
238
+ : `This bundle still has ${unresolvedCount + deferredCount + roleFollowupCount} auth-sensitive follow-up item(s).`
239
+ };
240
+ }
241
+
242
+ if (lane.role === "mapping_reviewer") {
243
+ const pending = (lane.owned_targets?.canonical_targets || []).length;
244
+ return {
245
+ lane_id: lane.lane_id,
246
+ role: lane.role,
247
+ bundle: null,
248
+ status: pending > 0 ? "ready" : "complete",
249
+ ready_for_handoff: pending === 0,
250
+ blocking_dependencies: [],
251
+ reason: pending > 0
252
+ ? "Mapping/customization-sensitive proposal surfaces still need explicit review."
253
+ : "No mapping-sensitive proposal surfaces remain."
254
+ };
255
+ }
256
+
257
+ if (lane.role === "doc_promoter") {
258
+ const pending = (lane.owned_targets?.canonical_targets || []).length;
259
+ return {
260
+ lane_id: lane.lane_id,
261
+ role: lane.role,
262
+ bundle: null,
263
+ status: pending > 0 ? "ready" : "complete",
264
+ ready_for_handoff: pending === 0,
265
+ blocking_dependencies: [],
266
+ reason: pending > 0
267
+ ? "Documentation-oriented proposal surfaces still need review before promotion."
268
+ : "No documentation promotion work remains."
269
+ };
270
+ }
271
+
272
+ const prereqReviewLanes = (multiAgentPlan?.lanes || [])
273
+ .filter((entry) => !["adoption_operator", "verification_runner"].includes(entry.role));
274
+ const reviewStatuses = prereqReviewLanes.map((entry) => laneStatusRecord(entry, { multiAgentPlan, report, adoptionStatus }));
275
+ const incompleteReviewLanes = reviewStatuses.filter((entry) => entry.status !== "complete");
276
+
277
+ if (lane.role === "adoption_operator") {
278
+ const complete = !adoptionStatus?.next_bundle;
279
+ if (complete) {
280
+ return {
281
+ lane_id: lane.lane_id,
282
+ role: lane.role,
283
+ bundle: null,
284
+ status: "complete",
285
+ ready_for_handoff: true,
286
+ blocking_dependencies: [],
287
+ reason: "Canonical adoption appears complete in the current adoption state."
288
+ };
289
+ }
290
+ return {
291
+ lane_id: lane.lane_id,
292
+ role: lane.role,
293
+ bundle: null,
294
+ status: incompleteReviewLanes.length === 0 ? "ready" : "blocked",
295
+ ready_for_handoff: false,
296
+ blocking_dependencies: incompleteReviewLanes.map((entry) => entry.lane_id),
297
+ reason: incompleteReviewLanes.length === 0
298
+ ? "All review-oriented lanes are resolved, so canonical adoption can proceed."
299
+ : "Canonical adoption remains blocked until review-oriented lanes publish resolved handoff state."
300
+ };
301
+ }
302
+
303
+ if (lane.role === "verification_runner") {
304
+ const adoptionLaneStatus = laneStatusRecord(
305
+ (multiAgentPlan?.lanes || []).find((entry) => entry.role === "adoption_operator"),
306
+ { multiAgentPlan, report, adoptionStatus }
307
+ );
308
+ return {
309
+ lane_id: lane.lane_id,
310
+ role: lane.role,
311
+ bundle: null,
312
+ status: adoptionLaneStatus.status === "complete" ? "ready" : "blocked",
313
+ ready_for_handoff: false,
314
+ blocking_dependencies: adoptionLaneStatus.status === "complete" ? [] : ["adoption_operator"],
315
+ reason: adoptionLaneStatus.status === "complete"
316
+ ? "Merged canonical state is ready for proof."
317
+ : "Verification remains blocked until canonical adoption completes."
318
+ };
319
+ }
320
+
321
+ return {
322
+ lane_id: lane.lane_id,
323
+ role: lane.role,
324
+ bundle: lane.bundle || null,
325
+ status: "ready",
326
+ ready_for_handoff: false,
327
+ blocking_dependencies: lane.blocking_dependencies || [],
328
+ reason: lane.completion_condition || null
329
+ };
330
+ }
331
+
332
+ export function buildLaneStatusPayload({
333
+ workspace,
334
+ multiAgentPlan,
335
+ report,
336
+ adoptionStatus
337
+ }) {
338
+ const lanes = (multiAgentPlan?.lanes || []).map((lane) => laneStatusRecord(lane, {
339
+ multiAgentPlan,
340
+ report,
341
+ adoptionStatus
342
+ }));
343
+ const statusCounts = lanes.reduce((acc, lane) => {
344
+ acc[lane.status] = (acc[lane.status] || 0) + 1;
345
+ return acc;
346
+ }, {});
347
+ const blocked = lanes.filter((lane) => lane.status === "blocked").map((lane) => lane.lane_id);
348
+ const ready = lanes.filter((lane) => lane.status === "ready").map((lane) => lane.lane_id);
349
+ const complete = lanes.filter((lane) => lane.status === "complete").map((lane) => lane.lane_id);
350
+ return {
351
+ type: "lane_status_query",
352
+ workspace: workspace || null,
353
+ mode: multiAgentPlan?.mode || null,
354
+ summary: {
355
+ lane_count: lanes.length,
356
+ status_counts: statusCounts,
357
+ blocked_lanes: blocked,
358
+ ready_lanes: ready,
359
+ complete_lanes: complete
360
+ },
361
+ lanes
362
+ };
363
+ }
364
+
365
+ export function buildHandoffStatusPayload({
366
+ workspace,
367
+ multiAgentPlan,
368
+ report,
369
+ adoptionStatus
370
+ }) {
371
+ const laneStatus = buildLaneStatusPayload({
372
+ workspace,
373
+ multiAgentPlan,
374
+ report,
375
+ adoptionStatus
376
+ });
377
+ const statusByLane = new Map(laneStatus.lanes.map((entry) => [entry.lane_id, entry]));
378
+ const handoffs = (multiAgentPlan?.handoff_packets || []).map((packet) => {
379
+ const lane = statusByLane.get(packet.from_lane);
380
+ const status = lane?.status === "complete"
381
+ ? "published"
382
+ : lane?.status === "blocked"
383
+ ? "blocked"
384
+ : "pending";
385
+ return {
386
+ packet_id: packet.packet_id,
387
+ from_lane: packet.from_lane,
388
+ to_lane: packet.to_lane,
389
+ status,
390
+ blocking_dependencies: lane?.blocking_dependencies || [],
391
+ scope: packet.scope || null,
392
+ canonical_targets: packet.canonical_targets || [],
393
+ reason: status === "published"
394
+ ? "The source lane appears resolved in the current artifact-backed status view."
395
+ : status === "blocked"
396
+ ? "The source lane is still blocked, so this handoff cannot be published yet."
397
+ : "The source lane still has review or execution work before publishing this handoff."
398
+ };
399
+ });
400
+ const statusCounts = handoffs.reduce((acc, handoff) => {
401
+ acc[handoff.status] = (acc[handoff.status] || 0) + 1;
402
+ return acc;
403
+ }, {});
404
+ return {
405
+ type: "handoff_status_query",
406
+ workspace: workspace || null,
407
+ mode: multiAgentPlan?.mode || null,
408
+ summary: {
409
+ handoff_count: handoffs.length,
410
+ status_counts: statusCounts,
411
+ published_packets: handoffs.filter((entry) => entry.status === "published").map((entry) => entry.packet_id),
412
+ pending_packets: handoffs.filter((entry) => entry.status === "pending").map((entry) => entry.packet_id),
413
+ blocked_packets: handoffs.filter((entry) => entry.status === "blocked").map((entry) => entry.packet_id)
414
+ },
415
+ handoffs
416
+ };
417
+ }