reflectt-node 0.1.7 → 0.1.11

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 (220) hide show
  1. package/README.md +13 -0
  2. package/defaults/TEAM-ROLES.yaml +317 -5
  3. package/defaults/gitignore.template +23 -0
  4. package/dist/agent-config.d.ts +51 -0
  5. package/dist/agent-config.d.ts.map +1 -0
  6. package/dist/agent-config.js +129 -0
  7. package/dist/agent-config.js.map +1 -0
  8. package/dist/agent-config.test.d.ts +2 -0
  9. package/dist/agent-config.test.d.ts.map +1 -0
  10. package/dist/agent-config.test.js +91 -0
  11. package/dist/agent-config.test.js.map +1 -0
  12. package/dist/agent-memories.d.ts +58 -0
  13. package/dist/agent-memories.d.ts.map +1 -0
  14. package/dist/agent-memories.js +168 -0
  15. package/dist/agent-memories.js.map +1 -0
  16. package/dist/agent-memories.test.d.ts +2 -0
  17. package/dist/agent-memories.test.d.ts.map +1 -0
  18. package/dist/agent-memories.test.js +327 -0
  19. package/dist/agent-memories.test.js.map +1 -0
  20. package/dist/agent-messaging.d.ts +50 -0
  21. package/dist/agent-messaging.d.ts.map +1 -0
  22. package/dist/agent-messaging.js +103 -0
  23. package/dist/agent-messaging.js.map +1 -0
  24. package/dist/agent-messaging.test.d.ts +2 -0
  25. package/dist/agent-messaging.test.d.ts.map +1 -0
  26. package/dist/agent-messaging.test.js +105 -0
  27. package/dist/agent-messaging.test.js.map +1 -0
  28. package/dist/agent-runs.d.ts +158 -0
  29. package/dist/agent-runs.d.ts.map +1 -0
  30. package/dist/agent-runs.js +514 -0
  31. package/dist/agent-runs.js.map +1 -0
  32. package/dist/agent-runs.test.d.ts +2 -0
  33. package/dist/agent-runs.test.d.ts.map +1 -0
  34. package/dist/agent-runs.test.js +386 -0
  35. package/dist/agent-runs.test.js.map +1 -0
  36. package/dist/approval-queue.test.d.ts +2 -0
  37. package/dist/approval-queue.test.d.ts.map +1 -0
  38. package/dist/approval-queue.test.js +118 -0
  39. package/dist/approval-queue.test.js.map +1 -0
  40. package/dist/artifact-store.d.ts +55 -0
  41. package/dist/artifact-store.d.ts.map +1 -0
  42. package/dist/artifact-store.js +128 -0
  43. package/dist/artifact-store.js.map +1 -0
  44. package/dist/artifact-store.test.d.ts +2 -0
  45. package/dist/artifact-store.test.d.ts.map +1 -0
  46. package/dist/artifact-store.test.js +119 -0
  47. package/dist/artifact-store.test.js.map +1 -0
  48. package/dist/boardHealthWorker.d.ts +32 -0
  49. package/dist/boardHealthWorker.d.ts.map +1 -1
  50. package/dist/boardHealthWorker.js +69 -2
  51. package/dist/boardHealthWorker.js.map +1 -1
  52. package/dist/buildInfo.d.ts.map +1 -1
  53. package/dist/buildInfo.js +47 -10
  54. package/dist/buildInfo.js.map +1 -1
  55. package/dist/canvas-input.test.d.ts +2 -0
  56. package/dist/canvas-input.test.d.ts.map +1 -0
  57. package/dist/canvas-input.test.js +96 -0
  58. package/dist/canvas-input.test.js.map +1 -0
  59. package/dist/canvas-render.test.d.ts +2 -0
  60. package/dist/canvas-render.test.d.ts.map +1 -0
  61. package/dist/canvas-render.test.js +95 -0
  62. package/dist/canvas-render.test.js.map +1 -0
  63. package/dist/capabilities/browser.d.ts +75 -0
  64. package/dist/capabilities/browser.d.ts.map +1 -0
  65. package/dist/capabilities/browser.js +172 -0
  66. package/dist/capabilities/browser.js.map +1 -0
  67. package/dist/channels.d.ts +1 -1
  68. package/dist/chat.d.ts +4 -0
  69. package/dist/chat.d.ts.map +1 -1
  70. package/dist/chat.js +6 -2
  71. package/dist/chat.js.map +1 -1
  72. package/dist/cli.js +41 -14
  73. package/dist/cli.js.map +1 -1
  74. package/dist/cloud.d.ts +2 -0
  75. package/dist/cloud.d.ts.map +1 -1
  76. package/dist/cloud.js +151 -64
  77. package/dist/cloud.js.map +1 -1
  78. package/dist/continuity-loop.d.ts.map +1 -1
  79. package/dist/continuity-loop.js +297 -29
  80. package/dist/continuity-loop.js.map +1 -1
  81. package/dist/cost-enforcement.d.ts +38 -0
  82. package/dist/cost-enforcement.d.ts.map +1 -0
  83. package/dist/cost-enforcement.js +84 -0
  84. package/dist/cost-enforcement.js.map +1 -0
  85. package/dist/db.d.ts.map +1 -1
  86. package/dist/db.js +131 -0
  87. package/dist/db.js.map +1 -1
  88. package/dist/deploy-monitor.d.ts +18 -0
  89. package/dist/deploy-monitor.d.ts.map +1 -0
  90. package/dist/deploy-monitor.js +165 -0
  91. package/dist/deploy-monitor.js.map +1 -0
  92. package/dist/e2e-loop-proof.test.d.ts +2 -0
  93. package/dist/e2e-loop-proof.test.d.ts.map +1 -0
  94. package/dist/e2e-loop-proof.test.js +104 -0
  95. package/dist/e2e-loop-proof.test.js.map +1 -0
  96. package/dist/email-sms-send.test.d.ts +2 -0
  97. package/dist/email-sms-send.test.d.ts.map +1 -0
  98. package/dist/email-sms-send.test.js +96 -0
  99. package/dist/email-sms-send.test.js.map +1 -0
  100. package/dist/events.d.ts +1 -1
  101. package/dist/events.d.ts.map +1 -1
  102. package/dist/events.js +2 -0
  103. package/dist/events.js.map +1 -1
  104. package/dist/executionSweeper.d.ts +1 -0
  105. package/dist/executionSweeper.d.ts.map +1 -1
  106. package/dist/executionSweeper.js +43 -7
  107. package/dist/executionSweeper.js.map +1 -1
  108. package/dist/files.d.ts.map +1 -1
  109. package/dist/files.js +17 -3
  110. package/dist/files.js.map +1 -1
  111. package/dist/fingerprint.d.ts +30 -0
  112. package/dist/fingerprint.d.ts.map +1 -0
  113. package/dist/fingerprint.js +117 -0
  114. package/dist/fingerprint.js.map +1 -0
  115. package/dist/github-webhook-attribution.d.ts +38 -0
  116. package/dist/github-webhook-attribution.d.ts.map +1 -0
  117. package/dist/github-webhook-attribution.js +123 -0
  118. package/dist/github-webhook-attribution.js.map +1 -0
  119. package/dist/github-webhook-chat.d.ts +75 -0
  120. package/dist/github-webhook-chat.d.ts.map +1 -0
  121. package/dist/github-webhook-chat.js +108 -0
  122. package/dist/github-webhook-chat.js.map +1 -0
  123. package/dist/handoff-state.test.d.ts +2 -0
  124. package/dist/handoff-state.test.d.ts.map +1 -0
  125. package/dist/handoff-state.test.js +102 -0
  126. package/dist/handoff-state.test.js.map +1 -0
  127. package/dist/health.d.ts +9 -0
  128. package/dist/health.d.ts.map +1 -1
  129. package/dist/health.js +18 -0
  130. package/dist/health.js.map +1 -1
  131. package/dist/host-error-correlation.d.ts +65 -0
  132. package/dist/host-error-correlation.d.ts.map +1 -0
  133. package/dist/host-error-correlation.js +123 -0
  134. package/dist/host-error-correlation.js.map +1 -0
  135. package/dist/inbox.d.ts.map +1 -1
  136. package/dist/inbox.js +4 -0
  137. package/dist/inbox.js.map +1 -1
  138. package/dist/index.js +76 -11
  139. package/dist/index.js.map +1 -1
  140. package/dist/notificationDedupeGuard.d.ts +4 -0
  141. package/dist/notificationDedupeGuard.d.ts.map +1 -1
  142. package/dist/notificationDedupeGuard.js +8 -4
  143. package/dist/notificationDedupeGuard.js.map +1 -1
  144. package/dist/presence.d.ts +37 -5
  145. package/dist/presence.d.ts.map +1 -1
  146. package/dist/presence.js +127 -16
  147. package/dist/presence.js.map +1 -1
  148. package/dist/pulse.d.ts +7 -0
  149. package/dist/pulse.d.ts.map +1 -1
  150. package/dist/pulse.js +15 -0
  151. package/dist/pulse.js.map +1 -1
  152. package/dist/review-sla.d.ts +9 -0
  153. package/dist/review-sla.d.ts.map +1 -0
  154. package/dist/review-sla.js +51 -0
  155. package/dist/review-sla.js.map +1 -0
  156. package/dist/review-state.d.ts +9 -0
  157. package/dist/review-state.d.ts.map +1 -0
  158. package/dist/review-state.js +17 -0
  159. package/dist/review-state.js.map +1 -0
  160. package/dist/routing-enforcement.test.d.ts +2 -0
  161. package/dist/routing-enforcement.test.d.ts.map +1 -0
  162. package/dist/routing-enforcement.test.js +86 -0
  163. package/dist/routing-enforcement.test.js.map +1 -0
  164. package/dist/run-retention.test.d.ts +2 -0
  165. package/dist/run-retention.test.d.ts.map +1 -0
  166. package/dist/run-retention.test.js +57 -0
  167. package/dist/run-retention.test.js.map +1 -0
  168. package/dist/run-stream.test.d.ts +2 -0
  169. package/dist/run-stream.test.d.ts.map +1 -0
  170. package/dist/run-stream.test.js +70 -0
  171. package/dist/run-stream.test.js.map +1 -0
  172. package/dist/schedule.d.ts +60 -0
  173. package/dist/schedule.d.ts.map +1 -0
  174. package/dist/schedule.js +176 -0
  175. package/dist/schedule.js.map +1 -0
  176. package/dist/server.d.ts.map +1 -1
  177. package/dist/server.js +1714 -88
  178. package/dist/server.js.map +1 -1
  179. package/dist/suppression-ledger.d.ts.map +1 -1
  180. package/dist/suppression-ledger.js +12 -3
  181. package/dist/suppression-ledger.js.map +1 -1
  182. package/dist/system-loop-state.d.ts +1 -1
  183. package/dist/system-loop-state.d.ts.map +1 -1
  184. package/dist/system-loop-state.js +1 -0
  185. package/dist/system-loop-state.js.map +1 -1
  186. package/dist/tasks.d.ts +9 -1
  187. package/dist/tasks.d.ts.map +1 -1
  188. package/dist/tasks.js +238 -41
  189. package/dist/tasks.js.map +1 -1
  190. package/dist/todoHoardingGuard.d.ts +17 -0
  191. package/dist/todoHoardingGuard.d.ts.map +1 -1
  192. package/dist/todoHoardingGuard.js +25 -2
  193. package/dist/todoHoardingGuard.js.map +1 -1
  194. package/dist/types.d.ts +1 -1
  195. package/dist/types.d.ts.map +1 -1
  196. package/dist/usage-tracking.d.ts +26 -0
  197. package/dist/usage-tracking.d.ts.map +1 -1
  198. package/dist/usage-tracking.js +91 -4
  199. package/dist/usage-tracking.js.map +1 -1
  200. package/dist/webhook-storage.d.ts +50 -0
  201. package/dist/webhook-storage.d.ts.map +1 -0
  202. package/dist/webhook-storage.js +102 -0
  203. package/dist/webhook-storage.js.map +1 -0
  204. package/dist/webhook-storage.test.d.ts +2 -0
  205. package/dist/webhook-storage.test.d.ts.map +1 -0
  206. package/dist/webhook-storage.test.js +86 -0
  207. package/dist/webhook-storage.test.js.map +1 -0
  208. package/dist/workflow-templates.d.ts +44 -0
  209. package/dist/workflow-templates.d.ts.map +1 -0
  210. package/dist/workflow-templates.js +154 -0
  211. package/dist/workflow-templates.js.map +1 -0
  212. package/dist/workflow-templates.test.d.ts +2 -0
  213. package/dist/workflow-templates.test.d.ts.map +1 -0
  214. package/dist/workflow-templates.test.js +76 -0
  215. package/dist/workflow-templates.test.js.map +1 -0
  216. package/package.json +3 -1
  217. package/public/dashboard.js +130 -37
  218. package/public/design-tokens-platform.md +118 -0
  219. package/public/design-tokens.css +195 -0
  220. package/public/docs.md +145 -2
