@lumenflow/cli 3.1.3 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/dist/agent-issues-query.js.map +1 -0
  2. package/dist/agent-log-issue.js.map +1 -0
  3. package/dist/agent-session-end.js.map +1 -0
  4. package/dist/agent-session.js.map +1 -0
  5. package/dist/backlog-prune.js.map +1 -0
  6. package/dist/cli-entry-point.js +139 -0
  7. package/dist/cli-entry-point.js.map +1 -0
  8. package/dist/commands/integrate.js.map +1 -0
  9. package/dist/commands.js.map +1 -0
  10. package/dist/config-get.js.map +1 -0
  11. package/dist/config-set.js.map +1 -0
  12. package/dist/constants.js +98 -0
  13. package/dist/constants.js.map +1 -0
  14. package/dist/delegation-list.js.map +1 -0
  15. package/dist/deps-add.js +259 -0
  16. package/dist/deps-add.js.map +1 -0
  17. package/dist/deps-remove.js +105 -0
  18. package/dist/deps-remove.js.map +1 -0
  19. package/dist/docs-sync.js.map +1 -0
  20. package/dist/doctor.js.map +1 -0
  21. package/dist/file-delete.js.map +1 -0
  22. package/dist/file-edit.js.map +1 -0
  23. package/dist/file-read.js.map +1 -0
  24. package/dist/file-write.js.map +1 -0
  25. package/dist/flow-bottlenecks.js.map +1 -0
  26. package/dist/flow-report.js.map +1 -0
  27. package/dist/formatters.js +151 -0
  28. package/dist/formatters.js.map +1 -0
  29. package/dist/gate-defaults.js +137 -0
  30. package/dist/gate-defaults.js.map +1 -0
  31. package/dist/gate-registry.js +73 -0
  32. package/dist/gate-registry.js.map +1 -0
  33. package/dist/gates-graceful-degradation.js +153 -0
  34. package/dist/gates-graceful-degradation.js.map +1 -0
  35. package/dist/gates-plan-resolvers.js +190 -0
  36. package/dist/gates-plan-resolvers.js.map +1 -0
  37. package/dist/gates-runners.js +545 -0
  38. package/dist/gates-runners.js.map +1 -0
  39. package/dist/gates-types.js +4 -0
  40. package/dist/gates-types.js.map +1 -0
  41. package/dist/gates-utils.js +333 -0
  42. package/dist/gates-utils.js.map +1 -0
  43. package/dist/gates.js.map +1 -0
  44. package/dist/git-branch.js.map +1 -0
  45. package/dist/git-diff.js.map +1 -0
  46. package/dist/git-log.js.map +1 -0
  47. package/dist/git-status.js.map +1 -0
  48. package/dist/guard-locked.js +172 -0
  49. package/dist/guard-locked.js.map +1 -0
  50. package/dist/guard-main-branch.js +217 -0
  51. package/dist/guard-main-branch.js.map +1 -0
  52. package/dist/guard-worktree-commit.js +163 -0
  53. package/dist/guard-worktree-commit.js.map +1 -0
  54. package/dist/hooks/auto-checkpoint-utils.js +54 -0
  55. package/dist/hooks/auto-checkpoint-utils.js.map +1 -0
  56. package/dist/hooks/enforcement-checks.js +399 -0
  57. package/dist/hooks/enforcement-checks.js.map +1 -0
  58. package/dist/hooks/enforcement-generator.js +139 -0
  59. package/dist/hooks/enforcement-generator.js.map +1 -0
  60. package/dist/hooks/enforcement-sync.js +380 -0
  61. package/dist/hooks/enforcement-sync.js.map +1 -0
  62. package/dist/hooks/generators/auto-checkpoint.js +125 -0
  63. package/dist/hooks/generators/auto-checkpoint.js.map +1 -0
  64. package/dist/hooks/generators/enforce-worktree.js +190 -0
  65. package/dist/hooks/generators/enforce-worktree.js.map +1 -0
  66. package/dist/hooks/generators/index.js +18 -0
  67. package/dist/hooks/generators/index.js.map +1 -0
  68. package/dist/hooks/generators/pre-compact-checkpoint.js +136 -0
  69. package/dist/hooks/generators/pre-compact-checkpoint.js.map +1 -0
  70. package/dist/hooks/generators/require-wu.js +117 -0
  71. package/dist/hooks/generators/require-wu.js.map +1 -0
  72. package/dist/hooks/generators/session-start-recovery.js +103 -0
  73. package/dist/hooks/generators/session-start-recovery.js.map +1 -0
  74. package/dist/hooks/generators/signal-utils.js +54 -0
  75. package/dist/hooks/generators/signal-utils.js.map +1 -0
  76. package/dist/hooks/generators/warn-incomplete.js +67 -0
  77. package/dist/hooks/generators/warn-incomplete.js.map +1 -0
  78. package/dist/hooks/index.js +10 -0
  79. package/dist/hooks/index.js.map +1 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/init-detection.js +232 -0
  82. package/dist/init-detection.js.map +1 -0
  83. package/dist/init-lane-validation.js +147 -0
  84. package/dist/init-lane-validation.js.map +1 -0
  85. package/dist/init-scaffolding.js +158 -0
  86. package/dist/init-scaffolding.js.map +1 -0
  87. package/dist/init-templates.js +1983 -0
  88. package/dist/init-templates.js.map +1 -0
  89. package/dist/init.js.map +1 -0
  90. package/dist/initiative-add-wu.js.map +1 -0
  91. package/dist/initiative-bulk-assign-wus.js.map +1 -0
  92. package/dist/initiative-create.js.map +1 -0
  93. package/dist/initiative-edit.js.map +1 -0
  94. package/dist/initiative-list.js.map +1 -0
  95. package/dist/initiative-plan.js.map +1 -0
  96. package/dist/initiative-remove-wu.js.map +1 -0
  97. package/dist/initiative-status.js.map +1 -0
  98. package/dist/lane-edit.js.map +1 -0
  99. package/dist/lane-health.js.map +1 -0
  100. package/dist/lane-lifecycle-process.js +381 -0
  101. package/dist/lane-lifecycle-process.js.map +1 -0
  102. package/dist/lane-lock.js.map +1 -0
  103. package/dist/lane-setup.js.map +1 -0
  104. package/dist/lane-status.js.map +1 -0
  105. package/dist/lane-suggest.js.map +1 -0
  106. package/dist/lane-validate.js.map +1 -0
  107. package/dist/lifecycle-regression-harness.js +181 -0
  108. package/dist/lifecycle-regression-harness.js.map +1 -0
  109. package/dist/lumenflow-upgrade.js +18 -10
  110. package/dist/lumenflow-upgrade.js.map +1 -0
  111. package/dist/mem-checkpoint.js.map +1 -0
  112. package/dist/mem-cleanup.js.map +1 -0
  113. package/dist/mem-context.js.map +1 -0
  114. package/dist/mem-create.js.map +1 -0
  115. package/dist/mem-delete.js.map +1 -0
  116. package/dist/mem-export.js.map +1 -0
  117. package/dist/mem-inbox.js.map +1 -0
  118. package/dist/mem-index.js +214 -0
  119. package/dist/mem-index.js.map +1 -0
  120. package/dist/mem-init.js.map +1 -0
  121. package/dist/mem-profile.js +210 -0
  122. package/dist/mem-profile.js.map +1 -0
  123. package/dist/mem-promote.js +257 -0
  124. package/dist/mem-promote.js.map +1 -0
  125. package/dist/mem-ready.js.map +1 -0
  126. package/dist/mem-recover.js.map +1 -0
  127. package/dist/mem-signal.js.map +1 -0
  128. package/dist/mem-start.js.map +1 -0
  129. package/dist/mem-summarize.js.map +1 -0
  130. package/dist/mem-triage.js.map +1 -0
  131. package/dist/merge-block.js +225 -0
  132. package/dist/merge-block.js.map +1 -0
  133. package/dist/metrics-cli.js.map +1 -0
  134. package/dist/metrics-snapshot.js.map +1 -0
  135. package/dist/object-guards.js +9 -0
  136. package/dist/object-guards.js.map +1 -0
  137. package/dist/onboard.js.map +1 -0
  138. package/dist/onboarding-smoke-test.js +432 -0
  139. package/dist/onboarding-smoke-test.js.map +1 -0
  140. package/dist/orchestrate-init-status.js.map +1 -0
  141. package/dist/orchestrate-initiative.js.map +1 -0
  142. package/dist/orchestrate-monitor.js.map +1 -0
  143. package/dist/pack-author.js.map +1 -0
  144. package/dist/pack-hash.js.map +1 -0
  145. package/dist/pack-install.js.map +1 -0
  146. package/dist/pack-publish.js.map +1 -0
  147. package/dist/pack-scaffold.js.map +1 -0
  148. package/dist/pack-search.js.map +1 -0
  149. package/dist/pack-validate.js.map +1 -0
  150. package/dist/plan-create.js.map +1 -0
  151. package/dist/plan-edit.js.map +1 -0
  152. package/dist/plan-link.js.map +1 -0
  153. package/dist/plan-promote.js.map +1 -0
  154. package/dist/public-manifest.js +931 -0
  155. package/dist/public-manifest.js.map +1 -0
  156. package/dist/release.js +664 -116
  157. package/dist/release.js.map +1 -0
  158. package/dist/rotate-progress.js +253 -0
  159. package/dist/rotate-progress.js.map +1 -0
  160. package/dist/session-coordinator.js +303 -0
  161. package/dist/session-coordinator.js.map +1 -0
  162. package/dist/shared-validators.js +81 -0
  163. package/dist/shared-validators.js.map +1 -0
  164. package/dist/signal-cleanup.js.map +1 -0
  165. package/dist/state-bootstrap.js.map +1 -0
  166. package/dist/state-cleanup.js.map +1 -0
  167. package/dist/state-doctor-fix.js +226 -0
  168. package/dist/state-doctor-fix.js.map +1 -0
  169. package/dist/state-doctor-stamps.js +23 -0
  170. package/dist/state-doctor-stamps.js.map +1 -0
  171. package/dist/state-doctor.js.map +1 -0
  172. package/dist/strict-progress.js +255 -0
  173. package/dist/strict-progress.js.map +1 -0
  174. package/dist/sync-templates.js.map +1 -0
  175. package/dist/task-claim.js.map +1 -0
  176. package/dist/trace-gen.js +401 -0
  177. package/dist/trace-gen.js.map +1 -0
  178. package/dist/validate-agent-skills.js +224 -0
  179. package/dist/validate-agent-skills.js.map +1 -0
  180. package/dist/validate-agent-sync.js +152 -0
  181. package/dist/validate-agent-sync.js.map +1 -0
  182. package/dist/validate-backlog-sync.js +77 -0
  183. package/dist/validate-backlog-sync.js.map +1 -0
  184. package/dist/validate-skills-spec.js +211 -0
  185. package/dist/validate-skills-spec.js.map +1 -0
  186. package/dist/validate.js.map +1 -0
  187. package/dist/validator-defaults.js +107 -0
  188. package/dist/validator-defaults.js.map +1 -0
  189. package/dist/validator-registry.js +71 -0
  190. package/dist/validator-registry.js.map +1 -0
  191. package/dist/workspace-init.js.map +1 -0
  192. package/dist/wu-block.js.map +1 -0
  193. package/dist/wu-brief.js.map +1 -0
  194. package/dist/wu-claim-branch.js +123 -0
  195. package/dist/wu-claim-branch.js.map +1 -0
  196. package/dist/wu-claim-cloud.js +79 -0
  197. package/dist/wu-claim-cloud.js.map +1 -0
  198. package/dist/wu-claim-mode.js +82 -0
  199. package/dist/wu-claim-mode.js.map +1 -0
  200. package/dist/wu-claim-output.js +85 -0
  201. package/dist/wu-claim-output.js.map +1 -0
  202. package/dist/wu-claim-repair-guidance.js +12 -0
  203. package/dist/wu-claim-repair-guidance.js.map +1 -0
  204. package/dist/wu-claim-resume-handler.js +87 -0
  205. package/dist/wu-claim-resume-handler.js.map +1 -0
  206. package/dist/wu-claim-state.js +581 -0
  207. package/dist/wu-claim-state.js.map +1 -0
  208. package/dist/wu-claim-validation.js +458 -0
  209. package/dist/wu-claim-validation.js.map +1 -0
  210. package/dist/wu-claim-worktree.js +238 -0
  211. package/dist/wu-claim-worktree.js.map +1 -0
  212. package/dist/wu-claim.js.map +1 -0
  213. package/dist/wu-cleanup-cloud.js +78 -0
  214. package/dist/wu-cleanup-cloud.js.map +1 -0
  215. package/dist/wu-cleanup.js.map +1 -0
  216. package/dist/wu-code-path-coverage.js +83 -0
  217. package/dist/wu-code-path-coverage.js.map +1 -0
  218. package/dist/wu-create-cloud.js +30 -0
  219. package/dist/wu-create-cloud.js.map +1 -0
  220. package/dist/wu-create-content.js +264 -0
  221. package/dist/wu-create-content.js.map +1 -0
  222. package/dist/wu-create-readiness.js +59 -0
  223. package/dist/wu-create-readiness.js.map +1 -0
  224. package/dist/wu-create-validation.js +128 -0
  225. package/dist/wu-create-validation.js.map +1 -0
  226. package/dist/wu-create.js.map +1 -0
  227. package/dist/wu-delegate.js.map +1 -0
  228. package/dist/wu-delete.js.map +1 -0
  229. package/dist/wu-deps.js.map +1 -0
  230. package/dist/wu-done-auto-cleanup.js +194 -0
  231. package/dist/wu-done-auto-cleanup.js.map +1 -0
  232. package/dist/wu-done-check.js +38 -0
  233. package/dist/wu-done-check.js.map +1 -0
  234. package/dist/wu-done-cloud.js +48 -0
  235. package/dist/wu-done-cloud.js.map +1 -0
  236. package/dist/wu-done-decay.js +83 -0
  237. package/dist/wu-done-decay.js.map +1 -0
  238. package/dist/wu-done.js.map +1 -0
  239. package/dist/wu-edit-operations.js +399 -0
  240. package/dist/wu-edit-operations.js.map +1 -0
  241. package/dist/wu-edit-validators.js +282 -0
  242. package/dist/wu-edit-validators.js.map +1 -0
  243. package/dist/wu-edit.js.map +1 -0
  244. package/dist/wu-infer-lane.js.map +1 -0
  245. package/dist/wu-preflight.js.map +1 -0
  246. package/dist/wu-prep.js.map +1 -0
  247. package/dist/wu-proto.js.map +1 -0
  248. package/dist/wu-prune.js.map +1 -0
  249. package/dist/wu-recover.js.map +1 -0
  250. package/dist/wu-release.js.map +1 -0
  251. package/dist/wu-repair.js.map +1 -0
  252. package/dist/wu-sandbox.js.map +1 -0
  253. package/dist/wu-spawn-completion.js +58 -0
  254. package/dist/wu-spawn-completion.js.map +1 -0
  255. package/dist/wu-spawn-prompt-builders.js +1190 -0
  256. package/dist/wu-spawn-prompt-builders.js.map +1 -0
  257. package/dist/wu-spawn-strategy-resolver.js +322 -0
  258. package/dist/wu-spawn-strategy-resolver.js.map +1 -0
  259. package/dist/wu-spawn.js +59 -0
  260. package/dist/wu-spawn.js.map +1 -0
  261. package/dist/wu-state-cloud.js +41 -0
  262. package/dist/wu-state-cloud.js.map +1 -0
  263. package/dist/wu-status.js.map +1 -0
  264. package/dist/wu-unblock.js.map +1 -0
  265. package/dist/wu-unlock-lane.js.map +1 -0
  266. package/dist/wu-validate.js.map +1 -0
  267. package/package.json +8 -10
