@lumenflow/cli 5.4.0 → 5.7.12

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 (227) hide show
  1. package/README.md +42 -40
  2. package/dist/db-journal-recover.js +400 -0
  3. package/dist/db-journal-recover.js.map +1 -0
  4. package/dist/docs-sync.js +8 -3
  5. package/dist/docs-sync.js.map +1 -1
  6. package/dist/gate-defaults.js +191 -9
  7. package/dist/gate-defaults.js.map +1 -1
  8. package/dist/gate-registry.js.map +1 -1
  9. package/dist/gates/monolithic-file-contention-guard.js +167 -0
  10. package/dist/gates/monolithic-file-contention-guard.js.map +1 -0
  11. package/dist/gates/prod-migration-drift.js +207 -0
  12. package/dist/gates/prod-migration-drift.js.map +1 -0
  13. package/dist/gates/test-over-deletion-guard.js +255 -0
  14. package/dist/gates/test-over-deletion-guard.js.map +1 -0
  15. package/dist/gates-runners.js +401 -2
  16. package/dist/gates-runners.js.map +1 -1
  17. package/dist/gates.js +349 -4
  18. package/dist/gates.js.map +1 -1
  19. package/dist/lumenflow-setup.js +144 -0
  20. package/dist/lumenflow-setup.js.map +1 -0
  21. package/dist/lumenflow-upgrade.js +2 -1
  22. package/dist/lumenflow-upgrade.js.map +1 -1
  23. package/dist/mem-create.js +10 -1
  24. package/dist/mem-create.js.map +1 -1
  25. package/dist/mem-signal.js +21 -4
  26. package/dist/mem-signal.js.map +1 -1
  27. package/dist/metrics-cli.js +19 -2
  28. package/dist/metrics-cli.js.map +1 -1
  29. package/dist/metrics-snapshot.js +25 -2
  30. package/dist/metrics-snapshot.js.map +1 -1
  31. package/dist/orchestrate-initiative.js +28 -3
  32. package/dist/orchestrate-initiative.js.map +1 -1
  33. package/dist/public-manifest.js +17 -0
  34. package/dist/public-manifest.js.map +1 -1
  35. package/dist/release.js +53 -18
  36. package/dist/release.js.map +1 -1
  37. package/dist/wu-done-gates.js +121 -8
  38. package/dist/wu-done-gates.js.map +1 -1
  39. package/dist/wu-done.js +30 -6
  40. package/dist/wu-done.js.map +1 -1
  41. package/dist/wu-edit-operations.js +74 -0
  42. package/dist/wu-edit-operations.js.map +1 -1
  43. package/dist/wu-edit-validators.js +58 -0
  44. package/dist/wu-edit-validators.js.map +1 -1
  45. package/dist/wu-edit.js +106 -4
  46. package/dist/wu-edit.js.map +1 -1
  47. package/dist/wu-prep.js +132 -8
  48. package/dist/wu-prep.js.map +1 -1
  49. package/dist/wu-recover.js +6 -0
  50. package/dist/wu-recover.js.map +1 -1
  51. package/dist/wu-release.js +120 -2
  52. package/dist/wu-release.js.map +1 -1
  53. package/dist/wu-sizing-validation.js +47 -17
  54. package/dist/wu-sizing-validation.js.map +1 -1
  55. package/dist/wu-status.js +33 -0
  56. package/dist/wu-status.js.map +1 -1
  57. package/package.json +13 -11
  58. package/packs/agent-runtime/package.json +1 -1
  59. package/packs/sidekick/package.json +1 -1
  60. package/packs/software-delivery/package.json +1 -1
  61. package/templates/core/AGENTS.md.template +162 -26
  62. package/templates/core/LUMENFLOW.md.template +381 -70
  63. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +0 -5
  64. package/templates/core/ai/onboarding/agent-safety-card.md.template +63 -17
  65. package/templates/core/ai/onboarding/initiative-orchestration.md.template +4 -0
  66. package/templates/core/ai/onboarding/release-process.md.template +7 -7
  67. package/templates/core/ai/onboarding/vendor-support.md.template +74 -10
  68. package/templates/vendors/claude/.claude/skills/frontend-design/SKILL.md.template +1 -1
  69. package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +28 -0
  70. package/packs/agent-runtime/agent-heartbeat.ts +0 -163
  71. package/packs/agent-runtime/auto-session-integration.ts +0 -888
  72. package/packs/agent-runtime/capability-factory.ts +0 -104
  73. package/packs/agent-runtime/constants.ts +0 -21
  74. package/packs/agent-runtime/delegation-registry-schema.ts +0 -220
  75. package/packs/agent-runtime/delegation-registry-store.ts +0 -269
  76. package/packs/agent-runtime/delegation-tree.ts +0 -328
  77. package/packs/agent-runtime/index.ts +0 -20
  78. package/packs/agent-runtime/manifest.ts +0 -348
  79. package/packs/agent-runtime/memory-coordination-contract.ts +0 -86
  80. package/packs/agent-runtime/orchestration.ts +0 -2027
  81. package/packs/agent-runtime/pack-registration.ts +0 -110
  82. package/packs/agent-runtime/policy-factory.ts +0 -165
  83. package/packs/agent-runtime/remote-controls/index.ts +0 -7
  84. package/packs/agent-runtime/remote-controls/operations.ts +0 -405
  85. package/packs/agent-runtime/remote-controls/port.ts +0 -48
  86. package/packs/agent-runtime/remote-controls/state-store.ts +0 -258
  87. package/packs/agent-runtime/remote-controls/types.ts +0 -105
  88. package/packs/agent-runtime/session-schema.ts +0 -467
  89. package/packs/agent-runtime/tool-impl/agent-turn-tools.ts +0 -793
  90. package/packs/agent-runtime/tool-impl/index.ts +0 -6
  91. package/packs/agent-runtime/tool-impl/provider-adapters.ts +0 -1245
  92. package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +0 -256
  93. package/packs/agent-runtime/tool-impl/remote-controls.ts +0 -273
  94. package/packs/agent-runtime/tools/index.ts +0 -4
  95. package/packs/agent-runtime/tools/types.ts +0 -47
  96. package/packs/agent-runtime/turn-lifecycle-events.ts +0 -590
  97. package/packs/agent-runtime/types.ts +0 -128
  98. package/packs/agent-runtime/vitest.config.ts +0 -11
  99. package/packs/sidekick/channel-ingress.ts +0 -137
  100. package/packs/sidekick/constants.ts +0 -10
  101. package/packs/sidekick/index.ts +0 -8
  102. package/packs/sidekick/manifest-schema.ts +0 -49
  103. package/packs/sidekick/manifest.ts +0 -512
  104. package/packs/sidekick/pack-registration.ts +0 -110
  105. package/packs/sidekick/policy-factory.ts +0 -38
  106. package/packs/sidekick/sidekick-events.ts +0 -694
  107. package/packs/sidekick/src/adapters/cloud-queue.ts +0 -101
  108. package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +0 -386
  109. package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +0 -228
  110. package/packs/sidekick/src/domain/channel.types.ts +0 -64
  111. package/packs/sidekick/src/ports/channel-bridge.port.ts +0 -92
  112. package/packs/sidekick/src/routines/commit.ts +0 -74
  113. package/packs/sidekick/tool-impl/channel-tools.ts +0 -577
  114. package/packs/sidekick/tool-impl/channel-transports.ts +0 -75
  115. package/packs/sidekick/tool-impl/index.ts +0 -29
  116. package/packs/sidekick/tool-impl/memory-tools.ts +0 -290
  117. package/packs/sidekick/tool-impl/routine-commit.ts +0 -102
  118. package/packs/sidekick/tool-impl/routine-tools.ts +0 -440
  119. package/packs/sidekick/tool-impl/runtime-context.ts +0 -28
  120. package/packs/sidekick/tool-impl/shared.ts +0 -125
  121. package/packs/sidekick/tool-impl/storage.ts +0 -325
  122. package/packs/sidekick/tool-impl/system-tools.ts +0 -160
  123. package/packs/sidekick/tool-impl/task-tools.ts +0 -506
  124. package/packs/sidekick/tools/channel-tools.ts +0 -53
  125. package/packs/sidekick/tools/index.ts +0 -9
  126. package/packs/sidekick/tools/memory-tools.ts +0 -53
  127. package/packs/sidekick/tools/routine-tools.ts +0 -53
  128. package/packs/sidekick/tools/system-tools.ts +0 -47
  129. package/packs/sidekick/tools/task-tools.ts +0 -61
  130. package/packs/sidekick/tools/types.ts +0 -57
  131. package/packs/sidekick/vitest.config.ts +0 -11
  132. package/packs/software-delivery/constants.ts +0 -10
  133. package/packs/software-delivery/extensions.ts +0 -140
  134. package/packs/software-delivery/gate-policies.ts +0 -134
  135. package/packs/software-delivery/index.ts +0 -8
  136. package/packs/software-delivery/manifest-schema.ts +0 -268
  137. package/packs/software-delivery/manifest.ts +0 -657
  138. package/packs/software-delivery/pack-registration.ts +0 -113
  139. package/packs/software-delivery/src/commands/index.ts +0 -5
  140. package/packs/software-delivery/src/config/delivery-review-contract.ts +0 -256
  141. package/packs/software-delivery/src/config/env-accessors.ts +0 -66
  142. package/packs/software-delivery/src/config/index.ts +0 -8
  143. package/packs/software-delivery/src/config/normalize-config-keys.ts +0 -9
  144. package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +0 -460
  145. package/packs/software-delivery/src/config/workspace-reader.ts +0 -375
  146. package/packs/software-delivery/src/constants/backlog-patterns.ts +0 -31
  147. package/packs/software-delivery/src/constants/client-ids.ts +0 -19
  148. package/packs/software-delivery/src/constants/config-contract.ts +0 -7
  149. package/packs/software-delivery/src/constants/docs-layout-presets.ts +0 -50
  150. package/packs/software-delivery/src/constants/duration-constants.ts +0 -20
  151. package/packs/software-delivery/src/constants/gate-constants.ts +0 -32
  152. package/packs/software-delivery/src/constants/index.ts +0 -29
  153. package/packs/software-delivery/src/constants/lock-constants.ts +0 -35
  154. package/packs/software-delivery/src/constants/object-guards.ts +0 -12
  155. package/packs/software-delivery/src/constants/section-headings.ts +0 -107
  156. package/packs/software-delivery/src/constants/wu-cli-constants.ts +0 -488
  157. package/packs/software-delivery/src/constants/wu-domain-constants.ts +0 -466
  158. package/packs/software-delivery/src/constants/wu-git-constants.ts +0 -7
  159. package/packs/software-delivery/src/constants/wu-id-format.ts +0 -327
  160. package/packs/software-delivery/src/constants/wu-paths-constants.ts +0 -384
  161. package/packs/software-delivery/src/constants/wu-statuses.ts +0 -287
  162. package/packs/software-delivery/src/constants/wu-type-helpers.ts +0 -67
  163. package/packs/software-delivery/src/constants/wu-ui-constants.ts +0 -267
  164. package/packs/software-delivery/src/constants/wu-validation-constants.ts +0 -73
  165. package/packs/software-delivery/src/domain/index.ts +0 -5
  166. package/packs/software-delivery/src/domain/orchestration.constants.ts +0 -166
  167. package/packs/software-delivery/src/domain/orchestration.schemas.ts +0 -238
  168. package/packs/software-delivery/src/domain/orchestration.types.ts +0 -176
  169. package/packs/software-delivery/src/methodology/incremental-test.ts +0 -122
  170. package/packs/software-delivery/src/methodology/index.ts +0 -6
  171. package/packs/software-delivery/src/methodology/manual-test-validator.ts +0 -292
  172. package/packs/software-delivery/src/policy/coverage-gate.ts +0 -270
  173. package/packs/software-delivery/src/policy/gates-agent-mode.ts +0 -223
  174. package/packs/software-delivery/src/policy/gates-config-internal.ts +0 -121
  175. package/packs/software-delivery/src/policy/gates-config.ts +0 -300
  176. package/packs/software-delivery/src/policy/gates-coverage.ts +0 -356
  177. package/packs/software-delivery/src/policy/gates-presets.ts +0 -134
  178. package/packs/software-delivery/src/policy/gates-schemas.ts +0 -173
  179. package/packs/software-delivery/src/policy/index.ts +0 -22
  180. package/packs/software-delivery/src/policy/package-manager-resolver.ts +0 -319
  181. package/packs/software-delivery/src/policy/resolve-policy.ts +0 -601
  182. package/packs/software-delivery/src/ports/config.ports.ts +0 -90
  183. package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +0 -125
  184. package/packs/software-delivery/src/ports/index.ts +0 -10
  185. package/packs/software-delivery/src/ports/sync-validator.ports.ts +0 -59
  186. package/packs/software-delivery/src/ports/wu-helpers.ports.ts +0 -168
  187. package/packs/software-delivery/src/ports/wu-state.ports.ts +0 -241
  188. package/packs/software-delivery/src/primitives/index.ts +0 -5
  189. package/packs/software-delivery/src/runtime/index.ts +0 -6
  190. package/packs/software-delivery/src/runtime/work-classifier.ts +0 -561
  191. package/packs/software-delivery/src/sandbox/index.ts +0 -10
  192. package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +0 -118
  193. package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +0 -88
  194. package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +0 -154
  195. package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +0 -47
  196. package/packs/software-delivery/src/sandbox/sandbox-profile.ts +0 -153
  197. package/packs/software-delivery/src/schemas/index.ts +0 -5
  198. package/packs/software-delivery/src/state/date-utils.ts +0 -158
  199. package/packs/software-delivery/src/state/index.ts +0 -15
  200. package/packs/software-delivery/src/state/state-machine.ts +0 -119
  201. package/packs/software-delivery/src/state/wu-doc-types.ts +0 -51
  202. package/packs/software-delivery/src/state/wu-paths.ts +0 -381
  203. package/packs/software-delivery/src/state/wu-schema.ts +0 -1139
  204. package/packs/software-delivery/src/state/wu-state-schema.ts +0 -255
  205. package/packs/software-delivery/src/state/wu-yaml.ts +0 -338
  206. package/packs/software-delivery/tool-impl/agent-tools.ts +0 -263
  207. package/packs/software-delivery/tool-impl/delegation-tools.ts +0 -66
  208. package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +0 -219
  209. package/packs/software-delivery/tool-impl/git-runner.ts +0 -113
  210. package/packs/software-delivery/tool-impl/git-tools.ts +0 -316
  211. package/packs/software-delivery/tool-impl/index.ts +0 -15
  212. package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +0 -720
  213. package/packs/software-delivery/tool-impl/lane-lock.ts +0 -246
  214. package/packs/software-delivery/tool-impl/memory-tools.ts +0 -470
  215. package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +0 -21
  216. package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +0 -329
  217. package/packs/software-delivery/tool-impl/runtime-native-tools.ts +0 -687
  218. package/packs/software-delivery/tool-impl/worker-loader.ts +0 -52
  219. package/packs/software-delivery/tool-impl/worktree-tools.ts +0 -46
  220. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +0 -807
  221. package/packs/software-delivery/tools/delegation-tools.ts +0 -23
  222. package/packs/software-delivery/tools/git-tools.ts +0 -55
  223. package/packs/software-delivery/tools/index.ts +0 -8
  224. package/packs/software-delivery/tools/lane-lock-tool.ts +0 -37
  225. package/packs/software-delivery/tools/types.ts +0 -71
  226. package/packs/software-delivery/tools/worktree-tools.ts +0 -49
  227. package/packs/software-delivery/vitest.config.ts +0 -11
