@os-eco/overstory-cli 0.6.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.
- package/LICENSE +21 -0
- package/README.md +381 -0
- package/agents/builder.md +137 -0
- package/agents/coordinator.md +263 -0
- package/agents/lead.md +301 -0
- package/agents/merger.md +160 -0
- package/agents/monitor.md +214 -0
- package/agents/reviewer.md +140 -0
- package/agents/scout.md +119 -0
- package/agents/supervisor.md +423 -0
- package/package.json +47 -0
- package/src/agents/checkpoint.test.ts +88 -0
- package/src/agents/checkpoint.ts +101 -0
- package/src/agents/hooks-deployer.test.ts +2040 -0
- package/src/agents/hooks-deployer.ts +607 -0
- package/src/agents/identity.test.ts +603 -0
- package/src/agents/identity.ts +384 -0
- package/src/agents/lifecycle.test.ts +196 -0
- package/src/agents/lifecycle.ts +183 -0
- package/src/agents/manifest.test.ts +746 -0
- package/src/agents/manifest.ts +354 -0
- package/src/agents/overlay.test.ts +676 -0
- package/src/agents/overlay.ts +308 -0
- package/src/beads/client.test.ts +217 -0
- package/src/beads/client.ts +202 -0
- package/src/beads/molecules.test.ts +338 -0
- package/src/beads/molecules.ts +198 -0
- package/src/commands/agents.test.ts +322 -0
- package/src/commands/agents.ts +287 -0
- package/src/commands/clean.test.ts +670 -0
- package/src/commands/clean.ts +618 -0
- package/src/commands/completions.test.ts +342 -0
- package/src/commands/completions.ts +887 -0
- package/src/commands/coordinator.test.ts +1530 -0
- package/src/commands/coordinator.ts +733 -0
- package/src/commands/costs.test.ts +1119 -0
- package/src/commands/costs.ts +564 -0
- package/src/commands/dashboard.test.ts +308 -0
- package/src/commands/dashboard.ts +838 -0
- package/src/commands/doctor.test.ts +294 -0
- package/src/commands/doctor.ts +213 -0
- package/src/commands/errors.test.ts +647 -0
- package/src/commands/errors.ts +248 -0
- package/src/commands/feed.test.ts +578 -0
- package/src/commands/feed.ts +361 -0
- package/src/commands/group.test.ts +262 -0
- package/src/commands/group.ts +511 -0
- package/src/commands/hooks.test.ts +458 -0
- package/src/commands/hooks.ts +253 -0
- package/src/commands/init.test.ts +347 -0
- package/src/commands/init.ts +650 -0
- package/src/commands/inspect.test.ts +670 -0
- package/src/commands/inspect.ts +431 -0
- package/src/commands/log.test.ts +1454 -0
- package/src/commands/log.ts +724 -0
- package/src/commands/logs.test.ts +379 -0
- package/src/commands/logs.ts +546 -0
- package/src/commands/mail.test.ts +1270 -0
- package/src/commands/mail.ts +771 -0
- package/src/commands/merge.test.ts +670 -0
- package/src/commands/merge.ts +355 -0
- package/src/commands/metrics.test.ts +444 -0
- package/src/commands/metrics.ts +143 -0
- package/src/commands/monitor.test.ts +191 -0
- package/src/commands/monitor.ts +390 -0
- package/src/commands/nudge.test.ts +230 -0
- package/src/commands/nudge.ts +372 -0
- package/src/commands/prime.test.ts +470 -0
- package/src/commands/prime.ts +381 -0
- package/src/commands/replay.test.ts +741 -0
- package/src/commands/replay.ts +360 -0
- package/src/commands/run.test.ts +431 -0
- package/src/commands/run.ts +351 -0
- package/src/commands/sling.test.ts +657 -0
- package/src/commands/sling.ts +661 -0
- package/src/commands/spec.test.ts +203 -0
- package/src/commands/spec.ts +168 -0
- package/src/commands/status.test.ts +430 -0
- package/src/commands/status.ts +398 -0
- package/src/commands/stop.test.ts +420 -0
- package/src/commands/stop.ts +151 -0
- package/src/commands/supervisor.test.ts +187 -0
- package/src/commands/supervisor.ts +535 -0
- package/src/commands/trace.test.ts +745 -0
- package/src/commands/trace.ts +325 -0
- package/src/commands/watch.test.ts +145 -0
- package/src/commands/watch.ts +247 -0
- package/src/commands/worktree.test.ts +786 -0
- package/src/commands/worktree.ts +311 -0
- package/src/config.test.ts +822 -0
- package/src/config.ts +829 -0
- package/src/doctor/agents.test.ts +454 -0
- package/src/doctor/agents.ts +396 -0
- package/src/doctor/config-check.test.ts +190 -0
- package/src/doctor/config-check.ts +183 -0
- package/src/doctor/consistency.test.ts +651 -0
- package/src/doctor/consistency.ts +294 -0
- package/src/doctor/databases.test.ts +290 -0
- package/src/doctor/databases.ts +218 -0
- package/src/doctor/dependencies.test.ts +184 -0
- package/src/doctor/dependencies.ts +175 -0
- package/src/doctor/logs.test.ts +251 -0
- package/src/doctor/logs.ts +295 -0
- package/src/doctor/merge-queue.test.ts +216 -0
- package/src/doctor/merge-queue.ts +144 -0
- package/src/doctor/structure.test.ts +291 -0
- package/src/doctor/structure.ts +198 -0
- package/src/doctor/types.ts +37 -0
- package/src/doctor/version.test.ts +136 -0
- package/src/doctor/version.ts +129 -0
- package/src/e2e/init-sling-lifecycle.test.ts +277 -0
- package/src/errors.ts +217 -0
- package/src/events/store.test.ts +660 -0
- package/src/events/store.ts +369 -0
- package/src/events/tool-filter.test.ts +330 -0
- package/src/events/tool-filter.ts +126 -0
- package/src/index.ts +316 -0
- package/src/insights/analyzer.test.ts +466 -0
- package/src/insights/analyzer.ts +203 -0
- package/src/logging/color.test.ts +142 -0
- package/src/logging/color.ts +71 -0
- package/src/logging/logger.test.ts +813 -0
- package/src/logging/logger.ts +266 -0
- package/src/logging/reporter.test.ts +259 -0
- package/src/logging/reporter.ts +109 -0
- package/src/logging/sanitizer.test.ts +190 -0
- package/src/logging/sanitizer.ts +57 -0
- package/src/mail/broadcast.test.ts +203 -0
- package/src/mail/broadcast.ts +92 -0
- package/src/mail/client.test.ts +773 -0
- package/src/mail/client.ts +223 -0
- package/src/mail/store.test.ts +705 -0
- package/src/mail/store.ts +387 -0
- package/src/merge/queue.test.ts +359 -0
- package/src/merge/queue.ts +231 -0
- package/src/merge/resolver.test.ts +1345 -0
- package/src/merge/resolver.ts +645 -0
- package/src/metrics/store.test.ts +667 -0
- package/src/metrics/store.ts +445 -0
- package/src/metrics/summary.test.ts +398 -0
- package/src/metrics/summary.ts +178 -0
- package/src/metrics/transcript.test.ts +356 -0
- package/src/metrics/transcript.ts +175 -0
- package/src/mulch/client.test.ts +671 -0
- package/src/mulch/client.ts +332 -0
- package/src/sessions/compat.test.ts +280 -0
- package/src/sessions/compat.ts +104 -0
- package/src/sessions/store.test.ts +873 -0
- package/src/sessions/store.ts +494 -0
- package/src/test-helpers.test.ts +124 -0
- package/src/test-helpers.ts +126 -0
- package/src/tracker/beads.ts +56 -0
- package/src/tracker/factory.test.ts +80 -0
- package/src/tracker/factory.ts +64 -0
- package/src/tracker/seeds.ts +182 -0
- package/src/tracker/types.ts +52 -0
- package/src/types.ts +724 -0
- package/src/watchdog/daemon.test.ts +1975 -0
- package/src/watchdog/daemon.ts +671 -0
- package/src/watchdog/health.test.ts +431 -0
- package/src/watchdog/health.ts +264 -0
- package/src/watchdog/triage.test.ts +164 -0
- package/src/watchdog/triage.ts +179 -0
- package/src/worktree/manager.test.ts +439 -0
- package/src/worktree/manager.ts +198 -0
- package/src/worktree/tmux.test.ts +1009 -0
- package/src/worktree/tmux.ts +509 -0
- package/templates/CLAUDE.md.tmpl +89 -0
- package/templates/hooks.json.tmpl +105 -0
- package/templates/overlay.md.tmpl +81 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { LifecycleError } from "../errors.ts";
|
|
4
|
+
import type { SessionCheckpoint, SessionHandoff } from "../types.ts";
|
|
5
|
+
import { clearCheckpoint, loadCheckpoint, saveCheckpoint } from "./checkpoint.ts";
|
|
6
|
+
|
|
7
|
+
const HANDOFFS_FILENAME = "handoffs.json";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Load handoffs array from disk.
|
|
11
|
+
* Returns an empty array if the file doesn't exist.
|
|
12
|
+
*/
|
|
13
|
+
async function loadHandoffs(agentsDir: string, agentName: string): Promise<SessionHandoff[]> {
|
|
14
|
+
const filePath = join(agentsDir, agentName, HANDOFFS_FILENAME);
|
|
15
|
+
const file = Bun.file(filePath);
|
|
16
|
+
const exists = await file.exists();
|
|
17
|
+
|
|
18
|
+
if (!exists) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const text = await file.text();
|
|
24
|
+
return JSON.parse(text) as SessionHandoff[];
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw new LifecycleError(`Failed to read handoffs: ${filePath}`, {
|
|
27
|
+
agentName,
|
|
28
|
+
cause: err instanceof Error ? err : undefined,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Write handoffs array to disk.
|
|
35
|
+
*/
|
|
36
|
+
async function writeHandoffs(
|
|
37
|
+
agentsDir: string,
|
|
38
|
+
agentName: string,
|
|
39
|
+
handoffs: SessionHandoff[],
|
|
40
|
+
): Promise<void> {
|
|
41
|
+
const filePath = join(agentsDir, agentName, HANDOFFS_FILENAME);
|
|
42
|
+
const dir = dirname(filePath);
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
await mkdir(dir, { recursive: true });
|
|
46
|
+
} catch (err) {
|
|
47
|
+
throw new LifecycleError(`Failed to create handoffs directory: ${dir}`, {
|
|
48
|
+
agentName,
|
|
49
|
+
cause: err instanceof Error ? err : undefined,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
await Bun.write(filePath, `${JSON.stringify(handoffs, null, "\t")}\n`);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
throw new LifecycleError(`Failed to write handoffs: ${filePath}`, {
|
|
57
|
+
agentName,
|
|
58
|
+
cause: err instanceof Error ? err : undefined,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Initiate a session handoff.
|
|
65
|
+
*
|
|
66
|
+
* 1. Builds a SessionCheckpoint from options
|
|
67
|
+
* 2. Saves the checkpoint to disk
|
|
68
|
+
* 3. Builds a SessionHandoff record
|
|
69
|
+
* 4. Appends to handoffs.json
|
|
70
|
+
* 5. Returns the handoff
|
|
71
|
+
*/
|
|
72
|
+
export async function initiateHandoff(options: {
|
|
73
|
+
agentsDir: string;
|
|
74
|
+
agentName: string;
|
|
75
|
+
sessionId: string;
|
|
76
|
+
beadId: string;
|
|
77
|
+
reason: SessionHandoff["reason"];
|
|
78
|
+
progressSummary: string;
|
|
79
|
+
pendingWork: string;
|
|
80
|
+
currentBranch: string;
|
|
81
|
+
filesModified: string[];
|
|
82
|
+
mulchDomains: string[];
|
|
83
|
+
}): Promise<SessionHandoff> {
|
|
84
|
+
const checkpoint: SessionCheckpoint = {
|
|
85
|
+
agentName: options.agentName,
|
|
86
|
+
beadId: options.beadId,
|
|
87
|
+
sessionId: options.sessionId,
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
progressSummary: options.progressSummary,
|
|
90
|
+
filesModified: options.filesModified,
|
|
91
|
+
currentBranch: options.currentBranch,
|
|
92
|
+
pendingWork: options.pendingWork,
|
|
93
|
+
mulchDomains: options.mulchDomains,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
await saveCheckpoint(options.agentsDir, checkpoint);
|
|
97
|
+
|
|
98
|
+
const handoff: SessionHandoff = {
|
|
99
|
+
fromSessionId: options.sessionId,
|
|
100
|
+
toSessionId: null,
|
|
101
|
+
checkpoint,
|
|
102
|
+
reason: options.reason,
|
|
103
|
+
handoffAt: new Date().toISOString(),
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const handoffs = await loadHandoffs(options.agentsDir, options.agentName);
|
|
107
|
+
handoffs.push(handoff);
|
|
108
|
+
await writeHandoffs(options.agentsDir, options.agentName, handoffs);
|
|
109
|
+
|
|
110
|
+
return handoff;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Resume from a pending handoff.
|
|
115
|
+
*
|
|
116
|
+
* Finds the most recent handoff where `toSessionId` is null,
|
|
117
|
+
* loads the associated checkpoint, and returns both.
|
|
118
|
+
* Returns null if no pending handoff exists.
|
|
119
|
+
*/
|
|
120
|
+
export async function resumeFromHandoff(options: {
|
|
121
|
+
agentsDir: string;
|
|
122
|
+
agentName: string;
|
|
123
|
+
}): Promise<{ checkpoint: SessionCheckpoint; handoff: SessionHandoff } | null> {
|
|
124
|
+
const handoffs = await loadHandoffs(options.agentsDir, options.agentName);
|
|
125
|
+
|
|
126
|
+
// Find most recent pending handoff (search from end)
|
|
127
|
+
let pendingHandoff: SessionHandoff | undefined;
|
|
128
|
+
for (let i = handoffs.length - 1; i >= 0; i--) {
|
|
129
|
+
const h = handoffs[i];
|
|
130
|
+
if (h !== undefined && h.toSessionId === null) {
|
|
131
|
+
pendingHandoff = h;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (pendingHandoff === undefined) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const checkpoint = await loadCheckpoint(options.agentsDir, options.agentName);
|
|
141
|
+
if (checkpoint === null) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return { checkpoint, handoff: pendingHandoff };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Complete a pending handoff.
|
|
150
|
+
*
|
|
151
|
+
* 1. Loads handoffs.json
|
|
152
|
+
* 2. Finds the most recent handoff with toSessionId === null
|
|
153
|
+
* 3. Sets toSessionId to the new session ID
|
|
154
|
+
* 4. Writes back handoffs.json
|
|
155
|
+
* 5. Clears the checkpoint
|
|
156
|
+
*/
|
|
157
|
+
export async function completeHandoff(options: {
|
|
158
|
+
agentsDir: string;
|
|
159
|
+
agentName: string;
|
|
160
|
+
newSessionId: string;
|
|
161
|
+
}): Promise<void> {
|
|
162
|
+
const handoffs = await loadHandoffs(options.agentsDir, options.agentName);
|
|
163
|
+
|
|
164
|
+
// Find most recent pending handoff (search from end)
|
|
165
|
+
let found = false;
|
|
166
|
+
for (let i = handoffs.length - 1; i >= 0; i--) {
|
|
167
|
+
const h = handoffs[i];
|
|
168
|
+
if (h !== undefined && h.toSessionId === null) {
|
|
169
|
+
h.toSessionId = options.newSessionId;
|
|
170
|
+
found = true;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!found) {
|
|
176
|
+
throw new LifecycleError("No pending handoff to complete", {
|
|
177
|
+
agentName: options.agentName,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await writeHandoffs(options.agentsDir, options.agentName, handoffs);
|
|
182
|
+
await clearCheckpoint(options.agentsDir, options.agentName);
|
|
183
|
+
}
|