@lumenflow/cli 4.24.0 → 5.0.0

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 (294) 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 +10 -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/.turbo/turbo-build.log +1 -1
  154. package/packs/agent-runtime/.turbo/turbo-test.log +25 -0
  155. package/packs/agent-runtime/.turbo/turbo-typecheck.log +4 -0
  156. package/packs/agent-runtime/agent-heartbeat.ts +163 -0
  157. package/packs/agent-runtime/auto-session-integration.ts +874 -0
  158. package/packs/agent-runtime/delegation-registry-schema.ts +220 -0
  159. package/packs/agent-runtime/delegation-registry-store.ts +269 -0
  160. package/packs/agent-runtime/delegation-tree.ts +328 -0
  161. package/packs/agent-runtime/index.ts +9 -0
  162. package/packs/agent-runtime/manifest.ts +103 -19
  163. package/packs/agent-runtime/manifest.yaml +132 -0
  164. package/packs/agent-runtime/memory-coordination-contract.ts +86 -0
  165. package/packs/agent-runtime/memory.d.ts +19 -0
  166. package/packs/agent-runtime/orchestration.ts +238 -23
  167. package/packs/agent-runtime/package.json +11 -2
  168. package/packs/agent-runtime/remote-controls/index.ts +7 -0
  169. package/packs/agent-runtime/remote-controls/operations.ts +399 -0
  170. package/packs/agent-runtime/remote-controls/port.ts +48 -0
  171. package/packs/agent-runtime/remote-controls/state-store.ts +258 -0
  172. package/packs/agent-runtime/remote-controls/types.ts +105 -0
  173. package/packs/agent-runtime/session-schema.ts +423 -0
  174. package/packs/agent-runtime/tool-impl/index.ts +1 -0
  175. package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +252 -0
  176. package/packs/agent-runtime/tool-impl/remote-controls.ts +273 -0
  177. package/packs/agent-runtime/tsconfig.json +1 -1
  178. package/packs/agent-runtime/turn-lifecycle-events.ts +501 -0
  179. package/packs/sidekick/.lumenflow/state/conductor/outbox/sidekick-events.jsonl +213 -0
  180. package/packs/sidekick/.turbo/turbo-build.log +1 -1
  181. package/packs/sidekick/.turbo/turbo-test.log +25 -0
  182. package/packs/sidekick/.turbo/turbo-typecheck.log +4 -0
  183. package/packs/sidekick/channel-ingress.ts +137 -0
  184. package/packs/sidekick/manifest.ts +74 -0
  185. package/packs/sidekick/manifest.yaml +88 -0
  186. package/packs/sidekick/package.json +3 -1
  187. package/packs/sidekick/sidekick-events.ts +517 -0
  188. package/packs/sidekick/src/adapters/cloud-queue.ts +101 -0
  189. package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +378 -0
  190. package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +224 -0
  191. package/packs/sidekick/src/domain/channel.types.ts +84 -0
  192. package/packs/sidekick/src/ports/channel-bridge.port.ts +75 -0
  193. package/packs/sidekick/src/routines/commit.ts +74 -0
  194. package/packs/sidekick/tool-impl/channel-tools.ts +47 -0
  195. package/packs/sidekick/tool-impl/memory-tools.ts +17 -0
  196. package/packs/sidekick/tool-impl/routine-commit.ts +102 -0
  197. package/packs/sidekick/tool-impl/routine-tools.ts +67 -7
  198. package/packs/sidekick/tool-impl/runtime-context.ts +4 -0
  199. package/packs/sidekick/tool-impl/storage.ts +3 -0
  200. package/packs/sidekick/tool-impl/system-tools.ts +7 -0
  201. package/packs/sidekick/tool-impl/task-tools.ts +46 -0
  202. package/packs/sidekick/tsconfig.json +1 -1
  203. package/packs/software-delivery/.turbo/turbo-build.log +1 -1
  204. package/packs/software-delivery/.turbo/turbo-test.log +63 -0
  205. package/packs/software-delivery/.turbo/turbo-typecheck.log +4 -0
  206. package/packs/software-delivery/manifest-schema.ts +30 -0
  207. package/packs/software-delivery/manifest.ts +99 -1
  208. package/packs/software-delivery/manifest.yaml +46 -0
  209. package/packs/software-delivery/package.json +88 -3
  210. package/packs/software-delivery/src/commands/index.ts +5 -0
  211. package/packs/software-delivery/src/config/delivery-review-contract.ts +20 -0
  212. package/packs/software-delivery/src/config/env-accessors.ts +19 -0
  213. package/packs/software-delivery/src/config/index.ts +8 -0
  214. package/packs/software-delivery/src/config/normalize-config-keys.ts +19 -0
  215. package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +436 -0
  216. package/packs/software-delivery/src/config/workspace-reader.ts +310 -0
  217. package/packs/software-delivery/src/constants/backlog-patterns.ts +31 -0
  218. package/packs/software-delivery/src/constants/client-ids.ts +19 -0
  219. package/packs/software-delivery/src/constants/config-contract.ts +7 -0
  220. package/packs/software-delivery/src/constants/docs-layout-presets.ts +50 -0
  221. package/packs/software-delivery/src/constants/duration-constants.ts +20 -0
  222. package/packs/software-delivery/src/constants/gate-constants.ts +32 -0
  223. package/packs/software-delivery/src/constants/index.ts +29 -0
  224. package/packs/software-delivery/src/constants/lock-constants.ts +35 -0
  225. package/packs/software-delivery/src/constants/object-guards.ts +12 -0
  226. package/packs/software-delivery/src/constants/section-headings.ts +107 -0
  227. package/packs/software-delivery/src/constants/wu-cli-constants.ts +485 -0
  228. package/packs/software-delivery/src/constants/wu-domain-constants.ts +466 -0
  229. package/packs/software-delivery/src/constants/wu-git-constants.ts +7 -0
  230. package/packs/software-delivery/src/constants/wu-id-format.ts +327 -0
  231. package/packs/software-delivery/src/constants/wu-paths-constants.ts +358 -0
  232. package/packs/software-delivery/src/constants/wu-statuses.ts +287 -0
  233. package/packs/software-delivery/src/constants/wu-type-helpers.ts +67 -0
  234. package/packs/software-delivery/src/constants/wu-ui-constants.ts +267 -0
  235. package/packs/software-delivery/src/constants/wu-validation-constants.ts +73 -0
  236. package/packs/software-delivery/src/domain/index.ts +5 -0
  237. package/packs/software-delivery/src/domain/orchestration.constants.ts +168 -0
  238. package/packs/software-delivery/src/domain/orchestration.schemas.ts +239 -0
  239. package/packs/software-delivery/src/domain/orchestration.types.ts +178 -0
  240. package/packs/software-delivery/src/methodology/incremental-test.ts +90 -0
  241. package/packs/software-delivery/src/methodology/index.ts +6 -0
  242. package/packs/software-delivery/src/methodology/manual-test-validator.ts +292 -0
  243. package/packs/software-delivery/src/policy/coverage-gate.ts +270 -0
  244. package/packs/software-delivery/src/policy/gates-agent-mode.ts +223 -0
  245. package/packs/software-delivery/src/policy/gates-config-internal.ts +121 -0
  246. package/packs/software-delivery/src/policy/gates-config.ts +293 -0
  247. package/packs/software-delivery/src/policy/gates-coverage.ts +247 -0
  248. package/packs/software-delivery/src/policy/gates-presets.ts +134 -0
  249. package/packs/software-delivery/src/policy/gates-schemas.ts +173 -0
  250. package/packs/software-delivery/src/policy/index.ts +22 -0
  251. package/packs/software-delivery/src/policy/package-manager-resolver.ts +319 -0
  252. package/packs/software-delivery/src/policy/resolve-policy.ts +518 -0
  253. package/packs/software-delivery/src/ports/config.ports.ts +90 -0
  254. package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +125 -0
  255. package/packs/software-delivery/src/ports/index.ts +10 -0
  256. package/packs/software-delivery/src/ports/sync-validator.ports.ts +59 -0
  257. package/packs/software-delivery/src/ports/wu-helpers.ports.ts +168 -0
  258. package/packs/software-delivery/src/ports/wu-state.ports.ts +241 -0
  259. package/packs/software-delivery/src/primitives/index.ts +5 -0
  260. package/packs/software-delivery/src/runtime/index.ts +6 -0
  261. package/packs/software-delivery/src/runtime/work-classifier.ts +561 -0
  262. package/packs/software-delivery/src/sandbox/index.ts +10 -0
  263. package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +118 -0
  264. package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +88 -0
  265. package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +154 -0
  266. package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +47 -0
  267. package/packs/software-delivery/src/sandbox/sandbox-profile.ts +153 -0
  268. package/packs/software-delivery/src/schemas/index.ts +5 -0
  269. package/packs/software-delivery/src/state/date-utils.ts +158 -0
  270. package/packs/software-delivery/src/state/index.ts +15 -0
  271. package/packs/software-delivery/src/state/state-machine.ts +119 -0
  272. package/packs/software-delivery/src/state/wu-doc-types.ts +51 -0
  273. package/packs/software-delivery/src/state/wu-paths.ts +381 -0
  274. package/packs/software-delivery/src/state/wu-schema.ts +1139 -0
  275. package/packs/software-delivery/src/state/wu-state-schema.ts +255 -0
  276. package/packs/software-delivery/src/state/wu-yaml.ts +338 -0
  277. package/packs/software-delivery/src/types.d.ts +16 -0
  278. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +18 -0
  279. package/packs/software-delivery/tsconfig.json +28 -2
  280. package/templates/core/AGENTS.md.template +76 -17
  281. package/templates/core/LUMENFLOW.md.template +265 -66
  282. package/templates/core/_frameworks/lumenflow/wu-sizing-guide.md.template +180 -116
  283. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +26 -8
  284. package/templates/core/ai/onboarding/existing-project-bootstrap.md.template +171 -0
  285. package/templates/core/ai/onboarding/first-15-mins.md.template +3 -1
  286. package/templates/core/ai/onboarding/first-wu-mistakes.md.template +1 -1
  287. package/templates/core/ai/onboarding/initiative-orchestration.md.template +46 -30
  288. package/templates/core/ai/onboarding/quick-ref-commands.md.template +36 -33
  289. package/templates/core/ai/onboarding/release-process.md.template +8 -7
  290. package/templates/core/ai/onboarding/starting-prompt.md.template +2 -0
  291. package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +62 -0
  292. package/templates/vendors/claude/.claude/CLAUDE.md.template +29 -54
  293. package/templates/vendors/cursor/.cursor/rules/lumenflow.md.template +24 -52
  294. package/templates/vendors/windsurf/.windsurf/rules/lumenflow.md.template +24 -52
