@lumenflow/cli 4.24.0 → 5.0.1

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 (287) hide show
  1. package/README.md +54 -52
  2. package/dist/agent-issues-query.js +10 -2
  3. package/dist/agent-issues-query.js.map +1 -1
  4. package/dist/agent-runtime-enrollment-events.js +44 -0
  5. package/dist/agent-runtime-enrollment-events.js.map +1 -0
  6. package/dist/agent-session-end.js +47 -0
  7. package/dist/agent-session-end.js.map +1 -1
  8. package/dist/agent-session-heartbeat.js +250 -0
  9. package/dist/agent-session-heartbeat.js.map +1 -0
  10. package/dist/agent-session.js +299 -5
  11. package/dist/agent-session.js.map +1 -1
  12. package/dist/capacity-snapshot-emitter.js +73 -0
  13. package/dist/capacity-snapshot-emitter.js.map +1 -0
  14. package/dist/claim-queue.js +276 -0
  15. package/dist/claim-queue.js.map +1 -0
  16. package/dist/config-set.js +22 -3
  17. package/dist/config-set.js.map +1 -1
  18. package/dist/control-plane-sidecar-runner.js +145 -0
  19. package/dist/control-plane-sidecar-runner.js.map +1 -0
  20. package/dist/delegation-list.js +160 -1
  21. package/dist/delegation-list.js.map +1 -1
  22. package/dist/delegation-role-resolver.js +69 -0
  23. package/dist/delegation-role-resolver.js.map +1 -0
  24. package/dist/docs-generate-pack-reference.js +500 -0
  25. package/dist/docs-generate-pack-reference.js.map +1 -0
  26. package/dist/docs-sync.js +116 -1
  27. package/dist/docs-sync.js.map +1 -1
  28. package/dist/file-edit.js +28 -8
  29. package/dist/file-edit.js.map +1 -1
  30. package/dist/file-write.js +29 -5
  31. package/dist/file-write.js.map +1 -1
  32. package/dist/gate-co-change.js +25 -7
  33. package/dist/gate-co-change.js.map +1 -1
  34. package/dist/gate-conditional.js +19 -7
  35. package/dist/gate-conditional.js.map +1 -1
  36. package/dist/gates-runners.js +42 -33
  37. package/dist/gates-runners.js.map +1 -1
  38. package/dist/gates-utils.js +34 -20
  39. package/dist/gates-utils.js.map +1 -1
  40. package/dist/gates.js +79 -7
  41. package/dist/gates.js.map +1 -1
  42. package/dist/hooks/config-resolver.js +10 -1
  43. package/dist/hooks/config-resolver.js.map +1 -1
  44. package/dist/init-package-config.js +1 -1
  45. package/dist/init-package-config.js.map +1 -1
  46. package/dist/init-scaffolding.js +5 -1
  47. package/dist/init-scaffolding.js.map +1 -1
  48. package/dist/init-templates.js +10 -0
  49. package/dist/init-templates.js.map +1 -1
  50. package/dist/init.js +1 -1
  51. package/dist/init.js.map +1 -1
  52. package/dist/initiative-create.js +17 -0
  53. package/dist/initiative-create.js.map +1 -1
  54. package/dist/initiative-remove-wu.js +17 -3
  55. package/dist/initiative-remove-wu.js.map +1 -1
  56. package/dist/kernel-event-sync/emitters.js +104 -0
  57. package/dist/kernel-event-sync/emitters.js.map +1 -0
  58. package/dist/kernel-event-sync/index.js +13 -0
  59. package/dist/kernel-event-sync/index.js.map +1 -0
  60. package/dist/kernel-event-sync/lifecycle-emitters.js +160 -0
  61. package/dist/kernel-event-sync/lifecycle-emitters.js.map +1 -0
  62. package/dist/kernel-event-sync/narrow-emissions.js +89 -0
  63. package/dist/kernel-event-sync/narrow-emissions.js.map +1 -0
  64. package/dist/kernel-event-sync/software-delivery-emitters.js +297 -0
  65. package/dist/kernel-event-sync/software-delivery-emitters.js.map +1 -0
  66. package/dist/lane-lock.js +14 -1
  67. package/dist/lane-lock.js.map +1 -1
  68. package/dist/lane-suggest.js +21 -0
  69. package/dist/lane-suggest.js.map +1 -1
  70. package/dist/lumenflow-upgrade.js +7 -5
  71. package/dist/lumenflow-upgrade.js.map +1 -1
  72. package/dist/mem-context.js +145 -0
  73. package/dist/mem-context.js.map +1 -1
  74. package/dist/mem-create.js +39 -6
  75. package/dist/mem-create.js.map +1 -1
  76. package/dist/mem-inbox.js +16 -0
  77. package/dist/mem-inbox.js.map +1 -1
  78. package/dist/mem-roster.js +95 -0
  79. package/dist/mem-roster.js.map +1 -0
  80. package/dist/mem-signal.js +97 -2
  81. package/dist/mem-signal.js.map +1 -1
  82. package/dist/metrics-snapshot.js +3 -2
  83. package/dist/metrics-snapshot.js.map +1 -1
  84. package/dist/orchestrate-init-status.js +117 -2
  85. package/dist/orchestrate-init-status.js.map +1 -1
  86. package/dist/orchestrate-initiative.js +83 -10
  87. package/dist/orchestrate-initiative.js.map +1 -1
  88. package/dist/orchestrate-monitor-quality.js +289 -0
  89. package/dist/orchestrate-monitor-quality.js.map +1 -0
  90. package/dist/orchestrate-monitor.js +85 -0
  91. package/dist/orchestrate-monitor.js.map +1 -1
  92. package/dist/pack-validate.js +127 -2
  93. package/dist/pack-validate.js.map +1 -1
  94. package/dist/plan-create.js +18 -0
  95. package/dist/plan-create.js.map +1 -1
  96. package/dist/plan-link.js +13 -0
  97. package/dist/plan-link.js.map +1 -1
  98. package/dist/plan-promote.js +14 -0
  99. package/dist/plan-promote.js.map +1 -1
  100. package/dist/pre-commit-check.js +4 -3
  101. package/dist/pre-commit-check.js.map +1 -1
  102. package/dist/public-manifest.js +17 -3
  103. package/dist/public-manifest.js.map +1 -1
  104. package/dist/release.js +28 -10
  105. package/dist/release.js.map +1 -1
  106. package/dist/session-cross-link.js +139 -0
  107. package/dist/session-cross-link.js.map +1 -0
  108. package/dist/sidecar-manager.js +208 -0
  109. package/dist/sidecar-manager.js.map +1 -0
  110. package/dist/state-path-resolvers.js +18 -0
  111. package/dist/state-path-resolvers.js.map +1 -1
  112. package/dist/stream-heartbeat.js +151 -0
  113. package/dist/stream-heartbeat.js.map +1 -0
  114. package/dist/sync-templates.js +56 -2
  115. package/dist/sync-templates.js.map +1 -1
  116. package/dist/wu-block.js +47 -5
  117. package/dist/wu-block.js.map +1 -1
  118. package/dist/wu-claim-branch.js +8 -4
  119. package/dist/wu-claim-branch.js.map +1 -1
  120. package/dist/wu-claim-state.js +5 -3
  121. package/dist/wu-claim-state.js.map +1 -1
  122. package/dist/wu-claim-worktree.js +5 -3
  123. package/dist/wu-claim-worktree.js.map +1 -1
  124. package/dist/wu-claim.js +261 -9
  125. package/dist/wu-claim.js.map +1 -1
  126. package/dist/wu-done-auto-cleanup.js +3 -2
  127. package/dist/wu-done-auto-cleanup.js.map +1 -1
  128. package/dist/wu-done-git-ops.js +12 -8
  129. package/dist/wu-done-git-ops.js.map +1 -1
  130. package/dist/wu-done-preflight.js +3 -3
  131. package/dist/wu-done-preflight.js.map +1 -1
  132. package/dist/wu-done.js +46 -10
  133. package/dist/wu-done.js.map +1 -1
  134. package/dist/wu-lifecycle-sync/gate-scope-resolver.js +16 -0
  135. package/dist/wu-lifecycle-sync/gate-scope-resolver.js.map +1 -0
  136. package/dist/wu-lifecycle-sync/kernel-event-sync-shim.js +10 -0
  137. package/dist/wu-lifecycle-sync/kernel-event-sync-shim.js.map +1 -0
  138. package/dist/wu-prep.js +363 -22
  139. package/dist/wu-prep.js.map +1 -1
  140. package/dist/wu-prune.js +68 -27
  141. package/dist/wu-prune.js.map +1 -1
  142. package/dist/wu-release.js +34 -3
  143. package/dist/wu-release.js.map +1 -1
  144. package/dist/wu-review.js +167 -0
  145. package/dist/wu-review.js.map +1 -0
  146. package/dist/wu-spawn-prompt-builders.js +296 -40
  147. package/dist/wu-spawn-prompt-builders.js.map +1 -1
  148. package/dist/wu-spawn-strategy-resolver.js +126 -14
  149. package/dist/wu-spawn-strategy-resolver.js.map +1 -1
  150. package/dist/wu-unblock.js +52 -22
  151. package/dist/wu-unblock.js.map +1 -1
  152. package/package.json +13 -8
  153. package/packs/agent-runtime/agent-heartbeat.ts +163 -0
  154. package/packs/agent-runtime/auto-session-integration.ts +874 -0
  155. package/packs/agent-runtime/delegation-registry-schema.ts +220 -0
  156. package/packs/agent-runtime/delegation-registry-store.ts +269 -0
  157. package/packs/agent-runtime/delegation-tree.ts +328 -0
  158. package/packs/agent-runtime/index.ts +9 -0
  159. package/packs/agent-runtime/manifest.ts +109 -19
  160. package/packs/agent-runtime/manifest.yaml +150 -0
  161. package/packs/agent-runtime/memory-coordination-contract.ts +86 -0
  162. package/packs/agent-runtime/memory.d.ts +19 -0
  163. package/packs/agent-runtime/orchestration.ts +238 -23
  164. package/packs/agent-runtime/package.json +11 -2
  165. package/packs/agent-runtime/remote-controls/index.ts +7 -0
  166. package/packs/agent-runtime/remote-controls/operations.ts +399 -0
  167. package/packs/agent-runtime/remote-controls/port.ts +48 -0
  168. package/packs/agent-runtime/remote-controls/state-store.ts +258 -0
  169. package/packs/agent-runtime/remote-controls/types.ts +105 -0
  170. package/packs/agent-runtime/session-schema.ts +423 -0
  171. package/packs/agent-runtime/tool-impl/index.ts +1 -0
  172. package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +252 -0
  173. package/packs/agent-runtime/tool-impl/remote-controls.ts +273 -0
  174. package/packs/agent-runtime/tsconfig.json +1 -1
  175. package/packs/agent-runtime/turn-lifecycle-events.ts +501 -0
  176. package/packs/sidekick/channel-ingress.ts +137 -0
  177. package/packs/sidekick/manifest.ts +74 -0
  178. package/packs/sidekick/manifest.yaml +88 -0
  179. package/packs/sidekick/package.json +3 -1
  180. package/packs/sidekick/sidekick-events.ts +517 -0
  181. package/packs/sidekick/src/adapters/cloud-queue.ts +101 -0
  182. package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +378 -0
  183. package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +224 -0
  184. package/packs/sidekick/src/domain/channel.types.ts +84 -0
  185. package/packs/sidekick/src/ports/channel-bridge.port.ts +75 -0
  186. package/packs/sidekick/src/routines/commit.ts +74 -0
  187. package/packs/sidekick/tool-impl/channel-tools.ts +47 -0
  188. package/packs/sidekick/tool-impl/memory-tools.ts +17 -0
  189. package/packs/sidekick/tool-impl/routine-commit.ts +102 -0
  190. package/packs/sidekick/tool-impl/routine-tools.ts +67 -7
  191. package/packs/sidekick/tool-impl/runtime-context.ts +4 -0
  192. package/packs/sidekick/tool-impl/storage.ts +3 -0
  193. package/packs/sidekick/tool-impl/system-tools.ts +7 -0
  194. package/packs/sidekick/tool-impl/task-tools.ts +46 -0
  195. package/packs/sidekick/tsconfig.json +1 -1
  196. package/packs/software-delivery/manifest-schema.ts +30 -0
  197. package/packs/software-delivery/manifest.ts +160 -11
  198. package/packs/software-delivery/manifest.yaml +210 -230
  199. package/packs/software-delivery/package.json +88 -3
  200. package/packs/software-delivery/src/commands/index.ts +5 -0
  201. package/packs/software-delivery/src/config/delivery-review-contract.ts +20 -0
  202. package/packs/software-delivery/src/config/env-accessors.ts +19 -0
  203. package/packs/software-delivery/src/config/index.ts +8 -0
  204. package/packs/software-delivery/src/config/normalize-config-keys.ts +19 -0
  205. package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +436 -0
  206. package/packs/software-delivery/src/config/workspace-reader.ts +310 -0
  207. package/packs/software-delivery/src/constants/backlog-patterns.ts +31 -0
  208. package/packs/software-delivery/src/constants/client-ids.ts +19 -0
  209. package/packs/software-delivery/src/constants/config-contract.ts +7 -0
  210. package/packs/software-delivery/src/constants/docs-layout-presets.ts +50 -0
  211. package/packs/software-delivery/src/constants/duration-constants.ts +20 -0
  212. package/packs/software-delivery/src/constants/gate-constants.ts +32 -0
  213. package/packs/software-delivery/src/constants/index.ts +29 -0
  214. package/packs/software-delivery/src/constants/lock-constants.ts +35 -0
  215. package/packs/software-delivery/src/constants/object-guards.ts +12 -0
  216. package/packs/software-delivery/src/constants/section-headings.ts +107 -0
  217. package/packs/software-delivery/src/constants/wu-cli-constants.ts +485 -0
  218. package/packs/software-delivery/src/constants/wu-domain-constants.ts +466 -0
  219. package/packs/software-delivery/src/constants/wu-git-constants.ts +7 -0
  220. package/packs/software-delivery/src/constants/wu-id-format.ts +327 -0
  221. package/packs/software-delivery/src/constants/wu-paths-constants.ts +358 -0
  222. package/packs/software-delivery/src/constants/wu-statuses.ts +287 -0
  223. package/packs/software-delivery/src/constants/wu-type-helpers.ts +67 -0
  224. package/packs/software-delivery/src/constants/wu-ui-constants.ts +267 -0
  225. package/packs/software-delivery/src/constants/wu-validation-constants.ts +73 -0
  226. package/packs/software-delivery/src/domain/index.ts +5 -0
  227. package/packs/software-delivery/src/domain/orchestration.constants.ts +168 -0
  228. package/packs/software-delivery/src/domain/orchestration.schemas.ts +239 -0
  229. package/packs/software-delivery/src/domain/orchestration.types.ts +178 -0
  230. package/packs/software-delivery/src/methodology/incremental-test.ts +90 -0
  231. package/packs/software-delivery/src/methodology/index.ts +6 -0
  232. package/packs/software-delivery/src/methodology/manual-test-validator.ts +292 -0
  233. package/packs/software-delivery/src/policy/coverage-gate.ts +270 -0
  234. package/packs/software-delivery/src/policy/gates-agent-mode.ts +223 -0
  235. package/packs/software-delivery/src/policy/gates-config-internal.ts +121 -0
  236. package/packs/software-delivery/src/policy/gates-config.ts +293 -0
  237. package/packs/software-delivery/src/policy/gates-coverage.ts +247 -0
  238. package/packs/software-delivery/src/policy/gates-presets.ts +134 -0
  239. package/packs/software-delivery/src/policy/gates-schemas.ts +173 -0
  240. package/packs/software-delivery/src/policy/index.ts +22 -0
  241. package/packs/software-delivery/src/policy/package-manager-resolver.ts +319 -0
  242. package/packs/software-delivery/src/policy/resolve-policy.ts +518 -0
  243. package/packs/software-delivery/src/ports/config.ports.ts +90 -0
  244. package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +125 -0
  245. package/packs/software-delivery/src/ports/index.ts +10 -0
  246. package/packs/software-delivery/src/ports/sync-validator.ports.ts +59 -0
  247. package/packs/software-delivery/src/ports/wu-helpers.ports.ts +168 -0
  248. package/packs/software-delivery/src/ports/wu-state.ports.ts +241 -0
  249. package/packs/software-delivery/src/primitives/index.ts +5 -0
  250. package/packs/software-delivery/src/runtime/index.ts +6 -0
  251. package/packs/software-delivery/src/runtime/work-classifier.ts +561 -0
  252. package/packs/software-delivery/src/sandbox/index.ts +10 -0
  253. package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +118 -0
  254. package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +88 -0
  255. package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +154 -0
  256. package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +47 -0
  257. package/packs/software-delivery/src/sandbox/sandbox-profile.ts +153 -0
  258. package/packs/software-delivery/src/schemas/index.ts +5 -0
  259. package/packs/software-delivery/src/state/date-utils.ts +158 -0
  260. package/packs/software-delivery/src/state/index.ts +15 -0
  261. package/packs/software-delivery/src/state/state-machine.ts +119 -0
  262. package/packs/software-delivery/src/state/wu-doc-types.ts +51 -0
  263. package/packs/software-delivery/src/state/wu-paths.ts +381 -0
  264. package/packs/software-delivery/src/state/wu-schema.ts +1139 -0
  265. package/packs/software-delivery/src/state/wu-state-schema.ts +255 -0
  266. package/packs/software-delivery/src/state/wu-yaml.ts +338 -0
  267. package/packs/software-delivery/src/types.d.ts +16 -0
  268. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +18 -0
  269. package/packs/software-delivery/tsconfig.json +28 -2
  270. package/templates/core/AGENTS.md.template +76 -17
  271. package/templates/core/LUMENFLOW.md.template +265 -66
  272. package/templates/core/_frameworks/lumenflow/wu-sizing-guide.md.template +180 -116
  273. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +26 -8
  274. package/templates/core/ai/onboarding/existing-project-bootstrap.md.template +171 -0
  275. package/templates/core/ai/onboarding/first-15-mins.md.template +3 -1
  276. package/templates/core/ai/onboarding/first-wu-mistakes.md.template +1 -1
  277. package/templates/core/ai/onboarding/initiative-orchestration.md.template +46 -30
  278. package/templates/core/ai/onboarding/quick-ref-commands.md.template +36 -33
  279. package/templates/core/ai/onboarding/release-process.md.template +8 -7
  280. package/templates/core/ai/onboarding/starting-prompt.md.template +2 -0
  281. package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +62 -0
  282. package/templates/vendors/claude/.claude/CLAUDE.md.template +29 -54
  283. package/templates/vendors/cursor/.cursor/rules/lumenflow.md.template +24 -52
  284. package/templates/vendors/windsurf/.windsurf/rules/lumenflow.md.template +24 -52
  285. package/packs/agent-runtime/.turbo/turbo-build.log +0 -4
  286. package/packs/sidekick/.turbo/turbo-build.log +0 -4
  287. package/packs/software-delivery/.turbo/turbo-build.log +0 -4
