@lumenflow/cli 2.18.3 → 2.19.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 (104) hide show
  1. package/README.md +42 -41
  2. package/dist/delegation-list.js +140 -0
  3. package/dist/delegation-list.js.map +1 -0
  4. package/dist/doctor.js +35 -99
  5. package/dist/doctor.js.map +1 -1
  6. package/dist/gates-plan-resolvers.js +150 -0
  7. package/dist/gates-plan-resolvers.js.map +1 -0
  8. package/dist/gates-runners.js +533 -0
  9. package/dist/gates-runners.js.map +1 -0
  10. package/dist/gates-types.js +3 -0
  11. package/dist/gates-types.js.map +1 -1
  12. package/dist/gates-utils.js +316 -0
  13. package/dist/gates-utils.js.map +1 -0
  14. package/dist/gates.js +44 -1016
  15. package/dist/gates.js.map +1 -1
  16. package/dist/hooks/enforcement-generator.js +16 -880
  17. package/dist/hooks/enforcement-generator.js.map +1 -1
  18. package/dist/hooks/enforcement-sync.js +1 -4
  19. package/dist/hooks/enforcement-sync.js.map +1 -1
  20. package/dist/hooks/generators/auto-checkpoint.js +123 -0
  21. package/dist/hooks/generators/auto-checkpoint.js.map +1 -0
  22. package/dist/hooks/generators/enforce-worktree.js +188 -0
  23. package/dist/hooks/generators/enforce-worktree.js.map +1 -0
  24. package/dist/hooks/generators/index.js +16 -0
  25. package/dist/hooks/generators/index.js.map +1 -0
  26. package/dist/hooks/generators/pre-compact-checkpoint.js +134 -0
  27. package/dist/hooks/generators/pre-compact-checkpoint.js.map +1 -0
  28. package/dist/hooks/generators/require-wu.js +115 -0
  29. package/dist/hooks/generators/require-wu.js.map +1 -0
  30. package/dist/hooks/generators/session-start-recovery.js +101 -0
  31. package/dist/hooks/generators/session-start-recovery.js.map +1 -0
  32. package/dist/hooks/generators/signal-utils.js +52 -0
  33. package/dist/hooks/generators/signal-utils.js.map +1 -0
  34. package/dist/hooks/generators/warn-incomplete.js +65 -0
  35. package/dist/hooks/generators/warn-incomplete.js.map +1 -0
  36. package/dist/init-detection.js +228 -0
  37. package/dist/init-detection.js.map +1 -0
  38. package/dist/init-scaffolding.js +146 -0
  39. package/dist/init-scaffolding.js.map +1 -0
  40. package/dist/init-templates.js +1928 -0
  41. package/dist/init-templates.js.map +1 -0
  42. package/dist/init.js +136 -2425
  43. package/dist/init.js.map +1 -1
  44. package/dist/initiative-edit.js +42 -11
  45. package/dist/initiative-edit.js.map +1 -1
  46. package/dist/initiative-remove-wu.js +0 -0
  47. package/dist/initiative-status.js +29 -2
  48. package/dist/initiative-status.js.map +1 -1
  49. package/dist/mem-context.js +22 -9
  50. package/dist/mem-context.js.map +1 -1
  51. package/dist/orchestrate-init-status.js +32 -1
  52. package/dist/orchestrate-init-status.js.map +1 -1
  53. package/dist/orchestrate-monitor.js +38 -38
  54. package/dist/orchestrate-monitor.js.map +1 -1
  55. package/dist/public-manifest.js +12 -5
  56. package/dist/public-manifest.js.map +1 -1
  57. package/dist/shared-validators.js +1 -0
  58. package/dist/shared-validators.js.map +1 -1
  59. package/dist/spawn-list.js +0 -0
  60. package/dist/wu-claim-branch.js +121 -0
  61. package/dist/wu-claim-branch.js.map +1 -0
  62. package/dist/wu-claim-output.js +83 -0
  63. package/dist/wu-claim-output.js.map +1 -0
  64. package/dist/wu-claim-resume-handler.js +85 -0
  65. package/dist/wu-claim-resume-handler.js.map +1 -0
  66. package/dist/wu-claim-state.js +572 -0
  67. package/dist/wu-claim-state.js.map +1 -0
  68. package/dist/wu-claim-validation.js +439 -0
  69. package/dist/wu-claim-validation.js.map +1 -0
  70. package/dist/wu-claim-worktree.js +221 -0
  71. package/dist/wu-claim-worktree.js.map +1 -0
  72. package/dist/wu-claim.js +54 -1402
  73. package/dist/wu-claim.js.map +1 -1
  74. package/dist/wu-create-content.js +254 -0
  75. package/dist/wu-create-content.js.map +1 -0
  76. package/dist/wu-create-readiness.js +57 -0
  77. package/dist/wu-create-readiness.js.map +1 -0
  78. package/dist/wu-create-validation.js +149 -0
  79. package/dist/wu-create-validation.js.map +1 -0
  80. package/dist/wu-create.js +39 -441
  81. package/dist/wu-create.js.map +1 -1
  82. package/dist/wu-done.js +144 -249
  83. package/dist/wu-done.js.map +1 -1
  84. package/dist/wu-edit-operations.js +432 -0
  85. package/dist/wu-edit-operations.js.map +1 -0
  86. package/dist/wu-edit-validators.js +280 -0
  87. package/dist/wu-edit-validators.js.map +1 -0
  88. package/dist/wu-edit.js +27 -713
  89. package/dist/wu-edit.js.map +1 -1
  90. package/dist/wu-prep.js +32 -2
  91. package/dist/wu-prep.js.map +1 -1
  92. package/dist/wu-repair.js +1 -1
  93. package/dist/wu-repair.js.map +1 -1
  94. package/dist/wu-spawn-prompt-builders.js +1123 -0
  95. package/dist/wu-spawn-prompt-builders.js.map +1 -0
  96. package/dist/wu-spawn-strategy-resolver.js +314 -0
  97. package/dist/wu-spawn-strategy-resolver.js.map +1 -0
  98. package/dist/wu-spawn.js +9 -1398
  99. package/dist/wu-spawn.js.map +1 -1
  100. package/package.json +10 -7
  101. package/templates/core/LUMENFLOW.md.template +29 -99
  102. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +1 -1
  103. package/templates/core/ai/onboarding/quick-ref-commands.md.template +29 -4
  104. package/templates/vendors/claude/.claude/skills/orchestration/SKILL.md.template +8 -8
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @file generators/require-wu.ts
3
+ * Generate the require-wu.sh hook script content (WU-1367).
4
+ *
5
+ * Extracted from enforcement-generator.ts by WU-1645.
6
+ */
7
+ /**
8
+ * Generate the require-wu.sh hook script content.
9
+ *
10
+ * This hook blocks Write/Edit operations when no WU is claimed.
11
+ * Implements graceful degradation: allows operations if LumenFlow
12
+ * state cannot be determined.
13
+ */
14
+ export function generateRequireWuScript() {
15
+ // Note: Shell variable escapes (\$, \") are intentional for the generated bash script
16
+ /* eslint-disable no-useless-escape */
17
+ return `#!/bin/bash
18
+ #
19
+ # require-wu.sh (WU-1367)
20
+ #
21
+ # PreToolUse hook that blocks Write/Edit when no WU is claimed.
22
+ # Graceful degradation: allows operations if state cannot be determined.
23
+ #
24
+ # Exit codes:
25
+ # 0 = Allow operation
26
+ # 2 = Block operation (stderr shown to Claude as guidance)
27
+ #
28
+
29
+ set -euo pipefail
30
+
31
+ SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
32
+
33
+ # Graceful degradation
34
+ graceful_allow() {
35
+ local reason="\$1"
36
+ exit 0
37
+ }
38
+
39
+ if [[ -z "\${CLAUDE_PROJECT_DIR:-}" ]]; then
40
+ graceful_allow "CLAUDE_PROJECT_DIR not set"
41
+ fi
42
+
43
+ MAIN_REPO_PATH="\$CLAUDE_PROJECT_DIR"
44
+ WORKTREES_DIR="\${MAIN_REPO_PATH}/worktrees"
45
+ LUMENFLOW_DIR="\${MAIN_REPO_PATH}/.lumenflow"
46
+ STATE_FILE="\${LUMENFLOW_DIR}/state/wu-events.jsonl"
47
+
48
+ # Check if LumenFlow is configured
49
+ if [[ ! -d "\$LUMENFLOW_DIR" ]]; then
50
+ graceful_allow "No .lumenflow directory"
51
+ fi
52
+
53
+ # Read JSON input
54
+ INPUT=\$(cat)
55
+ if [[ -z "\$INPUT" ]]; then
56
+ graceful_allow "No input"
57
+ fi
58
+
59
+ # Parse JSON
60
+ TMPFILE=\$(mktemp)
61
+ echo "\$INPUT" > "\$TMPFILE"
62
+
63
+ TOOL_NAME=\$(python3 -c "
64
+ import json
65
+ try:
66
+ with open('\$TMPFILE', 'r') as f:
67
+ data = json.load(f)
68
+ print(data.get('tool_name', ''))
69
+ except:
70
+ print('')
71
+ " 2>/dev/null || echo "")
72
+
73
+ rm -f "\$TMPFILE"
74
+
75
+ # Only check Write and Edit
76
+ if [[ "\$TOOL_NAME" != "Write" && "\$TOOL_NAME" != "Edit" ]]; then
77
+ exit 0
78
+ fi
79
+
80
+ # Check for active worktrees (indicates claimed WU)
81
+ if [[ -d "\$WORKTREES_DIR" ]]; then
82
+ WORKTREE_COUNT=\$(find "\$WORKTREES_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
83
+ if [[ "\$WORKTREE_COUNT" -gt 0 ]]; then
84
+ exit 0 # Has worktrees = has claimed WU
85
+ fi
86
+ fi
87
+
88
+ # Check state file for in_progress WUs
89
+ if [[ -f "\$STATE_FILE" ]]; then
90
+ # Look for any WU with in_progress status
91
+ if grep -q '"status":"in_progress"' "\$STATE_FILE" 2>/dev/null; then
92
+ exit 0 # Has in_progress WU
93
+ fi
94
+ fi
95
+
96
+ # No claimed WU found
97
+ echo "" >&2
98
+ echo "=== WU Enforcement ===" >&2
99
+ echo "" >&2
100
+ echo "BLOCKED: \$TOOL_NAME without claimed WU" >&2
101
+ echo "" >&2
102
+ echo "You must claim a WU before making edits:" >&2
103
+ echo " pnpm wu:claim --id WU-XXXX --lane <Lane>" >&2
104
+ echo " cd worktrees/<lane>-wu-xxxx" >&2
105
+ echo "" >&2
106
+ echo "Or create a new WU:" >&2
107
+ echo " pnpm wu:create --lane <Lane> --title \"Description\"" >&2
108
+ echo "" >&2
109
+ echo "See: LUMENFLOW.md for workflow details" >&2
110
+ echo "======================" >&2
111
+ exit 2
112
+ `;
113
+ /* eslint-enable no-useless-escape */
114
+ }
115
+ //# sourceMappingURL=require-wu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-wu.js","sourceRoot":"","sources":["../../../src/hooks/generators/require-wu.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB;IACrC,sFAAsF;IACtF,sCAAsC;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FR,CAAC;IACA,qCAAqC;AACvC,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @file generators/session-start-recovery.ts
3
+ * Generate the session-start-recovery.sh hook script content (WU-1394).
4
+ *
5
+ * Extracted from enforcement-generator.ts by WU-1645.
6
+ */
7
+ /**
8
+ * Generate the session-start-recovery.sh hook script content.
9
+ *
10
+ * This SessionStart hook checks for pending recovery files written by
11
+ * pre-compact-checkpoint.sh and displays the recovery context to the agent.
12
+ * After displaying, the recovery file is deleted (one-time recovery).
13
+ *
14
+ * Part of WU-1394: Durable recovery pattern for context preservation.
15
+ */
16
+ export function generateSessionStartRecoveryScript() {
17
+ // Note: Shell variable escapes (\$, \") are intentional for the generated bash script
18
+ /* eslint-disable no-useless-escape */
19
+ return `#!/bin/bash
20
+ #
21
+ # session-start-recovery.sh
22
+ #
23
+ # SessionStart hook - check for pending recovery and inject context (WU-1390)
24
+ #
25
+ # Fires after session start (on compact, resume, or clear) to:
26
+ # 1. Check for recovery-pending-*.md files written by pre-compact-checkpoint.sh
27
+ # 2. Display the recovery context to the agent
28
+ # 3. Remove the recovery file (one-time recovery)
29
+ #
30
+ # This completes the durable recovery pattern:
31
+ # PreCompact writes file → SessionStart reads and deletes it
32
+ #
33
+ # Exit codes:
34
+ # 0 = Always allow (informational hook)
35
+ #
36
+
37
+ set -euo pipefail
38
+
39
+ # Derive repo paths from CLAUDE_PROJECT_DIR
40
+ if [[ -n "\${CLAUDE_PROJECT_DIR:-}" ]]; then
41
+ REPO_PATH="\$CLAUDE_PROJECT_DIR"
42
+ else
43
+ REPO_PATH=\$(git rev-parse --show-toplevel 2>/dev/null || echo "")
44
+ if [[ -z "\$REPO_PATH" ]]; then
45
+ exit 0
46
+ fi
47
+ fi
48
+
49
+ RECOVERY_DIR="\${REPO_PATH}/.lumenflow/state"
50
+
51
+ # Check if recovery directory exists
52
+ if [[ ! -d "\$RECOVERY_DIR" ]]; then
53
+ exit 0
54
+ fi
55
+
56
+ # Find any pending recovery files
57
+ FOUND_RECOVERY=false
58
+
59
+ for recovery_file in "\$RECOVERY_DIR"/recovery-pending-*.md; do
60
+ # Check if glob matched any files (bash glob returns literal pattern if no match)
61
+ [[ -f "\$recovery_file" ]] || continue
62
+
63
+ FOUND_RECOVERY=true
64
+
65
+ # Extract WU ID from filename for display
66
+ WU_ID=\$(basename "\$recovery_file" | sed 's/recovery-pending-\\(.*\\)\\.md/\\1/')
67
+
68
+ echo "" >&2
69
+ echo "═══════════════════════════════════════════════════════" >&2
70
+ echo "⚠️ POST-COMPACTION RECOVERY DETECTED" >&2
71
+ echo "═══════════════════════════════════════════════════════" >&2
72
+ echo "" >&2
73
+
74
+ # Display the recovery context
75
+ cat "\$recovery_file" >&2
76
+
77
+ echo "" >&2
78
+ echo "═══════════════════════════════════════════════════════" >&2
79
+ echo "" >&2
80
+
81
+ # Remove after displaying (one-time recovery)
82
+ rm -f "\$recovery_file"
83
+ done
84
+
85
+ # Additional context if recovery was displayed
86
+ if [[ "\$FOUND_RECOVERY" == "true" ]]; then
87
+ echo "IMPORTANT: Your context was compacted. Review the recovery info above." >&2
88
+ echo "Recommended: Run 'pnpm wu:brief --id \$WU_ID --client claude-code' for fresh full context." >&2
89
+ echo "" >&2
90
+ fi
91
+
92
+ # WU-1473: Surface unread coordination signals for non-worktree orchestrators
93
+ # Even without recovery files, agents benefit from seeing recent inbox activity
94
+ # This supports orchestrators running from main checkout (not in a worktree)
95
+ pnpm mem:inbox --since 1h --unread-only --quiet 2>/dev/null >&2 || true
96
+
97
+ exit 0
98
+ `;
99
+ /* eslint-enable no-useless-escape */
100
+ }
101
+ //# sourceMappingURL=session-start-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start-recovery.js","sourceRoot":"","sources":["../../../src/hooks/generators/session-start-recovery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,MAAM,UAAU,kCAAkC;IAChD,sFAAsF;IACtF,sCAAsC;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+ER,CAAC;IACA,qCAAqC;AACvC,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @file generators/signal-utils.ts
3
+ * Signal surfacing and marking utilities for enforcement hooks (WU-1473).
4
+ *
5
+ * Extracted from enforcement-generator.ts by WU-1645.
6
+ */
7
+ import { loadSignals, markSignalsAsRead } from '@lumenflow/memory/signal';
8
+ /**
9
+ * WU-1473: Surface unread signals for agent consumption during claim/start.
10
+ *
11
+ * Loads all unread signals from the memory layer and returns them for display.
12
+ * Implements fail-open: any error returns an empty result without throwing.
13
+ *
14
+ * @param baseDir - Project base directory
15
+ * @returns Unread signal summary (never throws)
16
+ */
17
+ export async function surfaceUnreadSignals(baseDir) {
18
+ try {
19
+ const signals = await loadSignals(baseDir, { unreadOnly: true });
20
+ return { count: signals.length, signals };
21
+ }
22
+ catch {
23
+ // WU-1473 AC4: Fail-open - memory errors never block lifecycle commands
24
+ return { count: 0, signals: [] };
25
+ }
26
+ }
27
+ /**
28
+ * WU-1473: Mark all signals for a completed WU as read using receipt-aware behavior.
29
+ *
30
+ * Loads signals scoped to the given WU ID and marks any unread ones as read
31
+ * by appending receipts (WU-1472 pattern). Does not rewrite signals.jsonl.
32
+ * Implements fail-open: any error returns zero count without throwing.
33
+ *
34
+ * @param baseDir - Project base directory
35
+ * @param wuId - WU ID whose signals should be marked as read
36
+ * @returns Result with count of signals marked (never throws)
37
+ */
38
+ export async function markCompletedWUSignalsAsRead(baseDir, wuId) {
39
+ try {
40
+ const signals = await loadSignals(baseDir, { wuId, unreadOnly: true });
41
+ if (signals.length === 0) {
42
+ return { markedCount: 0 };
43
+ }
44
+ const signalIds = signals.map((sig) => sig.id);
45
+ return await markSignalsAsRead(baseDir, signalIds);
46
+ }
47
+ catch {
48
+ // WU-1473 AC4: Fail-open - memory errors never block lifecycle commands
49
+ return { markedCount: 0 };
50
+ }
51
+ }
52
+ //# sourceMappingURL=signal-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-utils.js","sourceRoot":"","sources":["../../../src/hooks/generators/signal-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAyB1E;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAe;IACxD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;QACxE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACnC,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAAe,EACf,IAAY;IAEZ,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QAC5B,CAAC;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/C,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;QACxE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @file generators/warn-incomplete.ts
3
+ * Generate the warn-incomplete.sh hook script content (WU-1367).
4
+ *
5
+ * Extracted from enforcement-generator.ts by WU-1645.
6
+ */
7
+ /**
8
+ * Generate the warn-incomplete.sh hook script content.
9
+ *
10
+ * This Stop hook warns when session ends without wu:done.
11
+ * Always exits 0 (warning only, never blocks).
12
+ */
13
+ export function generateWarnIncompleteScript() {
14
+ // Note: Shell variable escapes (\$, \") are intentional for the generated bash script
15
+ /* eslint-disable no-useless-escape */
16
+ return `#!/bin/bash
17
+ #
18
+ # warn-incomplete.sh (WU-1367)
19
+ #
20
+ # Stop hook that warns when session ends without wu:done.
21
+ # This is advisory only - never blocks session termination.
22
+ #
23
+ # Exit codes:
24
+ # 0 = Always (warnings only)
25
+ #
26
+
27
+ SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
28
+
29
+ if [[ -z "\${CLAUDE_PROJECT_DIR:-}" ]]; then
30
+ exit 0
31
+ fi
32
+
33
+ MAIN_REPO_PATH="\$CLAUDE_PROJECT_DIR"
34
+ WORKTREES_DIR="\${MAIN_REPO_PATH}/worktrees"
35
+
36
+ # Check for active worktrees
37
+ if [[ ! -d "\$WORKTREES_DIR" ]]; then
38
+ exit 0
39
+ fi
40
+
41
+ WORKTREE_COUNT=\$(find "\$WORKTREES_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
42
+ if [[ "\$WORKTREE_COUNT" -eq 0 ]]; then
43
+ exit 0
44
+ fi
45
+
46
+ # Get active worktree names
47
+ ACTIVE_WORKTREES=\$(find "\$WORKTREES_DIR" -mindepth 1 -maxdepth 1 -type d -printf '%f\\n' 2>/dev/null | head -5 | tr '\\n' ', ' | sed 's/,\$//')
48
+
49
+ echo "" >&2
50
+ echo "=== Session Completion Reminder ===" >&2
51
+ echo "" >&2
52
+ echo "You have active worktrees: \$ACTIVE_WORKTREES" >&2
53
+ echo "" >&2
54
+ echo "If your work is complete, remember to run:" >&2
55
+ echo " pnpm wu:prep --id WU-XXXX (from worktree)" >&2
56
+ echo " pnpm wu:done --id WU-XXXX (from main)" >&2
57
+ echo "" >&2
58
+ echo "If work is incomplete, it will be preserved in the worktree." >&2
59
+ echo "====================================" >&2
60
+
61
+ exit 0
62
+ `;
63
+ /* eslint-enable no-useless-escape */
64
+ }
65
+ //# sourceMappingURL=warn-incomplete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warn-incomplete.js","sourceRoot":"","sources":["../../../src/hooks/generators/warn-incomplete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B;IAC1C,sFAAsF;IACtF,sCAAsC;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CR,CAAC;IACA,qCAAqC;AACvC,CAAC"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * @file init-detection.ts
3
+ * Detection helpers for LumenFlow init command (WU-1644)
4
+ *
5
+ * Extracted from init.ts -- environment detection, prerequisite checks,
6
+ * git state inspection, and docs structure detection.
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { execFileSync } from 'node:child_process';
11
+ import { LUMENFLOW_CLIENT_IDS } from '@lumenflow/core';
12
+ const DEFAULT_CLIENT_CLAUDE = LUMENFLOW_CLIENT_IDS.CLAUDE_CODE;
13
+ /**
14
+ * WU-1177: Detect IDE environment from environment variables
15
+ * Auto-detects which AI coding assistant is running
16
+ */
17
+ export function detectIDEEnvironment() {
18
+ // Claude Code detection (highest priority - most specific)
19
+ if (process.env.CLAUDE_PROJECT_DIR || process.env.CLAUDE_CODE) {
20
+ return 'claude';
21
+ }
22
+ // Cursor detection
23
+ const cursorVars = Object.keys(process.env).filter((key) => key.startsWith('CURSOR_'));
24
+ if (cursorVars.length > 0) {
25
+ return 'cursor';
26
+ }
27
+ // Windsurf detection
28
+ const windsurfVars = Object.keys(process.env).filter((key) => key.startsWith('WINDSURF_'));
29
+ if (windsurfVars.length > 0) {
30
+ return 'windsurf';
31
+ }
32
+ // VS Code detection (lowest priority - most generic)
33
+ const vscodeVars = Object.keys(process.env).filter((key) => key.startsWith('VSCODE_'));
34
+ if (vscodeVars.length > 0) {
35
+ return 'vscode';
36
+ }
37
+ return undefined;
38
+ }
39
+ /**
40
+ * Get command version safely using execFileSync
41
+ */
42
+ function getCommandVersion(command, args) {
43
+ try {
44
+ const output = execFileSync(command, args, {
45
+ encoding: 'utf-8',
46
+ stdio: ['pipe', 'pipe', 'pipe'],
47
+ }).trim();
48
+ return output;
49
+ }
50
+ catch {
51
+ return 'not found';
52
+ }
53
+ }
54
+ /**
55
+ * Parse semver version string to compare
56
+ */
57
+ function parseVersion(versionStr) {
58
+ // Extract version numbers using a non-backtracking pattern
59
+ // eslint-disable-next-line security/detect-unsafe-regex -- static semver pattern; no backtracking risk
60
+ const match = /^v?(\d+)\.(\d+)(?:\.(\d+))?/.exec(versionStr);
61
+ if (!match) {
62
+ return [0, 0, 0];
63
+ }
64
+ return [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3] || '0', 10)];
65
+ }
66
+ /**
67
+ * Compare versions: returns true if actual >= required
68
+ */
69
+ function compareVersions(actual, required) {
70
+ const actualParts = parseVersion(actual);
71
+ const requiredParts = parseVersion(required);
72
+ for (let i = 0; i < 3; i++) {
73
+ if (actualParts[i] > requiredParts[i]) {
74
+ return true;
75
+ }
76
+ if (actualParts[i] < requiredParts[i]) {
77
+ return false;
78
+ }
79
+ }
80
+ return true;
81
+ }
82
+ /**
83
+ * WU-1177: Check prerequisite versions
84
+ * Non-blocking - returns results but doesn't fail init
85
+ */
86
+ export function checkPrerequisites() {
87
+ const nodeVersion = getCommandVersion('node', ['--version']);
88
+ const pnpmVersion = getCommandVersion('pnpm', ['--version']);
89
+ const gitVersion = getCommandVersion('git', ['--version']);
90
+ const requiredNode = '22.0.0';
91
+ const requiredPnpm = '9.0.0';
92
+ const requiredGit = '2.0.0';
93
+ const nodeOk = nodeVersion !== 'not found' && compareVersions(nodeVersion, requiredNode);
94
+ const pnpmOk = pnpmVersion !== 'not found' && compareVersions(pnpmVersion, requiredPnpm);
95
+ const gitOk = gitVersion !== 'not found' && compareVersions(gitVersion, requiredGit);
96
+ return {
97
+ node: {
98
+ passed: nodeOk,
99
+ version: nodeVersion,
100
+ required: `>=${requiredNode}`,
101
+ message: nodeOk ? undefined : `Node.js ${requiredNode}+ required`,
102
+ },
103
+ pnpm: {
104
+ passed: pnpmOk,
105
+ version: pnpmVersion,
106
+ required: `>=${requiredPnpm}`,
107
+ message: pnpmOk ? undefined : `pnpm ${requiredPnpm}+ required`,
108
+ },
109
+ git: {
110
+ passed: gitOk,
111
+ version: gitVersion,
112
+ required: `>=${requiredGit}`,
113
+ message: gitOk ? undefined : `Git ${requiredGit}+ required`,
114
+ },
115
+ };
116
+ }
117
+ /**
118
+ * WU-1309: Get docs paths based on structure type
119
+ */
120
+ export function getDocsPath(structure) {
121
+ if (structure === 'simple') {
122
+ return {
123
+ operations: 'docs',
124
+ tasks: 'docs/tasks',
125
+ onboarding: 'docs/_frameworks/lumenflow/agent/onboarding',
126
+ quickRefLink: 'docs/_frameworks/lumenflow/agent/onboarding/quick-ref-commands.md',
127
+ };
128
+ }
129
+ // arc42 structure
130
+ return {
131
+ operations: 'docs/04-operations',
132
+ tasks: 'docs/04-operations/tasks',
133
+ onboarding: 'docs/04-operations/_frameworks/lumenflow/agent/onboarding',
134
+ quickRefLink: 'docs/04-operations/_frameworks/lumenflow/agent/onboarding/quick-ref-commands.md',
135
+ };
136
+ }
137
+ /**
138
+ * WU-1309: Detect existing docs structure or return default
139
+ * Auto-detects arc42 when docs/04-operations or any numbered dir (01-*, 02-*, etc.) exists
140
+ */
141
+ export function detectDocsStructure(targetDir) {
142
+ const docsDir = path.join(targetDir, 'docs');
143
+ if (!fs.existsSync(docsDir)) {
144
+ return 'simple';
145
+ }
146
+ // Check for arc42 numbered directories (01-*, 02-*, ..., 04-operations, etc.)
147
+ const entries = fs.readdirSync(docsDir);
148
+ const hasNumberedDir = entries.some((entry) => /^\d{2}-/.test(entry));
149
+ if (hasNumberedDir) {
150
+ return 'arc42';
151
+ }
152
+ return 'simple';
153
+ }
154
+ /**
155
+ * Detect default client from environment
156
+ */
157
+ export function detectDefaultClient() {
158
+ if (process.env.CLAUDE_PROJECT_DIR || process.env.CLAUDE_CODE) {
159
+ return DEFAULT_CLIENT_CLAUDE;
160
+ }
161
+ return 'none';
162
+ }
163
+ /**
164
+ * WU-1364: Check if directory is a git repository
165
+ */
166
+ export function isGitRepo(targetDir) {
167
+ try {
168
+ // eslint-disable-next-line sonarjs/no-os-command-from-path -- git resolved from PATH; CLI tool requires git
169
+ execFileSync('git', ['rev-parse', '--git-dir'], {
170
+ cwd: targetDir,
171
+ stdio: 'pipe',
172
+ });
173
+ return true;
174
+ }
175
+ catch {
176
+ return false;
177
+ }
178
+ }
179
+ /**
180
+ * WU-1364: Check if git repo has any commits
181
+ */
182
+ export function hasGitCommits(targetDir) {
183
+ try {
184
+ // eslint-disable-next-line sonarjs/no-os-command-from-path -- git resolved from PATH; CLI tool requires git
185
+ execFileSync('git', ['rev-parse', 'HEAD'], {
186
+ cwd: targetDir,
187
+ stdio: 'pipe',
188
+ });
189
+ return true;
190
+ }
191
+ catch {
192
+ return false;
193
+ }
194
+ }
195
+ /**
196
+ * WU-1364: Check if git repo has an origin remote
197
+ */
198
+ export function hasOriginRemote(targetDir) {
199
+ try {
200
+ // eslint-disable-next-line sonarjs/no-os-command-from-path -- git resolved from PATH; CLI tool requires git
201
+ const result = execFileSync('git', ['remote', 'get-url', 'origin'], {
202
+ cwd: targetDir,
203
+ encoding: 'utf-8',
204
+ stdio: 'pipe',
205
+ });
206
+ return result.trim().length > 0;
207
+ }
208
+ catch {
209
+ return false;
210
+ }
211
+ }
212
+ /**
213
+ * WU-1364: Detect git state and return config overrides
214
+ * Returns requireRemote: false if no origin remote is configured
215
+ */
216
+ export function detectGitStateConfig(targetDir) {
217
+ // If not a git repo, default to local-only mode for safety
218
+ if (!isGitRepo(targetDir)) {
219
+ return { requireRemote: false };
220
+ }
221
+ // If git repo but no origin remote, set requireRemote: false
222
+ if (!hasOriginRemote(targetDir)) {
223
+ return { requireRemote: false };
224
+ }
225
+ // Has origin remote - use default (requireRemote: true)
226
+ return null;
227
+ }
228
+ //# sourceMappingURL=init-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-detection.js","sourceRoot":"","sources":["../src/init-detection.ts"],"names":[],"mappings":"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"}