@@ -0,0 +1,151 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Beautiful CLI Output Formatters
5
+ *
6
+ * WU-1929: Provides branded header, colored status indicators,
7
+ * structured tables, and progress spinners for consistent CLI output.
8
+ *
9
+ * Dependencies: chalk (color), cli-table3 (tables) - both already in package.json.
10
+ * Spinner: lightweight inline implementation (no external dependency).
11
+ *
12
+ * @module formatters
13
+ */
14
+ import chalk from 'chalk';
15
+ import Table from 'cli-table3';
16
+ // ── Constants ───────────────────────────────────────────────────────
17
+ const BRAND_NAME = 'LumenFlow';
18
+ const HEADER_WIDTH = 50;
19
+ const SPINNER_INTERVAL_MS = 80;
20
+ const SPINNER_FRAMES = ['|', '/', '-', '\\'];
21
+ /**
22
+ * Color mappings for WU status values.
23
+ * Maps each status to a chalk color function name.
24
+ */
25
+ export const STATUS_COLORS = {
26
+ ready: chalk.cyan,
27
+ in_progress: chalk.yellow,
28
+ done: chalk.green,
29
+ blocked: chalk.red,
30
+ waiting: chalk.magenta,
31
+ };
32
+ /** Default color for unknown statuses */
33
+ const DEFAULT_STATUS_COLOR = chalk.white;
34
+ // ── AC1: Branded Header ─────────────────────────────────────────────
35
+ /**
36
+ * Format a branded header string with version information.
37
+ *
38
+ * @param options - Header options
39
+ * @param options.version - CLI version string (optional)
40
+ * @returns Formatted header string
41
+ */
42
+ export function formatHeader(options = {}) {
43
+ const separator = chalk.dim('─'.repeat(HEADER_WIDTH));
44
+ const versionStr = options.version ? ` v${options.version}` : '';
45
+ const title = chalk.bold.cyan(`${BRAND_NAME}${versionStr}`);
46
+ const tagline = chalk.dim('The governance layer between AI agents and the world.');
47
+ return [separator, title, tagline, separator].join('\n');
48
+ }
49
+ /**
50
+ * Print the branded header to console.log.
51
+ *
52
+ * @param options - Header options
53
+ * @param options.version - CLI version string (optional)
54
+ */
55
+ export function printHeader(options = {}) {
56
+ console.log(formatHeader(options));
57
+ }
58
+ // ── AC2: Colored Status Indicators ──────────────────────────────────
59
+ /**
60
+ * Apply color to a WU status string based on its value.
61
+ *
62
+ * @param status - The WU status string (e.g., "ready", "in_progress", "done", "blocked")
63
+ * @returns Colored string suitable for terminal output
64
+ */
65
+ export function statusColor(status) {
66
+ const colorFn = STATUS_COLORS[status] ?? DEFAULT_STATUS_COLOR;
67
+ return colorFn(status);
68
+ }
69
+ // ── AC3: Structured Tables ──────────────────────────────────────────
70
+ /**
71
+ * Create a formatted table string using cli-table3.
72
+ *
73
+ * @param options - Table configuration
74
+ * @param options.head - Column headers
75
+ * @param options.rows - Array of row arrays
76
+ * @param options.colWidths - Optional column widths
77
+ * @returns Formatted table string
78
+ */
79
+ export function createStatusTable(options) {
80
+ const tableConfig = {
81
+ head: options.head,
82
+ style: {
83
+ head: ['cyan'],
84
+ },
85
+ };
86
+ if (options.colWidths) {
87
+ tableConfig.colWidths = options.colWidths;
88
+ }
89
+ const table = new Table(tableConfig);
90
+ for (const row of options.rows) {
91
+ table.push(row);
92
+ }
93
+ return table.toString();
94
+ }
95
+ /**
96
+ * Create a lightweight terminal spinner for long-running operations.
97
+ * Uses stderr to avoid polluting stdout (which may be piped).
98
+ * No external dependency required.
99
+ *
100
+ * @param message - The message to display next to the spinner
101
+ * @returns Spinner object with start/stop/succeed/fail methods
102
+ */
103
+ export function createSpinner(message) {
104
+ let intervalId = null;
105
+ let frameIndex = 0;
106
+ function clearLine() {
107
+ // Move cursor to beginning of line and clear it
108
+ process.stderr.write('\r\x1B[K');
109
+ }
110
+ function renderFrame() {
111
+ const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
112
+ clearLine();
113
+ process.stderr.write(`${chalk.cyan(frame)} ${message}`);
114
+ frameIndex++;
115
+ }
116
+ return {
117
+ start() {
118
+ if (intervalId !== null)
119
+ return;
120
+ frameIndex = 0;
121
+ renderFrame();
122
+ intervalId = setInterval(renderFrame, SPINNER_INTERVAL_MS);
123
+ },
124
+ stop() {
125
+ if (intervalId !== null) {
126
+ clearInterval(intervalId);
127
+ intervalId = null;
128
+ }
129
+ clearLine();
130
+ },
131
+ succeed(msg) {
132
+ if (intervalId !== null) {
133
+ clearInterval(intervalId);
134
+ intervalId = null;
135
+ }
136
+ clearLine();
137
+ const text = msg ?? message;
138
+ process.stderr.write(`${chalk.green('✓')} ${text}\n`);
139
+ },
140
+ fail(msg) {
141
+ if (intervalId !== null) {
142
+ clearInterval(intervalId);
143
+ intervalId = null;
144
+ }
145
+ clearLine();
146
+ const text = msg ?? message;
147
+ process.stderr.write(`${chalk.red('✗')} ${text}\n`);
148
+ },
149
+ };
150
+ }
151
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { GATE_NAMES, GATE_COMMANDS, SCRIPTS } from '@lumenflow/core/wu-constants';
4
+ /**
5
+ * Register the default docs-only gates into the registry.
6
+ *
7
+ * These gates run when --docs-only is passed or when risk detection
8
+ * identifies the change as documentation-only.
9
+ *
10
+ * @param registry - Gate registry to populate
11
+ * @param options - Configuration options affecting gate behavior
12
+ */
13
+ export function registerDocsOnlyGates(registry, options) {
14
+ const { laneHealthMode, testsRequired, docsOnlyTestPlan } = options;
15
+ // WU-2252: Invariants check runs first (non-bypassable)
16
+ registry.register({
17
+ name: GATE_NAMES.INVARIANTS,
18
+ cmd: GATE_COMMANDS.INVARIANTS,
19
+ });
20
+ registry.register({
21
+ name: GATE_NAMES.FORMAT_CHECK,
22
+ scriptName: SCRIPTS.FORMAT_CHECK,
23
+ // run function is injected by the gate runner (runFormatCheckGate)
24
+ // We use a sentinel to indicate this gate needs its run function set
25
+ cmd: undefined,
26
+ run: undefined,
27
+ });
28
+ registry.register({
29
+ name: GATE_NAMES.SPEC_LINTER,
30
+ scriptName: SCRIPTS.SPEC_LINTER,
31
+ });
32
+ // WU-1467: prompts:lint removed -- was a stub (exit 0)
33
+ registry.register({
34
+ name: GATE_NAMES.BACKLOG_SYNC,
35
+ });
36
+ registry.register({
37
+ name: GATE_NAMES.CLAIM_VALIDATION,
38
+ });
39
+ // WU-1191: Lane health check (configurable: warn/error/off)
40
+ registry.register({
41
+ name: GATE_NAMES.LANE_HEALTH,
42
+ warnOnly: laneHealthMode !== 'error',
43
+ });
44
+ // WU-1315: Onboarding smoke test
45
+ registry.register({
46
+ name: GATE_NAMES.ONBOARDING_SMOKE_TEST,
47
+ cmd: GATE_COMMANDS.ONBOARDING_SMOKE_TEST,
48
+ });
49
+ // WU-1299: Filtered tests for packages in code_paths (if UnsafeAny)
50
+ if (docsOnlyTestPlan && docsOnlyTestPlan.mode === 'filtered') {
51
+ registry.register({
52
+ name: GATE_NAMES.TEST,
53
+ warnOnly: !testsRequired,
54
+ });
55
+ }
56
+ }
57
+ /**
58
+ * Register the default code gates into the registry.
59
+ *
60
+ * These gates run for non-docs-only changes and include the full
61
+ * lint, typecheck, and test pipeline.
62
+ *
63
+ * @param registry - Gate registry to populate
64
+ * @param options - Configuration options affecting gate behavior
65
+ */
66
+ export function registerCodeGates(registry, options) {
67
+ const { isFullLint, isFullTests, isFullCoverage, laneHealthMode, testsRequired, shouldRunIntegration, configuredTestFullCmd, } = options;
68
+ // WU-2252: Invariants check runs first (non-bypassable)
69
+ registry.register({
70
+ name: GATE_NAMES.INVARIANTS,
71
+ cmd: GATE_COMMANDS.INVARIANTS,
72
+ });
73
+ registry.register({
74
+ name: GATE_NAMES.FORMAT_CHECK,
75
+ scriptName: SCRIPTS.FORMAT_CHECK,
76
+ });
77
+ registry.register({
78
+ name: GATE_NAMES.LINT,
79
+ cmd: isFullLint ? `pnpm ${SCRIPTS.LINT}` : GATE_COMMANDS.INCREMENTAL,
80
+ scriptName: SCRIPTS.LINT,
81
+ });
82
+ registry.register({
83
+ name: GATE_NAMES.TYPECHECK,
84
+ cmd: `pnpm ${SCRIPTS.TYPECHECK}`,
85
+ scriptName: SCRIPTS.TYPECHECK,
86
+ });
87
+ registry.register({
88
+ name: GATE_NAMES.SPEC_LINTER,
89
+ scriptName: SCRIPTS.SPEC_LINTER,
90
+ });
91
+ // WU-1467: prompts:lint removed -- was a stub (exit 0)
92
+ registry.register({
93
+ name: GATE_NAMES.BACKLOG_SYNC,
94
+ });
95
+ registry.register({
96
+ name: GATE_NAMES.CLAIM_VALIDATION,
97
+ });
98
+ registry.register({
99
+ name: GATE_NAMES.SUPABASE_DOCS_LINTER,
100
+ });
101
+ // WU-1191: Lane health check
102
+ registry.register({
103
+ name: GATE_NAMES.LANE_HEALTH,
104
+ warnOnly: laneHealthMode !== 'error',
105
+ });
106
+ // WU-1315: Onboarding smoke test
107
+ registry.register({
108
+ name: GATE_NAMES.ONBOARDING_SMOKE_TEST,
109
+ cmd: GATE_COMMANDS.ONBOARDING_SMOKE_TEST,
110
+ });
111
+ // WU-2062: Safety-critical tests ALWAYS run
112
+ registry.register({
113
+ name: GATE_NAMES.SAFETY_CRITICAL_TEST,
114
+ cmd: GATE_COMMANDS.SAFETY_CRITICAL_TEST,
115
+ warnOnly: !testsRequired,
116
+ });
117
+ // WU-1920: Changed tests by default, full suite with --full-tests
118
+ registry.register({
119
+ name: GATE_NAMES.TEST,
120
+ cmd: isFullTests || isFullCoverage ? configuredTestFullCmd : GATE_COMMANDS.INCREMENTAL_TEST,
121
+ warnOnly: !testsRequired,
122
+ });
123
+ // WU-2062: Integration tests only for high-risk changes
124
+ if (shouldRunIntegration) {
125
+ registry.register({
126
+ name: GATE_NAMES.INTEGRATION_TEST,
127
+ cmd: GATE_COMMANDS.TIERED_TEST,
128
+ warnOnly: !testsRequired,
129
+ });
130
+ }
131
+ // WU-1433: Coverage gate
132
+ registry.register({
133
+ name: GATE_NAMES.COVERAGE,
134
+ cmd: GATE_COMMANDS.COVERAGE_GATE,
135
+ });
136
+ }
137
+ //# sourceMappingURL=gate-defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-defaults.js","sourceRoot":"","sources":["../src/gate-defaults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Registry for quality gates.
5
+ *
6
+ * Gates are registered in order and executed sequentially.
7
+ * New gates can be added by calling `register()` without modifying
8
+ * the core executeGates() function.
9
+ */
10
+ export class GateRegistry {
11
+ gates = [];
12
+ nameIndex = new Map();
13
+ /**
14
+ * Register a single gate definition.
15
+ *
16
+ * @param gate - Gate definition to register
17
+ * @throws Error if a gate with the same name is already registered
18
+ */
19
+ register(gate) {
20
+ if (this.nameIndex.has(gate.name)) {
21
+ throw new Error(`Gate "${gate.name}" is already registered`);
22
+ }
23
+ this.nameIndex.set(gate.name, this.gates.length);
24
+ this.gates.push(gate);
25
+ }
26
+ /**
27
+ * Register multiple gate definitions at once.
28
+ *
29
+ * @param gates - Array of gate definitions to register
30
+ */
31
+ registerAll(gates) {
32
+ for (const gate of gates) {
33
+ this.register(gate);
34
+ }
35
+ }
36
+ /**
37
+ * Get all registered gates in insertion order.
38
+ *
39
+ * @returns Copy of the gates array
40
+ */
41
+ getAll() {
42
+ return [...this.gates];
43
+ }
44
+ /**
45
+ * Get a gate by name.
46
+ *
47
+ * @param name - Gate name to look up
48
+ * @returns Gate definition or undefined if not found
49
+ */
50
+ get(name) {
51
+ const index = this.nameIndex.get(name);
52
+ if (index === undefined)
53
+ return undefined;
54
+ return this.gates[index];
55
+ }
56
+ /**
57
+ * Check if a gate with the given name is registered.
58
+ *
59
+ * @param name - Gate name to check
60
+ * @returns true if the gate exists
61
+ */
62
+ has(name) {
63
+ return this.nameIndex.has(name);
64
+ }
65
+ /**
66
+ * Remove all registered gates.
67
+ */
68
+ clear() {
69
+ this.gates.length = 0;
70
+ this.nameIndex.clear();
71
+ }
72
+ }
73
+ //# sourceMappingURL=gate-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-registry.js","sourceRoot":"","sources":["../src/gate-registry.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAgDzC;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACN,KAAK,GAAqB,EAAE,CAAC;IAC7B,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvD;;;;;OAKG;IACH,QAAQ,CAAC,IAAoB;QAC3B,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,yBAAyB,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,KAAuB;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,IAAY;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,153 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Gates Graceful Degradation
5
+ *
6
+ * WU-1520: When gate scripts (format:check, lint, typecheck, spec:linter)
7
+ * are missing from package.json, emit a warning and skip instead of failing.
8
+ *
9
+ * Defense in depth: even if scaffold adds scripts, gates should degrade
10
+ * gracefully for UnsafeAny missing script.
11
+ *
12
+ * @module gates-graceful-degradation
13
+ */
14
+ import { readFileSync, existsSync } from 'node:fs';
15
+ import path from 'node:path';
16
+ /**
17
+ * Scripts that can be skipped when missing from package.json.
18
+ * These are optional tooling scripts that not every project configures.
19
+ */
20
+ export const SKIPPABLE_GATE_SCRIPTS = [
21
+ 'format:check',
22
+ 'lint',
23
+ 'typecheck',
24
+ 'spec:linter',
25
+ ];
26
+ /**
27
+ * Gates that are never skippable, regardless of configuration.
28
+ * These enforce critical invariants and must always run.
29
+ */
30
+ export const NON_SKIPPABLE_GATES = ['invariants'];
31
+ /**
32
+ * Check whether a script exists in a package.json scripts object.
33
+ *
34
+ * @param scriptName - The script name to check (e.g., 'lint', 'format:check')
35
+ * @param scripts - The scripts object from package.json, or undefined
36
+ * @returns true if the script exists
37
+ */
38
+ export function checkScriptExists(scriptName, scripts) {
39
+ if (!scripts)
40
+ return false;
41
+ return Object.prototype.hasOwnProperty.call(scripts, scriptName);
42
+ }
43
+ /**
44
+ * Load the scripts object from a package.json file.
45
+ *
46
+ * @param projectRoot - Project root directory containing package.json
47
+ * @returns The scripts object, or undefined if package.json is missing or unreadable
48
+ */
49
+ export function loadPackageJsonScripts(projectRoot) {
50
+ const packageJsonPath = path.join(projectRoot, 'package.json');
51
+ if (!existsSync(packageJsonPath))
52
+ return undefined;
53
+ try {
54
+ const content = readFileSync(packageJsonPath, 'utf8');
55
+ const pkg = JSON.parse(content);
56
+ return pkg.scripts;
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ }
62
+ /**
63
+ * Build a human-readable warning message for a missing gate script.
64
+ * Includes instructions on how to add the missing script.
65
+ *
66
+ * @param scriptName - The missing script name
67
+ * @returns Warning message string
68
+ */
69
+ export function buildMissingScriptWarning(scriptName) {
70
+ const suggestions = {
71
+ 'format:check': '"format:check": "prettier --check ."',
72
+ lint: '"lint": "eslint ."',
73
+ typecheck: '"typecheck": "tsc --noEmit"',
74
+ 'spec:linter': '"spec:linter": "node tools/spec-linter.js"',
75
+ };
76
+ const suggestion = suggestions[scriptName] ?? `"${scriptName}": "<your-command>"`;
77
+ return [
78
+ `Warning: "${scriptName}" script not found in package.json - skipping gate.`,
79
+ ` To enable this gate, add to your package.json scripts:`,
80
+ ` ${suggestion}`,
81
+ ].join('\n');
82
+ }
83
+ /**
84
+ * Determine whether a gate should be skipped due to a missing script.
85
+ *
86
+ * @param gateName - The gate name (e.g., 'lint', 'invariants')
87
+ * @param scriptName - The underlying script name, or null for non-script gates
88
+ * @param scripts - The scripts object from package.json
89
+ * @param strict - When true, missing scripts cause a hard failure instead of skip
90
+ * @returns 'skip' if the gate should be skipped, 'run' if it should run, 'fail' if strict mode failure
91
+ */
92
+ export function resolveGateAction(gateName, scriptName, scripts, strict) {
93
+ // Non-skippable gates always run
94
+ if (NON_SKIPPABLE_GATES.includes(gateName)) {
95
+ return 'run';
96
+ }
97
+ // If no script name is associated (e.g., custom run functions), always run
98
+ if (!scriptName) {
99
+ return 'run';
100
+ }
101
+ // If script exists, run it
102
+ if (checkScriptExists(scriptName, scripts)) {
103
+ return 'run';
104
+ }
105
+ // Script is missing
106
+ if (strict) {
107
+ return 'fail';
108
+ }
109
+ return 'skip';
110
+ }
111
+ /**
112
+ * Format a summary of gate results showing passed, skipped, and failed gates.
113
+ *
114
+ * @param results - Array of gate results
115
+ * @returns Formatted summary string
116
+ */
117
+ export function formatGateSummary(results) {
118
+ if (results.length === 0) {
119
+ return 'No gates were executed.';
120
+ }
121
+ const passed = results.filter((r) => r.status === 'passed');
122
+ const skipped = results.filter((r) => r.status === 'skipped');
123
+ const failed = results.filter((r) => r.status === 'failed');
124
+ const warned = results.filter((r) => r.status === 'warned');
125
+ const lines = [];
126
+ lines.push('Gate Summary:');
127
+ lines.push('');
128
+ for (const result of results) {
129
+ const statusIcon = result.status === 'passed'
130
+ ? 'PASS'
131
+ : result.status === 'skipped'
132
+ ? 'SKIP'
133
+ : result.status === 'warned'
134
+ ? 'WARN'
135
+ : 'FAIL';
136
+ const duration = result.durationMs > 0 ? ` (${result.durationMs}ms)` : '';
137
+ const reason = result.reason ? ` - ${result.reason}` : '';
138
+ lines.push(` [${statusIcon}] ${result.name}${duration}${reason}`);
139
+ }
140
+ lines.push('');
141
+ const parts = [];
142
+ if (passed.length > 0)
143
+ parts.push(`${passed.length} passed`);
144
+ if (skipped.length > 0)
145
+ parts.push(`${skipped.length} skipped`);
146
+ if (warned.length > 0)
147
+ parts.push(`${warned.length} warned`);
148
+ if (failed.length > 0)
149
+ parts.push(`${failed.length} failed`);
150
+ lines.push(parts.join(', '));
151
+ return lines.join('\n');
152
+ }
153
+ //# sourceMappingURL=gates-graceful-degradation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates-graceful-degradation.js","sourceRoot":"","sources":["../src/gates-graceful-degradation.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAqB7B;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD,cAAc;IACd,MAAM;IACN,WAAW;IACX,aAAa;CACL,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAsB,CAAC,YAAY,CAAU,CAAC;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAkB,EAClB,OAA2C;IAE3C,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC/D,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,SAAS,CAAC;IAEnD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAyC,CAAC;QACxE,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,MAAM,WAAW,GAA2B;QAC1C,cAAc,EAAE,sCAAsC;QACtD,IAAI,EAAE,oBAAoB;QAC1B,SAAS,EAAE,6BAA6B;QACxC,aAAa,EAAE,4CAA4C;KAC5D,CAAC;IAEF,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,IAAI,IAAI,UAAU,qBAAqB,CAAC;IAElF,OAAO;QACL,aAAa,UAAU,qDAAqD;QAC5E,0DAA0D;QAC1D,OAAO,UAAU,EAAE;KACpB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,UAAyB,EACzB,OAA2C,EAC3C,MAAe;IAEf,iCAAiC;IACjC,IAAI,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2EAA2E;IAC3E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2BAA2B;IAC3B,IAAI,iBAAiB,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oBAAoB;IACpB,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAqB;IACrD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,yBAAyB,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAE5D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,UAAU,GACd,MAAM,CAAC,MAAM,KAAK,QAAQ;YACxB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;gBAC3B,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,QAAQ;oBAC1B,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,MAAM,CAAC;QAEjB,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1D,KAAK,CAAC,IAAI,CAAC,MAAM,UAAU,KAAK,MAAM,CAAC,IAAI,GAAG,QAAQ,GAAG,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IAC7D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IAC7D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IAE7D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAE7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}