@@ -18,6 +18,13 @@ import {
18
18
  type ToolContextLike,
19
19
  type ToolOutput,
20
20
  } from './shared.js';
21
+ import {
22
+ buildTaskCompletedEvent,
23
+ buildTaskCreatedEvent,
24
+ buildTaskScheduledEvent,
25
+ buildTaskSnoozedEvent,
26
+ emitSidekickEvent,
27
+ } from '../sidekick-events.js';
21
28
 
22
29
  // ---------------------------------------------------------------------------
23
30
  // Constants
@@ -97,6 +104,16 @@ function buildCanceledTask(task: TaskRecord): TaskRecord {
97
104
  };
98
105
  }
99
106
 
107
+ function movedDueDateLater(
108
+ previousDueAt: string | undefined,
109
+ nextDueAt: string | undefined,
110
+ ): boolean {
111
+ if (!previousDueAt || !nextDueAt) {
112
+ return false;
113
+ }
114
+ return Date.parse(nextDueAt) > Date.parse(previousDueAt);
115
+ }
116
+
100
117
  // ---------------------------------------------------------------------------
101
118
  // task:create
102
119
  // ---------------------------------------------------------------------------
@@ -140,6 +157,8 @@ async function taskCreateTool(input: unknown, context?: ToolContextLike): Promis
140
157
  );
