@lumenflow/core 1.3.3 → 1.3.5

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 (58) hide show
  1. package/dist/adapters/filesystem-metrics.adapter.d.ts +1 -1
  2. package/dist/adapters/filesystem-metrics.adapter.js +1 -1
  3. package/dist/beacon-migration.d.ts +56 -0
  4. package/dist/beacon-migration.js +101 -0
  5. package/dist/cleanup-lock.js +3 -3
  6. package/dist/commands-logger.d.ts +2 -2
  7. package/dist/commands-logger.js +5 -5
  8. package/dist/core/tool-runner.d.ts +1 -1
  9. package/dist/core/tool-runner.js +2 -2
  10. package/dist/docs-path-validator.d.ts +2 -2
  11. package/dist/docs-path-validator.js +4 -4
  12. package/dist/domain/orchestration.constants.js +3 -3
  13. package/dist/force-bypass-audit.d.ts +2 -2
  14. package/dist/force-bypass-audit.js +8 -7
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +4 -0
  17. package/dist/lane-lock.d.ts +1 -1
  18. package/dist/lane-lock.js +3 -4
  19. package/dist/logs-lib.d.ts +2 -2
  20. package/dist/logs-lib.js +5 -4
  21. package/dist/lumenflow-config-schema.d.ts +1 -1
  22. package/dist/lumenflow-config-schema.js +19 -19
  23. package/dist/lumenflow-config.js +1 -1
  24. package/dist/merge-lock.js +7 -7
  25. package/dist/prompt-linter.js +3 -3
  26. package/dist/prompt-monitor.d.ts +1 -1
  27. package/dist/prompt-monitor.js +5 -5
  28. package/dist/rebase-artifact-cleanup.d.ts +1 -1
  29. package/dist/rebase-artifact-cleanup.js +1 -1
  30. package/dist/spawn-recovery.d.ts +2 -2
  31. package/dist/spawn-recovery.js +6 -6
  32. package/dist/spawn-registry-store.d.ts +2 -2
  33. package/dist/spawn-registry-store.js +2 -2
  34. package/dist/spawn-tree.d.ts +2 -2
  35. package/dist/spawn-tree.js +2 -2
  36. package/dist/stamp-utils.d.ts +1 -1
  37. package/dist/stamp-utils.js +1 -1
  38. package/dist/telemetry.d.ts +1 -1
  39. package/dist/telemetry.js +1 -1
  40. package/dist/wu-checkpoint.js +4 -4
  41. package/dist/wu-constants.d.ts +67 -4
  42. package/dist/wu-constants.js +41 -15
  43. package/dist/wu-done-branch-only.js +2 -2
  44. package/dist/wu-done-inputs.js +1 -1
  45. package/dist/wu-done-validation.js +2 -2
  46. package/dist/wu-done-worktree.js +4 -4
  47. package/dist/wu-paths.js +1 -1
  48. package/dist/wu-recovery.d.ts +4 -4
  49. package/dist/wu-recovery.js +8 -8
  50. package/dist/wu-repair-core.js +4 -4
  51. package/dist/wu-spawn-helpers.d.ts +1 -1
  52. package/dist/wu-spawn-helpers.js +3 -2
  53. package/dist/wu-spawn.js +7 -7
  54. package/dist/wu-state-store.d.ts +2 -2
  55. package/dist/wu-state-store.js +2 -2
  56. package/package.json +11 -11
  57. package/dist/spec-branch-helpers.d.ts +0 -118
  58. package/dist/spec-branch-helpers.js +0 -199
@@ -21,7 +21,7 @@ import { readWU, writeWU, parseYAML, stringifyYAML } from './wu-yaml.js';
21
21
  import { WU_PATHS } from './wu-paths.js';
22
22
  import { WUStateStore, WU_EVENTS_FILE_NAME } from './wu-state-store.js';
23
23
  import { getGitForCwd, createGitForPath } from './git-adapter.js';
24
- import { EXIT_CODES, LOG_PREFIX, EMOJI, WU_STATUS } from './wu-constants.js';
24
+ import { EXIT_CODES, LOG_PREFIX, EMOJI, WU_STATUS, LUMENFLOW_PATHS, } from './wu-constants.js';
25
25
  import { die } from './error-handler.js';