@@ -9,7 +9,7 @@
9
9
  * @module gates-runners
10
10
  */
11
11
  import { spawnSync } from 'node:child_process';
12
- import { existsSync, mkdirSync, readFileSync, writeFileSync, writeSync } from 'node:fs';
12
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, writeSync, } from 'node:fs';
13
13
  import { access } from 'node:fs/promises';
14
14
  import { createRequire } from 'node:module';
15
15
  import path from 'node:path';
@@ -19,7 +19,7 @@ import { createGitForPath } from '@lumenflow/core/git-adapter';
19
19
  import { resolveGatesCommands, resolveTestRunner, getGatesSection, resolveScopedUnitTestExecutionPlan, formatScopedUnitTestFallbackMessage, } from '@lumenflow/packs-software-delivery/policy/gates-config';
20
20
  import { CoChangeRuleConfigSchema, ConditionalCommandConfigSchema, } from '@lumenflow/core/config-schema';
21
21
  import { validateBacklogSync } from '@lumenflow/core/validators/backlog-sync';
22
- import { DELIVERY_REVIEW_ARTIFACT_DIR, DeliveryReviewResultSchema, calculateDeliveryReviewVerdict, createWuPaths, flattenDeliveryReviewAcceptanceCriteria, isCodePathCoveredByChangedFiles, isDeliveryReviewSkippedForType, isPathLikeTestEntry, readWU, resolveDeliveryReviewRuntimeConfig, validateClaimValidation, } from '@lumenflow/core';
22
+ import { DELIVERY_REVIEW_ARTIFACT_DIR, DeliveryReviewResultSchema, calculateDeliveryReviewVerdict, createWuPaths, flattenDeliveryReviewAcceptanceCriteria, isCodePathCoveredByChangedFiles, isDeliveryReviewSkippedForType, isPathLikeTestEntry, readWU, resolveDeliveryReviewRuntimeConfig, validateClaimValidation, DOCS_LAYOUT_PRESETS, } from '@lumenflow/core';
23
23
  import { runSupabaseDocsLinter } from '@lumenflow/core/validators/supabase-docs-linter';