141
158
  });
142
159
 
160
+ await emitSidekickEvent(buildTaskCreatedEvent(task));
161
+
143
162
  return success({ task: task as unknown as Record<string, unknown> });
144
163
  }
145
164
 
@@ -234,6 +253,8 @@ async function taskUpdateTool(input: unknown, context?: ToolContextLike): Promis
234
253
  });
235
254
  }
236
255
 
256
+ const previousDueAt = task.due_at ?? null;
257
+
237
258
  await storage.withLock(async () => {
238
259
  const latest = await storage.readStore('tasks');
239
260
  const target = latest.find((entry) => entry.id === id);
@@ -254,6 +275,15 @@ async function taskUpdateTool(input: unknown, context?: ToolContextLike): Promis
254
275
 
255
276
  const updated = await storage.readStore('tasks');
256
277
  const updatedTask = updated.find((entry) => entry.id === id);
278
+ if (updatedTask && movedDueDateLater(previousDueAt ?? undefined, updatedTask.due_at)) {
279
+ await emitSidekickEvent(
280
+ buildTaskSnoozedEvent({
281
+ task_id: id,
282
+ previous_due_at: previousDueAt,
283
+ due_at: updatedTask.due_at ?? previousDueAt ?? '',
284
+ }),
285
+ );
286
+ }
257
287
  return success({ task: updatedTask as unknown as Record<string, unknown> });
258
288
  }
259
289
 
@@ -309,6 +339,9 @@ async function taskCompleteTool(input: unknown, context?: ToolContextLike): Prom
309
339
 
310
340
  const updated = await storage.readStore('tasks');
311
341
  const completedTask = updated.find((t) => t.id === id);
342
+ if (completedTask) {
343
+ await emitSidekickEvent(buildTaskCompletedEvent(completedTask));
344
+ }
312
345
 
313
346
  return success({ task: completedTask as unknown as Record<string, unknown> });
314
347
  }