26
26
  import { ensureOnMain, ensureMainUpToDate, validateWUIDFormat } from './wu-helpers.js';
27
27
  import { withMicroWorktree } from './micro-worktree.js';
@@ -103,7 +103,7 @@ export async function checkClaimMetadata(id, worktreePath) {
103
103
  errors.push(`WU YAML not found at: ${wuPath}`);
104
104
  }
105
105
  // Check state store
106
- const stateDir = path.join(worktreePath, '.beacon', 'state');
106
+ const stateDir = path.join(worktreePath, LUMENFLOW_PATHS.STATE_DIR);
107
107
  const eventsPath = path.join(stateDir, WU_EVENTS_FILE_NAME);
108
108
  if (existsSync(eventsPath)) {
109
109
  try {
@@ -174,7 +174,7 @@ export async function repairClaimMetadata(id, worktreePath, checkResult) {
174
174
  // Repair 2: Add claim event to state store if missing
175
175
  if (!checkResult.stateStoreHasClaim) {
176
176
  try {
177
- const stateDir = path.join(worktreePath, '.beacon', 'state');
177
+ const stateDir = path.join(worktreePath, LUMENFLOW_PATHS.STATE_DIR);
178
178
  const eventsPath = path.join(stateDir, WU_EVENTS_FILE_NAME);
179
179
  // Ensure directory exists
180
180
  mkdirSync(stateDir, { recursive: true });
@@ -201,7 +201,7 @@ export async function repairClaimMetadata(id, worktreePath, checkResult) {
201
201
  const gitWorktree = createGitForPath(worktreePath);
202
202
  // Stage repaired files
203
203
  const filesToStage = [wuPath];
204
- const stateDir = path.join(worktreePath, '.beacon', 'state');
204
+ const stateDir = path.join(worktreePath, LUMENFLOW_PATHS.STATE_DIR);
205
205
  const eventsPath = path.join(stateDir, WU_EVENTS_FILE_NAME);
206
206
  if (existsSync(eventsPath)) {
207
207
  filesToStage.push(eventsPath);
@@ -79,7 +79,7 @@ export declare function getHelpText(): string;
79
79
  * @param {string} options.parentWuId - Parent WU ID (orchestrator)
80
80
  * @param {string} options.targetWuId - Target WU ID (spawned work)
81
81
  * @param {string} options.lane - Lane for the spawned work
82
- * @param {string} [options.baseDir] - Base directory for registry (defaults to .beacon/state)
82
+ * @param {string} [options.baseDir] - Base directory for registry (defaults to LUMENFLOW_PATHS.STATE_DIR)
83
83
  * @returns {Promise<{success: boolean, spawnId: string|null, error?: string}>}
84
84
  *
85
85
  * @example
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { Command } from 'commander';
14
14
  import { SpawnRegistryStore } from './spawn-registry-store.js';
15
+ import { LUMENFLOW_PATHS } from './wu-constants.js';
15
16
  /**
16
17
  * Option definitions for thinking mode configuration.
17
18
  *
@@ -210,7 +211,7 @@ const LOG_PREFIX = '[wu:spawn]';
210
211
  * @param {string} options.parentWuId - Parent WU ID (orchestrator)
211
212
  * @param {string} options.targetWuId - Target WU ID (spawned work)
212
213
  * @param {string} options.lane - Lane for the spawned work
213
- * @param {string} [options.baseDir] - Base directory for registry (defaults to .beacon/state)
214
+ * @param {string} [options.baseDir] - Base directory for registry (defaults to LUMENFLOW_PATHS.STATE_DIR)
214
215
  * @returns {Promise<{success: boolean, spawnId: string|null, error?: string}>}
215
216
  *
216
217
  * @example
@@ -225,7 +226,7 @@ const LOG_PREFIX = '[wu:spawn]';
225
226
  * }
226
227
  */
227
228
  export async function recordSpawnToRegistry(options) {
228
- const { parentWuId, targetWuId, lane, baseDir = '.beacon/state' } = options;
229
+ const { parentWuId, targetWuId, lane, baseDir = LUMENFLOW_PATHS.STATE_DIR } = options;
229
230
  try {
230
231
  const store = new SpawnRegistryStore(baseDir);
231
232
  await store.load();
package/dist/wu-spawn.js CHANGED
@@ -34,7 +34,7 @@ import { createWUParser, WU_OPTIONS } from './arg-parser.js';
34
34
  import { WU_PATHS } from './wu-paths.js';
35
35
  import { parseYAML } from './wu-yaml.js';
36
36
  import { die } from './error-handler.js';
37
- import { WU_STATUS, PATTERNS, EMOJI } from './wu-constants.js';
37
+ import { WU_STATUS, PATTERNS, EMOJI, LUMENFLOW_PATHS } from './wu-constants.js';
38
38
  // WU-1603: Check lane lock status before spawning
39
39
  import { checkLaneLock } from './lane-lock.js';
40
40
  import { minimatch } from 'minimatch';
@@ -650,7 +650,7 @@ git rev-parse --show-toplevel
650
650
 
651
651
  ### Stamp Creation
652
652
 
653
- When creating \`.beacon/\` stamps or other artifacts:
653
+ When creating \`.lumenflow/\` stamps or other artifacts:
654
654
 
655
655
  1. **ALWAYS** create stamps in the **worktree**, not main
656
656
  2. Use \`git rev-parse --show-toplevel\` to get the correct base path
@@ -659,11 +659,11 @@ When creating \`.beacon/\` stamps or other artifacts:
659
659
  \`\`\`bash
660
660
  # CORRECT: Create stamp in worktree
661
661
  WORKTREE_ROOT=$(git rev-parse --show-toplevel)
662
- mkdir -p "$WORKTREE_ROOT/.beacon/agent-runs"
663
- touch "$WORKTREE_ROOT/.beacon/agent-runs/beacon-guardian.stamp"
662
+ mkdir -p "$WORKTREE_ROOT/.lumenflow/agent-runs"
663
+ touch "$WORKTREE_ROOT/.lumenflow/agent-runs/beacon-guardian.stamp"
664
664
 
665
665
  # WRONG: Hardcoded path to main
666
- # touch /path/to/main/.beacon/agent-runs/beacon-guardian.stamp
666
+ # touch /path/to/main/.lumenflow/agent-runs/beacon-guardian.stamp
667
667
  \`\`\`
668
668
 
669
669
  ### Why This Matters
@@ -789,7 +789,7 @@ cd worktrees/${laneSlug}-${id.toLowerCase()}
789
789
  Then implement following all standards above.
790
790
 
791
791
  **CRITICAL:** Never use \`git worktree add\` directly. Always use \`pnpm wu:claim\` to ensure:
792
- - Event tracking in .beacon/state/wu-events.jsonl
792
+ - Event tracking in ${LUMENFLOW_PATHS.WU_EVENTS}
793
793
  - Lane lock acquisition (WIP=1 enforcement)
794
794
  - Session tracking for context recovery`;
795
795
  }
@@ -1229,7 +1229,7 @@ async function main() {
1229
1229
  parentWuId: args.parentWu,
1230
1230
  targetWuId: id,
1231
1231
  lane: doc.lane || 'Unknown',
1232
- baseDir: '.beacon/state',
1232
+ baseDir: LUMENFLOW_PATHS.STATE_DIR,
1233
1233
  });
1234
1234
  const registryMessage = formatSpawnRecordedMessage(registryResult.spawnId, registryResult.error);
1235
1235
  console.log(`\n${registryMessage}`);
@@ -2,7 +2,7 @@
2
2
  * WU State Store (WU-1570, WU-2240)
3
3
  *
4
4
  * Event-sourced state store for WU lifecycle following INIT-007 pattern.
5
- * Stores events in .beacon/state/wu-events.jsonl (append-only, git-friendly).
5
+ * Stores events in .lumenflow/state/wu-events.jsonl (append-only, git-friendly).
6
6
  *
7
7
  * Features:
8
8
  * - Event sourcing with replay for current state
@@ -255,7 +255,7 @@ export declare function releaseLock(lockPath: string): void;
255
255
  * - Returns detailed repair statistics
256
256
  *
257
257
  * @example
258
- * const stateFilePath = path.join(process.cwd(), '.beacon', 'state', 'wu-events.jsonl');
258
+ * const stateFilePath = path.join(process.cwd(), '.lumenflow', 'state', 'wu-events.jsonl');
259
259
  * const result = await repairStateFile(stateFilePath);
260
260
  * if (result.success) {
261
261
  * console.log(`Repaired: kept ${result.linesKept}, removed ${result.linesRemoved}`);
@@ -2,7 +2,7 @@
2
2
  * WU State Store (WU-1570, WU-2240)
3
3
  *
4
4
  * Event-sourced state store for WU lifecycle following INIT-007 pattern.
5
- * Stores events in .beacon/state/wu-events.jsonl (append-only, git-friendly).
5
+ * Stores events in .lumenflow/state/wu-events.jsonl (append-only, git-friendly).
6
6
  *
7
7
  * Features:
8
8
  * - Event sourcing with replay for current state
@@ -592,7 +592,7 @@ export function releaseLock(lockPath) {
592
592
  * - Returns detailed repair statistics
593
593
  *
594
594
  * @example
595
- * const stateFilePath = path.join(process.cwd(), '.beacon', 'state', 'wu-events.jsonl');
595
+ * const stateFilePath = path.join(process.cwd(), '.lumenflow', 'state', 'wu-events.jsonl');
596
596
  * const result = await repairStateFile(stateFilePath);
597
597
  * if (result.success) {
598
598
  * console.log(`Repaired: kept ${result.linesKept}, removed ${result.linesRemoved}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/core",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "Core WU lifecycle tools for LumenFlow workflow framework",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -65,13 +65,6 @@
65
65
  "LICENSE",
66
66
  "README.md"
67
67
  ],
68
- "scripts": {
69
- "build": "tsc",
70
- "build:dist": "tsc -p tsconfig.build.json",
71
- "pack:dist": "pnpm pack",
72
- "clean": "rm -rf dist *.tgz",
73
- "test": "vitest run"
74
- },
75
68
  "dependencies": {
76
69
  "change-case": "^5.4.4",
77
70
  "cli-progress": "^3.12.0",
@@ -98,8 +91,8 @@
98
91
  "vitest": "^4.0.17"
99
92
  },
100
93
  "peerDependencies": {
101
- "@lumenflow/memory": "workspace:*",
102
- "@lumenflow/initiatives": "workspace:*"
94
+ "@lumenflow/memory": "1.3.5",
95
+ "@lumenflow/initiatives": "1.3.5"
103
96
  },
104
97
  "peerDependenciesMeta": {
105
98
  "@lumenflow/memory": {
@@ -114,5 +107,12 @@
114
107
  },
115
108
  "publishConfig": {
116
109
  "access": "public"
110
+ },
111
+ "scripts": {
112
+ "build": "tsc",
113
+ "build:dist": "tsc -p tsconfig.build.json",
114
+ "pack:dist": "pnpm pack",
115
+ "clean": "rm -rf dist *.tgz",
116
+ "test": "vitest run"
117
117
  }
118
- }
118
+ }
@@ -1,118 +0,0 @@
1
- /**
2
- * Spec Branch Helpers
3
- *
4
- * WU-1062: External plan storage and no-main-write mode
5
- *
6
- * Provides helpers for working with spec branches (spec/wu-XXXX).
7
- * wu:create writes to spec branches by default; wu:claim merges them to main.
8
- *
9
- * @module
10
- */
11
- import type { GitAdapter } from './git-adapter.js';
12
- /**
13
- * Spec branch prefix
14
- */
15
- export declare const SPEC_BRANCH_PREFIX = "spec/";
16
- /**
17
- * WU source location constants
18
- */
19
- export declare const WU_SOURCE: {
20
- /** WU exists on main branch only */
21
- readonly MAIN: "main";
22
- /** WU exists on spec branch only */
23
- readonly SPEC_BRANCH: "spec_branch";
24
- /** WU exists on both main and spec branch */
25
- readonly BOTH: "both";
26
- /** WU not found anywhere */
27
- readonly NOT_FOUND: "not_found";
28
- };
29
- export type WUSourceType = (typeof WU_SOURCE)[keyof typeof WU_SOURCE];
30
- /**
31
- * Get the spec branch name for a WU
32
- *
33
- * @param {string} wuId - Work Unit ID (e.g., 'WU-1062')
34
- * @returns {string} Spec branch name (e.g., 'spec/wu-1062')
35
- *
36
- * @example
37
- * getSpecBranchName('WU-1062') // 'spec/wu-1062'
38
- */
39
- export declare function getSpecBranchName(wuId: string): string;
40
- /**
41
- * Get the origin-qualified spec branch name
42
- *
43
- * @param {string} wuId - Work Unit ID
44
- * @returns {string} Origin-qualified branch name (e.g., 'origin/spec/wu-1062')
45
- */
46
- export declare function getOriginSpecBranch(wuId: string): string;
47
- /**
48
- * Check if a spec branch exists on origin
49
- *
50
- * @param {string} wuId - Work Unit ID
51
- * @param {SimpleGit} git - Git adapter instance
52
- * @returns {Promise<boolean>} True if spec branch exists
53
- *
54
- * @example
55
- * const exists = await specBranchExists('WU-1062', git);
56
- */
57
- export declare function specBranchExists(wuId: string, git: GitAdapter): Promise<boolean>;
58
- /**
59
- * Check if a WU exists on main branch
60
- *
61
- * @param {string} wuId - Work Unit ID
62
- * @param {SimpleGit} git - Git adapter instance
63
- * @returns {Promise<boolean>} True if WU YAML exists on main
64
- */
65
- export declare function isWUOnMain(wuId: string, git: GitAdapter): Promise<boolean>;
66
- /**
67
- * Merge spec branch to main branch (fast-forward only)
68
- *
69
- * This is used by wu:claim when a WU exists only on a spec branch.
70
- * The spec branch is merged to main before creating the worktree.
71
- *
72
- * @param {string} wuId - Work Unit ID
73
- * @param {SimpleGit} git - Git adapter instance
74
- * @throws {Error} If merge fails (e.g., due to conflicts)
75
- *
76
- * @example
77
- * await mergeSpecBranchToMain('WU-1062', git);
78
- */
79
- export declare function mergeSpecBranchToMain(wuId: string, git: GitAdapter): Promise<void>;
80
- /**
81
- * Delete spec branch after merge
82
- *
83
- * @param {string} wuId - Work Unit ID
84
- * @param {SimpleGit} git - Git adapter instance
85
- */
86
- export declare function deleteSpecBranch(wuId: string, git: GitAdapter): Promise<void>;
87
- /**
88
- * Determine the source of a WU (main, spec branch, both, or not found)
89
- *
90
- * Used by wu:claim to decide whether to merge spec branch before creating worktree.
91
- *
92
- * @param {string} wuId - Work Unit ID
93
- * @param {SimpleGit} git - Git adapter instance
94
- * @returns {Promise<WUSourceType>} Source location constant
95
- *
96
- * @example
97
- * const source = await getWUSource('WU-1062', git);
98
- * if (source === WU_SOURCE.SPEC_BRANCH) {
99
- * await mergeSpecBranchToMain('WU-1062', git);
100
- * }
101
- */
102
- export declare function getWUSource(wuId: string, git: GitAdapter): Promise<WUSourceType>;
103
- /**
104
- * Create a spec branch from current HEAD
105
- *
106
- * Used by wu:create in default mode (no --direct flag).
107
- *
108
- * @param {string} wuId - Work Unit ID
109
- * @param {SimpleGit} git - Git adapter instance
110
- */
111
- export declare function createSpecBranch(wuId: string, git: GitAdapter): Promise<void>;
112
- /**
113
- * Push spec branch to origin
114
- *
115
- * @param {string} wuId - Work Unit ID
116
- * @param {SimpleGit} git - Git adapter instance
117
- */
118
- export declare function pushSpecBranch(wuId: string, git: GitAdapter): Promise<void>;
@@ -1,199 +0,0 @@
1
- /**
2
- * Spec Branch Helpers
3
- *
4
- * WU-1062: External plan storage and no-main-write mode
5
- *
6
- * Provides helpers for working with spec branches (spec/wu-XXXX).
7
- * wu:create writes to spec branches by default; wu:claim merges them to main.
8
- *
9
- * @module
10
- */
11
- import { WU_PATHS } from './wu-paths.js';
12
- import { REMOTES, GIT_REFS, GIT_COMMANDS, GIT_FLAGS } from './wu-constants.js';
13
- /**
14
- * Spec branch prefix
15
- */
16
- export const SPEC_BRANCH_PREFIX = 'spec/';
17
- /**
18
- * WU source location constants
19
- */
20
- export const WU_SOURCE = {
21
- /** WU exists on main branch only */
22
- MAIN: 'main',
23
- /** WU exists on spec branch only */
24
- SPEC_BRANCH: 'spec_branch',
25
- /** WU exists on both main and spec branch */
26
- BOTH: 'both',
27
- /** WU not found anywhere */
28
- NOT_FOUND: 'not_found',
29
- };
30
- /**
31
- * Get the spec branch name for a WU
32
- *
33
- * @param {string} wuId - Work Unit ID (e.g., 'WU-1062')
34
- * @returns {string} Spec branch name (e.g., 'spec/wu-1062')
35
- *
36
- * @example
37
- * getSpecBranchName('WU-1062') // 'spec/wu-1062'
38
- */
39
- export function getSpecBranchName(wuId) {
40
- return `${SPEC_BRANCH_PREFIX}${wuId.toLowerCase()}`;
41
- }
42
- /**
43
- * Get the origin-qualified spec branch name
44
- *
45
- * @param {string} wuId - Work Unit ID
46
- * @returns {string} Origin-qualified branch name (e.g., 'origin/spec/wu-1062')
47
- */
48
- export function getOriginSpecBranch(wuId) {
49
- return GIT_REFS.remote(REMOTES.ORIGIN, getSpecBranchName(wuId));
50
- }
51
- /**
52
- * Check if a spec branch exists on origin
53
- *
54
- * @param {string} wuId - Work Unit ID
55
- * @param {SimpleGit} git - Git adapter instance
56
- * @returns {Promise<boolean>} True if spec branch exists
57
- *
58
- * @example
59
- * const exists = await specBranchExists('WU-1062', git);
60
- */
61
- export async function specBranchExists(wuId, git) {
62
- try {
63
- const originBranch = getOriginSpecBranch(wuId);
64
- // Use branchExists if available, otherwise check with ls-remote
65
- if ('branchExists' in git && typeof git.branchExists === 'function') {
66
- return await git.branchExists(originBranch);
67
- }
68
- // Fallback: use ls-remote to check if branch exists
69
- const result = await git.raw([
70
- GIT_COMMANDS.LS_REMOTE,
71
- GIT_FLAGS.HEADS,
72
- REMOTES.ORIGIN,
73
- getSpecBranchName(wuId),
74
- ]);
75
- return result.trim().length > 0;
76
- }
77
- catch {
78
- return false;
79
- }
80
- }
81
- /**
82
- * Check if a WU exists on main branch
83
- *
84
- * @param {string} wuId - Work Unit ID
85
- * @param {SimpleGit} git - Git adapter instance
86
- * @returns {Promise<boolean>} True if WU YAML exists on main
87
- */
88
- export async function isWUOnMain(wuId, git) {
89
- try {
90
- const wuPath = WU_PATHS.WU(wuId);
91
- // Check if file exists on origin/main
92
- // git ls-tree returns exit 0 with empty output if file doesn't exist
93
- const result = await git.raw([GIT_COMMANDS.LS_TREE, GIT_REFS.ORIGIN_MAIN, GIT_FLAGS.PATH_SEPARATOR, wuPath]);
94
- return result.trim().length > 0;
95
- }
96
- catch {
97
- return false;
98
- }
99
- }
100
- /**
101
- * Merge spec branch to main branch (fast-forward only)
102
- *
103
- * This is used by wu:claim when a WU exists only on a spec branch.
104
- * The spec branch is merged to main before creating the worktree.
105
- *
106
- * @param {string} wuId - Work Unit ID
107
- * @param {SimpleGit} git - Git adapter instance
108
- * @throws {Error} If merge fails (e.g., due to conflicts)
109
- *
110
- * @example
111
- * await mergeSpecBranchToMain('WU-1062', git);
112
- */
113
- export async function mergeSpecBranchToMain(wuId, git) {
114
- const specBranch = getSpecBranchName(wuId);
115
- const originSpecBranch = getOriginSpecBranch(wuId);
116
- // Fetch the spec branch
117
- await git.fetch(REMOTES.ORIGIN, specBranch);
118
- // Merge with fast-forward only (safe merge)
119
- await git.merge(originSpecBranch, { ffOnly: true });
120
- }
121
- /**
122
- * Delete spec branch after merge
123
- *
124
- * @param {string} wuId - Work Unit ID
125
- * @param {SimpleGit} git - Git adapter instance
126
- */
127
- export async function deleteSpecBranch(wuId, git) {
128
- const specBranch = getSpecBranchName(wuId);
129
- try {
130
- // Delete local branch if exists
131
- await git.deleteBranch(specBranch);
132
- }
133
- catch {
134
- // Ignore if local branch doesn't exist
135
- }
136
- try {
137
- // Delete remote branch
138
- await git.raw([GIT_COMMANDS.PUSH, REMOTES.ORIGIN, GIT_FLAGS.DELETE_REMOTE, specBranch]);
139
- }
140
- catch {
141
- // Ignore if remote branch doesn't exist
142
- }
143
- }
144
- /**
145
- * Determine the source of a WU (main, spec branch, both, or not found)
146
- *
147
- * Used by wu:claim to decide whether to merge spec branch before creating worktree.
148
- *
149
- * @param {string} wuId - Work Unit ID
150
- * @param {SimpleGit} git - Git adapter instance
151
- * @returns {Promise<WUSourceType>} Source location constant
152
- *
153
- * @example
154
- * const source = await getWUSource('WU-1062', git);
155
- * if (source === WU_SOURCE.SPEC_BRANCH) {
156
- * await mergeSpecBranchToMain('WU-1062', git);
157
- * }
158
- */
159
- export async function getWUSource(wuId, git) {
160
- // Check both locations in parallel for efficiency
161
- const [onMain, hasSpecBranch] = await Promise.all([
162
- isWUOnMain(wuId, git),
163
- specBranchExists(wuId, git),
164
- ]);
165
- if (onMain && hasSpecBranch) {
166
- return WU_SOURCE.BOTH;
167
- }
168
- if (onMain) {
169
- return WU_SOURCE.MAIN;
170
- }
171
- if (hasSpecBranch) {
172
- return WU_SOURCE.SPEC_BRANCH;
173
- }
174
- return WU_SOURCE.NOT_FOUND;
175
- }
176
- /**
177
- * Create a spec branch from current HEAD
178
- *
179
- * Used by wu:create in default mode (no --direct flag).
180
- *
181
- * @param {string} wuId - Work Unit ID
182
- * @param {SimpleGit} git - Git adapter instance
183
- */
184
- export async function createSpecBranch(wuId, git) {
185
- const specBranch = getSpecBranchName(wuId);
186
- // Create local branch and checkout
187
- await git.createBranch(specBranch);
188
- }
189
- /**
190
- * Push spec branch to origin
191
- *
192
- * @param {string} wuId - Work Unit ID
193
- * @param {SimpleGit} git - Git adapter instance
194
- */
195
- export async function pushSpecBranch(wuId, git) {
196
- const specBranch = getSpecBranchName(wuId);
197
- // Push to origin
198
- await git.push(REMOTES.ORIGIN, specBranch);
199
- }