@lumenflow/core 1.0.0 → 1.3.2

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 (79) hide show
  1. package/dist/arg-parser.d.ts +6 -0
  2. package/dist/arg-parser.js +57 -1
  3. package/dist/backlog-generator.js +1 -1
  4. package/dist/backlog-sync-validator.js +3 -3
  5. package/dist/branch-check.d.ts +21 -0
  6. package/dist/branch-check.js +77 -0
  7. package/dist/cli/is-agent-branch.d.ts +11 -0
  8. package/dist/cli/is-agent-branch.js +15 -0
  9. package/dist/code-paths-overlap.js +2 -2
  10. package/dist/error-handler.d.ts +1 -0
  11. package/dist/error-handler.js +4 -1
  12. package/dist/git-adapter.d.ts +23 -0
  13. package/dist/git-adapter.js +38 -2
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +5 -0
  16. package/dist/lane-checker.d.ts +36 -3
  17. package/dist/lane-checker.js +128 -17
  18. package/dist/lane-inference.js +3 -4
  19. package/dist/lumenflow-config-schema.d.ts +125 -0
  20. package/dist/lumenflow-config-schema.js +76 -0
  21. package/dist/lumenflow-home.d.ts +130 -0
  22. package/dist/lumenflow-home.js +208 -0
  23. package/dist/manual-test-validator.js +1 -1
  24. package/dist/orchestration-rules.d.ts +1 -1
  25. package/dist/orchestration-rules.js +2 -2
  26. package/dist/orphan-detector.d.ts +16 -0
  27. package/dist/orphan-detector.js +24 -0
  28. package/dist/path-classifiers.d.ts +1 -1
  29. package/dist/path-classifiers.js +1 -1
  30. package/dist/rebase-artifact-cleanup.d.ts +17 -0
  31. package/dist/rebase-artifact-cleanup.js +49 -8
  32. package/dist/spawn-strategy.d.ts +53 -0
  33. package/dist/spawn-strategy.js +106 -0
  34. package/dist/spec-branch-helpers.d.ts +118 -0
  35. package/dist/spec-branch-helpers.js +192 -0
  36. package/dist/stamp-utils.d.ts +10 -0
  37. package/dist/stamp-utils.js +17 -19
  38. package/dist/token-counter.js +2 -2
  39. package/dist/wu-consistency-checker.d.ts +2 -0
  40. package/dist/wu-consistency-checker.js +40 -6
  41. package/dist/wu-constants.d.ts +98 -3
  42. package/dist/wu-constants.js +108 -3
  43. package/dist/wu-create-validators.d.ts +40 -2
  44. package/dist/wu-create-validators.js +76 -2
  45. package/dist/wu-done-branch-only.js +9 -0
  46. package/dist/wu-done-branch-utils.d.ts +10 -0
  47. package/dist/wu-done-branch-utils.js +31 -0
  48. package/dist/wu-done-cleanup.d.ts +8 -0
  49. package/dist/wu-done-cleanup.js +122 -0
  50. package/dist/wu-done-docs-generate.d.ts +73 -0
  51. package/dist/wu-done-docs-generate.js +108 -0
  52. package/dist/wu-done-docs-only.d.ts +20 -0
  53. package/dist/wu-done-docs-only.js +65 -0
  54. package/dist/wu-done-errors.d.ts +17 -0
  55. package/dist/wu-done-errors.js +24 -0
  56. package/dist/wu-done-inputs.d.ts +12 -0
  57. package/dist/wu-done-inputs.js +51 -0
  58. package/dist/wu-done-metadata.d.ts +100 -0
  59. package/dist/wu-done-metadata.js +193 -0
  60. package/dist/wu-done-paths.d.ts +69 -0
  61. package/dist/wu-done-paths.js +237 -0
  62. package/dist/wu-done-preflight.d.ts +48 -0
  63. package/dist/wu-done-preflight.js +185 -0
  64. package/dist/wu-done-validation.d.ts +82 -0
  65. package/dist/wu-done-validation.js +340 -0
  66. package/dist/wu-done-validators.d.ts +13 -409
  67. package/dist/wu-done-validators.js +9 -1225
  68. package/dist/wu-done-worktree.d.ts +0 -1
  69. package/dist/wu-done-worktree.js +24 -30
  70. package/dist/wu-schema.js +4 -4
  71. package/dist/wu-spawn-skills.d.ts +19 -0
  72. package/dist/wu-spawn-skills.js +148 -0
  73. package/dist/wu-spawn.d.ts +17 -4
  74. package/dist/wu-spawn.js +113 -177
  75. package/dist/wu-validation.d.ts +1 -0
  76. package/dist/wu-validation.js +21 -1
  77. package/dist/wu-validator.d.ts +51 -0
  78. package/dist/wu-validator.js +108 -0
  79. package/package.json +12 -8
