@lumenflow/cli 2.2.2 → 2.3.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/README.md +147 -57
- package/dist/__tests__/agent-log-issue.test.js +56 -0
- package/dist/__tests__/cli-entry-point.test.js +66 -17
- package/dist/__tests__/cli-subprocess.test.js +25 -0
- package/dist/__tests__/init.test.js +298 -0
- package/dist/__tests__/initiative-plan.test.js +340 -0
- package/dist/__tests__/mem-cleanup-execution.test.js +19 -0
- package/dist/__tests__/merge-block.test.js +220 -0
- package/dist/__tests__/safe-git.test.js +191 -0
- package/dist/__tests__/state-doctor.test.js +274 -0
- package/dist/__tests__/wu-done.test.js +36 -0
- package/dist/__tests__/wu-edit.test.js +119 -0
- package/dist/__tests__/wu-prep.test.js +108 -0
- package/dist/agent-issues-query.js +4 -3
- package/dist/agent-log-issue.js +25 -4
- package/dist/backlog-prune.js +5 -4
- package/dist/cli-entry-point.js +11 -1
- package/dist/doctor.js +368 -0
- package/dist/flow-bottlenecks.js +6 -5
- package/dist/flow-report.js +4 -3
- package/dist/gates.js +356 -101
- package/dist/guard-locked.js +4 -3
- package/dist/guard-worktree-commit.js +4 -3
- package/dist/init.js +508 -86
- package/dist/initiative-add-wu.js +4 -3
- package/dist/initiative-bulk-assign-wus.js +8 -5
- package/dist/initiative-create.js +73 -37
- package/dist/initiative-edit.js +37 -21
- package/dist/initiative-list.js +4 -3
- package/dist/initiative-plan.js +337 -0
- package/dist/initiative-status.js +4 -3
- package/dist/lane-health.js +377 -0
- package/dist/lane-suggest.js +382 -0
- package/dist/mem-checkpoint.js +2 -2
- package/dist/mem-cleanup.js +2 -2
- package/dist/mem-context.js +306 -0
- package/dist/mem-create.js +2 -2
- package/dist/mem-delete.js +293 -0
- package/dist/mem-inbox.js +2 -2
- package/dist/mem-index.js +211 -0
- package/dist/mem-init.js +1 -1
- package/dist/mem-profile.js +207 -0
- package/dist/mem-promote.js +254 -0
- package/dist/mem-ready.js +2 -2
- package/dist/mem-signal.js +2 -2
- package/dist/mem-start.js +2 -2
- package/dist/mem-summarize.js +2 -2
- package/dist/mem-triage.js +2 -2
- package/dist/merge-block.js +222 -0
- package/dist/metrics-cli.js +7 -4
- package/dist/metrics-snapshot.js +4 -3
- package/dist/orchestrate-initiative.js +10 -4
- package/dist/orchestrate-monitor.js +379 -31
- package/dist/signal-cleanup.js +296 -0
- package/dist/spawn-list.js +6 -5
- package/dist/state-bootstrap.js +5 -4
- package/dist/state-cleanup.js +360 -0
- package/dist/state-doctor-fix.js +196 -0
- package/dist/state-doctor.js +501 -0
- package/dist/validate-agent-skills.js +4 -3
- package/dist/validate-agent-sync.js +4 -3
- package/dist/validate-backlog-sync.js +4 -3
- package/dist/validate-skills-spec.js +4 -3
- package/dist/validate.js +4 -3
- package/dist/wu-block.js +3 -3
- package/dist/wu-claim.js +208 -98
- package/dist/wu-cleanup.js +5 -4
- package/dist/wu-create.js +71 -46
- package/dist/wu-delete.js +88 -60
- package/dist/wu-deps.js +6 -5
- package/dist/wu-done-check.js +34 -0
- package/dist/wu-done.js +39 -12
- package/dist/wu-edit.js +63 -28
- package/dist/wu-infer-lane.js +7 -6
- package/dist/wu-preflight.js +23 -81
- package/dist/wu-prep.js +125 -0
- package/dist/wu-prune.js +4 -3
- package/dist/wu-recover.js +88 -22
- package/dist/wu-repair.js +7 -6
- package/dist/wu-spawn.js +226 -270
- package/dist/wu-status.js +4 -3
- package/dist/wu-unblock.js +5 -5
- package/dist/wu-unlock-lane.js +4 -3
- package/dist/wu-validate.js +5 -4
- package/package.json +16 -7
- package/templates/core/.lumenflow/constraints.md.template +192 -0
- package/templates/core/.lumenflow/rules/git-safety.md.template +27 -0
- package/templates/core/.lumenflow/rules/wu-workflow.md.template +48 -0
- package/templates/core/AGENTS.md.template +60 -0
- package/templates/core/LUMENFLOW.md.template +255 -0
- package/templates/core/UPGRADING.md.template +121 -0
- package/templates/core/ai/onboarding/agent-safety-card.md.template +106 -0
- package/templates/core/ai/onboarding/first-wu-mistakes.md.template +198 -0
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +186 -0
- package/templates/core/ai/onboarding/release-process.md.template +362 -0
- package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +159 -0
- package/templates/core/ai/onboarding/wu-create-checklist.md.template +117 -0
- package/templates/vendors/aider/.aider.conf.yml.template +27 -0
- package/templates/vendors/claude/.claude/CLAUDE.md.template +52 -0
- package/templates/vendors/claude/.claude/settings.json.template +49 -0
- package/templates/vendors/claude/.claude/skills/bug-classification/SKILL.md.template +192 -0
- package/templates/vendors/claude/.claude/skills/code-quality/SKILL.md.template +152 -0
- package/templates/vendors/claude/.claude/skills/context-management/SKILL.md.template +155 -0
- package/templates/vendors/claude/.claude/skills/execution-memory/SKILL.md.template +304 -0
- package/templates/vendors/claude/.claude/skills/frontend-design/SKILL.md.template +131 -0
- package/templates/vendors/claude/.claude/skills/initiative-management/SKILL.md.template +164 -0
- package/templates/vendors/claude/.claude/skills/library-first/SKILL.md.template +98 -0
- package/templates/vendors/claude/.claude/skills/lumenflow-gates/SKILL.md.template +87 -0
- package/templates/vendors/claude/.claude/skills/multi-agent-coordination/SKILL.md.template +84 -0
- package/templates/vendors/claude/.claude/skills/ops-maintenance/SKILL.md.template +254 -0
- package/templates/vendors/claude/.claude/skills/orchestration/SKILL.md.template +189 -0
- package/templates/vendors/claude/.claude/skills/tdd-workflow/SKILL.md.template +139 -0
- package/templates/vendors/claude/.claude/skills/worktree-discipline/SKILL.md.template +138 -0
- package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +106 -0
- package/templates/vendors/cline/.clinerules.template +53 -0
- package/templates/vendors/cursor/.cursor/rules/lumenflow.md.template +34 -0
- package/templates/vendors/cursor/.cursor/rules.md.template +28 -0
- package/templates/vendors/windsurf/.windsurf/rules/lumenflow.md.template +34 -0
package/README.md
CHANGED
|
@@ -13,6 +13,25 @@
|
|
|
13
13
|
npm install @lumenflow/cli
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Initialize LumenFlow (works with any AI)
|
|
20
|
+
npx lumenflow-init
|
|
21
|
+
|
|
22
|
+
# Or specify your AI tool for enhanced integration
|
|
23
|
+
npx lumenflow-init --client claude # Claude Code
|
|
24
|
+
npx lumenflow-init --client cursor # Cursor
|
|
25
|
+
npx lumenflow-init --client windsurf # Windsurf
|
|
26
|
+
npx lumenflow-init --client cline # Cline
|
|
27
|
+
npx lumenflow-init --client aider # Aider
|
|
28
|
+
npx lumenflow-init --client all # All integrations
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The default `lumenflow-init` creates `AGENTS.md` and `LUMENFLOW.md` which work with **any AI coding assistant**. The `--client` flag adds vendor-specific configuration files for deeper integration.
|
|
32
|
+
|
|
33
|
+
See [AI Integrations](https://lumenflow.dev/guides/ai-integrations) for details on each tool.
|
|
34
|
+
|
|
16
35
|
## Overview
|
|
17
36
|
|
|
18
37
|
This package provides CLI commands for the LumenFlow workflow framework, including:
|
|
@@ -24,63 +43,134 @@ This package provides CLI commands for the LumenFlow workflow framework, includi
|
|
|
24
43
|
|
|
25
44
|
## Commands
|
|
26
45
|
|
|
27
|
-
### Work Unit
|
|
28
|
-
|
|
29
|
-
| Command
|
|
30
|
-
|
|
|
31
|
-
| `wu-
|
|
32
|
-
| `wu-
|
|
33
|
-
| `wu-
|
|
34
|
-
| `wu-
|
|
35
|
-
| `wu-
|
|
36
|
-
| `wu-
|
|
37
|
-
| `wu-
|
|
38
|
-
| `wu-
|
|
39
|
-
| `wu-
|
|
40
|
-
| `wu-
|
|
41
|
-
| `wu-prune`
|
|
42
|
-
| `wu-
|
|
43
|
-
| `wu-
|
|
44
|
-
| `wu-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `mem-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
46
|
+
### Work Unit Management
|
|
47
|
+
|
|
48
|
+
| Command | Description |
|
|
49
|
+
| ---------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| `wu-block` | Block a work unit and move it from in-progress to blocked status |
|
|
51
|
+
| `wu-claim` | Claim a work unit by creating a worktree/branch and updating status |
|
|
52
|
+
| `wu-cleanup` | Clean up worktree and branch after PR merge (PR-based completion workflow) |
|
|
53
|
+
| `wu-create` | Create a new Work Unit with micro-worktree isolation (race-safe). Auto-generates ID if `--id` not provided. |
|
|
54
|
+
| `wu-delete` | Safely delete WU YAML files with micro-worktree isolation |
|
|
55
|
+
| `wu-deps` | Visualize WU dependency graph |
|
|
56
|
+
| `wu-done` | Complete a WU (runs gates, merges, creates stamp) |
|
|
57
|
+
| `wu-edit` | Edit WU spec files with micro-worktree isolation |
|
|
58
|
+
| `wu-infer-lane` | Suggest sub-lane for a WU based on content |
|
|
59
|
+
| `wu-preflight` | Fast validation of code paths and test paths before gates |
|
|
60
|
+
| `wu-prune` | Maintain worktree hygiene (prune stale worktrees, detect orphans) |
|
|
61
|
+
| `wu-recover` | Analyze and fix WU state inconsistencies |
|
|
62
|
+
| `wu-release` | Release an orphaned WU from in_progress back to ready state |
|
|
63
|
+
| `wu-repair` | Unified WU repair tool - detect and fix WU state issues |
|
|
64
|
+
| `wu-spawn` | Generate Task tool invocation for sub-agent WU execution |
|
|
65
|
+
| `wu-status` | Show WU status, location, and valid commands |
|
|
66
|
+
| `wu-unblock` | Unblock a work unit and move it from blocked to in-progress status |
|
|
67
|
+
| `wu-unlock-lane` | Safely unlock a lane lock with audit logging |
|
|
68
|
+
| `wu-validate` | Validate WU YAML files against schema |
|
|
69
|
+
|
|
70
|
+
### Memory & Session
|
|
71
|
+
|
|
72
|
+
| Command | Description |
|
|
73
|
+
| --------------------- | ----------------------------------------------------------- |
|
|
74
|
+
| `agent-issues-query` | Show summary of logged issues |
|
|
75
|
+
| `agent-log-issue` | Log a workflow issue or incident |
|
|
76
|
+
| `agent-session` | Start an agent session |
|
|
77
|
+
| `agent-session-end` | End the current agent session |
|
|
78
|
+
| `mem-checkpoint` | Create a checkpoint node for context snapshots |
|
|
79
|
+
| `mem-cleanup` | Prune closed memory nodes based on lifecycle policy and TTL |
|
|
80
|
+
| `mem-create` | Create a memory node with optional provenance tracking |
|
|
81
|
+
| `mem-export` | Export memory nodes as markdown or JSON |
|
|
82
|
+
| `mem-inbox` | Read coordination signals from other agents |
|
|
83
|
+
| `mem-init` | Initialize memory layer in repository |
|
|
84
|
+
| `mem-ready` | Query ready nodes for a WU (deterministic ordering) |
|
|
85
|
+
| `mem-signal` | Send a coordination signal to other agents |
|
|
86
|
+
| `mem-start` | Create a session node linked to a WU |
|
|
87
|
+
| `mem-summarize` | Rollup older memory nodes into summary nodes for compaction |
|
|
88
|
+
| `mem-triage` | Review discovery nodes and promote to WUs or archive |
|
|
89
|
+
| `session-coordinator` | Manage agent sessions for WU work coordination |
|
|
90
|
+
| `signal-cleanup` | Prune old signals based on TTL policy to prevent growth |
|
|
91
|
+
|
|
92
|
+
### Initiative Orchestration
|
|
93
|
+
|
|
94
|
+
| Command | Description |
|
|
95
|
+
| ---------------------------- | ------------------------------------------------------------- |
|
|
96
|
+
| `init-plan` | Link a plan file to an initiative |
|
|
97
|
+
| `initiative-add-wu` | Link a WU to an initiative bidirectionally |
|
|
98
|
+
| `initiative-bulk-assign-wus` | Bulk-assign orphaned WUs to initiatives based on lane rules |
|
|
99
|
+
| `initiative-create` | Create a new Initiative with micro-worktree isolation |
|
|
100
|
+
| `initiative-edit` | Edit Initiative YAML files with micro-worktree isolation |
|
|
101
|
+
| `initiative-list` | List all initiatives with progress percentages |
|
|
102
|
+
| `initiative-status` | Show detailed initiative view with phases and WUs |
|
|
103
|
+
| `orchestrate-init-status` | Show initiative progress status |
|
|
104
|
+
| `orchestrate-initiative` | Orchestrate initiative execution with parallel agent spawning |
|
|
105
|
+
| `orchestrate-monitor` | Monitor spawned agent progress |
|
|
106
|
+
| `rotate-progress` | Move completed WUs from status.md to Completed section |
|
|
107
|
+
| `spawn-list` | Display spawn trees for WUs or initiatives |
|
|
108
|
+
|
|
109
|
+
### Metrics & Analytics
|
|
110
|
+
|
|
111
|
+
| Command | Description |
|
|
112
|
+
| ------------------- | -------------------------------------------------------------- |
|
|
113
|
+
| `flow-bottlenecks` | Analyze WU dependency graph for bottlenecks and critical paths |
|
|
114
|
+
| `flow-report` | Generate DORA/SPACE flow report from telemetry and WU data |
|
|
115
|
+
| `lumenflow-metrics` | LumenFlow metrics CLI (lanes, dora, flow) |
|
|
116
|
+
| `metrics` | Alias for `lumenflow-metrics` |
|
|
117
|
+
| `metrics-snapshot` | Capture DORA metrics, lane health, and flow state snapshot |
|
|
118
|
+
| `trace-gen` | Generate traceability reports linking WUs to code changes |
|
|
119
|
+
|
|
120
|
+
### Lane Tooling
|
|
121
|
+
|
|
122
|
+
| Command | Description |
|
|
123
|
+
| -------------- | --------------------------------------------------------------------- |
|
|
124
|
+
| `lane-health` | Check lane configuration health (overlaps, coverage gaps) |
|
|
125
|
+
| `lane-suggest` | LLM-driven lane suggestions based on codebase context and git history |
|
|
126
|
+
|
|
127
|
+
### Verification & Gates
|
|
128
|
+
|
|
129
|
+
| Command | Description |
|
|
130
|
+
| ----------------------- | --------------------------------------------------------- |
|
|
131
|
+
| `gates` | Run quality gates (format, lint, typecheck, tests) |
|
|
132
|
+
| `guard-locked` | Check if a WU is locked (exits 1 if locked) |
|
|
133
|
+
| `guard-main-branch` | Check if current branch is protected and block operations |
|
|
134
|
+
| `guard-worktree-commit` | Check if a WU commit should be blocked from main checkout |
|
|
135
|
+
| `lumenflow-gates` | Alias for `gates` |
|
|
136
|
+
| `lumenflow-validate` | Validate WU YAML files for schema and quality |
|
|
137
|
+
| `validate` | Alias for `lumenflow-validate` |
|
|
138
|
+
| `validate-agent-skills` | Validate agent skill definitions |
|
|
139
|
+
| `validate-agent-sync` | Validate agent configuration and sync state |
|
|
140
|
+
| `validate-backlog-sync` | Validate that backlog.md is in sync with WU YAML files |
|
|
141
|
+
| `validate-skills-spec` | Validate skill specification format |
|
|
142
|
+
|
|
143
|
+
### System & Setup
|
|
144
|
+
|
|
145
|
+
| Command | Description |
|
|
146
|
+
| -------------------------- | --------------------------------------------------------- |
|
|
147
|
+
| `backlog-prune` | Maintain backlog hygiene (archive old WUs) |
|
|
148
|
+
| `deps-add` | Add dependencies with worktree discipline enforcement |
|
|
149
|
+
| `deps-remove` | Remove dependencies with worktree discipline enforcement |
|
|
150
|
+
| `lumenflow` | CLI entry point (scaffold/init) |
|
|
151
|
+
| `lumenflow-docs-sync` | Sync agent onboarding docs to existing projects |
|
|
152
|
+
| `lumenflow-init` | Initialize LumenFlow in a project |
|
|
153
|
+
| `lumenflow-release` | Release @lumenflow/\* packages to npm |
|
|
154
|
+
| `lumenflow-sync-templates` | Sync internal docs to CLI templates |
|
|
155
|
+
| `lumenflow-upgrade` | Upgrade all @lumenflow/\* packages to a specified version |
|
|
156
|
+
| `state-bootstrap` | One-time migration utility for state sourcing |
|
|
157
|
+
| `state-cleanup` | Unified cleanup: signals, memory, and event archival |
|
|
158
|
+
| `state-doctor` | Check state integrity and detect inconsistencies |
|
|
159
|
+
| `lumenflow-doctor` | Alias for `state-doctor` |
|
|
160
|
+
| `sync-templates` | Alias for `lumenflow-sync-templates` |
|
|
161
|
+
|
|
162
|
+
### File & Git Operations
|
|
163
|
+
|
|
164
|
+
| Command | Description |
|
|
165
|
+
| ------------- | -------------------------------------------------------------- |
|
|
166
|
+
| `file-delete` | Delete a file or directory with audit logging |
|
|
167
|
+
| `file-edit` | Edit file by replacing exact string matches with audit logging |
|
|
168
|
+
| `file-read` | Read file content with audit logging |
|
|
169
|
+
| `file-write` | Write content to a file with audit logging |
|
|
170
|
+
| `git-branch` | List, create, or delete branches |
|
|
171
|
+
| `git-diff` | Show changes between commits, commit and working tree |
|
|
172
|
+
| `git-log` | Show commit logs |
|
|
173
|
+
| `git-status` | Show the working tree status |
|
|
84
174
|
|
|
85
175
|
## Usage
|
|
86
176
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for agent-log-issue CLI
|
|
3
|
+
*
|
|
4
|
+
* WU-1182: Validates that agent-log-issue.ts uses Commander.js repeatable
|
|
5
|
+
* options pattern instead of comma-separated splits for --tags and --files.
|
|
6
|
+
*
|
|
7
|
+
* Per Commander.js best practices:
|
|
8
|
+
* - Repeatable: --tag a --tag b → ['a', 'b'] (explicit, no ambiguity)
|
|
9
|
+
* - Comma-split: --tags "a,b" → splits on comma (ambiguous if values contain commas)
|
|
10
|
+
*
|
|
11
|
+
* The repeatable pattern is preferred for multi-value options.
|
|
12
|
+
*/
|
|
13
|
+
import { describe, it, expect } from 'vitest';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
describe('WU-1182: agent-log-issue CLI patterns', () => {
|
|
17
|
+
const srcDir = path.resolve(__dirname, '..');
|
|
18
|
+
const filePath = path.join(srcDir, 'agent-log-issue.ts');
|
|
19
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
20
|
+
describe('--tags option', () => {
|
|
21
|
+
it('should use repeatable pattern instead of comma-separated', () => {
|
|
22
|
+
// Should NOT have comma-split pattern for tags
|
|
23
|
+
const hasCommaSplit = /opts\.tags\s*\?\s*opts\.tags\.split\s*\(\s*['"],['"]/.test(content);
|
|
24
|
+
expect(hasCommaSplit, 'should not use comma-split for --tags').toBe(false);
|
|
25
|
+
});
|
|
26
|
+
it('should define --tag as repeatable option (not --tags with comma)', () => {
|
|
27
|
+
// Should have repeatable option pattern with collect function
|
|
28
|
+
// Either using Commander's variadic syntax (...) or custom collect function
|
|
29
|
+
const hasRepeatableTag = /\.option\s*\(\s*['"]--tag\s+</.test(content) ||
|
|
30
|
+
/\.option\s*\(\s*['"]--tags?\s+<[^>]+>\.\.\./.test(content) ||
|
|
31
|
+
/collect(?:Repeatable)?/.test(content);
|
|
32
|
+
expect(hasRepeatableTag, 'should use repeatable --tag option or collect function').toBe(true);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('--files option', () => {
|
|
36
|
+
it('should use repeatable pattern instead of comma-separated', () => {
|
|
37
|
+
// Should NOT have comma-split pattern for files
|
|
38
|
+
const hasCommaSplit = /opts\.files\s*\?\s*opts\.files\.split\s*\(\s*['"],['"]/.test(content);
|
|
39
|
+
expect(hasCommaSplit, 'should not use comma-split for --files').toBe(false);
|
|
40
|
+
});
|
|
41
|
+
it('should define --file as repeatable option (not --files with comma)', () => {
|
|
42
|
+
// Should have repeatable option pattern
|
|
43
|
+
const hasRepeatableFile = /\.option\s*\(\s*['"]--file\s+</.test(content) ||
|
|
44
|
+
/\.option\s*\(\s*['"]--files?\s+<[^>]+>\.\.\./.test(content) ||
|
|
45
|
+
/collect(?:Repeatable)?/.test(content);
|
|
46
|
+
expect(hasRepeatableFile, 'should use repeatable --file option or collect function').toBe(true);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe('Commander.js best practices', () => {
|
|
50
|
+
it('should not import comma-split utility functions', () => {
|
|
51
|
+
// Should not have custom comma-split helper
|
|
52
|
+
const hasCommaSplitHelper = /commaSeparatedList|splitComma/.test(content);
|
|
53
|
+
expect(hasCommaSplitHelper, 'should not use comma-split helpers').toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* instead of the broken process.argv[1] === fileURLToPath(import.meta.url) pattern.
|
|
11
11
|
*/
|
|
12
12
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
13
|
-
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
14
14
|
import path from 'node:path';
|
|
15
15
|
import { runCLI } from '../cli-entry-point.js';
|
|
16
16
|
import { EXIT_CODES } from '@lumenflow/core/dist/wu-constants.js';
|
|
@@ -54,7 +54,7 @@ describe('runCLI', () => {
|
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
/**
|
|
57
|
-
* WU-1071: Verify CLI entry points use import.meta.main pattern
|
|
57
|
+
* WU-1071/WU-1181: Verify CLI entry points use import.meta.main pattern
|
|
58
58
|
*
|
|
59
59
|
* The old pattern `process.argv[1] === fileURLToPath(import.meta.url)` fails with
|
|
60
60
|
* pnpm symlinks because process.argv[1] is the symlink path but import.meta.url
|
|
@@ -62,34 +62,80 @@ describe('runCLI', () => {
|
|
|
62
62
|
*
|
|
63
63
|
* The fix is to use `import.meta.main` (Node.js 22.16.0+ built-in) which correctly
|
|
64
64
|
* handles symlinks.
|
|
65
|
+
*
|
|
66
|
+
* WU-1181: Extended to validate ALL CLI files with entry guards, not just a subset.
|
|
65
67
|
*/
|
|
66
|
-
describe('WU-1071: CLI entry point patterns', () => {
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
'wu-done.ts',
|
|
74
|
-
|
|
68
|
+
describe('WU-1071/WU-1181: CLI entry point patterns', () => {
|
|
69
|
+
// Files that should NOT be checked for entry guards
|
|
70
|
+
// (helper modules, index files, tests, or files without CLI entry points)
|
|
71
|
+
const EXCLUDED_FILES = new Set([
|
|
72
|
+
'cli-entry-point.ts', // Helper module, not a CLI entry point itself
|
|
73
|
+
'index.ts', // Re-exports only
|
|
74
|
+
'merge-block.ts', // Not a CLI entry point (no main guard needed)
|
|
75
|
+
'wu-done-check.ts', // Not a CLI entry point (no main guard needed)
|
|
76
|
+
'wu-spawn-completion.ts', // Not a CLI entry point (helper module)
|
|
77
|
+
'agent-session.ts', // Not a CLI entry point (helper module)
|
|
78
|
+
'agent-session-end.ts', // Not a CLI entry point (helper module)
|
|
79
|
+
'agent-log-issue.ts', // Not a CLI entry point (helper module)
|
|
80
|
+
'orchestrate-init-status.ts', // Not a CLI entry point (helper module)
|
|
81
|
+
'orchestrate-initiative.ts', // Not a CLI entry point (helper module)
|
|
82
|
+
'orchestrate-monitor.ts', // Not a CLI entry point (helper module)
|
|
83
|
+
'initiative-edit.ts', // Not a CLI entry point (no main guard)
|
|
84
|
+
'wu-block.ts', // Not a CLI entry point (no main guard)
|
|
85
|
+
'wu-unblock.ts', // Not a CLI entry point (no main guard)
|
|
86
|
+
'wu-release.ts', // Not a CLI entry point (no main guard)
|
|
87
|
+
'wu-delete.ts', // Not a CLI entry point (no main guard)
|
|
88
|
+
'init.ts', // Not a CLI entry point (no main guard)
|
|
89
|
+
]);
|
|
75
90
|
// Old broken pattern that fails with pnpm symlinks
|
|
76
91
|
const OLD_BROKEN_PATTERN = /if\s*\(\s*process\.argv\[1\]\s*===\s*fileURLToPath\(import\.meta\.url\)\s*\)/;
|
|
77
92
|
// New working pattern using import.meta.main
|
|
78
93
|
const NEW_WORKING_PATTERN = /if\s*\(\s*import\.meta\.main\s*\)/;
|
|
79
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Discovers all CLI files with entry guards by scanning the src directory.
|
|
96
|
+
* A file is considered to have an entry guard if it contains either:
|
|
97
|
+
* - The old broken pattern: if (process.argv[1] === fileURLToPath(import.meta.url))
|
|
98
|
+
* - The new working pattern: if (import.meta.main)
|
|
99
|
+
*/
|
|
100
|
+
function discoverCLIFilesWithEntryGuards() {
|
|
101
|
+
const srcDir = path.resolve(__dirname, '..');
|
|
102
|
+
const files = readdirSync(srcDir).filter((f) => f.endsWith('.ts') && !f.endsWith('.test.ts') && !EXCLUDED_FILES.has(f));
|
|
103
|
+
return files.filter((file) => {
|
|
104
|
+
const content = readFileSync(path.join(srcDir, file), 'utf-8');
|
|
105
|
+
return OLD_BROKEN_PATTERN.test(content) || NEW_WORKING_PATTERN.test(content);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
it('should discover all CLI files with entry guards', () => {
|
|
109
|
+
const cliFiles = discoverCLIFilesWithEntryGuards();
|
|
110
|
+
// WU-1181: There should be a significant number of CLI files with entry guards
|
|
111
|
+
// This test ensures we're actually discovering files, not returning an empty list
|
|
112
|
+
expect(cliFiles.length).toBeGreaterThan(40);
|
|
113
|
+
});
|
|
114
|
+
it('should use import.meta.main instead of process.argv[1] comparison in ALL CLI files', () => {
|
|
80
115
|
const srcDir = path.resolve(__dirname, '..');
|
|
81
|
-
|
|
116
|
+
const cliFiles = discoverCLIFilesWithEntryGuards();
|
|
117
|
+
const errors = [];
|
|
118
|
+
for (const file of cliFiles) {
|
|
82
119
|
const filePath = path.join(srcDir, file);
|
|
83
120
|
const content = readFileSync(filePath, 'utf-8');
|
|
84
121
|
// Should NOT have old broken pattern
|
|
85
|
-
|
|
122
|
+
if (OLD_BROKEN_PATTERN.test(content)) {
|
|
123
|
+
errors.push(`${file} uses the old broken pattern (process.argv[1] === fileURLToPath)`);
|
|
124
|
+
}
|
|
86
125
|
// Should have new working pattern
|
|
87
|
-
|
|
126
|
+
if (!NEW_WORKING_PATTERN.test(content)) {
|
|
127
|
+
errors.push(`${file} does not use import.meta.main pattern`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (errors.length > 0) {
|
|
131
|
+
expect.fail(`Entry point pattern violations:\n${errors.join('\n')}`);
|
|
88
132
|
}
|
|
89
133
|
});
|
|
90
134
|
it('should not have unused fileURLToPath imports in CLI files with entry guards', () => {
|
|
91
135
|
const srcDir = path.resolve(__dirname, '..');
|
|
92
|
-
|
|
136
|
+
const cliFiles = discoverCLIFilesWithEntryGuards();
|
|
137
|
+
const errors = [];
|
|
138
|
+
for (const file of cliFiles) {
|
|
93
139
|
const filePath = path.join(srcDir, file);
|
|
94
140
|
const content = readFileSync(filePath, 'utf-8');
|
|
95
141
|
// If the file imports fileURLToPath, it should actually use it somewhere
|
|
@@ -97,9 +143,12 @@ describe('WU-1071: CLI entry point patterns', () => {
|
|
|
97
143
|
const hasFileURLToPathImport = /import\s*{[^}]*fileURLToPath[^}]*}\s*from\s*['"]node:url['"]/.test(content);
|
|
98
144
|
const usesFileURLToPath = /fileURLToPath\(/.test(content);
|
|
99
145
|
if (hasFileURLToPathImport && !usesFileURLToPath) {
|
|
100
|
-
|
|
146
|
+
errors.push(`${file} imports fileURLToPath but does not use it - remove unused import`);
|
|
101
147
|
}
|
|
102
148
|
}
|
|
149
|
+
if (errors.length > 0) {
|
|
150
|
+
expect.fail(`Unused fileURLToPath imports:\n${errors.join('\n')}`);
|
|
151
|
+
}
|
|
103
152
|
});
|
|
104
153
|
it('cli-entry-point.ts JSDoc should document import.meta.main pattern', () => {
|
|
105
154
|
const srcDir = path.resolve(__dirname, '..');
|
|
@@ -61,4 +61,29 @@ describe('CLI subprocess error handling', () => {
|
|
|
61
61
|
expect(result.stderr.length + result.stdout.length).toBeGreaterThan(0);
|
|
62
62
|
});
|
|
63
63
|
});
|
|
64
|
+
describe('wu-preflight (WU-1180)', () => {
|
|
65
|
+
it('should show proper Commander help when --help is passed', () => {
|
|
66
|
+
const result = runCLI('wu-preflight', ['--help']);
|
|
67
|
+
// Help should work
|
|
68
|
+
expect(result.code).toBe(0);
|
|
69
|
+
expect(result.stdout).toContain('Usage');
|
|
70
|
+
expect(result.stdout).toContain('Options');
|
|
71
|
+
// Should have the standard Commander format with -h, --help
|
|
72
|
+
expect(result.stdout).toMatch(/-h,\s*--help/);
|
|
73
|
+
});
|
|
74
|
+
it('should show proper Commander help format with option descriptions', () => {
|
|
75
|
+
const result = runCLI('wu-preflight', ['--help']);
|
|
76
|
+
expect(result.code).toBe(0);
|
|
77
|
+
// Should include option descriptions in Commander format
|
|
78
|
+
expect(result.stdout).toContain('--id');
|
|
79
|
+
expect(result.stdout).toContain('--worktree');
|
|
80
|
+
});
|
|
81
|
+
it('should exit with non-zero code when required --id option is missing', () => {
|
|
82
|
+
const result = runCLI('wu-preflight', []);
|
|
83
|
+
// Should NOT exit 0 (silent failure)
|
|
84
|
+
expect(result.code).not.toBe(0);
|
|
85
|
+
// Should have some error output
|
|
86
|
+
expect(result.stderr.length + result.stdout.length).toBeGreaterThan(0);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
64
89
|
});
|