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,208 @@
1
+ """Explicit valid-time and observation-time windows for memory recall."""
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass
5
+ from datetime import datetime, timedelta, timezone
6
+ import json
7
+ import re
8
+ from zoneinfo import ZoneInfo
9
+
10
+ UTC = timezone.utc
11
+ _MONTHS = {name.casefold(): i for i, name in enumerate(
12
+ ("January", "February", "March", "April", "May", "June", "July", "August",
13
+ "September", "October", "November", "December"), 1)}
14
+ _DATE = r"\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2}))?"
15
+ _MONTH_DATE = r"(?:" + "|".join(_MONTHS) + r")\s+\d{1,2},?\s+\d{4}"
16
+ _EVENT = re.compile(r"\b(footage|camera|observed|spotted|seen|saw|happened|recorded|arrived|visited)\b", re.I)
17
+
18
+
19
+ def utc_timestamp(value: str | None) -> datetime | None:
20
+ if not value:
21
+ return None
22
+ try:
23
+ result = datetime.fromisoformat(value.replace("Z", "+00:00"))
24
+ return result.astimezone(UTC) if result.tzinfo else None
25
+ except (TypeError, ValueError):
26
+ return None
27
+
28
+
29
+ def parse_source_date(expression: str, *, observed_at: str | None, timezone_name="UTC") -> str | None:
30
+ """Resolve only explicit supported date text, anchored to source occurrence."""
31
+ zone = ZoneInfo(timezone_name)
32
+ value = expression.strip().casefold()
33
+ try:
34
+ if value in {"now", "today", "yesterday", "tomorrow"}:
35
+ observed = utc_timestamp(observed_at)
36
+ if observed is None:
37
+ return None
38
+ if value == "now":
39
+ return observed.isoformat()
40
+ local = observed.astimezone(zone).replace(hour=0, minute=0, second=0, microsecond=0)
41
+ local += timedelta(days={"yesterday": -1, "today": 0, "tomorrow": 1}[value])
42
+ return local.astimezone(UTC).isoformat()
43
+ if re.fullmatch(_DATE, expression, re.I):
44
+ date = datetime.fromisoformat(expression.replace("Z", "+00:00"))
45
+ if date.tzinfo is None:
46
+ date = date.replace(tzinfo=zone)
47
+ return date.astimezone(UTC).isoformat()
48
+ match = re.fullmatch(r"([a-z]+)\s+(\d{1,2}),?\s+(\d{4})", value)
49
+ if match and match[1] in _MONTHS:
50
+ return datetime(int(match[3]), _MONTHS[match[1]], int(match[2]), tzinfo=zone).astimezone(UTC).isoformat()
51
+ except ValueError:
52
+ pass
53
+ return None
54
+
55
+
56
+ def source_event_time(expression: str | None, *, observed_at: str | None, timezone_name="UTC") -> dict:
57
+ """Retain source-grounded event precision without inventing a point in time.
58
+
59
+ The caller verifies the expression against the quotation. An unresolved
60
+ optional event date is different from an unresolved state-validity condition.
61
+ The latter must still prevent certifying when a state holds.
62
+ """
63
+ if expression is None:
64
+ return {"status": "unknown"}
65
+ result = {"expression": expression}
66
+ parsed = parse_source_date(expression, observed_at=observed_at, timezone_name=timezone_name)
67
+ if parsed:
68
+ if expression.casefold().strip() == "now" or (re.fullmatch(_DATE, expression, re.I) and "T" in expression.upper()):
69
+ return {**result, "status": "resolved", "precision": "instant", "at": parsed}
70
+ begin = utc_timestamp(parsed).astimezone(ZoneInfo(timezone_name))
71
+ return {**result, "status": "resolved", "precision": "calendar_day", "start": parsed,
72
+ "end_exclusive": (begin + timedelta(days=1)).astimezone(UTC).isoformat()}
73
+ # This relation refers to the message's occurrence, never its later import.
74
+ if re.fullmatch(r"before (?:sending )?(?:this|the current) message", expression.strip(), re.I):
75
+ observed = utc_timestamp(observed_at)
76
+ if observed:
77
+ return {**result, "status": "bounded", "before": observed.isoformat()}
78
+ return {**result, "status": "unresolved"}
79
+
80
+
81
+ @dataclass(frozen=True)
82
+ class MemoryTimeQuery:
83
+ mode: str = "current"
84
+ start: str | None = None
85
+ end: str | None = None
86
+ expression: str | None = None
87
+
88
+ def accepts_observation(self, occurred_at: str | None) -> bool:
89
+ if self.mode != "observed_range":
90
+ return True
91
+ stamp = utc_timestamp(occurred_at)
92
+ if stamp is None:
93
+ return False
94
+ return (not self.start or stamp >= utc_timestamp(self.start)) and (not self.end or stamp < utc_timestamp(self.end))
95
+
96
+ def accepts_claim(self, claim: dict) -> bool:
97
+ if claim.get("retracted_by"):
98
+ return False
99
+ if self.mode == "unresolved_time":
100
+ return False
101
+ if self.mode == "observed_range":
102
+ event = claim.get('event_time', {})
103
+ if event.get('status') == 'resolved' and event.get('precision') == 'calendar_day':
104
+ start, end = utc_timestamp(event.get('start')), utc_timestamp(event.get('end_exclusive'))
105
+ return bool(start and end
106
+ and (not self.end or start < utc_timestamp(self.end))
107
+ and (not self.start or end > utc_timestamp(self.start)))
108
+ return self.accepts_observation(claim.get("event_at"))
109
+ start, end = utc_timestamp(claim.get("valid_from")), utc_timestamp(claim.get("valid_to"))
110
+ query_start, query_end = utc_timestamp(self.start), utc_timestamp(self.end)
111
+ if self.mode == "valid_range":
112
+ # A historical assertion with no known validity start cannot be
113
+ # certified as true on an arbitrary earlier date.
114
+ if start is None:
115
+ return False
116
+ return (query_end is None or start < query_end) and (end is None or query_start < end)
117
+ if query_start:
118
+ return (start is None or start <= query_start) and (end is None or query_start < end)
119
+ return not claim.get("superseded_by")
120
+
121
+
122
+ def _temporal_request_text(text: str) -> str:
123
+ """Exclude delimited evidence, retaining a quoted date used as an operand.
124
+
125
+ This only selects text for temporal interpretation. Retrieval still uses
126
+ the original query, including every quoted word and structured field.
127
+ """
128
+ text = re.sub(r"(?s)```.*?```|~~~.*?~~~", " ", text)
129
+ text = re.sub(r"(?m)^\s*>[^\n]*", " ", text)
130
+ decoder = json.JSONDecoder()
131
+ spans, through = [], 0
132
+ for match in re.finditer(r"[\[{]", text):
133
+ if match.start() < through:
134
+ continue
135
+ try:
136
+ value, end = decoder.raw_decode(text, match.start())
137
+ except ValueError:
138
+ continue
139
+ if isinstance(value, (dict, list)):
140
+ spans.append((match.start(), end))
141
+ through = end
142
+ for start, end in reversed(spans):
143
+ text = text[:start] + " " + text[end:]
144
+
145
+ def quoted(match):
146
+ value = match[0][1:-1].strip()
147
+ if (re.fullmatch(_DATE + "|" + _MONTH_DATE + "|today|yesterday|tomorrow", value, re.I)
148
+ or re.fullmatch(r"last\s+\d{1,3}\s+(?:hours?|days?)|"
149
+ r"(?:last|next|previous)\s+(?:week|month|year)|"
150
+ r"\d+\s+(?:weeks?|months?|years?)\s+ago", value, re.I)):
151
+ return value
152
+ return " "
153
+
154
+ return re.sub(r'''"(?:\\.|[^"\\])*"|“[^”]*”|(?<!\w)'(?:\\.|[^'\\])*'(?!\w)|`[^`\n]*`''', quoted, text)
155
+
156
+
157
+ def interpret_time_query(text: str, *, now: datetime, timezone_name="UTC") -> MemoryTimeQuery:
158
+ """Calendar days differ from trailing windows and from source ingestion.
159
+
160
+ A date without a clock covers that local calendar day. If a fact changes
161
+ during the day, both intersecting validity intervals remain visible.
162
+ """
163
+ zone = ZoneInfo(timezone_name)
164
+ text = _temporal_request_text(text[:4096])
165
+ mode = "observed_range" if _EVENT.search(text) else "valid_range"
166
+ duration = re.search(r"\blast\s+(\d{1,3})\s+(hours?|days?)\b", text, re.I)
167
+ if duration and mode == "observed_range":
168
+ delta = timedelta(hours=int(duration[1])) if duration[2].lower().startswith("hour") else timedelta(days=int(duration[1]))
169
+ return MemoryTimeQuery(mode, (now - delta).astimezone(UTC).isoformat(), now.astimezone(UTC).isoformat(), duration[0])
170
+ # Do not quietly turn unsupported ranges/relative dates into a current
171
+ # answer or select the first date in a multi-date question.
172
+ unsupported = re.search(
173
+ r"\b(before|after|between|until|through|last (?:week|month|year)|next (?:week|month|year)|"
174
+ r"previous (?:week|month|year)|\d+ (?:weeks?|months?|years?) ago)\b", text, re.I)
175
+ matches = list(re.finditer(_DATE + "|" + _MONTH_DATE + r"|\b(?:today|yesterday|tomorrow)\b", text, re.I))
176
+ if unsupported or len(matches) > 1:
177
+ return MemoryTimeQuery("unresolved_time", expression=text)
178
+ match = re.search(_DATE + "|" + _MONTH_DATE + r"|\b(?:today|yesterday|tomorrow)\b", text, re.I)
179
+ if match:
180
+ expression = match[0]
181
+ if (mode == "valid_range" and expression.lower() in {"today", "tomorrow"}
182
+ and not re.search(r"\b(as of|valid|effective|held|was|were)\b", text, re.I)):
183
+ # "What tea should I bring later today?" asks for a current
184
+ # preference; it does not assert that an undated preference has a
185
+ # certified historical validity interval.
186
+ return MemoryTimeQuery("current", now.astimezone(UTC).isoformat())
187
+ start = parse_source_date(expression, observed_at=now.isoformat(), timezone_name=timezone_name)
188
+ if start:
189
+ begin = utc_timestamp(start)
190
+ if "T" in expression:
191
+ end = (begin + timedelta(microseconds=1)).isoformat()
192
+ else:
193
+ end = (begin.astimezone(zone) + timedelta(days=1)).astimezone(UTC).isoformat()
194
+ if re.search(r"\bsince\s+" + re.escape(expression), text, re.I):
195
+ mode, end = "observed_range", now.astimezone(UTC).isoformat()
196
+ return MemoryTimeQuery(mode, start, end, expression)
197
+ return MemoryTimeQuery("current", now.astimezone(UTC).isoformat())
198
+
199
+
200
+ def filter_unstructured(rows: list[dict], query: MemoryTimeQuery) -> list[dict]:
201
+ """Observation questions cannot use write time as evidence of occurrence."""
202
+ if query.mode == "current":
203
+ return rows
204
+ if query.mode == "observed_range":
205
+ return [dict(row, validity_status="source_occurrence_only")
206
+ for row in rows if query.accepts_observation(row.get("occurred_at"))]
207
+ # Source quotations alone do not establish when the asserted fact held.
208
+ return [dict(row, validity_status="unknown") for row in rows]
@@ -0,0 +1,133 @@
1
+ """BeliefStore -- conflict records, supersession audit, property snapshots."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import sqlite3
8
+ import threading
9
+ import time
10
+ from typing import Any, Dict, List, Optional
11
+
12
+
13
+ class BeliefStore:
14
+ def __init__(self, db_path: Optional[str] = None) -> None:
15
+ self._lock = threading.RLock()
16
+ self._conn = sqlite3.connect(str(db_path) if db_path else ":memory:",
17
+ check_same_thread=False)
18
+ self._conn.row_factory = sqlite3.Row
19
+ with self._lock:
20
+ self._conn.execute(
21
+ """CREATE TABLE IF NOT EXISTS conflicts (
22
+ id TEXT PRIMARY KEY, scope TEXT, subject TEXT,
23
+ predicate TEXT, value_a TEXT, value_b TEXT,
24
+ meta_a TEXT, meta_b TEXT,
25
+ status TEXT DEFAULT 'open',
26
+ resolution TEXT, detected_at REAL, resolved_at REAL
27
+ )""")
28
+ self._conn.execute(
29
+ """CREATE TABLE IF NOT EXISTS supersession_audit (
30
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
31
+ scope TEXT, subject TEXT, predicate TEXT,
32
+ old_value TEXT, new_value TEXT,
33
+ old_confidence REAL, new_confidence REAL,
34
+ reason TEXT, actor TEXT, created_at REAL
35
+ )""")
36
+ self._conn.execute(
37
+ """CREATE TABLE IF NOT EXISTS property_snapshot (
38
+ entity_id TEXT, key TEXT, value TEXT, confidence REAL,
39
+ updated_at REAL, PRIMARY KEY (entity_id, key)
40
+ )""")
41
+ self._conn.commit()
42
+
43
+ # -- conflicts ---------------------------------------------------------
44
+ @staticmethod
45
+ def conflict_id(scope: str, subject: str, predicate: str,
46
+ value_a: str, value_b: str) -> str:
47
+ basis = "|".join(sorted([str(value_a), str(value_b)])
48
+ + [scope, subject.lower(), predicate.lower()])
49
+ return "bc-" + hashlib.sha256(basis.encode()).hexdigest()[:12]
50
+
51
+ def record_conflict(self, scope: str, subject: str, predicate: str,
52
+ value_a: str, value_b: str,
53
+ meta_a: Optional[dict] = None,
54
+ meta_b: Optional[dict] = None,
55
+ status: str = "open") -> str:
56
+ cid = self.conflict_id(scope, subject, predicate, value_a, value_b)
57
+ with self._lock:
58
+ self._conn.execute(
59
+ """INSERT INTO conflicts
60
+ (id, scope, subject, predicate, value_a, value_b,
61
+ meta_a, meta_b, status, detected_at)
62
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
63
+ ON CONFLICT(id) DO NOTHING""",
64
+ (cid, scope, subject[:200], predicate[:120],
65
+ str(value_a)[:300], str(value_b)[:300],
66
+ json.dumps(meta_a or {}), json.dumps(meta_b or {}),
67
+ status, time.time()))
68
+ self._conn.commit()
69
+ return cid
70
+
71
+ def resolve_conflict(self, conflict_id: str, resolution: str,
72
+ status: str = "resolved") -> None:
73
+ with self._lock:
74
+ self._conn.execute(
75
+ "UPDATE conflicts SET status=?, resolution=?, resolved_at=? "
76
+ "WHERE id=?",
77
+ (status, resolution[:400], time.time(), conflict_id))
78
+ self._conn.commit()
79
+
80
+ def conflicts(self, status: Optional[str] = None,
81
+ limit: int = 50) -> List[Dict[str, Any]]:
82
+ q = "SELECT * FROM conflicts"
83
+ params: List[Any] = []
84
+ if status:
85
+ q += " WHERE status=?"; params.append(status)
86
+ q += " ORDER BY detected_at DESC LIMIT ?"; params.append(limit)
87
+ with self._lock:
88
+ rows = self._conn.execute(q, params).fetchall()
89
+ return [dict(r) for r in rows]
90
+
91
+ # -- supersession audit ---------------------------------------------------
92
+ def record_supersession(self, scope: str, subject: str, predicate: str,
93
+ old_value: Any, new_value: Any,
94
+ old_confidence: float, new_confidence: float,
95
+ reason: str, actor: str = "belief_engine") -> None:
96
+ with self._lock:
97
+ self._conn.execute(
98
+ """INSERT INTO supersession_audit
99
+ (scope, subject, predicate, old_value, new_value,
100
+ old_confidence, new_confidence, reason, actor, created_at)
101
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
102
+ (scope, subject[:200], predicate[:120], str(old_value)[:300],
103
+ str(new_value)[:300], old_confidence, new_confidence,
104
+ reason[:300], actor, time.time()))
105
+ self._conn.commit()
106
+
107
+ def supersessions(self, limit: int = 50) -> List[Dict[str, Any]]:
108
+ with self._lock:
109
+ rows = self._conn.execute(
110
+ "SELECT * FROM supersession_audit ORDER BY created_at DESC "
111
+ "LIMIT ?", (limit,)).fetchall()
112
+ return [dict(r) for r in rows]
113
+
114
+ # -- property snapshots (for change/supersession detection) ---------------
115
+ def snapshot_get(self, entity_id: str, key: str) -> Optional[Dict[str, Any]]:
116
+ with self._lock:
117
+ r = self._conn.execute(
118
+ "SELECT * FROM property_snapshot WHERE entity_id=? AND key=?",
119
+ (entity_id, key)).fetchone()
120
+ return dict(r) if r else None
121
+
122
+ def snapshot_put(self, entity_id: str, key: str, value: Any,
123
+ confidence: float) -> None:
124
+ with self._lock:
125
+ self._conn.execute(
126
+ """INSERT INTO property_snapshot
127
+ (entity_id, key, value, confidence, updated_at)
128
+ VALUES (?, ?, ?, ?, ?)
129
+ ON CONFLICT(entity_id, key) DO UPDATE SET
130
+ value=?, confidence=?, updated_at=?""",
131
+ (entity_id, key, str(value)[:300], confidence, time.time(),
132
+ str(value)[:300], confidence, time.time()))
133
+ self._conn.commit()