@lumenflow/cli 2.6.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +120 -105
  2. package/dist/__tests__/agent-spawn-coordination.test.js +451 -0
  3. package/dist/__tests__/commands/integrate.test.js +165 -0
  4. package/dist/__tests__/gates-config.test.js +0 -1
  5. package/dist/__tests__/hooks/enforcement.test.js +279 -0
  6. package/dist/__tests__/init-greenfield.test.js +247 -0
  7. package/dist/__tests__/init-quick-ref.test.js +0 -1
  8. package/dist/__tests__/init-template-portability.test.js +0 -1
  9. package/dist/__tests__/init.test.js +27 -0
  10. package/dist/__tests__/initiative-e2e.test.js +442 -0
  11. package/dist/__tests__/initiative-plan-replacement.test.js +0 -1
  12. package/dist/__tests__/memory-integration.test.js +333 -0
  13. package/dist/__tests__/release.test.js +1 -1
  14. package/dist/__tests__/safe-git.test.js +0 -1
  15. package/dist/__tests__/state-doctor.test.js +54 -0
  16. package/dist/__tests__/sync-templates.test.js +255 -0
  17. package/dist/__tests__/wu-create-required-fields.test.js +121 -0
  18. package/dist/__tests__/wu-done-auto-cleanup.test.js +135 -0
  19. package/dist/__tests__/wu-lifecycle-integration.test.js +388 -0
  20. package/dist/__tests__/wu-proto.test.js +97 -0
  21. package/dist/backlog-prune.js +0 -1
  22. package/dist/cli-entry-point.js +0 -1
  23. package/dist/commands/integrate.js +229 -0
  24. package/dist/docs-sync.js +46 -0
  25. package/dist/doctor.js +0 -2
  26. package/dist/gates.js +0 -7
  27. package/dist/hooks/enforcement-checks.js +209 -0
  28. package/dist/hooks/enforcement-generator.js +365 -0
  29. package/dist/hooks/enforcement-sync.js +243 -0
  30. package/dist/hooks/index.js +7 -0
  31. package/dist/init.js +266 -11
  32. package/dist/initiative-add-wu.js +0 -2
  33. package/dist/initiative-create.js +0 -3
  34. package/dist/initiative-edit.js +0 -5
  35. package/dist/initiative-plan.js +0 -1
  36. package/dist/initiative-remove-wu.js +0 -2
  37. package/dist/lane-health.js +0 -2
  38. package/dist/lane-suggest.js +0 -1
  39. package/dist/mem-checkpoint.js +0 -2
  40. package/dist/mem-cleanup.js +0 -2
  41. package/dist/mem-context.js +0 -3
  42. package/dist/mem-create.js +0 -2
  43. package/dist/mem-delete.js +0 -3
  44. package/dist/mem-inbox.js +0 -2
  45. package/dist/mem-index.js +0 -1
  46. package/dist/mem-init.js +0 -2
  47. package/dist/mem-profile.js +0 -1
  48. package/dist/mem-promote.js +0 -1
  49. package/dist/mem-ready.js +0 -2
  50. package/dist/mem-signal.js +0 -2
  51. package/dist/mem-start.js +0 -2
  52. package/dist/mem-summarize.js +0 -2
  53. package/dist/metrics-cli.js +1 -1
  54. package/dist/metrics-snapshot.js +1 -1
  55. package/dist/onboarding-smoke-test.js +0 -5
  56. package/dist/orchestrate-init-status.js +0 -1
  57. package/dist/orchestrate-initiative.js +0 -1
  58. package/dist/orchestrate-monitor.js +0 -1
  59. package/dist/plan-create.js +0 -2
  60. package/dist/plan-edit.js +0 -2
  61. package/dist/plan-link.js +0 -2
  62. package/dist/plan-promote.js +0 -2
  63. package/dist/signal-cleanup.js +0 -4
  64. package/dist/state-bootstrap.js +0 -1
  65. package/dist/state-cleanup.js +0 -4
  66. package/dist/state-doctor-fix.js +5 -8
  67. package/dist/state-doctor.js +0 -11
  68. package/dist/sync-templates.js +188 -34
  69. package/dist/wu-block.js +100 -48
  70. package/dist/wu-claim.js +1 -22
  71. package/dist/wu-cleanup.js +0 -1
  72. package/dist/wu-create.js +0 -2
  73. package/dist/wu-done-auto-cleanup.js +139 -0
  74. package/dist/wu-done.js +11 -4
  75. package/dist/wu-edit.js +0 -12
  76. package/dist/wu-preflight.js +0 -1
  77. package/dist/wu-prep.js +0 -1
  78. package/dist/wu-proto.js +329 -0
  79. package/dist/wu-spawn.js +0 -3
  80. package/dist/wu-unblock.js +0 -2
  81. package/dist/wu-validate.js +0 -1
  82. package/package.json +9 -7
  83. package/templates/core/.husky/pre-commit.template +93 -0
  84. package/templates/core/ai/onboarding/quick-ref-commands.md.template +27 -0
  85. package/templates/core/ai/onboarding/rapid-prototyping.md +143 -0
  86. package/templates/core/ai/onboarding/starting-prompt.md.template +3 -3
  87. package/templates/vendors/claude/.claude/CLAUDE.md.template +25 -0
  88. package/templates/vendors/claude/.claude/hooks/enforce-worktree.sh +135 -0
