@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.
- package/dist/agent-issues-query.js.map +1 -0
- package/dist/agent-log-issue.js.map +1 -0
- package/dist/agent-session-end.js.map +1 -0
- package/dist/agent-session.js.map +1 -0
- package/dist/backlog-prune.js.map +1 -0
- package/dist/cli-entry-point.js +139 -0
- package/dist/cli-entry-point.js.map +1 -0
- package/dist/commands/integrate.js.map +1 -0
- package/dist/commands.js.map +1 -0
- package/dist/config-get.js.map +1 -0
- package/dist/config-set.js.map +1 -0
- package/dist/constants.js +98 -0
- package/dist/constants.js.map +1 -0
- package/dist/delegation-list.js.map +1 -0
- package/dist/deps-add.js +259 -0
- package/dist/deps-add.js.map +1 -0
- package/dist/deps-remove.js +105 -0
- package/dist/deps-remove.js.map +1 -0
- package/dist/docs-sync.js.map +1 -0
- package/dist/doctor.js.map +1 -0
- package/dist/file-delete.js.map +1 -0
- package/dist/file-edit.js.map +1 -0
- package/dist/file-read.js.map +1 -0
- package/dist/file-write.js.map +1 -0
- package/dist/flow-bottlenecks.js.map +1 -0
- package/dist/flow-report.js.map +1 -0
- package/dist/formatters.js +151 -0
- package/dist/formatters.js.map +1 -0
- package/dist/gate-defaults.js +137 -0
- package/dist/gate-defaults.js.map +1 -0
- package/dist/gate-registry.js +73 -0
- package/dist/gate-registry.js.map +1 -0
- package/dist/gates-graceful-degradation.js +153 -0
- package/dist/gates-graceful-degradation.js.map +1 -0
- package/dist/gates-plan-resolvers.js +190 -0
- package/dist/gates-plan-resolvers.js.map +1 -0
- package/dist/gates-runners.js +545 -0
- package/dist/gates-runners.js.map +1 -0
- package/dist/gates-types.js +4 -0
- package/dist/gates-types.js.map +1 -0
- package/dist/gates-utils.js +333 -0
- package/dist/gates-utils.js.map +1 -0
- package/dist/gates.js.map +1 -0
- package/dist/git-branch.js.map +1 -0
- package/dist/git-diff.js.map +1 -0
- package/dist/git-log.js.map +1 -0
- package/dist/git-status.js.map +1 -0
- package/dist/guard-locked.js +172 -0
- package/dist/guard-locked.js.map +1 -0
- package/dist/guard-main-branch.js +217 -0
- package/dist/guard-main-branch.js.map +1 -0
- package/dist/guard-worktree-commit.js +163 -0
- package/dist/guard-worktree-commit.js.map +1 -0
- package/dist/hooks/auto-checkpoint-utils.js +54 -0
- package/dist/hooks/auto-checkpoint-utils.js.map +1 -0
- package/dist/hooks/enforcement-checks.js +399 -0
- package/dist/hooks/enforcement-checks.js.map +1 -0
- package/dist/hooks/enforcement-generator.js +139 -0
- package/dist/hooks/enforcement-generator.js.map +1 -0
- package/dist/hooks/enforcement-sync.js +380 -0
- package/dist/hooks/enforcement-sync.js.map +1 -0
- package/dist/hooks/generators/auto-checkpoint.js +125 -0
- package/dist/hooks/generators/auto-checkpoint.js.map +1 -0
- package/dist/hooks/generators/enforce-worktree.js +190 -0
- package/dist/hooks/generators/enforce-worktree.js.map +1 -0
- package/dist/hooks/generators/index.js +18 -0
- package/dist/hooks/generators/index.js.map +1 -0
- package/dist/hooks/generators/pre-compact-checkpoint.js +136 -0
- package/dist/hooks/generators/pre-compact-checkpoint.js.map +1 -0
- package/dist/hooks/generators/require-wu.js +117 -0
- package/dist/hooks/generators/require-wu.js.map +1 -0
- package/dist/hooks/generators/session-start-recovery.js +103 -0
- package/dist/hooks/generators/session-start-recovery.js.map +1 -0
- package/dist/hooks/generators/signal-utils.js +54 -0
- package/dist/hooks/generators/signal-utils.js.map +1 -0
- package/dist/hooks/generators/warn-incomplete.js +67 -0
- package/dist/hooks/generators/warn-incomplete.js.map +1 -0
- package/dist/hooks/index.js +10 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/init-detection.js +232 -0
- package/dist/init-detection.js.map +1 -0
- package/dist/init-lane-validation.js +147 -0
- package/dist/init-lane-validation.js.map +1 -0
- package/dist/init-scaffolding.js +158 -0
- package/dist/init-scaffolding.js.map +1 -0
- package/dist/init-templates.js +1983 -0
- package/dist/init-templates.js.map +1 -0
- package/dist/init.js.map +1 -0
- package/dist/initiative-add-wu.js.map +1 -0
- package/dist/initiative-bulk-assign-wus.js.map +1 -0
- package/dist/initiative-create.js.map +1 -0
- package/dist/initiative-edit.js.map +1 -0
- package/dist/initiative-list.js.map +1 -0
- package/dist/initiative-plan.js.map +1 -0
- package/dist/initiative-remove-wu.js.map +1 -0
- package/dist/initiative-status.js.map +1 -0
- package/dist/lane-edit.js.map +1 -0
- package/dist/lane-health.js.map +1 -0
- package/dist/lane-lifecycle-process.js +381 -0
- package/dist/lane-lifecycle-process.js.map +1 -0
- package/dist/lane-lock.js.map +1 -0
- package/dist/lane-setup.js.map +1 -0
- package/dist/lane-status.js.map +1 -0
- package/dist/lane-suggest.js.map +1 -0
- package/dist/lane-validate.js.map +1 -0
- package/dist/lifecycle-regression-harness.js +181 -0
- package/dist/lifecycle-regression-harness.js.map +1 -0
- package/dist/lumenflow-upgrade.js +18 -10
- package/dist/lumenflow-upgrade.js.map +1 -0
- package/dist/mem-checkpoint.js.map +1 -0
- package/dist/mem-cleanup.js.map +1 -0
- package/dist/mem-context.js.map +1 -0
- package/dist/mem-create.js.map +1 -0
- package/dist/mem-delete.js.map +1 -0
- package/dist/mem-export.js.map +1 -0
- package/dist/mem-inbox.js.map +1 -0
- package/dist/mem-index.js +214 -0
- package/dist/mem-index.js.map +1 -0
- package/dist/mem-init.js.map +1 -0
- package/dist/mem-profile.js +210 -0
- package/dist/mem-profile.js.map +1 -0
- package/dist/mem-promote.js +257 -0
- package/dist/mem-promote.js.map +1 -0
- package/dist/mem-ready.js.map +1 -0
- package/dist/mem-recover.js.map +1 -0
- package/dist/mem-signal.js.map +1 -0
- package/dist/mem-start.js.map +1 -0
- package/dist/mem-summarize.js.map +1 -0
- package/dist/mem-triage.js.map +1 -0
- package/dist/merge-block.js +225 -0
- package/dist/merge-block.js.map +1 -0
- package/dist/metrics-cli.js.map +1 -0
- package/dist/metrics-snapshot.js.map +1 -0
- package/dist/object-guards.js +9 -0
- package/dist/object-guards.js.map +1 -0
- package/dist/onboard.js.map +1 -0
- package/dist/onboarding-smoke-test.js +432 -0
- package/dist/onboarding-smoke-test.js.map +1 -0
- package/dist/orchestrate-init-status.js.map +1 -0
- package/dist/orchestrate-initiative.js.map +1 -0
- package/dist/orchestrate-monitor.js.map +1 -0
- package/dist/pack-author.js.map +1 -0
- package/dist/pack-hash.js.map +1 -0
- package/dist/pack-install.js.map +1 -0
- package/dist/pack-publish.js.map +1 -0
- package/dist/pack-scaffold.js.map +1 -0
- package/dist/pack-search.js.map +1 -0
- package/dist/pack-validate.js.map +1 -0
- package/dist/plan-create.js.map +1 -0
- package/dist/plan-edit.js.map +1 -0
- package/dist/plan-link.js.map +1 -0
- package/dist/plan-promote.js.map +1 -0
- package/dist/public-manifest.js +931 -0
- package/dist/public-manifest.js.map +1 -0
- package/dist/release.js +664 -116
- package/dist/release.js.map +1 -0
- package/dist/rotate-progress.js +253 -0
- package/dist/rotate-progress.js.map +1 -0
- package/dist/session-coordinator.js +303 -0
- package/dist/session-coordinator.js.map +1 -0
- package/dist/shared-validators.js +81 -0
- package/dist/shared-validators.js.map +1 -0
- package/dist/signal-cleanup.js.map +1 -0
- package/dist/state-bootstrap.js.map +1 -0
- package/dist/state-cleanup.js.map +1 -0
- package/dist/state-doctor-fix.js +226 -0
- package/dist/state-doctor-fix.js.map +1 -0
- package/dist/state-doctor-stamps.js +23 -0
- package/dist/state-doctor-stamps.js.map +1 -0
- package/dist/state-doctor.js.map +1 -0
- package/dist/strict-progress.js +255 -0
- package/dist/strict-progress.js.map +1 -0
- package/dist/sync-templates.js.map +1 -0
- package/dist/task-claim.js.map +1 -0
- package/dist/trace-gen.js +401 -0
- package/dist/trace-gen.js.map +1 -0
- package/dist/validate-agent-skills.js +224 -0
- package/dist/validate-agent-skills.js.map +1 -0
- package/dist/validate-agent-sync.js +152 -0
- package/dist/validate-agent-sync.js.map +1 -0
- package/dist/validate-backlog-sync.js +77 -0
- package/dist/validate-backlog-sync.js.map +1 -0
- package/dist/validate-skills-spec.js +211 -0
- package/dist/validate-skills-spec.js.map +1 -0
- package/dist/validate.js.map +1 -0
- package/dist/validator-defaults.js +107 -0
- package/dist/validator-defaults.js.map +1 -0
- package/dist/validator-registry.js +71 -0
- package/dist/validator-registry.js.map +1 -0
- package/dist/workspace-init.js.map +1 -0
- package/dist/wu-block.js.map +1 -0
- package/dist/wu-brief.js.map +1 -0
- package/dist/wu-claim-branch.js +123 -0
- package/dist/wu-claim-branch.js.map +1 -0
- package/dist/wu-claim-cloud.js +79 -0
- package/dist/wu-claim-cloud.js.map +1 -0
- package/dist/wu-claim-mode.js +82 -0
- package/dist/wu-claim-mode.js.map +1 -0
- package/dist/wu-claim-output.js +85 -0
- package/dist/wu-claim-output.js.map +1 -0
- package/dist/wu-claim-repair-guidance.js +12 -0
- package/dist/wu-claim-repair-guidance.js.map +1 -0
- package/dist/wu-claim-resume-handler.js +87 -0
- package/dist/wu-claim-resume-handler.js.map +1 -0
- package/dist/wu-claim-state.js +581 -0
- package/dist/wu-claim-state.js.map +1 -0
- package/dist/wu-claim-validation.js +458 -0
- package/dist/wu-claim-validation.js.map +1 -0
- package/dist/wu-claim-worktree.js +238 -0
- package/dist/wu-claim-worktree.js.map +1 -0
- package/dist/wu-claim.js.map +1 -0
- package/dist/wu-cleanup-cloud.js +78 -0
- package/dist/wu-cleanup-cloud.js.map +1 -0
- package/dist/wu-cleanup.js.map +1 -0
- package/dist/wu-code-path-coverage.js +83 -0
- package/dist/wu-code-path-coverage.js.map +1 -0
- package/dist/wu-create-cloud.js +30 -0
- package/dist/wu-create-cloud.js.map +1 -0
- package/dist/wu-create-content.js +264 -0
- package/dist/wu-create-content.js.map +1 -0
- package/dist/wu-create-readiness.js +59 -0
- package/dist/wu-create-readiness.js.map +1 -0
- package/dist/wu-create-validation.js +128 -0
- package/dist/wu-create-validation.js.map +1 -0
- package/dist/wu-create.js.map +1 -0
- package/dist/wu-delegate.js.map +1 -0
- package/dist/wu-delete.js.map +1 -0
- package/dist/wu-deps.js.map +1 -0
- package/dist/wu-done-auto-cleanup.js +194 -0
- package/dist/wu-done-auto-cleanup.js.map +1 -0
- package/dist/wu-done-check.js +38 -0
- package/dist/wu-done-check.js.map +1 -0
- package/dist/wu-done-cloud.js +48 -0
- package/dist/wu-done-cloud.js.map +1 -0
- package/dist/wu-done-decay.js +83 -0
- package/dist/wu-done-decay.js.map +1 -0
- package/dist/wu-done.js.map +1 -0
- package/dist/wu-edit-operations.js +399 -0
- package/dist/wu-edit-operations.js.map +1 -0
- package/dist/wu-edit-validators.js +282 -0
- package/dist/wu-edit-validators.js.map +1 -0
- package/dist/wu-edit.js.map +1 -0
- package/dist/wu-infer-lane.js.map +1 -0
- package/dist/wu-preflight.js.map +1 -0
- package/dist/wu-prep.js.map +1 -0
- package/dist/wu-proto.js.map +1 -0
- package/dist/wu-prune.js.map +1 -0
- package/dist/wu-recover.js.map +1 -0
- package/dist/wu-release.js.map +1 -0
- package/dist/wu-repair.js.map +1 -0
- package/dist/wu-sandbox.js.map +1 -0
- package/dist/wu-spawn-completion.js +58 -0
- package/dist/wu-spawn-completion.js.map +1 -0
- package/dist/wu-spawn-prompt-builders.js +1190 -0
- package/dist/wu-spawn-prompt-builders.js.map +1 -0
- package/dist/wu-spawn-strategy-resolver.js +322 -0
- package/dist/wu-spawn-strategy-resolver.js.map +1 -0
- package/dist/wu-spawn.js +59 -0
- package/dist/wu-spawn.js.map +1 -0
- package/dist/wu-state-cloud.js +41 -0
- package/dist/wu-state-cloud.js.map +1 -0
- package/dist/wu-status.js.map +1 -0
- package/dist/wu-unblock.js.map +1 -0
- package/dist/wu-unlock-lane.js.map +1 -0
- package/dist/wu-validate.js.map +1 -0
- 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":"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"}
|