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,23 @@
1
+ """Belief maintenance (item 7): drive the graph's epistemic scaffolding.
2
+
3
+ Detects contradictions (same subject + predicate, conflicting value) across
4
+ world-model properties and graph memories, resolves them by recency >
5
+ confidence > source-trust (marking losers superseded, with an audit trail),
6
+ surfaces genuinely unresolvable conflicts as internal review initiatives,
7
+ and decays stale world-state confidence past its TTL.
8
+
9
+ Modes (COLONY_BELIEFS_MODE, default shadow = calibration): shadow detects,
10
+ records and surfaces review initiatives without mutating epistemic state;
11
+ live also resolves and decays. Resolutions are journaled (Amendment 1.4).
12
+ """
13
+
14
+ from apsimo.beliefs.models import Claim, beliefs_mode
15
+ from apsimo.beliefs.store import BeliefStore
16
+ from apsimo.beliefs.contradictions import detect_conflicts, claims_from_text
17
+ from apsimo.beliefs.resolve import pick_winner, source_trust
18
+ from apsimo.beliefs.engine import BeliefEngine
19
+
20
+ __all__ = [
21
+ "Claim", "BeliefStore", "BeliefEngine", "detect_conflicts",
22
+ "claims_from_text", "pick_winner", "source_trust", "beliefs_mode",
23
+ ]
@@ -0,0 +1,109 @@
1
+ """Contradiction detection: same subject + predicate, conflicting value.
2
+
3
+ Two claim sources:
4
+ - World-model entity properties (fully structured; exact).
5
+ - Graph memories (free text): a CONSERVATIVE copular extractor pulls
6
+ (subject, predicate, value) triples only from short, unambiguous
7
+ constructions, so detected conflicts are real rather than parser noise.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from typing import Any, List, Optional, Tuple
14
+
15
+ from apsimo.beliefs.models import Claim, norm_value
16
+
17
+ # Conservative copular / relational patterns. Subject <= 4 tokens, sentence
18
+ # bounded, value bounded. Anything fancier waits for an LLM pass.
19
+ _PATTERNS: List[Tuple[re.Pattern, str]] = [
20
+ # "X's <predicate> is <value>"
21
+ (re.compile(r"^(?P<subj>[A-Z][\w .&-]{1,40}?)'s\s+(?P<pred>[a-z ]{2,25})\s+"
22
+ r"(?:is|are)\s+(?P<val>[^,.;]{1,60})[.,;]?$"), "possessive"),
23
+ # "X works at Y" / "X works for Y"
24
+ (re.compile(r"^(?P<subj>[A-Z][\w .&-]{1,40}?)\s+works?\s+(?:at|for)\s+"
25
+ r"(?P<val>[^,.;]{1,60})[.,;]?$"), "works_at"),
26
+ # "X lives in Y" / "X is based in Y" / "X is located in Y"
27
+ (re.compile(r"^(?P<subj>[A-Z][\w .&-]{1,40}?)\s+(?:lives|resides)\s+in\s+"
28
+ r"(?P<val>[^,.;]{1,60})[.,;]?$"), "location"),
29
+ (re.compile(r"^(?P<subj>[A-Z][\w .&-]{1,40}?)\s+is\s+(?:based|located)\s+in\s+"
30
+ r"(?P<val>[^,.;]{1,60})[.,;]?$"), "location"),
31
+ # "X is the <role> of/at Y" -> predicate role
32
+ (re.compile(r"^(?P<subj>[A-Z][\w .&-]{1,40}?)\s+is\s+the\s+"
33
+ r"(?P<pred>[a-z ]{2,25})\s+(?:of|at)\s+"
34
+ r"(?P<val>[^,.;]{1,60})[.,;]?$"), "role"),
35
+ ]
36
+
37
+ _SENT_SPLIT = re.compile(r"(?<=[.!?])\s+|\n+")
38
+
39
+ # Values that carry no belief content.
40
+ _EMPTY_VALUES = frozenset({"", "unknown", "none", "n a", "na", "null", "tbd"})
41
+
42
+
43
+ def claims_from_text(text: str, *, confidence: float = 0.5, ts: float = 0.0,
44
+ source: str = "inference", ref: str = "") -> List[Claim]:
45
+ """Conservative triple extraction from one memory's content."""
46
+ out: List[Claim] = []
47
+ for sent in _SENT_SPLIT.split(text or ""):
48
+ sent = sent.strip()
49
+ if not sent or len(sent) > 140:
50
+ continue
51
+ for pat, kind in _PATTERNS:
52
+ m = pat.match(sent)
53
+ if not m:
54
+ continue
55
+ subj = m.group("subj").strip()
56
+ if len(subj.split()) > 4:
57
+ continue
58
+ pred = (m.groupdict().get("pred") or kind).strip().lower()
59
+ val = m.group("val").strip()
60
+ if norm_value(val) in _EMPTY_VALUES:
61
+ continue
62
+ out.append(Claim(subject=subj, predicate=pred, value=val,
63
+ confidence=confidence, ts=ts, source=source,
64
+ ref=ref, scope="graph"))
65
+ break
66
+ return out
67
+
68
+
69
+ def property_claims(entity: Any) -> List[Claim]:
70
+ """Structured claims from a world-model entity's properties."""
71
+ out: List[Claim] = []
72
+ props = getattr(entity, "properties", None) or {}
73
+ name = getattr(entity, "name", "") or ""
74
+ eid = getattr(entity, "id", "") or ""
75
+ updated = getattr(entity, "updated_at", None)
76
+ try:
77
+ ts = updated.timestamp() if hasattr(updated, "timestamp") else 0.0
78
+ except Exception:
79
+ ts = 0.0
80
+ base_conf = float(getattr(entity, "confidence", 0.5) or 0.5)
81
+ for key, value in props.items():
82
+ if key.startswith("_conf_") or value in (None, ""):
83
+ continue
84
+ conf = float(props.get(f"_conf_{key}", base_conf) or base_conf)
85
+ out.append(Claim(subject=name or eid, predicate=key, value=str(value),
86
+ confidence=conf, ts=ts, source="world_model",
87
+ ref=eid, scope="world_model"))
88
+ return out
89
+
90
+
91
+ def detect_conflicts(claims: List[Claim]) -> List[Tuple[Claim, Claim]]:
92
+ """Pairs of claims sharing subject+predicate with conflicting values.
93
+
94
+ Within a key, claims whose values agree (normalized/containment) are
95
+ treated as corroboration, not conflict.
96
+ """
97
+ by_key = {}
98
+ for c in claims or []:
99
+ by_key.setdefault(c.key(), []).append(c)
100
+ out: List[Tuple[Claim, Claim]] = []
101
+ for _key, group in by_key.items():
102
+ if len(group) < 2:
103
+ continue
104
+ for i in range(len(group)):
105
+ for j in range(i + 1, len(group)):
106
+ a, b = group[i], group[j]
107
+ if not a.same_value(b):
108
+ out.append((a, b))
109
+ return out
@@ -0,0 +1,61 @@
1
+ """Stale world-state decay: entities unseen past the TTL lose confidence.
2
+
3
+ Graph memory decay already runs daily (_phase_memory_decay + ColonyGraph
4
+ half-life machinery); this module covers the WORLD MODEL side, which had no
5
+ staleness treatment at all.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from datetime import datetime, timezone
12
+ from typing import Any, List
13
+
14
+ from apsimo.beliefs.models import stale_ttl_days
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ _DECAY_FACTOR = 0.9
19
+ _MIN_CONFIDENCE = 0.1
20
+
21
+
22
+ def _age_days(entity: Any, now: datetime) -> float:
23
+ last = (getattr(entity, "last_seen", None)
24
+ or getattr(entity, "updated_at", None)
25
+ or getattr(entity, "created_at", None))
26
+ if last is None:
27
+ return 0.0
28
+ try:
29
+ if isinstance(last, str):
30
+ last = datetime.fromisoformat(last.replace("Z", "+00:00"))
31
+ if last.tzinfo is None:
32
+ last = last.replace(tzinfo=timezone.utc)
33
+ return max(0.0, (now - last).total_seconds() / 86400.0)
34
+ except Exception:
35
+ return 0.0
36
+
37
+
38
+ async def stale_entities(world_store: Any, limit: int = 500) -> List[Any]:
39
+ """Entities whose last observation is older than the TTL."""
40
+ if world_store is None:
41
+ return []
42
+ try:
43
+ ents = await world_store.find_entities(query="", min_confidence=0.0,
44
+ limit=limit)
45
+ except Exception:
46
+ return []
47
+ now = datetime.now(timezone.utc)
48
+ ttl = stale_ttl_days()
49
+ return [e for e in ents or [] if _age_days(e, now) > ttl]
50
+
51
+
52
+ async def decay_entity(world_store: Any, entity: Any) -> float:
53
+ """Lower one stale entity's confidence (bounded). Returns new value."""
54
+ new_conf = max(_MIN_CONFIDENCE,
55
+ float(getattr(entity, "confidence", 0.5)) * _DECAY_FACTOR)
56
+ entity.confidence = new_conf
57
+ try:
58
+ await world_store.upsert_entity(entity)
59
+ except Exception:
60
+ logger.debug("stale decay upsert failed", exc_info=True)
61
+ return new_conf
@@ -0,0 +1,479 @@
1
+ """BeliefEngine -- periodic belief maintenance over graph + world model.
2
+
3
+ Runs from the autonomy loop's daily `_phase_belief_maintenance`:
4
+ 1. World-model supersessions: snapshot-diff entity properties; a changed
5
+ value writes a supersession audit row (who/what/when/why survives even
6
+ though the store keeps only the winning value).
7
+ 2. Graph contradictions: conservative claim extraction over recent semantic
8
+ memories; same subject+predicate with conflicting values -> conflict
9
+ record. Resolution (live mode) marks the loser's epistemic_state
10
+ "superseded" with an audit trail; unresolvable conflicts become internal
11
+ review initiatives (never a reach-out).
12
+ 3. Stale decay: world-model entities unseen past the TTL lose confidence
13
+ (live mode).
14
+
15
+ Shadow mode (default) is the calibration stage: detect + record + surface,
16
+ mutate nothing. Every resolution/decay in live mode is journaled.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import asyncio
22
+ import logging
23
+ from typing import Any, Dict, List, Optional
24
+
25
+ from apsimo.beliefs.contradictions import (
26
+ claims_from_text, detect_conflicts, property_claims,
27
+ )
28
+ from apsimo.beliefs.decay import decay_entity, stale_entities
29
+ from apsimo.beliefs.models import Claim, beliefs_mode
30
+ from apsimo.beliefs.resolve import pick_winner
31
+ from apsimo.beliefs.store import BeliefStore
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+ _MEMORY_QUERY = """
36
+ MATCH (m:Memory)
37
+ WHERE m.type IN ['semantic', 'episodic']
38
+ AND m.superseded_by IS NULL
39
+ AND NOT coalesce(m.epistemic_state, 'inferred')
40
+ IN ['superseded', 'deprecated', 'archived']
41
+ RETURN m.id AS id, m.content AS content, m.source_type AS source_type,
42
+ coalesce(m.effective_confidence, m.base_confidence, 0.5) AS confidence,
43
+ m.created_at AS created_at
44
+ ORDER BY m.created_at DESC
45
+ LIMIT $limit
46
+ """
47
+
48
+
49
+ class BeliefEngine:
50
+ def __init__(self, store: BeliefStore, *, world_store: Any = None,
51
+ graph: Any = None, initiative_store: Any = None,
52
+ journal: Any = None, self_model: Any = None) -> None:
53
+ self.store = store
54
+ self._world = world_store
55
+ self._graph = graph
56
+ self._initiatives = initiative_store
57
+ self._journal = journal
58
+ self._self_model = self_model
59
+ self.last_report: Dict[str, Any] = {}
60
+
61
+ # ------------------------------------------------------------------
62
+ # Inline hook: cheap detection at property-update time
63
+ # ------------------------------------------------------------------
64
+
65
+ def note_property_update(self, entity_id: str, key: str,
66
+ old_value: Any, new_value: Any,
67
+ old_confidence: float,
68
+ new_confidence: float) -> None:
69
+ """Called inline when a world-model property changes value. Records
70
+ the superseded value; heavy resolution stays in the periodic run."""
71
+ from apsimo.beliefs.models import norm_value
72
+ if norm_value(old_value) == norm_value(new_value):
73
+ return
74
+ try:
75
+ self.store.record_supersession(
76
+ "world_model", entity_id, key, old_value, new_value,
77
+ old_confidence, new_confidence,
78
+ reason="higher-confidence update", actor="world_model_store")
79
+ except Exception:
80
+ logger.debug("inline supersession record failed", exc_info=True)
81
+
82
+ # ------------------------------------------------------------------
83
+ # Periodic run
84
+ # ------------------------------------------------------------------
85
+
86
+ def _effective_mode(self) -> str:
87
+ """Env mode graduated by the trust engine (Amendment 1.2). Belief
88
+ RESOLUTION mutates epistemic state autonomously (no sub-gate), so it
89
+ requires the fully-earned act_first stage; env "live" remains the
90
+ owner override, "off" stays off.
91
+
92
+ The trust ladder had a catch-22 for beliefs: graduation ask_first ->
93
+ act_first needs a real (non-shadow) track record, but the engine only
94
+ acted at act_first, so every outcome stayed shadow and the domain
95
+ could never graduate. COLONY_BELIEFS_SUPERVISED_LIVE=1 adds a
96
+ 'supervised' rung at ask_first: REVERSIBLE mutations only (epistemic
97
+ supersession that preserves the old value on the superseded node,
98
+ and bounded stale-confidence decay — no deletion), journaled with
99
+ prior state, outcomes recorded shadow=False. Destructive resolution
100
+ (anything that deletes or merges nodes) must still gate on the full
101
+ "live" mode, i.e. act_first or the explicit env override.
102
+
103
+ H1.2: the rung logic itself now lives in self_model/supervised.py
104
+ (generic across domains; enable via COLONY_SUPERVISED_LIVE_DOMAINS=
105
+ beliefs or the legacy alias COLONY_BELIEFS_SUPERVISED_LIVE=1). The
106
+ reversible operations named above are pinned in its
107
+ REVERSIBLE_CONTRACT under ("beliefs", "supersede"/"decay")."""
108
+ from apsimo.self_model.supervised import effective_mode
109
+ return effective_mode("beliefs", beliefs_mode(),
110
+ getattr(self._self_model, "trust", None))
111
+
112
+ async def run(self) -> Dict[str, Any]:
113
+ mode = self._effective_mode()
114
+ report: Dict[str, Any] = {
115
+ "mode": mode, "supersessions": 0, "conflicts_detected": 0,
116
+ "resolved": 0, "review_initiatives": 0, "decayed": 0,
117
+ "causal_conflicts": 0, "causal_decayed": 0,
118
+ "pass_errors": 0,
119
+ }
120
+ self.last_report = report
121
+ if mode == "off":
122
+ return report
123
+ try:
124
+ await self._world_model_pass(report)
125
+ except Exception:
126
+ report["pass_errors"] += 1
127
+ logger.debug("belief world-model pass failed", exc_info=True)
128
+ try:
129
+ await self._graph_pass(report, mode)
130
+ except Exception:
131
+ report["pass_errors"] += 1
132
+ logger.debug("belief graph pass failed", exc_info=True)
133
+ try:
134
+ await self._decay_pass(report, mode)
135
+ except Exception:
136
+ report["pass_errors"] += 1
137
+ logger.debug("belief decay pass failed", exc_info=True)
138
+ try:
139
+ await self._causal_pass(report, mode)
140
+ except Exception:
141
+ report["pass_errors"] += 1
142
+ logger.debug("belief causal pass failed", exc_info=True)
143
+ logger.info(
144
+ "belief-maintenance[%s]: supersessions=%d conflicts=%d "
145
+ "resolved=%d review=%d decayed=%d causal_conflicts=%d "
146
+ "causal_decayed=%d errors=%d", mode,
147
+ report["supersessions"], report["conflicts_detected"],
148
+ report["resolved"], report["review_initiatives"],
149
+ report["decayed"], report["causal_conflicts"],
150
+ report["causal_decayed"], report["pass_errors"])
151
+ self._record_outcome(mode, report)
152
+ return report
153
+
154
+ def _record_outcome(self, mode: str, report: Dict[str, Any]) -> None:
155
+ """Feed the trust ladder what the run EARNED (H1.3).
156
+
157
+ Strict (COLONY_TRUST_STRICT_OUTCOMES=1, the default): a run where
158
+ any pass raised records a failure; a run that actually mutated
159
+ state (resolved + decayed + supersessions > 0) records a success;
160
+ a no-op run records nothing. Supervised/live outcomes stay REAL
161
+ (shadow=False) — that is the whole point of the rung — but a
162
+ streak of no-op runs no longer builds a fake track record that
163
+ would graduate beliefs to act_first (and unlock destructive
164
+ resolution) unearned.
165
+
166
+ Legacy (flag=0): the historical unconditional per-run success.
167
+ """
168
+ if self._self_model is None:
169
+ return
170
+ try:
171
+ from apsimo.self_model.supervised import (
172
+ strict_trust_outcomes,
173
+ )
174
+ shadow = mode not in ("live", "supervised")
175
+ if not strict_trust_outcomes():
176
+ self._self_model.record("beliefs", "success", shadow=shadow)
177
+ return
178
+ mutated = (report["resolved"] + report["decayed"]
179
+ + report["supersessions"]
180
+ + report.get("causal_decayed", 0)) > 0
181
+ if report["pass_errors"] > 0:
182
+ self._self_model.record("beliefs", "failure", shadow=shadow)
183
+ elif mutated:
184
+ self._self_model.record("beliefs", "success", shadow=shadow)
185
+ # else: no-op run — nothing earned, nothing recorded
186
+ except Exception:
187
+ pass
188
+
189
+ # -- world model: snapshot diff -> supersession audit -------------------
190
+ async def _world_model_pass(self, report: Dict[str, Any]) -> None:
191
+ if self._world is None:
192
+ return
193
+ try:
194
+ ents = await self._world.find_entities(query="",
195
+ min_confidence=0.0,
196
+ limit=500)
197
+ except Exception:
198
+ return
199
+ from apsimo.beliefs.models import norm_value
200
+ for e in ents or []:
201
+ for c in property_claims(e):
202
+ snap = self.store.snapshot_get(c.ref, c.predicate)
203
+ if snap is not None and norm_value(snap["value"]) != norm_value(c.value):
204
+ self.store.record_supersession(
205
+ "world_model", c.subject, c.predicate,
206
+ snap["value"], c.value,
207
+ float(snap.get("confidence") or 0.0), c.confidence,
208
+ reason="property value changed since last scan",
209
+ actor="belief_engine")
210
+ report["supersessions"] += 1
211
+ self.store.snapshot_put(c.ref, c.predicate, c.value,
212
+ c.confidence)
213
+
214
+ # -- graph: claim conflicts -> resolve / review ---------------------------
215
+ async def _graph_pass(self, report: Dict[str, Any], mode: str) -> None:
216
+ claims = await self._graph_claims()
217
+ if not claims:
218
+ return
219
+ for a, b in detect_conflicts(claims):
220
+ report["conflicts_detected"] += 1
221
+ cid = self.store.record_conflict(
222
+ "graph", a.subject, a.predicate, a.value, b.value,
223
+ meta_a={"ref": a.ref, "source": a.source,
224
+ "confidence": a.confidence, "ts": a.ts},
225
+ meta_b={"ref": b.ref, "source": b.source,
226
+ "confidence": b.confidence, "ts": b.ts})
227
+ picked = pick_winner(a, b)
228
+ if picked is None:
229
+ self.store.resolve_conflict(
230
+ cid, "unresolvable: equal recency/confidence/trust",
231
+ status="review")
232
+ self._surface_review(a, b, cid)
233
+ report["review_initiatives"] += 1
234
+ continue
235
+ winner, loser = picked
236
+ # Supersession is the REVERSIBLE resolution: the loser node is
237
+ # marked (epistemic_state + superseded_by pointer) with its old
238
+ # value preserved on it, and the transition is journaled — so
239
+ # the supervised rung may perform it. Any future DESTRUCTIVE
240
+ # resolution (deleting or merging nodes) must check
241
+ # mode == "live" here, never "supervised".
242
+ if mode not in ("live", "supervised"):
243
+ logger.info(
244
+ "SHADOW-BELIEF conflict %s: would supersede %r "
245
+ "(%s=%s) in favor of %r", cid, loser.value,
246
+ a.subject, a.predicate, winner.value)
247
+ continue
248
+ await self._supersede_memory(winner, loser, cid)
249
+ report["resolved"] += 1
250
+
251
+ async def _graph_claims(self, limit: int = 200) -> List[Claim]:
252
+ if self._graph is None or not hasattr(self._graph, "run_query"):
253
+ return []
254
+ try:
255
+ # Register this exact parameterized read query with the graph
256
+ # client's Cypher allowlist (single-sourced here).
257
+ if hasattr(type(self._graph), "register_allowed_cypher"):
258
+ type(self._graph).register_allowed_cypher(_MEMORY_QUERY)
259
+ rows = await self._graph.run_query(_MEMORY_QUERY,
260
+ {"limit": int(limit)})
261
+ except Exception as exc:
262
+ logger.debug("belief memory query failed: %s", exc)
263
+ return []
264
+ claims: List[Claim] = []
265
+ for r in rows or []:
266
+ content = str(r.get("content") or "")
267
+ created = r.get("created_at")
268
+ try:
269
+ ts = created.to_native().timestamp() if hasattr(
270
+ created, "to_native") else (
271
+ created.timestamp() if hasattr(created, "timestamp")
272
+ else 0.0)
273
+ except Exception:
274
+ ts = 0.0
275
+ claims.extend(claims_from_text(
276
+ content,
277
+ confidence=float(r.get("confidence") or 0.5),
278
+ ts=ts, source=str(r.get("source_type") or "inference"),
279
+ ref=str(r.get("id") or "")))
280
+ return claims
281
+
282
+ async def _supersede_memory(self, winner: Claim, loser: Claim,
283
+ conflict_id: str) -> None:
284
+ try:
285
+ if loser.ref and hasattr(self._graph, "transition_epistemic_state"):
286
+ await self._graph.transition_epistemic_state(
287
+ loser.ref, "superseded",
288
+ superseded_by=winner.ref or None)
289
+ self.store.record_supersession(
290
+ "graph", loser.subject, loser.predicate, loser.value,
291
+ winner.value, loser.confidence, winner.confidence,
292
+ reason=f"conflict {conflict_id}: lost on "
293
+ "recency/confidence/trust ordering")
294
+ self.store.resolve_conflict(
295
+ conflict_id,
296
+ f"kept {winner.value!r} ({winner.source}, "
297
+ f"conf={winner.confidence:.2f}); superseded {loser.ref}")
298
+ if self._journal is not None:
299
+ self._journal.record(
300
+ "beliefs",
301
+ f"superseded belief {loser.subject} {loser.predicate}="
302
+ f"{loser.value!r} in favor of {winner.value!r}",
303
+ reasoning="conflict resolution: recency > confidence > "
304
+ "source trust",
305
+ confidence=winner.confidence,
306
+ reversibility="recoverable", decision="acted",
307
+ ref=conflict_id)
308
+ except Exception:
309
+ logger.debug("supersede failed for %s", conflict_id,
310
+ exc_info=True)
311
+
312
+ def _surface_review(self, a: Claim, b: Claim, conflict_id: str) -> None:
313
+ """Unresolvable -> internal review initiative (never a reach-out)."""
314
+ if self._initiatives is None:
315
+ return
316
+ try:
317
+ self._initiatives.create(
318
+ type="data_quality",
319
+ description=(
320
+ f"Belief conflict needs review: {a.subject} "
321
+ f"{a.predicate} = {a.value!r} vs {b.value!r} "
322
+ f"(equal recency/confidence/trust)"),
323
+ priority=0.55,
324
+ rationale=f"belief conflict {conflict_id}; sources "
325
+ f"{a.source} vs {b.source}",
326
+ dedup_key=f"belief_conflict:{conflict_id}",
327
+ source_type="belief_maintenance",
328
+ created_by="belief_engine",
329
+ )
330
+ except Exception:
331
+ logger.debug("review initiative creation failed", exc_info=True)
332
+
333
+ # -- stale decay -----------------------------------------------------------
334
+ async def _decay_pass(self, report: Dict[str, Any], mode: str) -> None:
335
+ stale = await stale_entities(self._world)
336
+ if not stale:
337
+ return
338
+ # Decay is reversible by construction (bounded multiplicative drop,
339
+ # floored at 0.1, never a deletion; prior value journaled below), so
340
+ # the supervised rung may perform it.
341
+ if mode not in ("live", "supervised"):
342
+ logger.info("SHADOW-BELIEF decay: %d stale entit(ies) would "
343
+ "lose confidence", len(stale))
344
+ return
345
+ for e in stale[:100]:
346
+ old = float(getattr(e, "confidence", 0.5) or 0.5)
347
+ new = await decay_entity(self._world, e)
348
+ report["decayed"] += 1
349
+ if self._journal is not None:
350
+ self._journal.record(
351
+ "beliefs",
352
+ f"decayed stale entity {getattr(e, 'name', '?')} "
353
+ f"confidence {old:.2f} -> {new:.2f}",
354
+ reasoning="unseen past TTL", decision="acted",
355
+ reversibility="recoverable",
356
+ ref=str(getattr(e, "id", "")))
357
+
358
+ # -- causal edges: contradiction + staleness (H2.3) -----------------------
359
+ async def _causal_pass(self, report: Dict[str, Any], mode: str) -> None:
360
+ """Two causal fabrication controls:
361
+
362
+ CONTRADICTION: opposing causal claims (WM_CAUSES/WM_ENABLES vs
363
+ WM_BLOCKS/WM_INHIBITS over the same ordered pair) become a conflict
364
+ row (status "review") + review initiative and are NEVER auto-resolved
365
+ — not in live mode, not at any trust stage. Recency/confidence
366
+ ordering settles graph claims, but silently picking a causal winner
367
+ would let one confidently-worded fabrication erase a true edge.
368
+
369
+ STALENESS: edges unsupported past COLONY_CAUSAL_TTL_DAYS lose 0.05
370
+ confidence per run, floored at 0.2, never deleted — live/supervised
371
+ only (a bounded reversible mutation, so the supervised rung may
372
+ perform it, exactly like entity decay).
373
+ """
374
+ if self._world is None:
375
+ return
376
+ from apsimo.world_model import causal_maintenance as cm
377
+ edges = await cm.load_causal_edges(self._world)
378
+ if not edges:
379
+ return
380
+
381
+ # Contradictions: detect + record + surface in every non-off mode
382
+ # (a conflict row is bookkeeping, not world-state mutation).
383
+ for pos, neg in cm.opposing_pairs(edges):
384
+ report["causal_conflicts"] += 1
385
+ pos_props = getattr(pos, "properties", None) or {}
386
+ neg_props = getattr(neg, "properties", None) or {}
387
+ cid = self.store.record_conflict(
388
+ "world_causal", f"{pos.source_id}->{pos.target_id}",
389
+ "causal_polarity", pos.relationship_type,
390
+ neg.relationship_type,
391
+ meta_a={"edge_id": pos.id, "confidence": pos.confidence,
392
+ "evidence": pos_props.get("evidence")},
393
+ meta_b={"edge_id": neg.id, "confidence": neg.confidence,
394
+ "evidence": neg_props.get("evidence")},
395
+ status="review")
396
+ self._surface_causal_review(pos, neg, cid)
397
+ report["review_initiatives"] += 1
398
+
399
+ # Staleness decay (live/supervised only).
400
+ stale = cm.stale_causal_edges(edges)
401
+ if not stale:
402
+ return
403
+ if mode not in ("live", "supervised"):
404
+ logger.info("SHADOW-BELIEF causal decay: %d stale causal "
405
+ "edge(s) would lose confidence", len(stale))
406
+ return
407
+ for e in stale[:100]:
408
+ old = float(getattr(e, "confidence", 0.0) or 0.0)
409
+ new = max(cm.CAUSAL_DECAY_FLOOR, old - cm.CAUSAL_DECAY_STEP)
410
+ if new >= old:
411
+ continue
412
+ support_ts = cm.support_timestamp(e)
413
+ e.confidence = new
414
+ props = dict(getattr(e, "properties", None) or {})
415
+ # Preserve the ORIGINAL support timestamp: the decay write must
416
+ # not reset the staleness clock, so the edge keeps losing 0.05
417
+ # per run until the floor or fresh corroboration.
418
+ if support_ts:
419
+ props.setdefault(cm.LAST_SUPPORT_PROP, support_ts)
420
+ props["stale_decays"] = int(props.get("stale_decays", 0) or 0) + 1
421
+ e.properties = props
422
+ try:
423
+ await self._world.upsert_relationship(e)
424
+ except Exception:
425
+ logger.debug("causal decay upsert failed", exc_info=True)
426
+ continue
427
+ report["causal_decayed"] += 1
428
+ if self._journal is not None:
429
+ self._journal.record(
430
+ "beliefs",
431
+ f"decayed stale causal edge {e.source_id} "
432
+ f"-{e.relationship_type}-> {e.target_id} confidence "
433
+ f"{old:.2f} -> {new:.2f}",
434
+ reasoning="no corroboration within "
435
+ f"{cm.causal_ttl_days():.0f}d TTL",
436
+ decision="acted", reversibility="recoverable",
437
+ ref=str(getattr(e, "id", "")))
438
+
439
+ def _surface_causal_review(self, pos: Any, neg: Any, cid: str) -> None:
440
+ """Causal contradiction -> internal review initiative (never a
441
+ reach-out, never an auto-resolution)."""
442
+ if self._initiatives is None:
443
+ return
444
+ try:
445
+ self._initiatives.create(
446
+ type="data_quality",
447
+ description=(
448
+ f"Causal contradiction needs review: "
449
+ f"{pos.source_id} {pos.relationship_type} "
450
+ f"{pos.target_id} vs {neg.relationship_type} — "
451
+ "opposing causal claims are never auto-resolved"),
452
+ priority=0.6,
453
+ rationale=(f"causal conflict {cid}; confidences "
454
+ f"{float(pos.confidence or 0):.2f} vs "
455
+ f"{float(neg.confidence or 0):.2f}"),
456
+ dedup_key=f"causal_conflict:{cid}",
457
+ source_type="belief_maintenance",
458
+ created_by="belief_engine",
459
+ )
460
+ except Exception:
461
+ logger.debug("causal review initiative creation failed",
462
+ exc_info=True)
463
+
464
+ # -- reads -----------------------------------------------------------------
465
+ def conflicts(self, status: Optional[str] = None,
466
+ limit: int = 50) -> List[Dict[str, Any]]:
467
+ return self.store.conflicts(status=status, limit=limit)
468
+
469
+ def status(self) -> Dict[str, Any]:
470
+ return {
471
+ "mode": beliefs_mode(),
472
+ "effective_mode": self._effective_mode(),
473
+ "last_report": self.last_report,
474
+ "open_conflicts": len(self.store.conflicts(status="open",
475
+ limit=1000)),
476
+ "review_conflicts": len(self.store.conflicts(status="review",
477
+ limit=1000)),
478
+ "recent_supersessions": self.store.supersessions(limit=10),
479
+ }