@@ -27,7 +27,6 @@ import { PATTERNS, EXIT_CODES, LOG_PREFIX, EMOJI } from '@lumenflow/core/dist/wu
27
27
  import { defaultWorktreeFrom, WU_PATHS } from '@lumenflow/core/dist/wu-paths.js';
28
28
  import { readWURaw } from '@lumenflow/core/dist/wu-yaml.js';
29
29
  import { die } from '@lumenflow/core/dist/error-handler.js';
30
- /* eslint-disable security/detect-non-literal-fs-filename */
31
30
  /**
32
31
  * Detect worktree path from WU YAML or calculate from lane
33
32
  * @param {string} id - WU ID
package/dist/wu-prep.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /* eslint-disable no-console -- CLI command uses console for status output */
3
2
  /**
4
3
  * WU Prep Helper (WU-1223)
5
4
  *
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * WU Proto Helper (WU-1359)
4
+ *
5
+ * Convenience command for rapid prototyping that creates a WU with
6
+ * type: prototype and relaxed validation, then immediately claims it.
7
+ *
8
+ * Key differences from wu:create:
9
+ * - type: prototype (not feature)
10
+ * - No --acceptance required
11
+ * - No --exposure required
12
+ * - No --code-paths required
13
+ * - No --test-paths required
14
+ * - No --spec-refs required
15
+ * - Automatically claims the WU after creation
16
+ * - Prints cd command to worktree
17
+ *
18
+ * Usage:
19
+ * pnpm wu:proto --lane "Framework: CLI" --title "Quick experiment"
20
+ *
21
+ * Context: WU-1359 (enhance init output and add wu:proto command)
22
+ */
23
+ import { getGitForCwd } from '@lumenflow/core/dist/git-adapter.js';
24
+ import { die } from '@lumenflow/core/dist/error-handler.js';
25
+ import { existsSync, writeFileSync, mkdirSync } from 'node:fs';
26
+ import { join } from 'node:path';
27
+ import { stringifyYAML } from '@lumenflow/core/dist/wu-yaml.js';
28
+ import { todayISO } from '@lumenflow/core/dist/date-utils.js';
29
+ import { validateLaneFormat } from '@lumenflow/core/dist/lane-checker.js';
30
+ import { createWUParser, WU_OPTIONS } from '@lumenflow/core/dist/arg-parser.js';
31
+ import { WU_PATHS } from '@lumenflow/core/dist/wu-paths.js';
32
+ import { validateWU } from '@lumenflow/core/dist/wu-schema.js';
33
+ import { COMMIT_FORMATS, FILE_SYSTEM, STRING_LITERALS } from '@lumenflow/core/dist/wu-constants.js';
34
+ import { ensureOnMain } from '@lumenflow/core/dist/wu-helpers.js';
35
+ import { withMicroWorktree } from '@lumenflow/core/dist/micro-worktree.js';
36
+ import { generateWuIdWithRetry } from '@lumenflow/core/dist/wu-id-generator.js';
37
+ import { parseBacklogFrontmatter } from '@lumenflow/core/dist/backlog-parser.js';
38
+ import { execFileSync } from 'node:child_process';
39
+ /** Log prefix for console output */
40
+ const LOG_PREFIX = '[wu:proto]';
41
+ /** Micro-worktree operation name */
42
+ const OPERATION_NAME = 'wu-proto';
43
+ /** Default priority for prototype WUs */
44
+ const DEFAULT_PRIORITY = 'P3';
45
+ /** Prototype WU type */
46
+ const PROTOTYPE_TYPE = 'prototype';
47
+ /**
48
+ * Validate prototype WU spec (relaxed validation)
49
+ *
50
+ * Unlike wu:create, this has minimal requirements:
51
+ * - lane is required
52
+ * - title is required
53
+ * - Everything else is optional
54
+ *
55
+ * @param params - Validation parameters
56
+ * @returns {{ valid: boolean, errors: string[] }}
57
+ */
58
+ export function validateProtoSpec({ id: _id, lane, title, opts: _opts = {}, }) {
59
+ const errors = [];
60
+ if (!lane || lane.trim() === '') {
61
+ errors.push('--lane is required');
62
+ }
63
+ if (!title || title.trim() === '') {
64
+ errors.push('--title is required');
65
+ }
66
+ return {
67
+ valid: errors.length === 0,
68
+ errors,
69
+ };
70
+ }
71
+ /**
72
+ * Build prototype WU content
73
+ * @returns WU content object for YAML serialization
74
+ */
75
+ function buildProtoWUContent({ id, lane, title, priority, created, opts, }) {
76
+ const { description, codePaths, labels, assignedTo } = opts;
77
+ return {
78
+ id,
79
+ title,
80
+ lane,
81
+ type: PROTOTYPE_TYPE,
82
+ status: 'ready',
83
+ priority,
84
+ created,
85
+ description: description || '',
86
+ // Prototype WUs have minimal default acceptance
87
+ acceptance: ['Prototype demonstrates concept'],
88
+ code_paths: codePaths ?? [],
89
+ tests: {
90
+ manual: [],
91
+ unit: [],
92
+ e2e: [],
93
+ },
94
+ artifacts: [`.lumenflow/stamps/${id}.done`],
95
+ dependencies: [],
96
+ risks: [],
97
+ notes: 'Prototype WU - relaxed validation applies',
98
+ requires_review: false,
99
+ ...(labels?.length && { labels }),
100
+ ...(assignedTo && { assigned_to: assignedTo }),
101
+ // WU-1359: Prototype WUs set exposure to backend-only by default
102
+ exposure: 'backend-only',
103
+ };
104
+ }
105
+ /**
106
+ * Create prototype WU YAML in micro-worktree
107
+ * @returns Relative path to created WU YAML file
108
+ */
109
+ function createProtoWUYamlInWorktree(worktreePath, id, lane, title, priority, opts) {
110
+ const wuRelativePath = WU_PATHS.WU(id);
111
+ const wuAbsolutePath = join(worktreePath, wuRelativePath);
112
+ const wuDir = join(worktreePath, WU_PATHS.WU_DIR());
113
+ if (!existsSync(wuDir)) {
114
+ mkdirSync(wuDir, { recursive: true });
115
+ }
116
+ const today = todayISO();
117
+ const wuContent = buildProtoWUContent({
118
+ id,
119
+ lane,
120
+ title,
121
+ priority,
122
+ created: today,
123
+ opts,
124
+ });
125
+ // Validate WU structure before writing
126
+ const validationResult = validateWU(wuContent);
127
+ if (!validationResult.success) {
128
+ const errors = validationResult.error.issues
129
+ .map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)
130
+ .join(STRING_LITERALS.NEWLINE);
131
+ die(`${LOG_PREFIX} WU validation failed:\n\n${errors}`);
132
+ }
133
+ const yamlContent = stringifyYAML(validationResult.data, { lineWidth: -1 });
134
+ writeFileSync(wuAbsolutePath, yamlContent, { encoding: FILE_SYSTEM.UTF8 });
135
+ console.log(`${LOG_PREFIX} Created ${id}.yaml in micro-worktree`);
136
+ return wuRelativePath;
137
+ }
138
+ /**
139
+ * Update backlog.md in micro-worktree
140
+ * @returns Relative path to updated backlog file
141
+ */
142
+ function updateBacklogInWorktree(worktreePath, id, lane, title) {
143
+ const backlogRelativePath = WU_PATHS.BACKLOG();
144
+ const backlogAbsolutePath = join(worktreePath, backlogRelativePath);
145
+ if (!existsSync(backlogAbsolutePath)) {
146
+ die(`Backlog not found: ${backlogAbsolutePath}`);
147
+ }
148
+ const { frontmatter, markdown } = parseBacklogFrontmatter(backlogAbsolutePath);
149
+ if (!frontmatter?.sections?.ready?.heading) {
150
+ die('Invalid backlog frontmatter: Missing sections.ready.heading');
151
+ }
152
+ const readyHeading = frontmatter.sections.ready.heading;
153
+ const lines = markdown.split(STRING_LITERALS.NEWLINE);
154
+ const headingIndex = lines.findIndex((line) => line === readyHeading);
155
+ if (headingIndex === -1) {
156
+ die(`Could not find Ready section heading: '${readyHeading}'`);
157
+ }
158
+ const insertionIndex = headingIndex + 2;
159
+ const newEntry = `- [${id} - ${title}](wu/${id}.yaml) - ${lane}`;
160
+ lines.splice(insertionIndex, 0, newEntry);
161
+ const updatedMarkdown = lines.join(STRING_LITERALS.NEWLINE);
162
+ const updatedBacklog = `---\n${stringifyYAML(frontmatter, { lineWidth: -1 })}---\n${updatedMarkdown}`;
163
+ writeFileSync(backlogAbsolutePath, updatedBacklog, {
164
+ encoding: FILE_SYSTEM.UTF8,
165
+ });
166
+ console.log(`${LOG_PREFIX} Updated backlog.md in micro-worktree`);
167
+ return backlogRelativePath;
168
+ }
169
+ /**
170
+ * Get default assigned_to value from git config user.email
171
+ */
172
+ async function getDefaultAssignedTo() {
173
+ try {
174
+ const email = await getGitForCwd().getConfigValue('user.email');
175
+ return email || '';
176
+ }
177
+ catch {
178
+ return '';
179
+ }
180
+ }
181
+ /** Regex to extract worktree path from wu:claim output */
182
+ const WORKTREE_PATH_REGEX = /Worktree:\s*(\S+)/;
183
+ /**
184
+ * Claim the WU after creation using execFileSync (safe from shell injection)
185
+ * @returns Path to the created worktree
186
+ */
187
+ function claimWU(wuId, lane) {
188
+ console.log(`${LOG_PREFIX} Claiming WU ${wuId}...`);
189
+ try {
190
+ // Use execFileSync for safety (no shell injection risk)
191
+ // Use process.execPath to get absolute path to node, then run pnpm via npx
192
+ const result = execFileSync(process.execPath, [
193
+ '--no-warnings',
194
+ '--experimental-import-meta-resolve',
195
+ ...process.execArgv.filter((a) => !a.startsWith('--inspect')),
196
+ require.resolve('.bin/wu-claim'),
197
+ '--id',
198
+ wuId,
199
+ '--lane',
200
+ lane,
201
+ ], {
202
+ encoding: 'utf-8',
203
+ stdio: ['pipe', 'pipe', 'pipe'],
204
+ cwd: process.cwd(),
205
+ });
206
+ // Extract worktree path from output using regex exec (sonarjs/prefer-regexp-exec)
207
+ const worktreeMatch = WORKTREE_PATH_REGEX.exec(result);
208
+ if (worktreeMatch) {
209
+ return worktreeMatch[1];
210
+ }
211
+ // Fallback: construct expected worktree path
212
+ const laneSuffix = lane.toLowerCase().replace(/[:\s]+/g, '-');
213
+ return `worktrees/${laneSuffix}-${wuId.toLowerCase()}`;
214
+ }
215
+ catch (error) {
216
+ die(`Failed to claim WU: ${error.message}`);
217
+ }
218
+ }
219
+ async function main() {
220
+ const args = createWUParser({
221
+ name: 'wu-proto',
222
+ description: 'Create and claim a prototype WU with relaxed validation (rapid prototyping)',
223
+ options: [
224
+ WU_OPTIONS.lane,
225
+ WU_OPTIONS.title,
226
+ WU_OPTIONS.description,
227
+ WU_OPTIONS.codePaths,
228
+ WU_OPTIONS.labels,
229
+ WU_OPTIONS.assignedTo,
230
+ ],
231
+ required: ['lane', 'title'],
232
+ allowPositionalId: false,
233
+ });
234
+ console.log(`${LOG_PREFIX} Creating prototype WU in ${args.lane} lane...`);
235
+ // Validate lane format
236
+ try {
237
+ validateLaneFormat(args.lane);
238
+ }
239
+ catch (error) {
240
+ die(`Invalid lane format: ${error.message}`);
241
+ }
242
+ await ensureOnMain(getGitForCwd());
243
+ // Auto-generate WU ID
244
+ console.log(`${LOG_PREFIX} Auto-generating WU ID...`);
245
+ let wuId;
246
+ try {
247
+ wuId = await generateWuIdWithRetry();
248
+ console.log(`${LOG_PREFIX} Generated WU ID: ${wuId}`);
249
+ }
250
+ catch (error) {
251
+ die(`Failed to auto-generate WU ID: ${error.message}`);
252
+ }
253
+ // Check if WU already exists
254
+ const wuPath = WU_PATHS.WU(wuId);
255
+ if (existsSync(wuPath)) {
256
+ die(`WU already exists: ${wuPath}`);
257
+ }
258
+ // Get assigned_to from flag or git config
259
+ const assignedTo = args.assignedTo || (await getDefaultAssignedTo());
260
+ // Validate proto spec
261
+ const validation = validateProtoSpec({
262
+ id: wuId,
263
+ lane: args.lane,
264
+ title: args.title,
265
+ opts: {
266
+ description: args.description,
267
+ codePaths: args.codePaths,
268
+ labels: args.labels,
269
+ assignedTo,
270
+ },
271
+ });
272
+ if (!validation.valid) {
273
+ const errorList = validation.errors.map((e) => ` - ${e}`).join(STRING_LITERALS.NEWLINE);
274
+ die(`${LOG_PREFIX} Validation failed:\n\n${errorList}`);
275
+ }
276
+ // WU-1255: Set LUMENFLOW_WU_TOOL to allow pre-push hook bypass
277
+ const previousWuTool = process.env.LUMENFLOW_WU_TOOL;
278
+ process.env.LUMENFLOW_WU_TOOL = OPERATION_NAME;
279
+ try {
280
+ await withMicroWorktree({
281
+ operation: OPERATION_NAME,
282
+ id: wuId,
283
+ logPrefix: LOG_PREFIX,
284
+ execute: async ({ worktreePath }) => {
285
+ // Create WU YAML
286
+ const wuRelativePath = createProtoWUYamlInWorktree(worktreePath, wuId, args.lane, args.title, DEFAULT_PRIORITY, {
287
+ description: args.description,
288
+ codePaths: args.codePaths,
289
+ labels: args.labels,
290
+ assignedTo,
291
+ });
292
+ // Update backlog
293
+ const backlogPath = updateBacklogInWorktree(worktreePath, wuId, args.lane, args.title);
294
+ return {
295
+ commitMessage: COMMIT_FORMATS.CREATE(wuId, args.title),
296
+ files: [wuRelativePath, backlogPath],
297
+ };
298
+ },
299
+ });
300
+ console.log(`\n${LOG_PREFIX} WU created!`);
301
+ console.log(` ID: ${wuId}`);
302
+ console.log(` Title: ${args.title}`);
303
+ console.log(` Lane: ${args.lane}`);
304
+ console.log(` Type: ${PROTOTYPE_TYPE}`);
305
+ console.log(` File: ${WU_PATHS.WU(wuId)}`);
306
+ // Immediately claim the WU
307
+ const worktreePath = claimWU(wuId, args.lane);
308
+ console.log(`\n${LOG_PREFIX} WU claimed and worktree created!`);
309
+ console.log(`\nNext step:`);
310
+ console.log(` cd ${worktreePath}`);
311
+ }
312
+ catch (error) {
313
+ die(`Transaction failed: ${error.message}`);
314
+ }
315
+ finally {
316
+ // Restore LUMENFLOW_WU_TOOL
317
+ if (previousWuTool === undefined) {
318
+ delete process.env.LUMENFLOW_WU_TOOL;
319
+ }
320
+ else {
321
+ process.env.LUMENFLOW_WU_TOOL = previousWuTool;
322
+ }
323
+ }
324
+ }
325
+ // Run CLI
326
+ import { runCLI } from './cli-entry-point.js';
327
+ if (import.meta.main) {
328
+ void runCLI(main);
329
+ }
package/dist/wu-spawn.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /* eslint-disable no-console -- CLI tool requires console output */
3
2
  /**
4
3
  * WU Spawn Helper
5
4
  *
@@ -43,7 +42,6 @@ import { minimatch } from 'minimatch';
43
42
  // WU-2252: Import invariants loader for spawn output injection
44
43
  import { loadInvariants, INVARIANT_TYPES } from '@lumenflow/core/dist/invariants-runner.js';
45
44
  import { validateSpawnArgs, generateExecutionModeSection, generateThinkToolGuidance, recordSpawnToRegistry, formatSpawnRecordedMessage, } from '@lumenflow/core/dist/wu-spawn-helpers.js';
46
- // eslint-disable-next-line sonarjs/deprecation -- legacy factory used by CLI spawns
47
45
  import { SpawnStrategyFactory } from '@lumenflow/core/dist/spawn-strategy.js';
48
46
  import { getConfig } from '@lumenflow/core/dist/lumenflow-config.js';
49
47
  import { generateClientSkillsGuidance, generateSkillsSelectionSection, resolveClientConfig, } from '@lumenflow/core/dist/wu-spawn-skills.js';
@@ -1331,7 +1329,6 @@ async function main() {
1331
1329
  }
1332
1330
  }
1333
1331
  // Create strategy
1334
- // eslint-disable-next-line sonarjs/deprecation -- legacy factory used by CLI spawns
1335
1332
  const strategy = SpawnStrategyFactory.create(clientName);
1336
1333
  const clientContext = { name: clientName, config: resolveClientConfig(config, clientName) };
1337
1334
  if (clientName === 'codex-cli' || args.codex) {
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /* eslint-disable no-console -- CLI tool requires console output */
3
2
  /**
4
3
  * WU Unblock Helper
5
4
  *
@@ -55,7 +54,6 @@ function branchExists(branch) {
55
54
  function createWorktree(doc, worktreePath, branchName) {
56
55
  if (!worktreePath)
57
56
  die('Worktree path required to create a worktree');
58
- // eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool checks worktree
59
57
  if (existsSync(worktreePath)) {
60
58
  console.warn(`${PREFIX} Worktree ${worktreePath} already exists; skipping creation.`);
61
59
  return;
@@ -112,7 +112,6 @@ function validateAllWUs({ strict = true } = {}) {
112
112
  /**
113
113
  * Main entry point
114
114
  */
