@volter/supercode-orchestrator 0.5.223 → 0.5.224

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/board/files.mjs CHANGED
@@ -12,7 +12,7 @@ import { fillReadableIds } from './readable-id.mjs';
12
12
  import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
13
13
  import { fenced } from './fence.mjs';
14
14
  import { markRemovedHeads } from './published.mjs';
15
- import { CARD_NUMBERS } from './store.mjs';
15
+ import { CARD_NUMBERS, unnumberTasks } from './store.mjs';
16
16
  import { createHash } from 'node:crypto';
17
17
  import { join } from 'node:path';
18
18
  import { DatabaseSync } from 'node:sqlite';
@@ -133,6 +133,9 @@ class FilesBoard {
133
133
  cards.sort((a, b) => madeAt(a) - madeAt(b) || (String(a.id) < String(b.id) ? -1 : String(a.id) > String(b.id) ? 1 : 0));
134
134
  for (const card of cards) for (const [table, rows] of Object.entries(card.tables ?? {})) if (table !== CARD_NUMBERS) insert(table, rows);
135
135
  for (const [table, rows] of Object.entries(state?.tables ?? {})) insert(table, rows);
136
+ // A task whose file names no number keeps none: only cards are numbered.
137
+ unnumberTasks(mem, new Set(cards.filter((card) => card.tables?.[CARD_NUMBERS]?.length).map((card) => card.id)),
138
+ (state?.sequence ?? []).find((row) => row.name === CARD_NUMBERS)?.seq ?? 0);
136
139
  // Loading inserts every card, which marks every card changed (published.mjs). The first load of this projection keeps
137
140
  // those marks: its next write compares each card with its published head once (a named limit: each projection opened
138
141
  // compares every card once, as each load already reads every card's file). A reload keeps the marks not yet
package/board/store.mjs CHANGED
@@ -370,6 +370,18 @@ function layOutNumbers(db) {
370
370
  } catch (error) { db.exec('ROLLBACK TO supercode_card_numbering; RELEASE supercode_card_numbering'); throw error; }
371
371
  }
372
372
 
373
+ /** Only cards are numbered (VO-3578 row 22): a task's row (supercode_cards.subtask_of) is numbered by the insert trigger
374
+ * like any row, so a load gives each task's number back unless its source named it (`named`, task ids). The sequence
375
+ * returns to the highest number held, never below `floor` (what the source had already handed out). */
376
+ export function unnumberTasks(db, named = new Set(), floor = 0) {
377
+ const taken = db.prepare(`SELECT n.task_id FROM ${CARD_NUMBERS} n JOIN supercode_cards c ON c.task_id = n.task_id WHERE c.subtask_of IS NOT NULL`).all()
378
+ .filter((row) => !named.has(row.task_id));
379
+ if (!taken.length) return;
380
+ const drop = db.prepare(`DELETE FROM ${CARD_NUMBERS} WHERE task_id = ?`);
381
+ for (const row of taken) drop.run(row.task_id);
382
+ db.prepare(`UPDATE sqlite_sequence SET seq = MAX(?, (SELECT COALESCE(MAX(number), 0) FROM ${CARD_NUMBERS})) WHERE name = ?`).run(Number(floor) || 0, CARD_NUMBERS);
383
+ }
384
+
373
385
  /** Raise the numbers' high-water mark to the highest number held, and to `floor`: AUTOINCREMENT hands out only numbers
374
386
  * above it. For a store whose numbers were given or copied explicitly. */
