reflectt-node 0.1.3 → 0.1.5

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 (100) hide show
  1. package/README.md +60 -151
  2. package/dist/alert-preflight.d.ts +28 -0
  3. package/dist/alert-preflight.d.ts.map +1 -1
  4. package/dist/alert-preflight.js +178 -0
  5. package/dist/alert-preflight.js.map +1 -1
  6. package/dist/boardHealthWorker.d.ts.map +1 -1
  7. package/dist/boardHealthWorker.js +25 -12
  8. package/dist/boardHealthWorker.js.map +1 -1
  9. package/dist/chat-approval-detector.d.ts.map +1 -1
  10. package/dist/chat-approval-detector.js +29 -11
  11. package/dist/chat-approval-detector.js.map +1 -1
  12. package/dist/chat.d.ts +1 -0
  13. package/dist/chat.d.ts.map +1 -1
  14. package/dist/chat.js +14 -3
  15. package/dist/chat.js.map +1 -1
  16. package/dist/cli.js +187 -22
  17. package/dist/cli.js.map +1 -1
  18. package/dist/cloud.d.ts +28 -1
  19. package/dist/cloud.d.ts.map +1 -1
  20. package/dist/cloud.js +55 -20
  21. package/dist/cloud.js.map +1 -1
  22. package/dist/compliance-detector.d.ts +42 -0
  23. package/dist/compliance-detector.d.ts.map +1 -0
  24. package/dist/compliance-detector.js +286 -0
  25. package/dist/compliance-detector.js.map +1 -0
  26. package/dist/continuity-loop.d.ts.map +1 -1
  27. package/dist/continuity-loop.js +7 -3
  28. package/dist/continuity-loop.js.map +1 -1
  29. package/dist/dashboard.d.ts +6 -2
  30. package/dist/dashboard.d.ts.map +1 -1
  31. package/dist/dashboard.js +56 -26
  32. package/dist/dashboard.js.map +1 -1
  33. package/dist/doctor.d.ts +2 -0
  34. package/dist/doctor.d.ts.map +1 -1
  35. package/dist/doctor.js +78 -11
  36. package/dist/doctor.js.map +1 -1
  37. package/dist/executionSweeper.d.ts.map +1 -1
  38. package/dist/executionSweeper.js +12 -0
  39. package/dist/executionSweeper.js.map +1 -1
  40. package/dist/health.d.ts.map +1 -1
  41. package/dist/health.js +30 -7
  42. package/dist/health.js.map +1 -1
  43. package/dist/hostConnectGuard.d.ts +25 -0
  44. package/dist/hostConnectGuard.d.ts.map +1 -0
  45. package/dist/hostConnectGuard.js +27 -0
  46. package/dist/hostConnectGuard.js.map +1 -0
  47. package/dist/index.js +144 -29
  48. package/dist/index.js.map +1 -1
  49. package/dist/insight-task-bridge.d.ts +22 -1
  50. package/dist/insight-task-bridge.d.ts.map +1 -1
  51. package/dist/insight-task-bridge.js +19 -4
  52. package/dist/insight-task-bridge.js.map +1 -1
  53. package/dist/mcp.js +6 -6
  54. package/dist/mcp.js.map +1 -1
  55. package/dist/notificationDedupeGuard.d.ts +33 -0
  56. package/dist/notificationDedupeGuard.d.ts.map +1 -0
  57. package/dist/notificationDedupeGuard.js +88 -0
  58. package/dist/notificationDedupeGuard.js.map +1 -0
  59. package/dist/policy.d.ts +1 -1
  60. package/dist/policy.d.ts.map +1 -1
  61. package/dist/policy.js +3 -1
  62. package/dist/policy.js.map +1 -1
  63. package/dist/preflight.d.ts.map +1 -1
  64. package/dist/preflight.js +7 -8
  65. package/dist/preflight.js.map +1 -1
  66. package/dist/reflection-automation.d.ts.map +1 -1
  67. package/dist/reflection-automation.js +38 -0
  68. package/dist/reflection-automation.js.map +1 -1
  69. package/dist/request-tracker.d.ts +13 -0
  70. package/dist/request-tracker.d.ts.map +1 -1
  71. package/dist/request-tracker.js +95 -16
  72. package/dist/request-tracker.js.map +1 -1
  73. package/dist/server.d.ts.map +1 -1
  74. package/dist/server.js +244 -58
  75. package/dist/server.js.map +1 -1
  76. package/dist/service-probe.d.ts.map +1 -1
  77. package/dist/service-probe.js +39 -2
  78. package/dist/service-probe.js.map +1 -1
  79. package/dist/shipped-heartbeat.d.ts +1 -1
  80. package/dist/shipped-heartbeat.js +1 -1
  81. package/dist/taskPrecheck.js +6 -6
  82. package/dist/taskPrecheck.js.map +1 -1
  83. package/dist/tasks.d.ts +1 -1
  84. package/dist/tasks.d.ts.map +1 -1
  85. package/dist/tasks.js +8 -5
  86. package/dist/tasks.js.map +1 -1
  87. package/dist/todoHoardingGuard.d.ts +35 -0
  88. package/dist/todoHoardingGuard.d.ts.map +1 -0
  89. package/dist/todoHoardingGuard.js +150 -0
  90. package/dist/todoHoardingGuard.js.map +1 -0
  91. package/dist/types.d.ts +2 -2
  92. package/dist/types.d.ts.map +1 -1
  93. package/dist/working-contract.d.ts.map +1 -1
  94. package/dist/working-contract.js +59 -3
  95. package/dist/working-contract.js.map +1 -1
  96. package/package.json +1 -1
  97. package/public/dashboard.js +94 -27
  98. package/public/docs.md +17 -2
  99. package/public/intensity-mock.html +413 -0
  100. package/public/polls-mock.html +610 -0