@@ -0,0 +1,57 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { describe, it } from 'node:test';
3
+ import assert from 'node:assert/strict';
4
+ const DEFAULT_POLICY = { maxAgeDays: 30, maxCompletedRuns: 100, deleteArchived: false };
5
+ function shouldArchive(run, policy, now) {
6
+ const terminal = ['completed', 'failed', 'cancelled'].includes(run.status);
7
+ if (!terminal)
8
+ return false;
9
+ const cutoff = now - policy.maxAgeDays * 24 * 60 * 60 * 1000;
10
+ return run.startedAt < cutoff;
11
+ }
12
+ describe('run retention policy', () => {
13
+ const now = Date.now();
14
+ const day = 24 * 60 * 60 * 1000;
15
+ it('does not archive active runs', () => {
16
+ assert.equal(shouldArchive({ status: 'working', startedAt: now - 60 * day }, DEFAULT_POLICY, now), false);
17
+ assert.equal(shouldArchive({ status: 'idle', startedAt: now - 60 * day }, DEFAULT_POLICY, now), false);
18
+ assert.equal(shouldArchive({ status: 'blocked', startedAt: now - 60 * day }, DEFAULT_POLICY, now), false);
19
+ });
20
+ it('archives completed runs older than maxAgeDays', () => {
21
+ assert.equal(shouldArchive({ status: 'completed', startedAt: now - 31 * day }, DEFAULT_POLICY, now), true);
22
+ });
23
+ it('does not archive recent completed runs', () => {
24
+ assert.equal(shouldArchive({ status: 'completed', startedAt: now - 5 * day }, DEFAULT_POLICY, now), false);
25
+ });
26
+ it('archives failed runs older than maxAgeDays', () => {
27
+ assert.equal(shouldArchive({ status: 'failed', startedAt: now - 31 * day }, DEFAULT_POLICY, now), true);
28
+ });
29
+ it('archives cancelled runs older than maxAgeDays', () => {
30
+ assert.equal(shouldArchive({ status: 'cancelled', startedAt: now - 31 * day }, DEFAULT_POLICY, now), true);
31
+ });
32
+ it('respects custom maxAgeDays', () => {
33
+ const policy = { ...DEFAULT_POLICY, maxAgeDays: 7 };
34
+ assert.equal(shouldArchive({ status: 'completed', startedAt: now - 8 * day }, policy, now), true);
35
+ assert.equal(shouldArchive({ status: 'completed', startedAt: now - 5 * day }, policy, now), false);
36
+ });
37
+ it('boundary: exactly at cutoff is not archived', () => {
38
+ const cutoff = now - 30 * day;
39
+ assert.equal(shouldArchive({ status: 'completed', startedAt: cutoff }, DEFAULT_POLICY, now), false);
40
+ });
41
+ it('boundary: one ms before cutoff is archived', () => {
42
+ const cutoff = now - 30 * day;
43
+ assert.equal(shouldArchive({ status: 'completed', startedAt: cutoff - 1 }, DEFAULT_POLICY, now), true);
44
+ });
45
+ it('default policy values are sensible', () => {
46
+ assert.equal(DEFAULT_POLICY.maxAgeDays, 30);
47
+ assert.equal(DEFAULT_POLICY.maxCompletedRuns, 100);
48
+ assert.equal(DEFAULT_POLICY.deleteArchived, false);
49
+ });
50
+ it('deleteArchived flag controls hard delete vs soft archive', () => {
51
+ const soft = { ...DEFAULT_POLICY, deleteArchived: false };
52
+ const hard = { ...DEFAULT_POLICY, deleteArchived: true };
53
+ assert.equal(soft.deleteArchived, false);
54
+ assert.equal(hard.deleteArchived, true);
55
+ });
56
+ });
57
+ //# sourceMappingURL=run-retention.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-retention.test.js","sourceRoot":"","sources":["../src/run-retention.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=run-stream.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-stream.test.d.ts","sourceRoot":"","sources":["../src/run-stream.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { describe, it } from 'node:test';
3
+ import assert from 'node:assert/strict';
4
+ // Test SSE format and event filtering logic
5
+ describe('run stream SSE', () => {
6
+ it('formats snapshot event correctly', () => {
7
+ const run = { id: 'arun-1', status: 'working', agentId: 'link' };
8
+ const events = [{ id: 'aevt-1', type: 'task_started' }];
9
+ const sseData = `event: snapshot\ndata: ${JSON.stringify({ run, events })}\n\n`;
10
+ assert.ok(sseData.startsWith('event: snapshot'));
11
+ assert.ok(sseData.includes('"arun-1"'));
12
+ });
13
+ it('formats event correctly', () => {
14
+ const event = { id: 'evt-1', type: 'canvas_render', data: { agentId: 'link', state: 'thinking' } };
15
+ const sseData = `event: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`;
16
+ assert.ok(sseData.startsWith('event: canvas_render'));
17
+ assert.ok(sseData.includes('"thinking"'));
18
+ });
19
+ it('heartbeat format is valid SSE comment', () => {
20
+ const heartbeat = `:heartbeat\n\n`;
21
+ assert.ok(heartbeat.startsWith(':'));
22
+ });
23
+ it('filters events by runId', () => {
24
+ const targetRunId = 'arun-target';
25
+ const events = [
26
+ { data: { runId: 'arun-target', agentId: 'link' } },
27
+ { data: { runId: 'arun-other', agentId: 'pixel' } },
28
+ { data: { runId: 'arun-target', agentId: 'link' } },
29
+ ];
30
+ const matched = events.filter(e => e.data.runId === targetRunId);
31
+ assert.equal(matched.length, 2);
32
+ });
33
+ it('filters events by agentId', () => {
34
+ const targetAgent = 'link';
35
+ const events = [
36
+ { data: { agentId: 'link' } },
37
+ { data: { agentId: 'pixel' } },
38
+ { data: { agentId: 'link' } },
39
+ { data: { agentId: 'kai' } },
40
+ ];
41
+ const matched = events.filter(e => e.data.agentId === targetAgent);
42
+ assert.equal(matched.length, 2);
43
+ });
44
+ it('snapshot includes both run state and recent events', () => {
45
+ const snapshot = {
46
+ run: { id: 'arun-1', status: 'working', objective: 'Build API' },
47
+ events: [
48
+ { id: 'aevt-1', type: 'run_started' },
49
+ { id: 'aevt-2', type: 'task_completed' },
50
+ ],
51
+ };
52
+ assert.ok(snapshot.run);
53
+ assert.equal(snapshot.events.length, 2);
54
+ assert.equal(snapshot.run.status, 'working');
55
+ });
56
+ it('agent stream includes active run and events', () => {
57
+ const snapshot = {
58
+ activeRun: { id: 'arun-1', status: 'working' },
59
+ events: [{ id: 'aevt-1' }],
60
+ };
61
+ assert.ok(snapshot.activeRun);
62
+ assert.equal(snapshot.events.length, 1);
63
+ });
64
+ it('agent stream handles null active run', () => {
65
+ const snapshot = { activeRun: null, events: [] };
66
+ assert.equal(snapshot.activeRun, null);
67
+ assert.equal(snapshot.events.length, 0);
68
+ });
69
+ });
70
+ //# sourceMappingURL=run-stream.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-stream.test.js","sourceRoot":"","sources":["../src/run-stream.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ export type ScheduleKind = 'deploy_window' | 'focus_block' | 'scheduled_task';
2
+ export interface ScheduleEntry {
3
+ id: string;
4
+ kind: ScheduleKind;
5
+ title: string;
6
+ /** Epoch ms — start of window */
7
+ start: number;
8
+ /** Epoch ms — end of window */
9
+ end: number;
10
+ /** Agent or team identifier that owns / created this entry */
11
+ owner: string;
12
+ /** Optional task ID for scheduled_task entries */
13
+ task_id: string | null;
14
+ /** deploy_window: 'open'|'closed'; focus_block: 'active'; scheduled_task: 'pending'|'done' */
15
+ status: string;
16
+ /** Free-form metadata (JSON string) */
17
+ meta: string | null;
18
+ created_at: number;
19
+ updated_at: number;
20
+ }
21
+ export interface CreateScheduleEntryInput {
22
+ kind: ScheduleKind;
23
+ title: string;
24
+ start: number;
25
+ end: number;
26
+ owner: string;
27
+ task_id?: string | null;
28
+ status?: string;
29
+ meta?: Record<string, unknown>;
30
+ }
31
+ export interface UpdateScheduleEntryInput {
32
+ title?: string;
33
+ start?: number;
34
+ end?: number;
35
+ status?: string;
36
+ meta?: Record<string, unknown>;
37
+ }
38
+ export interface ScheduleFeedOptions {
39
+ /** Only return entries starting/ending after this epoch ms (default: now) */
40
+ after?: number;
41
+ /** Only return entries starting before this epoch ms */
42
+ before?: number;
43
+ /** Filter by kind(s) */
44
+ kinds?: ScheduleKind[];
45
+ /** Filter by owner */
46
+ owner?: string;
47
+ /** Max entries to return (default: 50) */
48
+ limit?: number;
49
+ }
50
+ export declare function createScheduleEntry(input: CreateScheduleEntryInput): ScheduleEntry;
51
+ export declare function getScheduleEntry(id: string): ScheduleEntry | null;
52
+ export declare function updateScheduleEntry(id: string, input: UpdateScheduleEntryInput): ScheduleEntry | null;
53
+ export declare function deleteScheduleEntry(id: string): boolean;
54
+ /**
55
+ * Returns upcoming schedule entries in chronological order.
56
+ * Default: all entries ending after now, ordered by start asc.
57
+ */
58
+ export declare function getScheduleFeed(options?: ScheduleFeedOptions): ScheduleEntry[];
59
+ export declare function _resetScheduleStore(): void;
60
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,aAAa,GAAG,gBAAgB,CAAA;AAE7E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,8FAA8F;IAC9F,MAAM,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wBAAwB;IACxB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAA;IACtB,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AA+CD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,aAAa,CAsClF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIjE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB,GAAG,aAAa,GAAG,IAAI,CA0BrG;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKvD;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa,EAAE,CAqClF;AAID,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
@@ -0,0 +1,176 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) Reflectt AI
3
+ /**
4
+ * Schedule — Shared time-awareness feed for the team
5
+ *
6
+ * Provides canonical records for team-wide scheduling primitives:
7
+ * - deploy_window: when deploys are safe/unsafe
8
+ * - focus_block: team-wide quiet periods (low interruptions)
9
+ * - scheduled_task: task work scheduled for a specific time window
10
+ *
11
+ * Intentionally NOT in scope (MVP):
12
+ * - No full calendar UI
13
+ * - No iCal/RRULE integration (use calendar.ts for per-agent recurring blocks)
14
+ * - No reminder/notification engine (use calendar-reminder-engine.ts)
15
+ * - No per-agent availability (use calendar.ts + getAvailability())
16
+ * - No recurring rules — one-off windows only in v1
17
+ *
18
+ * The /schedule/feed endpoint returns upcoming items chronologically so agents
19
+ * can read shared timing data instead of coordinating via chat.
20
+ */
21
+ import { getDb } from './db.js';
22
+ // ── Valid values ───────────────────────────────────────────────────────────
23
+ const VALID_KINDS = ['deploy_window', 'focus_block', 'scheduled_task'];
24
+ const DEFAULT_STATUS = {
25
+ deploy_window: 'open',
26
+ focus_block: 'active',
27
+ scheduled_task: 'pending',
28
+ };
29
+ // ── Database setup ─────────────────────────────────────────────────────────
30
+ let initialized = false;
31
+ function ensureTable() {
32
+ if (initialized)
33
+ return;
34
+ const db = getDb();
35
+ db.exec(`
36
+ CREATE TABLE IF NOT EXISTS schedule_entries (
37
+ id TEXT PRIMARY KEY,
38
+ kind TEXT NOT NULL CHECK(kind IN ('deploy_window', 'focus_block', 'scheduled_task')),
39
+ title TEXT NOT NULL,
40
+ start INTEGER NOT NULL,
41
+ end INTEGER NOT NULL,
42
+ owner TEXT NOT NULL,
43
+ task_id TEXT,
44
+ status TEXT NOT NULL DEFAULT 'open',
45
+ meta TEXT,
46
+ created_at INTEGER NOT NULL,
47
+ updated_at INTEGER NOT NULL
48
+ )
49
+ `);
50
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_schedule_start ON schedule_entries(start)`);
51
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_schedule_kind ON schedule_entries(kind)`);
52
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_schedule_owner ON schedule_entries(owner)`);
53
+ initialized = true;
54
+ }
55
+ // ── CRUD ───────────────────────────────────────────────────────────────────
56
+ function generateId(kind) {
57
+ const prefix = kind === 'deploy_window' ? 'dw' : kind === 'focus_block' ? 'fb' : 'st';
58
+ return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
59
+ }
60
+ export function createScheduleEntry(input) {
61
+ ensureTable();
62
+ const db = getDb();
63
+ const now = Date.now();
64
+ if (!VALID_KINDS.includes(input.kind)) {
65
+ throw new Error(`kind must be one of: ${VALID_KINDS.join(', ')}`);
66
+ }
67
+ if (!input.title?.trim())
68
+ throw new Error('title is required');
69
+ if (typeof input.start !== 'number' || isNaN(input.start))
70
+ throw new Error('start must be epoch ms');
71
+ if (typeof input.end !== 'number' || isNaN(input.end))
72
+ throw new Error('end must be epoch ms');
73
+ if (input.end <= input.start)
74
+ throw new Error('end must be after start');
75
+ if (!input.owner?.trim())
76
+ throw new Error('owner is required');
77
+ const entry = {
78
+ id: generateId(input.kind),
79
+ kind: input.kind,
80
+ title: input.title.trim(),
81
+ start: input.start,
82
+ end: input.end,
83
+ owner: input.owner.trim(),
84
+ task_id: input.task_id ?? null,
85
+ status: input.status ?? DEFAULT_STATUS[input.kind],
86
+ meta: input.meta ? JSON.stringify(input.meta) : null,
87
+ created_at: now,
88
+ updated_at: now,
89
+ };
90
+ db.prepare(`
91
+ INSERT INTO schedule_entries (id, kind, title, start, end, owner, task_id, status, meta, created_at, updated_at)
92
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
93
+ `).run(entry.id, entry.kind, entry.title, entry.start, entry.end, entry.owner, entry.task_id, entry.status, entry.meta, entry.created_at, entry.updated_at);
94
+ return entry;
95
+ }
96
+ export function getScheduleEntry(id) {
97
+ ensureTable();
98
+ const db = getDb();
99
+ return db.prepare('SELECT * FROM schedule_entries WHERE id = ?').get(id) ?? null;
100
+ }
101
+ export function updateScheduleEntry(id, input) {
102
+ ensureTable();
103
+ const db = getDb();
104
+ const existing = getScheduleEntry(id);
105
+ if (!existing)
106
+ return null;
107
+ const now = Date.now();
108
+ const updated = {
109
+ ...existing,
110
+ title: input.title?.trim() ?? existing.title,
111
+ start: input.start ?? existing.start,
112
+ end: input.end ?? existing.end,
113
+ status: input.status ?? existing.status,
114
+ meta: input.meta ? JSON.stringify(input.meta) : existing.meta,
115
+ updated_at: now,
116
+ };
117
+ if (updated.end <= updated.start)
118
+ throw new Error('end must be after start');
119
+ db.prepare(`
120
+ UPDATE schedule_entries
121
+ SET title = ?, start = ?, end = ?, status = ?, meta = ?, updated_at = ?
122
+ WHERE id = ?
123
+ `).run(updated.title, updated.start, updated.end, updated.status, updated.meta, now, id);
124
+ return updated;
125
+ }
126
+ export function deleteScheduleEntry(id) {
127
+ ensureTable();
128
+ const db = getDb();
129
+ const result = db.prepare('DELETE FROM schedule_entries WHERE id = ?').run(id);
130
+ return result.changes > 0;
131
+ }
132
+ // ── Feed query ─────────────────────────────────────────────────────────────
133
+ /**
134
+ * Returns upcoming schedule entries in chronological order.
135
+ * Default: all entries ending after now, ordered by start asc.
136
+ */
137
+ export function getScheduleFeed(options = {}) {
138
+ ensureTable();
139
+ const db = getDb();
140
+ const now = Date.now();
141
+ const after = options.after ?? now;
142
+ const before = options.before;
143
+ const limit = Math.min(options.limit ?? 50, 200);
144
+ const conditions = ['end > ?'];
145
+ const params = [after];
146
+ if (before !== undefined) {
147
+ conditions.push('start < ?');
148
+ params.push(before);
149
+ }
150
+ if (options.kinds?.length) {
151
+ conditions.push(`kind IN (${options.kinds.map(() => '?').join(', ')})`);
152
+ params.push(...options.kinds);
153
+ }
154
+ if (options.owner) {
155
+ conditions.push('owner = ?');
156
+ params.push(options.owner);
157
+ }
158
+ params.push(limit);
159
+ const rows = db.prepare(`
160
+ SELECT * FROM schedule_entries
161
+ WHERE ${conditions.join(' AND ')}
162
+ ORDER BY start ASC
163
+ LIMIT ?
164
+ `).all(...params);
165
+ return rows;
166
+ }
167
+ // ── Test reset ─────────────────────────────────────────────────────────────
168
+ export function _resetScheduleStore() {
169
+ initialized = false;
170
+ try {
171
+ const db = getDb();
172
+ db.exec('DELETE FROM schedule_entries');
173
+ }
174
+ catch { /* ok in tests */ }
175
+ }
176
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAA;AAutD9D,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CAq7V7D"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAA;AA63D9D,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CA0/Y7D"}