@nusoft/nuos-build-catalogue 0.33.0 → 0.33.1
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.
- package/dist/commands/end-of-session.js +46 -20
- package/package.json +1 -1
|
@@ -299,22 +299,43 @@ async function checkWorkUnitsIndex(buildRoot) {
|
|
|
299
299
|
const content = await fileContent(indexPath);
|
|
300
300
|
if (!content)
|
|
301
301
|
return true; // If no index, no rows to check.
|
|
302
|
+
// Design A (WU 112 fix-pass): operate on table rows only; check status cell only.
|
|
303
|
+
// Row shape after split on '|': ['', id, title, status, dependsOn, ...]
|
|
304
|
+
// (leading empty string from the leading pipe character)
|
|
302
305
|
const lines = content.split('\n');
|
|
303
306
|
for (const line of lines) {
|
|
304
|
-
//
|
|
305
|
-
if (
|
|
307
|
+
// Only consider actual table rows (lines starting with '|' after optional whitespace).
|
|
308
|
+
if (!/^\s*\|/.test(line))
|
|
306
309
|
continue;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (
|
|
310
|
+
const cells = line.split('|');
|
|
311
|
+
// Need at least 5 cells: [empty, id, title, status, dependsOn, ...] (leading/trailing empty from outer pipes)
|
|
312
|
+
if (cells.length < 5)
|
|
310
313
|
continue;
|
|
314
|
+
// Status is the 3rd content cell (index 3 in the split array, after the leading empty).
|
|
315
|
+
const statusCell = cells[3];
|
|
316
|
+
if (!statusCell)
|
|
317
|
+
continue;
|
|
318
|
+
// A row is completed only if its STATUS cell contains ✅.
|
|
319
|
+
// This avoids false-positives from Depends-on column mentions, legend lines, and phase headers.
|
|
320
|
+
if (!statusCell.includes('✅'))
|
|
321
|
+
continue;
|
|
322
|
+
// Completed row: extract the first markdown link from the TITLE cell (index 2).
|
|
323
|
+
const titleCell = cells[2];
|
|
324
|
+
if (!titleCell)
|
|
325
|
+
continue;
|
|
326
|
+
const linkMatch = titleCell.match(/\[.*?\]\((.*?)\)/);
|
|
327
|
+
if (!linkMatch) {
|
|
328
|
+
// No link in the title cell — legacy/sibling WU (lives in a sibling repo, never had a done/ file here).
|
|
329
|
+
// Skip: not verifiable by this gate (presence-only, D130).
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
311
332
|
const linkTarget = linkMatch[1];
|
|
312
|
-
//
|
|
333
|
+
// A completed row linking to a top-level NNN-...md (not done/) is drift: the WU was never moved.
|
|
313
334
|
if (!linkTarget.includes('done/')) {
|
|
314
335
|
return false;
|
|
315
336
|
}
|
|
316
|
-
//
|
|
317
|
-
const filePath = path.join(buildRoot, 'work-units', linkTarget
|
|
337
|
+
// A completed row whose done/ file is missing is also drift.
|
|
338
|
+
const filePath = path.join(buildRoot, 'work-units', linkTarget);
|
|
318
339
|
const mtime = await fileMtime(filePath);
|
|
319
340
|
if (!mtime) {
|
|
320
341
|
return false;
|
|
@@ -330,21 +351,26 @@ async function checkStateMd(buildRoot, sessionStartMs, sessionDate) {
|
|
|
330
351
|
let stateMdLastUpdated = '';
|
|
331
352
|
let stateMdLastSessionResolves = false;
|
|
332
353
|
if (content) {
|
|
333
|
-
//
|
|
334
|
-
|
|
335
|
-
|
|
354
|
+
// Fix 1 (WU 112 fix-pass): accept all three "Last updated" shapes:
|
|
355
|
+
// table-row: | Last updated | 2026-05-31 (**Session 115 — ...**) ... |
|
|
356
|
+
// bold-colon: **Last updated:** 2026-05-31
|
|
357
|
+
// plain-colon: Last updated: 2026-05-31
|
|
358
|
+
// Anchor on the label text (colon optional), grab the FIRST YYYY-MM-DD on the same logical line.
|
|
359
|
+
// The [^\n]*? keeps the match within the label's own row.
|
|
360
|
+
const updatedMatch = content.match(/Last updated[^\n]*?(\d{4}-\d{2}-\d{2})/i);
|
|
336
361
|
if (updatedMatch) {
|
|
337
362
|
stateMdLastUpdated = updatedMatch[1];
|
|
338
363
|
}
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
364
|
+
// Fix 2 (WU 112 fix-pass): the real "Last session" row is narrative prose with NO markdown link.
|
|
365
|
+
// Real format: | Last session | Session 112 — ...prose... |
|
|
366
|
+
// Assert only that a non-empty "Last session" row/line is present (D130: do not overclaim).
|
|
367
|
+
// Link-resolution is dropped because the real format carries no link to resolve.
|
|
368
|
+
// Session-log existence on disk is independently verified by Step 7 (checkSessionLog).
|
|
369
|
+
const sessionLineMatch = content.match(/Last session[^\n]*/i);
|
|
370
|
+
if (sessionLineMatch) {
|
|
371
|
+
// The row is non-empty if it contains more than just the label itself.
|
|
372
|
+
const rowText = sessionLineMatch[0].replace(/Last session/i, '').replace(/[|:\s]/g, '');
|
|
373
|
+
stateMdLastSessionResolves = rowText.length > 0;
|
|
348
374
|
}
|
|
349
375
|
}
|
|
350
376
|
return { stateMdTouched, stateMdLastUpdated, stateMdLastSessionResolves };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nusoft/nuos-build-catalogue",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "NuOS build-catalogue tooling: semantic search (WU 110) + migration runner that lifts markdown artefacts into JSON-backed workflow records (WU 111, Phase G).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|