kaizen-agent 1.40.2 → 1.40.3
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/cli/sources.test.ts +3 -0
- package/cli/sources.ts +7 -2
- package/package.json +1 -1
package/cli/sources.test.ts
CHANGED
|
@@ -146,6 +146,9 @@ test("split: a header row holding a `#`, a year or a date cell is still the head
|
|
|
146
146
|
for (const head of ["#\tRequest\tStatus", "No\tRequest\tStatus\t2026", "No\tRequest\tStatus\t2026-09-30", "No\tRequest\tStatus\t17-Sep-2026", "\tRequest\tStatus"]) {
|
|
147
147
|
const body = `${head}\n1\tFix login page\tOpen\n2\tAdd export\tDone\n`;
|
|
148
148
|
expect(sift("sheet", body)).toEqual({ items: [{ text: "Fix login page", notes: "1 · Open", row: 2 }], done: 1 });
|
|
149
|
+
// a Done task merged over two rows: the export leaves NO and status blank below
|
|
150
|
+
const merged = "NO\tRequest\tStatus\n1\tExport button missing\tDone\n\tExport keeps old filter\t\n2\tAdd dark mode\t\n";
|
|
151
|
+
expect(sift("sheet", merged)).toEqual({ items: [{ text: "Add dark mode", notes: "2", row: 4 }], done: 2 });
|
|
149
152
|
}
|
|
150
153
|
// A numbered row is data even when one of its cells is a header word said once.
|
|
151
154
|
expect(split("sheet", "1\tIssue\tLogin fails on Safari\n2\tBug\tExport drops rows\n3\tBug\tSearch is slow\n").map((i) => i.text))
|
package/cli/sources.ts
CHANGED
|
@@ -507,10 +507,15 @@ export function sift(kind: Kind, body: string, pics?: Map<number | string, strin
|
|
|
507
507
|
const head = filled.slice(0, 5).find((row) => !/^\d{1,3}[.)]?$/.test(row.find(Boolean) ?? "") && (named(row, HEADER) >= 0 || named(row, STATUS) >= 0));
|
|
508
508
|
const data = head ? filled.slice(filled.indexOf(head) + 1) : filled;
|
|
509
509
|
const status = head ? named(head, STATUS) : -1;
|
|
510
|
+
// A task merged over several rows has its number and status in the top row only:
|
|
511
|
+
// the export leaves both blank below, so such a row takes the status above it.
|
|
512
|
+
let above = "";
|
|
513
|
+
const state = new Map(data.map((row) => { const own = row[status] ?? ""; if (own || row[0]) above = own; return [row, own || above]; }));
|
|
514
|
+
const finished = (row: string[]) => status >= 0 && DONE.test(state.get(row) ?? "");
|
|
510
515
|
// One column for the whole sheet, the one holding the most text that reads like a
|
|
511
516
|
// request. Never a cell per row, which takes `Open` or a name.
|
|
512
517
|
// Finished rows do not vote: their replies outweigh the requests still open.
|
|
513
|
-
const open = data.filter((row) =>
|
|
518
|
+
const open = data.filter((row) => !finished(row));
|
|
514
519
|
const text = (i: number) => i === status ? 0 : open.reduce((sum, row) => sum + (wordy(row[i] ?? "") ? row[i]!.length : 0), 0);
|
|
515
520
|
let wordiest = -1;
|
|
516
521
|
for (let i = 0, most = 0; i < Math.max(0, ...data.map((row) => row.length)); i++) if (text(i) > most) { most = text(i); wordiest = i; }
|
|
@@ -524,7 +529,7 @@ export function sift(kind: Kind, body: string, pics?: Map<number | string, strin
|
|
|
524
529
|
const items = data.flatMap((row) => {
|
|
525
530
|
const text = row[col] ?? "";
|
|
526
531
|
if (!text || (known < 0 && !wordy(text))) return [];
|
|
527
|
-
if (
|
|
532
|
+
if (finished(row)) { done++; return []; }
|
|
528
533
|
const rest = row.filter((c, i) => c && i !== col).join(" · ");
|
|
529
534
|
// The export keeps every row from the top, so a row's index is its number less one.
|
|
530
535
|
return [with_({ text, ...(rest ? { notes: rest } : {}), row: cells.indexOf(row) + 1 }, cells.indexOf(row) + 1)];
|
package/package.json
CHANGED