@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,691 @@
1
+ /**
2
+ * @holoscript/core - Voting Mechanisms
3
+ *
4
+ * Implementations of various voting algorithms for agent negotiation.
5
+ * Part of HoloScript v3.1 Agentic Choreography.
6
+ *
7
+ * Supported mechanisms:
8
+ * - Majority: Simple majority wins
9
+ * - Supermajority: 2/3 threshold required
10
+ * - Weighted: Vote weight by trust level
11
+ * - Consensus: All must agree
12
+ * - Ranked Choice: Instant runoff voting
13
+ * - Approval: Multiple approval voting
14
+ * - Borda Count: Point-based ranking
15
+ *
16
+ * @version 3.1.0
17
+ * @Sprint v3.1 (March 2026)
18
+ */
19
+
20
+ import type {
21
+ Vote,
22
+ VoteTally,
23
+ VotingMechanism,
24
+ Proposal,
25
+ ResolutionOutcome,
26
+ NegotiationConfig,
27
+ } from './NegotiationTypes';
28
+
29
+ // =============================================================================
30
+ // TYPES
31
+ // =============================================================================
32
+
33
+ /**
34
+ * Result from a voting round
35
+ */
36
+ export interface VotingResult {
37
+ /** Final tallies */
38
+ tallies: VoteTally[];
39
+ /** Winner ID (if determined) */
40
+ winnerId?: string;
41
+ /** Whether resolution was reached */
42
+ resolved: boolean;
43
+ /** Outcome type */
44
+ outcome: ResolutionOutcome;
45
+ /** Tie detected */
46
+ tie?: boolean;
47
+ /** Eliminated proposals (for ranked choice) */
48
+ eliminated?: string[];
49
+ /** Consensus level (0-1) */
50
+ consensusLevel?: number;
51
+ /** Dissenters */
52
+ dissenters?: string[];
53
+ }
54
+
55
+ /**
56
+ * Voting mechanism handler interface
57
+ */
58
+ export interface VotingHandler {
59
+ /** Count votes and determine result */
60
+ count(
61
+ votes: Vote[],
62
+ proposals: Proposal[],
63
+ config: NegotiationConfig,
64
+ round: number
65
+ ): VotingResult;
66
+
67
+ /** Validate a vote for this mechanism */
68
+ validateVote(vote: Vote, proposals: Proposal[]): boolean;
69
+
70
+ /** Get required quorum for this mechanism */
71
+ getRequiredQuorum(config: NegotiationConfig): number;
72
+ }
73
+
74
+ // =============================================================================
75
+ // UTILITY FUNCTIONS
76
+ // =============================================================================
77
+
78
+ /**
79
+ * Calculate total weight of all votes
80
+ */
81
+ function getTotalWeight(votes: Vote[]): number {
82
+ return votes.reduce((sum, v) => sum + v.weight, 0);
83
+ }
84
+
85
+ /**
86
+ * Build initial tally structure
87
+ */
88
+ function initializeTallies(proposals: Proposal[]): Map<string, VoteTally> {
89
+ const tallies = new Map<string, VoteTally>();
90
+ for (const p of proposals) {
91
+ tallies.set(p.id, {
92
+ proposalId: p.id,
93
+ voteCount: 0,
94
+ weightedScore: 0,
95
+ approvalCount: 0,
96
+ bordaPoints: 0,
97
+ percentage: 0,
98
+ });
99
+ }
100
+ return tallies;
101
+ }
102
+
103
+ /**
104
+ * Convert tallies map to sorted array
105
+ */
106
+ function talliesToArray(tallies: Map<string, VoteTally>, totalWeight: number): VoteTally[] {
107
+ const arr = Array.from(tallies.values());
108
+ // Calculate percentages
109
+ for (const t of arr) {
110
+ t.percentage = totalWeight > 0 ? (t.weightedScore / totalWeight) * 100 : 0;
111
+ }
112
+ // Sort by weighted score descending
113
+ return arr.sort((a, b) => b.weightedScore - a.weightedScore);
114
+ }
115
+
116
+ /**
117
+ * Find ties at the top
118
+ */
119
+ function findTies(tallies: VoteTally[]): VoteTally[] {
120
+ if (tallies.length < 2) return [];
121
+ const topScore = tallies[0].weightedScore;
122
+ return tallies.filter((t) => t.weightedScore === topScore);
123
+ }
124
+
125
+ /**
126
+ * Apply tie-breaker
127
+ */
128
+ function breakTie(
129
+ tied: VoteTally[],
130
+ proposals: Proposal[],
131
+ config: NegotiationConfig
132
+ ): string | undefined {
133
+ if (tied.length === 0) return undefined;
134
+ if (tied.length === 1) return tied[0].proposalId;
135
+
136
+ switch (config.tieBreaker) {
137
+ case 'random':
138
+ return tied[Math.floor(Math.random() * tied.length)].proposalId;
139
+
140
+ case 'seniority': {
141
+ // Earliest submitted proposal wins
142
+ const proposalMap = new Map(proposals.map((p) => [p.id, p]));
143
+ const sorted = [...tied].sort((a, b) => {
144
+ const pa = proposalMap.get(a.proposalId);
145
+ const pb = proposalMap.get(b.proposalId);
146
+ return (pa?.submittedAt || 0) - (pb?.submittedAt || 0);
147
+ });
148
+ return sorted[0].proposalId;
149
+ }
150
+
151
+ case 'priority': {
152
+ // Highest priority proposal wins
153
+ const proposalMap = new Map(proposals.map((p) => [p.id, p]));
154
+ const sorted = [...tied].sort((a, b) => {
155
+ const pa = proposalMap.get(a.proposalId);
156
+ const pb = proposalMap.get(b.proposalId);
157
+ return (pb?.priority || 0) - (pa?.priority || 0);
158
+ });
159
+ return sorted[0].proposalId;
160
+ }
161
+
162
+ case 'proposer':
163
+ // First in tied list (arbitrary but deterministic)
164
+ return tied[0].proposalId;
165
+
166
+ case 'escalate':
167
+ default:
168
+ return undefined; // No winner, escalate
169
+ }
170
+ }
171
+
172
+ // =============================================================================
173
+ // MAJORITY VOTING
174
+ // =============================================================================
175
+
176
+ /**
177
+ * Simple majority voting (>50% wins)
178
+ */
179
+ export const majorityHandler: VotingHandler = {
180
+ count(votes, proposals, config, _round): VotingResult {
181
+ const tallies = initializeTallies(proposals);
182
+ const totalWeight = getTotalWeight(votes);
183
+
184
+ // Count first-choice votes
185
+ for (const vote of votes) {
186
+ if (vote.ranking.length > 0) {
187
+ const firstChoice = vote.ranking[0];
188
+ const tally = tallies.get(firstChoice);
189
+ if (tally) {
190
+ tally.voteCount++;
191
+ tally.weightedScore += vote.weight;
192
+ }
193
+ }
194
+ }
195
+
196
+ const sorted = talliesToArray(tallies, totalWeight);
197
+ const ties = findTies(sorted);
198
+
199
+ // Check if top has majority
200
+ if (sorted.length > 0 && sorted[0].percentage > 50) {
201
+ return {
202
+ tallies: sorted,
203
+ winnerId: sorted[0].proposalId,
204
+ resolved: true,
205
+ outcome: 'winner_declared',
206
+ consensusLevel: sorted[0].percentage / 100,
207
+ };
208
+ }
209
+
210
+ // Check for tie
211
+ if (ties.length > 1) {
212
+ const tieBreakWinner = breakTie(ties, proposals, config);
213
+ if (tieBreakWinner) {
214
+ return {
215
+ tallies: sorted,
216
+ winnerId: tieBreakWinner,
217
+ resolved: true,
218
+ outcome: 'tie_broken',
219
+ tie: true,
220
+ };
221
+ }
222
+ return {
223
+ tallies: sorted,
224
+ resolved: false,
225
+ outcome: 'deadlock',
226
+ tie: true,
227
+ };
228
+ }
229
+
230
+ // No majority but has a leader
231
+ if (sorted.length > 0) {
232
+ return {
233
+ tallies: sorted,
234
+ winnerId: sorted[0].proposalId,
235
+ resolved: true,
236
+ outcome: 'winner_declared',
237
+ consensusLevel: sorted[0].percentage / 100,
238
+ };
239
+ }
240
+
241
+ return {
242
+ tallies: sorted,
243
+ resolved: false,
244
+ outcome: 'deadlock',
245
+ };
246
+ },
247
+
248
+ validateVote(vote, proposals) {
249
+ if (vote.ranking.length === 0) return false;
250
+ const proposalIds = new Set(proposals.map((p) => p.id));
251
+ return proposalIds.has(vote.ranking[0]);
252
+ },
253
+
254
+ getRequiredQuorum(config) {
255
+ return config.quorum || 0.5;
256
+ },
257
+ };
258
+
259
+ // =============================================================================
260
+ // SUPERMAJORITY VOTING
261
+ // =============================================================================
262
+
263
+ /**
264
+ * Supermajority voting (≥66.67% wins)
265
+ */
266
+ export const supermajorityHandler: VotingHandler = {
267
+ count(votes, proposals, _config, _round): VotingResult {
268
+ const tallies = initializeTallies(proposals);
269
+ const totalWeight = getTotalWeight(votes);
270
+
271
+ for (const vote of votes) {
272
+ if (vote.ranking.length > 0) {
273
+ const firstChoice = vote.ranking[0];
274
+ const tally = tallies.get(firstChoice);
275
+ if (tally) {
276
+ tally.voteCount++;
277
+ tally.weightedScore += vote.weight;
278
+ }
279
+ }
280
+ }
281
+
282
+ const sorted = talliesToArray(tallies, totalWeight);
283
+ const threshold = 66.67;
284
+
285
+ if (sorted.length > 0 && sorted[0].percentage >= threshold) {
286
+ return {
287
+ tallies: sorted,
288
+ winnerId: sorted[0].proposalId,
289
+ resolved: true,
290
+ outcome: 'winner_declared',
291
+ consensusLevel: sorted[0].percentage / 100,
292
+ };
293
+ }
294
+
295
+ return {
296
+ tallies: sorted,
297
+ resolved: false,
298
+ outcome: 'deadlock',
299
+ };
300
+ },
301
+
302
+ validateVote(vote, proposals) {
303
+ return majorityHandler.validateVote(vote, proposals);
304
+ },
305
+
306
+ getRequiredQuorum(config) {
307
+ return config.quorum || 0.67;
308
+ },
309
+ };
310
+
311
+ // =============================================================================
312
+ // WEIGHTED VOTING
313
+ // =============================================================================
314
+
315
+ /**
316
+ * Weighted voting (trust-level based weights)
317
+ */
318
+ export const weightedHandler: VotingHandler = {
319
+ count(votes, proposals, config, round): VotingResult {
320
+ // Same as majority but weights already applied
321
+ return majorityHandler.count(votes, proposals, config, round);
322
+ },
323
+
324
+ validateVote(vote, proposals) {
325
+ return majorityHandler.validateVote(vote, proposals);
326
+ },
327
+
328
+ getRequiredQuorum(config) {
329
+ return config.quorum || 0.5;
330
+ },
331
+ };
332
+
333
+ // =============================================================================
334
+ // CONSENSUS VOTING
335
+ // =============================================================================
336
+
337
+ /**
338
+ * Consensus voting (all must agree)
339
+ */
340
+ export const consensusHandler: VotingHandler = {
341
+ count(votes, proposals, _config, _round): VotingResult {
342
+ if (votes.length === 0) {
343
+ return {
344
+ tallies: [],
345
+ resolved: false,
346
+ outcome: 'deadlock',
347
+ };
348
+ }
349
+
350
+ const tallies = initializeTallies(proposals);
351
+ const totalWeight = getTotalWeight(votes);
352
+
353
+ // Count first choices
354
+ const firstChoices = new Map<string, string[]>();
355
+ for (const vote of votes) {
356
+ if (vote.ranking.length > 0) {
357
+ const choice = vote.ranking[0];
358
+ const tally = tallies.get(choice);
359
+ if (tally) {
360
+ tally.voteCount++;
361
+ tally.weightedScore += vote.weight;
362
+ }
363
+ if (!firstChoices.has(choice)) {
364
+ firstChoices.set(choice, []);
365
+ }
366
+ firstChoices.get(choice)!.push(vote.agentId);
367
+ }
368
+ }
369
+
370
+ const sorted = talliesToArray(tallies, totalWeight);
371
+
372
+ // Check if all votes are for the same proposal
373
+ if (firstChoices.size === 1) {
374
+ const winnerId = Array.from(firstChoices.keys())[0];
375
+ return {
376
+ tallies: sorted,
377
+ winnerId,
378
+ resolved: true,
379
+ outcome: 'consensus_reached',
380
+ consensusLevel: 1.0,
381
+ };
382
+ }
383
+
384
+ // No consensus - identify dissenters
385
+ const leader = sorted[0];
386
+ const leaderVoters = new Set(firstChoices.get(leader.proposalId) || []);
387
+ const dissenters = votes.filter((v) => !leaderVoters.has(v.agentId)).map((v) => v.agentId);
388
+
389
+ return {
390
+ tallies: sorted,
391
+ resolved: false,
392
+ outcome: 'deadlock',
393
+ consensusLevel: leader.percentage / 100,
394
+ dissenters,
395
+ };
396
+ },
397
+
398
+ validateVote(vote, proposals) {
399
+ return majorityHandler.validateVote(vote, proposals);
400
+ },
401
+
402
+ getRequiredQuorum() {
403
+ return 1.0; // All must participate
404
+ },
405
+ };
406
+
407
+ // =============================================================================
408
+ // RANKED CHOICE (INSTANT RUNOFF)
409
+ // =============================================================================
410
+
411
+ /**
412
+ * Ranked choice voting with instant runoff
413
+ */
414
+ export const rankedHandler: VotingHandler = {
415
+ count(votes, proposals, _config, _round): VotingResult {
416
+ const eliminated = new Set<string>();
417
+ const runoffVotes = votes.map((v) => ({
418
+ ...v,
419
+ currentRanking: [...v.ranking],
420
+ }));
421
+ const totalWeight = getTotalWeight(votes);
422
+ let rounds = 0;
423
+ const maxRounds = proposals.length;
424
+
425
+ while (rounds < maxRounds) {
426
+ rounds++;
427
+
428
+ // Count current first choices
429
+ const tallies = initializeTallies(proposals.filter((p) => !eliminated.has(p.id)));
430
+
431
+ for (const vote of runoffVotes) {
432
+ // Find first non-eliminated choice
433
+ const validChoice = vote.currentRanking.find((id) => !eliminated.has(id));
434
+ if (validChoice) {
435
+ const tally = tallies.get(validChoice);
436
+ if (tally) {
437
+ tally.voteCount++;
438
+ tally.weightedScore += vote.weight;
439
+ }
440
+ }
441
+ }
442
+
443
+ const sorted = talliesToArray(tallies, totalWeight);
444
+
445
+ // Check for majority
446
+ if (sorted.length > 0 && sorted[0].percentage > 50) {
447
+ return {
448
+ tallies: sorted,
449
+ winnerId: sorted[0].proposalId,
450
+ resolved: true,
451
+ outcome: 'winner_declared',
452
+ eliminated: Array.from(eliminated),
453
+ consensusLevel: sorted[0].percentage / 100,
454
+ };
455
+ }
456
+
457
+ // Eliminate lowest
458
+ if (sorted.length > 1) {
459
+ const loser = sorted[sorted.length - 1];
460
+ eliminated.add(loser.proposalId);
461
+ } else if (sorted.length === 1) {
462
+ // Only one left
463
+ return {
464
+ tallies: sorted,
465
+ winnerId: sorted[0].proposalId,
466
+ resolved: true,
467
+ outcome: 'winner_declared',
468
+ eliminated: Array.from(eliminated),
469
+ };
470
+ } else {
471
+ break;
472
+ }
473
+ }
474
+
475
+ return {
476
+ tallies: [],
477
+ resolved: false,
478
+ outcome: 'deadlock',
479
+ eliminated: Array.from(eliminated),
480
+ };
481
+ },
482
+
483
+ validateVote(vote, proposals) {
484
+ if (vote.ranking.length === 0) return false;
485
+ const proposalIds = new Set(proposals.map((p) => p.id));
486
+ return vote.ranking.every((id) => proposalIds.has(id));
487
+ },
488
+
489
+ getRequiredQuorum(config) {
490
+ return config.quorum || 0.5;
491
+ },
492
+ };
493
+
494
+ // =============================================================================
495
+ // APPROVAL VOTING
496
+ // =============================================================================
497
+
498
+ /**
499
+ * Approval voting (vote for multiple acceptable options)
500
+ */
501
+ export const approvalHandler: VotingHandler = {
502
+ count(votes, proposals, config, _round): VotingResult {
503
+ const tallies = initializeTallies(proposals);
504
+ const totalVotes = votes.length;
505
+
506
+ for (const vote of votes) {
507
+ const approvals = vote.approvals || vote.ranking;
508
+ for (const proposalId of approvals) {
509
+ const tally = tallies.get(proposalId);
510
+ if (tally) {
511
+ tally.voteCount++;
512
+ tally.weightedScore += vote.weight;
513
+ tally.approvalCount = (tally.approvalCount || 0) + 1;
514
+ }
515
+ }
516
+ }
517
+
518
+ const sorted = talliesToArray(
519
+ tallies,
520
+ votes.reduce((s, v) => s + v.weight, 0)
521
+ );
522
+ const ties = findTies(sorted);
523
+
524
+ if (ties.length > 1) {
525
+ const tieBreakWinner = breakTie(ties, proposals, config);
526
+ if (tieBreakWinner) {
527
+ return {
528
+ tallies: sorted,
529
+ winnerId: tieBreakWinner,
530
+ resolved: true,
531
+ outcome: 'tie_broken',
532
+ tie: true,
533
+ };
534
+ }
535
+ }
536
+
537
+ if (sorted.length > 0) {
538
+ return {
539
+ tallies: sorted,
540
+ winnerId: sorted[0].proposalId,
541
+ resolved: true,
542
+ outcome: 'winner_declared',
543
+ consensusLevel: totalVotes > 0 ? (sorted[0].approvalCount || 0) / totalVotes : 0,
544
+ };
545
+ }
546
+
547
+ return {
548
+ tallies: sorted,
549
+ resolved: false,
550
+ outcome: 'deadlock',
551
+ };
552
+ },
553
+
554
+ validateVote(vote, proposals) {
555
+ const approvals = vote.approvals || vote.ranking;
556
+ if (approvals.length === 0) return false;
557
+ const proposalIds = new Set(proposals.map((p) => p.id));
558
+ return approvals.every((id) => proposalIds.has(id));
559
+ },
560
+
561
+ getRequiredQuorum(config) {
562
+ return config.quorum || 0.5;
563
+ },
564
+ };
565
+
566
+ // =============================================================================
567
+ // BORDA COUNT
568
+ // =============================================================================
569
+
570
+ /**
571
+ * Borda count voting (points by rank position)
572
+ */
573
+ export const bordaHandler: VotingHandler = {
574
+ count(votes, proposals, config, _round): VotingResult {
575
+ const tallies = initializeTallies(proposals);
576
+ const n = proposals.length;
577
+
578
+ for (const vote of votes) {
579
+ // Award points: n-1 for 1st, n-2 for 2nd, etc.
580
+ for (let i = 0; i < vote.ranking.length; i++) {
581
+ const proposalId = vote.ranking[i];
582
+ const tally = tallies.get(proposalId);
583
+ if (tally) {
584
+ const points = (n - 1 - i) * vote.weight;
585
+ tally.bordaPoints = (tally.bordaPoints || 0) + points;
586
+ tally.weightedScore += points;
587
+ tally.voteCount++;
588
+ }
589
+ }
590
+ }
591
+
592
+ const sorted = talliesToArray(tallies, n * votes.reduce((s, v) => s + v.weight, 0));
593
+ const ties = findTies(sorted);
594
+
595
+ if (ties.length > 1) {
596
+ const tieBreakWinner = breakTie(ties, proposals, config);
597
+ if (tieBreakWinner) {
598
+ return {
599
+ tallies: sorted,
600
+ winnerId: tieBreakWinner,
601
+ resolved: true,
602
+ outcome: 'tie_broken',
603
+ tie: true,
604
+ };
605
+ }
606
+ }
607
+
608
+ if (sorted.length > 0) {
609
+ return {
610
+ tallies: sorted,
611
+ winnerId: sorted[0].proposalId,
612
+ resolved: true,
613
+ outcome: 'winner_declared',
614
+ };
615
+ }
616
+
617
+ return {
618
+ tallies: sorted,
619
+ resolved: false,
620
+ outcome: 'deadlock',
621
+ };
622
+ },
623
+
624
+ validateVote(vote, proposals) {
625
+ return rankedHandler.validateVote(vote, proposals);
626
+ },
627
+
628
+ getRequiredQuorum(config) {
629
+ return config.quorum || 0.5;
630
+ },
631
+ };
632
+
633
+ // =============================================================================
634
+ // MECHANISM REGISTRY
635
+ // =============================================================================
636
+
637
+ /**
638
+ * Get handler for a voting mechanism
639
+ */
640
+ export function getVotingHandler(mechanism: VotingMechanism): VotingHandler {
641
+ switch (mechanism) {
642
+ case 'majority':
643
+ return majorityHandler;
644
+ case 'supermajority':
645
+ return supermajorityHandler;
646
+ case 'weighted':
647
+ return weightedHandler;
648
+ case 'consensus':
649
+ return consensusHandler;
650
+ case 'ranked':
651
+ return rankedHandler;
652
+ case 'approval':
653
+ return approvalHandler;
654
+ case 'borda':
655
+ return bordaHandler;
656
+ case 'custom':
657
+ default:
658
+ return majorityHandler;
659
+ }
660
+ }
661
+
662
+ /**
663
+ * Check if quorum is met
664
+ */
665
+ export function checkQuorum(
666
+ votes: Vote[],
667
+ participants: number,
668
+ config: NegotiationConfig,
669
+ mechanism: VotingMechanism
670
+ ): boolean {
671
+ const handler = getVotingHandler(mechanism);
672
+ const requiredQuorum = handler.getRequiredQuorum(config);
673
+ const participation = participants > 0 ? votes.length / participants : 0;
674
+ return participation >= requiredQuorum;
675
+ }
676
+
677
+ /**
678
+ * Get trust-based vote weight
679
+ */
680
+ export function getTrustWeight(trustLevel: 'local' | 'verified' | 'external'): number {
681
+ switch (trustLevel) {
682
+ case 'local':
683
+ return 1.0;
684
+ case 'verified':
685
+ return 0.8;
686
+ case 'external':
687
+ return 0.5;
688
+ default:
689
+ return 0.5;
690
+ }
691
+ }