apsimo 1.3.0__py3-none-any.whl

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 (614) hide show
  1. apsimo/__init__.py +38 -0
  2. apsimo/__main__.py +6 -0
  3. apsimo/agent/__init__.py +6 -0
  4. apsimo/agent/client.py +276 -0
  5. apsimo/agent/models.py +46 -0
  6. apsimo/agents/__init__.py +20 -0
  7. apsimo/agents/models.py +264 -0
  8. apsimo/agents/store.py +861 -0
  9. apsimo/agents/websocket.py +522 -0
  10. apsimo/api/__init__.py +1 -0
  11. apsimo/api/auth_telemetry.py +287 -0
  12. apsimo/api/authority.py +1203 -0
  13. apsimo/api/contact_grants.py +347 -0
  14. apsimo/api/middleware.py +483 -0
  15. apsimo/api/routers/__init__.py +1 -0
  16. apsimo/api/routers/commitment_work.py +265 -0
  17. apsimo/api/routers/context_gate.py +123 -0
  18. apsimo/api/routers/executions.py +140 -0
  19. apsimo/api/routers/followup_plans.py +147 -0
  20. apsimo/api/routers/governed_actions.py +162 -0
  21. apsimo/api/routers/host.py +14473 -0
  22. apsimo/api/routers/initiative_work.py +115 -0
  23. apsimo/api/routers/mining.py +104 -0
  24. apsimo/api/routers/observations.py +110 -0
  25. apsimo/api/routers/social_state.py +225 -0
  26. apsimo/api/routers/task_queue.py +2715 -0
  27. apsimo/api/routers/temporal_followups.py +251 -0
  28. apsimo/api/routers/transport.py +110 -0
  29. apsimo/api/routers/transport_ingress_api.py +240 -0
  30. apsimo/api/schemas/__init__.py +1 -0
  31. apsimo/api/schemas/host.py +1949 -0
  32. apsimo/autonomy/cli.py +110 -0
  33. apsimo/autonomy/condition_worker.py +437 -0
  34. apsimo/autonomy/config.py +424 -0
  35. apsimo/autonomy/loop.py +4316 -0
  36. apsimo/autonomy/registry.py +339 -0
  37. apsimo/autonomy/scheduler.py +1822 -0
  38. apsimo/autonomy/synthesis.py +449 -0
  39. apsimo/backup.py +962 -0
  40. apsimo/beliefs/__init__.py +23 -0
  41. apsimo/beliefs/contradictions.py +109 -0
  42. apsimo/beliefs/decay.py +61 -0
  43. apsimo/beliefs/engine.py +479 -0
  44. apsimo/beliefs/models.py +67 -0
  45. apsimo/beliefs/promotion.py +41 -0
  46. apsimo/beliefs/resolve.py +58 -0
  47. apsimo/beliefs/source_claims.py +690 -0
  48. apsimo/beliefs/source_projection.py +883 -0
  49. apsimo/beliefs/source_time.py +208 -0
  50. apsimo/beliefs/store.py +133 -0
  51. apsimo/briefings/aggregators.py +824 -0
  52. apsimo/briefings/composer.py +420 -0
  53. apsimo/briefings/config.py +55 -0
  54. apsimo/briefings/delivery.py +439 -0
  55. apsimo/briefings/engagement.py +97 -0
  56. apsimo/briefings/engine.py +274 -0
  57. apsimo/briefings/enhancer.py +99 -0
  58. apsimo/briefings/models.py +183 -0
  59. apsimo/briefings/scheduler.py +382 -0
  60. apsimo/briefings/store.py +435 -0
  61. apsimo/chain/__init__.py +48 -0
  62. apsimo/chain/block.py +100 -0
  63. apsimo/chain/cli.py +704 -0
  64. apsimo/chain/genesis.py +443 -0
  65. apsimo/chain/identity.py +416 -0
  66. apsimo/chain/keys.py +1025 -0
  67. apsimo/chain/local_keys.py +187 -0
  68. apsimo/chain/manager.py +290 -0
  69. apsimo/chain/node.py +163 -0
  70. apsimo/chain/plugin_transactions.py +371 -0
  71. apsimo/chain/protocol.py +220 -0
  72. apsimo/chain/state_machine.py +676 -0
  73. apsimo/chain/storage.py +503 -0
  74. apsimo/chain/transactions.py +250 -0
  75. apsimo/chain/validation.py +397 -0
  76. apsimo/channels/__init__.py +1 -0
  77. apsimo/channels/manifest.py +31 -0
  78. apsimo/channels/migrations/001_channels_schema.sql +12 -0
  79. apsimo/channels/phone_gateways.py +42 -0
  80. apsimo/channels/presence.py +188 -0
  81. apsimo/channels/router.py +235 -0
  82. apsimo/channels/store.py +231 -0
  83. apsimo/cli.py +2688 -0
  84. apsimo/cognition/__init__.py +11 -0
  85. apsimo/cognition/charter.py +398 -0
  86. apsimo/cognition/drive_governance.py +3530 -0
  87. apsimo/cognition/evidence_pipeline.py +1627 -0
  88. apsimo/cognition/external_events.py +932 -0
  89. apsimo/cognition/goal_spine.py +3488 -0
  90. apsimo/cognition/introspection.py +214 -0
  91. apsimo/cognition/prompt.py +150 -0
  92. apsimo/cognition/runtime.py +108 -0
  93. apsimo/cognition/trigger.py +154 -0
  94. apsimo/commitments/__init__.py +18 -0
  95. apsimo/commitments/local_work.py +355 -0
  96. apsimo/commitments/store.py +1052 -0
  97. apsimo/commitments/work.py +91 -0
  98. apsimo/compat.py +53 -0
  99. apsimo/compression/__init__.py +467 -0
  100. apsimo/connectors/__init__.py +21 -0
  101. apsimo/connectors/base.py +152 -0
  102. apsimo/connectors/caldav_calendar.py +125 -0
  103. apsimo/connectors/fs_documents.py +85 -0
  104. apsimo/connectors/imap_email.py +138 -0
  105. apsimo/connectors/manager.py +218 -0
  106. apsimo/connectors/webhook_pull.py +88 -0
  107. apsimo/contacts/__init__.py +33 -0
  108. apsimo/contacts/comms.py +357 -0
  109. apsimo/contacts/config.py +79 -0
  110. apsimo/contacts/exporters/__init__.py +1 -0
  111. apsimo/contacts/exporters/vcard.py +71 -0
  112. apsimo/contacts/identity_links.py +251 -0
  113. apsimo/contacts/importer.py +280 -0
  114. apsimo/contacts/importers/__init__.py +1 -0
  115. apsimo/contacts/importers/batch.py +43 -0
  116. apsimo/contacts/importers/macos_contacts.py +101 -0
  117. apsimo/contacts/migrations/001_contacts_schema.sql +141 -0
  118. apsimo/contacts/migrations/002_trust_scopes.sql +36 -0
  119. apsimo/contacts/migrations/003_open_gateway_enum.sql +32 -0
  120. apsimo/contacts/migrations/004_contact_provision_operations.sql +18 -0
  121. apsimo/contacts/migrations/005_identity_links.sql +27 -0
  122. apsimo/contacts/models.py +308 -0
  123. apsimo/contacts/scoring.py +16 -0
  124. apsimo/contacts/store.py +1623 -0
  125. apsimo/contacts/transport_ingress.py +252 -0
  126. apsimo/contacts/world_bridge.py +314 -0
  127. apsimo/contextgate/__init__.py +69 -0
  128. apsimo/contextgate/chunker.py +169 -0
  129. apsimo/contextgate/estimate.py +54 -0
  130. apsimo/contextgate/gate.py +313 -0
  131. apsimo/contextgate/retrieve.py +115 -0
  132. apsimo/delivery/__init__.py +16 -0
  133. apsimo/delivery/bridge.py +1260 -0
  134. apsimo/delivery/channels.py +526 -0
  135. apsimo/delivery/classification.py +50 -0
  136. apsimo/delivery/rate_limiter.py +268 -0
  137. apsimo/delivery/reachout_policy.py +206 -0
  138. apsimo/directed/__init__.py +22 -0
  139. apsimo/directed/audit.py +167 -0
  140. apsimo/directed/intake.py +95 -0
  141. apsimo/directed/models.py +191 -0
  142. apsimo/directed/service.py +509 -0
  143. apsimo/directives/__init__.py +25 -0
  144. apsimo/directives/evidence.py +87 -0
  145. apsimo/directives/extractor.py +188 -0
  146. apsimo/directives/guard.py +364 -0
  147. apsimo/directives/models.py +206 -0
  148. apsimo/directives/service.py +372 -0
  149. apsimo/directives/store.py +167 -0
  150. apsimo/doctor.py +2173 -0
  151. apsimo/environment.py +43 -0
  152. apsimo/events/__init__.py +33 -0
  153. apsimo/events/broadcaster.py +98 -0
  154. apsimo/events/bus.py +217 -0
  155. apsimo/events/journal.py +863 -0
  156. apsimo/events/stream.py +131 -0
  157. apsimo/events/types.py +150 -0
  158. apsimo/execution_results.py +357 -0
  159. apsimo/feedback/__init__.py +5 -0
  160. apsimo/feedback/store.py +76 -0
  161. apsimo/feeds/__init__.py +19 -0
  162. apsimo/feeds/cli.py +84 -0
  163. apsimo/feeds/engine.py +437 -0
  164. apsimo/feeds/example-feed.yaml +77 -0
  165. apsimo/feeds/hermes_cron.py +126 -0
  166. apsimo/feeds/manager.py +235 -0
  167. apsimo/feeds/spec.py +250 -0
  168. apsimo/feeds/template.py +202 -0
  169. apsimo/gate/__init__.py +18 -0
  170. apsimo/gate/audit.py +61 -0
  171. apsimo/gate/communication_policy.py +166 -0
  172. apsimo/gate/config.py +72 -0
  173. apsimo/gate/context_provenance.py +170 -0
  174. apsimo/gate/env_risk.py +226 -0
  175. apsimo/gate/guard_audit.py +353 -0
  176. apsimo/gate/layers/__init__.py +1 -0
  177. apsimo/gate/layers/base.py +15 -0
  178. apsimo/gate/layers/l1_recipient.py +66 -0
  179. apsimo/gate/layers/l2_pii.py +134 -0
  180. apsimo/gate/layers/l3_cross_context.py +50 -0
  181. apsimo/gate/layers/l4_trust_tier.py +78 -0
  182. apsimo/gate/layers/l5_injection.py +199 -0
  183. apsimo/gate/layers/l6_review.py +86 -0
  184. apsimo/gate/layers/l7_delay.py +100 -0
  185. apsimo/gate/layers/tom2_epistemic.py +185 -0
  186. apsimo/gate/models.py +64 -0
  187. apsimo/gate/pending_dispatch.py +5 -0
  188. apsimo/gate/pipeline.py +206 -0
  189. apsimo/gate/rejection.py +259 -0
  190. apsimo/gate/response_guard.py +700 -0
  191. apsimo/gate/rulesets/injection_v1.yaml +51 -0
  192. apsimo/gate/surface_policy.py +189 -0
  193. apsimo/gate/taint.py +226 -0
  194. apsimo/genesis.json +9 -0
  195. apsimo/goals/__init__.py +100 -0
  196. apsimo/goals/config.py +38 -0
  197. apsimo/goals/decomposer.py +421 -0
  198. apsimo/goals/engine.py +617 -0
  199. apsimo/goals/inference.py +354 -0
  200. apsimo/goals/models.py +302 -0
  201. apsimo/goals/priority.py +270 -0
  202. apsimo/goals/queue_bridge.py +149 -0
  203. apsimo/goals/replan.py +450 -0
  204. apsimo/goals/schema.sql +89 -0
  205. apsimo/goals/store.py +692 -0
  206. apsimo/governed_actions.py +1708 -0
  207. apsimo/harness_integration/__init__.py +45 -0
  208. apsimo/harness_integration/context.py +41 -0
  209. apsimo/harness_integration/skills.py +231 -0
  210. apsimo/identity/__init__.py +26 -0
  211. apsimo/identity/participants.py +181 -0
  212. apsimo/identity/resolver.py +329 -0
  213. apsimo/identity_bootstrap/__init__.py +5 -0
  214. apsimo/identity_bootstrap/builder.py +208 -0
  215. apsimo/identity_bootstrap/corpus.py +443 -0
  216. apsimo/identity_bootstrap/models.py +54 -0
  217. apsimo/identity_bootstrap/runner.py +353 -0
  218. apsimo/identity_bootstrap/seeders/__init__.py +25 -0
  219. apsimo/identity_bootstrap/seeders/briefings.py +109 -0
  220. apsimo/identity_bootstrap/seeders/chain.py +57 -0
  221. apsimo/identity_bootstrap/seeders/goals.py +128 -0
  222. apsimo/identity_bootstrap/seeders/memory.py +191 -0
  223. apsimo/identity_bootstrap/seeders/neo4j_cognition.py +79 -0
  224. apsimo/identity_bootstrap/seeders/relationship.py +152 -0
  225. apsimo/identity_bootstrap/seeders/sessions.py +67 -0
  226. apsimo/identity_bootstrap/seeders/skills.py +92 -0
  227. apsimo/identity_bootstrap/seeders/task_queue.py +72 -0
  228. apsimo/identity_bootstrap/seeders/world_model.py +143 -0
  229. apsimo/identity_bootstrap/self_query.py +92 -0
  230. apsimo/identity_bootstrap/self_reflection.py +155 -0
  231. apsimo/identity_bootstrap/skill.py +37 -0
  232. apsimo/identity_bootstrap/verifier.py +436 -0
  233. apsimo/initiatives/__init__.py +20 -0
  234. apsimo/initiatives/action_registry.py +454 -0
  235. apsimo/initiatives/approval_authority.py +2105 -0
  236. apsimo/initiatives/approval_policy.py +123 -0
  237. apsimo/initiatives/assignment.py +263 -0
  238. apsimo/initiatives/backup_evidence.py +100 -0
  239. apsimo/initiatives/context_freshness.py +103 -0
  240. apsimo/initiatives/models.py +318 -0
  241. apsimo/initiatives/native_work.py +270 -0
  242. apsimo/initiatives/standing_approvals.py +232 -0
  243. apsimo/initiatives/store.py +1081 -0
  244. apsimo/initiatives/temporal_followup.py +410 -0
  245. apsimo/intelligence/__init__.py +1 -0
  246. apsimo/intelligence/cognition/__init__.py +24 -0
  247. apsimo/intelligence/cognition/gap_detector.py +148 -0
  248. apsimo/intelligence/cognition/metalearner.py +547 -0
  249. apsimo/intelligence/cognition/metrics_collector.py +217 -0
  250. apsimo/intelligence/cognition/performance_index.py +299 -0
  251. apsimo/intelligence/cognition/registry.py +192 -0
  252. apsimo/intelligence/cognition/strategy_adjuster.py +222 -0
  253. apsimo/intelligence/cognition/types.py +16 -0
  254. apsimo/intelligence/components/__init__.py +66 -0
  255. apsimo/intelligence/components/anomaly_detector.py +413 -0
  256. apsimo/intelligence/components/initiative_engine.py +2643 -0
  257. apsimo/intelligence/components/preference_learner.py +521 -0
  258. apsimo/intelligence/components/research_orchestrator.py +358 -0
  259. apsimo/intelligence/components/self_directed_thinker.py +221 -0
  260. apsimo/intelligence/components/self_reflector.py +252 -0
  261. apsimo/intelligence/components/session_continuity.py +154 -0
  262. apsimo/intelligence/components/task_planner.py +320 -0
  263. apsimo/intelligence/components/tool_learner.py +217 -0
  264. apsimo/intelligence/graph/__init__.py +79 -0
  265. apsimo/intelligence/graph/client.py +2483 -0
  266. apsimo/intelligence/graph/consolidator.py +405 -0
  267. apsimo/intelligence/graph/distiller.py +312 -0
  268. apsimo/intelligence/graph/migrations.py +129 -0
  269. apsimo/intelligence/graph/queries.py +248 -0
  270. apsimo/intelligence/graph/recall.py +281 -0
  271. apsimo/intelligence/graph/reconciler.py +144 -0
  272. apsimo/intelligence/graph/schema.py +337 -0
  273. apsimo/intelligence/graph/selection.py +252 -0
  274. apsimo/intelligence/learning/__init__.py +17 -0
  275. apsimo/intelligence/learning/continuous_learner.py +245 -0
  276. apsimo/intelligence/learning/feedback_store.py +321 -0
  277. apsimo/intelligence/mind_model/__init__.py +1 -0
  278. apsimo/intelligence/mind_model/graph_baseline.py +136 -0
  279. apsimo/intelligence/mind_model/signal_collector.py +361 -0
  280. apsimo/intelligence/relationships/__init__.py +11 -0
  281. apsimo/intelligence/relationships/profiler.py +389 -0
  282. apsimo/intelligence/relationships/scorer.py +560 -0
  283. apsimo/intelligence/relationships/signal_floor.py +66 -0
  284. apsimo/intelligence/relationships/trust_tiers.py +300 -0
  285. apsimo/intelligence/synthesis/__init__.py +40 -0
  286. apsimo/intelligence/synthesis/connection_discoverer.py +379 -0
  287. apsimo/intelligence/synthesis/cross_domain_analyzer.py +287 -0
  288. apsimo/intelligence/synthesis/insight_deliverer.py +171 -0
  289. apsimo/intelligence/synthesis/insight_store.py +79 -0
  290. apsimo/intelligence/synthesis/insight_validator.py +183 -0
  291. apsimo/intelligence/synthesis/novelty_scorer.py +267 -0
  292. apsimo/intelligence/turn_middleware/__init__.py +15 -0
  293. apsimo/intelligence/turn_middleware/memory_sync.py +119 -0
  294. apsimo/mcp/__init__.py +41 -0
  295. apsimo/mcp/__main__.py +6 -0
  296. apsimo/mcp/config.py +287 -0
  297. apsimo/mcp/server.py +501 -0
  298. apsimo/migrations.py +187 -0
  299. apsimo/mining/__init__.py +27 -0
  300. apsimo/mining/corpus.py +239 -0
  301. apsimo/mining/escalations.py +289 -0
  302. apsimo/mining/models.py +169 -0
  303. apsimo/mining/store.py +210 -0
  304. apsimo/models/__init__.py +30 -0
  305. apsimo/models/memory.py +80 -0
  306. apsimo/models/mesh.py +72 -0
  307. apsimo/models/person.py +104 -0
  308. apsimo/models/signal.py +108 -0
  309. apsimo/observations/__init__.py +15 -0
  310. apsimo/observations/store.py +277 -0
  311. apsimo/patterns/__init__.py +6 -0
  312. apsimo/patterns/extract.py +187 -0
  313. apsimo/patterns/store.py +227 -0
  314. apsimo/persona/__init__.py +1 -0
  315. apsimo/persona/engine.py +611 -0
  316. apsimo/persona/manifest.py +140 -0
  317. apsimo/projects/__init__.py +28 -0
  318. apsimo/projects/engine.py +1681 -0
  319. apsimo/projects/event_outbox.py +188 -0
  320. apsimo/projects/models.py +216 -0
  321. apsimo/projects/planner.py +181 -0
  322. apsimo/projects/store.py +1446 -0
  323. apsimo/proposals/__init__.py +12 -0
  324. apsimo/proposals/engine.py +114 -0
  325. apsimo/proposals/models.py +207 -0
  326. apsimo/qualification/__init__.py +1 -0
  327. apsimo/qualification/cases.py +75 -0
  328. apsimo/qualification/cli.py +51 -0
  329. apsimo/qualification/memory_cases.py +209 -0
  330. apsimo/qualification/records.py +92 -0
  331. apsimo/qualification/report.py +87 -0
  332. apsimo/qualification/runner.py +311 -0
  333. apsimo/qualification/structured_cases.py +131 -0
  334. apsimo/reasoning/__init__.py +13 -0
  335. apsimo/reasoning/executor.py +506 -0
  336. apsimo/reasoning/loop.py +373 -0
  337. apsimo/reasoning/native_tools/__init__.py +16 -0
  338. apsimo/reasoning/native_tools/calculate.py +141 -0
  339. apsimo/reasoning/native_tools/file_ops.py +150 -0
  340. apsimo/reasoning/native_tools/web_search.py +49 -0
  341. apsimo/reasoning/tool_policy.py +182 -0
  342. apsimo/redact/__init__.py +176 -0
  343. apsimo/repos/__init__.py +5 -0
  344. apsimo/repos/mirrors.py +204 -0
  345. apsimo/research/__init__.py +41 -0
  346. apsimo/research/artifact.py +482 -0
  347. apsimo/research/gatherer.py +387 -0
  348. apsimo/research/pipeline.py +513 -0
  349. apsimo/research/search/__init__.py +7 -0
  350. apsimo/research/search/base.py +41 -0
  351. apsimo/research/search/brave.py +59 -0
  352. apsimo/research/search/cache.py +51 -0
  353. apsimo/research/search/duckduckgo.py +103 -0
  354. apsimo/research/search/orchestrator.py +119 -0
  355. apsimo/research/search/serpapi.py +59 -0
  356. apsimo/research/search/tavily.py +59 -0
  357. apsimo/research/synthesizer.py +309 -0
  358. apsimo/router/__init__.py +30 -0
  359. apsimo/router/complexity_scorer.py +148 -0
  360. apsimo/router/endpoints.py +153 -0
  361. apsimo/router/fallback.py +58 -0
  362. apsimo/router/functions.py +243 -0
  363. apsimo/router/native_policy.py +52 -0
  364. apsimo/router/router.py +762 -0
  365. apsimo/router/self_learning.py +174 -0
  366. apsimo/router/tiers.py +677 -0
  367. apsimo/sandbox/__init__.py +21 -0
  368. apsimo/sandbox/backend.py +195 -0
  369. apsimo/sandbox/manager.py +173 -0
  370. apsimo/scope_bounds.py +7 -0
  371. apsimo/secrets/__init__.py +6 -0
  372. apsimo/secrets/backends/__init__.py +8 -0
  373. apsimo/secrets/backends/base.py +42 -0
  374. apsimo/secrets/backends/env.py +110 -0
  375. apsimo/secrets/backends/keyring.py +72 -0
  376. apsimo/secrets/backends/onepassword.py +232 -0
  377. apsimo/secrets/cli.py +191 -0
  378. apsimo/secrets/manager.py +160 -0
  379. apsimo/secrets/migration.py +101 -0
  380. apsimo/secrets/types.py +98 -0
  381. apsimo/seed.py +41 -0
  382. apsimo/self_model/__init__.py +37 -0
  383. apsimo/self_model/appraisals.py +673 -0
  384. apsimo/self_model/benchmark.py +1314 -0
  385. apsimo/self_model/brief.py +40 -0
  386. apsimo/self_model/event_concerns.py +1128 -0
  387. apsimo/self_model/execution_forecasts.py +353 -0
  388. apsimo/self_model/expectations.py +1595 -0
  389. apsimo/self_model/experiments.py +1150 -0
  390. apsimo/self_model/journal.py +148 -0
  391. apsimo/self_model/judgments.py +705 -0
  392. apsimo/self_model/native_outcomes.py +55 -0
  393. apsimo/self_model/params.py +220 -0
  394. apsimo/self_model/perspective.py +246 -0
  395. apsimo/self_model/reconcile.py +183 -0
  396. apsimo/self_model/reply_forecasts.py +381 -0
  397. apsimo/self_model/runtime_forecasts.py +296 -0
  398. apsimo/self_model/runtime_models.py +67 -0
  399. apsimo/self_model/settlement.py +207 -0
  400. apsimo/self_model/situation.py +1731 -0
  401. apsimo/self_model/store.py +883 -0
  402. apsimo/self_model/supervised.py +137 -0
  403. apsimo/self_model/thinker.py +99 -0
  404. apsimo/self_model/trust.py +388 -0
  405. apsimo/self_model/workspace.py +2388 -0
  406. apsimo/server.py +4197 -0
  407. apsimo/services/__init__.py +1 -0
  408. apsimo/services/agent_bridge.py +474 -0
  409. apsimo/services/initiative_executor.py +914 -0
  410. apsimo/services/instance.py +297 -0
  411. apsimo/sessions/__init__.py +22 -0
  412. apsimo/sessions/config.py +13 -0
  413. apsimo/sessions/context_loader.py +88 -0
  414. apsimo/sessions/federation_session.py +75 -0
  415. apsimo/sessions/isolated_session.py +98 -0
  416. apsimo/sessions/reports.py +84 -0
  417. apsimo/sessions/store.py +148 -0
  418. apsimo/setup.py +2818 -0
  419. apsimo/setup_hermes.py +879 -0
  420. apsimo/setup_local_work.py +218 -0
  421. apsimo/setup_native_goals.py +134 -0
  422. apsimo/setup_native_reviews.py +115 -0
  423. apsimo/skills/__init__.py +10 -0
  424. apsimo/skills/base.py +108 -0
  425. apsimo/skills/budget.py +28 -0
  426. apsimo/skills/executor.py +493 -0
  427. apsimo/skills/executors/__init__.py +1 -0
  428. apsimo/skills/executors/behavioral_correction.py +75 -0
  429. apsimo/skills/executors/capability_gap.py +38 -0
  430. apsimo/skills/executors/data_quality.py +163 -0
  431. apsimo/skills/executors/knowledge_acquisition.py +41 -0
  432. apsimo/skills/executors/operational_hygiene.py +185 -0
  433. apsimo/skills/executors/subsystem_health.py +169 -0
  434. apsimo/skills/hermes_export.py +431 -0
  435. apsimo/skills/index.py +123 -0
  436. apsimo/skills/learning/__init__.py +21 -0
  437. apsimo/skills/learning/novelty_detector.py +206 -0
  438. apsimo/skills/learning/pattern_extractor.py +199 -0
  439. apsimo/skills/learning/triggers.py +159 -0
  440. apsimo/skills/loader.py +246 -0
  441. apsimo/skills/migrations/002_progressive_loading.sql +6 -0
  442. apsimo/skills/migrations/backfill_triggers.py +20 -0
  443. apsimo/skills/models.py +202 -0
  444. apsimo/skills/packager.py +128 -0
  445. apsimo/skills/protocols.py +70 -0
  446. apsimo/skills/registry.py +191 -0
  447. apsimo/skills/runtime.py +58 -0
  448. apsimo/skills/sandbox_runner.py +229 -0
  449. apsimo/skills/scheduler.py +129 -0
  450. apsimo/skills/schema.py +79 -0
  451. apsimo/skills/security/__init__.py +12 -0
  452. apsimo/skills/security/guards.py +53 -0
  453. apsimo/skills/security/scanner.py +223 -0
  454. apsimo/skills_memory/__init__.py +26 -0
  455. apsimo/skills_memory/distill.py +159 -0
  456. apsimo/skills_memory/models.py +85 -0
  457. apsimo/skills_memory/retrieve.py +62 -0
  458. apsimo/skills_memory/store.py +172 -0
  459. apsimo/surprise/__init__.py +6 -0
  460. apsimo/surprise/accumulation.py +57 -0
  461. apsimo/surprise/scorer.py +102 -0
  462. apsimo/surprise/store.py +203 -0
  463. apsimo/task_queue/__init__.py +69 -0
  464. apsimo/task_queue/action_receipts.py +148 -0
  465. apsimo/task_queue/approval_relay_canary.py +108 -0
  466. apsimo/task_queue/config.py +85 -0
  467. apsimo/task_queue/contract.py +361 -0
  468. apsimo/task_queue/events.py +130 -0
  469. apsimo/task_queue/governor.py +1031 -0
  470. apsimo/task_queue/handlers/__init__.py +16 -0
  471. apsimo/task_queue/handlers/base.py +37 -0
  472. apsimo/task_queue/handlers/inference.py +640 -0
  473. apsimo/task_queue/handlers/monitoring.py +116 -0
  474. apsimo/task_queue/handlers/registry.py +75 -0
  475. apsimo/task_queue/handlers/subtask_handler.py +173 -0
  476. apsimo/task_queue/handlers/system_maintenance.py +147 -0
  477. apsimo/task_queue/mesh_integration.py +111 -0
  478. apsimo/task_queue/models.py +317 -0
  479. apsimo/task_queue/queue_manager.py +8286 -0
  480. apsimo/task_queue/routing.py +287 -0
  481. apsimo/task_queue/scheduler.py +252 -0
  482. apsimo/task_queue/schema.sql +197 -0
  483. apsimo/task_queue/work_control.py +342 -0
  484. apsimo/task_queue/worker.py +993 -0
  485. apsimo/telemetry.py +145 -0
  486. apsimo/tom/__init__.py +6 -0
  487. apsimo/tom/affect.py +387 -0
  488. apsimo/tom/approvals.py +171 -0
  489. apsimo/tom/arcs.py +896 -0
  490. apsimo/tom/asymmetry.py +131 -0
  491. apsimo/tom/eligibility.py +248 -0
  492. apsimo/tom/engagement.py +214 -0
  493. apsimo/tom/exposure.py +214 -0
  494. apsimo/tom/extractor.py +306 -0
  495. apsimo/tom/fact_adapters.py +144 -0
  496. apsimo/tom/facts.py +326 -0
  497. apsimo/tom/integration.py +592 -0
  498. apsimo/tom/leveled.py +118 -0
  499. apsimo/tom/levels.py +247 -0
  500. apsimo/tom/recipient_audit.py +995 -0
  501. apsimo/tom/recipient_simulator.py +593 -0
  502. apsimo/tom/source_lineage.py +93 -0
  503. apsimo/tom/tom2.py +277 -0
  504. apsimo/tom/visibility.py +559 -0
  505. apsimo/tom/visibility_store.py +414 -0
  506. apsimo/tools/__init__.py +0 -0
  507. apsimo/tools/definitions.py +740 -0
  508. apsimo/tools/handlers.py +943 -0
  509. apsimo/toolsmith/__init__.py +26 -0
  510. apsimo/toolsmith/authority.py +166 -0
  511. apsimo/toolsmith/engine.py +559 -0
  512. apsimo/toolsmith/integrity.py +100 -0
  513. apsimo/toolsmith/miner.py +145 -0
  514. apsimo/toolsmith/policy.py +110 -0
  515. apsimo/toolsmith/registry.py +635 -0
  516. apsimo/turns/__init__.py +17 -0
  517. apsimo/turns/audio.py +134 -0
  518. apsimo/turns/documents.py +235 -0
  519. apsimo/turns/executions.py +486 -0
  520. apsimo/turns/hermes_history.py +245 -0
  521. apsimo/turns/hermes_kanban.py +268 -0
  522. apsimo/turns/hermes_work.py +96 -0
  523. apsimo/turns/idempotency.py +752 -0
  524. apsimo/turns/local_work.py +115 -0
  525. apsimo/turns/media.py +581 -0
  526. apsimo/turns/reported_workers.py +196 -0
  527. apsimo/turns/source_annotations.py +283 -0
  528. apsimo/turns/source_attribution.py +154 -0
  529. apsimo/turns/source_read.py +351 -0
  530. apsimo/turns/source_vectors.py +263 -0
  531. apsimo/turns/video.py +210 -0
  532. apsimo/util/autonomy_preset.py +220 -0
  533. apsimo/util/instance.py +92 -0
  534. apsimo/util/model_output.py +25 -0
  535. apsimo/util/quiet_hours.py +27 -0
  536. apsimo/util/session_safety.py +37 -0
  537. apsimo/util/temporal.py +343 -0
  538. apsimo/vector/__init__.py +75 -0
  539. apsimo/vector/backfill.py +171 -0
  540. apsimo/vector/caption.py +114 -0
  541. apsimo/vector/collections.py +51 -0
  542. apsimo/vector/config.py +102 -0
  543. apsimo/vector/embedder.py +670 -0
  544. apsimo/vector/image_preprocess.py +406 -0
  545. apsimo/vector/image_store.py +296 -0
  546. apsimo/vector/indexes.py +162 -0
  547. apsimo/vector/migrate.py +334 -0
  548. apsimo/vector/multimodal_provider.py +417 -0
  549. apsimo/vector/multimodal_types.py +87 -0
  550. apsimo/vector/openai_provider.py +119 -0
  551. apsimo/vector/query.py +49 -0
  552. apsimo/vector/reranker.py +565 -0
  553. apsimo/vector/safety_image.py +159 -0
  554. apsimo/vector/scanner.py +197 -0
  555. apsimo/vector/setup.py +289 -0
  556. apsimo/vector/store.py +533 -0
  557. apsimo/vector/tiers.py +263 -0
  558. apsimo/work_orders.py +925 -0
  559. apsimo/workers/__init__.py +21 -0
  560. apsimo/workers/agent_bridge.py +640 -0
  561. apsimo/workers/colony_worker.py +382 -0
  562. apsimo/workers/queue_worker.py +441 -0
  563. apsimo/workers/skills_sync.py +152 -0
  564. apsimo/world_model/__init__.py +71 -0
  565. apsimo/world_model/causal_maintenance.py +131 -0
  566. apsimo/world_model/causal_policy.py +43 -0
  567. apsimo/world_model/causal_query.py +125 -0
  568. apsimo/world_model/confidence.py +54 -0
  569. apsimo/world_model/config.py +64 -0
  570. apsimo/world_model/constants.py +97 -0
  571. apsimo/world_model/entities.py +145 -0
  572. apsimo/world_model/expectation_resolvers.py +177 -0
  573. apsimo/world_model/extraction/__init__.py +7 -0
  574. apsimo/world_model/extraction/base.py +62 -0
  575. apsimo/world_model/extraction/conversation_extractor.py +262 -0
  576. apsimo/world_model/extraction/detector.py +74 -0
  577. apsimo/world_model/extraction/document_extractor.py +78 -0
  578. apsimo/world_model/extraction/formats/__init__.py +24 -0
  579. apsimo/world_model/extraction/formats/csv_fmt.py +68 -0
  580. apsimo/world_model/extraction/formats/html_fmt.py +72 -0
  581. apsimo/world_model/extraction/formats/json_fmt.py +68 -0
  582. apsimo/world_model/extraction/formats/pdf.py +43 -0
  583. apsimo/world_model/extraction/formats/text.py +27 -0
  584. apsimo/world_model/extraction/llm_extractor.py +164 -0
  585. apsimo/world_model/extraction/pipeline.py +73 -0
  586. apsimo/world_model/integrations/__init__.py +5 -0
  587. apsimo/world_model/integrations/mind_model_bridge.py +115 -0
  588. apsimo/world_model/integrations/social_intel_bridge.py +120 -0
  589. apsimo/world_model/jobs/__init__.py +4 -0
  590. apsimo/world_model/jobs/extraction_job.py +168 -0
  591. apsimo/world_model/llm_extract.py +572 -0
  592. apsimo/world_model/neo4j/__init__.py +5 -0
  593. apsimo/world_model/neo4j/backend.py +654 -0
  594. apsimo/world_model/observations.py +155 -0
  595. apsimo/world_model/populator.py +307 -0
  596. apsimo/world_model/postgres/__init__.py +1 -0
  597. apsimo/world_model/postgres/backend.py +683 -0
  598. apsimo/world_model/relationships.py +25 -0
  599. apsimo/world_model/resolution/__init__.py +13 -0
  600. apsimo/world_model/resolution/entity_resolver.py +232 -0
  601. apsimo/world_model/resolution/merge_audit.py +16 -0
  602. apsimo/world_model/resolution/merge_workflow.py +117 -0
  603. apsimo/world_model/source_reports.py +121 -0
  604. apsimo/world_model/sqlite/__init__.py +4 -0
  605. apsimo/world_model/sqlite/backend.py +855 -0
  606. apsimo/world_model/sqlite/schema.sql +132 -0
  607. apsimo/world_model/store.py +545 -0
  608. apsimo-1.3.0.dist-info/METADATA +78 -0
  609. apsimo-1.3.0.dist-info/RECORD +614 -0
  610. apsimo-1.3.0.dist-info/WHEEL +5 -0
  611. apsimo-1.3.0.dist-info/entry_points.txt +11 -0
  612. apsimo-1.3.0.dist-info/licenses/LICENSE +21 -0
  613. apsimo-1.3.0.dist-info/top_level.txt +2 -0
  614. colony_sidecar/__init__.py +4 -0