@@ -391,6 +424,7 @@ async function taskScheduleTool(input: unknown, context?: ToolContextLike): Prom
391
424
 
392
425
  const dueAt = asNonEmptyString(parsed.due_at);
393
426
  const cron = asNonEmptyString(parsed.cron);
427
+ const previousDueAt = task.due_at ?? null;
394
428
 
395
429
  if (isDryRun(parsed)) {
396
430
  const preview = {
@@ -429,6 +463,18 @@ async function taskScheduleTool(input: unknown, context?: ToolContextLike): Prom
429
463
 
430
464
  const updated = await storage.readStore('tasks');
431
465
  const scheduledTask = updated.find((t) => t.id === id);
466
+ if (scheduledTask) {
467
+ await emitSidekickEvent(buildTaskScheduledEvent(scheduledTask));
468
+ if (movedDueDateLater(previousDueAt ?? undefined, scheduledTask.due_at)) {
469
+ await emitSidekickEvent(
470
+ buildTaskSnoozedEvent({
471
+ task_id: id,
472
+ previous_due_at: previousDueAt,
473
+ due_at: scheduledTask.due_at ?? previousDueAt ?? '',
474
+ }),
475
+ );
476
+ }
477
+ }
432
478
 
433
479
  return success({ task: scheduledTask as unknown as Record<string, unknown> });
434
480
  }
@@ -15,6 +15,6 @@
15
15
  "checkJs": false,
16
16
  "noEmitOnError": true
17
17
  },
