pi-harness-runtime 0.9.15 → 0.9.17

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 (101) hide show
  1. package/package.json +1 -1
  2. package/packages/autonomous-runtime/README.md +48 -0
  3. package/packages/autonomous-runtime/dist/inbox.d.ts +75 -0
  4. package/packages/autonomous-runtime/dist/inbox.d.ts.map +1 -0
  5. package/packages/autonomous-runtime/dist/inbox.js +212 -0
  6. package/packages/autonomous-runtime/dist/inbox.js.map +1 -0
  7. package/packages/autonomous-runtime/dist/index.d.ts +17 -0
  8. package/packages/autonomous-runtime/dist/index.d.ts.map +1 -0
  9. package/packages/autonomous-runtime/dist/index.js +17 -0
  10. package/packages/autonomous-runtime/dist/index.js.map +1 -0
  11. package/packages/autonomous-runtime/dist/lease.d.ts +78 -0
  12. package/packages/autonomous-runtime/dist/lease.d.ts.map +1 -0
  13. package/packages/autonomous-runtime/dist/lease.js +273 -0
  14. package/packages/autonomous-runtime/dist/lease.js.map +1 -0
  15. package/packages/autonomous-runtime/dist/types.d.ts +160 -0
  16. package/packages/autonomous-runtime/dist/types.d.ts.map +1 -0
  17. package/packages/autonomous-runtime/dist/types.js +31 -0
  18. package/packages/autonomous-runtime/dist/types.js.map +1 -0
  19. package/packages/autonomous-runtime/dist/worker.d.ts +63 -0
  20. package/packages/autonomous-runtime/dist/worker.d.ts.map +1 -0
  21. package/packages/autonomous-runtime/dist/worker.js +133 -0
  22. package/packages/autonomous-runtime/dist/worker.js.map +1 -0
  23. package/packages/autonomous-runtime/package.json +34 -0
  24. package/packages/autonomous-runtime/src/inbox.ts +266 -0
  25. package/packages/autonomous-runtime/src/index.ts +22 -0
  26. package/packages/autonomous-runtime/src/lease.ts +318 -0
  27. package/packages/autonomous-runtime/src/types.ts +257 -0
  28. package/packages/autonomous-runtime/test/autonomous-runtime.test.ts +194 -0
  29. package/packages/autonomous-runtime/test/inbox.test.mjs +266 -0
  30. package/packages/autonomous-runtime/test/inbox.test.ts +80 -0
  31. package/packages/autonomous-runtime/test/types.test.ts +68 -0
  32. package/packages/autonomous-runtime/tsconfig.json +22 -0
  33. package/packages/autonomous-runtime/tsconfig.tsbuildinfo +1 -0
  34. package/packages/privilege-broker/README.md +45 -0
  35. package/packages/privilege-broker/config/privileges.yaml.example +172 -0
  36. package/packages/privilege-broker/dist/approval.d.ts +23 -0
  37. package/packages/privilege-broker/dist/approval.d.ts.map +1 -0
  38. package/packages/privilege-broker/dist/approval.js +45 -0
  39. package/packages/privilege-broker/dist/approval.js.map +1 -0
  40. package/packages/privilege-broker/dist/audit.d.ts +38 -0
  41. package/packages/privilege-broker/dist/audit.d.ts.map +1 -0
  42. package/packages/privilege-broker/dist/audit.js +125 -0
  43. package/packages/privilege-broker/dist/audit.js.map +1 -0
  44. package/packages/privilege-broker/dist/executor.d.ts +25 -0
  45. package/packages/privilege-broker/dist/executor.d.ts.map +1 -0
  46. package/packages/privilege-broker/dist/executor.js +83 -0
  47. package/packages/privilege-broker/dist/executor.js.map +1 -0
  48. package/packages/privilege-broker/dist/index.d.ts +30 -0
  49. package/packages/privilege-broker/dist/index.d.ts.map +1 -0
  50. package/packages/privilege-broker/dist/index.js +5 -0
  51. package/packages/privilege-broker/dist/index.js.map +1 -0
  52. package/packages/privilege-broker/dist/registry.d.ts +15 -0
  53. package/packages/privilege-broker/dist/registry.d.ts.map +1 -0
  54. package/packages/privilege-broker/dist/registry.js +76 -0
  55. package/packages/privilege-broker/dist/registry.js.map +1 -0
  56. package/packages/privilege-broker/dist/types.d.ts +77 -0
  57. package/packages/privilege-broker/dist/types.d.ts.map +1 -0
  58. package/packages/privilege-broker/dist/types.js +11 -0
  59. package/packages/privilege-broker/dist/types.js.map +1 -0
  60. package/packages/privilege-broker/package.json +35 -0
  61. package/packages/privilege-broker/src/approval.ts +70 -0
  62. package/packages/privilege-broker/src/audit.ts +142 -0
  63. package/packages/privilege-broker/src/executor.ts +110 -0
  64. package/packages/privilege-broker/src/index.ts +46 -0
  65. package/packages/privilege-broker/src/registry.ts +98 -0
  66. package/packages/privilege-broker/src/types.ts +105 -0
  67. package/packages/privilege-broker/tsconfig.json +22 -0
  68. package/packages/privilege-broker/tsconfig.tsbuildinfo +1 -0
  69. package/packages/scheduler-adapter/README.md +36 -0
  70. package/packages/scheduler-adapter/dist/cron.d.ts +21 -0
  71. package/packages/scheduler-adapter/dist/cron.d.ts.map +1 -0
  72. package/packages/scheduler-adapter/dist/cron.js +116 -0
  73. package/packages/scheduler-adapter/dist/cron.js.map +1 -0
  74. package/packages/scheduler-adapter/dist/index.d.ts +9 -0
  75. package/packages/scheduler-adapter/dist/index.d.ts.map +1 -0
  76. package/packages/scheduler-adapter/dist/index.js +8 -0
  77. package/packages/scheduler-adapter/dist/index.js.map +1 -0
  78. package/packages/scheduler-adapter/dist/interface.d.ts +61 -0
  79. package/packages/scheduler-adapter/dist/interface.d.ts.map +1 -0
  80. package/packages/scheduler-adapter/dist/interface.js +2 -0
  81. package/packages/scheduler-adapter/dist/interface.js.map +1 -0
  82. package/packages/scheduler-adapter/dist/internal.d.ts +30 -0
  83. package/packages/scheduler-adapter/dist/internal.d.ts.map +1 -0
  84. package/packages/scheduler-adapter/dist/internal.js +82 -0
  85. package/packages/scheduler-adapter/dist/internal.js.map +1 -0
  86. package/packages/scheduler-adapter/dist/systemd.d.ts +31 -0
  87. package/packages/scheduler-adapter/dist/systemd.d.ts.map +1 -0
  88. package/packages/scheduler-adapter/dist/systemd.js +203 -0
  89. package/packages/scheduler-adapter/dist/systemd.js.map +1 -0
  90. package/packages/scheduler-adapter/package.json +32 -0
  91. package/packages/scheduler-adapter/src/cron.ts +123 -0
  92. package/packages/scheduler-adapter/src/index.ts +9 -0
  93. package/packages/scheduler-adapter/src/interface.ts +61 -0
  94. package/packages/scheduler-adapter/src/internal.ts +99 -0
  95. package/packages/scheduler-adapter/src/systemd.ts +221 -0
  96. package/packages/scheduler-adapter/tsconfig.json +22 -0
  97. package/packages/scheduler-adapter/tsconfig.tsbuildinfo +1 -0
  98. package/packages/types/dist/ai-providers.d.ts +0 -36
  99. package/packages/types/dist/ai-providers.d.ts.map +0 -1
  100. package/packages/types/dist/ai-providers.js +0 -66
  101. package/packages/types/dist/ai-providers.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "0.9.15",