@@ -0,0 +1,137 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ /**
5
+ * WU-2731 (INIT-060 phase 3, ADR-013 §5 Identity):
6
+ * Pure inbound-channel ingress sanitizer.
7
+ *
8
+ * ADR-013 §5 rules, enforced here:
9
+ *
10
+ * - The authoritative `from` value for an inbound phone POST comes from the
11
+ * authenticated token subject (`{workspace_id}:phone:{device_id}`). Cloud
12
+ * MUST NOT trust a `from` field supplied in the request body.
13
+ *
14
+ * - Body-supplied `from` (and any alias under `metadata.from`) is stripped
15
+ * before the envelope reaches domain code. The surface that calls this
16
+ * module is expected to pass the resolved `from` separately; attempting to
17
+ * ingest a body-only envelope (no authoritative from) fails closed.
18
+ *
19
+ * The module is HTTP-independent: both the kernel tool-api surface and the
20
+ * future control-plane adapter (WU-2737) call the same sanitizer so the
21
+ * ignore-body-from rule is enforced in one place.
22
+ */
23
+
24
+ const ENVELOPE_BODY_FIELD_FROM = 'from' as const;
25
+ const ENVELOPE_METADATA_KEY = 'metadata' as const;
26
+ const ENVELOPE_FROM_SOURCE_TOKEN = 'token' as const;
27
+
28
+ export interface PhoneChannelIngressInput {
29
+ /**
30
+ * Raw request body as parsed from JSON. Opaque record; the sanitizer does
31
+ * not inspect `body`, only the `from` attribution fields.
32
+ */
33
+ body: Readonly<Record<string, unknown>>;
34
+ /**
35
+ * Authoritative identity claim resolved from the bearer token. Required:
36
+ * without a token subject, cloud cannot attribute the message, and the
37
+ * ingress path rejects the request.
38
+ */
39
+ authoritativeFrom: string;
40
+ }
41
+
42
+ export interface PhoneChannelIngressEnvelope {
43
+ /**
44
+ * Sanitised request body with any body-level `from` stripped. Everything
45
+ * else the caller supplied is preserved so downstream code (channel.send,
46
+ * routing) can consume arbitrary payload fields.
47
+ */
48
+ body: Record<string, unknown>;
49
+ /** Authoritative attribution string (`{workspace_id}:phone:{device_id}`). */
50
+ from: string;
51
+ /** Always `'token'` — cloud-safe invariant per ADR-013 §5. */
52
+ from_source: typeof ENVELOPE_FROM_SOURCE_TOKEN;
53
+ }
54
+
55
+ export class PhoneChannelIngressError extends Error {
56
+ readonly statusCode: number;
57
+
58
+ constructor(message: string, statusCode: number) {
59
+ super(message);
60
+ this.name = 'PhoneChannelIngressError';
61
+ this.statusCode = statusCode;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Sanitize an inbound phone-channel request. Returns a cleaned envelope with
67
+ * the authoritative `from` baked in. Throws `PhoneChannelIngressError` (HTTP
68
+ * 400) when the authoritative `from` is missing — the surface translates the
69
+ * error to a 400/403 response.
70
+ */
71
+ export function sanitizePhoneChannelIngress(
72
+ input: PhoneChannelIngressInput,
73
+ ): PhoneChannelIngressEnvelope {
74
+ if (typeof input.authoritativeFrom !== 'string' || input.authoritativeFrom.length === 0) {
75
+ throw new PhoneChannelIngressError(
76
+ 'Inbound phone channel requires authoritative from (token subject); body-only attribution is rejected.',
77
+ 400,
78
+ );
79
+ }
80
+
81
+ const sanitizedBody = stripKey(input.body, ENVELOPE_BODY_FIELD_FROM);
82
+ const rawMetadata = sanitizedBody[ENVELOPE_METADATA_KEY];
83
+ if (
84
+ rawMetadata !== null &&
85
+ typeof rawMetadata === 'object' &&
86
+ !Array.isArray(rawMetadata) &&
87
+ ENVELOPE_BODY_FIELD_FROM in (rawMetadata as Record<string, unknown>)
88
+ ) {
89
+ sanitizedBody[ENVELOPE_METADATA_KEY] = stripKey(
90
+ rawMetadata as Record<string, unknown>,
91
+ ENVELOPE_BODY_FIELD_FROM,
92
+ );
93
+ }
94
+
95
+ return {
96
+ body: sanitizedBody,
97
+ from: input.authoritativeFrom,
98
+ from_source: ENVELOPE_FROM_SOURCE_TOKEN,
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Copy `record` omitting the given key. Implemented with a filtered
104
+ * `Object.entries` rather than `delete` to satisfy the linter's ban on
105
+ * dynamic-delete (which would otherwise be a no-op for literal keys but
106
+ * fails the rule uniformly).
107
+ */
108
+ function stripKey(record: Readonly<Record<string, unknown>>, key: string): Record<string, unknown> {
109
+ const result: Record<string, unknown> = {};
110
+ for (const [entryKey, entryValue] of Object.entries(record)) {
111
+ if (entryKey !== key) {
112
+ result[entryKey] = entryValue;
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * Convenience: reports whether the given `from` subject matches the
120
+ * phone-device grammar (`{workspace_id}:phone:{device_id}`). Useful to
121
+ * tell workspace-scoped actors from phone-device actors in the audit log
122
+ * without reaching for the enrollment parser.
123
+ */
124
+ export function isPhoneSubject(subject: string): boolean {
125
+ const parts = subject.split(':');
126
+ if (parts.length !== 3) {
127
+ return false;
128
+ }
129
+ const [workspace, kind, device] = parts;
130
+ return (
131
+ kind === 'phone' &&
132
+ typeof workspace === 'string' &&
133
+ workspace.length > 0 &&
134
+ typeof device === 'string' &&
135
+ device.length > 0
136
+ );
137
+ }
@@ -16,6 +16,7 @@ import {
16
16
  type PathScope,
17
17
  type ToolPermission,
18
18
  } from './tools/types.js';
19
+ import { SIDEKICK_EVENT_KIND_VALUES } from './sidekick-events.js';
19
20
 
20
21
  // ---------------------------------------------------------------------------
21
22
  // Scope constants
@@ -62,6 +63,10 @@ const TOOL_PERMISSIONS_MAP = {
62
63
  'routine:update': TOOL_PERMISSIONS.WRITE,
63
64
  'routine:delete': TOOL_PERMISSIONS.ADMIN,
64
65
  'routine:run': TOOL_PERMISSIONS.READ, // plan-only, no execution
66
+ // WU-2738 (INIT-060, ADR-013 §6 governance): plan-to-commit flow routed
67
+ // through agent:execute-turn. Runtime-callable tool, no top-level
68
+ // surface -- the governed dispatch is the only path to commit a plan.
69
+ 'sidekick:routine:commit_plan': TOOL_PERMISSIONS.WRITE,
65
70
  // System tools (3)
66
71
  'sidekick:init': TOOL_PERMISSIONS.WRITE,
67
72
  'sidekick:status': TOOL_PERMISSIONS.READ,
@@ -74,6 +79,7 @@ const TASK_TOOLS_ENTRY = 'tool-impl/task-tools.ts';
74
79
  const MEMORY_TOOLS_ENTRY = 'tool-impl/memory-tools.ts';
75
80
  const CHANNEL_TOOLS_ENTRY = 'tool-impl/channel-tools.ts';
76
81
  const ROUTINE_TOOLS_ENTRY = 'tool-impl/routine-tools.ts';
82
+ const ROUTINE_COMMIT_TOOL_ENTRY = 'tool-impl/routine-commit.ts';
77
83
  const SYSTEM_TOOLS_ENTRY = 'tool-impl/system-tools.ts';
78
84
  const POLICY_FACTORY_ENTRY = 'policy-factory.ts#createSidekickPolicyFactory';
79
85
 
@@ -98,6 +104,7 @@ const TOOL_ENTRIES: Record<SidekickToolName, string> = {
98
104
  'routine:update': ROUTINE_TOOLS_ENTRY,
99
105
  'routine:delete': ROUTINE_TOOLS_ENTRY,
100
106
  'routine:run': ROUTINE_TOOLS_ENTRY,
107
+ 'sidekick:routine:commit_plan': ROUTINE_COMMIT_TOOL_ENTRY,
101
108
  'sidekick:init': SYSTEM_TOOLS_ENTRY,
102
109
  'sidekick:status': SYSTEM_TOOLS_ENTRY,
103
110
  'sidekick:export': SYSTEM_TOOLS_ENTRY,
@@ -343,6 +350,23 @@ const TOOL_INPUT_SCHEMAS: Record<SidekickToolName, Record<string, unknown>> = {
343
350
  required: ['id'],
344
351
  additionalProperties: false,
345
352
  },
353
+ 'sidekick:routine:commit_plan': {
354
+ type: 'object',
355
+ properties: {
356
+ plan_id: { type: 'string', minLength: 1 },
357
+ attestation: {
358
+ type: 'object',
359
+ properties: {
360
+ actor: { type: 'string', minLength: 1 },
361
+ reason: { type: 'string', minLength: 1 },
362
+ },
363
+ required: ['actor', 'reason'],
364
+ additionalProperties: true,
365
+ },
366
+ },
367
+ required: ['plan_id', 'attestation'],
368
+ additionalProperties: false,
369
+ },
346
370
  'sidekick:init': {
347
371
  type: 'object',
348
372
  properties: {},
@@ -387,8 +411,17 @@ function resolveRequiredScopes(permission: ToolPermission): PathScope[] {
387
411
  return [SIDEKICK_SCOPE_READ, SIDEKICK_SCOPE_WRITE];
388
412
  }
389
413
 
414
+ // WU-2738 (INIT-060, ADR-013 §6 governance): tool-level approval surface
415
+ // declarations. Empty array means the default policy permits dispatch; a
416
+ // populated array signals the cloud conductor to render an approval prompt
417
+ // before the governed `agent:execute-turn` dispatch invokes the tool.
418
+ const TOOL_REQUIRED_APPROVALS: Partial<Record<SidekickToolName, string[]>> = {
419
+ 'sidekick:routine:commit_plan': [],
420
+ };
421
+
390
422
  function buildTool(name: SidekickToolName): SidekickManifestTool {
391
423
  const permission = TOOL_PERMISSIONS_MAP[name];
424
+ const requiredApprovals = TOOL_REQUIRED_APPROVALS[name];
392
425
  return {
393
426
  name,
394
427
  entry: TOOL_ENTRIES[name],
@@ -396,6 +429,7 @@ function buildTool(name: SidekickToolName): SidekickManifestTool {
396
429
  required_scopes: resolveRequiredScopes(permission),
397
430
  input_schema: TOOL_INPUT_SCHEMAS[name],
398
431
  output_schema: GENERIC_OUTPUT_SCHEMA,
432
+ ...(requiredApprovals !== undefined ? { required_approvals: requiredApprovals } : {}),
399
433
  };
400
434
  }
401
435
 
@@ -405,6 +439,41 @@ function buildTool(name: SidekickToolName): SidekickManifestTool {
405
439
 
406
440
  export const SIDEKICK_TOOL_NAMES = Object.keys(TOOL_PERMISSIONS_MAP) as SidekickToolName[];
407
441
 
442
+ /**
443
+ * WU-2780 (ADR-013 §6 governance): tool names the sidekick pack forbids from
444
+ * the top-level remote surface (POST /tools/:name). These tools remain
445
+ * registered as runtime-callable — `agent:execute-turn` dispatches them via
446
+ * the governed manifest path — but any HTTP allowlist that includes them
447
+ * MUST be rejected fail-closed. ADR-013 §6 explicitly names `channel.send`:
448
+ * "The sidekick pack does NOT expose `channel.send` as a top-level surface
449
+ * the agent can call outside a turn. It is registered only as a
450
+ * runtime-callable tool."
451
+ */
452
+ const ADR_013_SECTION_6_RUNTIME_ONLY_TOOLS: readonly SidekickToolName[] = ['channel:send'] as const;
453
+
454
+ /**
455
+ * WU-2780 (INIT-060, ADR-013 §6): sidekick pack tools that MAY be exposed on
456
+ * the HTTP tool-api surface (POST /tools/:name). Mirrors the
457
+ * `REMOTE_CALLABLE_TOOLS` export pattern in sibling packs (software-delivery,
458
+ * agent-runtime) so integrators have a single source of truth when wiring
459
+ * the surface allowlist. ADR-013 §6 runtime-only tools are excluded by
460
+ * construction; the HTTP tool-api also enforces this fail-closed at router
461
+ * construction.
462
+ */
463
+ export const SIDEKICK_REMOTE_CALLABLE_TOOLS: readonly SidekickToolName[] =
464
+ SIDEKICK_TOOL_NAMES.filter(
465
+ (name): name is SidekickToolName => !ADR_013_SECTION_6_RUNTIME_ONLY_TOOLS.includes(name),
466
+ );
467
+
468
+ /**
469
+ * WU-2780 (INIT-060, ADR-013 §6): returns a fresh copy of the ordered
470
+ * remote-callable tool name list. Keeps the export immutable for callers
471
+ * that prefer arrays over readonly tuples.
472
+ */
473
+ export function getSidekickRemoteCallableToolNames(): SidekickToolName[] {
474
+ return [...SIDEKICK_REMOTE_CALLABLE_TOOLS];
475
+ }
476
+
408
477
  const SIDEKICK_MANIFEST_TEMPLATE = {
409
478
  id: SIDEKICK_PACK_ID,
410
479
  version: SIDEKICK_PACK_VERSION,
@@ -421,8 +490,13 @@ const SIDEKICK_MANIFEST_TEMPLATE = {
421
490
  },
422
491
  ],
423
492
  evidence_types: ['sidekick.audited.tool-call'],
493
+ emitted_event_kinds: [...SIDEKICK_EVENT_KIND_VALUES],
424
494
  state_aliases: {},
425
495
  lane_templates: [],
496
+ // WU-2735 (INIT-060 WU-7a, ADR-013 §ChannelBridge): the sidekick pack
497
+ // requires the `sidekick-channel` transport surface. The kernel refuses
498
+ // to activate the pack if the surface isn't registered at startup.
499
+ surfaces_required: ['sidekick-channel'],
426
500
  };
427
501
 
428
502
  export const SIDEKICK_MANIFEST: SidekickPackManifest = SidekickManifestSchema.parse(
@@ -353,6 +353,13 @@ tools:
353
353
  output_schema:
354
354
  type: object
355
355
  additionalProperties: true
356
+ # WU-2780 (ADR-013 §6 governance): runtime-callable only. `channel.send`
357
+ # MUST route through agent:execute-turn so every phone-directed message
358
+ # becomes an `agent-runtime:tool_called` audit event. The pack manifest
359
+ # registers it here so the kernel can dispatch it from within a turn, but
360
+ # the HTTP tool-api surface (POST /tools/:name) rejects it fail-closed —
361
+ # see SIDEKICK_REMOTE_CALLABLE_TOOLS in manifest.ts and
362
+ # ADR_013_SECTION_6_FORBIDDEN_REMOTE_TOOLS in surfaces/http/tool-api.ts.
356
363
  - name: channel:send
357
364
  entry: tool-impl/channel-tools.ts
358
365
  permission: write
@@ -558,6 +565,44 @@ tools:
558
565
  output_schema:
559
566
  type: object
560
567
  additionalProperties: true
568
+ # WU-2738 (INIT-060, ADR-013 §6 governance): plan-to-commit flow routed
569
+ # through agent:execute-turn. Runtime-callable tool, no top-level
570
+ # surface -- the governed dispatch is the only path to commit a plan.
571
+ # required_approvals is declared (empty) so the cloud conductor treats
572
+ # the tool as approval-aware even when the default policy permits it.
573
+ - name: sidekick:routine:commit_plan
574
+ entry: tool-impl/routine-commit.ts
575
+ permission: write
576
+ required_scopes:
577
+ - type: path
578
+ pattern: .sidekick/**
579
+ access: read
580
+ - type: path
581
+ pattern: .sidekick/**
582
+ access: write
583
+ required_approvals: []
584
+ input_schema:
585
+ type: object
586
+ properties:
587
+ plan_id:
588
+ type: string
589
+ minLength: 1
590
+ attestation:
591
+ type: object
592
+ properties:
593
+ actor:
594
+ type: string
595
+ minLength: 1
596
+ reason:
597
+ type: string
598
+ minLength: 1
599
+ required: [actor, reason]
600
+ additionalProperties: true
601
+ required: [plan_id, attestation]
602
+ additionalProperties: false
603
+ output_schema:
604
+ type: object
605
+ additionalProperties: true
561
606
  - name: sidekick:init
562
607
  entry: tool-impl/system-tools.ts
563
608
  permission: write
@@ -612,5 +657,48 @@ policies:
612
657
  reason: Default sidekick policy permits declared tools within scoped access.
613
658
  evidence_types:
614
659
  - sidekick.audited.tool-call
660
+ # WU-2734 (INIT-060, ADR-013): sidekick emits 16 namespaced event kinds on the
661
+ # pack channel. Command-style task/routine/bootstrap events use queued replay;
662
+ # memory and channel observations are ephemeral and fail silent without
663
+ # control_plane.org_id.
664
+ emitted_event_kinds:
665
+ - sidekick:task_created
666
+ - sidekick:task_completed
667
+ - sidekick:task_scheduled
668
+ - sidekick:task_snoozed
669
+ - sidekick:memory_stored
670
+ - sidekick:memory_recalled
671
+ - sidekick:memory_forgotten
672
+ - sidekick:channel_message_sent
673
+ - sidekick:channel_message_received
674
+ - sidekick:channel_bridge_connected
675
+ - sidekick:channel_bridge_disconnected
676
+ - sidekick:routine_planned
677
+ - sidekick:routine_committed
678
+ - sidekick:routine_executed
679
+ - sidekick:routine_step_failed
680
+ - sidekick:state_rehydrated
681
+ backpressure_policy:
682
+ sidekick:task_created: queue-with-replay
683
+ sidekick:task_completed: queue-with-replay
684
+ sidekick:task_scheduled: queue-with-replay
685
+ sidekick:task_snoozed: queue-with-replay
686
+ sidekick:memory_stored: ephemeral
687
+ sidekick:memory_recalled: ephemeral
688
+ sidekick:memory_forgotten: ephemeral
689
+ sidekick:channel_message_sent: ephemeral
690
+ sidekick:channel_message_received: ephemeral
691
+ sidekick:channel_bridge_connected: ephemeral
692
+ sidekick:channel_bridge_disconnected: ephemeral
693
+ sidekick:routine_planned: queue-with-replay
694
+ sidekick:routine_committed: queue-with-replay
695
+ sidekick:routine_executed: queue-with-replay
696
+ sidekick:routine_step_failed: queue-with-replay
697
+ sidekick:state_rehydrated: queue-with-replay
615
698
  state_aliases: {}
616
699
  lane_templates: []
700
+ # WU-2735 (INIT-060 WU-7a, ADR-013 §ChannelBridge): the sidekick pack requires
701
+ # the `sidekick-channel` transport surface. The kernel refuses to activate the
702
+ # pack if the surface isn't registered at startup.
703
+ surfaces_required:
704
+ - sidekick-channel
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/packs-sidekick",
3
- "version": "4.24.0",
3
+ "version": "5.0.0",
4
4
  "description": "Sidekick personal assistant pack for LumenFlow — 16 tools for task management, typed memory, channels, routines, and audit",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -24,12 +24,14 @@
24
24
  "type": "module",
25
25
  "exports": {
26
26
  ".": "./dist/index.js",
27
+ "./channel-ingress": "./dist/channel-ingress.js",
27
28
  "./storage": "./dist/tool-impl/storage.js",
28
29
  "./tools": "./dist/tools/index.js",
29
30
  "./tool-impl": "./dist/tool-impl/index.js",
30
31
  "./tool-impl/channel-transports": "./dist/tool-impl/channel-transports.js",
31
32
  "./tool-impl/channel-tools": "./dist/tool-impl/channel-tools.js",
32
33
  "./tool-impl/memory-tools": "./dist/tool-impl/memory-tools.js",
34
+ "./tool-impl/routine-commit": "./dist/tool-impl/routine-commit.js",
33
35
  "./tool-impl/routine-tools": "./dist/tool-impl/routine-tools.js",
34
36
  "./tool-impl/shared": "./dist/tool-impl/shared.js",
35
37
  "./tool-impl/storage": "./dist/tool-impl/storage.js",