@katyella/legio 0.1.0
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/CHANGELOG.md +422 -0
- package/LICENSE +21 -0
- package/README.md +555 -0
- package/agents/builder.md +141 -0
- package/agents/coordinator.md +351 -0
- package/agents/cto.md +196 -0
- package/agents/gateway.md +276 -0
- package/agents/lead.md +281 -0
- package/agents/merger.md +156 -0
- package/agents/monitor.md +212 -0
- package/agents/reviewer.md +142 -0
- package/agents/scout.md +131 -0
- package/agents/supervisor.md +416 -0
- package/bin/legio.mjs +38 -0
- package/package.json +77 -0
- package/src/agents/checkpoint.test.ts +88 -0
- package/src/agents/checkpoint.ts +102 -0
- package/src/agents/hooks-deployer.test.ts +1820 -0
- package/src/agents/hooks-deployer.ts +574 -0
- package/src/agents/identity.test.ts +614 -0
- package/src/agents/identity.ts +385 -0
- package/src/agents/lifecycle.test.ts +202 -0
- package/src/agents/lifecycle.ts +184 -0
- package/src/agents/manifest.test.ts +558 -0
- package/src/agents/manifest.ts +297 -0
- package/src/agents/overlay.test.ts +592 -0
- package/src/agents/overlay.ts +316 -0
- package/src/beads/client.test.ts +210 -0
- package/src/beads/client.ts +227 -0
- package/src/beads/molecules.test.ts +320 -0
- package/src/beads/molecules.ts +209 -0
- package/src/commands/agents.test.ts +325 -0
- package/src/commands/agents.ts +286 -0
- package/src/commands/clean.test.ts +730 -0
- package/src/commands/clean.ts +653 -0
- package/src/commands/completions.test.ts +346 -0
- package/src/commands/completions.ts +950 -0
- package/src/commands/coordinator.test.ts +1524 -0
- package/src/commands/coordinator.ts +880 -0
- package/src/commands/costs.test.ts +1015 -0
- package/src/commands/costs.ts +473 -0
- package/src/commands/dashboard.test.ts +94 -0
- package/src/commands/dashboard.ts +607 -0
- package/src/commands/doctor.test.ts +295 -0
- package/src/commands/doctor.ts +213 -0
- package/src/commands/down.test.ts +308 -0
- package/src/commands/down.ts +124 -0
- package/src/commands/errors.test.ts +648 -0
- package/src/commands/errors.ts +255 -0
- package/src/commands/feed.test.ts +579 -0
- package/src/commands/feed.ts +368 -0
- package/src/commands/gateway.test.ts +698 -0
- package/src/commands/gateway.ts +419 -0
- package/src/commands/group.test.ts +262 -0
- package/src/commands/group.ts +539 -0
- package/src/commands/hooks.test.ts +292 -0
- package/src/commands/hooks.ts +210 -0
- package/src/commands/init.test.ts +211 -0
- package/src/commands/init.ts +622 -0
- package/src/commands/inspect.test.ts +670 -0
- package/src/commands/inspect.ts +455 -0
- package/src/commands/log.test.ts +1556 -0
- package/src/commands/log.ts +752 -0
- package/src/commands/logs.test.ts +379 -0
- package/src/commands/logs.ts +544 -0
- package/src/commands/mail.test.ts +1726 -0
- package/src/commands/mail.ts +926 -0
- package/src/commands/merge.test.ts +676 -0
- package/src/commands/merge.ts +374 -0
- package/src/commands/metrics.test.ts +444 -0
- package/src/commands/metrics.ts +150 -0
- package/src/commands/monitor.test.ts +151 -0
- package/src/commands/monitor.ts +394 -0
- package/src/commands/nudge.test.ts +230 -0
- package/src/commands/nudge.ts +373 -0
- package/src/commands/prime.test.ts +467 -0
- package/src/commands/prime.ts +386 -0
- package/src/commands/replay.test.ts +742 -0
- package/src/commands/replay.ts +367 -0
- package/src/commands/run.test.ts +443 -0
- package/src/commands/run.ts +365 -0
- package/src/commands/server.test.ts +626 -0
- package/src/commands/server.ts +298 -0
- package/src/commands/sling.test.ts +810 -0
- package/src/commands/sling.ts +700 -0
- package/src/commands/spec.test.ts +206 -0
- package/src/commands/spec.ts +171 -0
- package/src/commands/status.test.ts +276 -0
- package/src/commands/status.ts +339 -0
- package/src/commands/stop.test.ts +357 -0
- package/src/commands/stop.ts +119 -0
- package/src/commands/supervisor.test.ts +186 -0
- package/src/commands/supervisor.ts +544 -0
- package/src/commands/trace.test.ts +746 -0
- package/src/commands/trace.ts +332 -0
- package/src/commands/up.test.ts +597 -0
- package/src/commands/up.ts +275 -0
- package/src/commands/watch.test.ts +152 -0
- package/src/commands/watch.ts +238 -0
- package/src/commands/worktree.test.ts +648 -0
- package/src/commands/worktree.ts +266 -0
- package/src/config.test.ts +496 -0
- package/src/config.ts +616 -0
- package/src/doctor/agents.test.ts +448 -0
- package/src/doctor/agents.ts +396 -0
- package/src/doctor/config-check.test.ts +184 -0
- package/src/doctor/config-check.ts +185 -0
- package/src/doctor/consistency.test.ts +645 -0
- package/src/doctor/consistency.ts +294 -0
- package/src/doctor/databases.test.ts +284 -0
- package/src/doctor/databases.ts +211 -0
- package/src/doctor/dependencies.test.ts +150 -0
- package/src/doctor/dependencies.ts +179 -0
- package/src/doctor/logs.test.ts +244 -0
- package/src/doctor/logs.ts +295 -0
- package/src/doctor/merge-queue.test.ts +210 -0
- package/src/doctor/merge-queue.ts +144 -0
- package/src/doctor/structure.test.ts +285 -0
- package/src/doctor/structure.ts +195 -0
- package/src/doctor/types.ts +37 -0
- package/src/doctor/version.test.ts +130 -0
- package/src/doctor/version.ts +131 -0
- package/src/e2e/chat-flow.test.ts +346 -0
- package/src/e2e/init-sling-lifecycle.test.ts +288 -0
- package/src/errors.test.ts +21 -0
- package/src/errors.ts +246 -0
- package/src/events/store.test.ts +660 -0
- package/src/events/store.ts +344 -0
- package/src/events/tool-filter.test.ts +330 -0
- package/src/events/tool-filter.ts +126 -0
- package/src/global-setup.ts +14 -0
- package/src/index.ts +339 -0
- package/src/insights/analyzer.test.ts +466 -0
- package/src/insights/analyzer.ts +203 -0
- package/src/logging/color.test.ts +118 -0
- package/src/logging/color.ts +71 -0
- package/src/logging/logger.test.ts +812 -0
- package/src/logging/logger.ts +266 -0
- package/src/logging/reporter.test.ts +258 -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 +873 -0
- package/src/mail/client.ts +236 -0
- package/src/mail/store.test.ts +815 -0
- package/src/mail/store.ts +402 -0
- package/src/merge/queue.test.ts +449 -0
- package/src/merge/queue.ts +262 -0
- package/src/merge/resolver.test.ts +1453 -0
- package/src/merge/resolver.ts +759 -0
- package/src/metrics/store.test.ts +1167 -0
- package/src/metrics/store.ts +511 -0
- package/src/metrics/summary.test.ts +397 -0
- package/src/metrics/summary.ts +178 -0
- package/src/metrics/transcript.test.ts +643 -0
- package/src/metrics/transcript.ts +351 -0
- package/src/mulch/client.test.ts +547 -0
- package/src/mulch/client.ts +416 -0
- package/src/server/audit-store.test.ts +384 -0
- package/src/server/audit-store.ts +257 -0
- package/src/server/headless.test.ts +180 -0
- package/src/server/headless.ts +151 -0
- package/src/server/index.test.ts +241 -0
- package/src/server/index.ts +317 -0
- package/src/server/public/app.js +187 -0
- package/src/server/public/apple-touch-icon.png +0 -0
- package/src/server/public/components/agent-badge.js +37 -0
- package/src/server/public/components/data-table.js +114 -0
- package/src/server/public/components/gateway-chat.js +256 -0
- package/src/server/public/components/issue-card.js +96 -0
- package/src/server/public/components/layout.js +88 -0
- package/src/server/public/components/message-bubble.js +120 -0
- package/src/server/public/components/stat-card.js +26 -0
- package/src/server/public/components/terminal-panel.js +140 -0
- package/src/server/public/favicon-16.png +0 -0
- package/src/server/public/favicon-32.png +0 -0
- package/src/server/public/favicon.ico +0 -0
- package/src/server/public/favicon.png +0 -0
- package/src/server/public/index.html +64 -0
- package/src/server/public/lib/api.js +35 -0
- package/src/server/public/lib/markdown.js +8 -0
- package/src/server/public/lib/preact-setup.js +8 -0
- package/src/server/public/lib/state.js +99 -0
- package/src/server/public/lib/utils.js +309 -0
- package/src/server/public/lib/ws.js +79 -0
- package/src/server/public/views/chat.js +983 -0
- package/src/server/public/views/costs.js +692 -0
- package/src/server/public/views/dashboard.js +781 -0
- package/src/server/public/views/gateway-chat.js +622 -0
- package/src/server/public/views/inspect.js +399 -0
- package/src/server/public/views/issues.js +470 -0
- package/src/server/public/views/setup.js +94 -0
- package/src/server/public/views/task-detail.js +422 -0
- package/src/server/routes.test.ts +3816 -0
- package/src/server/routes.ts +1964 -0
- package/src/server/websocket.test.ts +288 -0
- package/src/server/websocket.ts +196 -0
- package/src/sessions/compat.test.ts +109 -0
- package/src/sessions/compat.ts +17 -0
- package/src/sessions/store.test.ts +969 -0
- package/src/sessions/store.ts +480 -0
- package/src/test-helpers.test.ts +97 -0
- package/src/test-helpers.ts +143 -0
- package/src/types.ts +708 -0
- package/src/watchdog/daemon.test.ts +1233 -0
- package/src/watchdog/daemon.ts +533 -0
- package/src/watchdog/health.test.ts +371 -0
- package/src/watchdog/health.ts +248 -0
- package/src/watchdog/triage.test.ts +162 -0
- package/src/watchdog/triage.ts +193 -0
- package/src/worktree/manager.test.ts +444 -0
- package/src/worktree/manager.ts +224 -0
- package/src/worktree/tmux.test.ts +1238 -0
- package/src/worktree/tmux.ts +644 -0
- package/templates/CLAUDE.md.tmpl +89 -0
- package/templates/hooks.json.tmpl +132 -0
- package/templates/overlay.md.tmpl +79 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
// === Provider Configuration ===
|
|
2
|
+
|
|
3
|
+
/** Short alias for model selection (e.g., in config.yaml models section). */
|
|
4
|
+
export type ModelAlias = "sonnet" | "opus" | "haiku";
|
|
5
|
+
|
|
6
|
+
/** Full model reference: either an alias or a provider-qualified string. */
|
|
7
|
+
export type ModelRef = ModelAlias | string;
|
|
8
|
+
|
|
9
|
+
/** Provider endpoint configuration for custom API routing. */
|
|
10
|
+
export interface ProviderConfig {
|
|
11
|
+
/** Base URL for the Anthropic API (maps to ANTHROPIC_BASE_URL). */
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
/** Auth token for the Anthropic API (maps to ANTHROPIC_AUTH_TOKEN). */
|
|
14
|
+
authToken?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// === Project Configuration ===
|
|
18
|
+
|
|
19
|
+
export interface LegioConfig {
|
|
20
|
+
project: {
|
|
21
|
+
name: string;
|
|
22
|
+
root: string; // Absolute path to target repo
|
|
23
|
+
canonicalBranch: string; // "main" | "develop"
|
|
24
|
+
};
|
|
25
|
+
agents: {
|
|
26
|
+
manifestPath: string; // Path to agent-manifest.json
|
|
27
|
+
baseDir: string; // Path to base agent definitions
|
|
28
|
+
maxConcurrent: number; // Rate limit ceiling
|
|
29
|
+
staggerDelayMs: number; // Delay between spawns
|
|
30
|
+
maxDepth: number; // Hierarchy depth limit (default 2)
|
|
31
|
+
maxAgentsPerLead?: number; // Max child agents per lead (default 5)
|
|
32
|
+
};
|
|
33
|
+
worktrees: {
|
|
34
|
+
baseDir: string; // Where worktrees live
|
|
35
|
+
};
|
|
36
|
+
beads: {
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
};
|
|
39
|
+
mulch: {
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
domains: string[]; // Domains to prime (empty = auto-detect)
|
|
42
|
+
primeFormat: "markdown" | "xml" | "json";
|
|
43
|
+
domainMap?: Record<string, string[]>; // file glob -> domain names (empty = use DEFAULT_DOMAIN_MAP)
|
|
44
|
+
};
|
|
45
|
+
merge: {
|
|
46
|
+
aiResolveEnabled: boolean;
|
|
47
|
+
reimagineEnabled: boolean;
|
|
48
|
+
};
|
|
49
|
+
watchdog: {
|
|
50
|
+
tier0Enabled: boolean; // Tier 0: Mechanical daemon (heartbeat, tmux/pid liveness)
|
|
51
|
+
tier0IntervalMs: number; // Default 30_000
|
|
52
|
+
tier1Enabled: boolean; // Tier 1: Triage agent (ephemeral AI analysis)
|
|
53
|
+
tier2Enabled: boolean; // Tier 2: Monitor agent (continuous patrol — not yet implemented)
|
|
54
|
+
zombieThresholdMs: number; // When to kill
|
|
55
|
+
nudgeIntervalMs: number; // Time between progressive nudge stages (default 60_000)
|
|
56
|
+
};
|
|
57
|
+
models: Partial<Record<string, ModelAlias>>;
|
|
58
|
+
logging: {
|
|
59
|
+
verbose: boolean;
|
|
60
|
+
redactSecrets: boolean;
|
|
61
|
+
};
|
|
62
|
+
qualityGates?: {
|
|
63
|
+
test?: string; // default: "npm test"
|
|
64
|
+
lint?: string; // default: "npm run lint"
|
|
65
|
+
typecheck?: string; // default: "npm run typecheck"
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// === Agent Manifest ===
|
|
70
|
+
|
|
71
|
+
export interface AgentManifest {
|
|
72
|
+
version: string;
|
|
73
|
+
agents: Record<string, AgentDefinition>;
|
|
74
|
+
capabilityIndex: Record<string, string[]>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface AgentDefinition {
|
|
78
|
+
file: string; // Path to base agent definition (.md)
|
|
79
|
+
model: ModelAlias;
|
|
80
|
+
tools: string[]; // Allowed tools
|
|
81
|
+
capabilities: string[]; // What this agent can do
|
|
82
|
+
canSpawn: boolean; // Can this agent spawn sub-workers?
|
|
83
|
+
constraints: string[]; // Machine-readable restrictions
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** All valid agent capability types. Used for compile-time validation. */
|
|
87
|
+
export const SUPPORTED_CAPABILITIES = [
|
|
88
|
+
"scout",
|
|
89
|
+
"builder",
|
|
90
|
+
"reviewer",
|
|
91
|
+
"lead",
|
|
92
|
+
"merger",
|
|
93
|
+
"coordinator",
|
|
94
|
+
"supervisor",
|
|
95
|
+
"monitor",
|
|
96
|
+
"gateway",
|
|
97
|
+
"cto",
|
|
98
|
+
] as const;
|
|
99
|
+
|
|
100
|
+
/** Union type derived from the capabilities constant. */
|
|
101
|
+
export type Capability = (typeof SUPPORTED_CAPABILITIES)[number];
|
|
102
|
+
|
|
103
|
+
// === Agent Session ===
|
|
104
|
+
|
|
105
|
+
export type AgentState = "booting" | "working" | "completed" | "zombie";
|
|
106
|
+
|
|
107
|
+
export interface AgentSession {
|
|
108
|
+
id: string; // Unique session ID
|
|
109
|
+
agentName: string; // Unique per-session name
|
|
110
|
+
capability: string; // Which agent definition
|
|
111
|
+
worktreePath: string;
|
|
112
|
+
branchName: string;
|
|
113
|
+
beadId: string; // Task being worked
|
|
114
|
+
tmuxSession: string; // Tmux session name
|
|
115
|
+
state: AgentState;
|
|
116
|
+
pid: number | null; // Claude Code PID
|
|
117
|
+
parentAgent: string | null; // Who spawned this agent (null = orchestrator)
|
|
118
|
+
depth: number; // 0 = direct from orchestrator
|
|
119
|
+
runId: string | null; // Groups sessions in the same orchestrator run
|
|
120
|
+
startedAt: string;
|
|
121
|
+
lastActivity: string;
|
|
122
|
+
escalationLevel: number; // Progressive nudge stage: 0=warn, 1=nudge, 2=escalate, 3=terminate
|
|
123
|
+
stalledSince: string | null; // ISO timestamp when agent first entered stalled state
|
|
124
|
+
terminalLogPath?: string | null; // Path to pipe-pane terminal log file
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// === Headless Coordinator ===
|
|
128
|
+
|
|
129
|
+
export interface HeadlessCoordinatorConfig {
|
|
130
|
+
/** Command to run (e.g., "claude --model opus --dangerously-skip-permissions") */
|
|
131
|
+
command: string;
|
|
132
|
+
/** Working directory for the subprocess */
|
|
133
|
+
cwd: string;
|
|
134
|
+
/** Environment variables to inject */
|
|
135
|
+
env?: Record<string, string>;
|
|
136
|
+
/** Max lines in the ring buffer (default: 500) */
|
|
137
|
+
ringBufferSize?: number;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// === Agent Identity ===
|
|
141
|
+
|
|
142
|
+
export interface AgentIdentity {
|
|
143
|
+
name: string;
|
|
144
|
+
capability: string;
|
|
145
|
+
created: string;
|
|
146
|
+
sessionsCompleted: number;
|
|
147
|
+
expertiseDomains: string[];
|
|
148
|
+
recentTasks: Array<{
|
|
149
|
+
beadId: string;
|
|
150
|
+
summary: string;
|
|
151
|
+
completedAt: string;
|
|
152
|
+
}>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// === Mail (Custom SQLite) ===
|
|
156
|
+
|
|
157
|
+
/** Semantic message types (original, human-readable). */
|
|
158
|
+
export type MailSemanticType = "status" | "question" | "result" | "error";
|
|
159
|
+
|
|
160
|
+
/** Protocol message types for structured agent coordination. */
|
|
161
|
+
export type MailProtocolType =
|
|
162
|
+
| "worker_done"
|
|
163
|
+
| "merge_ready"
|
|
164
|
+
| "merged"
|
|
165
|
+
| "merge_failed"
|
|
166
|
+
| "escalation"
|
|
167
|
+
| "health_check"
|
|
168
|
+
| "dispatch"
|
|
169
|
+
| "assign";
|
|
170
|
+
|
|
171
|
+
/** All valid mail message types. */
|
|
172
|
+
export type MailMessageType = MailSemanticType | MailProtocolType;
|
|
173
|
+
|
|
174
|
+
/** All protocol type strings as a runtime array for CHECK constraint generation. */
|
|
175
|
+
export const MAIL_MESSAGE_TYPES: readonly MailMessageType[] = [
|
|
176
|
+
"status",
|
|
177
|
+
"question",
|
|
178
|
+
"result",
|
|
179
|
+
"error",
|
|
180
|
+
"worker_done",
|
|
181
|
+
"merge_ready",
|
|
182
|
+
"merged",
|
|
183
|
+
"merge_failed",
|
|
184
|
+
"escalation",
|
|
185
|
+
"health_check",
|
|
186
|
+
"dispatch",
|
|
187
|
+
"assign",
|
|
188
|
+
] as const;
|
|
189
|
+
|
|
190
|
+
/** Audience targeting for mail messages. */
|
|
191
|
+
export type MailAudience = "human" | "agent" | "both";
|
|
192
|
+
|
|
193
|
+
/** Runtime array of valid audience values for CHECK constraint generation. */
|
|
194
|
+
export const MAIL_AUDIENCE_VALUES: readonly MailAudience[] = ["human", "agent", "both"] as const;
|
|
195
|
+
|
|
196
|
+
export interface MailMessage {
|
|
197
|
+
id: string; // "msg-" + nanoid(12)
|
|
198
|
+
from: string; // Agent name
|
|
199
|
+
to: string; // Agent name or "orchestrator"
|
|
200
|
+
subject: string;
|
|
201
|
+
body: string;
|
|
202
|
+
priority: "low" | "normal" | "high" | "urgent";
|
|
203
|
+
type: MailMessageType;
|
|
204
|
+
audience: MailAudience; // Intended audience: "human", "agent", or "both"
|
|
205
|
+
threadId: string | null; // Conversation threading
|
|
206
|
+
payload: string | null; // JSON-encoded structured data for protocol messages
|
|
207
|
+
read: boolean;
|
|
208
|
+
createdAt: string; // ISO timestamp
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// === Mail Protocol Payloads ===
|
|
212
|
+
|
|
213
|
+
/** Worker signals task completion to supervisor. */
|
|
214
|
+
export interface WorkerDonePayload {
|
|
215
|
+
beadId: string;
|
|
216
|
+
branch: string;
|
|
217
|
+
exitCode: number;
|
|
218
|
+
filesModified: string[];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Supervisor signals branch is verified and ready for merge. */
|
|
222
|
+
interface MergeReadyPayload {
|
|
223
|
+
branch: string;
|
|
224
|
+
beadId: string;
|
|
225
|
+
agentName: string;
|
|
226
|
+
filesModified: string[];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Merger signals branch was merged successfully. */
|
|
230
|
+
interface MergedPayload {
|
|
231
|
+
branch: string;
|
|
232
|
+
beadId: string;
|
|
233
|
+
tier: ResolutionTier;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Merger signals merge failed, needs rework. */
|
|
237
|
+
interface MergeFailedPayload {
|
|
238
|
+
branch: string;
|
|
239
|
+
beadId: string;
|
|
240
|
+
conflictFiles: string[];
|
|
241
|
+
errorMessage: string;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Any agent escalates an issue to a higher-level decision-maker. */
|
|
245
|
+
interface EscalationPayload {
|
|
246
|
+
severity: "warning" | "error" | "critical";
|
|
247
|
+
beadId: string | null;
|
|
248
|
+
context: string;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Watchdog probes agent liveness. */
|
|
252
|
+
interface HealthCheckPayload {
|
|
253
|
+
agentName: string;
|
|
254
|
+
checkType: "liveness" | "readiness";
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Coordinator dispatches work to a supervisor. */
|
|
258
|
+
interface DispatchPayload {
|
|
259
|
+
beadId: string;
|
|
260
|
+
specPath: string;
|
|
261
|
+
capability: Capability;
|
|
262
|
+
fileScope: string[];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Supervisor assigns work to a specific worker. */
|
|
266
|
+
interface AssignPayload {
|
|
267
|
+
beadId: string;
|
|
268
|
+
specPath: string;
|
|
269
|
+
workerName: string;
|
|
270
|
+
branch: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** Maps protocol message types to their payload interfaces. */
|
|
274
|
+
export interface MailPayloadMap {
|
|
275
|
+
worker_done: WorkerDonePayload;
|
|
276
|
+
merge_ready: MergeReadyPayload;
|
|
277
|
+
merged: MergedPayload;
|
|
278
|
+
merge_failed: MergeFailedPayload;
|
|
279
|
+
escalation: EscalationPayload;
|
|
280
|
+
health_check: HealthCheckPayload;
|
|
281
|
+
dispatch: DispatchPayload;
|
|
282
|
+
assign: AssignPayload;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// === Overlay ===
|
|
286
|
+
|
|
287
|
+
export interface OverlayConfig {
|
|
288
|
+
agentName: string;
|
|
289
|
+
beadId: string;
|
|
290
|
+
specPath: string | null;
|
|
291
|
+
branchName: string;
|
|
292
|
+
worktreePath: string;
|
|
293
|
+
fileScope: string[];
|
|
294
|
+
mulchDomains: string[];
|
|
295
|
+
parentAgent: string | null;
|
|
296
|
+
depth: number;
|
|
297
|
+
canSpawn: boolean;
|
|
298
|
+
capability: string;
|
|
299
|
+
/** Full content of the base agent definition file (Layer 1: role-specific HOW). */
|
|
300
|
+
baseDefinition: string;
|
|
301
|
+
/** Pre-fetched mulch expertise output to embed directly in the overlay. */
|
|
302
|
+
mulchExpertise?: string;
|
|
303
|
+
/** Absolute path to the canonical project root (for agents that need to write outside their worktree). */
|
|
304
|
+
canonicalRoot?: string;
|
|
305
|
+
/** When true, lead agents should skip reviewer spawning and self-verify quality gates instead. */
|
|
306
|
+
skipReview?: boolean;
|
|
307
|
+
/** Per-project quality gate commands, passed through from LegioConfig. */
|
|
308
|
+
qualityGates?: {
|
|
309
|
+
test: string;
|
|
310
|
+
lint: string;
|
|
311
|
+
typecheck: string;
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// === Merge Queue ===
|
|
316
|
+
|
|
317
|
+
export type ResolutionTier = "clean-merge" | "auto-resolve" | "ai-resolve" | "reimagine";
|
|
318
|
+
|
|
319
|
+
export interface MergeEntry {
|
|
320
|
+
branchName: string;
|
|
321
|
+
beadId: string;
|
|
322
|
+
agentName: string;
|
|
323
|
+
filesModified: string[];
|
|
324
|
+
enqueuedAt: string;
|
|
325
|
+
status: "pending" | "merging" | "merged" | "conflict" | "failed";
|
|
326
|
+
resolvedTier: ResolutionTier | null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface MergeResult {
|
|
330
|
+
entry: MergeEntry;
|
|
331
|
+
success: boolean;
|
|
332
|
+
tier: ResolutionTier;
|
|
333
|
+
conflictFiles: string[];
|
|
334
|
+
errorMessage: string | null;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Parsed conflict pattern from a single mulch record. */
|
|
338
|
+
export interface ParsedConflictPattern {
|
|
339
|
+
tier: ResolutionTier;
|
|
340
|
+
success: boolean;
|
|
341
|
+
files: string[];
|
|
342
|
+
agent: string;
|
|
343
|
+
branch: string;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** Historical conflict data assembled from mulch search results. */
|
|
347
|
+
export interface ConflictHistory {
|
|
348
|
+
/** Tiers to skip based on historical failure rates for these files. */
|
|
349
|
+
skipTiers: ResolutionTier[];
|
|
350
|
+
/** Descriptions of past successful resolutions for AI prompt enrichment. */
|
|
351
|
+
pastResolutions: string[];
|
|
352
|
+
/** Files predicted to conflict based on historical patterns. */
|
|
353
|
+
predictedConflictFiles: string[];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// === Watchdog ===
|
|
357
|
+
|
|
358
|
+
export interface HealthCheck {
|
|
359
|
+
agentName: string;
|
|
360
|
+
timestamp: string;
|
|
361
|
+
processAlive: boolean;
|
|
362
|
+
tmuxAlive: boolean;
|
|
363
|
+
pidAlive: boolean | null; // null when pid is unavailable
|
|
364
|
+
lastActivity: string;
|
|
365
|
+
state: AgentState;
|
|
366
|
+
action: "none" | "escalate" | "terminate" | "investigate";
|
|
367
|
+
/** Describes any conflict between observable state and recorded state. */
|
|
368
|
+
reconciliationNote: string | null;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// === Logging ===
|
|
372
|
+
|
|
373
|
+
export interface LogEvent {
|
|
374
|
+
timestamp: string;
|
|
375
|
+
level: "debug" | "info" | "warn" | "error";
|
|
376
|
+
event: string;
|
|
377
|
+
agentName: string | null;
|
|
378
|
+
data: Record<string, unknown>;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// === Metrics ===
|
|
382
|
+
|
|
383
|
+
export interface SessionMetrics {
|
|
384
|
+
agentName: string;
|
|
385
|
+
beadId: string;
|
|
386
|
+
capability: string;
|
|
387
|
+
startedAt: string;
|
|
388
|
+
completedAt: string | null;
|
|
389
|
+
durationMs: number;
|
|
390
|
+
exitCode: number | null;
|
|
391
|
+
mergeResult: ResolutionTier | null;
|
|
392
|
+
parentAgent: string | null;
|
|
393
|
+
runId?: string | null; // Links metric to a coordinator run
|
|
394
|
+
inputTokens: number;
|
|
395
|
+
outputTokens: number;
|
|
396
|
+
cacheReadTokens: number;
|
|
397
|
+
cacheCreationTokens: number;
|
|
398
|
+
estimatedCostUsd: number | null;
|
|
399
|
+
modelUsed: string | null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** A point-in-time token usage snapshot for a running agent session. */
|
|
403
|
+
export interface TokenSnapshot {
|
|
404
|
+
agentName: string;
|
|
405
|
+
inputTokens: number;
|
|
406
|
+
outputTokens: number;
|
|
407
|
+
cacheReadTokens: number;
|
|
408
|
+
cacheCreationTokens: number;
|
|
409
|
+
estimatedCostUsd: number | null;
|
|
410
|
+
modelUsed: string | null;
|
|
411
|
+
createdAt: string;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// === Task Groups (Batch Coordination) ===
|
|
415
|
+
|
|
416
|
+
export interface TaskGroup {
|
|
417
|
+
id: string; // "group-" + nanoid(8)
|
|
418
|
+
name: string;
|
|
419
|
+
memberIssueIds: string[]; // beads issue IDs tracked by this group
|
|
420
|
+
status: "active" | "completed";
|
|
421
|
+
createdAt: string; // ISO timestamp
|
|
422
|
+
completedAt: string | null; // ISO timestamp when all members closed
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export interface TaskGroupProgress {
|
|
426
|
+
group: TaskGroup;
|
|
427
|
+
total: number;
|
|
428
|
+
completed: number;
|
|
429
|
+
inProgress: number;
|
|
430
|
+
blocked: number;
|
|
431
|
+
open: number;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// === Event Store (Observability) ===
|
|
435
|
+
|
|
436
|
+
/** Event types for agent activity tracking. */
|
|
437
|
+
export type EventType =
|
|
438
|
+
| "tool_start"
|
|
439
|
+
| "tool_end"
|
|
440
|
+
| "session_start"
|
|
441
|
+
| "session_end"
|
|
442
|
+
| "mail_sent"
|
|
443
|
+
| "mail_received"
|
|
444
|
+
| "spawn"
|
|
445
|
+
| "error"
|
|
446
|
+
| "custom";
|
|
447
|
+
|
|
448
|
+
/** Severity levels for events. */
|
|
449
|
+
export type EventLevel = "debug" | "info" | "warn" | "error";
|
|
450
|
+
|
|
451
|
+
/** All valid event level strings as a runtime array for CHECK constraint generation. */
|
|
452
|
+
export const EVENT_LEVELS: readonly EventLevel[] = ["debug", "info", "warn", "error"] as const;
|
|
453
|
+
|
|
454
|
+
/** An event as stored in the SQLite events table. */
|
|
455
|
+
export interface StoredEvent {
|
|
456
|
+
id: number;
|
|
457
|
+
runId: string | null;
|
|
458
|
+
agentName: string;
|
|
459
|
+
sessionId: string | null;
|
|
460
|
+
eventType: EventType;
|
|
461
|
+
toolName: string | null;
|
|
462
|
+
toolArgs: string | null;
|
|
463
|
+
toolDurationMs: number | null;
|
|
464
|
+
level: EventLevel;
|
|
465
|
+
data: string | null;
|
|
466
|
+
createdAt: string;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/** Input for inserting a new event (id and createdAt are auto-generated). */
|
|
470
|
+
export type InsertEvent = Omit<StoredEvent, "id" | "createdAt">;
|
|
471
|
+
|
|
472
|
+
/** Options for filtering event queries. */
|
|
473
|
+
export interface EventQueryOptions {
|
|
474
|
+
limit?: number;
|
|
475
|
+
since?: string; // ISO timestamp
|
|
476
|
+
until?: string; // ISO timestamp
|
|
477
|
+
level?: EventLevel;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** Tool usage statistics returned by getToolStats. */
|
|
481
|
+
export interface ToolStats {
|
|
482
|
+
toolName: string;
|
|
483
|
+
count: number;
|
|
484
|
+
avgDurationMs: number;
|
|
485
|
+
maxDurationMs: number;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/** Interface for the SQLite-backed event store. */
|
|
489
|
+
export interface EventStore {
|
|
490
|
+
/** Insert a new event. Returns the auto-generated row ID. */
|
|
491
|
+
insert(event: InsertEvent): number;
|
|
492
|
+
/** Find the most recent unmatched tool_start for correlation. Returns start ID and duration. */
|
|
493
|
+
correlateToolEnd(
|
|
494
|
+
agentName: string,
|
|
495
|
+
toolName: string,
|
|
496
|
+
): { startId: number; durationMs: number } | null;
|
|
497
|
+
/** Get events for a specific agent. */
|
|
498
|
+
getByAgent(agentName: string, opts?: EventQueryOptions): StoredEvent[];
|
|
499
|
+
/** Get events for a specific run. */
|
|
500
|
+
getByRun(runId: string, opts?: EventQueryOptions): StoredEvent[];
|
|
501
|
+
/** Get error-level events. */
|
|
502
|
+
getErrors(opts?: EventQueryOptions): StoredEvent[];
|
|
503
|
+
/** Get a timeline of events with required options. */
|
|
504
|
+
getTimeline(opts: EventQueryOptions & { since: string }): StoredEvent[];
|
|
505
|
+
/** Get aggregated tool usage statistics. */
|
|
506
|
+
getToolStats(opts?: { agentName?: string; since?: string }): ToolStats[];
|
|
507
|
+
/** Delete events matching criteria. Returns number of rows deleted. */
|
|
508
|
+
purge(opts: { all?: boolean; olderThanMs?: number; agentName?: string }): number;
|
|
509
|
+
/** Close the database connection. */
|
|
510
|
+
close(): void;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// === Run (Coordinator Session Grouping) ===
|
|
514
|
+
|
|
515
|
+
/** Status of a run (coordinator session grouping agents). */
|
|
516
|
+
export type RunStatus = "active" | "completed" | "failed";
|
|
517
|
+
|
|
518
|
+
/** A run groups all agents spawned from one coordinator session. */
|
|
519
|
+
export interface Run {
|
|
520
|
+
id: string; // Format: run-{ISO timestamp}
|
|
521
|
+
startedAt: string;
|
|
522
|
+
completedAt: string | null;
|
|
523
|
+
agentCount: number;
|
|
524
|
+
coordinatorSessionId: string | null;
|
|
525
|
+
status: RunStatus;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** Input for creating a new run. */
|
|
529
|
+
export type InsertRun = Omit<Run, "completedAt" | "agentCount"> & {
|
|
530
|
+
agentCount?: number;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
/** Interface for run management operations. */
|
|
534
|
+
export interface RunStore {
|
|
535
|
+
/** Create a new run. */
|
|
536
|
+
createRun(run: InsertRun): void;
|
|
537
|
+
/** Get a run by ID, or null if not found. */
|
|
538
|
+
getRun(id: string): Run | null;
|
|
539
|
+
/** Get the most recently started active run. */
|
|
540
|
+
getActiveRun(): Run | null;
|
|
541
|
+
/** List runs, optionally limited. */
|
|
542
|
+
listRuns(opts?: { limit?: number; status?: RunStatus }): Run[];
|
|
543
|
+
/** Increment agent count for a run. */
|
|
544
|
+
incrementAgentCount(runId: string): void;
|
|
545
|
+
/** Complete a run (set status and completedAt). */
|
|
546
|
+
completeRun(runId: string, status: "completed" | "failed"): void;
|
|
547
|
+
/** Close the store (if standalone — in practice may share DB with SessionStore). */
|
|
548
|
+
close(): void;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// === Mulch CLI Results ===
|
|
552
|
+
|
|
553
|
+
/** Mulch status result (domain statistics). */
|
|
554
|
+
export interface MulchStatus {
|
|
555
|
+
domains: Array<{ name: string; recordCount: number; lastUpdated: string }>;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Result from mulch diff command. */
|
|
559
|
+
export interface MulchDiffResult {
|
|
560
|
+
success: boolean;
|
|
561
|
+
command: string;
|
|
562
|
+
since: string;
|
|
563
|
+
domains: string[];
|
|
564
|
+
message: string;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/** Result from mulch learn command. */
|
|
568
|
+
export interface MulchLearnResult {
|
|
569
|
+
success: boolean;
|
|
570
|
+
command: string;
|
|
571
|
+
changedFiles: string[];
|
|
572
|
+
suggestedDomains: string[];
|
|
573
|
+
unmatchedFiles: string[];
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** Result from mulch prune command. */
|
|
577
|
+
export interface MulchPruneResult {
|
|
578
|
+
success: boolean;
|
|
579
|
+
command: string;
|
|
580
|
+
dryRun: boolean;
|
|
581
|
+
totalPruned: number;
|
|
582
|
+
results: Array<{
|
|
583
|
+
domain: string;
|
|
584
|
+
pruned: number;
|
|
585
|
+
records: string[];
|
|
586
|
+
}>;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/** Health check result from mulch doctor. */
|
|
590
|
+
export interface MulchDoctorResult {
|
|
591
|
+
success: boolean;
|
|
592
|
+
command: string;
|
|
593
|
+
checks: Array<{
|
|
594
|
+
name: string;
|
|
595
|
+
status: "pass" | "warn" | "fail";
|
|
596
|
+
message: string;
|
|
597
|
+
fixable: boolean;
|
|
598
|
+
details: string[];
|
|
599
|
+
}>;
|
|
600
|
+
summary: {
|
|
601
|
+
pass: number;
|
|
602
|
+
warn: number;
|
|
603
|
+
fail: number;
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/** Ready records result from mulch ready. */
|
|
608
|
+
export interface MulchReadyResult {
|
|
609
|
+
success: boolean;
|
|
610
|
+
command: string;
|
|
611
|
+
count: number;
|
|
612
|
+
entries: Array<{
|
|
613
|
+
domain: string;
|
|
614
|
+
id: string;
|
|
615
|
+
type: string;
|
|
616
|
+
recorded_at: string;
|
|
617
|
+
summary: string;
|
|
618
|
+
record: Record<string, unknown>;
|
|
619
|
+
}>;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/** Result from mulch compact command. */
|
|
623
|
+
export interface MulchCompactResult {
|
|
624
|
+
success: boolean;
|
|
625
|
+
command: string;
|
|
626
|
+
action: string;
|
|
627
|
+
candidates?: Array<{
|
|
628
|
+
domain: string;
|
|
629
|
+
type: string;
|
|
630
|
+
records: Array<{
|
|
631
|
+
id: string;
|
|
632
|
+
summary: string;
|
|
633
|
+
recorded_at: string;
|
|
634
|
+
}>;
|
|
635
|
+
}>;
|
|
636
|
+
compacted?: Array<{
|
|
637
|
+
domain: string;
|
|
638
|
+
type: string;
|
|
639
|
+
before: number;
|
|
640
|
+
after: number;
|
|
641
|
+
recordIds: string[];
|
|
642
|
+
}>;
|
|
643
|
+
message?: string;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// === Session Lifecycle (Checkpoint / Handoff / Continuity) ===
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Snapshot of agent progress, saved before compaction or handoff.
|
|
650
|
+
* Stored as JSON in .legio/agents/{name}/checkpoint.json.
|
|
651
|
+
*/
|
|
652
|
+
export interface SessionCheckpoint {
|
|
653
|
+
agentName: string;
|
|
654
|
+
beadId: string;
|
|
655
|
+
sessionId: string; // The AgentSession.id that created this checkpoint
|
|
656
|
+
timestamp: string; // ISO
|
|
657
|
+
progressSummary: string; // Human-readable summary of work done so far
|
|
658
|
+
filesModified: string[]; // Paths modified since session start
|
|
659
|
+
currentBranch: string;
|
|
660
|
+
pendingWork: string; // What remains to be done
|
|
661
|
+
mulchDomains: string[]; // Domains the agent has been working in
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Record of a session handoff — when one session ends and another picks up.
|
|
666
|
+
*/
|
|
667
|
+
export interface SessionHandoff {
|
|
668
|
+
fromSessionId: string;
|
|
669
|
+
toSessionId: string | null; // null until the new session starts
|
|
670
|
+
checkpoint: SessionCheckpoint;
|
|
671
|
+
reason: "compaction" | "crash" | "manual" | "timeout";
|
|
672
|
+
handoffAt: string; // ISO timestamp
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// === Session Insight Analysis ===
|
|
676
|
+
|
|
677
|
+
/** A single structured insight extracted from a completed session. */
|
|
678
|
+
export interface SessionInsight {
|
|
679
|
+
/** Mulch record type for this insight. */
|
|
680
|
+
type: "pattern" | "convention" | "failure";
|
|
681
|
+
/** Mulch domain this insight belongs to. */
|
|
682
|
+
domain: string;
|
|
683
|
+
/** Human-readable description of the insight. */
|
|
684
|
+
description: string;
|
|
685
|
+
/** Tags for mulch record categorization. */
|
|
686
|
+
tags: string[];
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/** Aggregated tool usage profile for a session. */
|
|
690
|
+
export interface ToolProfile {
|
|
691
|
+
topTools: Array<{ name: string; count: number; avgMs: number }>;
|
|
692
|
+
totalToolCalls: number;
|
|
693
|
+
errorCount: number;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/** File edit frequency profile for a session. */
|
|
697
|
+
export interface FileProfile {
|
|
698
|
+
/** Files edited more than once, sorted by edit count descending. */
|
|
699
|
+
hotFiles: Array<{ path: string; editCount: number }>;
|
|
700
|
+
totalEdits: number;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/** Complete insight analysis result for a completed session. */
|
|
704
|
+
export interface InsightAnalysis {
|
|
705
|
+
insights: SessionInsight[];
|
|
706
|
+
toolProfile: ToolProfile;
|
|
707
|
+
fileProfile: FileProfile;
|
|
708
|
+
}
|