@@ -0,0 +1,169 @@
1
+ """Mining models: escalation records + verbatim turn capture.
2
+
3
+ Concept provenance: inspired by external scaffolding work (drowzeys
4
+ Keys-Setup) on turning cloud/escalation corrections into local supervision
5
+ and serving logs into training data. Concepts only; no code adopted
6
+ (unlicensed + immature upstream).
7
+
8
+ Env flags
9
+ ---------
10
+ COLONY_ESCALATION_MINING = off | shadow | live (default shadow)
11
+ off: no capture, no detection.
12
+ shadow: capture verbatim turns + bank/journal escalation records.
13
+ live: shadow + feed banked escalations into skills-memory distillation.
14
+ COLONY_ESCALATION_CONSULT_REGEX
15
+ Pattern that marks a turn as a build-agent consultation (the agent
16
+ shelled out to a coding agent). Deployment-tunable.
17
+ COLONY_ESCALATION_HEAVY_RE
18
+ Pattern over the per-turn model name that marks a provider escalation
19
+ (heavy-model or cloud-failover turn). Empty (default) disables the
20
+ provider detector; deployments list their heavy/cloud models.
21
+ COLONY_MINING_TURN_CAP
22
+ Per-side verbatim capture cap in chars (default 8000).
23
+ COLONY_CORPUS_EXPORT_ENABLED
24
+ Gate for the corpus exporter endpoint (default true; exports only run
25
+ on explicit request and never leave the state dir).
26
+ """
27
+ from __future__ import annotations
28
+
29
+ import json
30
+ import os
31
+ import time
32
+ import uuid
33
+ from dataclasses import dataclass, field
34
+ from typing import Any, Dict, List, Optional
35
+
36
+ ESCALATION_KINDS = ("consultation", "provider_escalation")
37
+
38
+
39
+ def mining_mode() -> str:
40
+ from apsimo.util.autonomy_preset import resolve
41
+ return resolve("COLONY_ESCALATION_MINING",
42
+ ("off", "shadow", "live"), "shadow")
43
+
44
+
45
+ def corpus_export_enabled() -> bool:
46
+ return os.environ.get(
47
+ "COLONY_CORPUS_EXPORT_ENABLED", "true"
48
+ ).strip().lower() not in ("false", "0", "no", "off")
49
+
50
+
51
+ def consult_regex() -> str:
52
+ return os.environ.get(
53
+ "COLONY_ESCALATION_CONSULT_REGEX",
54
+ r"claude\s+-p|claude[-_ ]code|\bcode agent\b",
55
+ )
56
+
57
+
58
+ def heavy_model_regex() -> str:
59
+ return os.environ.get("COLONY_ESCALATION_HEAVY_RE", "")
60
+
61
+
62
+ def turn_cap() -> int:
63
+ try:
64
+ return max(500, int(os.environ.get("COLONY_MINING_TURN_CAP", "8000")))
65
+ except ValueError:
66
+ return 8000
67
+
68
+
69
+ @dataclass
70
+ class MinedTurn:
71
+ """One verbatim conversation exchange, banked for corpus export."""
72
+
73
+ id: str = field(default_factory=lambda: str(uuid.uuid4()))
74
+ session_id: str = ""
75
+ contact_id: str = ""
76
+ channel_id: str = ""
77
+ user_text: str = ""
78
+ assistant_text: str = ""
79
+ summary: str = ""
80
+ tools_used: List[str] = field(default_factory=list)
81
+ model: str = ""
82
+ ts: float = field(default_factory=time.time)
83
+
84
+ def to_row(self) -> Dict[str, Any]:
85
+ return {
86
+ "id": self.id,
87
+ "session_id": self.session_id,
88
+ "contact_id": self.contact_id,
89
+ "channel_id": self.channel_id,
90
+ "user_text": self.user_text,
91
+ "assistant_text": self.assistant_text,
92
+ "summary": self.summary,
93
+ "tools_used": json.dumps(self.tools_used),
94
+ "model": self.model,
95
+ "ts": self.ts,
96
+ }
97
+
98
+ @classmethod
99
+ def from_row(cls, row: Dict[str, Any]) -> "MinedTurn":
100
+ return cls(
101
+ id=row["id"],
102
+ session_id=row.get("session_id") or "",
103
+ contact_id=row.get("contact_id") or "",
104
+ channel_id=row.get("channel_id") or "",
105
+ user_text=row.get("user_text") or "",
106
+ assistant_text=row.get("assistant_text") or "",
107
+ summary=row.get("summary") or "",
108
+ tools_used=json.loads(row.get("tools_used") or "[]"),
109
+ model=row.get("model") or "",
110
+ ts=float(row.get("ts") or 0.0),
111
+ )
112
+
113
+
114
+ @dataclass
115
+ class EscalationRecord:
116
+ """A turn where the agent escalated: consulted a build agent, or the
117
+ turn ran on a heavy/cloud model. High-value supervision material."""
118
+
119
+ id: str = field(default_factory=lambda: str(uuid.uuid4()))
120
+ kind: str = "consultation" # one of ESCALATION_KINDS
121
+ session_id: str = ""
122
+ contact_id: str = ""
123
+ channel_id: str = ""
124
+ task_context: str = "" # what was being asked/attempted
125
+ local_attempt: str = "" # prior local answer in-session, if any
126
+ escalated_answer: str = "" # the answer produced with escalation
127
+ model: str = ""
128
+ matched: str = "" # which signature matched (audit)
129
+ outcome: str = "unknown" # unknown | followed_up
130
+ outcome_note: str = "" # next user message excerpt
131
+ distilled: int = 0 # fed to skills distillation (live mode)
132
+ ts: float = field(default_factory=time.time)
133
+
134
+ def to_row(self) -> Dict[str, Any]:
135
+ return {
136
+ "id": self.id,
137
+ "kind": self.kind,
138
+ "session_id": self.session_id,
139
+ "contact_id": self.contact_id,
140
+ "channel_id": self.channel_id,
141
+ "task_context": self.task_context,
142
+ "local_attempt": self.local_attempt,
143
+ "escalated_answer": self.escalated_answer,
144
+ "model": self.model,
145
+ "matched": self.matched,
146
+ "outcome": self.outcome,
147
+ "outcome_note": self.outcome_note,
148
+ "distilled": self.distilled,
149
+ "ts": self.ts,
150
+ }
151
+
152
+ @classmethod
153
+ def from_row(cls, row: Dict[str, Any]) -> "EscalationRecord":
154
+ return cls(
155
+ id=row["id"],
156
+ kind=row.get("kind") or "consultation",
157
+ session_id=row.get("session_id") or "",
158
+ contact_id=row.get("contact_id") or "",
159
+ channel_id=row.get("channel_id") or "",
160
+ task_context=row.get("task_context") or "",
161
+ local_attempt=row.get("local_attempt") or "",
162
+ escalated_answer=row.get("escalated_answer") or "",
163
+ model=row.get("model") or "",
164
+ matched=row.get("matched") or "",
165
+ outcome=row.get("outcome") or "unknown",
166
+ outcome_note=row.get("outcome_note") or "",
167
+ distilled=int(row.get("distilled") or 0),
168
+ ts=float(row.get("ts") or 0.0),
169
+ )
apsimo/mining/store.py ADDED
@@ -0,0 +1,210 @@
1
+ """MiningStore: SQLite persistence for verbatim turns + escalation records.
2
+
3
+ The rest of the sidecar keeps salience-gated summaries (memory graph, comms
4
+ ledger, rolling journal); none of those is a durable verbatim corpus. This
5
+ store is: every accepted turn is banked verbatim (capped per side), queryable
6
+ by channel / contact / date range, feeding the escalation miner and the
7
+ training-corpus exporter. Data never leaves COLONY_STATE_DIR.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import sqlite3
12
+ import threading
13
+ import time
14
+ from typing import Any, List, Optional
15
+
16
+ from apsimo.mining.models import EscalationRecord, MinedTurn
17
+
18
+
19
+ class MiningStore:
20
+ def __init__(self, db_path: Optional[str] = None) -> None:
21
+ self._lock = threading.RLock()
22
+ self._conn = sqlite3.connect(
23
+ str(db_path) if db_path else ":memory:", check_same_thread=False
24
+ )
25
+ self._conn.row_factory = sqlite3.Row
26
+ with self._lock:
27
+ self._conn.execute(
28
+ """CREATE TABLE IF NOT EXISTS mined_turns (
29
+ id TEXT PRIMARY KEY,
30
+ session_id TEXT,
31
+ contact_id TEXT,
32
+ channel_id TEXT,
33
+ user_text TEXT,
34
+ assistant_text TEXT,
35
+ summary TEXT,
36
+ tools_used TEXT,
37
+ model TEXT,
38
+ ts REAL
39
+ )"""
40
+ )
41
+ self._conn.execute(
42
+ """CREATE TABLE IF NOT EXISTS escalations (
43
+ id TEXT PRIMARY KEY,
44
+ kind TEXT,
45
+ session_id TEXT,
46
+ contact_id TEXT,
47
+ channel_id TEXT,
48
+ task_context TEXT,
49
+ local_attempt TEXT,
50
+ escalated_answer TEXT,
51
+ model TEXT,
52
+ matched TEXT,
53
+ outcome TEXT,
54
+ outcome_note TEXT,
55
+ distilled INTEGER DEFAULT 0,
56
+ ts REAL
57
+ )"""
58
+ )
59
+ self._conn.execute(
60
+ "CREATE INDEX IF NOT EXISTS idx_turns_session ON mined_turns(session_id, ts)"
61
+ )
62
+ self._conn.execute(
63
+ "CREATE INDEX IF NOT EXISTS idx_turns_ts ON mined_turns(ts)"
64
+ )
65
+ self._conn.execute(
66
+ "CREATE INDEX IF NOT EXISTS idx_esc_session ON escalations(session_id, ts)"
67
+ )
68
+ self._conn.commit()
69
+
70
+ # -- turns ---------------------------------------------------------------
71
+
72
+ def add_turn(self, t: MinedTurn) -> MinedTurn:
73
+ row = t.to_row()
74
+ with self._lock:
75
+ cols = ", ".join(row)
76
+ ph = ", ".join(["?"] * len(row))
77
+ self._conn.execute(
78
+ f"INSERT OR REPLACE INTO mined_turns ({cols}) VALUES ({ph})",
79
+ list(row.values()),
80
+ )
81
+ self._conn.commit()
82
+ return t
83
+
84
+ def last_turn_in_session(self, session_id: str) -> Optional[MinedTurn]:
85
+ with self._lock:
86
+ r = self._conn.execute(
87
+ "SELECT * FROM mined_turns WHERE session_id=? ORDER BY ts DESC LIMIT 1",
88
+ (session_id,),
89
+ ).fetchone()
90
+ return MinedTurn.from_row(dict(r)) if r else None
91
+
92
+ def list_turns(
93
+ self,
94
+ *,
95
+ contact_id: Optional[str] = None,
96
+ channels: Optional[List[str]] = None,
97
+ since_ts: Optional[float] = None,
98
+ until_ts: Optional[float] = None,
99
+ limit: int = 5000,
100
+ ) -> List[MinedTurn]:
101
+ q = "SELECT * FROM mined_turns WHERE 1=1"
102
+ params: List[Any] = []
103
+ if contact_id and contact_id != "*":
104
+ q += " AND contact_id=?"
105
+ params.append(contact_id)
106
+ if channels:
107
+ q += f" AND channel_id IN ({','.join(['?'] * len(channels))})"
108
+ params.extend(channels)
109
+ if since_ts is not None:
110
+ q += " AND ts >= ?"
111
+ params.append(since_ts)
112
+ if until_ts is not None:
113
+ q += " AND ts <= ?"
114
+ params.append(until_ts)
115
+ q += " ORDER BY session_id, ts ASC LIMIT ?"
116
+ params.append(limit)
117
+ with self._lock:
118
+ rows = self._conn.execute(q, params).fetchall()
119
+ return [MinedTurn.from_row(dict(r)) for r in rows]
120
+
121
+ def turn_count(self) -> int:
122
+ with self._lock:
123
+ r = self._conn.execute("SELECT COUNT(*) AS n FROM mined_turns").fetchone()
124
+ return int(r["n"])
125
+
126
+ def prune_turns(self, *, retention_days: int = 0,
127
+ max_turns: int = 0) -> dict:
128
+ """Prune banked turns by age and/or count (newest kept).
129
+
130
+ Both knobs default to 0 = keep everything: the verbatim corpus is
131
+ unbounded by design unless a deployment opts into retention via
132
+ COLONY_MINING_RETENTION_DAYS / COLONY_MINING_MAX_TURNS. Escalation
133
+ records are never pruned here — they are the distilled, high-value
134
+ output the turn bank exists to produce.
135
+ """
136
+ deleted_by_age = deleted_by_count = 0
137
+ with self._lock:
138
+ if retention_days > 0:
139
+ cutoff = time.time() - retention_days * 86400
140
+ cur = self._conn.execute(
141
+ "DELETE FROM mined_turns WHERE ts < ?", (cutoff,))
142
+ deleted_by_age = cur.rowcount
143
+ if max_turns > 0:
144
+ cur = self._conn.execute(
145
+ "DELETE FROM mined_turns WHERE id NOT IN ("
146
+ "SELECT id FROM mined_turns ORDER BY ts DESC LIMIT ?)",
147
+ (max_turns,))
148
+ deleted_by_count = cur.rowcount
149
+ if deleted_by_age or deleted_by_count:
150
+ self._conn.commit()
151
+ return {"deleted_by_age": deleted_by_age,
152
+ "deleted_by_count": deleted_by_count,
153
+ "remaining": self.turn_count()}
154
+
155
+ # -- escalations -----------------------------------------------------------
156
+
157
+ def add_escalation(self, e: EscalationRecord) -> EscalationRecord:
158
+ row = e.to_row()
159
+ with self._lock:
160
+ cols = ", ".join(row)
161
+ ph = ", ".join(["?"] * len(row))
162
+ self._conn.execute(
163
+ f"INSERT OR REPLACE INTO escalations ({cols}) VALUES ({ph})",
164
+ list(row.values()),
165
+ )
166
+ self._conn.commit()
167
+ return e
168
+
169
+ def update_escalation(self, e: EscalationRecord) -> EscalationRecord:
170
+ return self.add_escalation(e)
171
+
172
+ def latest_open_escalation(self, session_id: str) -> Optional[EscalationRecord]:
173
+ with self._lock:
174
+ r = self._conn.execute(
175
+ "SELECT * FROM escalations WHERE session_id=? AND outcome='unknown' "
176
+ "ORDER BY ts DESC LIMIT 1",
177
+ (session_id,),
178
+ ).fetchone()
179
+ return EscalationRecord.from_row(dict(r)) if r else None
180
+
181
+ def list_escalations(
182
+ self, *, kind: Optional[str] = None, limit: int = 50
183
+ ) -> List[EscalationRecord]:
184
+ q = "SELECT * FROM escalations"
185
+ params: List[Any] = []
186
+ if kind:
187
+ q += " WHERE kind=?"
188
+ params.append(kind)
189
+ q += " ORDER BY ts DESC LIMIT ?"
190
+ params.append(limit)
191
+ with self._lock:
192
+ rows = self._conn.execute(q, params).fetchall()
193
+ return [EscalationRecord.from_row(dict(r)) for r in rows]
194
+
195
+ def escalation_stats(self) -> dict:
196
+ with self._lock:
197
+ rows = self._conn.execute(
198
+ "SELECT kind, outcome, COUNT(*) AS n, SUM(distilled) AS d "
199
+ "FROM escalations GROUP BY kind, outcome"
200
+ ).fetchall()
201
+ total = self._conn.execute(
202
+ "SELECT COUNT(*) AS n FROM escalations"
203
+ ).fetchone()
204
+ by_bucket = [
205
+ {"kind": r["kind"], "outcome": r["outcome"], "count": int(r["n"]),
206
+ "distilled": int(r["d"] or 0)}
207
+ for r in rows
208
+ ]
209
+ return {"total": int(total["n"]), "buckets": by_bucket,
210
+ "turns_banked": self.turn_count()}
@@ -0,0 +1,30 @@
1
+ """Colony foundation data models.
2
+
3
+ Core dataclasses for people, signals, memories, and mesh nodes.
4
+ These models are the shared vocabulary across all Colony subsystems.
5
+ """
6
+
7
+ from .memory import Memory, MemoryStrength, MemoryType
8
+ from .mesh import MeshNode, NodeRole, NodeStatus
9
+ from .person import ContactInfo, ContactType, Person, RelationshipTier
10
+ from .signal import Signal, SignalStrength, SignalType
11
+
12
+ __all__ = [
13
+ # Person & relationships
14
+ "Person",
15
+ "ContactInfo",
16
+ "ContactType",
17
+ "RelationshipTier",
18
+ # Behavioral signals
19
+ "Signal",
20
+ "SignalType",
21
+ "SignalStrength",
22
+ # Memory
23
+ "Memory",
24
+ "MemoryType",
25
+ "MemoryStrength",
26
+ # Mesh
27
+ "MeshNode",
28
+ "NodeRole",
29
+ "NodeStatus",
30
+ ]
@@ -0,0 +1,80 @@
1
+ """Memory storage models.
2
+
3
+ Colony's memory system stores three types of knowledge:
4
+ - Episodic: Events and conversations (what happened)
5
+ - Semantic: Facts and preferences (what is known)
6
+ - Procedural: Workflows and processes (how to do things)
7
+
8
+ Memories support semantic search via embeddings and decay/reinforce
9
+ based on access patterns.
10
+ """
11
+
12
+ from dataclasses import dataclass, field
13
+ from datetime import datetime
14
+ from enum import Enum
15
+ from typing import Any, Dict, List, Optional
16
+
17
+
18
+ class MemoryType(str, Enum):
19
+ """Classification of memory content.
20
+
21
+ EPISODIC: Events, conversations, interactions
22
+ SEMANTIC: Facts, preferences, knowledge
23
+ PROCEDURAL: How-to knowledge, workflows, processes
24
+ """
25
+
26
+ EPISODIC = "episodic"
27
+ SEMANTIC = "semantic"
28
+ PROCEDURAL = "procedural"
29
+
30
+
31
+ class MemoryStrength(str, Enum):
32
+ """How strongly a memory is retained.
33
+
34
+ LOW: Weak retention, score < 0.3. Candidate for decay.
35
+ MEDIUM: Normal retention, score 0.3-0.7.
36
+ HIGH: Strong retention, score > 0.7. Frequently accessed or important.
37
+ """
38
+
39
+ LOW = "low"
40
+ MEDIUM = "medium"
41
+ HIGH = "high"
42
+
43
+
44
+ @dataclass
45
+ class Memory:
46
+ """A single memory unit in Colony's long-term store.
47
+
48
+ Memories are created from interactions, observations, and explicit input.
49
+ They support vector similarity search via the embedding field and have
50
+ strength/importance scores that evolve with access patterns.
51
+
52
+ Attributes:
53
+ id: Unique identifier
54
+ type: Category of memory (episodic, semantic, procedural)
55
+ content: The actual memory content as text
56
+ person_id: Related person, if the memory is about someone specific
57
+ strength: Retention strength 0-1, decays without access
58
+ importance: How important this memory is 0-1
59
+ tags: Categorization tags for filtering
60
+ embedding: Vector embedding for semantic search
61
+ source: Where this memory originated (channel, file, etc.)
62
+ created_at: When the memory was first stored
63
+ last_accessed: Most recent retrieval timestamp
64
+ access_count: How many times this memory has been retrieved
65
+ metadata: Additional structured data
66
+ """
67
+
68
+ id: str
69
+ type: MemoryType
70
+ content: str
71
+ person_id: Optional[str] = None
72
+ strength: float = 0.5
73
+ importance: float = 0.5
74
+ tags: List[str] = field(default_factory=list)
75
+ embedding: Optional[List[float]] = None
76
+ source: Optional[str] = None
77
+ created_at: Optional[datetime] = None
78
+ last_accessed: Optional[datetime] = None
79
+ access_count: int = 0
80
+ metadata: Dict[str, Any] = field(default_factory=dict)
apsimo/models/mesh.py ADDED
@@ -0,0 +1,72 @@
1
+ """Mesh node data models.
2
+
3
+ Colony runs as a distributed mesh where nodes take on different roles.
4
+ The Sovereign node is the primary brain, Regents are backup brains,
5
+ and Vassals are worker nodes that handle specific tasks.
6
+ """
7
+
8
+ from dataclasses import dataclass, field
9
+ from datetime import datetime
10
+ from enum import Enum
11
+ from typing import Any, Dict, List, Optional
12
+
13
+
14
+ class NodeRole(str, Enum):
15
+ """Role a node plays in the Colony mesh.
16
+
17
+ SOVEREIGN: The queen node with full brain capabilities.
18
+ REGENT: Backup brain, can assume sovereignty if needed.
19
+ VASSAL: Worker node, handles delegated tasks.
20
+ """
21
+
22
+ SOVEREIGN = "sovereign"
23
+ REGENT = "regent"
24
+ VASSAL = "vassal"
25
+
26
+
27
+ class NodeStatus(str, Enum):
28
+ """Current operational status of a mesh node.
29
+
30
+ ONLINE: Node is healthy and responsive.
31
+ OFFLINE: Node is unreachable.
32
+ DEGRADED: Node is up but not fully functional.
33
+ SYNCING: Node is catching up on state.
34
+ """
35
+
36
+ ONLINE = "online"
37
+ OFFLINE = "offline"
38
+ DEGRADED = "degraded"
39
+ SYNCING = "syncing"
40
+
41
+
42
+ @dataclass
43
+ class MeshNode:
44
+ """A node in the Colony mesh network.
45
+
46
+ Each node has a role, capabilities, and resource score that determines
47
+ what work gets routed to it. Nodes communicate via encrypted channels
48
+ using their public keys.
49
+
50
+ Attributes:
51
+ id: Unique node identifier
52
+ role: What role this node serves (sovereign, regent, vassal)
53
+ status: Current operational status
54
+ capabilities: What this node can do ("gpu", "neo4j", "llm", etc.)
55
+ resource_score: Relative compute power score (higher = more capable)
56
+ endpoint: URL for the node's API
57
+ public_key: Encryption key for secure mesh communication
58
+ last_seen: Most recent heartbeat timestamp
59
+ registered_at: When the node joined the mesh
60
+ metadata: Additional node-specific data
61
+ """
62
+
63
+ id: str
64
+ role: NodeRole
65
+ status: NodeStatus = NodeStatus.OFFLINE
66
+ capabilities: List[str] = field(default_factory=list)
67
+ resource_score: int = 0
68
+ endpoint: Optional[str] = None
69
+ public_key: Optional[bytes] = None
70
+ last_seen: Optional[datetime] = None
71
+ registered_at: Optional[datetime] = None
72
+ metadata: Dict[str, Any] = field(default_factory=dict)
@@ -0,0 +1,104 @@
1
+ """Person and relationship data models.
2
+
3
+ Core identity and relationship tracking for Colony's social graph.
4
+ Each person has a tier (computed from behavioral signals) and contact info
5
+ across multiple channels.
6
+
7
+ Two-layer model
8
+ ---------------
9
+ Colony maintains two distinct layers of relationship data:
10
+
11
+ - **Colony layer** (``score``, ``tier``): Colony's own evidence-based assessment,
12
+ derived from interaction signals observed across connected gateways. A score
13
+ of 80 means Colony has observed strong, consistent engagement — not that the
14
+ owner designated this person as important.
15
+
16
+ - **Owner layer** (``notes``, manual tier overrides in TrustTierManager): explicit
17
+ guidance the owner provides to inform Colony's initial orientation. Owner input
18
+ carries weight but does not override Colony's evidence once sufficient history
19
+ exists. The ``notes`` field is an owner-layer input: free-form context the
20
+ owner wants Colony to keep in mind.
21
+ """
22
+
23
+ from dataclasses import dataclass, field
24
+ from datetime import datetime
25
+ from enum import Enum
26
+ from typing import List, Optional
27
+
28
+
29
+ class RelationshipTier(str, Enum):
30
+ """Relationship tier based on interaction score.
31
+
32
+ Score ranges:
33
+ INNER_CIRCLE: 80-100 — closest relationships
34
+ TRUSTED: 60-79 — reliable, frequent contact
35
+ REGULAR: 30-59 — normal interaction level
36
+ PERIPHERAL: 10-29 — infrequent or new contacts
37
+ SILENCED: manual — explicitly muted by user
38
+ """
39
+
40
+ INNER_CIRCLE = "inner_circle"
41
+ TRUSTED = "trusted"
42
+ REGULAR = "regular"
43
+ PERIPHERAL = "peripheral"
44
+ SILENCED = "silenced"
45
+
46
+
47
+ class ContactType(str, Enum):
48
+ """Supported communication channels."""
49
+
50
+ PHONE = "phone"
51
+ EMAIL = "email"
52
+ TELEGRAM = "telegram"
53
+ DISCORD = "discord"
54
+ WHATSAPP = "whatsapp"
55
+ SIGNAL = "signal"
56
+
57
+
58
+ @dataclass
59
+ class ContactInfo:
60
+ """A single contact method for a person.
61
+
62
+ Attributes:
63
+ type: Communication channel (phone, email, etc.)
64
+ value: The actual contact identifier (number, address, handle)
65
+ label: Optional label like "personal", "work"
66
+ last_used: When this contact method was last used
67
+ """
68
+
69
+ type: ContactType
70
+ value: str
71
+ label: Optional[str] = None
72
+ last_used: Optional[datetime] = None
73
+
74
+
75
+ @dataclass
76
+ class Person:
77
+ """A person in Colony's social graph.
78
+
79
+ Represents anyone the Colony owner interacts with. The owner themselves
80
+ is represented with is_user=True.
81
+
82
+ Attributes:
83
+ id: Unique identifier
84
+ name: Display name
85
+ tier: Relationship tier (computed from score or manually set)
86
+ score: Relationship score 0-100, drives tier computation
87
+ aliases: Alternative names or handles
88
+ contacts: List of contact methods
89
+ first_seen: When this person first appeared in the system
90
+ last_interaction: Most recent interaction timestamp
91
+ notes: Free-form notes about the person
92
+ is_user: True if this represents the Colony owner
93
+ """
94
+
95
+ id: str
96
+ name: str
97
+ tier: RelationshipTier = RelationshipTier.PERIPHERAL
98
+ score: float = 0.0 # Colony's evidence-based assessment (0–100); not owner-assigned
99
+ aliases: List[str] = field(default_factory=list)
100
+ contacts: List[ContactInfo] = field(default_factory=list)
101
+ first_seen: Optional[datetime] = None
102
+ last_interaction: Optional[datetime] = None
103
+ notes: Optional[str] = None # Owner-layer input: context the owner wants Colony to know
104
+ is_user: bool = False