@@ -0,0 +1,150 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) Reflectt AI
3
+ /**
4
+ * Todo Hoarding Guard
5
+ *
6
+ * Prevents idle agents from holding too many todo tasks:
7
+ * Rule A — Cap: if assignee.todo > TODO_CAP && assignee.doing == 0 &&
8
+ * last_activity > IDLE_THRESHOLD_MS, auto-unassign lowest-priority
9
+ * todos beyond top TODO_CAP.
10
+ * Rule B — Orphan: mark todos held by idle/offline agents as orphaned
11
+ * so they don't count toward ready-floor supply.
12
+ * Rule C — Claim: /tasks/next?claim=1 auto-transitions todo→doing.
13
+ */
14
+ import { taskManager } from './tasks.js';
15
+ // ── Config ─────────────────────────────────────────────────────────────────
16
+ /** Max todo tasks per agent before auto-unassign kicks in */
17
+ export const TODO_CAP = 3;
18
+ /** Agent must be idle for this long (no doing tasks + no activity) before unassign */
19
+ export const IDLE_THRESHOLD_MS = 30 * 60 * 1000; // 30 minutes
20
+ /** Priority ordering (lower index = higher priority, kept first) */
21
+ const PRIORITY_ORDER = ['P0', 'P1', 'P2', 'P3'];
22
+ // ── Helpers ────────────────────────────────────────────────────────────────
23
+ function priorityRank(p) {
24
+ const idx = PRIORITY_ORDER.indexOf(p);
25
+ return idx >= 0 ? idx : PRIORITY_ORDER.length;
26
+ }
27
+ /**
28
+ * Get the most recent activity timestamp for an agent.
29
+ * Activity = last task update.
30
+ */
31
+ function getAgentLastActivity(agent, allTasks) {
32
+ let latest = 0;
33
+ for (const t of allTasks) {
34
+ if (t.assignee?.toLowerCase() !== agent.toLowerCase())
35
+ continue;
36
+ const ts = typeof t.updatedAt === 'number' ? t.updatedAt : 0;
37
+ if (ts > latest)
38
+ latest = ts;
39
+ }
40
+ return latest;
41
+ }
42
+ // ── Core Logic ─────────────────────────────────────────────────────────────
43
+ /**
44
+ * Run the hoarding sweep. Returns actions taken (or would be taken in dry-run).
45
+ */
46
+ export async function sweepTodoHoarding(opts = {}) {
47
+ const { dryRun = false } = opts;
48
+ const now = Date.now();
49
+ const allTasks = taskManager.listTasks();
50
+ // Group by assignee
51
+ const byAssignee = new Map();
52
+ for (const t of allTasks) {
53
+ if (!t.assignee || t.assignee === 'unassigned')
54
+ continue;
55
+ const agent = t.assignee.toLowerCase();
56
+ if (!byAssignee.has(agent))
57
+ byAssignee.set(agent, { todo: [], doing: [] });
58
+ const bucket = byAssignee.get(agent);
59
+ if (t.status === 'todo')
60
+ bucket.todo.push(t);
61
+ else if (t.status === 'doing')
62
+ bucket.doing.push(t);
63
+ }
64
+ const unassigned = [];
65
+ const orphaned = [];
66
+ for (const [agent, { todo, doing }] of byAssignee) {
67
+ const lastActivity = getAgentLastActivity(agent, allTasks);
68
+ const idleMs = now - lastActivity;
69
+ // Rule B: orphan detection — flag todos held by agents with 0 doing AND idle
70
+ if (doing.length === 0 && todo.length > 0 && idleMs >= IDLE_THRESHOLD_MS) {
71
+ for (const t of todo) {
72
+ orphaned.push({
73
+ taskId: t.id,
74
+ taskTitle: t.title || '',
75
+ assignee: agent,
76
+ idleMinutes: Math.round(idleMs / 60000),
77
+ });
78
+ }
79
+ }
80
+ // Rule A: auto-unassign overflow
81
+ // Skip agents actively doing work
82
+ if (doing.length > 0)
83
+ continue;
84
+ // Skip agents with todo at or below cap
85
+ if (todo.length <= TODO_CAP)
86
+ continue;
87
+ // Only unassign if idle beyond threshold
88
+ if (idleMs < IDLE_THRESHOLD_MS)
89
+ continue;
90
+ // Sort by priority (keep highest priority), then by createdAt (keep newest)
91
+ const sorted = [...todo].sort((a, b) => {
92
+ const pDiff = priorityRank(a.priority || 'P3') - priorityRank(b.priority || 'P3');
93
+ if (pDiff !== 0)
94
+ return pDiff;
95
+ // Same priority: keep more recently created
96
+ return (b.createdAt || 0) - (a.createdAt || 0);
97
+ });
98
+ // Keep top TODO_CAP, unassign the rest
99
+ const toUnassign = sorted.slice(TODO_CAP);
100
+ for (const task of toUnassign) {
101
+ // Skip pinned tasks
102
+ if (task.metadata?.pinned)
103
+ continue;
104
+ const reason = `Auto-unassigned: ${agent} held ${todo.length} todos with 0 doing and ${Math.round(idleMs / 60000)}m idle (cap: ${TODO_CAP})`;
105
+ if (!dryRun) {
106
+ await taskManager.updateTask(task.id, {
107
+ assignee: 'unassigned',
108
+ });
109
+ // Add comment for audit trail
110
+ await taskManager.addTaskComment(task.id, 'system', `🔄 ${reason}`);
111
+ }
112
+ unassigned.push({
113
+ taskId: task.id,
114
+ taskTitle: task.title || '',
115
+ previousAssignee: agent,
116
+ reason,
117
+ });
118
+ }
119
+ }
120
+ return {
121
+ unassigned,
122
+ orphaned,
123
+ scanned: allTasks.length,
124
+ timestamp: new Date().toISOString(),
125
+ };
126
+ }
127
+ /**
128
+ * Claim a task: transition from todo → doing when fetched via /tasks/next.
129
+ * Returns the updated task or null if transition fails.
130
+ */
131
+ export async function claimTask(taskId, agent) {
132
+ const task = taskManager.getTask(taskId);
133
+ if (!task)
134
+ return null;
135
+ if (task.status !== 'todo')
136
+ return null;
137
+ const updated = await taskManager.updateTask(taskId, {
138
+ status: 'doing',
139
+ assignee: agent,
140
+ metadata: {
141
+ ...(task.metadata || {}),
142
+ eta: '~60m (auto-claimed)',
143
+ },
144
+ });
145
+ if (updated) {
146
+ await taskManager.addTaskComment(taskId, 'system', `📋 Auto-claimed by ${agent} via /tasks/next?claim=1`);
147
+ }
148
+ return updated || null;
149
+ }
150
+ //# sourceMappingURL=todoHoardingGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todoHoardingGuard.js","sourceRoot":"","sources":["../src/todoHoardingGuard.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -25,7 +25,7 @@ export interface Task {
25
25
  id: string;