375
387
  export function raiseCardNumbers(db, floor = 0) {
package/board/ztrack.mjs CHANGED
@@ -19,7 +19,7 @@ import { createHash, randomBytes } from 'node:crypto';
19
19
  import { existsSync, linkSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
20
20
  import { basename, dirname, join, resolve } from 'node:path';
21
21
  import { DatabaseSync } from 'node:sqlite';
22
- import { actorOf, boardKey, CARD_NUMBERS, contention, raiseCardNumbers, event, json, now, principalOf, storageFault, STORAGE_TRIES, unreadable } from './store.mjs';
22
+ import { actorOf, boardKey, CARD_NUMBERS, contention, raiseCardNumbers, unnumberTasks, event, json, now, principalOf, storageFault, STORAGE_TRIES, unreadable } from './store.mjs';
23
23
  import { GitDocument } from './git-document.mjs';
24
24
  import { unimported } from './legacy-store.mjs';
25
25
  import { noteStep, recordSlow } from '@volter/supercode-harness-sdk/slow-log';
@@ -462,13 +462,14 @@ class ZtrackBoard {
462
462
  put(`chunks:${role}`, entries);
463
463
  }
464
464
  put('published', published);
465
- // The earlier store held no numbers: its cards take the numbers their documents' headings give them, and the rest
466
- // are numbered in the order they were made, after every number the documents name (documentNumbers).
465
+ // The earlier store held no numbers: its cards take the numbers their documents' headings give them, and the other
466
+ // cards are numbered in the order they were made, after every number the documents name (documentNumbers); a task is not.
467
467
  db.exec(`DELETE FROM ${CARD_NUMBERS}; DELETE FROM sqlite_sequence WHERE name = '${CARD_NUMBERS}'`);
468
468
  const named = this.documentNumbers();
469
469
  this.numberFromHeadings([...named.headings].filter(([id]) => db.prepare('SELECT 1 FROM tasks WHERE id = ?').get(id)), db);
470
470
  raiseCardNumbers(db, named.highest);
471
- db.exec(`INSERT INTO ${CARD_NUMBERS} (task_id) SELECT id FROM tasks WHERE id NOT IN (SELECT task_id FROM ${CARD_NUMBERS}) ORDER BY created_at, id`);
471
+ db.exec(`INSERT INTO ${CARD_NUMBERS} (task_id) SELECT id FROM tasks WHERE id NOT IN (SELECT task_id FROM ${CARD_NUMBERS})
472
+ AND id NOT IN (SELECT task_id FROM supercode_cards WHERE subtask_of IS NOT NULL) ORDER BY created_at, id`);
472
473
  db.exec('COMMIT');
473
474
  }
474
475
 
@@ -921,6 +922,10 @@ class ZtrackBoard {
921
922
  this.numberFromHeadings([...plan.numbers].filter(([id]) => plan.rows.has(id)));
922
923
  raiseCardNumbers(this.conn, this.documentNumbers().highest);
923
924
  }
925
+ // What is numbered before the cards load: a task the document or the store had numbered keeps it, and a task row the
926
+ // load inserts gives back the number the insert trigger hands it (only cards are numbered).
927
+ const numbered = overlay ? null : new Set(this.statement(`SELECT task_id FROM main.${CARD_NUMBERS}`).all().map((row) => row.task_id));
928
+ const handedOut = overlay ? 0 : this.one(`SELECT seq FROM main.sqlite_sequence WHERE name = '${CARD_NUMBERS}'`)?.seq ?? 0;
924
929
  for (const [id, rows] of plan.rows) {
925
930
  const before = fingerprintOf(id);
926
931
  const oldTask = this.one(`SELECT * FROM ${schema}.tasks WHERE id = ?`, id) ?? {};
@@ -939,6 +944,7 @@ class ZtrackBoard {
939
944
  events.push({ id, kind, payload: { by, source: 'document', status: after.status, assignee: after.assignee, author: by }, before, after });
940
945
  }
941
946
  }
947
+ if (!overlay) unnumberTasks(this.conn, numbered, handedOut);
942
948
  for (const id of plan.checked) this.errors.delete(id);
943
949
  for (const [id, reason] of plan.errors) this.errors.set(id, reason);
944
950
  // A read overlays new document cards before the owner commits them. Give that
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.5.223",
3
+ "version": "0.5.224",
4
4
  "type": "module",
5
5
  "description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
6
6
  "exports": {
@@ -36,7 +36,7 @@
36
36
  "check-types": "node scripts/generate-types.mjs --check"
37
37
  },
38
38
  "dependencies": {
39
- "@volter/supercode-teams": "^0.3.380",
39
+ "@volter/supercode-teams": "^0.3.381",
40
40
  "@volter/supercode-terminal": "^0.3.12",
41
41
  "@volter/supercode-harness-sdk": "^0.3.106",
42
42
  "@volter/teams": "0.2.106",