@lumenflow/core 1.0.0 → 1.3.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 (65) hide show
  1. package/dist/arg-parser.js +31 -1
  2. package/dist/backlog-generator.js +1 -1
  3. package/dist/backlog-sync-validator.js +3 -3
  4. package/dist/branch-check.d.ts +21 -0
  5. package/dist/branch-check.js +77 -0
  6. package/dist/cli/is-agent-branch.d.ts +11 -0
  7. package/dist/cli/is-agent-branch.js +15 -0
  8. package/dist/code-paths-overlap.js +2 -2
  9. package/dist/error-handler.d.ts +1 -0
  10. package/dist/error-handler.js +4 -1
  11. package/dist/git-adapter.d.ts +16 -0
  12. package/dist/git-adapter.js +23 -1
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.js +2 -0
  15. package/dist/lane-checker.d.ts +36 -3
  16. package/dist/lane-checker.js +128 -17
  17. package/dist/lane-inference.js +3 -4
  18. package/dist/lumenflow-config-schema.d.ts +125 -0
  19. package/dist/lumenflow-config-schema.js +76 -0
  20. package/dist/orchestration-rules.d.ts +1 -1
  21. package/dist/orchestration-rules.js +2 -2
  22. package/dist/path-classifiers.d.ts +1 -1
  23. package/dist/path-classifiers.js +1 -1
  24. package/dist/rebase-artifact-cleanup.d.ts +17 -0
  25. package/dist/rebase-artifact-cleanup.js +49 -8
  26. package/dist/spawn-strategy.d.ts +53 -0
  27. package/dist/spawn-strategy.js +106 -0
  28. package/dist/stamp-utils.d.ts +10 -0
  29. package/dist/stamp-utils.js +17 -19
  30. package/dist/token-counter.js +2 -2
  31. package/dist/wu-consistency-checker.js +5 -5
  32. package/dist/wu-constants.d.ts +21 -3
  33. package/dist/wu-constants.js +28 -3
  34. package/dist/wu-done-branch-utils.d.ts +10 -0
  35. package/dist/wu-done-branch-utils.js +31 -0
  36. package/dist/wu-done-cleanup.d.ts +8 -0
  37. package/dist/wu-done-cleanup.js +122 -0
  38. package/dist/wu-done-docs-only.d.ts +20 -0
  39. package/dist/wu-done-docs-only.js +65 -0
  40. package/dist/wu-done-errors.d.ts +17 -0
  41. package/dist/wu-done-errors.js +24 -0
  42. package/dist/wu-done-inputs.d.ts +12 -0
  43. package/dist/wu-done-inputs.js +51 -0
  44. package/dist/wu-done-metadata.d.ts +100 -0
  45. package/dist/wu-done-metadata.js +193 -0
  46. package/dist/wu-done-paths.d.ts +69 -0
  47. package/dist/wu-done-paths.js +237 -0
  48. package/dist/wu-done-preflight.d.ts +48 -0
  49. package/dist/wu-done-preflight.js +185 -0
  50. package/dist/wu-done-validation.d.ts +82 -0
  51. package/dist/wu-done-validation.js +340 -0
  52. package/dist/wu-done-validators.d.ts +13 -409
  53. package/dist/wu-done-validators.js +9 -1225
  54. package/dist/wu-done-worktree.d.ts +0 -1
  55. package/dist/wu-done-worktree.js +12 -30
  56. package/dist/wu-schema.js +1 -3
  57. package/dist/wu-spawn-skills.d.ts +19 -0
  58. package/dist/wu-spawn-skills.js +148 -0
  59. package/dist/wu-spawn.d.ts +17 -4
  60. package/dist/wu-spawn.js +99 -176
  61. package/dist/wu-validation.d.ts +1 -0
  62. package/dist/wu-validation.js +21 -1
  63. package/dist/wu-validator.d.ts +51 -0
  64. package/dist/wu-validator.js +108 -0
  65. package/package.json +11 -8
@@ -15,6 +15,16 @@ function collectRepeatable(value, previous) {
15
15
  }