18
- "include": ["*.ts", "tools/**/*.ts", "tool-impl/**/*.ts"],
18
+ "include": ["*.ts", "tools/**/*.ts", "tool-impl/**/*.ts", "src/**/*.ts"],
19
19
  "exclude": ["node_modules", "dist", "__tests__"]
20
20
  }
@@ -37,6 +37,13 @@ export interface SoftwareDeliveryManifestTool {
37
37
  permission: ToolPermission;
38
38
  required_scopes: PathScope[];
39
39
  internal_only?: boolean;
40
+ /**
41
+ * WU-2729 (INIT-060 Phase 2, ADR-013 §3): approval-surface identifiers the
42
+ * tool must present to callers before runtime dispatch. Empty array means
43
+ * no approval gate; undefined means the tool does not declare approval
44
+ * metadata (treated the same as empty by the discovery surface).
45
+ */
46
+ required_approvals?: string[];
40
47
  }
41
48
 
42
49
  export interface SoftwareDeliveryManifestPolicy {
@@ -57,6 +64,11 @@ export interface SoftwareDeliveryPackManifest {
57
64
  evidence_types: string[];
58
65
  state_aliases: Record<string, string>;
59
66
  lane_templates: Array<{ id: string }>;
67
+ /** WU-2718 (INIT-060 WU-1, ADR-013). */
68
+ emitted_event_kinds: string[];
69
+ subscribed_event_kinds: string[];
70
+ required_approvals: string[];
71
+ surfaces_required: string[];
60
72
  }
61
73
 
62
74
  function asRecord(input: unknown, label: string): Record<string, unknown> {
@@ -166,6 +178,12 @@ function parseTool(input: unknown, index: number): SoftwareDeliveryManifestTool
166
178
  throw new Error(`tools[${index}].permission is invalid.`);
167
179
  }
168
180
 
181
+ // WU-2729: optional per-tool required_approvals list.
182
+ const parsedApprovals =
183
+ tool.required_approvals === undefined
184
+ ? undefined
185
+ : parseStringArray(tool.required_approvals, `tools[${index}].required_approvals`);
186
+
169
187
  return {
170
188
  name: parseNonEmptyString(tool.name, `tools[${index}].name`),
171
189
  entry: parseNonEmptyString(tool.entry, `tools[${index}].entry`),
@@ -180,6 +198,7 @@ function parseTool(input: unknown, index: number): SoftwareDeliveryManifestTool
180
198
  }
181
199
  return tool.internal_only;
182
200
  })(),
