@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,247 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ /**
5
+ * Gates Coverage Policy Resolution
6
+ *
7
+ * WU-2037: Extracted from gates-config.ts
8
+ *
9
+ * Resolves coverage configuration and test policy from methodology settings.
10
+ * Uses resolvePolicy() to derive thresholds and modes from workspace.yaml.
11
+ *
12
+ * @module gates-coverage
13
+ */
14
+
15
+ import { asRecord, isBoolean, isNumber } from '../constants/object-guards.js';
16
+ import {
17
+ resolvePolicy,
18
+ getDefaultPolicy,
19
+ MethodologyConfigSchema,
20
+ TddDiffEvidenceConfigSchema,
21
+ TddOrderingConfigSchema,
22
+ type TddDiffEvidenceConfig,
23
+ type TddDiffEvidencePolicy,
24
+ type TddOrderingConfig,
25
+ type TddOrderingPolicy,
26
+ } from './resolve-policy.js';
27
+ import type { CoverageConfig, TestPolicy } from './gates-schemas.js';
28
+ import {
29
+ GATES_RUNTIME_DEFAULTS,
30
+ SOFTWARE_DELIVERY_FIELDS,
31
+ GATES_FIELDS,
32
+ loadSoftwareDeliveryConfig,
33
+ } from './gates-config-internal.js';
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Private helpers for reading typed fields from raw config
37
+ // ---------------------------------------------------------------------------
38
+
39
+ function readNumberField(
40
+ source: Record<string, unknown> | undefined,
41
+ primaryKey: string,
42
+ secondaryKey: string,
43
+ ): number | undefined {
44
+ const primary = source?.[primaryKey];
45
+ if (isNumber(primary)) {
46
+ return primary;
47
+ }
48
+ const secondary = source?.[secondaryKey];
49
+ return isNumber(secondary) ? secondary : undefined;
50
+ }
51
+
52
+ function readBooleanField(
53
+ source: Record<string, unknown> | undefined,
54
+ primaryKey: string,
55
+ secondaryKey: string,
56
+ ): boolean | undefined {
57
+ const primary = source?.[primaryKey];
58
+ if (isBoolean(primary)) {
59
+ return primary;
60
+ }
61
+ const secondary = source?.[secondaryKey];
62
+ return isBoolean(secondary) ? secondary : undefined;
63
+ }
64
+
65
+ function readGateMinCoverage(gatesRaw: Record<string, unknown> | undefined): number | undefined {
66
+ return readNumberField(gatesRaw, GATES_FIELDS.MIN_COVERAGE, GATES_FIELDS.MIN_COVERAGE_SNAKE);
67
+ }
68
+
69
+ function readGateEnableCoverage(
70
+ gatesRaw: Record<string, unknown> | undefined,
71
+ ): boolean | undefined {
72
+ return readBooleanField(
73
+ gatesRaw,
74
+ GATES_FIELDS.ENABLE_COVERAGE,
75
+ GATES_FIELDS.ENABLE_COVERAGE_SNAKE,
76
+ );
77
+ }
78
+
79
+ function readTddDiffEvidenceConfig(
80
+ gatesRaw: Record<string, unknown> | undefined,
81
+ ): TddDiffEvidenceConfig | undefined {
82
+ const raw = asRecord(gatesRaw?.[GATES_FIELDS.TDD_DIFF_EVIDENCE]) ?? undefined;
83
+ return TddDiffEvidenceConfigSchema.optional().parse(raw);
84
+ }
85
+
86
+ function readTddOrderingConfig(
87
+ gatesRaw: Record<string, unknown> | undefined,
88
+ ): TddOrderingConfig | undefined {
89
+ const raw = asRecord(gatesRaw?.[GATES_FIELDS.TDD_ORDERING]) ?? undefined;
90
+ return TddOrderingConfigSchema.optional().parse(raw);
91
+ }
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // Shared policy resolution helper (DRY: used by both public functions)
95
+ // ---------------------------------------------------------------------------
96
+
97
+ function resolvePolicyFromConfig(rawConfig: Record<string, unknown>) {
98
+ const methodologyRaw = asRecord(rawConfig[SOFTWARE_DELIVERY_FIELDS.METHODOLOGY]) ?? undefined;
99
+ const gatesRaw = asRecord(rawConfig[SOFTWARE_DELIVERY_FIELDS.GATES]) ?? undefined;
100
+ const minCoverage = readGateMinCoverage(gatesRaw);
101
+ const enableCoverage = readGateEnableCoverage(gatesRaw);
102
+ const tddDiffEvidence = readTddDiffEvidenceConfig(gatesRaw);
103
+ const tddOrdering = readTddOrderingConfig(gatesRaw);
104
+
105
+ // Parse methodology with Zod to get defaults
106
+ const methodology = MethodologyConfigSchema.parse(methodologyRaw ?? {});
107
+
108
+ // Build the config structure that resolvePolicy expects
109
+ const minimalConfig = {
110
+ methodology: methodologyRaw, // Pass raw methodology for explicit detection
111
+ gates: {
112
+ minCoverage,
113
+ enableCoverage,
114
+ tdd_diff_evidence: tddDiffEvidence,
115
+ tdd_ordering: tddOrdering,
116
+ },
117
+ };
118
+
119
+ // Resolve policy using the methodology configuration
120
+ // Pass rawConfig to detect explicit gates.* settings vs Zod defaults
121
+ return resolvePolicy(
122
+ {
123
+ methodology,
124
+ gates: {
125
+ // Default gates values from schema
126
+ maxEslintWarnings: GATES_RUNTIME_DEFAULTS.MAX_ESLINT_WARNINGS,
127
+ enableCoverage: enableCoverage ?? GATES_RUNTIME_DEFAULTS.DEFAULT_ENABLE_COVERAGE,
128
+ minCoverage: minCoverage ?? GATES_RUNTIME_DEFAULTS.DEFAULT_MIN_COVERAGE,
129
+ enableSafetyCriticalTests: true,
130
+ enableInvariants: true,
131
+ tdd_diff_evidence: tddDiffEvidence,
132
+ tdd_ordering: tddOrdering,
133
+ },
134
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Minimal type for config
135
+ } as unknown as Parameters<typeof resolvePolicy>[0],
136
+ {
137
+ rawConfig: minimalConfig,
138
+ },
139
+ );
140
+ }
141
+
142
+ // ---------------------------------------------------------------------------
143
+ // Public API
144
+ // ---------------------------------------------------------------------------
145
+
146
+ /**
147
+ * WU-1262: Resolve coverage configuration from methodology policy
148
+ *
149
+ * Uses resolvePolicy() to determine coverage defaults based on methodology.testing:
150
+ * - tdd: 90% threshold, block mode
151
+ * - test-after: 70% threshold, warn mode
152
+ * - none: 0% threshold, off mode
153
+ *
154
+ * Precedence (highest to lowest):
155
+ * 1. Explicit gates.minCoverage / gates.enableCoverage
156
+ * 2. methodology.overrides.coverage_threshold / coverage_mode
157
+ * 3. methodology.testing template defaults
158
+ *
159
+ * @param projectRoot - Project root directory
160
+ * @returns Resolved coverage configuration
161
+ */
162
+ export function resolveCoverageConfig(projectRoot: string): CoverageConfig {
163
+ const rawConfig = loadSoftwareDeliveryConfig(projectRoot) ?? {};
164
+
165
+ // If no config file, use default policy
166
+ if (Object.keys(rawConfig).length === 0) {
167
+ const defaultPolicy = getDefaultPolicy();
168
+ return {
169
+ threshold: defaultPolicy.coverage_threshold,
170
+ mode: defaultPolicy.coverage_mode,
171
+ };
172
+ }
173
+
174
+ const policy = resolvePolicyFromConfig(rawConfig);
175
+
176
+ return {
177
+ threshold: policy.coverage_threshold,
178
+ mode: policy.coverage_mode,
179
+ };
180
+ }
181
+
182
+ /**
183
+ * WU-1280: Resolve test policy from methodology configuration
184
+ *
185
+ * Returns the full test policy including coverage config AND tests_required.
186
+ * This is used by gates to determine whether test failures should block or warn.
187
+ *
188
+ * Methodology mapping:
189
+ * - tdd: 90% threshold, block mode, tests_required=true
190
+ * - test-after: 70% threshold, warn mode, tests_required=true
191
+ * - none: 0% threshold, off mode, tests_required=false
192
+ *
193
+ * When tests_required=false:
194
+ * - Test failures produce WARNINGS instead of FAILURES
195
+ * - Gates continue but log the test failures
196
+ * - Coverage gate is effectively skipped (mode='off')
197
+ *
198
+ * @param projectRoot - Project root directory
199
+ * @returns Resolved test policy including tests_required
200
+ */
201
+ export function resolveTestPolicy(projectRoot: string): TestPolicy {
202
+ const rawConfig = loadSoftwareDeliveryConfig(projectRoot) ?? {};
203
+
204
+ // If no config file, use default policy (TDD)
205
+ if (Object.keys(rawConfig).length === 0) {
206
+ const defaultPolicy = getDefaultPolicy();
207
+ return {
208
+ threshold: defaultPolicy.coverage_threshold,
209
+ mode: defaultPolicy.coverage_mode,
210
+ tests_required: defaultPolicy.tests_required,
211
+ };
212
+ }
213
+
214
+ const policy = resolvePolicyFromConfig(rawConfig);
215
+
216
+ return {
217
+ threshold: policy.coverage_threshold,
218
+ mode: policy.coverage_mode,
219
+ tests_required: policy.tests_required,
220
+ };
221
+ }
222
+
223
+ export function resolveTddDiffEvidencePolicy(projectRoot: string): TddDiffEvidencePolicy {
224
+ const rawConfig = loadSoftwareDeliveryConfig(projectRoot) ?? {};
225
+
226
+ if (Object.keys(rawConfig).length === 0) {
227
+ return getDefaultPolicy().tdd_diff_evidence;
228
+ }
229
+
230
+ return resolvePolicyFromConfig(rawConfig).tdd_diff_evidence;
231
+ }
232
+
233
+ /**
234
+ * WU-2650: Resolve the commit-order (RED-first) policy.
235
+ *
236
+ * Mirrors resolveTddDiffEvidencePolicy. Enforces only for feature/bug WUs
237
+ * under TDD methodology by default; docs/chore/process/tooling WUs bypass.
238
+ */
239
+ export function resolveTddOrderingPolicy(projectRoot: string): TddOrderingPolicy {
240
+ const rawConfig = loadSoftwareDeliveryConfig(projectRoot) ?? {};
241
+
242
+ if (Object.keys(rawConfig).length === 0) {
243
+ return getDefaultPolicy().tdd_ordering;
244
+ }
245
+
246
+ return resolvePolicyFromConfig(rawConfig).tdd_ordering;
247
+ }
@@ -0,0 +1,134 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ /**
5
+ * Gates Presets
6
+ *
7
+ * WU-2037: Extracted from gates-config.ts
8
+ *
9
+ * Language ecosystem preset definitions and expansion logic.
10
+ *
11
+ * @module gates-presets
12
+ */
13
+
14
+ import type { GatesExecutionConfig } from './gates-schemas.js';
15
+
16
+ /**
17
+ * Gate preset definitions
18
+ *
19
+ * These provide sensible defaults for common language ecosystems.
20
+ * Users can override fields via workspace.yaml software_delivery
21
+ */
22
+ export const GATE_PRESETS: Record<string, Partial<GatesExecutionConfig>> = {
23
+ node: {
24
+ setup: 'npm ci || npm install',
25
+ format: 'npx prettier --check .',
26
+ lint: 'npx eslint .',
27
+ typecheck: 'npx tsc --noEmit',
28
+ test: 'npm test',
29
+ },
30
+ python: {
31
+ setup: 'pip install -e ".[dev]" || pip install -r requirements.txt',
32
+ format: 'ruff format --check .',
33
+ lint: 'ruff check .',
34
+ typecheck: 'mypy .',
35
+ test: 'pytest',
36
+ },
37
+ go: {
38
+ format: 'gofmt -l . | grep -v "^$" && exit 1 || exit 0',
39
+ lint: 'golangci-lint run',
40
+ typecheck: 'go vet ./...',
41
+ test: 'go test ./...',
42
+ },
43
+ rust: {
44
+ format: 'cargo fmt --check',
45
+ lint: 'cargo clippy -- -D warnings',
46
+ typecheck: 'cargo check',
47
+ test: 'cargo test',
48
+ },
49
+ dotnet: {
50
+ setup: 'dotnet restore',
51
+ format: 'dotnet format --verify-no-changes',
52
+ lint: 'dotnet build --no-restore -warnaserror',
53
+ test: 'dotnet test --no-restore',
54
+ },
55
+ // WU-1118: Java/JVM, Ruby, and PHP presets
56
+ java: {
57
+ format: 'mvn spotless:check || ./gradlew spotlessCheck',
58
+ lint: 'mvn checkstyle:check || ./gradlew checkstyleMain',
59
+ typecheck: 'mvn compile -DskipTests || ./gradlew compileJava',
60
+ test: 'mvn test || ./gradlew test',
61
+ },
62
+ ruby: {
63
+ setup: 'bundle install',
64
+ format: 'bundle exec rubocop --format simple --fail-level W',
65
+ lint: 'bundle exec rubocop',
66
+ test: 'bundle exec rspec',
67
+ },
68
+ php: {
69
+ setup: 'composer install',
70
+ format: 'vendor/bin/php-cs-fixer fix --dry-run --diff',
71
+ lint: 'vendor/bin/phpstan analyse',
72
+ test: 'vendor/bin/phpunit',
73
+ },
74
+ };
75
+
76
+ /**
77
+ * Expand a preset name into its default gate commands
78
+ *
79
+ * @param preset - Preset name (node, python, go, rust, dotnet) or undefined
80
+ * @returns Partial gates config with preset defaults, or empty object if unknown
81
+ */
82
+ export function expandPreset(preset: string | undefined): Partial<GatesExecutionConfig> {
83
+ if (!preset) {
84
+ return {};
85
+ }
86
+
87
+ return GATE_PRESETS[preset] ?? {};
88
+ }
89
+
90
+ /**
91
+ * WU-2547: Preset-specific format-fix remediation commands.
92
+ *
93
+ * The `format` key in GATE_PRESETS above is the *verification* command used
94
+ * by gates (e.g. `dotnet format --verify-no-changes`). When an agent or
95
+ * user needs to actually fix a formatting failure they need the mutating
96
+ * equivalent of that command — `dotnet format`, `cargo fmt`, etc.
97
+ *
98
+ * Onboarding templates used to hardcode `pnpm prettier --write <file>`,
99
+ * which silently teaches agents the wrong habit in non-JS repos. init.ts
100
+ * now resolves this map against the chosen preset and substitutes the
101
+ * result into the `{{format_fix_command}}` placeholder.
102
+ */
103
+ export const PRESET_FIX_COMMANDS: Record<string, string> = {
104
+ node: 'pnpm prettier --write <file>',
105
+ python: 'ruff format <file>',
106
+ go: 'gofmt -w <file>',
107
+ rust: 'cargo fmt',
108
+ dotnet: 'dotnet format',
109
+ java: 'mvn spotless:apply',
110
+ ruby: 'bundle exec rubocop -a <file>',
111
+ php: 'vendor/bin/php-cs-fixer fix <file>',
112
+ };
113
+
114
+ /**
115
+ * WU-2547: Safe fallback when a caller passes an unknown preset.
116
+ * Mirrors PRESET_FIX_COMMANDS.node so the two always match; kept as its own
117
+ * constant to satisfy noUncheckedIndexedAccess without a non-null assertion.
118
+ */
119
+ const DEFAULT_FORMAT_FIX_COMMAND = 'pnpm prettier --write <file>';
120
+
121
+ /**
122
+ * WU-2547: Resolve the format-fix remediation command for a preset.
123
+ *
124
+ * Used by init.ts to populate the `{{format_fix_command}}` token in
125
+ * onboarding templates so a .NET repo gets `dotnet format` guidance
126
+ * instead of `pnpm prettier --write`.
127
+ *
128
+ * @param preset - Gate preset name (node, dotnet, python, etc.)
129
+ * @returns The remediation command for the preset, or the node default
130
+ * if the preset is unknown (never returns empty).
131
+ */
132
+ export function getFormatFixCommand(preset: string): string {
133
+ return PRESET_FIX_COMMANDS[preset] ?? DEFAULT_FORMAT_FIX_COMMAND;
134
+ }
@@ -0,0 +1,173 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ /**
5
+ * Gates Schemas and Types
6
+ *
7
+ * WU-2037: Extracted from gates-config.ts
8
+ *
9
+ * Zod schema definitions, TypeScript types, and interfaces for gates configuration.
10
+ * This module contains only shape definitions -- no runtime logic.
11
+ *
12
+ * @module gates-schemas
13
+ */
14
+
15
+ import { z } from 'zod';
16
+ import type { CoverageMode } from './resolve-policy.js';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Gate command schemas
20
+ // ---------------------------------------------------------------------------
21
+
22
+ /**
23
+ * Schema for a gate command object with options
24
+ */
25
+ const GateCommandObjectSchema = z.object({
26
+ /** The shell command to execute */
27
+ command: z.string(),
28
+ /** Whether to continue if this gate fails (default: false) */
29
+ continueOnError: z.boolean().optional(),
30
+ /** Timeout in milliseconds */
31
+ timeout: z.number().int().positive().optional(),
32
+ });
33
+
34
+ /**
35
+ * Schema for a gate command - either a string or an object with options
36
+ */
37
+ export const GateCommandConfigSchema = z.union([z.string(), GateCommandObjectSchema]);
38
+
39
+ /**
40
+ * Type for parsed gate command configuration
41
+ */
42
+ export type GateCommandConfig = z.infer<typeof GateCommandConfigSchema>;
43
+
44
+ /**
45
+ * Schema for the gates execution configuration section
46
+ */
47
+ export const GatesExecutionConfigSchema = z.object({
48
+ /** Preset to use for default commands (node, python, go, rust, dotnet) */
49
+ preset: z.string().optional(),
50
+ /** Setup command (e.g., install dependencies) */
51
+ setup: GateCommandConfigSchema.optional(),
52
+ /** Format check command */
53
+ format: GateCommandConfigSchema.optional(),
54
+ /** Lint command */
55
+ lint: GateCommandConfigSchema.optional(),
56
+ /** Type check command */
57
+ typecheck: GateCommandConfigSchema.optional(),
58
+ /** Test command */
59
+ test: GateCommandConfigSchema.optional(),
60
+ /** Coverage configuration */
61
+ coverage: z
62
+ .union([
63
+ z.string(),
64
+ z.object({
65
+ command: z.string(),
66
+ threshold: z.number().min(0).max(100).optional(),
67
+ }),
68
+ ])
69
+ .optional(),
70
+ });
71
+
72
+ /**
73
+ * Type for gates execution configuration
74
+ */
75
+ export type GatesExecutionConfig = z.infer<typeof GatesExecutionConfigSchema>;
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Parsed gate command interface
79
+ // ---------------------------------------------------------------------------
80
+
81
+ /**
82
+ * Parsed gate command ready for execution
83
+ */
84
+ export interface ParsedGateCommand {
85
+ /** The shell command to execute */
86
+ command: string;
87
+ /** Whether to continue if this gate fails */
88
+ continueOnError: boolean;
89
+ /** Timeout in milliseconds */
90
+ timeout: number;
91
+ }
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // Lane health types
95
+ // ---------------------------------------------------------------------------
96
+
97
+ /**
98
+ * WU-1191: Lane health gate mode
99
+ * Controls how lane health check behaves during gates
100
+ */
101
+ export type LaneHealthMode = 'warn' | 'error' | 'off';
102
+
103
+ /**
104
+ * Schema for lane health mode validation
105
+ */
106
+ export const LaneHealthModeSchema = z.enum(['warn', 'error', 'off']);
107
+
108
+ /**
109
+ * Default lane health mode (advisory by default)
110
+ */
111
+ export const DEFAULT_LANE_HEALTH_MODE: LaneHealthMode = 'warn';
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Coverage / test policy interfaces
115
+ // ---------------------------------------------------------------------------
116
+
117
+ /**
118
+ * WU-1262: Resolved coverage configuration
119
+ * Contains threshold and mode derived from methodology policy
120
+ */
121
+ export interface CoverageConfig {
122
+ /** Coverage threshold (0-100) */
123
+ threshold: number;
124
+ /** Coverage mode (block, warn, or off) */
125
+ mode: CoverageMode;
126
+ }
127
+
128
+ /**
129
+ * WU-2020: Focused coverage policy interface (ISP-compliant).
130
+ * Single-responsibility: coverage threshold and enforcement mode.
131
+ */
132
+ export interface CoveragePolicy {
133
+ /** Coverage threshold (0-100) */
134
+ threshold: number;
135
+ /** Coverage mode (block, warn, or off) */
136
+ mode: CoverageMode;
137
+ }
138
+
139
+ /**
140
+ * WU-2020: Focused test runner policy interface (ISP-compliant).
141
+ * Single-responsibility: whether tests are mandatory for completion.
142
+ */
143
+ export interface TestRunnerPolicy {
144
+ /** Whether tests are required for completion (from methodology.testing) */
145
+ tests_required: boolean;
146
+ }
147
+
148
+ /**
149
+ * WU-1280: Resolved test policy configuration
150
+ * Extends CoverageConfig with tests_required from methodology policy.
151
+ *
152
+ * WU-2020: Now defined as the intersection of CoveragePolicy and
153
+ * TestRunnerPolicy. Consumers that only need coverage or test-runner
154
+ * semantics should prefer the focused interfaces.
155
+ */
156
+ export interface TestPolicy extends CoveragePolicy, TestRunnerPolicy {}
157
+
158
+ // ---------------------------------------------------------------------------
159
+ // Gates commands interface
160
+ // ---------------------------------------------------------------------------
161
+
162
+ /**
163
+ * WU-1356: Gates commands configuration type
164
+ */
165
+ export interface GatesCommands {
166
+ test_full: string;
167
+ test_docs_only: string;
168
+ test_incremental: string;
169
+ lint?: string;
170
+ typecheck?: string;
171
+ format?: string;
172
+ migration_verify: string;
173
+ }
@@ -0,0 +1,22 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ /**
5
+ * Software Delivery Pack — Policy Barrel
6
+ *
7
+ * WU-2674 (INIT-058 L3): Cohesion-closed policy bundle moved from
8
+ * @lumenflow/core/src/. These modules share tight internal coupling
9
+ * (CoverageMode crosses them) and evolve together.
10
+ *
11
+ * @module packs/software-delivery/policy
12
+ */
13
+
14
+ export * from './gates-schemas.js';
15
+ export * from './resolve-policy.js';
16
+ export * from './coverage-gate.js';
17
+ export * from './gates-config.js';
18
+ export * from './gates-presets.js';
19
+ export * from './gates-config-internal.js';
20
+ export * from './gates-agent-mode.js';
21
+ export * from './gates-coverage.js';
22
+ export * from './package-manager-resolver.js';