16
16
  export const WU_OPTIONS = {
17
17
  // String options (require values)
18
+ client: {
19
+ name: 'client',
20
+ flags: '--client <client>',
21
+ description: 'Client name (claude-code, gemini-cli, etc)',
22
+ },
23
+ vendor: {
24
+ name: 'vendor',
25
+ flags: '--vendor <vendor>',
26
+ description: 'Deprecated alias for --client',
27
+ },
18
28
  id: {
19
29
  name: 'id',
20
30
  flags: '-i, --id <wuId>',
@@ -124,6 +134,11 @@ export const WU_OPTIONS = {
124
134
  flags: '--skip-gates',
125
135
  description: 'Skip gates check (requires --reason and --fix-wu)',
126
136
  },
137
+ docsOnly: {
138
+ name: 'docsOnly',
139
+ flags: '--docs-only',
140
+ description: 'Run docs-only gates (requires exposure: documentation or docs-only code_paths)',
141
+ },
127
142
  allowTodo: {
128
143
  name: 'allowTodo',
129
144
  flags: '--allow-todo',
@@ -154,6 +169,12 @@ export const WU_OPTIONS = {
154
169
  flags: '--fix',
155
170
  description: 'Auto-fix common YAML validation issues (WU-1359)',
156
171
  },
172
+ noPush: {
173
+ name: 'noPush',
174
+ flags: '--no-push',
175
+ description: 'Skip pushing claim branch or canonical updates (air-gapped/offline)',
176
+ isNegated: true,
177
+ },
157
178
  createPr: {
158
179
  name: 'createPr',
159
180
  flags: '--create-pr',
@@ -368,12 +389,18 @@ export const WU_OPTIONS = {
368
389
  flags: '--resume',
369
390
  description: 'Resume a WU from a crashed/killed agent (handoff) by taking over the existing worktree and updating the lock with new PID. Fails if original PID is still running (safety) or worktree does not exist.',
370
391
  },
392
+ // WU-1023: Skip auto-setup for fast claims
393
+ skipSetup: {
394
+ name: 'skipSetup',
395
+ flags: '--skip-setup',
396
+ description: 'Skip automatic pnpm install in worktree after creation (faster claims when deps already built)',
397
+ },
371
398
  };
372
399
  /**
373
400
  * Negated options that commander handles specially.
374
401
  * --no-foo creates opts.foo = false. We convert to noFoo = true.
375
402
  */
376
- const NEGATED_OPTIONS = ['auto', 'remove', 'merge', 'autoRebase'];
403
+ const NEGATED_OPTIONS = ['auto', 'remove', 'merge', 'autoRebase', 'push'];
377
404
  /**
378
405
  * Post-process commander opts to handle negated boolean options.
379
406
  * Commander's --no-* flags create opts.foo = false.
@@ -527,6 +554,7 @@ export function parseWUArgs(argv) {
527
554
  WU_OPTIONS.noMerge,
528
555
  WU_OPTIONS.help,
529
556
  WU_OPTIONS.skipGates,
557
+ WU_OPTIONS.docsOnly,
530
558
  WU_OPTIONS.allowTodo,
531
559
  WU_OPTIONS.skipExposureCheck,
532
560
  WU_OPTIONS.skipAccessibilityCheck,
@@ -535,6 +563,8 @@ export function parseWUArgs(argv) {
535
563
  WU_OPTIONS.overrideOwner,
536
564
  WU_OPTIONS.noAutoRebase,
537
565
  WU_OPTIONS.requireAgents,
566
+ WU_OPTIONS.client,
567
+ WU_OPTIONS.vendor,
538
568
  ];
539
569
  for (const opt of allOptions) {
540
570
  program.option(opt.flags, opt.description, opt.default);
@@ -54,7 +54,7 @@ sections:
54
54
  insertion: after_heading_blank_line
55
55
  ---
56
56
 
57
- > Agent: Read **ai/onboarding/starting-prompt.md** first, then follow **docs/04-operations/\\_frameworks/lumenflow/lumenflow-complete.md** for execution.
57
+ > Agent: Read **docs/04-operations/_frameworks/lumenflow/agent/onboarding/starting-prompt.md** first, then follow **docs/04-operations/\\_frameworks/lumenflow/lumenflow-complete.md** for execution.
58
58
 
59
59
  # Backlog (single source of truth)
60
60
 
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { readFileSync, writeFileSync, existsSync, copyFileSync } from 'node:fs';
9
9
  import path from 'node:path';
10
- import yaml from 'js-yaml';
10
+ import { parseYAML } from './wu-yaml.js';
11
11
  import { parseBacklogFrontmatter, getSectionHeadings } from './backlog-parser.js';
12
12
  import { extractParent } from './lane-checker.js';
13
13
  import { CONFIG_FILES, STRING_LITERALS, getProjectRoot, } from './wu-constants.js';
@@ -24,7 +24,7 @@ function hasSubLaneTaxonomy(parent, projectRoot) {
24
24
  }
25
25
  try {
26
26
  const taxonomyContent = readFileSync(taxonomyPath, { encoding: 'utf-8' });
27
- const taxonomy = yaml.load(taxonomyContent);
27
+ const taxonomy = parseYAML(taxonomyContent);
28
28
  const normalizedParent = parent.trim().toLowerCase();
29
29
  return Object.keys(taxonomy).some((key) => key.toLowerCase().trim() === normalizedParent);
30
30
  }
@@ -126,7 +126,7 @@ export function validateBacklogSync(backlogPath) {
126
126
  }
127
127
  try {
128
128
  const wuContent = readFileSync(wuPath, { encoding: 'utf-8' });
129
- const wuDoc = yaml.load(wuContent);
129
+ const wuDoc = parseYAML(wuContent);
130
130
  if (wuDoc && wuDoc.lane) {
131
131
  const lane = wuDoc.lane.toString().trim();
132
132
  const hasColon = lane.includes(':');
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Branch-aware bypass detection for cloud/automation agents.
3
+ *
4
+ * Provides functions to check if a branch is an agent branch that can
5
+ * bypass worktree requirements, and if headless mode is allowed.
6
+ *
7
+ * @module branch-check
8
+ */
9
+ /**
10
+ * Check if branch is an agent branch that can bypass worktree requirements.
11
+ * Uses the existing config loader (which handles caching/validation).
12
+ *
13
+ * @param branch - Branch name to check
14
+ * @returns True if branch matches agent patterns
15
+ */
16
+ export declare function isAgentBranch(branch: string | null | undefined): boolean;
17
+ /**
18
+ * Check if headless mode is allowed (guarded).
19
+ * Requires LUMENFLOW_HEADLESS=1 AND (LUMENFLOW_ADMIN=1 OR CI truthy OR GITHUB_ACTIONS truthy)
20
+ */
21
+ export declare function isHeadlessAllowed(): boolean;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Branch-aware bypass detection for cloud/automation agents.
3
+ *
4
+ * Provides functions to check if a branch is an agent branch that can
5
+ * bypass worktree requirements, and if headless mode is allowed.
6
+ *
7
+ * @module branch-check
8
+ */
9
+ import micromatch from 'micromatch';
10
+ import { getConfig } from './lumenflow-config.js';
11
+ /** Default agent branch patterns (narrow: just agent/*) */
12
+ const DEFAULT_AGENT_BRANCH_PATTERNS = ['agent/*'];
13
+ /** Legacy protected branch (always protected regardless of mainBranch setting) */
14
+ const LEGACY_PROTECTED = 'master';
15
+ /**
16
+ * Get lane branch pattern from config (or default).
17
+ * Lane branches always require worktrees - never bypassed.
18
+ */
19
+ function getLaneBranchPattern() {
20
+ const config = getConfig();
21
+ const prefix = config?.git?.laneBranchPrefix ?? 'lane/';
22
+ // Escape regex special chars in prefix, then anchor to start
23
+ const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
24
+ return new RegExp(`^${escaped}`);
25
+ }
26
+ /**
27
+ * Get protected branches derived from config.
28
+ * Returns [mainBranch, 'master'] to avoid config duplication.
29
+ */
30
+ function getProtectedBranches() {
31
+ const config = getConfig();
32
+ const mainBranch = config?.git?.mainBranch ?? 'main';
33
+ // Deduplicate in case mainBranch is 'master'
34
+ const protectedSet = new Set([mainBranch, LEGACY_PROTECTED]);
35
+ return Array.from(protectedSet);
36
+ }
37
+ /**
38
+ * Check if branch is an agent branch that can bypass worktree requirements.
39
+ * Uses the existing config loader (which handles caching/validation).
40
+ *
41
+ * @param branch - Branch name to check
42
+ * @returns True if branch matches agent patterns
43
+ */
44
+ export function isAgentBranch(branch) {
45
+ // Fail-closed: no branch = protected
46
+ if (!branch)
47
+ return false;
48
+ // Detached HEAD = protected (fail-closed)
49
+ if (branch === 'HEAD')
50
+ return false;
51
+ // Load config (uses existing loader with caching)
52
+ const config = getConfig();
53
+ const protectedBranches = getProtectedBranches();
54
+ const patterns = config?.git?.agentBranchPatterns?.length > 0
55
+ ? config.git.agentBranchPatterns
56
+ : DEFAULT_AGENT_BRANCH_PATTERNS;
57
+ // Protected branches are NEVER bypassed (mainBranch + 'master')
58
+ if (protectedBranches.includes(branch))
59
+ return false;
60
+ // LumenFlow lane branches require worktrees (uses config's laneBranchPrefix)
61
+ if (getLaneBranchPattern().test(branch))
62
+ return false;
63
+ // Use micromatch for proper glob matching
64
+ return micromatch.isMatch(branch, patterns);
65
+ }
66
+ /**
67
+ * Check if headless mode is allowed (guarded).
68
+ * Requires LUMENFLOW_HEADLESS=1 AND (LUMENFLOW_ADMIN=1 OR CI truthy OR GITHUB_ACTIONS truthy)
69
+ */
70
+ export function isHeadlessAllowed() {
71
+ if (process.env.LUMENFLOW_HEADLESS !== '1')
72
+ return false;
73
+ return (process.env.LUMENFLOW_ADMIN === '1' ||
74
+ Boolean(process.env.CI) || // Any truthy CI value (true, 1, yes, etc.)
75
+ Boolean(process.env.GITHUB_ACTIONS) // Any truthy value
76
+ );
77
+ }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI helper for bash hooks to check if branch is an agent branch.
4
+ * Uses the same isAgentBranch() logic as TypeScript code.
5
+ *
6
+ * Usage: node dist/cli/is-agent-branch.js [branch-name]
7
+ * Exit codes: 0 = agent branch (allowed), 1 = not agent branch (protected)
8
+ *
9
+ * @module cli/is-agent-branch
10
+ */
11
+ export {};
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI helper for bash hooks to check if branch is an agent branch.
4
+ * Uses the same isAgentBranch() logic as TypeScript code.
5
+ *
6
+ * Usage: node dist/cli/is-agent-branch.js [branch-name]
7
+ * Exit codes: 0 = agent branch (allowed), 1 = not agent branch (protected)
8
+ *
9
+ * @module cli/is-agent-branch
10
+ */
11
+ import { isAgentBranch } from '../branch-check.js';
12
+ const branch = process.argv[2] || null;
13
+ const result = isAgentBranch(branch);
14
+ // Exit 0 = agent branch (truthy), Exit 1 = not agent branch
15
+ process.exit(result ? 0 : 1);
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import { readFileSync, existsSync } from 'fs';
11
11
  import path from 'path';
12
- import yaml from 'js-yaml';
12
+ import { parseYAML } from './wu-yaml.js';
13
13
  import fg from 'fast-glob';
14
14
  import micromatch from 'micromatch';
15
15
  import { STATUS_SECTIONS, BACKLOG_SECTIONS, STRING_LITERALS } from './wu-constants.js';
@@ -166,7 +166,7 @@ export function detectConflicts(statusPath, claimingPaths, claimingWU) {
166
166
  continue; // Skip if YAML doesn't exist
167
167
  }
168
168
  const wuContent = readFileSync(wuPath, { encoding: 'utf-8' });
169
- const wuDoc = yaml.load(wuContent);
169
+ const wuDoc = parseYAML(wuContent);
170
170
  // Extract code_paths (skip if not defined)
171
171
  const existingPaths = wuDoc?.code_paths;
172
172
  if (!existingPaths || existingPaths.length === 0) {
@@ -2,6 +2,7 @@
2
2
  * @file error-handler.mjs
3
3
  * @description Structured error handling with error codes
4
4
  * WU-1082: Extract shared utilities (eliminate die() duplication)
5
+ * WU-1006: Library-First - use path.basename() instead of manual split
5
6
  *
6
7
  * Replaces die() function in:
7
8
  * - tools/wu-claim.mjs
@@ -2,6 +2,7 @@
2
2
  * @file error-handler.mjs
3
3
  * @description Structured error handling with error codes
4
4
  * WU-1082: Extract shared utilities (eliminate die() duplication)
5
+ * WU-1006: Library-First - use path.basename() instead of manual split
5
6
  *
6
7
  * Replaces die() function in:
7
8
  * - tools/wu-claim.mjs
@@ -14,6 +15,7 @@
14
15
  * - tools/validate.mjs
15
16
  * - tools/guard-worktree-commit.mjs
16
17
  */
18
+ import path from 'node:path';
17
19
  /**
18
20
  * Structured error class with error codes and details
19
21
  * @class WUError
@@ -56,8 +58,9 @@ export class WUError extends Error {
56
58
  */
57
59
  export function die(message, exitCode = 1) {
58
60
  // Auto-detect script name from process.argv[1] (eliminates string literal duplication)
61
+ // WU-1006: Use path.basename() instead of manual split (Library-First principle)
59
62
  const scriptPath = process.argv[1] || 'unknown';
60
- const scriptName = scriptPath.split('/').pop().replace('.js', '');
63
+ const scriptName = path.basename(scriptPath, '.js');
61
64
  console.error(`[${scriptName}] ${message}`);
62
65
  process.exit(exitCode);
63
66
  }
@@ -77,6 +77,17 @@ export declare class GitAdapter {
77
77
  * await git.branchExists('nonexistent'); // false
78
78
  */
79
79
  branchExists(branch: string): Promise<boolean>;
80
+ /**
81
+ * Check if a remote branch exists via git ls-remote --heads
82
+ * @param {string} remote - Remote name (e.g., 'origin')
83
+ * @param {string} branch - Branch name
84
+ * @returns {Promise<boolean>} True if remote branch exists
85
+ * @throws {TypeError} If remote or branch is not a string
86
+ * @throws {Error} If remote or branch is empty
87
+ * @example
88
+ * await git.remoteBranchExists('origin', 'lane/operations/wu-123'); // true/false
89
+ */
90
+ remoteBranchExists(remote: string, branch: string): Promise<boolean>;
80
91
  /**
81
92
  * Fetch from remote
82
93
  * @param {string} [remote] - Remote name (defaults to fetching all)
@@ -391,5 +402,10 @@ export declare function createGitForPath(baseDir: string): GitAdapter;
391
402
  * const git = getGitForCwd(); // Uses new directory
392
403
  */
393
404
  export declare function getGitForCwd(): GitAdapter;
405
+ /**
406
+ * Reset singleton warning flag (for testing only)
407
+ * @internal
408
+ */
409
+ export declare function _resetSingletonWarning(): void;
394
410
  export declare const git: GitAdapter;
395
411
  export {};
@@ -137,6 +137,22 @@ export class GitAdapter {
137
137
  return false;
138
138
  }
139
139
  }
140
+ /**
141
+ * Check if a remote branch exists via git ls-remote --heads
142
+ * @param {string} remote - Remote name (e.g., 'origin')
143
+ * @param {string} branch - Branch name
144
+ * @returns {Promise<boolean>} True if remote branch exists
145
+ * @throws {TypeError} If remote or branch is not a string
146
+ * @throws {Error} If remote or branch is empty
147
+ * @example
148
+ * await git.remoteBranchExists('origin', 'lane/operations/wu-123'); // true/false
149
+ */
150
+ async remoteBranchExists(remote, branch) {
151
+ assertNonEmptyString(remote, 'remote');
152
+ assertNonEmptyString(branch, 'branch');
153
+ const result = await this.git.raw(['ls-remote', '--heads', remote, branch]);
154
+ return result.trim().length > 0;
155
+ }
140
156
  /**
141
157
  * Fetch from remote
142
158
  * @param {string} [remote] - Remote name (defaults to fetching all)
@@ -465,7 +481,13 @@ export class GitAdapter {
465
481
  // This handles edge cases where git worktree remove succeeds but leaves the directory
466
482
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool with validated worktree path
467
483
  if (existsSync(worktreePath)) {
468
- rmSync(worktreePath, { recursive: true, force: true });
484
+ try {
485
+ rmSync(worktreePath, { recursive: true, force: true });
486
+ }
487
+ catch (rmErr) {
488
+ // WU-1014: Log but don't throw - git worktree remove succeeded, directory cleanup is best-effort
489
+ console.warn(`[git-adapter] worktreeRemove: git succeeded but directory cleanup failed for ${worktreePath}: ${rmErr instanceof Error ? rmErr.message : String(rmErr)}`);
490
+ }
469
491
  }
470
492
  }
471
493
  /**
package/dist/index.d.ts CHANGED
@@ -40,3 +40,4 @@ export * from './dependency-guard.js';
40
40
  export * from './stamp-utils.js';
41
41
  export * from './lumenflow-config.js';
42
42
  export * from './lumenflow-config-schema.js';
43
+ export * from './branch-check.js';
package/dist/index.js CHANGED
@@ -59,3 +59,5 @@ export * from './stamp-utils.js';
59
59
  // Configuration
60
60
  export * from './lumenflow-config.js';
61
61
  export * from './lumenflow-config-schema.js';
62
+ // Branch check utilities
63
+ export * from './branch-check.js';
@@ -18,6 +18,22 @@ interface CheckLaneFreeResult {
18
18
  free: boolean;
19
19
  occupiedBy: string | null;
20
20
  error: string | null;
21
+ /** WU-1016: List of WU IDs currently in progress in this lane */
22
+ inProgressWUs?: string[];
23
+ /** WU-1016: The configured WIP limit for this lane */
24
+ wipLimit?: number;
25
+ /** WU-1016: Current count of in-progress WUs in this lane */
26
+ currentCount?: number;
27
+ }
28
+ /** WU-1016: Options for checkLaneFree */
29
+ interface CheckLaneFreeOptions {
30
+ /** Path to .lumenflow.config.yaml (for testing) */
31
+ configPath?: string;
32
+ }
33
+ /** WU-1016: Options for getWipLimitForLane */
34
+ interface GetWipLimitOptions {
35
+ /** Path to .lumenflow.config.yaml (for testing) */
36
+ configPath?: string;
21
37
  }
22
38
  export { getSubLanesForParent };
23
39
  /**
@@ -41,10 +57,27 @@ export declare function extractParent(lane: string): string;
41
57
  */
42
58
  export declare function validateLaneFormat(lane: string, configPath?: string | null, options?: ValidateLaneOptions): ValidateLaneResult;
43
59
  /**
44
- * Check if a lane is free (no in_progress WU currently in that lane)
60
+ * WU-1016: Get WIP limit for a lane from config
61
+ *
62
+ * Reads the wip_limit field from .lumenflow.config.yaml for the specified lane.
63
+ * Returns DEFAULT_WIP_LIMIT (1) if the lane is not found or wip_limit is not specified.
64
+ *
65
+ * @param {string} lane - Lane name (e.g., "Core", "CLI")
66
+ * @param {GetWipLimitOptions} options - Options including configPath for testing
67
+ * @returns {number} The WIP limit for the lane (default: 1)
68
+ */
69
+ export declare function getWipLimitForLane(lane: string, options?: GetWipLimitOptions): number;
70
+ /**
71
+ * Check if a lane is free (in_progress WU count is below wip_limit)
72
+ *
73
+ * WU-1016: Now respects configurable wip_limit per lane from .lumenflow.config.yaml.
74
+ * Lane is considered "free" if current in_progress count < wip_limit.
75
+ * Default wip_limit is 1 if not specified in config (backward compatible).
76
+ *
45
77
  * @param {string} statusPath - Path to status.md
46
78
  * @param {string} lane - Lane name (e.g., "Operations", "Intelligence")
47
79
  * @param {string} wuid - WU ID being claimed (e.g., "WU-419")
48
- * @returns {{ free: boolean, occupiedBy: string | null, error: string | null }}
80
+ * @param {CheckLaneFreeOptions} options - Options including configPath for testing
81
+ * @returns {{ free: boolean, occupiedBy: string | null, error: string | null, inProgressWUs?: string[], wipLimit?: number, currentCount?: number }}
49
82
  */
50
- export declare function checkLaneFree(statusPath: string, lane: string, wuid: string): CheckLaneFreeResult;
83
+ export declare function checkLaneFree(statusPath: string, lane: string, wuid: string, options?: CheckLaneFreeOptions): CheckLaneFreeResult;