201
+ ...(parsedApprovals === undefined ? {} : { required_approvals: parsedApprovals }),
183
202
  };
184
203
  }
185
204
 
@@ -233,6 +252,17 @@ export const SoftwareDeliveryManifestSchema: Parser<SoftwareDeliveryPackManifest
233
252
  const entry = asRecord(laneTemplate, `lane_templates[${index}]`);
234
253
  return { id: parseNonEmptyString(entry.id, `lane_templates[${index}].id`) };
235
254
  }),
255
+ // WU-2718 (INIT-060 WU-1, ADR-013): manifest extension fields.
256
+ emitted_event_kinds: parseStringArray(
257
+ manifest.emitted_event_kinds ?? [],
258
+ 'emitted_event_kinds',
259
+ ),
260
+ subscribed_event_kinds: parseStringArray(
261
+ manifest.subscribed_event_kinds ?? [],
262
+ 'subscribed_event_kinds',
263
+ ),
264
+ required_approvals: parseStringArray(manifest.required_approvals ?? [], 'required_approvals'),
265
+ surfaces_required: parseStringArray(manifest.surfaces_required ?? [], 'surfaces_required'),
236
266
  };
237
267
  },
238
268
  };
@@ -31,6 +31,51 @@ export type {
31
31
  } from './manifest-schema.js';
32
32
 
33
33
  const FULL_WORKSPACE_SCOPE_PATTERN = '**';
34
+ const SOFTWARE_DELIVERY_WRITE_DIRECTORY_PATTERNS = [
35
+ '.changeset/**',
36
+ '.claude/**',
37
+ '.codex/**',
38
+ '.cursor/**',
39
+ '.github/**',
40
+ '.git/**',
41
+ '.husky/**',
42
+ '.lumenflow/**',
43
+ '.vercel/**',
44
+ '.windsurf/**',
45
+ 'apps/**',
46
+ 'docs/**',
47
+ 'packages/**',
48
+ 'scripts/**',
49
+ 'tools/**',
50
+ 'worktrees/**',
51
+ ] as const;
52
+ const SOFTWARE_DELIVERY_ROOT_WRITE_FILE_PATTERNS = [
53
+ '.gitignore',
54
+ '.npmrc',
55
+ 'LUMENFLOW.md',
56
+ 'README.md',
57
+ 'package.json',
58
+ 'pnpm-lock.yaml',
59
+ 'pnpm-workspace.yaml',
60
+ 'turbo.json',
61
+ 'workspace.yaml',
62
+ '*.cjs',
63
+ '*.js',
64
+ '*.json',
65
+ '*.md',
66
+ '*.mjs',
67
+ '*.sh',
68
+ '*.toml',
69
+ '*.ts',
70
+ '*.tsx',
71
+ '*.txt',
72
+ '*.yaml',
73
+ '*.yml',
74
+ ] as const;
75
+ const SOFTWARE_DELIVERY_WRITE_SCOPE_PATTERNS = [
76
+ ...SOFTWARE_DELIVERY_WRITE_DIRECTORY_PATTERNS,
77
+ ...SOFTWARE_DELIVERY_ROOT_WRITE_FILE_PATTERNS,
78
+ ] as const;
34
79
  const GIT_STATUS_TOOL_ENTRY = 'tool-impl/git-tools.ts#gitStatusTool';
35
80
  const WU_STATUS_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#wuStatusTool';