115
- // eslint-disable-next-line sonarjs/cognitive-complexity -- Pre-existing complexity, refactor tracked separately
116
115
  async function main() {
117
116
  const args = createWUParser({
118
117
  name: 'wu-validate',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/cli",
3
- "version": "2.6.0",
3
+ "version": "2.8.0",
4
4
  "description": "Command-line interface for LumenFlow workflow framework",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -40,6 +40,7 @@
40
40
  "wu-block": "./dist/wu-block.js",
41
41
  "wu-unblock": "./dist/wu-unblock.js",
42
42
  "wu-create": "./dist/wu-create.js",
43
+ "wu-proto": "./dist/wu-proto.js",
43
44
  "wu-edit": "./dist/wu-edit.js",
44
45
  "wu-spawn": "./dist/wu-spawn.js",
45
46
  "wu-validate": "./dist/wu-validate.js",
@@ -130,7 +131,8 @@
130
131
  "lane-health": "./dist/lane-health.js",
131
132
  "lane-suggest": "./dist/lane-suggest.js",
132
133
  "state-cleanup": "./dist/state-cleanup.js",
133
- "state-doctor": "./dist/state-doctor.js"
134
+ "state-doctor": "./dist/state-doctor.js",
135
+ "lumenflow-integrate": "./dist/commands/integrate.js"
134
136
  },
135
137
  "files": [
136
138
  "dist",
@@ -148,11 +150,11 @@
148
150
  "pretty-ms": "^9.2.0",
149
151
  "simple-git": "^3.30.0",
150
152
  "yaml": "^2.8.2",
151
- "@lumenflow/core": "2.6.0",
152
- "@lumenflow/initiatives": "2.6.0",
153
- "@lumenflow/metrics": "2.6.0",
154
- "@lumenflow/agent": "2.6.0",
155
- "@lumenflow/memory": "2.6.0"
153
+ "@lumenflow/core": "2.8.0",
154
+ "@lumenflow/memory": "2.8.0",
155
+ "@lumenflow/metrics": "2.8.0",
156
+ "@lumenflow/agent": "2.8.0",
157
+ "@lumenflow/initiatives": "2.8.0"
156
158
  },
157
159
  "devDependencies": {
158
160
  "@vitest/coverage-v8": "^4.0.17",
@@ -0,0 +1,93 @@
1
+ #!/bin/sh
2
+ #
3
+ # LumenFlow Pre-Commit Hook (Vendor-Agnostic)
4
+ #
5
+ # This hook enforces worktree discipline for all users and AI agents.
6
+ # It blocks direct commits to main/master branches.
7
+ #
8
+ # Rules:
9
+ # 1. BLOCK commits to main/master (use WU workflow instead)
10
+ # 2. ALLOW commits on lane branches (lane/*/wu-*)
11
+ # 3. ALLOW commits on tmp/* branches (CLI micro-worktrees)
12
+ #
13
+ # Escape hatch (logged, emergency only):
14
+ # LUMENFLOW_FORCE=1 LUMENFLOW_FORCE_REASON="reason" git commit ...
15
+ #
16
+ # Configuration:
17
+ # Package manager is configured in .lumenflow.config.yaml (package_manager)
18
+ # Default: pnpm (examples below use pnpm - adjust for your project)
19
+ #
20
+ # For documentation on the WU workflow, see:
21
+ # - LUMENFLOW.md
22
+ # - docs/_frameworks/lumenflow/agent/onboarding/starting-prompt.md
23
+ #
24
+
25
+ # Skip on tmp/* branches (CLI micro-worktrees in /tmp with no node_modules)
26
+ BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
27
+ case "$BRANCH" in tmp/*) exit 0 ;; esac
28
+
29
+ # Check for force bypass (logged for audit)
30
+ if [ "$LUMENFLOW_FORCE" = "1" ]; then
31
+ if [ -z "$LUMENFLOW_FORCE_REASON" ]; then
32
+ echo "" >&2
33
+ echo "[pre-commit] Warning: LUMENFLOW_FORCE_REASON not set." >&2
34
+ echo "Consider: LUMENFLOW_FORCE_REASON=\"reason\" LUMENFLOW_FORCE=1 git commit ..." >&2
35
+ echo "" >&2
36
+ fi
37
+ # Log bypass to .beacon/ for audit trail
38
+ BEACON_DIR="$(git rev-parse --show-toplevel 2>/dev/null)/.beacon"
39
+ if [ -n "$BEACON_DIR" ]; then
40
+ mkdir -p "$BEACON_DIR"
41
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
42
+ USER=$(git config user.name 2>/dev/null || echo "unknown")
43
+ echo "${TIMESTAMP} | pre-commit | ${USER} | ${BRANCH} | ${LUMENFLOW_FORCE_REASON:-no reason} | $(pwd)" >> "${BEACON_DIR}/force-bypasses.log"
44
+ fi
45
+ exit 0
46
+ fi
47
+
48
+ # Block direct commits to main/master
49
+ case "$BRANCH" in
50
+ main|master)
51
+ echo "" >&2
52
+ echo "==================================================================" >&2
53
+ echo " DIRECT COMMIT TO ${BRANCH} BLOCKED" >&2
54
+ echo "==================================================================" >&2
55
+ echo "" >&2
56
+ echo "WHY THIS HAPPENS" >&2
57
+ echo "------------------------------------------------------------------" >&2
58
+ echo "LumenFlow protects main from direct commits to ensure:" >&2
59
+ echo " - All work is tracked in Work Units (WUs)" >&2
60
+ echo " - Changes can be reviewed and coordinated" >&2
61
+ echo " - Parallel work across lanes stays isolated" >&2
62
+ echo "" >&2
63
+ echo "WHAT TO DO" >&2
64
+ echo "------------------------------------------------------------------" >&2
65
+ echo "" >&2
66
+ echo "1. If you have a Work Unit to implement:" >&2
67
+ echo " pnpm wu:claim --id WU-XXXX --lane \"<Lane>\"" >&2
68
+ echo " cd worktrees/<lane>-wu-xxxx" >&2
69
+ echo " Then make your commits in the worktree" >&2
70
+ echo "" >&2
71
+ echo "2. If you need to create a new Work Unit:" >&2
72
+ echo " pnpm wu:create --lane \"<Lane>\" --title \"Your task\"" >&2
73
+ echo " This generates a WU ID, then claim it as above" >&2
74
+ echo "" >&2
75
+ echo "NEED HELP?" >&2
76
+ echo "------------------------------------------------------------------" >&2
77
+ echo " - Read: LUMENFLOW.md (workflow overview)" >&2
78
+ echo " - Read: docs/_frameworks/lumenflow/agent/onboarding/" >&2
79
+ echo " - Run: pnpm wu:help" >&2
80
+ echo "" >&2
81
+ echo "------------------------------------------------------------------" >&2
82
+ echo "EMERGENCY BYPASS (last resort, logged)" >&2
83
+ echo "------------------------------------------------------------------" >&2
84
+ echo "Bypasses are audit-logged. Only use for genuine emergencies." >&2
85
+ echo " LUMENFLOW_FORCE=1 LUMENFLOW_FORCE_REASON=\"<reason>\" git commit ..." >&2
86
+ echo "------------------------------------------------------------------" >&2
87
+ echo "" >&2
88
+ exit 1
89
+ ;;
90
+ esac
91
+
92
+ # Allow commits on lane branches and other branches
93
+ exit 0
@@ -6,6 +6,33 @@ Complete reference for all CLI commands. Organized by category for quick discove
6
6
 
7
7
  ---
8
8
 
9
+ ## Quick Start (Essential Commands)
10
+
11
+ Most common workflow in 4 commands:
12
+
13
+ ```bash
14
+ # 1. Claim WU and create isolated workspace
15
+ pnpm wu:claim --id WU-XXX --lane "Lane Name"
16
+ cd worktrees/<lane>-wu-xxx
17
+
18
+ # 2. Work in worktree, then run gates
19
+ pnpm gates # For code changes
20
+ pnpm gates --docs-only # For documentation only
21
+
22
+ # 3. Prepare for completion (from worktree)
23
+ pnpm wu:prep --id WU-XXX
24
+
25
+ # 4. Complete (from main - copy command from wu:prep output)
26
+ cd /path/to/main && pnpm wu:done --id WU-XXX
27
+ ```
28
+
29
+ **Key rules:**
30
+ - Always work in worktrees, never on main
31
+ - Always run `wu:done` to complete (not just documenting it)
32
+ - Use `wu:prep` first (runs gates), then `wu:done` (merges)
33
+
34
+ ---
35
+
9
36
  ## Setup & Development
10
37
 
11
38
  **For this monorepo (development):**