24
24
  import { isIntegrationMainBranch, resolveIntegrationTargetRef, } from '@lumenflow/core/integration-target';
25
25
  import { PACKAGES, PKG_MANAGER, ESLINT_FLAGS, ESLINT_COMMANDS, ESLINT_DEFAULTS, SCRIPTS, CACHE_STRATEGIES, DIRECTORIES, EXIT_CODES, FILE_SYSTEM, } from '@lumenflow/core/wu-constants';
@@ -49,6 +49,8 @@ const DEFAULT_MIGRATION_VERIFY_PATTERNS = [
49
49
  'prisma/migrations/**',
50
50
  'drizzle/migrations/**',
51
51
  ];
52
+ const WU_DB_IMPACTING_FIELD = 'db_impacting';
53
+ const WU_YAML_EXTENSION = '.yaml';
52
54
  const DELIVERY_REVIEW_HIGH_RISK_PATH_PATTERN = /(auth|permission|secret|token|credential|billing|payment|migration|schema|policy|sandbox|security|hook)/i;
53
55
  const DELIVERY_REVIEW_TEST_PATH_PATTERN = /(^|\/)(__tests__\/|.*\.(test|spec)\.[A-Za-z0-9]+$)/i;
54
56
  function asStringArray(value) {
@@ -585,6 +587,181 @@ export async function runIntegrationTests({ agentLog, cwd, }) {
585
587
  return { ok: false, duration: Date.now() - start };
586
588
  }
587
589
  }
