oxe-cc 1.2.1 → 1.4.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.
Files changed (281) hide show
  1. package/.cursor/commands/oxe-ask.md +2 -2
  2. package/.cursor/commands/oxe-capabilities.md +2 -2
  3. package/.cursor/commands/oxe-checkpoint.md +2 -2
  4. package/.cursor/commands/oxe-compact.md +2 -2
  5. package/.cursor/commands/oxe-dashboard.md +2 -2
  6. package/.cursor/commands/oxe-debug.md +2 -2
  7. package/.cursor/commands/oxe-discuss.md +2 -2
  8. package/.cursor/commands/oxe-execute.md +5 -2
  9. package/.cursor/commands/oxe-forensics.md +2 -2
  10. package/.cursor/commands/oxe-help.md +2 -2
  11. package/.cursor/commands/oxe-loop.md +2 -2
  12. package/.cursor/commands/oxe-milestone.md +2 -2
  13. package/.cursor/commands/oxe-next.md +2 -2
  14. package/.cursor/commands/oxe-obs.md +2 -2
  15. package/.cursor/commands/oxe-plan-agent.md +2 -2
  16. package/.cursor/commands/oxe-plan.md +2 -2
  17. package/.cursor/commands/oxe-project.md +2 -2
  18. package/.cursor/commands/oxe-quick.md +2 -2
  19. package/.cursor/commands/oxe-research.md +2 -2
  20. package/.cursor/commands/oxe-retro.md +2 -2
  21. package/.cursor/commands/oxe-review-pr.md +2 -2
  22. package/.cursor/commands/oxe-route.md +2 -2
  23. package/.cursor/commands/oxe-scan.md +2 -2
  24. package/.cursor/commands/oxe-security.md +2 -2
  25. package/.cursor/commands/oxe-session.md +2 -2
  26. package/.cursor/commands/oxe-ship.md +2 -2
  27. package/.cursor/commands/oxe-skill.md +2 -2
  28. package/.cursor/commands/oxe-spec.md +2 -2
  29. package/.cursor/commands/oxe-ui-review.md +2 -2
  30. package/.cursor/commands/oxe-ui-spec.md +2 -2
  31. package/.cursor/commands/oxe-update.md +2 -2
  32. package/.cursor/commands/oxe-validate-gaps.md +2 -2
  33. package/.cursor/commands/oxe-verify.md +5 -2
  34. package/.cursor/commands/oxe-workstream.md +2 -2
  35. package/.cursor/commands/oxe.md +2 -2
  36. package/.github/copilot-instructions.md +13 -13
  37. package/.github/prompts/oxe-ask.prompt.md +2 -2
  38. package/.github/prompts/oxe-capabilities.prompt.md +2 -2
  39. package/.github/prompts/oxe-checkpoint.prompt.md +2 -2
  40. package/.github/prompts/oxe-compact.prompt.md +2 -2
  41. package/.github/prompts/oxe-dashboard.prompt.md +2 -2
  42. package/.github/prompts/oxe-debug.prompt.md +2 -2
  43. package/.github/prompts/oxe-discuss.prompt.md +2 -2
  44. package/.github/prompts/oxe-execute.prompt.md +5 -2
  45. package/.github/prompts/oxe-forensics.prompt.md +2 -2
  46. package/.github/prompts/oxe-help.prompt.md +2 -2
  47. package/.github/prompts/oxe-loop.prompt.md +2 -2
  48. package/.github/prompts/oxe-milestone.prompt.md +2 -2
  49. package/.github/prompts/oxe-next.prompt.md +2 -2
  50. package/.github/prompts/oxe-obs.prompt.md +2 -2
  51. package/.github/prompts/oxe-plan-agent.prompt.md +2 -2
  52. package/.github/prompts/oxe-plan.prompt.md +2 -2
  53. package/.github/prompts/oxe-project.prompt.md +2 -2
  54. package/.github/prompts/oxe-quick.prompt.md +2 -2
  55. package/.github/prompts/oxe-research.prompt.md +2 -2
  56. package/.github/prompts/oxe-retro.prompt.md +2 -2
  57. package/.github/prompts/oxe-review-pr.prompt.md +2 -2
  58. package/.github/prompts/oxe-route.prompt.md +2 -2
  59. package/.github/prompts/oxe-scan.prompt.md +2 -2
  60. package/.github/prompts/oxe-security.prompt.md +2 -2
  61. package/.github/prompts/oxe-session.prompt.md +2 -2
  62. package/.github/prompts/oxe-ship.prompt.md +2 -2
  63. package/.github/prompts/oxe-skill.prompt.md +2 -2
  64. package/.github/prompts/oxe-spec.prompt.md +2 -2
  65. package/.github/prompts/oxe-ui-review.prompt.md +2 -2
  66. package/.github/prompts/oxe-ui-spec.prompt.md +2 -2
  67. package/.github/prompts/oxe-update.prompt.md +2 -2
  68. package/.github/prompts/oxe-validate-gaps.prompt.md +2 -2
  69. package/.github/prompts/oxe-verify.prompt.md +5 -2
  70. package/.github/prompts/oxe-workstream.prompt.md +2 -2
  71. package/.github/prompts/oxe.prompt.md +2 -2
  72. package/AGENTS.md +5 -3
  73. package/CHANGELOG.md +72 -10
  74. package/LICENSE +21 -674
  75. package/README.md +631 -535
  76. package/bin/banner.txt +6 -6
  77. package/bin/lib/oxe-agent-install.cjs +69 -69
  78. package/bin/lib/oxe-azure.cjs +1445 -1445
  79. package/bin/lib/oxe-context-engine.cjs +867 -867
  80. package/bin/lib/oxe-dashboard.cjs +76 -28
  81. package/bin/lib/oxe-operational.cjs +2144 -1340
  82. package/bin/lib/oxe-project-health.cjs +483 -1
  83. package/bin/lib/oxe-runtime-semantics.cjs +12 -0
  84. package/bin/oxe-cc.js +554 -152
  85. package/commands/oxe/ask.md +2 -2
  86. package/commands/oxe/capabilities.md +2 -2
  87. package/commands/oxe/checkpoint.md +2 -2
  88. package/commands/oxe/compact.md +2 -2
  89. package/commands/oxe/dashboard.md +2 -2
  90. package/commands/oxe/debug.md +2 -2
  91. package/commands/oxe/discuss.md +2 -2
  92. package/commands/oxe/execute.md +5 -2
  93. package/commands/oxe/forensics.md +2 -2
  94. package/commands/oxe/help.md +2 -2
  95. package/commands/oxe/loop.md +2 -2
  96. package/commands/oxe/milestone.md +2 -2
  97. package/commands/oxe/next.md +2 -2
  98. package/commands/oxe/obs.md +2 -2
  99. package/commands/oxe/oxe.md +2 -2
  100. package/commands/oxe/plan-agent.md +2 -2
  101. package/commands/oxe/plan.md +2 -2
  102. package/commands/oxe/project.md +2 -2
  103. package/commands/oxe/quick.md +2 -2
  104. package/commands/oxe/research.md +2 -2
  105. package/commands/oxe/retro.md +2 -2
  106. package/commands/oxe/review-pr.md +2 -2
  107. package/commands/oxe/route.md +2 -2
  108. package/commands/oxe/scan.md +2 -2
  109. package/commands/oxe/security.md +2 -2
  110. package/commands/oxe/session.md +2 -2
  111. package/commands/oxe/ship.md +2 -2
  112. package/commands/oxe/skill.md +2 -2
  113. package/commands/oxe/spec.md +2 -2
  114. package/commands/oxe/ui-review.md +2 -2
  115. package/commands/oxe/ui-spec.md +2 -2
  116. package/commands/oxe/update.md +2 -2
  117. package/commands/oxe/validate-gaps.md +2 -2
  118. package/commands/oxe/verify.md +5 -2
  119. package/commands/oxe/workstream.md +2 -2
  120. package/lib/runtime/delivery/branch-manager.d.ts +1 -0
  121. package/lib/runtime/delivery/branch-manager.js +7 -0
  122. package/lib/runtime/delivery/ci-checks.js +34 -1
  123. package/lib/runtime/delivery/delivery-records.d.ts +34 -0
  124. package/lib/runtime/delivery/delivery-records.js +48 -0
  125. package/lib/runtime/delivery/index.d.ts +1 -0
  126. package/lib/runtime/delivery/index.js +1 -0
  127. package/lib/runtime/delivery/promotion-pipeline.d.ts +26 -2
  128. package/lib/runtime/delivery/promotion-pipeline.js +111 -14
  129. package/lib/runtime/gate/gate-manager.d.ts +41 -0
  130. package/lib/runtime/gate/gate-manager.js +108 -1
  131. package/lib/runtime/index.d.ts +2 -2
  132. package/lib/runtime/index.js +3 -1
  133. package/lib/runtime/models/gate-decision.d.ts +4 -1
  134. package/lib/runtime/models/workspace.d.ts +3 -0
  135. package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
  136. package/lib/runtime/plugins/capability-adapter.js +204 -0
  137. package/lib/runtime/plugins/capability-matrix.d.ts +5 -0
  138. package/lib/runtime/plugins/capability-matrix.js +48 -17
  139. package/lib/runtime/plugins/index.d.ts +1 -0
  140. package/lib/runtime/plugins/index.js +1 -0
  141. package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
  142. package/lib/runtime/plugins/plugin-manifest.d.ts +1 -1
  143. package/lib/runtime/plugins/plugin-manifest.js +6 -2
  144. package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
  145. package/lib/runtime/plugins/plugin-registry.js +79 -2
  146. package/lib/runtime/policy/policy-engine.d.ts +19 -0
  147. package/lib/runtime/policy/policy-engine.js +76 -4
  148. package/lib/runtime/projection/projection-engine.d.ts +9 -1
  149. package/lib/runtime/projection/projection-engine.js +73 -3
  150. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +43 -1
  151. package/lib/runtime/scheduler/multi-agent-coordinator.js +151 -39
  152. package/lib/runtime/scheduler/run-journal.d.ts +1 -1
  153. package/lib/runtime/scheduler/scheduler.d.ts +19 -1
  154. package/lib/runtime/scheduler/scheduler.js +258 -13
  155. package/lib/runtime/verification/verification-compiler.d.ts +43 -0
  156. package/lib/runtime/verification/verification-compiler.js +137 -0
  157. package/lib/runtime/verification/verification-manifest.d.ts +9 -0
  158. package/lib/runtime/verification/verification-manifest.js +56 -6
  159. package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
  160. package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
  161. package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
  162. package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
  163. package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
  164. package/lib/runtime/workspace/strategies/inplace.js +2 -0
  165. package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
  166. package/lib/sdk/README.md +20 -8
  167. package/lib/sdk/index.cjs +33 -24
  168. package/lib/sdk/index.d.ts +149 -14
  169. package/oxe/templates/ACTIVE-RUN.template.json +32 -32
  170. package/oxe/templates/CAPABILITIES.template.md +7 -7
  171. package/oxe/templates/CAPABILITY.template.md +45 -45
  172. package/oxe/templates/CHECKPOINTS.template.md +7 -7
  173. package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
  174. package/oxe/templates/HYPOTHESES.template.md +33 -33
  175. package/oxe/templates/LESSONS-METRICS.template.json +13 -13
  176. package/oxe/templates/NOTES.template.md +16 -16
  177. package/oxe/templates/PLAN-REVIEW.template.md +31 -31
  178. package/oxe/templates/SESSION.template.md +34 -34
  179. package/oxe/templates/SKILL.template.md +26 -26
  180. package/oxe/templates/STATE.md +55 -55
  181. package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
  182. package/oxe/workflows/ask.md +96 -96
  183. package/oxe/workflows/capabilities.md +25 -25
  184. package/oxe/workflows/dashboard.md +33 -33
  185. package/oxe/workflows/discuss.md +12 -12
  186. package/oxe/workflows/execute.md +14 -0
  187. package/oxe/workflows/help.md +352 -352
  188. package/oxe/workflows/next.md +22 -22
  189. package/oxe/workflows/oxe.md +6 -6
  190. package/oxe/workflows/plan-agent.md +9 -9
  191. package/oxe/workflows/plan.md +51 -20
  192. package/oxe/workflows/quick.md +10 -10
  193. package/oxe/workflows/references/reasoning-discovery.md +28 -28
  194. package/oxe/workflows/references/reasoning-execution.md +29 -29
  195. package/oxe/workflows/references/reasoning-planning.md +32 -32
  196. package/oxe/workflows/references/reasoning-review.md +29 -29
  197. package/oxe/workflows/references/reasoning-status.md +24 -24
  198. package/oxe/workflows/references/robustness-elevation.md +295 -295
  199. package/oxe/workflows/references/workflow-runtime-contracts.json +952 -930
  200. package/oxe/workflows/route.md +16 -16
  201. package/oxe/workflows/session.md +213 -213
  202. package/oxe/workflows/ship.md +142 -142
  203. package/oxe/workflows/skill.md +44 -44
  204. package/oxe/workflows/ui-review.md +36 -36
  205. package/oxe/workflows/verify-audit.md +73 -73
  206. package/oxe/workflows/verify.md +10 -0
  207. package/package.json +92 -92
  208. package/packages/runtime/package.json +16 -15
  209. package/packages/runtime/src/audit/audit-trail.ts +243 -243
  210. package/packages/runtime/src/audit/index.ts +2 -2
  211. package/packages/runtime/src/audit/policy-pack.ts +62 -62
  212. package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
  213. package/packages/runtime/src/compiler/index.ts +1 -1
  214. package/packages/runtime/src/context/context-pack-builder.ts +259 -259
  215. package/packages/runtime/src/context/context-pack-store.ts +197 -197
  216. package/packages/runtime/src/context/context-profiles.ts +60 -60
  217. package/packages/runtime/src/context/index.ts +3 -3
  218. package/packages/runtime/src/decision/decision-engine.ts +174 -174
  219. package/packages/runtime/src/decision/decision-memo.ts +211 -211
  220. package/packages/runtime/src/decision/index.ts +2 -2
  221. package/packages/runtime/src/delivery/branch-manager.ts +91 -84
  222. package/packages/runtime/src/delivery/ci-checks.ts +285 -252
  223. package/packages/runtime/src/delivery/delivery-records.ts +75 -0
  224. package/packages/runtime/src/delivery/index.ts +5 -4
  225. package/packages/runtime/src/delivery/pr-manager.ts +112 -112
  226. package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -180
  227. package/packages/runtime/src/events/bus.ts +92 -92
  228. package/packages/runtime/src/events/catalog.ts +29 -29
  229. package/packages/runtime/src/events/envelope.ts +14 -14
  230. package/packages/runtime/src/events/index.ts +3 -3
  231. package/packages/runtime/src/evidence/evidence-store.ts +130 -130
  232. package/packages/runtime/src/evidence/index.ts +1 -1
  233. package/packages/runtime/src/gate/gate-manager.ts +289 -137
  234. package/packages/runtime/src/gate/index.ts +1 -1
  235. package/packages/runtime/src/index.ts +41 -37
  236. package/packages/runtime/src/models/attempt.ts +19 -19
  237. package/packages/runtime/src/models/evidence.ts +21 -21
  238. package/packages/runtime/src/models/gate-decision.ts +25 -21
  239. package/packages/runtime/src/models/index.ts +8 -8
  240. package/packages/runtime/src/models/run.ts +24 -24
  241. package/packages/runtime/src/models/session.ts +11 -11
  242. package/packages/runtime/src/models/verification-result.ts +10 -10
  243. package/packages/runtime/src/models/work-item.ts +25 -25
  244. package/packages/runtime/src/models/workspace.ts +31 -28
  245. package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
  246. package/packages/runtime/src/plugins/capability-matrix.ts +126 -83
  247. package/packages/runtime/src/plugins/index.ts +5 -4
  248. package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
  249. package/packages/runtime/src/plugins/plugin-manifest.ts +118 -113
  250. package/packages/runtime/src/plugins/plugin-registry.ts +232 -124
  251. package/packages/runtime/src/policy/index.ts +1 -1
  252. package/packages/runtime/src/policy/policy-engine.ts +330 -244
  253. package/packages/runtime/src/projection/index.ts +1 -1
  254. package/packages/runtime/src/projection/projection-engine.ts +328 -249
  255. package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
  256. package/packages/runtime/src/reducers/index.ts +2 -2
  257. package/packages/runtime/src/reducers/run-state-reducer.ts +269 -269
  258. package/packages/runtime/src/scheduler/agent-registry.ts +132 -132
  259. package/packages/runtime/src/scheduler/agent-roles.ts +109 -109
  260. package/packages/runtime/src/scheduler/index.ts +4 -4
  261. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -333
  262. package/packages/runtime/src/scheduler/run-journal.ts +62 -62
  263. package/packages/runtime/src/scheduler/scheduler.ts +722 -441
  264. package/packages/runtime/src/verification/index.ts +2 -2
  265. package/packages/runtime/src/verification/verification-compiler.ts +436 -225
  266. package/packages/runtime/src/verification/verification-manifest.ts +252 -192
  267. package/packages/runtime/src/workspace/index.ts +5 -5
  268. package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
  269. package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
  270. package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
  271. package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
  272. package/packages/runtime/tsconfig.json +17 -17
  273. package/vscode-extension/.vscodeignore +7 -7
  274. package/vscode-extension/LICENSE +21 -0
  275. package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
  276. package/vscode-extension/oxe-agents-1.4.0.vsix +0 -0
  277. package/vscode-extension/package.json +184 -184
  278. package/vscode-extension/src/extension.js +310 -310
  279. package/vscode-extension/src/shared/contextLoader.js +137 -137
  280. package/vscode-extension/src/shared/contractBuilder.js +159 -159
  281. package/vscode-extension/src/shared/stateReader.js +101 -101