@@ -132,7 +132,6 @@ export declare function checkMergeConflicts(branch: any): Promise<void>;
132
132
  * @throws {Error} When code_paths defined but files not modified in commits
133
133
  */
134
134
  export declare function checkEmptyMerge(branch: any, doc?: any): Promise<void>;
135
- export declare function isBranchAlreadyMerged(branch: any): Promise<boolean>;
136
135
  /**
137
136
  * Merge lane branch to main with exponential backoff retry (WU-1747)
138
137
  *
@@ -28,12 +28,16 @@ import { BRANCHES, REMOTES, THRESHOLDS, LOG_PREFIX, EMOJI, COMMIT_FORMATS, BOX,
28
28
  import { RECOVERY, REBASE, PREFLIGHT, MERGE } from './wu-done-messages.js';
29
29
  import { getDriftLevel, DRIFT_LEVELS } from './branch-drift.js';
30
30
  import { createError, ErrorCodes } from './error-handler.js';
31
+ import { createRecoveryError, createValidationError } from './wu-done-errors.js';
31
32
  import { validateDoneWU, validateAndNormalizeWUYAML } from './wu-schema.js';
32
33
  import { assertTransition } from './state-machine.js';
33
34
  import { detectZombieState, resetWorktreeYAMLForRecovery, getRecoveryAttemptCount, incrementRecoveryAttempt, clearRecoveryAttempts, shouldEscalateToManualIntervention, MAX_RECOVERY_ATTEMPTS, } from './wu-recovery.js';
34
35
  import { isPRModeEnabled, createPR, printPRCreatedMessage } from './wu-done-pr.js';
36
+ import { isBranchAlreadyMerged } from './wu-done-branch-utils.js';
35
37
  // WU-1371: Import rebase artifact cleanup functions
36
38
  import { detectRebasedArtifacts, cleanupRebasedArtifacts } from './rebase-artifact-cleanup.js';
39
+ // WU-1061: Import docs regeneration utilities
40
+ import { maybeRegenerateAndStageDocs } from './wu-done-docs-generate.js';
37
41
  import { WUTransaction, createTransactionSnapshot, restoreFromSnapshot } from './wu-transaction.js';
38
42
  // WU-1506: Import backlog invariant repair
39
43
  // WU-1574: Removed repairBacklogInvariants - no longer needed with state store architecture
@@ -113,7 +117,7 @@ export async function executeWorktreeCompletion(context) {
113
117
  console.log(`${BOX.SIDE} Or reset the recovery counter:`);
114
118
  console.log(`${BOX.SIDE} rm .beacon/recovery/${id}.recovery`);
115
119
  console.log(BOX.BOT);
116
- throw createError(ErrorCodes.RECOVERY_ERROR, `Recovery loop detected for ${id} after ${attemptCount} attempts. Manual intervention required.`, { wuId: id, attemptCount, maxAttempts: MAX_RECOVERY_ATTEMPTS });
120
+ throw createRecoveryError(`Recovery loop detected for ${id} after ${attemptCount} attempts. Manual intervention required.`, { wuId: id, attemptCount, maxAttempts: MAX_RECOVERY_ATTEMPTS });
117
121
  }
118
122
  // Increment attempt counter before trying recovery
119
123
  const newAttemptCount = incrementRecoveryAttempt(id);
@@ -184,7 +188,7 @@ export async function executeWorktreeCompletion(context) {
184
188
  // This catches schema issues early and auto-fixes normalizable problems
185
189
  const normalizeResult = validateAndNormalizeWUYAML(docForUpdate);
186
190
  if (!normalizeResult.valid) {
187
- throw createError(ErrorCodes.VALIDATION_ERROR, `WU YAML validation failed:\n - ${normalizeResult.errors.join('\n - ')}\n\nNext step: Fix the validation errors in ${workingWUPath} and rerun wu:done`, { wuId: id });
191
+ throw createValidationError(`WU YAML validation failed:\n - ${normalizeResult.errors.join('\n - ')}\n\nNext step: Fix the validation errors in ${workingWUPath} and rerun wu:done`, { wuId: id });
188
192
  }
189
193
  // WU-1811: If normalizations were applied, write back to YAML file
190
194
  if (normalizeResult.wasNormalized) {
@@ -197,7 +201,7 @@ export async function executeWorktreeCompletion(context) {
197
201
  // Validate done-specific completeness (uses normalized data)
198
202
  const completenessResult = validateDoneWU(normalizeResult.normalized);
199
203
  if (!completenessResult.valid) {
200
- throw createError(ErrorCodes.VALIDATION_ERROR, `Cannot mark WU as done - spec incomplete:\n ${completenessResult.errors.join('\n ')}\n\nNext step: Update ${workingWUPath} to meet completion requirements and rerun wu:done`, { wuId: id });
204
+ throw createValidationError(`Cannot mark WU as done - spec incomplete:\n ${completenessResult.errors.join('\n ')}\n\nNext step: Update ${workingWUPath} to meet completion requirements and rerun wu:done`, { wuId: id });
201
205
  }
202
206
  console.log(`${LOG_PREFIX.DONE} ${EMOJI.SUCCESS} All validations passed`);
203
207
  // ======================================================================
@@ -252,13 +256,23 @@ export async function executeWorktreeCompletion(context) {
252
256
  stampPath: workingStampPath,
253
257
  });
254
258
  if (!postMutationResult.valid) {
255
- throw createError(ErrorCodes.VALIDATION_ERROR, `Post-mutation validation failed:\n ${postMutationResult.errors.join('\n ')}`, { wuId: id, errors: postMutationResult.errors });
259
+ throw createValidationError(`Post-mutation validation failed:\n ${postMutationResult.errors.join('\n ')}`, { wuId: id, errors: postMutationResult.errors });
256
260
  }
257
261
  console.log(`${LOG_PREFIX.DONE} ${EMOJI.SUCCESS} Post-mutation validation passed (WU-1617)`);
258
262
  // ======================================================================
259
263
  // PHASE 4: GIT OPERATIONS (stage, format, commit)
260
264
  // Files are now written - proceed with git operations
261
265
  // ======================================================================
266
+ // ======================================================================
267
+ // WU-1061: Regenerate docs if doc-source files changed
268
+ // This runs BEFORE stageAndFormatMetadata to include doc outputs
269
+ // in the single atomic commit
270
+ // Uses main as base to detect changes introduced by this WU
271
+ // ======================================================================
272
+ await maybeRegenerateAndStageDocs({
273
+ baseBranch: BRANCHES.MAIN,
274
+ repoRoot: worktreePath,
275
+ });
262
276
  // Stage and format files
263
277
  await stageAndFormatMetadata({
264
278
  id,
@@ -930,7 +944,12 @@ export async function checkEmptyMerge(branch, doc = null) {
930
944
  const missingCodePaths = codePaths.filter((codePath) => !modifiedFiles.some((modified) => modified.includes(codePath) || codePath.includes(modified)));
931
945
  if (missingCodePaths.length > 0) {
932
946
  // BLOCK: code_paths defined but files not modified
933
- throw createError(ErrorCodes.VALIDATION_ERROR, PREFLIGHT.CODE_PATHS_NOT_MODIFIED(missingCodePaths), { branch, codePaths, missingCodePaths, modifiedFiles });
947
+ throw createValidationError(PREFLIGHT.CODE_PATHS_NOT_MODIFIED(missingCodePaths), {
948
+ branch,
949
+ codePaths,
950
+ missingCodePaths,
951
+ modifiedFiles,
952
+ });
934
953
  }
935
954
  // All code_paths files were modified
936
955
  console.log(PREFLIGHT.CODE_PATHS_VERIFIED);
@@ -951,31 +970,6 @@ export async function checkEmptyMerge(branch, doc = null) {
951
970
  console.warn(`${LOG_PREFIX.DONE} Warning: Could not check for empty merge: ${e.message}`);
952
971
  }
953
972
  }
954
- /**
955
- * Check if branch is already merged to main
956
- *
957
- * @param {string} branch - Lane branch name
958
- * @returns {Promise<boolean>} Whether branch is already merged
959
- */
960
- /** @constant {number} SHA_SHORT_LENGTH - Length of shortened git SHA hashes for display */
961
- const SHA_SHORT_LENGTH = 8;
962
- export async function isBranchAlreadyMerged(branch) {
963
- const gitAdapter = getGitForCwd();
964
- try {
965
- const branchTip = (await gitAdapter.getCommitHash(branch)).trim();
966
- const mergeBase = (await gitAdapter.mergeBase(BRANCHES.MAIN, branch)).trim();
967
- const mainHead = (await gitAdapter.getCommitHash(BRANCHES.MAIN)).trim();
968
- if (branchTip === mergeBase) {
969
- console.log(PREFLIGHT.BRANCH_INFO(branch, branchTip.substring(0, SHA_SHORT_LENGTH), mergeBase.substring(0, SHA_SHORT_LENGTH), mainHead.substring(0, SHA_SHORT_LENGTH)));
970
- return true;
971
- }
972
- return false;
973
- }
974
- catch (e) {
975
- console.warn(`${LOG_PREFIX.DONE} Warning: Could not check if branch is merged: ${e.message}`);
976
- return false;
977
- }
978
- }
979
973
  async function isMainAncestorOfBranch(gitAdapter, branch) {
980
974
  try {
981
975
  await gitAdapter.raw([GIT_COMMANDS.MERGE_BASE, GIT_FLAGS.IS_ANCESTOR, BRANCHES.MAIN, branch]);
package/dist/wu-schema.js CHANGED
@@ -109,9 +109,7 @@ const normalizedMultilineString = z.string().transform((s) => s.replace(/\\n/g,
109
109
  *
110
110
  * WU-1750: After normalization, paths should be clean. This catches any edge cases.
111
111
  */
112
- const filePathItem = z
113
- .string()
114
- .refine((s) => !s.includes('\n') && !s.includes('\\n'), {
112
+ const filePathItem = z.string().refine((s) => !s.includes('\n') && !s.includes('\\n'), {
115
113
  message: 'File path cannot contain newlines - split into separate array items',
116
114
  });
117
115
  /**
@@ -828,10 +826,12 @@ export function validateWUCompleteness(wu) {
828
826
  warnings.push(`${wu.id}: Missing 'tests.manual' field. Add manual verification steps for acceptance criteria.`);
829
827
  }
830
828
  // Check for spec_refs (features should link to plans/specs)
829
+ // WU-1062: Accepts both repo-relative paths (docs/04-operations/plans/) and
830
+ // external paths (~/.lumenflow/plans/, $LUMENFLOW_HOME/plans/, lumenflow://plans/)
831
831
  if (type === 'feature') {
832
832
  const hasSpecRefs = wu.spec_refs && wu.spec_refs.length > 0;
833
833
  if (!hasSpecRefs) {
834
- warnings.push(`${wu.id}: Missing 'spec_refs' field. Link to plan file in docs/04-operations/plans/ for traceability.`);
834
+ warnings.push(`${wu.id}: Missing 'spec_refs' field. Link to plan file (docs/04-operations/plans/, lumenflow://plans/, or ~/.lumenflow/plans/) for traceability.`);
835
835
  }
836
836
  }
837
837
  return { warnings };
@@ -0,0 +1,19 @@
1
+ import type { ClientConfig } from './lumenflow-config-schema.js';
2
+ interface ClientContext {
3
+ name: string;
4
+ config?: ClientConfig;
5
+ }
6
+ export declare function resolveClientConfig(config: any, clientName: any): any;
7
+ export declare function resolveSkillsPaths(config: any, clientName: any): {
8
+ clientConfig: any;
9
+ configuredSkillsDir: any;
10
+ configuredAgentsDir: any;
11
+ skillsDir: any;
12
+ agentsDir: any;
13
+ configuredSkillsMissing: boolean;
14
+ configuredAgentsMissing: boolean;
15
+ };
16
+ export declare function generateSkillsCatalogGuidance(config: any, clientName: any): string;
17
+ export declare function generateClientSkillsGuidance(clientContext: ClientContext): string;
18
+ export declare function generateSkillsSelectionSection(doc: any, config: any, clientName: any): string;
19
+ export {};
@@ -0,0 +1,148 @@
1
+ import { existsSync } from 'node:fs';
2
+ const KNOWN_SKILLS_DIRS = [
3
+ '.lumenflow/skills',
4
+ '.claude/skills',
5
+ '.codex/skills',
6
+ '.gemini/skills',
7
+ ];
8
+ const KNOWN_AGENTS_DIRS = [
9
+ '.lumenflow/agents',
10
+ '.claude/agents',
11
+ '.codex/agents',
12
+ '.gemini/agents',
13
+ ];
14
+ const SECTION = {
15
+ skillsSelection: '## Skills Selection',
16
+ skillsCatalog: '### Skills Catalog',
17
+ softPolicy: '### Soft Policy (baselines for this WU)',
18
+ additionalSkills: '### Additional Skills (load if needed)',
19
+ gracefulDegradation: '### Graceful Degradation',
20
+ clientSkills: '### Client Skills Guidance',
21
+ };
22
+ const MESSAGES = {
23
+ skillsIntro: '**IMPORTANT**: Before starting work, select and load relevant skills.',
24
+ catalogMissing: 'No skills directories configured or found. Set `directories.skillsDir` or `agents.clients.<client>.skillsDir` in .lumenflow.config.yaml.',
25
+ baselineFallback: '- Load baseline skills: `/skill wu-lifecycle`, `/skill tdd-workflow` (for features)\n- Continue with implementation using Mandatory Standards below',
26
+ };
27
+ const CONTEXT_HINTS = {
28
+ wuLifecycle: '- `wu-lifecycle` — ALL WUs need workflow automation',
29
+ worktreeDiscipline: '- `worktree-discipline` — ALL WUs need path safety',
30
+ tddWorkflow: '- `tdd-workflow` — TDD is mandatory for feature/enhancement WUs',
31
+ bugClassification: '- `bug-classification` — Bug severity assessment',
32
+ lumenflowGates: '- `lumenflow-gates` — Tooling often affects gates',
33
+ beaconCompliance: '- `beacon-compliance` — Intelligence lane requires Beacon validation',
34
+ promptManagement: '- `prompt-management` — For prompt template work',
35
+ frontendDesign: '- `frontend-design` — For UI component work',
36
+ };
37
+ const ADDITIONAL_SKILLS_TABLE = `| Skill | Use When |
38
+ |-------|----------|
39
+ | lumenflow-gates | Gates fail, debugging format/lint/typecheck errors |
40
+ | bug-classification | Bug discovered mid-WU, need priority classification |
41
+ | beacon-compliance | Code touches LLM, prompts, classification |
42
+ | prompt-management | Working with prompt templates, golden datasets |
43
+ | frontend-design | Building UI components, pages |
44
+ | initiative-management | Multi-phase projects, INIT-XXX coordination |
45
+ | multi-agent-coordination | Spawning sub-agents, parallel WU work |
46
+ | orchestration | Agent coordination, mandatory agent checks |
47
+ | ops-maintenance | Metrics, validation, health checks |`;
48
+ export function resolveClientConfig(config, clientName) {
49
+ const clients = config?.agents?.clients || {};
50
+ if (!clientName)
51
+ return undefined;
52
+ if (clients[clientName])
53
+ return clients[clientName];
54
+ const matchKey = Object.keys(clients).find((key) => key.toLowerCase() === clientName.toLowerCase());
55
+ return matchKey ? clients[matchKey] : undefined;
56
+ }
57
+ function uniqueNonEmpty(values) {
58
+ const seen = new Set();
59
+ const result = [];
60
+ for (const value of values) {
61
+ if (!value)
62
+ continue;
63
+ if (seen.has(value))
64
+ continue;
65
+ seen.add(value);
66
+ result.push(value);
67
+ }
68
+ return result;
69
+ }
70
+ export function resolveSkillsPaths(config, clientName) {
71
+ const clientConfig = resolveClientConfig(config, clientName);
72
+ const configuredSkillsDir = clientConfig?.skillsDir || config?.directories?.skillsDir;
73
+ const configuredAgentsDir = config?.directories?.agentsDir;
74
+ const skillsCandidates = uniqueNonEmpty([configuredSkillsDir, ...KNOWN_SKILLS_DIRS]);
75
+ const agentsCandidates = uniqueNonEmpty([configuredAgentsDir, ...KNOWN_AGENTS_DIRS]);
76
+ const skillsDir = skillsCandidates.find((candidate) => existsSync(candidate));
77
+ const agentsDir = agentsCandidates.find((candidate) => existsSync(candidate));
78
+ const configuredSkillsMissing = Boolean(configuredSkillsDir && !existsSync(configuredSkillsDir));
79
+ const configuredAgentsMissing = Boolean(configuredAgentsDir && !existsSync(configuredAgentsDir));
80
+ return {
81
+ clientConfig,
82
+ configuredSkillsDir,
83
+ configuredAgentsDir,
84
+ skillsDir,
85
+ agentsDir,
86
+ configuredSkillsMissing,
87
+ configuredAgentsMissing,
88
+ };
89
+ }
90
+ export function generateSkillsCatalogGuidance(config, clientName) {
91
+ const resolution = resolveSkillsPaths(config, clientName);
92
+ const lines = [];
93
+ if (resolution.skillsDir) {
94
+ lines.push(`- Check \`${resolution.skillsDir}\` for available skills.`);
95
+ }
96
+ if (resolution.agentsDir) {
97
+ lines.push(`- Check \`${resolution.agentsDir}\` for agent configs (optional).`);
98
+ }
99
+ if (lines.length > 0) {
100
+ return `${SECTION.skillsCatalog}\n\n${lines.join('\n')}\n`;
101
+ }
102
+ const configuredHint = resolution.configuredSkillsDir
103
+ ? `Configured skillsDir \`${resolution.configuredSkillsDir}\` was not found. `
104
+ : '';
105
+ const clientHint = clientName
106
+ ? `agents.clients.${clientName}.skillsDir`
107
+ : 'agents.clients.<client>.skillsDir';
108
+ return `${SECTION.skillsCatalog}\n\n${configuredHint}No skills directories configured or found. Set \`directories.skillsDir\` or \`${clientHint}\` in .lumenflow.config.yaml.\n`;
109
+ }
110
+ export function generateClientSkillsGuidance(clientContext) {
111
+ const skills = clientContext?.config?.skills;
112
+ if (!skills ||
113
+ (!skills.instructions && (!skills.recommended || skills.recommended.length === 0))) {
114
+ return '';
115
+ }
116
+ const instructions = skills.instructions ? `${skills.instructions.trim()}\n\n` : '';
117
+ const recommended = skills.recommended && skills.recommended.length > 0
118
+ ? `Recommended skills:\n${skills.recommended.map((s) => `- \`${s}\``).join('\n')}\n`
119
+ : '';
120
+ return `${SECTION.clientSkills} (${clientContext.name})\n\n${instructions}${recommended}`;
121
+ }
122
+ export function generateSkillsSelectionSection(doc, config, clientName) {
123
+ const lane = doc.lane || '';
124
+ const type = doc.type || 'feature';
125
+ const laneParent = lane.split(':')[0].trim();
126
+ const contextHints = [];
127
+ contextHints.push(CONTEXT_HINTS.wuLifecycle);
128
+ contextHints.push(CONTEXT_HINTS.worktreeDiscipline);
129
+ if (type === 'feature' || type === 'enhancement') {
130
+ contextHints.push(CONTEXT_HINTS.tddWorkflow);
131
+ }
132
+ if (type === 'bug') {
133
+ contextHints.push(CONTEXT_HINTS.bugClassification);
134
+ }
135
+ if (laneParent === 'Operations' && lane.includes('Tooling')) {
136
+ contextHints.push(CONTEXT_HINTS.lumenflowGates);
137
+ }
138
+ if (laneParent === 'Intelligence') {
139
+ contextHints.push(CONTEXT_HINTS.beaconCompliance);
140
+ contextHints.push(CONTEXT_HINTS.promptManagement);
141
+ }
142
+ if (laneParent === 'Experience') {
143
+ contextHints.push(CONTEXT_HINTS.frontendDesign);
144
+ }
145
+ const softPolicySection = `${SECTION.softPolicy}\n\nBased on WU context, consider loading:\n\n${contextHints.join('\n')}\n\n`;
146
+ const catalogGuidance = generateSkillsCatalogGuidance(config, clientName);
147
+ return `${SECTION.skillsSelection}\n\n${MESSAGES.skillsIntro}\n\n${catalogGuidance}${softPolicySection}${SECTION.additionalSkills}\n\n${ADDITIONAL_SKILLS_TABLE}\n\n${SECTION.gracefulDegradation}\n\nIf the skill catalogue is missing or invalid:\n${MESSAGES.baselineFallback}\n`;
148
+ }
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Output:
13
13
  * A complete Task tool invocation block with:
14
- * - Context loading preamble (CLAUDE-core.md, README, lumenflow, WU YAML)
14
+ * - Context loading preamble (.claude/CLAUDE.md, README, lumenflow, WU YAML)
15
15
  * - WU details and acceptance criteria
16
16
  * - Skills Selection section (sub-agent reads catalogue and selects at runtime)
17
17
  * - Mandatory agent advisory
@@ -25,8 +25,9 @@
25
25
  * Codex Mode:
26
26
  * When --codex is used, outputs a Codex/GPT-friendly Markdown prompt (no antml/XML escaping).
27
27
  *
28
- * @see {@link ai/onboarding/agent-invocation-guide.md} - Context loading templates
28
+ * @see {@link docs/04-operations/_frameworks/lumenflow/agent/onboarding/agent-invocation-guide.md} - Context loading templates
29
29
  */
30
+ import type { ClientConfig, LumenFlowConfig } from './lumenflow-config-schema.js';
30
31
  /**
31
32
  * Generate effort scaling rules section (WU-1986)
32
33
  *
@@ -119,19 +120,31 @@ export declare function generateWorktreePathGuidance(worktreePath: any): string;
119
120
  * @returns {string} Action section content
120
121
  */
121
122
  export declare function generateActionSection(doc: any, id: any): string;
123
+ interface ClientContext {
124
+ name: string;
125
+ config?: ClientConfig;
126
+ }
127
+ interface SpawnOptions {
128
+ thinking?: boolean;
129
+ noThinking?: boolean;
130
+ budget?: string;
131
+ client?: ClientContext;
132
+ config?: LumenFlowConfig;
133
+ }
122
134
  /**
123
135
  * Generate the complete Task tool invocation
124
136
  *
125
137
  * @param {object} doc - WU YAML document
126
138
  * @param {string} id - WU ID
139
+ * @param {SpawnStrategy} strategy - Client strategy
127
140
  * @param {object} [options={}] - Thinking mode options
128
141
  * @param {boolean} [options.thinking] - Whether extended thinking is enabled
129
142
  * @param {boolean} [options.noThinking] - Whether thinking is explicitly disabled
130
143
  * @param {string} [options.budget] - Token budget for thinking
131
144
  * @returns {string} Complete Task tool invocation
132
145
  */
133
- export declare function generateTaskInvocation(doc: any, id: any, options?: {}): string;
134
- export declare function generateCodexPrompt(doc: any, id: any, options?: {}): string;
146
+ export declare function generateTaskInvocation(doc: any, id: any, strategy: any, options?: SpawnOptions): string;
147
+ export declare function generateCodexPrompt(doc: any, id: any, strategy: any, options?: SpawnOptions): string;
135
148
  /**
136
149
  * WU-1603: Check if a lane is currently occupied by another WU
137
150
  *