590
+ // ── WU-2927: Opt-in local-prep gates (build / integration-test / e2e-smoke) ──
591
+ /**
592
+ * WU-2927: Resolve `software_delivery.gates.local_prep` from workspace.yaml.
593
+ *
594
+ * Returns the typed sub-shape (or undefined when the section is missing or
595
+ * malformed). The runtime callers fall through to "not applicable" semantics
596
+ * when this returns undefined or `{ enabled: false }` — backward-compat for
597
+ * repos that have not opted in.
598
+ */
599
+ function readLocalPrepConfig(cwd) {
600
+ try {
601
+ const section = getGatesSection(cwd);
602
+ const lp = section?.local_prep;
603
+ if (lp && typeof lp === 'object' && !Array.isArray(lp)) {
604
+ return lp;
605
+ }
606
+ return undefined;
607
+ }
608
+ catch {
609
+ return undefined;
610
+ }
611
+ }
612
+ function readPackageScripts(cwd) {
613
+ try {
614
+ const pkgPath = path.join(cwd, 'package.json');
615
+ if (!existsSync(pkgPath))
616
+ return undefined;
617
+ const raw = readFileSync(pkgPath, 'utf8');
618
+ const parsed = JSON.parse(raw);
619
+ return parsed.scripts;
620
+ }
621
+ catch {
622
+ return undefined;
623
+ }
624
+ }
625
+ /**
626
+ * WU-2927: build gate applicability — only when the local-prep profile opts in
627
+ * (`local_prep.build.enabled = true`). Default false → not-applicable.
628
+ */
629
+ export function checkBuildApplicability(ctx) {
630
+ const cwd = ctx.cwd ?? process.cwd();
631
+ const lp = readLocalPrepConfig(cwd);
632
+ return Promise.resolve(lp?.build?.enabled === true ? 'applicable' : 'not-applicable');
633
+ }
634
+ /**
635
+ * WU-2927: build gate preconditions — `build` script must exist in
636
+ * package.json. With `prereq_strategy: 'fail'` a missing script is treated as
637
+ * a misconfiguration, not an environmental gap.
638
+ */
639
+ export function checkBuildPreconditions(ctx) {
640
+ const cwd = ctx.cwd ?? process.cwd();
641
+ const scripts = readPackageScripts(cwd);
642
+ return scripts && Object.prototype.hasOwnProperty.call(scripts, SCRIPTS.BUILD)
643
+ ? 'satisfied'
644
+ : 'missing';
645
+ }
646
+ /**
647
+ * WU-2927: integration-test gate applicability — opt-in via
648
+ * `local_prep.integration_test.enabled = true`. Replaces the pre-WU-2927
649
+ * conditional registration (gate-defaults.ts:209 / gates.ts:450/486) so that
650
+ * the gate is unconditionally registered and applicability is the only knob.
651
+ */
652
+ export function checkIntegrationTestApplicability(ctx) {
653
+ const cwd = ctx.cwd ?? process.cwd();
654
+ const lp = readLocalPrepConfig(cwd);
655
+ return Promise.resolve(lp?.integration_test?.enabled === true ? 'applicable' : 'not-applicable');
656
+ }
657
+ /**
658
+ * WU-2927: integration-test gate preconditions — `test:integration` script
659
+ * must exist. Same fail-on-missing semantics as build (misconfig).
660
+ */
661
+ export function checkIntegrationTestPreconditions(ctx) {
662
+ const cwd = ctx.cwd ?? process.cwd();
663
+ const scripts = readPackageScripts(cwd);
664
+ return scripts && Object.prototype.hasOwnProperty.call(scripts, SCRIPTS.TEST_INTEGRATION)
665
+ ? 'satisfied'
666
+ : 'missing';
667
+ }
668
+ /**
669
+ * WU-2927: e2e-smoke gate applicability — applicable iff
670
+ * (a) `local_prep.e2e_smoke.enabled = true`, AND
671
+ * (b) `playwright.config.{ts,js,mjs}` exists at repo root.
672
+ *
673
+ * Per stated policy: the absence of a Playwright config is a clean opt-out,
674
+ * not a missing precondition (no explicit disable required for repos that do
675
+ * not use Playwright).
676
+ */
677
+ export function checkE2eSmokeApplicability(ctx) {
678
+ const cwd = ctx.cwd ?? process.cwd();
679
+ const lp = readLocalPrepConfig(cwd);
680
+ if (lp?.e2e_smoke?.enabled !== true)
681
+ return Promise.resolve('not-applicable');
682
+ for (const ext of ['ts', 'js', 'mjs']) {
683
+ if (existsSync(path.join(cwd, `playwright.config.${ext}`))) {
684
+ return Promise.resolve('applicable');
685
+ }
686
+ }
687
+ return Promise.resolve('not-applicable');
688
+ }
689
+ /**
690
+ * WU-2927: e2e-smoke gate preconditions — once applicable (Playwright config
691
+ * present + opted in), the `test:e2e` script must exist. Missing = misconfig
692
+ * → 'failed' under `prereq_strategy: 'fail'`.
693
+ */
694
+ export function checkE2eSmokePreconditions(ctx) {
695
+ const cwd = ctx.cwd ?? process.cwd();
696
+ const scripts = readPackageScripts(cwd);
697
+ return scripts && Object.prototype.hasOwnProperty.call(scripts, SCRIPTS.TEST_E2E)
698
+ ? 'satisfied'
699
+ : 'missing';
700
+ }
701
+ /**
702
+ * WU-2927: Read the configured e2e_smoke.tag (default 'smoke').
703
+ */
704
+ export function getE2eSmokeTag(cwd) {
705
+ const lp = readLocalPrepConfig(cwd);
706
+ const tag = lp?.e2e_smoke?.tag;
707
+ return typeof tag === 'string' && tag.length > 0 ? tag : 'smoke';
708
+ }
709
+ /**
710
+ * WU-2927: Read the configured latency_budget_warn_ms (default 180_000).
711
+ */
712
+ export function getLocalPrepLatencyBudgetMs(cwd) {
713
+ const lp = readLocalPrepConfig(cwd);
714
+ const budget = lp?.latency_budget_warn_ms;
715
+ return typeof budget === 'number' && budget >= 0 ? budget : 180_000;
716
+ }
717
+ /**
718
+ * WU-2927: Run the opt-in build gate (`pnpm build`). Wraps SCRIPTS.BUILD.
719
+ */
720
+ export async function runBuildGate({ agentLog, cwd, }) {
721
+ const start = Date.now();
722
+ const logLine = (line) => {
723
+ if (!agentLog) {
724
+ console.log(line);
725
+ return;
726
+ }
727
+ writeSync(agentLog.logFd, `${line}\n`);
728
+ };
729
+ try {
730
+ logLine('\n> Build gate (local_prep)\n');
731
+ const result = await run(pnpmRun(SCRIPTS.BUILD), { agentLog, cwd });
732
+ return { ok: result.ok, duration: Date.now() - start };
733
+ }
734
+ catch (error) {
735
+ const message = error instanceof Error ? error.message : String(error);
736
+ logLine(`⚠️ Build gate failed: ${message}`);
737
+ return { ok: false, duration: Date.now() - start };
738
+ }
739
+ }
740
+ /**
741
+ * WU-2927: Run the opt-in e2e-smoke gate. Executes
742
+ * `pnpm test:e2e --tag <local_prep.e2e_smoke.tag>` (default tag 'smoke').
743
+ */
744
+ export async function runE2eSmokeGate({ agentLog, cwd, }) {
745
+ const start = Date.now();
746
+ const logLine = (line) => {
747
+ if (!agentLog) {
748
+ console.log(line);
749
+ return;
750
+ }
751
+ writeSync(agentLog.logFd, `${line}\n`);
752
+ };
753
+ try {
754
+ const tag = getE2eSmokeTag(cwd);
755
+ logLine(`\n> E2E smoke gate (local_prep, tag=${tag})\n`);
756
+ const result = await run(pnpmRun(SCRIPTS.TEST_E2E, '--tag', tag), { agentLog, cwd });
757
+ return { ok: result.ok, duration: Date.now() - start };
758
+ }
759
+ catch (error) {
760
+ const message = error instanceof Error ? error.message : String(error);
761
+ logLine(`⚠️ E2E smoke gate failed: ${message}`);
762
+ return { ok: false, duration: Date.now() - start };
763
+ }
764
+ }
588
765
  // ── Co-change gate ────────────────────────────────────────────────────