36
81
  const WU_CREATE_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#wuCreateTool';
@@ -55,6 +100,10 @@ const WU_RELEASE_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#wuReleaseTool';
55
100
  const WU_RECOVER_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#wuRecoverTool';
56
101
  const WU_REPAIR_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#wuRepairTool';
57
102
  const GATES_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#gatesTool';
103
+ // WU-2729 (INIT-060 Phase 2): gates:docs exposes docs-only gate runs via a
104
+ // dedicated manifest entry so remote callers can request the docs gate
105
+ // without opting into the permissive gates handler surface.
106
+ const GATES_DOCS_TOOL_ENTRY = 'tool-impl/wu-lifecycle-tools.ts#gatesDocsTool';
58
107
  const CONFIG_SET_TOOL_ENTRY = 'tool-impl/runtime-native-tools.ts#configSetTool';
59
108
  const CONFIG_GET_TOOL_ENTRY = 'tool-impl/runtime-native-tools.ts#configGetTool';
60
109
  const MEM_INIT_TOOL_ENTRY = 'tool-impl/memory-tools.ts#memInitTool';
@@ -193,6 +242,7 @@ const TOOL_PERMISSIONS = {
193
242
  'flow:bottlenecks': 'read',
194
243
  'flow:report': 'read',
195
244
  gates: 'write',
245
+ 'gates:docs': 'write',
196
246
  'file:delete': 'write',
197
247
  'file:edit': 'write',
198
248
  'file:read': 'read',
@@ -272,6 +322,7 @@ const TOOL_ENTRY_OVERRIDES: Partial<Record<ToolName, string>> = {
272
322
  'wu:repair': WU_REPAIR_TOOL_ENTRY,
273
323
  'wu:infer-lane': WU_INFER_LANE_TOOL_ENTRY,
274
324
  gates: GATES_TOOL_ENTRY,
325
+ 'gates:docs': GATES_DOCS_TOOL_ENTRY,
275
326
  'mem:init': MEM_INIT_TOOL_ENTRY,
276
327
  'mem:start': MEM_START_TOOL_ENTRY,
277
328
  'mem:ready': MEM_READY_TOOL_ENTRY,
@@ -348,28 +399,104 @@ export interface SoftwareDeliveryMigrationScorecard {
348
399
  realHandlerEntries: number;
349
400
  }
350
401
 
402
+ function createPathScopes(
403
+ patterns: readonly string[],
404
+ access: (typeof TOOL_SCOPE_ACCESS)[keyof typeof TOOL_SCOPE_ACCESS],
405
+ ): PathScope[] {
406
+ return patterns.map((pattern) => ({
407
+ type: TOOL_SCOPE_TYPES.PATH,
408
+ pattern,
409
+ access,
410
+ }));
411
+ }
412
+
351
413
  function requiredScopesForPermission(permission: ToolPermission): PathScope[] {
352
- return [
353
- {
354
- type: TOOL_SCOPE_TYPES.PATH,
355
- pattern: FULL_WORKSPACE_SCOPE_PATTERN,
356
- access:
357
- permission === TOOL_PERMISSION_VALUES.READ
358
- ? TOOL_SCOPE_ACCESS.READ
359
- : TOOL_SCOPE_ACCESS.WRITE,
360
- },
361
- ];
414
+ if (permission === TOOL_PERMISSION_VALUES.READ) {
415
+ return createPathScopes([FULL_WORKSPACE_SCOPE_PATTERN], TOOL_SCOPE_ACCESS.READ);
416
+ }
417
+
418
+ return createPathScopes(SOFTWARE_DELIVERY_WRITE_SCOPE_PATTERNS, TOOL_SCOPE_ACCESS.WRITE);
419
+ }
420
+
421
+ /**
422
+ * WU-2729 (INIT-060 Phase 2): the 10 software-delivery pack tools that are
423
+ * callable remotely via POST /tools/:name. The HTTP surface uses this list
424
+ * to build its allowlist so the set is the single source of truth (no
425
+ * duplicate allowlist in surface code). ADR-013 §3 tool exposure.
426
+ */
427
+ export const REMOTE_CALLABLE_TOOLS = [
428
+ 'gates',
429
+ 'gates:docs',
430
+ 'lane:suggest',
431
+ 'lane:health',
432
+ 'plan:create',
433
+ 'plan:promote',
434
+ 'initiative:create',
435
+ 'initiative:add-wu',
436
+ 'initiative:status',
437
+ 'flow:report',
438
+ ] as const satisfies readonly ToolName[];
439
+
440
+ export type RemoteCallableToolName = (typeof REMOTE_CALLABLE_TOOLS)[number];
441
+
442
+ /**
443
+ * Well-known approval identifiers the software-delivery pack may request.
444
+ * Kept narrow on purpose; adding a new identifier requires an ADR.
445
+ */
446
+ export const SOFTWARE_DELIVERY_APPROVAL_IDS = {
447
+ REMOTE_MUTATION: 'software-delivery:remote_mutation',
448
+ } as const;
449
+
450
+ /**
451
+ * WU-2729 (INIT-060 Phase 2): per-tool required_approvals overrides.
452
+ * Tools absent from this table default to `[]` (no approval required).
453
+ * Read-only tools MUST remain at `[]`; state-mutating remote-callable
454
+ * tools SHOULD request an explicit approval identifier so the conductor
455
+ * UI can surface the approval gate to operators.
456
+ */
457
+ const APPROVAL_OVERRIDES: Partial<Record<ToolName, readonly string[]>> = {
458
+ 'lane:suggest': [SOFTWARE_DELIVERY_APPROVAL_IDS.REMOTE_MUTATION],
459
+ 'plan:create': [SOFTWARE_DELIVERY_APPROVAL_IDS.REMOTE_MUTATION],
460
+ 'plan:promote': [SOFTWARE_DELIVERY_APPROVAL_IDS.REMOTE_MUTATION],
461
+ 'initiative:create': [SOFTWARE_DELIVERY_APPROVAL_IDS.REMOTE_MUTATION],
462
+ 'initiative:add-wu': [SOFTWARE_DELIVERY_APPROVAL_IDS.REMOTE_MUTATION],
463
+ };
464
+
465
+ function requiredApprovalsForTool(name: ToolName): string[] | undefined {
466
+ // WU-2729: only the 10 remote-callable tools carry explicit
467
+ // required_approvals metadata (even if empty). Other tools leave the
468
+ // field undefined so the manifest stays minimally descriptive.
469
+ const isRemoteCallable = (REMOTE_CALLABLE_TOOLS as readonly string[]).includes(name);
470
+ if (!isRemoteCallable) {
471
+ return undefined;
472
+ }
473
+ const override = APPROVAL_OVERRIDES[name];
474
+ return override ? [...override] : [];
475
+ }
476
+
477
+ /**
478
+ * WU-2729: ordered list of the 10 remote-callable tool names. Preserves
479
+ * declaration order from REMOTE_CALLABLE_TOOLS so callers can render
480
+ * stable UIs without re-sorting.
481
+ */
482
+ export function getRemoteCallableToolNames(): RemoteCallableToolName[] {
483
+ return [...REMOTE_CALLABLE_TOOLS];
362
484
  }
363
485
 
364
486
  function createManifestTools(): SoftwareDeliveryManifestTool[] {
365
487
  return (Object.keys(TOOL_PERMISSIONS) as ToolName[]).map((name) => {
366
488
  const permission = TOOL_PERMISSIONS[name];
367
- return {
489
+ const approvals = requiredApprovalsForTool(name);
490
+ const entry: SoftwareDeliveryManifestTool = {
368
491
  name,
369
492
  entry: resolveToolEntry(name),
370
493
  permission,
371
494
  required_scopes: requiredScopesForPermission(permission),
372
495
  };
496
+ if (approvals !== undefined) {
497
+ entry.required_approvals = approvals;
498
+ }
499
+ return entry;
373
500
  });
374
501
  }
375
502
 
@@ -400,6 +527,24 @@ export function renderSoftwareDeliveryMigrationScorecard(
400
527
  }
401
528
 
402
529
  const POLICY_SUFFIXES = ['format', 'lint', 'typecheck', 'test', 'coverage'] as const;
530
+ const SOFTWARE_DELIVERY_EMITTED_EVENT_KINDS = [
531
+ 'software-delivery:gate_started',
532
+ 'software-delivery:gate_passed',
533
+ 'software-delivery:gate_failed',
534
+ 'software-delivery:co_change_rule_fired',
535
+ 'software-delivery:conditional_command_fired',
536
+ 'software-delivery:lane_wip_breached',
537
+ 'software-delivery:lane_locked',
538
+ 'software-delivery:lane_unlocked',
539
+ 'software-delivery:lane_suggestion_emitted',
540
+ 'software-delivery:initiative_created',
541
+ 'software-delivery:initiative_closed',
542
+ 'software-delivery:initiative_phase_advanced',
543
+ 'software-delivery:plan_created',
544
+ 'software-delivery:plan_linked',
545
+ 'software-delivery:plan_promoted',
546
+ ] as const;
547
+ const SOFTWARE_DELIVERY_REQUIRED_SURFACES = ['http'] as const;
403
548
 
404
549
  export const SOFTWARE_DELIVERY_MANIFEST: SoftwareDeliveryPackManifest = {
405
550
  id: SOFTWARE_DELIVERY_PACK_ID,
@@ -415,4 +560,8 @@ export const SOFTWARE_DELIVERY_MANIFEST: SoftwareDeliveryPackManifest = {
415
560
  evidence_types: ['gate-run'],
416
561
  state_aliases: { active: 'in_progress' },
417
562
  lane_templates: [],
563
+ emitted_event_kinds: [...SOFTWARE_DELIVERY_EMITTED_EVENT_KINDS],
564
+ subscribed_event_kinds: [],
565
+ required_approvals: [],
566
+ surfaces_required: [...SOFTWARE_DELIVERY_REQUIRED_SURFACES],
418
567
  };