oxe-cc 1.2.1 → 1.3.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 (276) 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/CHANGELOG.md +52 -17
  73. package/README.md +610 -551
  74. package/bin/banner.txt +1 -1
  75. package/bin/lib/oxe-agent-install.cjs +69 -69
  76. package/bin/lib/oxe-azure.cjs +1445 -1445
  77. package/bin/lib/oxe-context-engine.cjs +867 -867
  78. package/bin/lib/oxe-dashboard.cjs +76 -28
  79. package/bin/lib/oxe-operational.cjs +2144 -1340
  80. package/bin/lib/oxe-project-health.cjs +483 -1
  81. package/bin/lib/oxe-runtime-semantics.cjs +12 -0
  82. package/bin/oxe-cc.js +554 -152
  83. package/commands/oxe/ask.md +2 -2
  84. package/commands/oxe/capabilities.md +2 -2
  85. package/commands/oxe/checkpoint.md +2 -2
  86. package/commands/oxe/compact.md +2 -2
  87. package/commands/oxe/dashboard.md +2 -2
  88. package/commands/oxe/debug.md +2 -2
  89. package/commands/oxe/discuss.md +2 -2
  90. package/commands/oxe/execute.md +5 -2
  91. package/commands/oxe/forensics.md +2 -2
  92. package/commands/oxe/help.md +2 -2
  93. package/commands/oxe/loop.md +2 -2
  94. package/commands/oxe/milestone.md +2 -2
  95. package/commands/oxe/next.md +2 -2
  96. package/commands/oxe/obs.md +2 -2
  97. package/commands/oxe/oxe.md +2 -2
  98. package/commands/oxe/plan-agent.md +2 -2
  99. package/commands/oxe/plan.md +2 -2
  100. package/commands/oxe/project.md +2 -2
  101. package/commands/oxe/quick.md +2 -2
  102. package/commands/oxe/research.md +2 -2
  103. package/commands/oxe/retro.md +2 -2
  104. package/commands/oxe/review-pr.md +2 -2
  105. package/commands/oxe/route.md +2 -2
  106. package/commands/oxe/scan.md +2 -2
  107. package/commands/oxe/security.md +2 -2
  108. package/commands/oxe/session.md +2 -2
  109. package/commands/oxe/ship.md +2 -2
  110. package/commands/oxe/skill.md +2 -2
  111. package/commands/oxe/spec.md +2 -2
  112. package/commands/oxe/ui-review.md +2 -2
  113. package/commands/oxe/ui-spec.md +2 -2
  114. package/commands/oxe/update.md +2 -2
  115. package/commands/oxe/validate-gaps.md +2 -2
  116. package/commands/oxe/verify.md +5 -2
  117. package/commands/oxe/workstream.md +2 -2
  118. package/lib/runtime/delivery/branch-manager.d.ts +1 -0
  119. package/lib/runtime/delivery/branch-manager.js +7 -0
  120. package/lib/runtime/delivery/ci-checks.js +34 -1
  121. package/lib/runtime/delivery/delivery-records.d.ts +34 -0
  122. package/lib/runtime/delivery/delivery-records.js +48 -0
  123. package/lib/runtime/delivery/index.d.ts +1 -0
  124. package/lib/runtime/delivery/index.js +1 -0
  125. package/lib/runtime/delivery/promotion-pipeline.d.ts +26 -2
  126. package/lib/runtime/delivery/promotion-pipeline.js +111 -14
  127. package/lib/runtime/gate/gate-manager.d.ts +41 -0
  128. package/lib/runtime/gate/gate-manager.js +108 -1
  129. package/lib/runtime/index.d.ts +2 -2
  130. package/lib/runtime/index.js +3 -1
  131. package/lib/runtime/models/gate-decision.d.ts +4 -1
  132. package/lib/runtime/models/workspace.d.ts +3 -0
  133. package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
  134. package/lib/runtime/plugins/capability-adapter.js +204 -0
  135. package/lib/runtime/plugins/capability-matrix.d.ts +5 -0
  136. package/lib/runtime/plugins/capability-matrix.js +48 -17
  137. package/lib/runtime/plugins/index.d.ts +1 -0
  138. package/lib/runtime/plugins/index.js +1 -0
  139. package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
  140. package/lib/runtime/plugins/plugin-manifest.d.ts +1 -1
  141. package/lib/runtime/plugins/plugin-manifest.js +6 -2
  142. package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
  143. package/lib/runtime/plugins/plugin-registry.js +79 -2
  144. package/lib/runtime/policy/policy-engine.d.ts +19 -0
  145. package/lib/runtime/policy/policy-engine.js +76 -4
  146. package/lib/runtime/projection/projection-engine.d.ts +9 -1
  147. package/lib/runtime/projection/projection-engine.js +73 -3
  148. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +43 -1
  149. package/lib/runtime/scheduler/multi-agent-coordinator.js +151 -39
  150. package/lib/runtime/scheduler/run-journal.d.ts +1 -1
  151. package/lib/runtime/scheduler/scheduler.d.ts +19 -1
  152. package/lib/runtime/scheduler/scheduler.js +258 -13
  153. package/lib/runtime/verification/verification-compiler.d.ts +43 -0
  154. package/lib/runtime/verification/verification-compiler.js +137 -0
  155. package/lib/runtime/verification/verification-manifest.d.ts +9 -0
  156. package/lib/runtime/verification/verification-manifest.js +56 -6
  157. package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
  158. package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
  159. package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
  160. package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
  161. package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
  162. package/lib/runtime/workspace/strategies/inplace.js +2 -0
  163. package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
  164. package/lib/sdk/README.md +9 -9
  165. package/lib/sdk/index.cjs +33 -24
  166. package/lib/sdk/index.d.ts +149 -14
  167. package/oxe/templates/ACTIVE-RUN.template.json +32 -32
  168. package/oxe/templates/CAPABILITIES.template.md +7 -7
  169. package/oxe/templates/CAPABILITY.template.md +45 -45
  170. package/oxe/templates/CHECKPOINTS.template.md +7 -7
  171. package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
  172. package/oxe/templates/HYPOTHESES.template.md +33 -33
  173. package/oxe/templates/LESSONS-METRICS.template.json +13 -13
  174. package/oxe/templates/NOTES.template.md +16 -16
  175. package/oxe/templates/PLAN-REVIEW.template.md +31 -31
  176. package/oxe/templates/SESSION.template.md +34 -34
  177. package/oxe/templates/SKILL.template.md +26 -26
  178. package/oxe/templates/STATE.md +55 -55
  179. package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
  180. package/oxe/workflows/ask.md +96 -96
  181. package/oxe/workflows/capabilities.md +25 -25
  182. package/oxe/workflows/dashboard.md +33 -33
  183. package/oxe/workflows/discuss.md +12 -12
  184. package/oxe/workflows/execute.md +14 -0
  185. package/oxe/workflows/help.md +352 -352
  186. package/oxe/workflows/next.md +22 -22
  187. package/oxe/workflows/oxe.md +6 -6
  188. package/oxe/workflows/plan-agent.md +9 -9
  189. package/oxe/workflows/quick.md +10 -10
  190. package/oxe/workflows/references/reasoning-discovery.md +28 -28
  191. package/oxe/workflows/references/reasoning-execution.md +29 -29
  192. package/oxe/workflows/references/reasoning-planning.md +32 -32
  193. package/oxe/workflows/references/reasoning-review.md +29 -29
  194. package/oxe/workflows/references/reasoning-status.md +24 -24
  195. package/oxe/workflows/references/robustness-elevation.md +295 -295
  196. package/oxe/workflows/references/workflow-runtime-contracts.json +952 -930
  197. package/oxe/workflows/route.md +16 -16
  198. package/oxe/workflows/session.md +213 -213
  199. package/oxe/workflows/ship.md +142 -142
  200. package/oxe/workflows/skill.md +44 -44
  201. package/oxe/workflows/ui-review.md +36 -36
  202. package/oxe/workflows/verify-audit.md +73 -73
  203. package/oxe/workflows/verify.md +10 -0
  204. package/package.json +92 -92
  205. package/packages/runtime/package.json +17 -17
  206. package/packages/runtime/src/audit/audit-trail.ts +243 -243
  207. package/packages/runtime/src/audit/index.ts +2 -2
  208. package/packages/runtime/src/audit/policy-pack.ts +62 -62
  209. package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
  210. package/packages/runtime/src/compiler/index.ts +1 -1
  211. package/packages/runtime/src/context/context-pack-builder.ts +259 -259
  212. package/packages/runtime/src/context/context-pack-store.ts +197 -197
  213. package/packages/runtime/src/context/context-profiles.ts +60 -60
  214. package/packages/runtime/src/context/index.ts +3 -3
  215. package/packages/runtime/src/decision/decision-engine.ts +174 -174
  216. package/packages/runtime/src/decision/decision-memo.ts +211 -211
  217. package/packages/runtime/src/decision/index.ts +2 -2
  218. package/packages/runtime/src/delivery/branch-manager.ts +91 -84
  219. package/packages/runtime/src/delivery/ci-checks.ts +285 -252
  220. package/packages/runtime/src/delivery/delivery-records.ts +75 -0
  221. package/packages/runtime/src/delivery/index.ts +5 -4
  222. package/packages/runtime/src/delivery/pr-manager.ts +112 -112
  223. package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -180
  224. package/packages/runtime/src/events/bus.ts +92 -92
  225. package/packages/runtime/src/events/catalog.ts +29 -29
  226. package/packages/runtime/src/events/envelope.ts +14 -14
  227. package/packages/runtime/src/events/index.ts +3 -3
  228. package/packages/runtime/src/evidence/evidence-store.ts +130 -130
  229. package/packages/runtime/src/evidence/index.ts +1 -1
  230. package/packages/runtime/src/gate/gate-manager.ts +289 -137
  231. package/packages/runtime/src/gate/index.ts +1 -1
  232. package/packages/runtime/src/index.ts +41 -37
  233. package/packages/runtime/src/models/attempt.ts +19 -19
  234. package/packages/runtime/src/models/evidence.ts +21 -21
  235. package/packages/runtime/src/models/gate-decision.ts +25 -21
  236. package/packages/runtime/src/models/index.ts +8 -8
  237. package/packages/runtime/src/models/run.ts +24 -24
  238. package/packages/runtime/src/models/session.ts +11 -11
  239. package/packages/runtime/src/models/verification-result.ts +10 -10
  240. package/packages/runtime/src/models/work-item.ts +25 -25
  241. package/packages/runtime/src/models/workspace.ts +31 -28
  242. package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
  243. package/packages/runtime/src/plugins/capability-matrix.ts +126 -83
  244. package/packages/runtime/src/plugins/index.ts +5 -4
  245. package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
  246. package/packages/runtime/src/plugins/plugin-manifest.ts +118 -113
  247. package/packages/runtime/src/plugins/plugin-registry.ts +232 -124
  248. package/packages/runtime/src/policy/index.ts +1 -1
  249. package/packages/runtime/src/policy/policy-engine.ts +330 -244
  250. package/packages/runtime/src/projection/index.ts +1 -1
  251. package/packages/runtime/src/projection/projection-engine.ts +328 -249
  252. package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
  253. package/packages/runtime/src/reducers/index.ts +2 -2
  254. package/packages/runtime/src/reducers/run-state-reducer.ts +269 -269
  255. package/packages/runtime/src/scheduler/agent-registry.ts +132 -132
  256. package/packages/runtime/src/scheduler/agent-roles.ts +109 -109
  257. package/packages/runtime/src/scheduler/index.ts +4 -4
  258. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -333
  259. package/packages/runtime/src/scheduler/run-journal.ts +62 -62
  260. package/packages/runtime/src/scheduler/scheduler.ts +722 -441
  261. package/packages/runtime/src/verification/index.ts +2 -2
  262. package/packages/runtime/src/verification/verification-compiler.ts +436 -225
  263. package/packages/runtime/src/verification/verification-manifest.ts +252 -192
  264. package/packages/runtime/src/workspace/index.ts +5 -5
  265. package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
  266. package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
  267. package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
  268. package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
  269. package/packages/runtime/tsconfig.json +17 -17
  270. package/vscode-extension/.vscodeignore +7 -7
  271. package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
  272. package/vscode-extension/package.json +185 -185
  273. package/vscode-extension/src/extension.js +310 -310
  274. package/vscode-extension/src/shared/contextLoader.js +137 -137
  275. package/vscode-extension/src/shared/contractBuilder.js +159 -159
  276. 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';