589
766
  const CoChangeRulesConfigSchema = CoChangeRuleConfigSchema.array();
590
767
  const ConditionalCommandsConfigSchema = ConditionalCommandConfigSchema.array();
@@ -610,6 +787,38 @@ export function getMatchingCoChangeRulesForPaths(options) {
610
787
  export function shouldRunMigrationVerifyForChanges(options) {
611
788
  return hasPatternMatch(options.changedFiles, [...DEFAULT_MIGRATION_VERIFY_PATTERNS]);
612
789
  }
790
+ async function isDbImpactingDisabledForCurrentWU(cwd) {
791
+ const wuId = (await detectCurrentWUForCwd(cwd)) ?? findSingleWuIdInWuDirectory(cwd);
792
+ if (!wuId) {
793
+ return false;
794
+ }
795
+ try {
796
+ const wuPaths = createWuPaths({ projectRoot: cwd });
797
+ const wuPath = path.join(cwd, wuPaths.WU(wuId));
798
+ const wu = readWU(wuPath, wuId);
799
+ return wu[WU_DB_IMPACTING_FIELD] === false;
800
+ }
801
+ catch {
802
+ return false;
803
+ }
804
+ }
805
+ function findSingleWuIdInWuDirectory(cwd) {
806
+ try {
807
+ const wuPaths = createWuPaths({ projectRoot: cwd });
808
+ const wuDir = path.join(cwd, wuPaths.WU_DIR());
809
+ if (!existsSync(wuDir)) {
810
+ return null;
811
+ }
812
+ const wuFiles = readdirSync(wuDir).filter((entry) => entry.endsWith(WU_YAML_EXTENSION));
813
+ if (wuFiles.length !== 1) {
814
+ return null;
815
+ }
816
+ return path.basename(wuFiles[0], WU_YAML_EXTENSION);
817
+ }
818
+ catch {
819
+ return null;
820
+ }
821
+ }
613
822
  function resolveConditionalCommandGuidanceRefs(commands, projectRoot, logWarning) {
614
823
  return commands.map((command) => {
615
824
  if (!command.guidance_ref) {
@@ -753,6 +962,10 @@ export async function runMigrationVerifyGate({ agentLog, useAgentMode, cwd }) {
753
962
  logLine('ℹ️ No changed files detected; skipping migration verification.');
754
963
  return { ok: true, duration: Date.now() - start };
755
964
  }
965
+ if (await isDbImpactingDisabledForCurrentWU(effectiveCwd)) {
966
+ logLine('ℹ️ WU declares db_impacting:false; skipping migration verification.');
967
+ return { ok: true, duration: Date.now() - start };
968
+ }
756
969
  const conditionalCommands = getResolvedConditionalCommands(effectiveCwd, (msg) => logLine(`⚠️ ${msg}`));
757
970
  const matchingConditionalCommands = getMatchingConditionalCommandsForPaths({
758
971
  filePaths: changedFiles,
@@ -1099,4 +1312,190 @@ export async function runDocsOnlyFilteredTests({ packages, agentLog, cwd = proce
1099
1312
  const result = await run(filteredCmd, { agentLog });
1100
1313
  return { ok: result.ok, duration: Date.now() - start };
1101
1314
  }
1315
+ // ── WU-2926: Per-gate applicability + precondition helpers ─────────────
1316
+ /**
1317
+ * WU-2926: Test whether any changed file matches one of the
1318
+ * `applicability_paths` patterns. Returns `true` (applicable) when the override
1319
+ * is undefined or empty so safety-critical-test preserves today's "always
1320
+ * runs" behaviour at gate-defaults.ts:195.
1321
+ */
1322
+ export function applicabilityPathsMatch(input) {
1323
+ const { applicabilityPaths } = input;
1324
+ if (!applicabilityPaths || applicabilityPaths.length === 0) {
1325
+ // Default applicable — preserves backward-compat (no override, no narrowing).
1326
+ return true;
1327
+ }
1328
+ return micromatch.isMatch.length >= 0
1329
+ ? input.changedFiles.some((file) => micromatch.isMatch(file, applicabilityPaths))
1330
+ : false;
1331
+ }
1332
+ /**
1333
+ * WU-2926: Default safety-critical applicability check.
1334
+ *
1335
+ * Backward-compat preservation (load-bearing): with no per-repo
1336
+ * `applicability_paths` override, returns 'applicable' for every change set —
1337
+ * matching the always-runs behaviour at gate-defaults.ts:195 and
1338
+ * gates-runners.ts:743 (runSafetyCriticalTests).
1339
+ *
1340
+ * With an override (e.g. `['app/security/**', 'lib/auth/**']`), returns
1341
+ * 'applicable' only when at least one changed file matches.
1342
+ */
1343
+ export async function checkSafetyCriticalApplicability(input) {
1344
+ // Resolve applicability_paths: explicit input wins; else read from
1345
+ // software_delivery.gates.overrides.safety-critical-test.applicability_paths.
1346
+ let paths = input.applicabilityPaths;
1347
+ if (paths === undefined) {
1348
+ paths = readApplicabilityPathsOverride('safety-critical-test', input.cwd ?? process.cwd());
1349
+ }
1350
+ if (!paths || paths.length === 0) {
1351
+ return 'applicable';
1352
+ }
1353
+ let files = input.changedFiles;
1354
+ if (!files) {
1355
+ try {
1356
+ const git = createGitForPath(input.cwd ?? process.cwd());
1357
+ files = await getChangedFilesForIncremental({ git });
1358
+ }
1359
+ catch {
1360
+ files = [];
1361
+ }
1362
+ }
1363
+ return applicabilityPathsMatch({ changedFiles: files, applicabilityPaths: paths })
1364
+ ? 'applicable'
1365
+ : 'not-applicable';
1366
+ }
1367
+ /**
1368
+ * WU-2926: Read `software_delivery.gates.overrides.<gate_id>.applicability_paths`
1369
+ * from workspace.yaml. Returns undefined when no override is set so callers
1370
+ * can fall through to default-applicable behaviour.
1371
+ */
1372
+ function readApplicabilityPathsOverride(gateId, cwd) {
1373
+ try {
1374
+ const required = require;
1375
+ const cfgMod = required('@lumenflow/core/config');
1376
+ if (!cfgMod || typeof cfgMod.getConfig !== 'function')
1377
+ return undefined;
1378
+ const cfg = cfgMod.getConfig();
1379
+ const sd = cfg &&
1380
+ cfg.software_delivery;
1381
+ const gates = sd?.gates;
1382
+ const overrides = gates?.overrides;
1383
+ const entry = overrides?.[gateId];
1384
+ const ap = entry?.applicability_paths;
1385
+ if (Array.isArray(ap) && ap.every((s) => typeof s === 'string')) {
1386
+ return ap;
1387
+ }
1388
+ return undefined;
1389
+ }
1390
+ catch {
1391
+ void cwd;
1392
+ return undefined;
1393
+ }
1394
+ }
1395
+ /**
1396
+ * WU-2926: migration-verify applicability — only when migrations/.sql or
1397
+ * schema files have changed.
1398
+ */
1399
+ export async function checkMigrationVerifyApplicability(ctx) {
1400
+ try {
1401
+ if (await isDbImpactingDisabledForCurrentWU(ctx.cwd ?? process.cwd())) {
1402
+ return 'not-applicable';
1403
+ }
1404
+ const git = createGitForPath(ctx.cwd ?? process.cwd());
1405
+ const changed = await getChangedFilesForIncremental({ git });
1406
+ return shouldRunMigrationVerifyForChanges({ changedFiles: changed })
1407
+ ? 'applicable'
1408
+ : 'not-applicable';
1409
+ }
1410
+ catch {
1411
+ return 'not-applicable';
1412
+ }
1413
+ }
1414
+ /**
1415
+ * WU-2926: migration-verify preconditions — DATABASE_URL set OR PGlite available.
1416
+ *
1417
+ * PGlite presence is approximated by node_modules/@electric-sql/pglite, the
1418
+ * canonical package the migration toolchain uses for in-process Postgres in
1419
+ * agent worktrees.
1420
+ */
1421
+ export function checkMigrationVerifyPreconditions(ctx) {
1422
+ if (process.env.DATABASE_URL && process.env.DATABASE_URL.trim().length > 0) {
1423
+ return Promise.resolve('satisfied');
1424
+ }
1425
+ const cwd = ctx.cwd ?? process.cwd();
1426
+ const pgliteDir = path.join(cwd, 'node_modules', '@electric-sql', 'pglite');
1427
+ return Promise.resolve(existsSync(pgliteDir) ? 'satisfied' : 'missing');
1428
+ }
1429
+ /**
1430
+ * WU-2926: invariants gate — always applicable; preconditions satisfied when
1431
+ * an invariants config is present (best-effort detection at standard paths).
1432
+ */
1433
+ export function checkInvariantsPreconditions(ctx) {
1434
+ const cwd = ctx.cwd ?? process.cwd();
1435
+ const candidates = [
1436
+ 'invariants.yaml',
1437
+ 'invariants.yml',
1438
+ '.lumenflow/invariants.yaml',
1439
+ `${DOCS_LAYOUT_PRESETS.arc42.operations}/_frameworks/lumenflow/invariants.yaml`,
1440
+ ];
1441
+ for (const rel of candidates) {
1442
+ if (existsSync(path.join(cwd, rel)))
1443
+ return Promise.resolve('satisfied');
1444
+ }
1445
+ // Fallback: invariants runner has internal defaults (the existing gate
1446
+ // already runs without explicit config). Return 'satisfied' to preserve
1447
+ // today's behaviour.
1448
+ return Promise.resolve('satisfied');
1449
+ }
1450
+ /**
1451
+ * WU-2926: lane-health applicability — only when `.lumenflow/state/lane-state.json`
1452
+ * exists. Preconditions = state path is writable.
1453
+ */
1454
+ export function checkLaneHealthApplicability(ctx) {
1455
+ const cwd = ctx.cwd ?? process.cwd();
1456
+ return Promise.resolve(existsSync(path.join(cwd, '.lumenflow', 'state', 'lane-state.json'))
1457
+ ? 'applicable'
1458
+ : 'not-applicable');
1459
+ }
1460
+ export async function checkLaneHealthPreconditions(ctx) {
1461
+ const cwd = ctx.cwd ?? process.cwd();
1462
+ const stateDir = path.join(cwd, '.lumenflow', 'state');
1463
+ try {
1464
+ await access(stateDir);
1465
+ return 'satisfied';
1466
+ }
1467
+ catch {
1468
+ return 'missing';
1469
+ }
1470
+ }
1471
+ /**
1472
+ * WU-2926: co-change applicability — only when workspace.yaml has co-change
1473
+ * rules (otherwise the gate has nothing to evaluate).
1474
+ */
1475
+ export function checkCoChangeApplicability(ctx) {
1476
+ const cwd = ctx.cwd ?? process.cwd();
1477
+ try {
1478
+ const section = getGatesSection(cwd);
1479
+ const rules = section?.co_change?.rules;
1480
+ return Promise.resolve(Array.isArray(rules) && rules.length > 0 ? 'applicable' : 'not-applicable');
1481
+ }
1482
+ catch {
1483
+ return Promise.resolve('not-applicable');
1484
+ }
1485
+ }
1486
+ /**
1487
+ * WU-2926: claim-validation applicability — only when a claimed WU YAML
1488
+ * exists for the current worktree. Without a claim, the gate has nothing to
1489
+ * validate.
1490
+ */
1491
+ export async function checkClaimValidationApplicability(ctx) {
1492
+ const cwd = ctx.cwd ?? process.cwd();
1493
+ try {
1494
+ const wuId = await detectCurrentWUForCwd(cwd);
1495
+ return wuId ? 'applicable' : 'not-applicable';
1496
+ }
1497
+ catch {
1498
+ return 'not-applicable';
1499
+ }
1500
+ }
1102
1501
  //# sourceMappingURL=gates-runners.js.map