26
26
  title: string;
27
27
  description?: string;
28
- status: 'todo' | 'doing' | 'blocked' | 'validating' | 'done';
28
+ status: 'todo' | 'doing' | 'blocked' | 'validating' | 'done' | 'resolved_externally' | 'cancelled';
29
29
  assignee?: string;
30
30
  reviewer?: string;
31
31
  done_criteria?: string[];
@@ -88,7 +88,7 @@ export interface RecurringTask {
88
88
  metadata?: Record<string, unknown>;
89
89
  schedule: RecurringTaskSchedule;
90
90
  enabled: boolean;
91
- status?: 'todo' | 'doing' | 'blocked' | 'validating' | 'done';
91
+ status?: 'todo' | 'doing' | 'blocked' | 'validating' | 'done' | 'resolved_externally' | 'cancelled';
92
92
  lastRunAt?: number;
93
93
  lastSkipAt?: number;
94
94
  lastSkipReason?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"working-contract.d.ts","sourceRoot":"","sources":["../src/working-contract.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,qBAAqB,EAAE,OAAO,CAAA;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,GAAG,cAAc,GAAG,uBAAuB,CAAA;IAC1D,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,oBAAoB,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAQD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CA+G/D;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAkE7D;AAqCD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAElD"}
1
+ {"version":3,"file":"working-contract.d.ts","sourceRoot":"","sources":["../src/working-contract.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,qBAAqB,EAAE,OAAO,CAAA;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,GAAG,cAAc,GAAG,uBAAuB,CAAA;IAC1D,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,oBAAoB,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AA6DD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAmH/D;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAkE7D;AAqCD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAElD"}
@@ -14,7 +14,60 @@ import { routeMessage } from './messageRouter.js';
14
14
  import { listReflections } from './reflections.js';
15
15
  import { getEffectiveActivity, formatActivityWarning } from './activity-signal.js';
16
16
  // ── State: track warnings ──
17
- const warningTimestamps = new Map(); // key: `${agent}:${taskId}`
17
+ /**
18
+ * warningTimestamps: key → epoch ms when Phase 1 warning was issued.
19
+ *
20
+ * Backed by SQLite so restarts don't re-fire warnings. In-memory cache
21
+ * is seeded from DB on first use.
22
+ *
23
+ * Root cause of compliance snapshot 3x bug: this was previously a plain
24
+ * in-memory Map that reset on every server restart. Each restart would
25
+ * re-fire the Phase 1 warning for every stale doing task. The stale
26
+ * duration increments between restarts (e.g. "stale for 45m" vs "46m"),
27
+ * which bypassed chat.ts content dedup, resulting in 2–3x identical-
28
+ * looking warning messages per agent per deploy cycle.
29
+ */
30
+ const warningTimestamps = new Map();
31
+ let _warningDbSeeded = false;
32
+ function ensureWarningTable() {
33
+ const db = getDb();
34
+ db.prepare(`
35
+ CREATE TABLE IF NOT EXISTS wc_warning_timestamps (
36
+ key TEXT PRIMARY KEY,
37
+ warned_at INTEGER NOT NULL
38
+ )
39
+ `).run();
40
+ }
41
+ function seedWarningTimestamps() {
42
+ if (_warningDbSeeded)
43
+ return;
44
+ _warningDbSeeded = true;
45
+ try {
46
+ ensureWarningTable();
47
+ const db = getDb();
48
+ const rows = db.prepare('SELECT key, warned_at FROM wc_warning_timestamps').all();
49
+ for (const row of rows) {
50
+ warningTimestamps.set(row.key, row.warned_at);
51
+ }
52
+ }
53
+ catch { /* db may not be ready */ }
54
+ }
55
+ function persistWarning(key, timestamp) {
56
+ try {
57
+ ensureWarningTable();
58
+ const db = getDb();
59
+ db.prepare('INSERT OR REPLACE INTO wc_warning_timestamps (key, warned_at) VALUES (?, ?)').run(key, timestamp);
60
+ }
61
+ catch { /* best-effort */ }
62
+ }
63
+ function clearWarning(key) {
64
+ warningTimestamps.delete(key);
65
+ try {
66
+ const db = getDb();
67
+ db.prepare('DELETE FROM wc_warning_timestamps WHERE key = ?').run(key);
68
+ }
69
+ catch { /* best-effort */ }
70
+ }
18
71
  // ── Enforcement tick ──
19
72
  /**
20
73
  * Called periodically. Checks all 'doing' tasks for stale status.
@@ -24,6 +77,8 @@ export async function tickWorkingContract() {
24
77
  const config = getConfig();
25
78
  if (!config.enabled)
26
79
  return { warnings: 0, requeued: 0, actions: [] };
80
+ // Seed warningTimestamps from DB on first tick (survives process restarts)
81
+ seedWarningTimestamps();
27
82
  const now = Date.now();
28
83
  const staleThresholdMs = config.staleAutoRequeueMin * 60_000;
29
84
  const graceMs = config.graceAfterWarningMin * 60_000;
@@ -51,6 +106,7 @@ export async function tickWorkingContract() {
51
106
  if (!warnedAt) {
52
107
  // Phase 1: Issue warning
53
108
  warningTimestamps.set(warningKey, now);
109
+ persistWarning(warningKey, now);
54
110
  const signalInfo = formatActivityWarning(activitySignal, config.staleAutoRequeueMin, now);
55
111
  const action = {
56
112
  type: 'warning',
@@ -80,7 +136,7 @@ export async function tickWorkingContract() {
80
136
  const activitySinceWarning = getLastActivityForAgent(task.id, agent);
81
137
  if (activitySinceWarning && activitySinceWarning > warnedAt) {
82
138
  // Agent responded — clear warning
83
- warningTimestamps.delete(warningKey);
139
+ clearWarning(warningKey);
84
140
  continue;
85
141
  }
86
142
  // Auto-requeue
@@ -95,7 +151,7 @@ export async function tickWorkingContract() {
95
151
  };
96
152
  actions.push(action);
97
153
  requeued++;
98
- warningTimestamps.delete(warningKey);
154
+ clearWarning(warningKey);
99
155
  if (!config.dryRun) {
100
156
  try {
101
157
  // Move task back to todo, clear assignee
@@ -1 +1 @@
1
- {"version":3,"file":"working-contract.js","sourceRoot":"","sources":["../src/working-contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"working-contract.js","sourceRoot":"","sources":["../src/working-contract.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reflectt-node",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Coordinate your AI agent team. Shared tasks, memory, reflections, and presence. Self-host for free.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -71,8 +71,14 @@ function updateFirstBootBanner() {
71
71
  const el = document.getElementById('first-boot-banner');
72
72
  if (!el) return;
73
73
  const dismissed = localStorage.getItem('reflectt-first-boot-dismissed');
74
- const hasTasks = allTasks.length > 0;
75
- el.hidden = dismissed === '1' || hasTasks;
74
+ // We seed a welcome task on first boot, so `allTasks.length > 0` is not a good proxy for
75
+ // "user has started using the system". Only hide the banner once a *non-seeded* task exists.
76
+ const seededSources = new Set(['first-boot', 'first-boot-intent']);
77
+ const hasRealTasks = allTasks.some(t => {
78
+ const src = t && t.metadata && t.metadata.source;
79
+ return !src || !seededSources.has(src);
80
+ });
81
+ el.hidden = dismissed === '1' || hasRealTasks;
76
82
  }
77
83
  function dismissFirstBootBanner() {
78
84
  localStorage.setItem('reflectt-first-boot-dismissed', '1');
@@ -80,6 +86,14 @@ function dismissFirstBootBanner() {
80
86
  if (el) el.hidden = true;
81
87
  }
82
88
 
89
+ function updateOverviewEmptyState() {
90
+ const el = document.getElementById('overview-empty-state');
91
+ if (!el) return;
92
+ const hasTasks = allTasks.length > 0;
93
+ const hasMessages = allMessages.length > 0;
94
+ el.style.display = (hasTasks || hasMessages) ? 'none' : '';
95
+ }
96
+
83
97
  // Delta cursors for lower payload refreshes
84
98
  let lastTaskSync = 0;
85
99
  let lastChatSync = 0;
@@ -164,6 +178,14 @@ function formatProductiveText(agent) {
164
178
  function esc(s) { const d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; }
165
179
  function formatBytes(b) { if (!b || b < 1024) return b + ' B'; if (b < 1048576) return (b/1024).toFixed(1) + ' KB'; return (b/1048576).toFixed(1) + ' MB'; }
166
180
  function truncate(s, n) { return s && s.length > n ? s.slice(0, n) + '…' : (s || ''); }
181
+ function humanizeMinutes(m) {
182
+ if (m == null || m === '') return '—';
183
+ const n = Number(m);
184
+ if (!Number.isFinite(n) || n >= 9999) return '—';
185
+ if (n < 60) return n + 'm';
186
+ if (n < 1440) return Math.round(n / 60) + 'h';
187
+ return Math.round(n / 1440) + 'd';
188
+ }
167
189
  function renderTaskTags(tags) {
168
190
  if (!Array.isArray(tags) || tags.length === 0) return '';
169
191
  const shown = tags.filter(Boolean).slice(0, 3);
@@ -250,7 +272,7 @@ function renderLaneTransitionMeta(task) {
250
272
  return `<div style="margin-top:6px;font-size:11px;color:var(--text-muted)">🧭 ${esc(parts.join(' · '))}</div>`;
251
273
  }
252
274
 
253
- function mentionsRyan(message) { return /@ryan\b/i.test(message || ''); }
275
+ function hasMention(message) { return /@([a-zA-Z][a-zA-Z0-9_-]*)/i.test(message || ''); }
254
276
 
255
277
  function resolveSSOTState(lastVerifiedUtc) {
256
278
  if (!lastVerifiedUtc) return { state: 'unknown', label: 'unknown', text: 'verification timestamp unavailable' };
@@ -442,12 +464,12 @@ function formatDurationMin(min) {
442
464
 
443
465
  function statusTemplateFor(agent, taskId) {
444
466
  const mentions = agent === 'pixel'
445
- ? '@kai @link'
467
+ ? '@owner @link'
446
468
  : agent === 'link'
447
- ? '@kai @pixel'
469
+ ? '@owner @pixel'
448
470
  : agent === 'kai'
449
471
  ? '@link @pixel'
450
- : '@kai @pixel';
472
+ : '@owner @pixel';
451
473
  return [
452
474
  mentions,
453
475
  'Task: ' + (taskId || '<task-id>'),
@@ -495,7 +517,7 @@ function renderCompliance(compliance) {
495
517
 
496
518
  const chipsHtml = chips.map(c => {
497
519
  const state = complianceState(c.value, c.threshold);
498
- return '<div class="sla-chip ' + state + '"><span>' + esc(c.label) + '</span><strong>' + formatDurationMin(c.value) + '</strong></div>';
520
+ return '<div class="sla-chip ' + state + '"><span>' + esc(c.label) + '</span><strong>' + humanizeMinutes(c.value) + '</strong></div>';
499
521
  }).join('');
500
522
 
501
523
  const rows = agents.map(a => {
@@ -504,7 +526,7 @@ function renderCompliance(compliance) {
504
526
  return '<tr>' +
505
527
  '<td>' + esc(a.agent) + '</td>' +
506
528
  '<td>' + taskCell + '</td>' +
507
- '<td>' + formatDurationMin(a.lastValidStatusAgeMin) + '</td>' +
529
+ '<td>' + humanizeMinutes(a.lastValidStatusAgeMin) + '</td>' +
508
530
  '<td>' + a.expectedCadenceMin + 'm</td>' +
509
531
  '<td><span class="state-pill ' + a.state + ' compliance-state-' + a.state + '">' + esc(a.state) + '</span></td>' +
510
532
  '<td><button class="copy-template-btn" data-agent="' + esc(a.agent) + '" data-task="' + esc(taskValue) + '" onclick="copyStatusTemplate(this.dataset.agent, this.dataset.task)">Copy template</button></td>' +
@@ -709,6 +731,7 @@ async function loadTasks(forceFull = false) {
709
731
  const navTaskBadge = document.getElementById('nav-task-count');
710
732
  if (navTaskBadge) navTaskBadge.textContent = allTasks.length;
711
733
  updateFirstBootBanner();
734
+ updateOverviewEmptyState();
712
735
  }
713
736
 
714
737
  function renderProjectTabs() {
@@ -733,7 +756,7 @@ function toggleTestTasks() {
733
756
  renderStatusFilterTabs();
734
757
  renderKanban();
735
758
  // Update task count
736
- const openCount = getVisibleTasks().filter(t => t.status !== 'done').length;
759
+ const openCount = getVisibleTasks().filter(t => !['done', 'resolved_externally', 'cancelled'].includes(t.status)).length;
737
760
  document.getElementById('task-count').textContent = currentStatusFilter === 'open'
738
761
  ? openCount + ' open tasks'
739
762
  : getVisibleTasks().length + ' tasks';
@@ -771,20 +794,47 @@ function renderKanban() {
771
794
  const filtered = currentProject === 'all' ? visible : visible.filter(t => classifyProject(t) === currentProject);
772
795
  const cols = currentStatusFilter === 'open'
773
796
  ? ['todo', 'doing', 'blocked', 'validating']
774
- : ['todo', 'doing', 'blocked', 'validating', 'done'];
797
+ : ['todo', 'doing', 'blocked', 'validating', 'done', 'resolved_externally', 'cancelled'];
775
798
  const grouped = {}; cols.forEach(c => grouped[c] = []);
776
- filtered.forEach(t => { const s = t.status || 'todo'; if (grouped[s]) grouped[s].push(t); else grouped['todo'].push(t); });
799
+ const tasksForBoard = currentStatusFilter === 'open'
800
+ ? filtered.filter(t => cols.includes(t.status || 'todo'))
801
+ : filtered;
802
+ tasksForBoard.forEach(t => { const s = t.status || 'todo'; if (grouped[s]) grouped[s].push(t); else grouped['todo'].push(t); });
777
803
  const pOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
778
804
  cols.forEach(c => grouped[c].sort((a, b) => (pOrder[a.priority] ?? 9) - (pOrder[b.priority] ?? 9)));
779
805
 
780
806
  const kanban = document.getElementById('kanban');
807
+
808
+ // Full-board empty state: no tasks at all
809
+ const totalOnBoard = tasksForBoard.length;
810
+ if (totalOnBoard === 0) {
811
+ kanban.innerHTML = '<div class="board-empty-state" style="grid-column:1/-1;text-align:center;padding:40px 20px;color:var(--text-muted)">'
812
+ + '<div style="font-size:28px;margin-bottom:12px">📋</div>'
813
+ + '<div style="font-size:15px;font-weight:500;color:var(--text-bright);margin-bottom:6px">No tasks yet</div>'
814
+ + '<div style="font-size:13px;max-width:340px;margin:0 auto;line-height:1.5">Create your first task via the API, or connect an AI agent to start generating work automatically.</div>'
815
+ + '<div style="margin-top:14px;display:flex;gap:10px;justify-content:center;flex-wrap:wrap">'
816
+ + '<a href="/docs" target="_blank" style="color:var(--accent);font-size:12px;text-decoration:none">API reference →</a>'
817
+ + '<a href="/capabilities" target="_blank" style="color:var(--accent);font-size:12px;text-decoration:none">Capabilities →</a>'
818
+ + '</div></div>';
819
+ return;
820
+ }
821
+
781
822
  kanban.innerHTML = cols.map(col => {
782
823
  const items = grouped[col];
783
824
  const isDone = col === 'done';
784
- const shown = isDone ? items.slice(0, 3) : items;
785
- const cards = shown.length === 0
786
- ? '<div class="empty">—</div>'
787
- : shown.map(t => {
825
+ const isTodo = col === 'todo';
826
+ const colLimit = isDone ? 3 : isTodo ? 10 : items.length;
827
+ const emptyMessages = {
828
+ todo: 'No tasks queued',
829
+ doing: 'Nothing in progress',
830
+ blocked: 'Nothing blocked',
831
+ validating: 'Nothing awaiting review',
832
+ done: 'No completed tasks yet',
833
+ };
834
+ const cards = items.length === 0
835
+ ? '<div class="empty" style="font-size:12px;padding:12px 8px">' + (emptyMessages[col] || '—') + '</div>'
836
+ : items.map((t, idx) => {
837
+ const isHidden = idx >= colLimit;
788
838
  const assigneeAgent = t.assignee ? AGENTS.find(a => a.name === t.assignee) : null;
789
839
  const assigneeDisplay = t.assignee
790
840
  ? `<span class="assignee-tag">👤 ${esc(t.assignee)}${assigneeAgent ? ' <span class="role-small">' + esc(assigneeAgent.role) + '</span>' : ''}</span>`
@@ -793,7 +843,7 @@ function renderKanban() {
793
843
  ? `<div style="margin-top:4px"><span class="assignee-tag" style="font-family:monospace;font-size:10px;color:var(--accent)">🌿 ${esc(t.metadata.branch)}</span></div>`
794
844
  : '';
795
845
  return `
796
- <div class="task-card" data-task-id="${t.id}">
846
+ <div class="task-card${isHidden ? ' hidden' : ''}" data-task-id="${t.id}">
797
847
  <div class="task-title">${esc(truncate(t.title, 60))}</div>
798
848
  <div class="task-meta">
799
849
  ${t.priority ? '<span class="priority-badge ' + t.priority + '">' + t.priority + '</span>' : ''}
@@ -808,8 +858,9 @@ function renderKanban() {
808
858
  ${renderQaContract(t)}
809
859
  </div>`;
810
860
  }).join('');
811
- const extra = isDone && items.length > 3
812
- ? `<button class="done-toggle" onclick="this.parentElement.querySelectorAll('.task-card.hidden').forEach(c=>c.classList.remove('hidden'));this.remove()">+ ${items.length - 3} more</button>` : '';
861
+ const hasMore = items.length > colLimit;
862
+ const extra = hasMore
863
+ ? `<button class="done-toggle" onclick="this.parentElement.querySelectorAll('.task-card.hidden').forEach(c=>c.classList.remove('hidden'));this.remove()">+ ${items.length - colLimit} more</button>` : '';
813
864
  return `<div class="kanban-col" data-status="${col}">
814
865
  <div class="kanban-col-header">${col} <span class="cnt">${items.length}</span></div>
815
866
  ${cards}${extra}
@@ -1021,13 +1072,13 @@ async function loadChat(forceFull = false) {
1021
1072
  if (!channelStats.has(ch)) channelStats.set(ch, { total: 0, mentions: 0 });
1022
1073
  const stats = channelStats.get(ch);
1023
1074
  stats.total += 1;
1024
- if (mentionsRyan(m.content)) stats.mentions += 1;
1075
+ if (hasMention(m.content)) stats.mentions += 1;
1025
1076
  });
1026
1077
 
1027
1078
  const tabs = document.getElementById('channel-tabs');
1028
1079
  tabs.innerHTML = Array.from(channels).map(ch => {
1029
1080
  const stats = ch === 'all'
1030
- ? { total: allMessages.length, mentions: allMessages.filter(m => mentionsRyan(m.content)).length }
1081
+ ? { total: allMessages.length, mentions: allMessages.filter(m => hasMention(m.content)).length }
1031
1082
  : (channelStats.get(ch) || { total: 0, mentions: 0 });
1032
1083
  const label = ch === 'all' ? '🌐 all' : '#' + esc(ch);
1033
1084
  const countMeta = `<span class="meta">${stats.total}</span>`;
@@ -1058,7 +1109,7 @@ function renderChat() {
1058
1109
  body.innerHTML = shown.map(m => {
1059
1110
  const agent = AGENT_INDEX.get(m.from);
1060
1111
  const roleTag = agent ? `<span class="msg-role">${esc(agent.role)}</span>` : '';
1061
- const mentioned = mentionsRyan(m.content);
1112
+ const mentioned = hasMention(m.content);
1062
1113
  const channelTag = m.channel ? '<span class="msg-channel">#' + esc(m.channel) + '</span>' : '';
1063
1114
  const editedTag = m.metadata && m.metadata.editedAt ? '<span class="msg-edited">(edited)</span>' : '';
1064
1115
  return `
@@ -1283,9 +1334,9 @@ async function loadSharedArtifacts() {
1283
1334
  const files = entries.filter(e => e && e.type === 'file');
1284
1335
  count.textContent = files.length + ' files';
1285
1336
 
1286
- // Pinned: Ryan's thoughts (if symlinked into shared workspace process/)
1337
+ // Pinned: operator notes (optional)
1287
1338
  const pinned = [
1288
- { name: "RYANS-THOUGHTS.md", label: "Ryan's thoughts" },
1339
+ { name: "OPERATOR-NOTES.md", label: "Operator notes" },
1289
1340
  ];
1290
1341
 
1291
1342
  const pinnedRows = pinned.map(p => {
@@ -1544,6 +1595,7 @@ async function loadReleaseStatus(force = false) {
1544
1595
  badge.classList.toggle('stale', stale);
1545
1596
  badge.classList.toggle('fresh', !stale);
1546
1597
  badge.textContent = stale ? 'deploy: stale' : 'deploy: in sync';
1598
+ badge.style.display = '';
1547
1599
 
1548
1600
  const reasons = Array.isArray(status.reasons) ? status.reasons : [];
1549
1601
  const startupCommit = status.startup && status.startup.commit ? status.startup.commit.slice(0, 8) : 'unknown';
@@ -1579,6 +1631,7 @@ async function loadBuildInfo() {
1579
1631
  badge.classList.toggle('stale', branch !== 'main');
1580
1632
  badge.textContent = `${sha} • ${uptimeStr}`;
1581
1633
  badge.title = `SHA: ${info.gitSha}\nBranch: ${branch}\nCommit: ${info.gitMessage}\nAuthor: ${info.gitAuthor}\nPID: ${info.pid}\nNode: ${info.nodeVersion}\nStarted: ${info.startedAt}`;
1634
+ badge.style.display = '';
1582
1635
  } catch (err) {
1583
1636
  badge.textContent = 'build: error';
1584
1637
  badge.title = 'Failed to load build info';
@@ -1697,7 +1750,16 @@ function renderReviewQueue() {
1697
1750
  });
1698
1751
 
1699
1752
  if (validating.length === 0) {
1700
- panel.style.display = 'none';
1753
+ panel.style.display = '';
1754
+ count.textContent = '';
1755
+ body.innerHTML = '<div style="text-align:center;padding:24px 16px;color:var(--text-muted)">'
1756
+ + '<div style="font-size:22px;margin-bottom:8px">✓</div>'
1757
+ + '<div style="font-size:13px;font-weight:500;color:var(--text-bright);margin-bottom:4px">Review queue is clear</div>'
1758
+ + '<div style="font-size:12px;line-height:1.5">Tasks move here when they enter <em>validating</em>. Reviewers will see SLA timers and can approve or request changes.</div>'
1759
+ + '</div>';
1760
+ // Clear sidebar badge
1761
+ const navReviewBadge = document.getElementById('nav-review-count');
1762
+ if (navReviewBadge) navReviewBadge.textContent = '0';
1701
1763
  return;
1702
1764
  }
1703
1765
 
@@ -1759,7 +1821,7 @@ async function escalateReviewBreaches(breachedTasks) {
1759
1821
  return '- ' + t.id + ' (' + (t.title || '').slice(0, 50) + ') — reviewer: @' + reviewer + ', waiting ' + formatDuration(t.timeInReview);
1760
1822
  });
1761
1823
 
1762
- const content = '@kai Review SLA breach detected:\n' + lines.join('\n');
1824
+ const content = '@owner Review SLA breach detected:\n' + lines.join('\n');
1763
1825
 
1764
1826
  try {
1765
1827
  await fetch(BASE + '/chat/messages', {
@@ -2738,6 +2800,11 @@ function toggleFocusMode() {
2738
2800
  // Persist preference
2739
2801
  try { localStorage.setItem('reflectt-focus-mode', focusModeActive ? '1' : '0'); } catch {}
2740
2802
 
2803
+ // Show/hide dev-only panels
2804
+ document.querySelectorAll('.panel.focus-only').forEach(panel => {
2805
+ panel.style.display = focusModeActive ? '' : 'none';
2806
+ });
2807
+
2741
2808
  // Re-render kanban to add/remove QA contract details
2742
2809
  renderKanban();
2743
2810
 
@@ -2829,9 +2896,9 @@ async function checkGettingStarted() {
2829
2896
  const hasTasks = (health.tasks?.total || 0) > 0;
2830
2897
  const hasMessages = (health.chat?.total || 0) > 0;
2831
2898
 
2832
- // Step 1: preflight — done if server is healthy
2899
+ // Step 1: server running always done if dashboard loads
2833
2900
  const step1 = document.getElementById('gs-preflight');
2834
- if (step1 && hasHeartbeat) {
2901
+ if (step1) {
2835
2902
  step1.classList.add('done');
2836
2903
  step1.querySelector('.gs-icon').textContent = '✓';
2837
2904
  }