@holoscript/framework 6.0.3

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 (329) hide show
  1. package/ALL-test-results.json +1 -0
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/ROADMAP.md +175 -0
  5. package/dist/AgentManifest-CB4xM-Ma.d.cts +704 -0
  6. package/dist/AgentManifest-CB4xM-Ma.d.ts +704 -0
  7. package/dist/BehaviorTree-BrBFECv5.d.cts +103 -0
  8. package/dist/BehaviorTree-BrBFECv5.d.ts +103 -0
  9. package/dist/InvisibleWallet-BB6tFvRA.d.cts +1732 -0
  10. package/dist/InvisibleWallet-rtRrBOA8.d.ts +1732 -0
  11. package/dist/OrchestratorAgent-BvWgf9uw.d.cts +798 -0
  12. package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +798 -0
  13. package/dist/agents/index.cjs +4790 -0
  14. package/dist/agents/index.d.cts +1788 -0
  15. package/dist/agents/index.d.ts +1788 -0
  16. package/dist/agents/index.js +4695 -0
  17. package/dist/ai/index.cjs +5347 -0
  18. package/dist/ai/index.d.cts +1753 -0
  19. package/dist/ai/index.d.ts +1753 -0
  20. package/dist/ai/index.js +5244 -0
  21. package/dist/behavior.cjs +449 -0
  22. package/dist/behavior.d.cts +130 -0
  23. package/dist/behavior.d.ts +130 -0
  24. package/dist/behavior.js +407 -0
  25. package/dist/economy/index.cjs +3659 -0
  26. package/dist/economy/index.d.cts +747 -0
  27. package/dist/economy/index.d.ts +747 -0
  28. package/dist/economy/index.js +3617 -0
  29. package/dist/implementations-D9T3un9D.d.cts +236 -0
  30. package/dist/implementations-D9T3un9D.d.ts +236 -0
  31. package/dist/index.cjs +24550 -0
  32. package/dist/index.d.cts +1729 -0
  33. package/dist/index.d.ts +1729 -0
  34. package/dist/index.js +24277 -0
  35. package/dist/learning/index.cjs +219 -0
  36. package/dist/learning/index.d.cts +104 -0
  37. package/dist/learning/index.d.ts +104 -0
  38. package/dist/learning/index.js +189 -0
  39. package/dist/negotiation/index.cjs +970 -0
  40. package/dist/negotiation/index.d.cts +610 -0
  41. package/dist/negotiation/index.d.ts +610 -0
  42. package/dist/negotiation/index.js +931 -0
  43. package/dist/skills/index.cjs +1118 -0
  44. package/dist/skills/index.d.cts +289 -0
  45. package/dist/skills/index.d.ts +289 -0
  46. package/dist/skills/index.js +1079 -0
  47. package/dist/swarm/index.cjs +5268 -0
  48. package/dist/swarm/index.d.cts +2433 -0
  49. package/dist/swarm/index.d.ts +2433 -0
  50. package/dist/swarm/index.js +5221 -0
  51. package/dist/training/index.cjs +2745 -0
  52. package/dist/training/index.d.cts +1734 -0
  53. package/dist/training/index.d.ts +1734 -0
  54. package/dist/training/index.js +2687 -0
  55. package/extract-failures.js +10 -0
  56. package/package.json +82 -0
  57. package/src/__tests__/bounty-marketplace.test.ts +374 -0
  58. package/src/__tests__/delegation.test.ts +144 -0
  59. package/src/__tests__/distributed-claimer.test.ts +147 -0
  60. package/src/__tests__/done-log-audit.test.ts +342 -0
  61. package/src/__tests__/framework.test.ts +865 -0
  62. package/src/__tests__/goal-synthesizer.test.ts +236 -0
  63. package/src/__tests__/presence.test.ts +223 -0
  64. package/src/__tests__/protocol-agent.test.ts +254 -0
  65. package/src/__tests__/revenue-splitter.test.ts +114 -0
  66. package/src/__tests__/scenario-driven-todo.test.ts +197 -0
  67. package/src/__tests__/self-improve.test.ts +349 -0
  68. package/src/__tests__/service-lifecycle.test.ts +237 -0
  69. package/src/__tests__/skill-router.test.ts +121 -0
  70. package/src/agents/AgentManifest.ts +493 -0
  71. package/src/agents/AgentRegistry.ts +475 -0
  72. package/src/agents/AgentTypes.ts +585 -0
  73. package/src/agents/AgentWalletRegistry.ts +83 -0
  74. package/src/agents/AuthenticatedCRDT.ts +388 -0
  75. package/src/agents/CapabilityMatcher.ts +453 -0
  76. package/src/agents/CrossRealityHandoff.ts +305 -0
  77. package/src/agents/CulturalMemory.ts +454 -0
  78. package/src/agents/FederatedRegistryAdapter.ts +429 -0
  79. package/src/agents/NormEngine.ts +450 -0
  80. package/src/agents/OrchestratorAgent.ts +414 -0
  81. package/src/agents/SkillWorkflowEngine.ts +472 -0
  82. package/src/agents/TaskDelegationService.ts +551 -0
  83. package/src/agents/__tests__/AgentManifest.prod.test.ts +134 -0
  84. package/src/agents/__tests__/AgentManifest.test.ts +182 -0
  85. package/src/agents/__tests__/AgentModule.test.ts +864 -0
  86. package/src/agents/__tests__/AgentRegistry.prod.test.ts +125 -0
  87. package/src/agents/__tests__/AgentRegistry.test.ts +148 -0
  88. package/src/agents/__tests__/AgentTypes.test.ts +534 -0
  89. package/src/agents/__tests__/AgentWalletRegistry.test.ts +152 -0
  90. package/src/agents/__tests__/AuthenticatedCRDT.test.ts +558 -0
  91. package/src/agents/__tests__/CapabilityMatcher.prod.test.ts +117 -0
  92. package/src/agents/__tests__/CapabilityMatcher.test.ts +178 -0
  93. package/src/agents/__tests__/CrossRealityHandoff.test.ts +402 -0
  94. package/src/agents/__tests__/CulturalMemory.test.ts +200 -0
  95. package/src/agents/__tests__/FederatedRegistryAdapter.test.ts +409 -0
  96. package/src/agents/__tests__/NormEngine.test.ts +276 -0
  97. package/src/agents/__tests__/OrchestratorAgent.test.ts +182 -0
  98. package/src/agents/__tests__/SkillWorkflowEngine.test.ts +357 -0
  99. package/src/agents/__tests__/TaskDelegationService.test.ts +446 -0
  100. package/src/agents/index.ts +107 -0
  101. package/src/agents/spatial-comms/Layer1RealTime.ts +621 -0
  102. package/src/agents/spatial-comms/Layer2A2A.ts +661 -0
  103. package/src/agents/spatial-comms/Layer3MCP.ts +651 -0
  104. package/src/agents/spatial-comms/ProtocolTypes.ts +543 -0
  105. package/src/agents/spatial-comms/SpatialCommClient.ts +483 -0
  106. package/src/agents/spatial-comms/__tests__/performance-benchmark.test.ts +465 -0
  107. package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +409 -0
  108. package/src/agents/spatial-comms/index.ts +66 -0
  109. package/src/ai/AIAdapter.ts +313 -0
  110. package/src/ai/AICopilot.ts +331 -0
  111. package/src/ai/AIOutputValidator.ts +203 -0
  112. package/src/ai/BTNodes.ts +239 -0
  113. package/src/ai/BehaviorSelector.ts +135 -0
  114. package/src/ai/BehaviorTree.ts +153 -0
  115. package/src/ai/Blackboard.ts +165 -0
  116. package/src/ai/GenerationAnalytics.ts +461 -0
  117. package/src/ai/GenerationCache.ts +265 -0
  118. package/src/ai/GoalPlanner.ts +165 -0
  119. package/src/ai/HoloScriptGenerator.ts +580 -0
  120. package/src/ai/InfluenceMap.ts +180 -0
  121. package/src/ai/NavMesh.ts +168 -0
  122. package/src/ai/PerceptionSystem.ts +178 -0
  123. package/src/ai/PromptTemplates.ts +453 -0
  124. package/src/ai/SemanticSearchService.ts +80 -0
  125. package/src/ai/StateMachine.ts +196 -0
  126. package/src/ai/SteeringBehavior.ts +150 -0
  127. package/src/ai/SteeringBehaviors.ts +244 -0
  128. package/src/ai/TrainingDataGenerator.ts +1082 -0
  129. package/src/ai/UtilityAI.ts +145 -0
  130. package/src/ai/__tests__/AIAdapter.prod.test.ts +259 -0
  131. package/src/ai/__tests__/AIAdapter.test.ts +109 -0
  132. package/src/ai/__tests__/AICopilot.prod.test.ts +341 -0
  133. package/src/ai/__tests__/AICopilot.test.ts +178 -0
  134. package/src/ai/__tests__/AIOutputValidator.prod.test.ts +226 -0
  135. package/src/ai/__tests__/AIOutputValidator.test.ts +138 -0
  136. package/src/ai/__tests__/BTNodes.prod.test.ts +391 -0
  137. package/src/ai/__tests__/BTNodes.test.ts +263 -0
  138. package/src/ai/__tests__/BehaviorSelector.prod.test.ts +129 -0
  139. package/src/ai/__tests__/BehaviorSelector.test.ts +132 -0
  140. package/src/ai/__tests__/BehaviorTree.prod.test.ts +266 -0
  141. package/src/ai/__tests__/BehaviorTree.test.ts +216 -0
  142. package/src/ai/__tests__/Blackboard.prod.test.ts +339 -0
  143. package/src/ai/__tests__/Blackboard.test.ts +183 -0
  144. package/src/ai/__tests__/GenerationAnalytics.prod.test.ts +141 -0
  145. package/src/ai/__tests__/GenerationAnalytics.test.ts +165 -0
  146. package/src/ai/__tests__/GenerationCache.prod.test.ts +144 -0
  147. package/src/ai/__tests__/GenerationCache.test.ts +171 -0
  148. package/src/ai/__tests__/GoalPlanner.prod.test.ts +189 -0
  149. package/src/ai/__tests__/GoalPlanner.test.ts +137 -0
  150. package/src/ai/__tests__/GoalPlannerDepth.prod.test.ts +217 -0
  151. package/src/ai/__tests__/HoloScriptGenerator.test.ts +125 -0
  152. package/src/ai/__tests__/InfluenceMap.prod.test.ts +146 -0
  153. package/src/ai/__tests__/InfluenceMap.test.ts +149 -0
  154. package/src/ai/__tests__/NavMesh.prod.test.ts +141 -0
  155. package/src/ai/__tests__/NavMesh.test.ts +159 -0
  156. package/src/ai/__tests__/PerceptionSystem.prod.test.ts +135 -0
  157. package/src/ai/__tests__/PerceptionSystem.test.ts +250 -0
  158. package/src/ai/__tests__/PromptTemplates.prod.test.ts +313 -0
  159. package/src/ai/__tests__/PromptTemplates.test.ts +146 -0
  160. package/src/ai/__tests__/SemanticSearch.test.ts +37 -0
  161. package/src/ai/__tests__/StateMachine.prod.test.ts +162 -0
  162. package/src/ai/__tests__/StateMachine.test.ts +163 -0
  163. package/src/ai/__tests__/SteeringBehavior.prod.test.ts +251 -0
  164. package/src/ai/__tests__/SteeringBehavior.test.ts +135 -0
  165. package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +133 -0
  166. package/src/ai/__tests__/SteeringBehaviors.test.ts +151 -0
  167. package/src/ai/__tests__/TrainingDataGenerator.prod.test.ts +286 -0
  168. package/src/ai/__tests__/TrainingDataGenerator.test.ts +286 -0
  169. package/src/ai/__tests__/UtilityAI.prod.test.ts +207 -0
  170. package/src/ai/__tests__/UtilityAI.test.ts +155 -0
  171. package/src/ai/__tests__/adapters.prod.test.ts +263 -0
  172. package/src/ai/__tests__/adapters.test.ts +320 -0
  173. package/src/ai/adapters.ts +1585 -0
  174. package/src/ai/index.ts +130 -0
  175. package/src/behavior/BehaviorPresets.ts +140 -0
  176. package/src/behavior/BehaviorTree.ts +236 -0
  177. package/src/behavior/StateMachine.ts +176 -0
  178. package/src/behavior/StateTrait.ts +67 -0
  179. package/src/behavior/index.ts +8 -0
  180. package/src/behavior.ts +8 -0
  181. package/src/board/audit.ts +284 -0
  182. package/src/board/board-ops.ts +336 -0
  183. package/src/board/board-types.ts +302 -0
  184. package/src/board/index.ts +69 -0
  185. package/src/define-agent.ts +46 -0
  186. package/src/define-team.ts +33 -0
  187. package/src/delegation.ts +265 -0
  188. package/src/distributed-claimer.ts +228 -0
  189. package/src/economy/AgentBudgetEnforcer.ts +464 -0
  190. package/src/economy/BountyManager.ts +185 -0
  191. package/src/economy/CreatorRevenueAggregator.ts +460 -0
  192. package/src/economy/InvisibleWallet.ts +82 -0
  193. package/src/economy/KnowledgeMarketplace.ts +193 -0
  194. package/src/economy/PaymentWebhookService.ts +512 -0
  195. package/src/economy/RevenueSplitter.ts +156 -0
  196. package/src/economy/SubscriptionManager.ts +546 -0
  197. package/src/economy/UnifiedBudgetOptimizer.ts +635 -0
  198. package/src/economy/UsageMeter.ts +440 -0
  199. package/src/economy/_core-stubs.ts +219 -0
  200. package/src/economy/index.ts +100 -0
  201. package/src/economy/x402-facilitator.ts +1978 -0
  202. package/src/index.ts +348 -0
  203. package/src/knowledge/__tests__/knowledge-consolidator.test.ts +444 -0
  204. package/src/knowledge/__tests__/knowledge-store-vector.test.ts +291 -0
  205. package/src/knowledge/brain.ts +167 -0
  206. package/src/knowledge/consolidation.ts +581 -0
  207. package/src/knowledge/knowledge-consolidator.ts +510 -0
  208. package/src/knowledge/knowledge-store.ts +616 -0
  209. package/src/learning/MemoryConsolidator.ts +102 -0
  210. package/src/learning/MemoryScorer.ts +69 -0
  211. package/src/learning/ProceduralCompiler.ts +45 -0
  212. package/src/learning/SemanticClusterer.ts +66 -0
  213. package/src/learning/index.ts +8 -0
  214. package/src/llm/llm-adapter.ts +159 -0
  215. package/src/mesh/index.ts +309 -0
  216. package/src/negotiation/NegotiationProtocol.ts +694 -0
  217. package/src/negotiation/NegotiationTypes.ts +473 -0
  218. package/src/negotiation/VotingMechanisms.ts +691 -0
  219. package/src/negotiation/index.ts +49 -0
  220. package/src/protocol/goal-synthesizer.ts +317 -0
  221. package/src/protocol/implementations.ts +474 -0
  222. package/src/protocol/micro-phase-decomposer.ts +299 -0
  223. package/src/protocol/micro-step-decomposer.test.ts +306 -0
  224. package/src/protocol-agent.test.ts +353 -0
  225. package/src/protocol-agent.ts +670 -0
  226. package/src/self-improve/absorb-scanner.ts +252 -0
  227. package/src/self-improve/evolution-engine.ts +149 -0
  228. package/src/self-improve/framework-absorber.ts +214 -0
  229. package/src/self-improve/index.ts +50 -0
  230. package/src/self-improve/prompt-optimizer.ts +212 -0
  231. package/src/self-improve/test-generator.ts +175 -0
  232. package/src/skill-router.ts +186 -0
  233. package/src/skills/index.ts +5 -0
  234. package/src/skills/skill-md-bridge.ts +1699 -0
  235. package/src/swarm/ACOEngine.ts +261 -0
  236. package/src/swarm/CollectiveIntelligence.ts +383 -0
  237. package/src/swarm/ContributionSynthesizer.ts +481 -0
  238. package/src/swarm/LeaderElection.ts +393 -0
  239. package/src/swarm/PSOEngine.ts +206 -0
  240. package/src/swarm/QuorumPolicy.ts +173 -0
  241. package/src/swarm/SwarmCoordinator.ts +335 -0
  242. package/src/swarm/SwarmManager.ts +442 -0
  243. package/src/swarm/SwarmMembership.ts +456 -0
  244. package/src/swarm/VotingRound.ts +255 -0
  245. package/src/swarm/__tests__/ACOEngine.prod.test.ts +164 -0
  246. package/src/swarm/__tests__/ACOEngine.test.ts +117 -0
  247. package/src/swarm/__tests__/CollectiveIntelligence.prod.test.ts +296 -0
  248. package/src/swarm/__tests__/CollectiveIntelligence.test.ts +457 -0
  249. package/src/swarm/__tests__/ContributionSynthesizer.prod.test.ts +269 -0
  250. package/src/swarm/__tests__/ContributionSynthesizer.test.ts +254 -0
  251. package/src/swarm/__tests__/LeaderElection.prod.test.ts +196 -0
  252. package/src/swarm/__tests__/LeaderElection.test.ts +151 -0
  253. package/src/swarm/__tests__/PSOEngine.prod.test.ts +162 -0
  254. package/src/swarm/__tests__/PSOEngine.test.ts +106 -0
  255. package/src/swarm/__tests__/QuorumPolicy.prod.test.ts +216 -0
  256. package/src/swarm/__tests__/QuorumPolicy.test.ts +177 -0
  257. package/src/swarm/__tests__/SwarmCoordinator.prod.test.ts +186 -0
  258. package/src/swarm/__tests__/SwarmCoordinator.test.ts +167 -0
  259. package/src/swarm/__tests__/SwarmManager.prod.test.ts +308 -0
  260. package/src/swarm/__tests__/SwarmManager.test.ts +373 -0
  261. package/src/swarm/__tests__/SwarmMembership.prod.test.ts +273 -0
  262. package/src/swarm/__tests__/SwarmMembership.test.ts +264 -0
  263. package/src/swarm/__tests__/VotingRound.prod.test.ts +233 -0
  264. package/src/swarm/__tests__/VotingRound.test.ts +174 -0
  265. package/src/swarm/analytics/SwarmInspector.ts +476 -0
  266. package/src/swarm/analytics/SwarmMetrics.ts +449 -0
  267. package/src/swarm/analytics/__tests__/SwarmInspector.prod.test.ts +366 -0
  268. package/src/swarm/analytics/__tests__/SwarmInspector.test.ts +454 -0
  269. package/src/swarm/analytics/__tests__/SwarmMetrics.prod.test.ts +254 -0
  270. package/src/swarm/analytics/__tests__/SwarmMetrics.test.ts +370 -0
  271. package/src/swarm/analytics/index.ts +7 -0
  272. package/src/swarm/index.ts +69 -0
  273. package/src/swarm/messaging/BroadcastChannel.ts +509 -0
  274. package/src/swarm/messaging/GossipProtocol.ts +565 -0
  275. package/src/swarm/messaging/SwarmEventBus.ts +443 -0
  276. package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +331 -0
  277. package/src/swarm/messaging/__tests__/BroadcastChannel.test.ts +333 -0
  278. package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +356 -0
  279. package/src/swarm/messaging/__tests__/GossipProtocol.test.ts +437 -0
  280. package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +191 -0
  281. package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +247 -0
  282. package/src/swarm/messaging/index.ts +8 -0
  283. package/src/swarm/spatial/FlockingBehavior.ts +462 -0
  284. package/src/swarm/spatial/FormationController.ts +500 -0
  285. package/src/swarm/spatial/Vector3.ts +170 -0
  286. package/src/swarm/spatial/ZoneClaiming.ts +509 -0
  287. package/src/swarm/spatial/__tests__/FlockingBehavior.prod.test.ts +239 -0
  288. package/src/swarm/spatial/__tests__/FlockingBehavior.test.ts +298 -0
  289. package/src/swarm/spatial/__tests__/FormationController.prod.test.ts +240 -0
  290. package/src/swarm/spatial/__tests__/FormationController.test.ts +297 -0
  291. package/src/swarm/spatial/__tests__/Vector3.prod.test.ts +283 -0
  292. package/src/swarm/spatial/__tests__/Vector3.test.ts +224 -0
  293. package/src/swarm/spatial/__tests__/ZoneClaiming.prod.test.ts +246 -0
  294. package/src/swarm/spatial/__tests__/ZoneClaiming.test.ts +374 -0
  295. package/src/swarm/spatial/index.ts +28 -0
  296. package/src/team.ts +1245 -0
  297. package/src/training/LRScheduler.ts +377 -0
  298. package/src/training/QualityScoringPipeline.ts +139 -0
  299. package/src/training/SoftDedup.ts +461 -0
  300. package/src/training/SparsityMonitor.ts +685 -0
  301. package/src/training/SparsityMonitorTypes.ts +209 -0
  302. package/src/training/SpatialTrainingDataGenerator.ts +1526 -0
  303. package/src/training/SpatialTrainingDataTypes.ts +216 -0
  304. package/src/training/TrainingPipelineConfig.ts +215 -0
  305. package/src/training/constants.ts +94 -0
  306. package/src/training/index.ts +138 -0
  307. package/src/training/schema.ts +147 -0
  308. package/src/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
  309. package/src/training/scripts/generate-spatial-dataset.ts +521 -0
  310. package/src/training/training/data/novel-use-cases.jsonl +153 -0
  311. package/src/training/training/data/spatial-reasoning-10k.jsonl +9354 -0
  312. package/src/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
  313. package/src/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
  314. package/src/training/trainingmonkey/index.ts +26 -0
  315. package/src/training/trait-mappings.ts +157 -0
  316. package/src/types/core-stubs.d.ts +113 -0
  317. package/src/types.ts +304 -0
  318. package/test-output.txt +0 -0
  319. package/test-result.json +1 -0
  320. package/tsc-errors.txt +4 -0
  321. package/tsc_output.txt +0 -0
  322. package/tsconfig.json +14 -0
  323. package/tsup-learning-esm.config.ts +12 -0
  324. package/tsup.config.ts +21 -0
  325. package/typescript-errors-2.txt +0 -0
  326. package/typescript-errors.txt +22 -0
  327. package/vitest-log-utf8.txt +268 -0
  328. package/vitest-log.txt +0 -0
  329. package/vitest.config.ts +8 -0
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Cross-team Delegation — Send tasks between teams.
3
+ *
4
+ * Tracks delegation chains to prevent infinite loops and
5
+ * enables cross-team collaboration via board forwarding.
6
+ *
7
+ * FW-0.6 — Cross-team delegation.
8
+ *
9
+ * @module delegation
10
+ */
11
+
12
+ import type { TaskDef, SlotRole } from './types';
13
+
14
+ // =============================================================================
15
+ // TYPES
16
+ // =============================================================================
17
+
18
+ export interface DelegationResult {
19
+ /** Whether the delegation was accepted */
20
+ success: boolean;
21
+ /** The task that was delegated */
22
+ taskId: string;
23
+ /** Source team ID */
24
+ fromTeam: string;
25
+ /** Target team ID */
26
+ toTeam: string;
27
+ /** The delegation chain (to detect loops) */
28
+ chain: string[];
29
+ /** Reason for success or failure */
30
+ reason: string;
31
+ }
32
+
33
+ export interface DelegationRecord {
34
+ /** Original task ID */
35
+ taskId: string;
36
+ /** Task title (for display) */
37
+ taskTitle: string;
38
+ /** The team that delegated */
39
+ fromTeam: string;
40
+ /** The team that received */
41
+ toTeam: string;
42
+ /** Full chain of delegations */
43
+ chain: string[];
44
+ /** When the delegation happened */
45
+ timestamp: number;
46
+ /** Status of the delegated task */
47
+ status: 'pending' | 'accepted' | 'rejected' | 'completed' | 'bounced';
48
+ /** Callback URL or team reference for result delivery */
49
+ callbackRef?: string;
50
+ }
51
+
52
+ export interface DelegationPolicy {
53
+ /** Maximum delegation chain length before rejecting (default 5) */
54
+ maxChainLength?: number;
55
+ /** Whether to allow delegating back to a team already in the chain (default false) */
56
+ allowCycles?: boolean;
57
+ /** Required capabilities the target team must have (optional) */
58
+ requiredCapabilities?: string[];
59
+ }
60
+
61
+ /**
62
+ * Adapter interface for sending tasks to other teams.
63
+ * Implementations may use HTTP (remote boards), gossip (mesh), or in-process (local).
64
+ */
65
+ export interface TeamBoardAdapter {
66
+ /** Send a task to a target team's board */
67
+ sendTask(
68
+ targetTeamId: string,
69
+ task: Pick<TaskDef, 'title' | 'description' | 'priority' | 'role' | 'source'>
70
+ ): Promise<{ accepted: boolean; taskId?: string; reason?: string }>;
71
+
72
+ /** Notify a team about delegation completion */
73
+ notifyCompletion(
74
+ teamId: string,
75
+ delegation: DelegationRecord,
76
+ result: { summary: string }
77
+ ): Promise<void>;
78
+ }
79
+
80
+ // =============================================================================
81
+ // IN-PROCESS ADAPTER (for teams in the same process)
82
+ // =============================================================================
83
+
84
+ type AddTasksFn = (
85
+ tasks: Array<Pick<TaskDef, 'title' | 'description' | 'priority' | 'role' | 'source'>>
86
+ ) => Promise<TaskDef[]>;
87
+
88
+ export class InProcessBoardAdapter implements TeamBoardAdapter {
89
+ private teams: Map<string, { addTasks: AddTasksFn }> = new Map();
90
+
91
+ registerTeam(teamId: string, addTasks: AddTasksFn): void {
92
+ this.teams.set(teamId, { addTasks });
93
+ }
94
+
95
+ async sendTask(
96
+ targetTeamId: string,
97
+ task: Pick<TaskDef, 'title' | 'description' | 'priority' | 'role' | 'source'>
98
+ ): Promise<{ accepted: boolean; taskId?: string; reason?: string }> {
99
+ const target = this.teams.get(targetTeamId);
100
+ if (!target) {
101
+ return { accepted: false, reason: `Team "${targetTeamId}" not found` };
102
+ }
103
+ try {
104
+ const added = await target.addTasks([task]);
105
+ if (added.length > 0) {
106
+ return { accepted: true, taskId: added[0].id };
107
+ }
108
+ return { accepted: false, reason: 'Task was deduplicated' };
109
+ } catch (err) {
110
+ return { accepted: false, reason: err instanceof Error ? err.message : String(err) };
111
+ }
112
+ }
113
+
114
+ async notifyCompletion(
115
+ _teamId: string,
116
+ _delegation: DelegationRecord,
117
+ _result: { summary: string }
118
+ ): Promise<void> {
119
+ // In-process: no-op — the originating team can poll or observe directly
120
+ }
121
+ }
122
+
123
+ // =============================================================================
124
+ // DELEGATION MANAGER
125
+ // =============================================================================
126
+
127
+ export class DelegationManager {
128
+ private delegations: Map<string, DelegationRecord> = new Map();
129
+ private policy: Required<Omit<DelegationPolicy, 'requiredCapabilities'>> & {
130
+ requiredCapabilities: string[];
131
+ };
132
+
133
+ constructor(
134
+ private teamId: string,
135
+ private adapter: TeamBoardAdapter,
136
+ policy: DelegationPolicy = {}
137
+ ) {
138
+ this.policy = {
139
+ maxChainLength: policy.maxChainLength ?? 5,
140
+ allowCycles: policy.allowCycles ?? false,
141
+ requiredCapabilities: policy.requiredCapabilities ?? [],
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Delegate a task to another team.
147
+ *
148
+ * 1. Validate delegation chain (no cycles, max length)
149
+ * 2. Forward task to target team's board via adapter
150
+ * 3. Track delegation record
151
+ */
152
+ async delegate(
153
+ task: TaskDef,
154
+ targetTeamId: string,
155
+ existingChain: string[] = []
156
+ ): Promise<DelegationResult> {
157
+ const chain = [...existingChain, this.teamId];
158
+
159
+ // Prevent self-delegation
160
+ if (targetTeamId === this.teamId) {
161
+ return {
162
+ success: false,
163
+ taskId: task.id,
164
+ fromTeam: this.teamId,
165
+ toTeam: targetTeamId,
166
+ chain,
167
+ reason: 'Cannot delegate to self',
168
+ };
169
+ }
170
+
171
+ // Check for cycles
172
+ if (!this.policy.allowCycles && chain.includes(targetTeamId)) {
173
+ return {
174
+ success: false,
175
+ taskId: task.id,
176
+ fromTeam: this.teamId,
177
+ toTeam: targetTeamId,
178
+ chain,
179
+ reason: `Cycle detected: "${targetTeamId}" is already in the delegation chain`,
180
+ };
181
+ }
182
+
183
+ // Check chain length
184
+ if (chain.length >= this.policy.maxChainLength) {
185
+ return {
186
+ success: false,
187
+ taskId: task.id,
188
+ fromTeam: this.teamId,
189
+ toTeam: targetTeamId,
190
+ chain,
191
+ reason: `Delegation chain too long (${chain.length} >= max ${this.policy.maxChainLength})`,
192
+ };
193
+ }
194
+
195
+ // Forward to target team
196
+ const result = await this.adapter.sendTask(targetTeamId, {
197
+ title: task.title,
198
+ description: `[Delegated from ${this.teamId}] ${task.description}`,
199
+ priority: task.priority,
200
+ role: task.role,
201
+ source: `delegation:${this.teamId}:${task.id}`,
202
+ });
203
+
204
+ const record: DelegationRecord = {
205
+ taskId: task.id,
206
+ taskTitle: task.title,
207
+ fromTeam: this.teamId,
208
+ toTeam: targetTeamId,
209
+ chain,
210
+ timestamp: Date.now(),
211
+ status: result.accepted ? 'accepted' : 'rejected',
212
+ };
213
+
214
+ const key = `${task.id}:${targetTeamId}`;
215
+ this.delegations.set(key, record);
216
+
217
+ return {
218
+ success: result.accepted,
219
+ taskId: task.id,
220
+ fromTeam: this.teamId,
221
+ toTeam: targetTeamId,
222
+ chain,
223
+ reason: result.accepted
224
+ ? `Delegated to "${targetTeamId}" (remote task: ${result.taskId})`
225
+ : result.reason ?? 'Target team rejected the task',
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Mark a delegation as completed.
231
+ */
232
+ async completeDelegation(
233
+ taskId: string,
234
+ targetTeamId: string,
235
+ summary: string
236
+ ): Promise<boolean> {
237
+ const key = `${taskId}:${targetTeamId}`;
238
+ const record = this.delegations.get(key);
239
+ if (!record) return false;
240
+
241
+ record.status = 'completed';
242
+
243
+ // Notify originating team if there's a chain
244
+ if (record.chain.length > 1) {
245
+ const originTeam = record.chain[0];
246
+ await this.adapter.notifyCompletion(originTeam, record, { summary });
247
+ }
248
+
249
+ return true;
250
+ }
251
+
252
+ /**
253
+ * Get all delegations from this team.
254
+ */
255
+ getOutboundDelegations(): DelegationRecord[] {
256
+ return [...this.delegations.values()].filter(d => d.fromTeam === this.teamId);
257
+ }
258
+
259
+ /**
260
+ * Get pending delegations.
261
+ */
262
+ getPendingDelegations(): DelegationRecord[] {
263
+ return [...this.delegations.values()].filter(d => d.status === 'pending' || d.status === 'accepted');
264
+ }
265
+ }
@@ -0,0 +1,228 @@
1
+ /**
2
+ * DistributedClaimer — Optimistic CAS-based task claiming across machines.
3
+ *
4
+ * Uses the MeshDiscovery gossip layer for distributed state.
5
+ * Conflict resolution: priority + first-writer-wins via monotonic timestamps.
6
+ *
7
+ * FW-0.6 — Distributed task claiming across machines.
8
+ *
9
+ * @module distributed-claimer
10
+ */
11
+
12
+ import type { MeshDiscovery, GossipPacket } from './mesh';
13
+ import type { GossipProtocol } from './mesh';
14
+
15
+ // =============================================================================
16
+ // TYPES
17
+ // =============================================================================
18
+
19
+ export interface ClaimResult {
20
+ /** Whether this agent successfully claimed the task */
21
+ success: boolean;
22
+ /** The task ID that was claimed */
23
+ taskId: string;
24
+ /** The agent that holds the claim (may differ from requester on conflict) */
25
+ claimedBy: string;
26
+ /** Monotonic timestamp of the winning claim */
27
+ claimTimestamp: number;
28
+ /** If claim was contested, the losing agent IDs */
29
+ contested?: string[];
30
+ }
31
+
32
+ export interface ClaimRecord {
33
+ taskId: string;
34
+ agentId: string;
35
+ /** Monotonic timestamp (Date.now + counter to guarantee uniqueness) */
36
+ timestamp: number;
37
+ /** Agent priority — lower is higher priority */
38
+ priority: number;
39
+ /** Expiry timestamp — claims expire if not confirmed */
40
+ expiresAt: number;
41
+ }
42
+
43
+ export interface DistributedClaimerConfig {
44
+ /** Claim TTL in ms before auto-expiry (default 30_000) */
45
+ claimTtlMs?: number;
46
+ /** How often to prune expired claims in ms (default 10_000) */
47
+ pruneIntervalMs?: number;
48
+ }
49
+
50
+ // =============================================================================
51
+ // CLAIM GOSSIP PAYLOAD
52
+ // =============================================================================
53
+
54
+ interface ClaimGossipPayload {
55
+ type: 'claim' | 'release' | 'confirm';
56
+ record: ClaimRecord;
57
+ }
58
+
59
+ function isClaimPayload(p: unknown): p is ClaimGossipPayload {
60
+ if (!p || typeof p !== 'object') return false;
61
+ const obj = p as Record<string, unknown>;
62
+ return (
63
+ (obj.type === 'claim' || obj.type === 'release' || obj.type === 'confirm') &&
64
+ typeof obj.record === 'object' &&
65
+ obj.record !== null
66
+ );
67
+ }
68
+
69
+ // =============================================================================
70
+ // DISTRIBUTED CLAIMER
71
+ // =============================================================================
72
+
73
+ export class DistributedClaimer {
74
+ private claims: Map<string, ClaimRecord> = new Map();
75
+ private claimTtlMs: number;
76
+ private counter = 0;
77
+
78
+ constructor(
79
+ private mesh: MeshDiscovery,
80
+ private gossip: GossipProtocol,
81
+ config: DistributedClaimerConfig = {}
82
+ ) {
83
+ this.claimTtlMs = config.claimTtlMs ?? 30_000;
84
+ }
85
+
86
+ /**
87
+ * Attempt to claim a task using optimistic CAS.
88
+ *
89
+ * 1. Check local claim state
90
+ * 2. If unclaimed, write optimistic claim + broadcast via gossip
91
+ * 3. If already claimed, compare priority + timestamp (first-writer-wins)
92
+ */
93
+ claim(taskId: string, agentId: string, priority: number = 5): ClaimResult {
94
+ this.pruneExpired();
95
+
96
+ const now = Date.now();
97
+ const timestamp = now * 1000 + this.counter++;
98
+
99
+ const existing = this.claims.get(taskId);
100
+
101
+ // Unclaimed — take it
102
+ if (!existing || existing.expiresAt < now) {
103
+ const record: ClaimRecord = {
104
+ taskId,
105
+ agentId,
106
+ timestamp,
107
+ priority,
108
+ expiresAt: now + this.claimTtlMs,
109
+ };
110
+ this.claims.set(taskId, record);
111
+ this.broadcastClaim('claim', record);
112
+ return { success: true, taskId, claimedBy: agentId, claimTimestamp: timestamp };
113
+ }
114
+
115
+ // Already claimed by the same agent — refresh
116
+ if (existing.agentId === agentId) {
117
+ existing.expiresAt = now + this.claimTtlMs;
118
+ return { success: true, taskId, claimedBy: agentId, claimTimestamp: existing.timestamp };
119
+ }
120
+
121
+ // Conflict resolution: lower priority number wins; on tie, earlier timestamp wins
122
+ if (
123
+ priority < existing.priority ||
124
+ (priority === existing.priority && timestamp < existing.timestamp)
125
+ ) {
126
+ const loser = existing.agentId;
127
+ const record: ClaimRecord = {
128
+ taskId,
129
+ agentId,
130
+ timestamp,
131
+ priority,
132
+ expiresAt: now + this.claimTtlMs,
133
+ };
134
+ this.claims.set(taskId, record);
135
+ this.broadcastClaim('claim', record);
136
+ return { success: true, taskId, claimedBy: agentId, claimTimestamp: timestamp, contested: [loser] };
137
+ }
138
+
139
+ // Lost the conflict
140
+ return { success: false, taskId, claimedBy: existing.agentId, claimTimestamp: existing.timestamp };
141
+ }
142
+
143
+ /**
144
+ * Release a claim (task completed or abandoned).
145
+ */
146
+ release(taskId: string, agentId: string): boolean {
147
+ const existing = this.claims.get(taskId);
148
+ if (!existing || existing.agentId !== agentId) return false;
149
+ this.claims.delete(taskId);
150
+ this.broadcastClaim('release', existing);
151
+ return true;
152
+ }
153
+
154
+ /**
155
+ * Confirm a claim (mark as committed — extends TTL significantly).
156
+ */
157
+ confirm(taskId: string, agentId: string): boolean {
158
+ const existing = this.claims.get(taskId);
159
+ if (!existing || existing.agentId !== agentId) return false;
160
+ existing.expiresAt = Date.now() + this.claimTtlMs * 10; // 10x TTL for confirmed claims
161
+ this.broadcastClaim('confirm', existing);
162
+ return true;
163
+ }
164
+
165
+ /**
166
+ * Get the current claim holder for a task.
167
+ */
168
+ getClaimHolder(taskId: string): ClaimRecord | undefined {
169
+ this.pruneExpired();
170
+ return this.claims.get(taskId);
171
+ }
172
+
173
+ /**
174
+ * Get all active claims.
175
+ */
176
+ getActiveClaims(): ClaimRecord[] {
177
+ this.pruneExpired();
178
+ return [...this.claims.values()];
179
+ }
180
+
181
+ /**
182
+ * Ingest a gossip packet (called when receiving from peers).
183
+ */
184
+ ingestGossip(packet: GossipPacket): void {
185
+ if (!isClaimPayload(packet.payload)) return;
186
+
187
+ const { type, record } = packet.payload;
188
+
189
+ if (type === 'release') {
190
+ const existing = this.claims.get(record.taskId);
191
+ if (existing && existing.agentId === record.agentId) {
192
+ this.claims.delete(record.taskId);
193
+ }
194
+ return;
195
+ }
196
+
197
+ // claim or confirm — apply CAS logic
198
+ const existing = this.claims.get(record.taskId);
199
+ if (!existing || existing.expiresAt < Date.now()) {
200
+ this.claims.set(record.taskId, { ...record });
201
+ return;
202
+ }
203
+
204
+ // Conflict: lower priority wins, then earlier timestamp
205
+ if (
206
+ record.priority < existing.priority ||
207
+ (record.priority === existing.priority && record.timestamp < existing.timestamp)
208
+ ) {
209
+ this.claims.set(record.taskId, { ...record });
210
+ }
211
+ }
212
+
213
+ // ── Private ──
214
+
215
+ private broadcastClaim(type: ClaimGossipPayload['type'], record: ClaimRecord): void {
216
+ const payload: ClaimGossipPayload = { type, record };
217
+ this.gossip.shareWisdom(`claimer:${this.mesh.localId}`, payload);
218
+ }
219
+
220
+ private pruneExpired(): void {
221
+ const now = Date.now();
222
+ for (const [taskId, record] of this.claims) {
223
+ if (record.expiresAt < now) {
224
+ this.claims.delete(taskId);
225
+ }
226
+ }
227
+ }
228
+ }