@@ -1,132 +1,132 @@
1
- import type { TaskExecutor } from './scheduler';
2
- import type { WorkspaceManager } from '../workspace/workspace-manager';
3
- import type { AgentRole, AgentActionLog } from './agent-roles';
4
-
5
- export type AgentStatus = 'idle' | 'running' | 'paused' | 'failed' | 'timeout';
6
-
7
- export interface AgentHeartbeat {
8
- agent_id: string;
9
- last_seen: string;
10
- current_task: string | null;
11
- status: AgentStatus;
12
- }
13
-
14
- export interface RegisteredAgent {
15
- id: string;
16
- executor: TaskExecutor;
17
- workspaceManager: WorkspaceManager;
18
- assignedTaskIds: string[];
19
- heartbeat: AgentHeartbeat;
20
- role?: AgentRole;
21
- actionLog: AgentActionLog[];
22
- }
23
-
24
- export class AgentRegistry {
25
- private agents = new Map<string, RegisteredAgent>();
26
- private readonly heartbeatTimeoutMs: number;
27
-
28
- constructor(heartbeatTimeoutMs = 30_000) {
29
- this.heartbeatTimeoutMs = heartbeatTimeoutMs;
30
- }
31
-
32
- register(
33
- id: string,
34
- executor: TaskExecutor,
35
- workspaceManager: WorkspaceManager,
36
- assignedTaskIds: string[] = [],
37
- role?: AgentRole
38
- ): RegisteredAgent {
39
- if (this.agents.has(id)) throw new Error(`Agent "${id}" is already registered`);
40
- const agent: RegisteredAgent = {
41
- id,
42
- executor,
43
- workspaceManager,
44
- assignedTaskIds,
45
- heartbeat: {
46
- agent_id: id,
47
- last_seen: new Date().toISOString(),
48
- current_task: null,
49
- status: 'idle',
50
- },
51
- role,
52
- actionLog: [],
53
- };
54
- this.agents.set(id, agent);
55
- return agent;
56
- }
57
-
58
- unregister(id: string): void {
59
- this.agents.delete(id);
60
- }
61
-
62
- beat(id: string, currentTask: string | null = null): void {
63
- const agent = this.agents.get(id);
64
- if (!agent) return;
65
- agent.heartbeat.last_seen = new Date().toISOString();
66
- agent.heartbeat.current_task = currentTask;
67
- agent.heartbeat.status = currentTask ? 'running' : 'idle';
68
- }
69
-
70
- setStatus(id: string, status: AgentStatus): void {
71
- const agent = this.agents.get(id);
72
- if (agent) agent.heartbeat.status = status;
73
- }
74
-
75
- isAlive(id: string): boolean {
76
- const agent = this.agents.get(id);
77
- if (!agent) return false;
78
- const elapsed = Date.now() - new Date(agent.heartbeat.last_seen).getTime();
79
- return elapsed < this.heartbeatTimeoutMs;
80
- }
81
-
82
- /** Returns agents that haven't sent a heartbeat within the timeout window */
83
- timedOut(): RegisteredAgent[] {
84
- return [...this.agents.values()].filter((a) => !this.isAlive(a.id));
85
- }
86
-
87
- liveAgents(): RegisteredAgent[] {
88
- return [...this.agents.values()].filter((a) => this.isAlive(a.id));
89
- }
90
-
91
- get(id: string): RegisteredAgent | null {
92
- return this.agents.get(id) ?? null;
93
- }
94
-
95
- list(): RegisteredAgent[] {
96
- return [...this.agents.values()];
97
- }
98
-
99
- /**
100
- * Reassign orphaned tasks from timed-out agents to a fallback agent.
101
- * Returns the list of task IDs that were reassigned.
102
- */
103
- failover(fallbackAgentId: string): string[] {
104
- const fallback = this.agents.get(fallbackAgentId);
105
- if (!fallback) throw new Error(`Fallback agent "${fallbackAgentId}" not found`);
106
-
107
- const orphaned: string[] = [];
108
- for (const agent of this.timedOut()) {
109
- orphaned.push(...agent.assignedTaskIds);
110
- agent.assignedTaskIds = [];
111
- agent.heartbeat.status = 'failed';
112
- }
113
-
114
- fallback.assignedTaskIds = [...fallback.assignedTaskIds, ...orphaned];
115
- return orphaned;
116
- }
117
-
118
- /** Return all agents assigned to a given role */
119
- getByRole(role: AgentRole): RegisteredAgent[] {
120
- return [...this.agents.values()].filter((a) => a.role === role);
121
- }
122
-
123
- /** Append an action log entry for a registered agent (no-op if unknown) */
124
- logAction(agentId: string, log: AgentActionLog): void {
125
- const agent = this.agents.get(agentId);
126
- if (agent) agent.actionLog.push(log);
127
- }
128
-
129
- clear(): void {
130
- this.agents.clear();
131
- }
132
- }
1
+ import type { TaskExecutor } from './scheduler';
2
+ import type { WorkspaceManager } from '../workspace/workspace-manager';
3
+ import type { AgentRole, AgentActionLog } from './agent-roles';
4
+
5
+ export type AgentStatus = 'idle' | 'running' | 'paused' | 'failed' | 'timeout';
6
+
7
+ export interface AgentHeartbeat {
8
+ agent_id: string;
9
+ last_seen: string;
10
+ current_task: string | null;
11
+ status: AgentStatus;
12
+ }
13
+
14
+ export interface RegisteredAgent {
15
+ id: string;
16
+ executor: TaskExecutor;
17
+ workspaceManager: WorkspaceManager;
18
+ assignedTaskIds: string[];
19
+ heartbeat: AgentHeartbeat;
20
+ role?: AgentRole;
21
+ actionLog: AgentActionLog[];
22
+ }
23
+
24
+ export class AgentRegistry {
25
+ private agents = new Map<string, RegisteredAgent>();
26
+ private readonly heartbeatTimeoutMs: number;
27
+
28
+ constructor(heartbeatTimeoutMs = 30_000) {
29
+ this.heartbeatTimeoutMs = heartbeatTimeoutMs;
30
+ }
31
+
32
+ register(
33
+ id: string,
34
+ executor: TaskExecutor,
35
+ workspaceManager: WorkspaceManager,
36
+ assignedTaskIds: string[] = [],
37
+ role?: AgentRole
38
+ ): RegisteredAgent {
39
+ if (this.agents.has(id)) throw new Error(`Agent "${id}" is already registered`);
40
+ const agent: RegisteredAgent = {
41
+ id,
42
+ executor,
43
+ workspaceManager,
44
+ assignedTaskIds,
45
+ heartbeat: {
46
+ agent_id: id,
47
+ last_seen: new Date().toISOString(),
48
+ current_task: null,
49
+ status: 'idle',
50
+ },
51
+ role,
52
+ actionLog: [],
53
+ };
54
+ this.agents.set(id, agent);
55
+ return agent;
56
+ }
57
+
58
+ unregister(id: string): void {
59
+ this.agents.delete(id);
60
+ }
61
+
62
+ beat(id: string, currentTask: string | null = null): void {
63
+ const agent = this.agents.get(id);
64
+ if (!agent) return;
65
+ agent.heartbeat.last_seen = new Date().toISOString();
66
+ agent.heartbeat.current_task = currentTask;
67
+ agent.heartbeat.status = currentTask ? 'running' : 'idle';
68
+ }
69
+
70
+ setStatus(id: string, status: AgentStatus): void {
71
+ const agent = this.agents.get(id);
72
+ if (agent) agent.heartbeat.status = status;
73
+ }
74
+
75
+ isAlive(id: string): boolean {
76
+ const agent = this.agents.get(id);
77
+ if (!agent) return false;
78
+ const elapsed = Date.now() - new Date(agent.heartbeat.last_seen).getTime();
79
+ return elapsed < this.heartbeatTimeoutMs;
80
+ }
81
+
82
+ /** Returns agents that haven't sent a heartbeat within the timeout window */
83
+ timedOut(): RegisteredAgent[] {
84
+ return [...this.agents.values()].filter((a) => !this.isAlive(a.id));
85
+ }
86
+
87
+ liveAgents(): RegisteredAgent[] {
88
+ return [...this.agents.values()].filter((a) => this.isAlive(a.id));
89
+ }
90
+
91
+ get(id: string): RegisteredAgent | null {
92
+ return this.agents.get(id) ?? null;
93
+ }
94
+
95
+ list(): RegisteredAgent[] {
96
+ return [...this.agents.values()];
97
+ }
98
+
99
+ /**
100
+ * Reassign orphaned tasks from timed-out agents to a fallback agent.
101
+ * Returns the list of task IDs that were reassigned.
102
+ */
103
+ failover(fallbackAgentId: string): string[] {
104
+ const fallback = this.agents.get(fallbackAgentId);
105
+ if (!fallback) throw new Error(`Fallback agent "${fallbackAgentId}" not found`);
106
+
107
+ const orphaned: string[] = [];
108
+ for (const agent of this.timedOut()) {
109
+ orphaned.push(...agent.assignedTaskIds);
110
+ agent.assignedTaskIds = [];
111
+ agent.heartbeat.status = 'failed';
112
+ }
113
+
114
+ fallback.assignedTaskIds = [...fallback.assignedTaskIds, ...orphaned];
115
+ return orphaned;
116
+ }
117
+
118
+ /** Return all agents assigned to a given role */
119
+ getByRole(role: AgentRole): RegisteredAgent[] {
120
+ return [...this.agents.values()].filter((a) => a.role === role);
121
+ }
122
+
123
+ /** Append an action log entry for a registered agent (no-op if unknown) */
124
+ logAction(agentId: string, log: AgentActionLog): void {
125
+ const agent = this.agents.get(agentId);
126
+ if (agent) agent.actionLog.push(log);
127
+ }
128
+
129
+ clear(): void {
130
+ this.agents.clear();
131
+ }
132
+ }
@@ -1,109 +1,109 @@
1
- import type { TaskResult } from './scheduler';
2
-
3
- export type AgentRole = 'planner' | 'executor' | 'reviewer' | 'verifier';
4
-
5
- export interface AgentBudget {
6
- max_tokens: number;
7
- max_time_ms: number;
8
- max_retries: number;
9
- consumed_tokens: number;
10
- consumed_time_ms: number;
11
- consumed_retries: number;
12
- }
13
-
14
- export interface CooperativeHandoff {
15
- handoff_id: string;
16
- from_agent_id: string;
17
- to_agent_id: string;
18
- from_role: AgentRole;
19
- to_role: AgentRole;
20
- work_item_id: string;
21
- context_pack_ref: string | null;
22
- transferred_at: string;
23
- }
24
-
25
- export interface AgentActionLog {
26
- agent_id: string;
27
- role: AgentRole;
28
- work_item_id: string;
29
- action: 'execute' | 'verify' | 'review' | 'plan';
30
- result: 'success' | 'failure';
31
- duration_ms: number;
32
- timestamp: string;
33
- }
34
-
35
- export function createBudget(
36
- opts: Partial<Omit<AgentBudget, 'consumed_tokens' | 'consumed_time_ms' | 'consumed_retries'>> = {}
37
- ): AgentBudget {
38
- return {
39
- max_tokens: opts.max_tokens ?? Infinity,
40
- max_time_ms: opts.max_time_ms ?? Infinity,
41
- max_retries: opts.max_retries ?? Infinity,
42
- consumed_tokens: 0,
43
- consumed_time_ms: 0,
44
- consumed_retries: 0,
45
- };
46
- }
47
-
48
- export function consumeBudget(
49
- budget: AgentBudget,
50
- delta: { tokens?: number; time_ms?: number; retries?: number }
51
- ): AgentBudget {
52
- return {
53
- ...budget,
54
- consumed_tokens: budget.consumed_tokens + (delta.tokens ?? 0),
55
- consumed_time_ms: budget.consumed_time_ms + (delta.time_ms ?? 0),
56
- consumed_retries: budget.consumed_retries + (delta.retries ?? 0),
57
- };
58
- }
59
-
60
- export function isBudgetExhausted(budget: AgentBudget): boolean {
61
- return (
62
- budget.consumed_tokens >= budget.max_tokens ||
63
- budget.consumed_time_ms >= budget.max_time_ms ||
64
- budget.consumed_retries >= budget.max_retries
65
- );
66
- }
67
-
68
- export function buildHandoff(opts: {
69
- from_agent_id: string;
70
- to_agent_id: string;
71
- from_role: AgentRole;
72
- to_role: AgentRole;
73
- work_item_id: string;
74
- context_pack_ref?: string | null;
75
- }): CooperativeHandoff {
76
- return {
77
- handoff_id: `hoff-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
78
- from_agent_id: opts.from_agent_id,
79
- to_agent_id: opts.to_agent_id,
80
- from_role: opts.from_role,
81
- to_role: opts.to_role,
82
- work_item_id: opts.work_item_id,
83
- context_pack_ref: opts.context_pack_ref ?? null,
84
- transferred_at: new Date().toISOString(),
85
- };
86
- }
87
-
88
- // ─── ArbitrationEngine ────────────────────────────────────────────────────────
89
-
90
- export class ArbitrationEngine {
91
- /**
92
- * Choose the best result from multiple competing agents.
93
- * Prefers success; among successes prefers more evidence; falls back to first.
94
- */
95
- arbitrate(results: Array<{ agent_id: string; result: TaskResult }>): TaskResult {
96
- if (results.length === 0) {
97
- return { success: false, failure_class: null, evidence: [], output: 'no results to arbitrate' };
98
- }
99
-
100
- const successes = results.filter((r) => r.result.success);
101
- if (successes.length === 0) {
102
- return results[0].result;
103
- }
104
-
105
- // Among successes, prefer the one with most evidence
106
- successes.sort((a, b) => b.result.evidence.length - a.result.evidence.length);
107
- return successes[0].result;
108
- }
109
- }
1
+ import type { TaskResult } from './scheduler';
2
+
3
+ export type AgentRole = 'planner' | 'executor' | 'reviewer' | 'verifier';
4
+
5
+ export interface AgentBudget {
6
+ max_tokens: number;
7
+ max_time_ms: number;
8
+ max_retries: number;
9
+ consumed_tokens: number;
10
+ consumed_time_ms: number;
11
+ consumed_retries: number;
12
+ }
13
+
14
+ export interface CooperativeHandoff {
15
+ handoff_id: string;
16
+ from_agent_id: string;
17
+ to_agent_id: string;
18
+ from_role: AgentRole;
19
+ to_role: AgentRole;
20
+ work_item_id: string;
21
+ context_pack_ref: string | null;
22
+ transferred_at: string;
23
+ }
24
+
25
+ export interface AgentActionLog {
26
+ agent_id: string;
27
+ role: AgentRole;
28
+ work_item_id: string;
29
+ action: 'execute' | 'verify' | 'review' | 'plan';
30
+ result: 'success' | 'failure';
31
+ duration_ms: number;
32
+ timestamp: string;
33
+ }
34
+
35
+ export function createBudget(
36
+ opts: Partial<Omit<AgentBudget, 'consumed_tokens' | 'consumed_time_ms' | 'consumed_retries'>> = {}
37
+ ): AgentBudget {
38
+ return {
39
+ max_tokens: opts.max_tokens ?? Infinity,
40
+ max_time_ms: opts.max_time_ms ?? Infinity,
41
+ max_retries: opts.max_retries ?? Infinity,
42
+ consumed_tokens: 0,
43
+ consumed_time_ms: 0,
44
+ consumed_retries: 0,
45
+ };
46
+ }
47
+
48
+ export function consumeBudget(
49
+ budget: AgentBudget,
50
+ delta: { tokens?: number; time_ms?: number; retries?: number }
51
+ ): AgentBudget {
52
+ return {
53
+ ...budget,
54
+ consumed_tokens: budget.consumed_tokens + (delta.tokens ?? 0),
55
+ consumed_time_ms: budget.consumed_time_ms + (delta.time_ms ?? 0),
56
+ consumed_retries: budget.consumed_retries + (delta.retries ?? 0),
57
+ };
58
+ }
59
+
60
+ export function isBudgetExhausted(budget: AgentBudget): boolean {
61
+ return (
62
+ budget.consumed_tokens >= budget.max_tokens ||
63
+ budget.consumed_time_ms >= budget.max_time_ms ||
64
+ budget.consumed_retries >= budget.max_retries
65
+ );
66
+ }
67
+
68
+ export function buildHandoff(opts: {
69
+ from_agent_id: string;
70
+ to_agent_id: string;
71
+ from_role: AgentRole;
72
+ to_role: AgentRole;
73
+ work_item_id: string;
74
+ context_pack_ref?: string | null;
75
+ }): CooperativeHandoff {
76
+ return {
77
+ handoff_id: `hoff-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
78
+ from_agent_id: opts.from_agent_id,
79
+ to_agent_id: opts.to_agent_id,
80
+ from_role: opts.from_role,
81
+ to_role: opts.to_role,
82
+ work_item_id: opts.work_item_id,
83
+ context_pack_ref: opts.context_pack_ref ?? null,
84
+ transferred_at: new Date().toISOString(),
85
+ };
86
+ }
87
+
88
+ // ─── ArbitrationEngine ────────────────────────────────────────────────────────
89
+
90
+ export class ArbitrationEngine {
91
+ /**
92
+ * Choose the best result from multiple competing agents.
93
+ * Prefers success; among successes prefers more evidence; falls back to first.
94
+ */
95
+ arbitrate(results: Array<{ agent_id: string; result: TaskResult }>): TaskResult {
96
+ if (results.length === 0) {
97
+ return { success: false, failure_class: null, evidence: [], output: 'no results to arbitrate' };
98
+ }
99
+
100
+ const successes = results.filter((r) => r.result.success);
101
+ if (successes.length === 0) {
102
+ return results[0].result;
103
+ }
104
+
105
+ // Among successes, prefer the one with most evidence
106
+ successes.sort((a, b) => b.result.evidence.length - a.result.evidence.length);
107
+ return successes[0].result;
108
+ }
109
+ }
@@ -1,4 +1,4 @@
1
- export * from './scheduler';
2
- export * from './run-journal';
3
- export * from './agent-registry';
4
- export * from './agent-roles';
1
+ export * from './scheduler';
2
+ export * from './run-journal';
3
+ export * from './agent-registry';
4
+ export * from './agent-roles';