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,424 @@
1
+ """AutonomyLoop configuration dataclass."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import os
7
+ from dataclasses import dataclass
8
+ from typing import Optional
9
+ from enum import Enum
10
+ from zoneinfo import ZoneInfo
11
+
12
+
13
+ class AutonomyMode(str, Enum):
14
+ """Autonomy loop operating mode."""
15
+ REACTIVE = "reactive" # On-demand only (default)
16
+ PROACTIVE = "proactive" # Timer-based
17
+
18
+
19
+ def _enabled_phases(value) -> Optional[tuple[str, ...]]:
20
+ if value is None:
21
+ return None
22
+ parts = value.split(',') if isinstance(value, str) else value
23
+ if not isinstance(parts, (list, tuple)) or not parts:
24
+ raise ValueError('enabled_phases must name at least one existing phase')
25
+ if any(not isinstance(part, str) or not part.strip() for part in parts):
26
+ raise ValueError('enabled_phases contains an empty or invalid name')
27
+ return tuple(dict.fromkeys(part.strip() for part in parts))
28
+
29
+
30
+ @dataclass
31
+ class InitiativeConfig:
32
+ """Configuration for initiative deduplication and feedback (v0.7.10)."""
33
+ cooldown_hours: float = 24.0
34
+ cooldown_tasks: float = 12.0
35
+ cooldown_contacts: float = 72.0
36
+ max_snooze_hours: int = 168
37
+ feedback_enabled: bool = True
38
+
39
+
40
+ @dataclass
41
+ class AutonomyConfig:
42
+ """Configuration for the Colony autonomy loop.
43
+
44
+ All time values are in seconds unless noted.
45
+ """
46
+
47
+ # Operating mode: reactive (on-demand) or proactive (timer-based)
48
+ mode: AutonomyMode = AutonomyMode.REACTIVE
49
+
50
+ # Where the mode came from: "env" (explicit COLONY_AUTONOMY_MODE),
51
+ # "preset" (COLONY_AUTONOMY_PRESET via preset-loop coupling, H4.1),
52
+ # "legacy_tick" (tick interval set without a mode), "config" (config
53
+ # file), or "default". Diagnostic only — surfaced in the posture
54
+ # endpoint so an operator can always see WHY the loop runs as it does.
55
+ mode_source: str = "default"
56
+
57
+ # None retains the existing phase set. A deployment can activate only the
58
+ # reviewed phases of this same loop without waking unrelated maintenance.
59
+ enabled_phases: Optional[tuple[str, ...]] = None
60
+ # Only affects the execute phase: persist proposals without legacy skill
61
+ # execution, queue dispatch, broadcasts or delivery. Other services retain
62
+ # their independent configuration and authority.
63
+ proposals_only: bool = False
64
+
65
+ # IANA timezone for quiet hours (e.g., "America/El_Salvador")
66
+ timezone: str = "UTC"
67
+
68
+ # How long to sleep between ticks when no events wake the loop early.
69
+ tick_interval_secs: float = 300.0
70
+
71
+ # Minimum initiative priority score [0.0–1.0] to execute an action.
72
+ initiative_confidence_threshold: float = 0.7
73
+
74
+ # Maximum autonomous actions taken per hour (safety limit).
75
+ max_actions_per_hour: int = 20
76
+
77
+ # Suppress non-urgent surfacing during quiet hours ("HH:MM" 24-hour format).
78
+ # Set both to "00:00" to disable quiet hours.
79
+ quiet_hours_start: str = "22:00"
80
+ quiet_hours_end: str = "07:00"
81
+
82
+ # Minimum anomaly severity [0.0–1.0] to surface to the initiative engine.
83
+ anomaly_severity_threshold: float = 0.6
84
+
85
+ # Minimum prediction confidence [0.0–1.0] to surface predictions.
86
+ prediction_confidence_threshold: float = 0.75
87
+
88
+ # Hours after which an active goal is considered stale.
89
+ goal_stale_threshold_hours: float = 24.0
90
+
91
+ # How often to run the identity bootstrap self-check (hours).
92
+ bootstrap_check_interval_hours: int = 24
93
+
94
+ # How often to run the self-reflection component (days).
95
+ self_reflection_interval_days: int = 7
96
+
97
+ # ── Owner check-in (silence-triggered proactive outreach) ──────────
98
+ # When no initiatives fire for this many hours, reach out to the owner.
99
+ owner_check_in_enabled: bool = False
100
+ owner_check_in_silent_hours: float = 1.0
101
+ owner_check_in_cooldown_hours: float = 4.0
102
+ owner_contact_id: Optional[str] = None # None = resolve from identity
103
+
104
+ # ── Proactive delivery (push initiatives to webhook) ────────────────
105
+ # When False, initiatives are stored but never pushed to the delivery bridge.
106
+ # The agent must poll via context-digest to see pending work.
107
+ proactive_delivery_enabled: bool = False
108
+
109
+ # ── Delivery shadow mode (outward-facing rollout safety) ────────────
110
+ # When True, reach-out initiatives that would be delivered are LOGGED
111
+ # (target + payload) but never sent, regardless of proactive_delivery_enabled.
112
+ # Lets an operator eyeball the intended first batch before enabling real
113
+ # sends. Real delivery requires proactive_delivery_enabled AND shadow off.
114
+ delivery_shadow_mode: bool = False
115
+
116
+ # ── Conversation synthesis (periodic memory scan for goals) ─────────
117
+ # Scans stored conversation memories for implicit goals and commitments.
118
+ conversation_synthesis_enabled: bool = True
119
+ conversation_synthesis_interval_secs: float = 1800.0 # 30 min
120
+ conversation_synthesis_lookback_hours: float = 2.0
121
+ conversation_synthesis_min_confidence: float = 0.35
122
+
123
+ # ── class methods ──────────────────────────────────────────────────
124
+
125
+ @classmethod
126
+ def from_colony_config(cls, colony_cfg: object) -> "AutonomyConfig":
127
+ """Construct config from a Colony config object or dict.
128
+
129
+ Looks for an ``autonomy`` sub-key/attribute. If not found, returns
130
+ defaults. Supports both dict-like (``colony_cfg["autonomy"]``) and
131
+ object-like (``colony_cfg.autonomy``) configs.
132
+
133
+ Args:
134
+ colony_cfg: Colony config object/dict, or None for defaults.
135
+ """
136
+ if colony_cfg is None:
137
+ return cls()
138
+
139
+ # Extract the autonomy sub-section
140
+ autonomy_section = None
141
+ if isinstance(colony_cfg, dict):
142
+ autonomy_section = colony_cfg.get("autonomy")
143
+ else:
144
+ autonomy_section = getattr(colony_cfg, "autonomy", None)
145
+
146
+ if autonomy_section is None:
147
+ return cls()
148
+
149
+ # Read values from the section
150
+ def _get(key: str, default):
151
+ if isinstance(autonomy_section, dict):
152
+ return autonomy_section.get(key, default)
153
+ return getattr(autonomy_section, key, default)
154
+
155
+ defaults = cls()
156
+
157
+ # Mode and timezone
158
+ mode_str = str(_get("mode", "reactive")).lower()
159
+ mode = AutonomyMode(mode_str) if mode_str in [m.value for m in AutonomyMode] else AutonomyMode.REACTIVE
160
+ timezone = str(_get("timezone", "UTC"))
161
+
162
+ # Validate timezone
163
+ try:
164
+ ZoneInfo(timezone)
165
+ except Exception:
166
+ timezone = "UTC"
167
+
168
+ return cls(
169
+ mode=mode,
170
+ mode_source="config",
171
+ enabled_phases=_enabled_phases(_get("enabled_phases", None)),
172
+ proposals_only=bool(_get("proposals_only", False)),
173
+ timezone=timezone,
174
+ tick_interval_secs=float(_get("tick_interval_secs", defaults.tick_interval_secs)),
175
+ initiative_confidence_threshold=float(_get(
176
+ "initiative_confidence_threshold",
177
+ defaults.initiative_confidence_threshold,
178
+ )),
179
+ max_actions_per_hour=int(_get("max_actions_per_hour", defaults.max_actions_per_hour)),
180
+ quiet_hours_start=str(_get("quiet_hours_start", defaults.quiet_hours_start)),
181
+ quiet_hours_end=str(_get("quiet_hours_end", defaults.quiet_hours_end)),
182
+ anomaly_severity_threshold=float(_get(
183
+ "anomaly_severity_threshold",
184
+ defaults.anomaly_severity_threshold,
185
+ )),
186
+ prediction_confidence_threshold=float(_get(
187
+ "prediction_confidence_threshold",
188
+ defaults.prediction_confidence_threshold,
189
+ )),
190
+ goal_stale_threshold_hours=float(_get(
191
+ "goal_stale_threshold_hours",
192
+ defaults.goal_stale_threshold_hours,
193
+ )),
194
+ bootstrap_check_interval_hours=int(_get(
195
+ "bootstrap_check_interval_hours",
196
+ defaults.bootstrap_check_interval_hours,
197
+ )),
198
+ self_reflection_interval_days=int(_get(
199
+ "self_reflection_interval_days",
200
+ defaults.self_reflection_interval_days,
201
+ )),
202
+ owner_check_in_enabled=bool(_get("owner_check_in_enabled", defaults.owner_check_in_enabled)),
203
+ owner_check_in_silent_hours=float(_get(
204
+ "owner_check_in_silent_hours",
205
+ defaults.owner_check_in_silent_hours,
206
+ )),
207
+ owner_check_in_cooldown_hours=float(_get(
208
+ "owner_check_in_cooldown_hours",
209
+ defaults.owner_check_in_cooldown_hours,
210
+ )),
211
+ owner_contact_id=_get("owner_contact_id", defaults.owner_contact_id),
212
+ proactive_delivery_enabled=bool(
213
+ _get("proactive_delivery_enabled", defaults.proactive_delivery_enabled)
214
+ ),
215
+ delivery_shadow_mode=bool(
216
+ _get("delivery_shadow_mode", defaults.delivery_shadow_mode)
217
+ ),
218
+ conversation_synthesis_enabled=bool(_get(
219
+ "conversation_synthesis_enabled",
220
+ defaults.conversation_synthesis_enabled,
221
+ )),
222
+ conversation_synthesis_interval_secs=float(_get(
223
+ "conversation_synthesis_interval_secs",
224
+ defaults.conversation_synthesis_interval_secs,
225
+ )),
226
+ conversation_synthesis_lookback_hours=float(_get(
227
+ "conversation_synthesis_lookback_hours",
228
+ defaults.conversation_synthesis_lookback_hours,
229
+ )),
230
+ conversation_synthesis_min_confidence=float(_get(
231
+ "conversation_synthesis_min_confidence",
232
+ defaults.conversation_synthesis_min_confidence,
233
+ )),
234
+ )
235
+
236
+ @classmethod
237
+ def from_env(cls) -> "AutonomyConfig":
238
+ """Construct config from environment variables.
239
+
240
+ All env vars are optional; unset vars fall back to field defaults.
241
+
242
+ Environment variables:
243
+ COLONY_AUTONOMY_MODE
244
+ COLONY_AUTONOMY_PHASES (comma-separated existing phase names)
245
+ COLONY_AUTONOMY_PROPOSALS_ONLY
246
+ COLONY_PRESET_LOOP_COUPLING (default on: an active
247
+ COLONY_AUTONOMY_PRESET supplies the mode when
248
+ COLONY_AUTONOMY_MODE is unset)
249
+ COLONY_TIMEZONE
250
+ COLONY_AUTONOMY_TICK_INTERVAL_SECS
251
+ COLONY_AUTONOMY_INITIATIVE_CONFIDENCE_THRESHOLD
252
+ COLONY_AUTONOMY_MAX_ACTIONS_PER_HOUR
253
+ COLONY_AUTONOMY_QUIET_HOURS_START
254
+ COLONY_AUTONOMY_QUIET_HOURS_END
255
+ COLONY_AUTONOMY_ANOMALY_SEVERITY_THRESHOLD
256
+ COLONY_AUTONOMY_PREDICTION_CONFIDENCE_THRESHOLD
257
+ COLONY_AUTONOMY_GOAL_STALE_THRESHOLD_HOURS
258
+ COLONY_OWNER_CHECK_IN_ENABLED
259
+ COLONY_OWNER_CHECK_IN_SILENT_HOURS
260
+ COLONY_OWNER_CHECK_IN_COOLDOWN_HOURS
261
+ COLONY_OWNER_CONTACT_ID
262
+ COLONY_PROACTIVE_DELIVERY_ENABLED
263
+ COLONY_DELIVERY_SHADOW
264
+ COLONY_CONVERSATION_SYNTHESIS_ENABLED
265
+ COLONY_CONVERSATION_SYNTHESIS_INTERVAL_SECS
266
+ COLONY_CONVERSATION_SYNTHESIS_LOOKBACK_HOURS
267
+ COLONY_CONVERSATION_SYNTHESIS_MIN_CONFIDENCE
268
+ """
269
+ logger = logging.getLogger(__name__)
270
+
271
+ # Mode selection. Precedence (H4.1):
272
+ # explicit COLONY_AUTONOMY_MODE > coupled preset mode
273
+ # > legacy tick-interval migration > default (reactive)
274
+ # Explicit env ALWAYS wins — COLONY_AUTONOMY_MODE=reactive is the
275
+ # rollback path even under a preset. Coupling errors fail toward
276
+ # reactive (coupled_loop_mode never raises; a broken import just
277
+ # falls through to the legacy resolution).
278
+ mode = AutonomyMode.REACTIVE
279
+ mode_source = "default"
280
+ raw_mode = os.environ.get("COLONY_AUTONOMY_MODE")
281
+ if raw_mode is not None and raw_mode.strip():
282
+ mode_str = raw_mode.strip().lower()
283
+ mode = (AutonomyMode(mode_str)
284
+ if mode_str in [m.value for m in AutonomyMode]
285
+ else AutonomyMode.REACTIVE)
286
+ mode_source = "env"
287
+ else:
288
+ coupled = None
289
+ try:
290
+ from apsimo.util.autonomy_preset import coupled_loop_mode
291
+ coupled = coupled_loop_mode()
292
+ except Exception:
293
+ coupled = None # fail toward reactive
294
+ if coupled in ("reactive", "proactive"):
295
+ mode = AutonomyMode(coupled)
296
+ mode_source = "preset"
297
+
298
+ # Timezone
299
+ timezone = os.environ.get("COLONY_TIMEZONE", "UTC")
300
+ try:
301
+ ZoneInfo(timezone)
302
+ except Exception:
303
+ logger.warning("Invalid COLONY_TIMEZONE '%s', falling back to UTC", timezone)
304
+ timezone = "UTC"
305
+
306
+ # Legacy migration: if tick interval set without mode (and no coupled
307
+ # preset supplied one), assume proactive
308
+ legacy_tick = os.environ.get("COLONY_AUTONOMY_TICK_INTERVAL_SECS")
309
+ if legacy_tick and mode_source == "default":
310
+ logger.warning(
311
+ "COLONY_AUTONOMY_TICK_INTERVAL_SECS set without COLONY_AUTONOMY_MODE. "
312
+ "Defaulting to PROACTIVE mode to preserve existing behavior. "
313
+ "Add COLONY_AUTONOMY_MODE=proactive to make this explicit."
314
+ )
315
+ mode = AutonomyMode.PROACTIVE
316
+ mode_source = "legacy_tick"
317
+
318
+ def _float(key: str, default: float) -> float:
319
+ v = os.environ.get(key)
320
+ return float(v) if v is not None else default
321
+
322
+ def _int(key: str, default: int) -> int:
323
+ v = os.environ.get(key)
324
+ return int(v) if v is not None else default
325
+
326
+ def _str(key: str, default: str) -> str:
327
+ return os.environ.get(key, default)
328
+
329
+ def _bool(key: str, default: bool) -> bool:
330
+ v = os.environ.get(key, "").lower()
331
+ if v == "true":
332
+ return True
333
+ if v == "false":
334
+ return False
335
+ return default
336
+
337
+ defaults = cls()
338
+ return cls(
339
+ mode=mode,
340
+ mode_source=mode_source,
341
+ enabled_phases=_enabled_phases(os.environ.get("COLONY_AUTONOMY_PHASES")),
342
+ proposals_only=_bool("COLONY_AUTONOMY_PROPOSALS_ONLY", False),
343
+ timezone=timezone,
344
+ tick_interval_secs=_float(
345
+ "COLONY_AUTONOMY_TICK_INTERVAL_SECS",
346
+ defaults.tick_interval_secs,
347
+ ),
348
+ initiative_confidence_threshold=_float(
349
+ "COLONY_AUTONOMY_INITIATIVE_CONFIDENCE_THRESHOLD",
350
+ defaults.initiative_confidence_threshold,
351
+ ),
352
+ max_actions_per_hour=_int(
353
+ "COLONY_AUTONOMY_MAX_ACTIONS_PER_HOUR",
354
+ defaults.max_actions_per_hour,
355
+ ),
356
+ quiet_hours_start=_str(
357
+ "COLONY_AUTONOMY_QUIET_HOURS_START",
358
+ defaults.quiet_hours_start,
359
+ ),
360
+ quiet_hours_end=_str(
361
+ "COLONY_AUTONOMY_QUIET_HOURS_END",
362
+ defaults.quiet_hours_end,
363
+ ),
364
+ anomaly_severity_threshold=_float(
365
+ "COLONY_AUTONOMY_ANOMALY_SEVERITY_THRESHOLD",
366
+ defaults.anomaly_severity_threshold,
367
+ ),
368
+ prediction_confidence_threshold=_float(
369
+ "COLONY_AUTONOMY_PREDICTION_CONFIDENCE_THRESHOLD",
370
+ defaults.prediction_confidence_threshold,
371
+ ),
372
+ goal_stale_threshold_hours=_float(
373
+ "COLONY_AUTONOMY_GOAL_STALE_THRESHOLD_HOURS",
374
+ defaults.goal_stale_threshold_hours,
375
+ ),
376
+ bootstrap_check_interval_hours=_int(
377
+ "COLONY_AUTONOMY_BOOTSTRAP_CHECK_INTERVAL_HOURS",
378
+ defaults.bootstrap_check_interval_hours,
379
+ ),
380
+ self_reflection_interval_days=_int(
381
+ "COLONY_AUTONOMY_SELF_REFLECTION_INTERVAL_DAYS",
382
+ defaults.self_reflection_interval_days,
383
+ ),
384
+ owner_check_in_enabled=_bool(
385
+ "COLONY_OWNER_CHECK_IN_ENABLED",
386
+ defaults.owner_check_in_enabled,
387
+ ),
388
+ owner_check_in_silent_hours=_float(
389
+ "COLONY_OWNER_CHECK_IN_SILENT_HOURS",
390
+ defaults.owner_check_in_silent_hours,
391
+ ),
392
+ owner_check_in_cooldown_hours=_float(
393
+ "COLONY_OWNER_CHECK_IN_COOLDOWN_HOURS",
394
+ defaults.owner_check_in_cooldown_hours,
395
+ ),
396
+ owner_contact_id=os.environ.get(
397
+ "COLONY_OWNER_CONTACT_ID",
398
+ defaults.owner_contact_id,
399
+ ),
400
+ proactive_delivery_enabled=_bool(
401
+ "COLONY_PROACTIVE_DELIVERY_ENABLED",
402
+ defaults.proactive_delivery_enabled,
403
+ ),
404
+ delivery_shadow_mode=_bool(
405
+ "COLONY_DELIVERY_SHADOW",
406
+ defaults.delivery_shadow_mode,
407
+ ),
408
+ conversation_synthesis_enabled=_bool(
409
+ "COLONY_CONVERSATION_SYNTHESIS_ENABLED",
410
+ defaults.conversation_synthesis_enabled,
411
+ ),
412
+ conversation_synthesis_interval_secs=_float(
413
+ "COLONY_CONVERSATION_SYNTHESIS_INTERVAL_SECS",
414
+ defaults.conversation_synthesis_interval_secs,
415
+ ),
416
+ conversation_synthesis_lookback_hours=_float(
417
+ "COLONY_CONVERSATION_SYNTHESIS_LOOKBACK_HOURS",
418
+ defaults.conversation_synthesis_lookback_hours,
419
+ ),
420
+ conversation_synthesis_min_confidence=_float(
421
+ "COLONY_CONVERSATION_SYNTHESIS_MIN_CONFIDENCE",
422
+ defaults.conversation_synthesis_min_confidence,
423
+ ),
424
+ )