3
+ "version": "0.9.17",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -0,0 +1,48 @@
1
+ # Autonomous Runtime — RFC-0101
2
+
3
+ Task Inbox, Task Lease, and worker supervision for autonomous post-session execution.
4
+
5
+ ## Package
6
+
7
+ `@pi-harness/autonomous-runtime`
8
+
9
+ ## Concepts
10
+
11
+ ### Task Inbox
12
+
13
+ Durable queue of tasks submitted by the harness master planner. Survives worker crashes, host reboots, and provider quota exhaustion.
14
+
15
+ ### Task Lease
16
+
17
+ Atomic exclusive claim on a task. Guarantees **single-execution** under crash recovery. Other workers skip a leased task.
18
+
19
+ ### Worker
20
+
21
+ Supervised process that reads from the inbox, claims tasks via leases, executes, and reports results.
22
+
23
+ ## Usage
24
+
25
+ ```ts
26
+ import { TaskInbox, TaskLeaseManager, WORKER_ROOT } from "@pi-harness/autonomous-runtime";
27
+
28
+ const inbox = new TaskInbox();
29
+ const leaseMgr = new TaskLeaseManager();
30
+
31
+ // Submit a task
32
+ await inbox.submit({
33
+ title: "Fix login bug",
34
+ description: "Users cannot log in with SSO",
35
+ capability: "write",
36
+ });
37
+
38
+ // Worker: claim and work
39
+ const task = await inbox.claimNext("worker-1", leaseMgr);
40
+ if (task) {
41
+ // ... do work ...
42
+ await inbox.complete(task.id, { success: true });
43
+ }
44
+ ```
45
+
46
+ ## Status
47
+
48
+ **Phase 1 done.** Phases 2–10 pending implementation.
@@ -0,0 +1,75 @@
1
+ import type { TaskRecord, TaskStatus, TaskEvent } from "./types.js";
2
+ export declare class InboxError extends Error {
3
+ constructor(msg: string);
4
+ }
5
+ /**
6
+ * Manages the append-only task inbox at `~/.pi/harness/inbox/tasks.jsonl`.
7
+ *
8
+ * Storage layout:
9
+ * ```
10
+ * ~/.pi/harness/inbox/
11
+ * ├── tasks.jsonl # append-only log (one JSON line per task)
12
+ * ├── claimed/ # active leases (one JSON file per task)
13
+ * └── BACKLOG.md # human-friendly authoring surface (optional)
14
+ * ```
15
+ *
16
+ * Operations are:
17
+ * - **append** — append a new task to tasks.jsonl
18
+ * - **list** — read all tasks, filterable by status
19
+ * - **transition** — update a task's status in-place (rewrite)
20
+ * - **get** — read one task by id
21
+ * - **reindex** — compact tasks.jsonl by rewriting it from in-memory state
22
+ */
23
+ export declare class TaskInbox {
24
+ private readonly tasksPath;
25
+ private readonly inboxDir;
26
+ private _cache;
27
+ constructor(options?: {
28
+ tasksPath?: string;
29
+ inboxDir?: string;
30
+ });
31
+ /** Ensure the inbox directory exists. Call before any write. */
32
+ ensureDir(): void;
33
+ /**
34
+ * Append a new task to tasks.jsonl.
35
+ * The task is validated before writing. Duplicate ids are rejected.
36
+ *
37
+ * @throws {InboxError} if the task id already exists or validation fails
38
+ */
39
+ append(task: TaskRecord): void;
40
+ /**
41
+ * Read all tasks from tasks.jsonl.
42
+ * Results are sorted by priority ASC then createdAt ASC (oldest first).
43
+ *
44
+ * @param filter Optionally filter by status. If omitted, returns all.
45
+ */
46
+ list(filter?: {
47
+ status?: TaskStatus | TaskStatus[];
48
+ }): TaskRecord[];
49
+ /** Retrieve a single task by id, or null if not found. */
50
+ get(id: string): TaskRecord | null;
51
+ /**
52
+ * Update a task's status in-place inside tasks.jsonl.
53
+ *
54
+ * Uses read→parse→update→rewrite to avoid corrupting the JSONL file.
55
+ * The rewrite is atomic (write-tmp-then-rename).
56
+ *
57
+ * @param taskId The id of the task to transition
58
+ * @param newStatus The target status
59
+ * @param extra Optional additional fields to merge into the task record
60
+ * @param event Optional TaskEvent to append to the history
61
+ * @throws {InboxError} if the task does not exist
62
+ */
63
+ transition(taskId: string, newStatus: TaskStatus, extra?: Partial<TaskRecord>, event?: TaskEvent): TaskRecord;
64
+ /** Convenience: mark a task as completed with a result. */
65
+ complete(taskId: string, result: TaskRecord["result"]): TaskRecord;
66
+ /** Convenience: mark a task as failed with a reason. */
67
+ fail(taskId: string, reason: string): TaskRecord;
68
+ /** Rewrite tasks.jsonl from the given task list. */
69
+ private _rewriteAll;
70
+ /** Force a full reindex. Call after manual edits to tasks.jsonl. */
71
+ reindex(): void;
72
+ /** Return counts of tasks grouped by status. */
73
+ stats(): Record<TaskStatus, number>;
74
+ }
75
+ //# sourceMappingURL=inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKpE,qBAAa,UAAW,SAAQ,KAAK;IACpC,YAAY,GAAG,EAAE,MAAM,EAGtB;CACD;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,MAAM,CAA6B;IAE3C,YAAY,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,EAGlE;IAED,gEAAgE;IAChE,SAAS,IAAI,IAAI,CAIhB;IAID;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAc7B;IAID;;;;;OAKG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CAAA;KAAE,GAAG,UAAU,EAAE,CAoClE;IAID,0DAA0D;IAC1D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGjC;IAID;;;;;;;;;;;OAWG;IACH,UAAU,CACT,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,UAAU,EACrB,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAC3B,KAAK,CAAC,EAAE,SAAS,GACf,UAAU,CAqCZ;IAID,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,UAAU,CAWjE;IAED,wDAAwD;IACxD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAe/C;IAID,oDAAoD;IACpD,OAAO,CAAC,WAAW;IAUnB,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAKd;IAID,gDAAgD;IAChD,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAOlC;CACD"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Task Inbox — RFC-0101 §2
3
+ *
4
+ * Append-only durable store for TaskRecords backed by `tasks.jsonl`.
5
+ * One JSONL line per task — easy to tail, grep, and replay.
6
+ */
7
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
8
+ import { getInboxDir, getTasksPath } from "./types.js";
9
+ // ─── Errors ───────────────────────────────────────────────────────────────────
10
+ export class InboxError extends Error {
11
+ constructor(msg) {
12
+ super(`[InboxError] ${msg}`);
13
+ this.name = "InboxError";
14
+ }
15
+ }
16
+ // ─── TaskInbox ────────────────────────────────────────────────────────────────
17
+ /**
18
+ * Manages the append-only task inbox at `~/.pi/harness/inbox/tasks.jsonl`.
19
+ *
20
+ * Storage layout:
21
+ * ```
22
+ * ~/.pi/harness/inbox/
23
+ * ├── tasks.jsonl # append-only log (one JSON line per task)
24
+ * ├── claimed/ # active leases (one JSON file per task)
25
+ * └── BACKLOG.md # human-friendly authoring surface (optional)
26
+ * ```
27
+ *
28
+ * Operations are:
29
+ * - **append** — append a new task to tasks.jsonl
30
+ * - **list** — read all tasks, filterable by status
31
+ * - **transition** — update a task's status in-place (rewrite)
32
+ * - **get** — read one task by id
33
+ * - **reindex** — compact tasks.jsonl by rewriting it from in-memory state
34
+ */
35
+ export class TaskInbox {
36
+ tasksPath;
37
+ inboxDir;
38
+ _cache = null;
39
+ constructor(options = {}) {
40
+ this.inboxDir = options.inboxDir ?? getInboxDir();
41
+ this.tasksPath = options.tasksPath ?? getTasksPath();
42
+ }
43
+ /** Ensure the inbox directory exists. Call before any write. */
44
+ ensureDir() {
45
+ if (!existsSync(this.inboxDir)) {
46
+ mkdirSync(this.inboxDir, { recursive: true });
47
+ }
48
+ }
49
+ // ─── append ──────────────────────────────────────────────────────────────
50
+ /**
51
+ * Append a new task to tasks.jsonl.
52
+ * The task is validated before writing. Duplicate ids are rejected.
53
+ *
54
+ * @throws {InboxError} if the task id already exists or validation fails
55
+ */
56
+ append(task) {
57
+ this.ensureDir();
58
+ // Guard against duplicate ids
59
+ const existing = this.list().find((t) => t.id === task.id);
60
+ if (existing) {
61
+ throw new InboxError(`Task ${task.id} already exists in inbox (status=${existing.status})`);
62
+ }
63
+ const line = JSON.stringify(task) + "\n";
64
+ appendFileSync(this.tasksPath, line, "utf8");
65
+ this._cache = null; // invalidate
66
+ }
67
+ // ─── list ─────────────────────────────────────────────────────────────────
68
+ /**
69
+ * Read all tasks from tasks.jsonl.
70
+ * Results are sorted by priority ASC then createdAt ASC (oldest first).
71
+ *
72
+ * @param filter Optionally filter by status. If omitted, returns all.
73
+ */
74
+ list(filter) {
75
+ if (!existsSync(this.tasksPath)) {
76
+ return [];
77
+ }
78
+ const raw = readFileSync(this.tasksPath, "utf8");
79
+ const tasks = [];
80
+ for (const line of raw.split("\n")) {
81
+ const trimmed = line.trim();
82
+ if (!trimmed)
83
+ continue;
84
+ try {
85
+ const task = JSON.parse(trimmed);
86
+ tasks.push(task);
87
+ }
88
+ catch {
89
+ // Corrupt line — skip but don't fail the whole list
90
+ console.warn(`[TaskInbox] Skipping corrupt line in ${this.tasksPath}`);
91
+ }
92
+ }
93
+ // Filter by status
94
+ let filtered = tasks;
95
+ if (filter?.status !== undefined) {
96
+ const statuses = Array.isArray(filter.status)
97
+ ? filter.status
98
+ : [filter.status];
99
+ filtered = tasks.filter((t) => statuses.includes(t.status));
100
+ }
101
+ // Sort: priority ASC, then createdAt ASC
102
+ filtered.sort((a, b) => {
103
+ if (a.priority !== b.priority)
104
+ return a.priority - b.priority;
105
+ return a.createdAt.localeCompare(b.createdAt);
106
+ });
107
+ return filtered;
108
+ }
109
+ // ─── get ─────────────────────────────────────────────────────────────────
110
+ /** Retrieve a single task by id, or null if not found. */
111
+ get(id) {
112
+ const tasks = this.list();
113
+ return tasks.find((t) => t.id === id) ?? null;
114
+ }
115
+ // ─── transition ──────────────────────────────────────────────────────────
116
+ /**
117
+ * Update a task's status in-place inside tasks.jsonl.
118
+ *
119
+ * Uses read→parse→update→rewrite to avoid corrupting the JSONL file.
120
+ * The rewrite is atomic (write-tmp-then-rename).
121
+ *
122
+ * @param taskId The id of the task to transition
123
+ * @param newStatus The target status
124
+ * @param extra Optional additional fields to merge into the task record
125
+ * @param event Optional TaskEvent to append to the history
126
+ * @throws {InboxError} if the task does not exist
127
+ */
128
+ transition(taskId, newStatus, extra, event) {
129
+ if (!existsSync(this.tasksPath)) {
130
+ throw new InboxError(`tasks.jsonl does not exist at ${this.tasksPath}`);
131
+ }
132
+ const tasks = this.list();
133
+ const idx = tasks.findIndex((t) => t.id === taskId);
134
+ if (idx === -1) {
135
+ throw new InboxError(`Task ${taskId} not found in inbox`);
136
+ }
137
+ const updated = {
138
+ ...tasks[idx],
139
+ ...extra,
140
+ status: newStatus,
141
+ updatedAt: new Date().toISOString(),
142
+ history: event
143
+ ? [...tasks[idx].history, event]
144
+ : [
145
+ ...tasks[idx].history,
146
+ {
147
+ ts: new Date().toISOString(),
148
+ kind: "transitioned",
149
+ payload: { from: tasks[idx].status, to: newStatus },
150
+ },
151
+ ],
152
+ };
153
+ // Rewrite tasks.jsonl atomically
154
+ this._rewriteAll([
155
+ ...tasks.slice(0, idx),
156
+ updated,
157
+ ...tasks.slice(idx + 1),
158
+ ]);
159
+ this._cache = null;
160
+ return updated;
161
+ }
162
+ // ─── markDone / markFailed ───────────────────────────────────────────────
163
+ /** Convenience: mark a task as completed with a result. */
164
+ complete(taskId, result) {
165
+ return this.transition(taskId, "completed", { result }, {
166
+ ts: new Date().toISOString(),
167
+ kind: "completed",
168
+ payload: { result },
169
+ });
170
+ }
171
+ /** Convenience: mark a task as failed with a reason. */
172
+ fail(taskId, reason) {
173
+ const task = this.get(taskId);
174
+ const attempts = (task?.attempts ?? 0) + 1;
175
+ const newStatus = attempts >= (task?.maxAttempts ?? 3) ? "dead_letter" : "retrying";
176
+ return this.transition(taskId, newStatus, { failureReason: reason, attempts }, {
177
+ ts: new Date().toISOString(),
178
+ kind: newStatus === "dead_letter" ? "dead_lettered" : "failed",
179
+ payload: { reason, attempts },
180
+ });
181
+ }
182
+ // ─── reindex ─────────────────────────────────────────────────────────────
183
+ /** Rewrite tasks.jsonl from the given task list. */
184
+ _rewriteAll(tasks) {
185
+ const tmp = `${this.tasksPath}.tmp`;
186
+ const content = tasks.map((t) => JSON.stringify(t)).join("\n") + "\n";
187
+ writeFileSync(tmp, content, "utf8");
188
+ // Atomic rename (POSIX guarantees atomicity)
189
+ // Bun/Node will use the native rename which is atomic on POSIX
190
+ const { renameSync } = require("node:fs");
191
+ renameSync(tmp, this.tasksPath);
192
+ }
193
+ /** Force a full reindex. Call after manual edits to tasks.jsonl. */
194
+ reindex() {
195
+ if (!existsSync(this.tasksPath))
196
+ return;
197
+ const tasks = this.list(); // reads and validates
198
+ this._rewriteAll(tasks);
199
+ this._cache = null;
200
+ }
201
+ // ─── count ───────────────────────────────────────────────────────────────
202
+ /** Return counts of tasks grouped by status. */
203
+ stats() {
204
+ const tasks = this.list();
205
+ const counts = {};
206
+ for (const t of tasks) {
207
+ counts[t.status] = (counts[t.status] ?? 0) + 1;
208
+ }
209
+ return counts;
210
+ }
211
+ }
212
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Autonomous Operations Runtime — Public API
3
+ *
4
+ * Phase 1 exports (RFC-0101 §1-2):
5
+ * - TaskRecord, TaskLease, TaskEvent, TaskStatus, CapabilityName, ApprovalClass types
6
+ * - TaskInbox: append, list, get, transition, complete, fail
7
+ * - LeaseManager: claim, heartbeat, release, reap, recoverOnStartup
8
+ *
9
+ * Phase 2+ exports (added as implemented):
10
+ * - Worker lifecycle (worker.ts)
11
+ * - Privilege broker (privilege-broker package)
12
+ * - Scheduler adapter (scheduler-adapter package)
13
+ */
14
+ export * from "./types.js";
15
+ export { TaskInbox, InboxError } from "./inbox.js";
16
+ export { LeaseManager, LeaseError, DEFAULT_LEASE_TTL_MS, HEARTBEAT_INTERVAL_MS, HEARTBEAT_EXTENSION_MS, } from "./lease.js";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EACN,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Autonomous Operations Runtime — Public API
3
+ *
4
+ * Phase 1 exports (RFC-0101 §1-2):
5
+ * - TaskRecord, TaskLease, TaskEvent, TaskStatus, CapabilityName, ApprovalClass types
6
+ * - TaskInbox: append, list, get, transition, complete, fail
7
+ * - LeaseManager: claim, heartbeat, release, reap, recoverOnStartup
8
+ *
9
+ * Phase 2+ exports (added as implemented):
10
+ * - Worker lifecycle (worker.ts)
11
+ * - Privilege broker (privilege-broker package)
12
+ * - Scheduler adapter (scheduler-adapter package)
13
+ */
14
+ export * from "./types.js";
15
+ export { TaskInbox, InboxError } from "./inbox.js";
16
+ export { LeaseManager, LeaseError, DEFAULT_LEASE_TTL_MS, HEARTBEAT_INTERVAL_MS, HEARTBEAT_EXTENSION_MS, } from "./lease.js";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EACN,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,78 @@
1
+ import type { TaskLease } from "./types.js";
2
+ export declare class LeaseError extends Error {
3
+ constructor(msg: string);
4
+ }
5
+ /** Default lease duration before heartbeat extension is required. */
6
+ export declare const DEFAULT_LEASE_TTL_MS = 30000;
7
+ /** Heartbeat interval sent by the worker. */
8
+ export declare const HEARTBEAT_INTERVAL_MS = 5000;
9
+ /** Default worker heartbeat interval extension. */
10
+ export declare const HEARTBEAT_EXTENSION_MS = 30000;
11
+ export interface LeaseOptions {
12
+ leasesDir?: string;
13
+ /** TTL in ms for new leases. Default: DEFAULT_LEASE_TTL_MS */
14
+ leaseTtlMs?: number;
15
+ }
16
+ /**
17
+ * Manages task leases on disk using atomic write-tmp-then-rename.
18
+ */
19
+ export declare class LeaseManager {
20
+ private readonly leasesDir;
21
+ private readonly leaseTtlMs;
22
+ constructor(options?: LeaseOptions);
23
+ /** Ensure the claimed/ directory exists. */
24
+ ensureDir(): void;
25
+ /**
26
+ * Atomically claim a task for a worker.
27
+ *
28
+ * Algorithm:
29
+ * 1. Write lease to a temp file in the same directory (same filesystem → fast rename)
30
+ * 2. Attempt atomic rename to `claimed/<taskId>.lease.json`
31
+ * 3. If rename fails (EEXIST) → another worker won → return null
32
+ *
33
+ * @param taskId The task to claim
34
+ * @param workerId The worker claiming it
35
+ * @param attempt Which attempt number (for retry)
36
+ * @returns The TaskLease if won, null if another worker claimed first
37
+ */
38
+ claim(taskId: string, workerId: string, attempt?: number): TaskLease | null;
39
+ /**
40
+ * Extend a lease's expiry time.
41
+ * Only the worker that holds the lease can extend it.
42
+ *
43
+ * @returns Updated lease, or null if the lease no longer exists
44
+ */
45
+ heartbeat(taskId: string, workerId: string): TaskLease | null;
46
+ /**
47
+ * Explicitly release a lease (task completed or failed without retry).
48
+ */
49
+ release(taskId: string, workerId: string): void;
50
+ /** Read a lease by taskId. Returns null if not found. */
51
+ get(taskId: string): TaskLease | null;
52
+ /** Check if a lease has expired (expiresAt is in the past). */
53
+ isExpired(lease: TaskLease): boolean;
54
+ /**
55
+ * Scan all leases and return the ones that have expired.
56
+ * Does NOT remove them — call reapAndRelease() to remove atomically.
57
+ */
58
+ reap(): TaskLease[];
59
+ /**
60
+ * Release all expired leases and return their taskIds.
61
+ * Idempotent — safe to call on every heartbeat interval.
62
+ */
63
+ reapAndRelease(): string[];
64
+ /**
65
+ * On worker startup, release any leases held by dead workers.
66
+ * A lease is orphaned if its worker has not re-claimed it since startup.
67
+ *
68
+ * Strategy: remove all leases whose expiresAt has passed.
69
+ * Safe because the next claim will succeed (no other worker holds it).
70
+ */
71
+ recoverOnStartup(): string[];
72
+ /** Return all active (non-expired) leases. */
73
+ listActive(): TaskLease[];
74
+ private _leasePath;
75
+ private _writeLease;
76
+ private _removeLease;
77
+ }
78
+ //# sourceMappingURL=lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../src/lease.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,qBAAa,UAAW,SAAQ,KAAK;IACpC,YAAY,GAAG,EAAE,MAAM,EAGtB;CACD;AAID,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,mDAAmD;AACnD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAI7C,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,YAAY,OAAO,GAAE,YAAiB,EAGrC;IAED,4CAA4C;IAC5C,SAAS,IAAI,IAAI,CAIhB;IAID;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,SAAS,GAAG,IAAI,CA8CrE;IAID;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAiB5D;IAID;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS9C;IAID,yDAAyD;IACzD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAQpC;IAID,+DAA+D;IAC/D,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEnC;IAID;;;OAGG;IACH,IAAI,IAAI,SAAS,EAAE,CAwBlB;IAED;;;OAGG;IACH,cAAc,IAAI,MAAM,EAAE,CAYzB;IAID;;;;;;OAMG;IACH,gBAAgB,IAAI,MAAM,EAAE,CAE3B;IAID,8CAA8C;IAC9C,UAAU,IAAI,SAAS,EAAE,CAwBxB;IAID,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,YAAY;CAIpB"}