@jungjaehoon/mama-os 0.49.0 → 0.49.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.
Files changed (42) hide show
  1. package/dist/agent/agent-loop.d.ts.map +1 -1
  2. package/dist/agent/agent-loop.js +14 -2
  3. package/dist/agent/agent-loop.js.map +1 -1
  4. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  5. package/dist/agent/code-act/host-bridge.js +7 -1
  6. package/dist/agent/code-act/host-bridge.js.map +1 -1
  7. package/dist/agent/gateway-tools.md +1 -1
  8. package/dist/agent/tool-registry.d.ts.map +1 -1
  9. package/dist/agent/tool-registry.js +27 -2
  10. package/dist/agent/tool-registry.js.map +1 -1
  11. package/dist/agent/types.d.ts +2 -0
  12. package/dist/agent/types.d.ts.map +1 -1
  13. package/dist/agent/types.js.map +1 -1
  14. package/dist/cli/commands/start.d.ts.map +1 -1
  15. package/dist/cli/commands/start.js +21 -15
  16. package/dist/cli/commands/start.js.map +1 -1
  17. package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
  18. package/dist/cli/runtime/agent-loop-init.js +3 -0
  19. package/dist/cli/runtime/agent-loop-init.js.map +1 -1
  20. package/dist/gateways/message-router.d.ts +2 -0
  21. package/dist/gateways/message-router.d.ts.map +1 -1
  22. package/dist/gateways/message-router.js +27 -6
  23. package/dist/gateways/message-router.js.map +1 -1
  24. package/dist/operator/owner-event-loop.d.ts +1 -1
  25. package/dist/operator/owner-event-loop.d.ts.map +1 -1
  26. package/dist/operator/owner-event-loop.js +1 -2
  27. package/dist/operator/owner-event-loop.js.map +1 -1
  28. package/dist/operator/situation-report.d.ts.map +1 -1
  29. package/dist/operator/situation-report.js +3 -0
  30. package/dist/operator/situation-report.js.map +1 -1
  31. package/dist/operator/task-ledger.d.ts +8 -1
  32. package/dist/operator/task-ledger.d.ts.map +1 -1
  33. package/dist/operator/task-ledger.js +51 -16
  34. package/dist/operator/task-ledger.js.map +1 -1
  35. package/dist/operator/task-list-views.d.ts.map +1 -1
  36. package/dist/operator/task-list-views.js +45 -24
  37. package/dist/operator/task-list-views.js.map +1 -1
  38. package/dist/operator/task-temporal.d.ts +3 -0
  39. package/dist/operator/task-temporal.d.ts.map +1 -1
  40. package/dist/operator/task-temporal.js +12 -0
  41. package/dist/operator/task-temporal.js.map +1 -1
  42. package/package.json +1 -1
