@lumenflow/core 2.3.2 → 2.5.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.
@@ -105,11 +105,13 @@ function validateSchema(doc, id) {
105
105
  /**
106
106
  * Validate code_paths files exist
107
107
  *
108
+ * WU-1329: Exported for use by wu:create strict validation.
109
+ *
108
110
  * @param {string[]} codePaths - List of code paths from WU YAML
109
111
  * @param {string} rootDir - Root directory to resolve paths against
110
112
  * @returns {{ valid: boolean, errors: string[], missing: string[] }}
111
113
  */
112
- function validateCodePathsExistence(codePaths, rootDir) {
114
+ export function validateCodePathsExistence(codePaths, rootDir) {
113
115
  if (!codePaths || !Array.isArray(codePaths) || codePaths.length === 0) {
114
116
  return { valid: true, errors: [], missing: [] };
115
117
  }
@@ -136,11 +138,13 @@ function validateCodePathsExistence(codePaths, rootDir) {
136
138
  *
137
139
  * Manual tests are descriptions, not file paths, so they're skipped.
138
140
  *
141
+ * WU-1329: Exported for use by wu:create strict validation.
142
+ *
139
143
  * @param {object} tests - tests object from WU YAML
140
144
  * @param {string} rootDir - Root directory to resolve paths against
141
145
  * @returns {{ valid: boolean, errors: string[], missing: string[] }}
142
146
  */
143
- function validateTestPathsExistence(tests, rootDir) {
147
+ export function validateTestPathsExistence(tests, rootDir) {
144
148
  if (!tests || typeof tests !== 'object') {
145
149
  return { valid: true, errors: [], missing: [] };
146
150
  }
@@ -71,6 +71,18 @@ export declare function computeWUEventsContentAfterComplete(backlogPath: any, wu
71
71
  * @returns {Promise<string>} New backlog.md content
72
72
  */
73
73
  export declare function computeBacklogContent(backlogPath: any, id: any, _title: any): Promise<string>;
74
+ /**
75
+ * Compute updated status.md content from merged state store
76
+ *
77
+ * WU-1319: Generates status.md from merged state (origin/main + worktree events)
78
+ * instead of editing the local file snapshot. This prevents reintroducing
79
+ * stale "In Progress" entries when concurrent WUs complete on main.
80
+ *
81
+ * @param {string} backlogPath - Path to backlog.md (used to find state dir)
82
+ * @param {string} id - WU ID to mark complete
83
+ * @returns {Promise<string>} New status.md content
84
+ */
85
+ export declare function computeStatusContentFromMergedState(backlogPath: any, id: any): Promise<string>;
74
86
  /**
75
87
  * Compute stamp file content
76
88
  *
@@ -82,6 +94,7 @@ export declare function computeStampContent(id: any, title: any): string;
82
94
  /**
83
95
  * Collect all metadata updates for a transaction
84
96
  * WU-1574: Made async for computeBacklogContent
97
+ * WU-1319: Made status.md generation use merged state
85
98
  *
86
99
  * Convenience function that computes all file contents at once.
87
100
  * Returns an object with all computed content.
@@ -30,12 +30,8 @@ import { getSectionHeadingsWithDefaults } from './section-headings.js';
30
30
  import { todayISO } from './date-utils.js';
31
31
  import { createError, ErrorCodes } from './error-handler.js';
32
32
  import { STRING_LITERALS } from './wu-constants.js';
33
- // WU-1574: BacklogManager removed - using state store + generator
34
- import { WUStateStore } from './wu-state-store.js';
35
- // WU-1734: Import proper path resolution utility
36
- import { getStateStoreDirFromBacklog } from './wu-paths.js';
37
- // WU-1145: Import concurrent merge utilities
38
- import { computeBacklogContentWithMainMerge, computeWUEventsContentWithMainMerge, } from './wu-done-concurrent-merge.js';
33
+ // WU-1145, WU-1319: Import concurrent merge utilities
34
+ import { computeBacklogContentWithMainMerge, computeStatusContentWithMainMerge, computeWUEventsContentWithMainMerge, } from './wu-done-concurrent-merge.js';
39
35
  /**
40
36
  * Compute WU YAML content for done state
41
37
  *
@@ -167,31 +163,6 @@ export function computeStatusContent(statusPath, id, title) {
167
163
  const frontmatterText = frontmatterMatch ? frontmatterMatch[0] : '';
168
164
  return frontmatterText + lines.join(STRING_LITERALS.NEWLINE);
169
165
  }
170
- function ensureTrailingNewline(content) {
171
- if (content === '')
172
- return content;
173
- if (content.endsWith(STRING_LITERALS.NEWLINE))
174
- return content;
175
- return content + STRING_LITERALS.NEWLINE;
176
- }
177
- async function computeCompletionUpdatesFromStateStore(backlogPath, wuId) {
178
- const stateDir = getStateStoreDirFromBacklog(backlogPath);
179
- const store = new WUStateStore(stateDir);
180
- await store.load();
181
- const current = store.getWUState(wuId);
182
- if (!current) {
183
- throw new Error(`WU ${wuId} is not in_progress`);
184
- }
185
- if (current.status === 'done') {
186
- return { store, stateDir, shouldAppendCompleteEvent: false, completeEvent: null };
187
- }
188
- if (current.status !== 'in_progress') {
189
- throw new Error(`WU ${wuId} is not in_progress`);
190
- }
191
- const completeEvent = store.createCompleteEvent(wuId);
192
- store.applyEvent(completeEvent);
193
- return { store, stateDir, shouldAppendCompleteEvent: true, completeEvent };
194
- }
195
166
  /**
196
167
  * Compute wu-events.jsonl content after completing a WU.
197
168
  *
@@ -221,6 +192,21 @@ export async function computeBacklogContent(backlogPath, id, _title) {
221
192
  // WU-1145: Use merged state to preserve concurrent changes
222
193
  return computeBacklogContentWithMainMerge(backlogPath, id);
223
194
  }
195
+ /**
196
+ * Compute updated status.md content from merged state store
197
+ *
198
+ * WU-1319: Generates status.md from merged state (origin/main + worktree events)
199
+ * instead of editing the local file snapshot. This prevents reintroducing
200
+ * stale "In Progress" entries when concurrent WUs complete on main.
201
+ *
202
+ * @param {string} backlogPath - Path to backlog.md (used to find state dir)
203
+ * @param {string} id - WU ID to mark complete
204
+ * @returns {Promise<string>} New status.md content
205
+ */
206
+ export async function computeStatusContentFromMergedState(backlogPath, id) {
207
+ // WU-1319: Use merged state to preserve concurrent changes
208
+ return computeStatusContentWithMainMerge(backlogPath, id);
209
+ }
224
210
  /**
225
211
  * Compute stamp file content
226
212
  *
@@ -235,6 +221,7 @@ export function computeStampContent(id, title) {
235
221
  /**
236
222
  * Collect all metadata updates for a transaction
237
223
  * WU-1574: Made async for computeBacklogContent
224
+ * WU-1319: Made status.md generation use merged state
238
225
  *
239
226
  * Convenience function that computes all file contents at once.
240
227
  * Returns an object with all computed content.
@@ -258,7 +245,8 @@ export async function collectMetadataUpdates({ doc, id, title, wuPath, statusPat
258
245
  },
259
246
  status: {
260
247
  path: statusPath,
261
- content: computeStatusContent(statusPath, id, title),
248
+ // WU-1319: Use merged state to preserve concurrent changes
249
+ content: await computeStatusContentFromMergedState(backlogPath, id),
262
250
  description: 'status.md',
263
251
  },
264
252
  backlog: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/core",
3
- "version": "2.3.2",
3
+ "version": "2.5.0",
4
4
  "description": "Core WU lifecycle tools for LumenFlow workflow framework",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -72,6 +72,7 @@
72
72
  "dependencies": {
73
73
  "chalk": "^5.6.2",
74
74
  "change-case": "^5.4.4",
75
+ "p-retry": "^6.2.1",
75
76
  "cli-progress": "^3.12.0",
76
77
  "cli-table3": "^0.6.5",
77
78
  "commander": "^14.0.2",
@@ -98,7 +99,7 @@
98
99
  "vitest": "^4.0.17"
99
100
  },
100
101
  "peerDependencies": {
101
- "@lumenflow/memory": "2.3.2"
102
+ "@lumenflow/memory": "2.5.0"
102
103
  },
103
104
  "peerDependenciesMeta": {
104
105
  "@lumenflow/memory": {