@@ -210,6 +210,12 @@ class TaskLedger {
210
210
  toRecord(row) {
211
211
  return rowToRecord(row, this.now(), this.timeZone);
212
212
  }
213
+ toRecordAt(row, observedAt) {
214
+ return rowToRecord(row, observedAt, this.timeZone);
215
+ }
216
+ temporalStateAt(task, observedAt) {
217
+ return (0, task_temporal_js_1.deriveTemporalState)(task, observedAt, this.timeZone);
218
+ }
213
219
  runMigration() {
214
220
  // Both construction sites (start.ts boot + operator-handler lazy) run this;
215
221
  // busy_timeout here covers BOTH connections against the rebuild race.
@@ -364,7 +370,11 @@ class TaskLedger {
364
370
  return row.count;
365
371
  }
366
372
  list(filter = {}) {
367
- const { where, params } = this.buildListPredicate(filter);
373
+ const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
374
+ const { where, params } = this.buildListPredicate({
375
+ ...filter,
376
+ temporalAsOfMs: observedAt,
377
+ });
368
378
  const rawLimit = Number(filter.limit);
369
379
  // No LIMIT at all unless the caller asks for one: the whole board is the read, and the
370
380
  // 50/200 bound is what made the board turn judge 216 tasks from 50 (owner, 2026-09-04).
@@ -375,7 +385,14 @@ class TaskLedger {
375
385
  ORDER BY ${TaskLedger.orderSql(filter.order)}
376
386
  ${limit === null ? '' : 'LIMIT ?'}`)
377
387
  .all(...params, ...(limit === null ? [] : [limit]));
378
- return rows.map((row) => this.toRecord(row));
388
+ return rows.map((row) => this.toRecordAt(row, observedAt));
389
+ }
390
+ temporalAsOf(value) {
391
+ const observedAt = value ?? this.now();
392
+ if (!Number.isSafeInteger(observedAt)) {
393
+ throw new Error('task list temporal as-of must be a finite integer epoch millisecond');
394
+ }
395
+ return observedAt;
379
396
  }
380
397
  /** Shared filter predicate. Owner surface only - system workorder rows never appear in
381
398
  * board/REST/gateway listings (Stage-2 kind filter; workorders have dedicated readers). */
@@ -428,6 +445,27 @@ class TaskLedger {
428
445
  else if (filter.qualification === 'legacy_unqualified') {
429
446
  where.push('completion_criteria IS NULL');
430
447
  }
448
+ if (filter.dueBucket !== undefined) {
449
+ const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
450
+ const rows = this.db
451
+ .prepare(`SELECT id, status, due_at, deadline, deadline_offset_minutes
452
+ FROM operator_tasks WHERE ${where.join(' AND ')}`)
453
+ .all(...params);
454
+ const ids = rows
455
+ .filter((row) => {
456
+ const state = (0, task_temporal_js_1.deriveTemporalState)({
457
+ status: row.status,
458
+ dueAt: row.due_at,
459
+ deadlineIso: row.deadline,
460
+ deadlineOffsetMinutes: row.deadline_offset_minutes,
461
+ }, observedAt, this.timeZone);
462
+ return (0, task_temporal_js_1.dueBucketForTemporalState)(state) === filter.dueBucket;
463
+ })
464
+ .map((row) => row.id);
465
+ // One JSON parameter avoids SQLite's variable limit even on a large board.
466
+ where.push('id IN (SELECT CAST(value AS INTEGER) FROM json_each(?))');
467
+ params.push(JSON.stringify(ids));
468
+ }
431
469
  return { where, params };
432
470
  }
433
471
  /** ORDER BY for both list() and listPage(); the trailing id makes it a TOTAL order,
@@ -462,8 +500,12 @@ class TaskLedger {
462
500
  * read that quietly lost items.
463
501
  */
464
502
  listPage(filter = {}) {
503
+ const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
465
504
  const order = filter.order === 'updated' ? 'updated' : 'deadline_priority';
466
- const { where, params } = this.buildListPredicate(filter);
505
+ const { where, params } = this.buildListPredicate({
506
+ ...filter,
507
+ temporalAsOfMs: observedAt,
508
+ });
467
509
  const rawLimit = Number(filter.limit);
468
510
  // No cap and a whole-board default: Kagemusha's task_list is selectAll, and the 50/200
469
511
  // bound is what made the board turn judge 216 tasks from 50 (owner, 2026-09-04). The
@@ -494,7 +536,7 @@ class TaskLedger {
494
536
  LIMIT ?`)
495
537
  .all(...pageParams, limit + 1);
496
538
  const hasMore = rows.length > limit;
497
- const tasks = rows.slice(0, limit).map((row) => this.toRecord(row));
539
+ const tasks = rows.slice(0, limit).map((row) => this.toRecordAt(row, observedAt));
498
540
  const last = tasks[tasks.length - 1];
499
541
  return {
500
542
  tasks,
@@ -515,9 +557,9 @@ class TaskLedger {
515
557
  // statements cannot make the returned readVersion disagree with the page it
516
558
  // describes. Synchronous JS alone is not a cross-connection snapshot.
517
559
  return this.readSnapshot(() => {
518
- const observedAt = this.now();
560
+ const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
519
561
  const readVersion = this.readGeneration();
520
- const page = this.listPage(filter);
562
+ const page = this.listPage({ ...filter, temporalAsOfMs: observedAt });
521
563
  return { ...page, readVersion, observedAt };
522
564
  });
523
565
  }
@@ -566,9 +608,9 @@ class TaskLedger {
566
608
  }
567
609
  overviewInSnapshot(filter) {
568
610
  // One captured time for every derived due bucket; one snapshot for every count.
569
- const now = this.now();
611
+ const now = this.temporalAsOf(filter.temporalAsOfMs);
570
612
  const readVersion = this.readGeneration();
571
- const { where, params } = this.buildListPredicate(filter);
613
+ const { where, params } = this.buildListPredicate({ ...filter, temporalAsOfMs: now });
572
614
  const whereSql = where.join(' AND ');
573
615
  const groupBy = (column) => this.db
574
616
  .prepare(`SELECT ${column} AS key, COUNT(*) AS count FROM operator_tasks
@@ -600,14 +642,7 @@ class TaskLedger {
600
642
  deadlineIso: row.deadline,
601
643
  deadlineOffsetMinutes: row.deadline_offset_minutes,
602
644
  }, now, this.timeZone);
603
- if (state === 'closed')
604
- due.closed += 1;
605
- else if (state === 'unscheduled')
606
- due.missing += 1;
607
- else if (state === 'exact_overdue' || state === 'date_overdue')
608
- due.overdue += 1;
609
- else
610
- due.upcoming += 1;
645
+ due[(0, task_temporal_js_1.dueBucketForTemporalState)(state)] += 1;
611
646
  }
612
647
  return { total, observedAt: now, readVersion, status, priority, channels, assignees, due };
613
648
  }