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,274 @@
1
+ """BriefingEngine — top-level coordinator for the Colony Briefing System."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from datetime import datetime, timezone
7
+ from typing import Any, List, Optional
8
+
9
+ from apsimo.briefings.composer import BriefingComposer
10
+ from apsimo.briefings.config import BriefingConfig
11
+ from apsimo.briefings.delivery import BriefingDeliveryEngine
12
+ from apsimo.briefings.engagement import SectionEngagementTracker
13
+ from apsimo.briefings.enhancer import BriefingLMEnhancer
14
+ from apsimo.briefings.models import (
15
+ Briefing,
16
+ BriefingCompletionSignal,
17
+ BriefingStatus,
18
+ BriefingType,
19
+ SectionEngagementRecord,
20
+ )
21
+ from apsimo.briefings.store import BriefingStore
22
+
23
+
24
+ class BriefingEngine:
25
+ """Top-level coordinator for generating, delivering, and tracking briefings."""
26
+
27
+ def __init__(
28
+ self,
29
+ config: Optional[BriefingConfig] = None,
30
+ store: Optional[BriefingStore] = None,
31
+ delivery: Optional[BriefingDeliveryEngine] = None,
32
+ enhancer: Optional[BriefingLMEnhancer] = None,
33
+ delivery_bridge: Optional[Any] = None, # ProactiveDeliveryBridge
34
+ relationship_aggregator: Optional[Any] = None,
35
+ calendar_aggregator: Optional[Any] = None,
36
+ goal_aggregator: Optional[Any] = None,
37
+ anomaly_aggregator: Optional[Any] = None,
38
+ mind_model_aggregator: Optional[Any] = None,
39
+ synthesis_aggregator: Optional[Any] = None,
40
+ ) -> None:
41
+ self._config = config or BriefingConfig()
42
+ self._store = store or BriefingStore(db_path=":memory:")
43
+ self._delivery = delivery or BriefingDeliveryEngine(gateways=[], default_gateway="api")
44
+ self._enhancer = enhancer or BriefingLMEnhancer(enabled=False)
45
+ self._delivery_bridge = delivery_bridge
46
+ # Aggregators default to stubs inside the composer; the real ones must
47
+ # be passed through or every briefing data section is permanently empty.
48
+ self._composer = BriefingComposer(
49
+ relationship_aggregator=relationship_aggregator,
50
+ calendar_aggregator=calendar_aggregator,
51
+ goal_aggregator=goal_aggregator,
52
+ anomaly_aggregator=anomaly_aggregator,
53
+ mind_model_aggregator=mind_model_aggregator,
54
+ synthesis_aggregator=synthesis_aggregator,
55
+ suppressed_sections=self._config.suppressed_sections,
56
+ )
57
+ self._engagement = SectionEngagementTracker(store=self._store)
58
+ self._scheduler = None
59
+
60
+ # Register the WhatsApp gateway if a delivery bridge is available.
61
+ if delivery_bridge is not None:
62
+ from apsimo.briefings.delivery import WhatsAppBriefingGateway
63
+ self._delivery.register(WhatsAppBriefingGateway(delivery_bridge=delivery_bridge))
64
+
65
+ # ------------------------------------------------------------------
66
+ # Generation & Delivery
67
+ # ------------------------------------------------------------------
68
+
69
+ def generate_and_deliver(self, briefing_type: BriefingType) -> Briefing:
70
+ """Generate a briefing of the given type, persist it, and deliver it.
71
+
72
+ Raises ValueError for BriefingType.TACTICAL (use fire_tactical() instead).
73
+ Engagement history is used to re-order sections by prior engagement score.
74
+ If LM enhancement is enabled, the briefing is polished before delivery.
75
+
76
+ Returns:
77
+ The saved Briefing object after delivery attempt. The returned
78
+ Briefing.status reflects the delivery outcome (DELIVERED or PENDING).
79
+ """
80
+ if briefing_type == BriefingType.TACTICAL:
81
+ raise ValueError("Use fire_tactical() for tactical briefings")
82
+
83
+ now = datetime.now(timezone.utc)
84
+ scores = self._engagement.get_section_scores()
85
+
86
+ if briefing_type == BriefingType.DAILY:
87
+ cfg = self._config.daily
88
+ briefing = self._composer.build_daily_briefing(
89
+ date=now.strftime("%Y-%m-%d"),
90
+ tz=cfg.timezone,
91
+ max_sections=cfg.max_sections,
92
+ section_order=cfg.section_order,
93
+ engagement_history=scores,
94
+ )
95
+ else: # WEEKLY
96
+ cfg = self._config.weekly
97
+ from datetime import timedelta
98
+ week_start = now - timedelta(days=now.weekday())
99
+ briefing = self._composer.build_weekly_briefing(
100
+ period_start=week_start,
101
+ period_end=now,
102
+ engagement_history=scores,
103
+ )
104
+
105
+ if self._config.lm_enhancement_enabled:
106
+ briefing = self._enhancer.enhance_briefing(briefing)
107
+
108
+ # Resolve home channel gateway before persisting (Fix 8 point 1).
109
+ if not briefing.gateway:
110
+ briefing.gateway = self._resolve_home_channel()
111
+
112
+ # draft → saved
113
+ self._store.save(briefing)
114
+ # draft → queued
115
+ self._store.mark_queued(briefing.briefing_id)
116
+ # queued → delivering
117
+ self._store.mark_delivering(briefing.briefing_id)
118
+ result = self._delivery.deliver(briefing)
119
+ if result.success:
120
+ # delivering → delivered
121
+ self._store.mark_delivered(briefing.briefing_id, result.gateway)
122
+ briefing = self._store.get(briefing.briefing_id)
123
+ return briefing
124
+
125
+ def fire_tactical(
126
+ self,
127
+ trigger: str,
128
+ severity: str,
129
+ summary: str,
130
+ details: str,
131
+ suggested_actions: Optional[List[str]] = None,
132
+ ) -> Optional[Briefing]:
133
+ """Fire a tactical (event-driven) briefing if the tactical channel is enabled.
134
+
135
+ Returns None when tactical briefings are disabled in config, so callers
136
+ must handle the None case. When enabled, saves and delivers immediately
137
+ without engagement scoring.
138
+
139
+ Returns:
140
+ The delivered Briefing, or None if tactical is disabled.
141
+ """
142
+ if not self._config.tactical.enabled:
143
+ return None
144
+
145
+ briefing = self._composer.build_tactical_briefing(
146
+ trigger=trigger,
147
+ severity=severity,
148
+ summary=summary,
149
+ details=details,
150
+ suggested_actions=suggested_actions,
151
+ )
152
+ if not briefing.gateway:
153
+ briefing.gateway = self._resolve_home_channel()
154
+ self._store.save(briefing)
155
+ self._store.mark_queued(briefing.briefing_id)
156
+ self._store.mark_delivering(briefing.briefing_id)
157
+ result = self._delivery.deliver(briefing)
158
+ if result.success:
159
+ self._store.mark_delivered(briefing.briefing_id, result.gateway)
160
+ briefing = self._store.get(briefing.briefing_id)
161
+ return briefing
162
+
163
+ # ------------------------------------------------------------------
164
+ # Pending delivery (Fix 8 point 3 — pick up stalled drafts)
165
+ # ------------------------------------------------------------------
166
+
167
+ def deliver_pending(self) -> int:
168
+ """Attempt delivery of any DRAFT or QUEUED briefings.
169
+
170
+ Transitions each briefing through the state machine:
171
+ draft/queued → delivering → delivered (or back to queued on failure).
172
+
173
+ Returns the number of briefings successfully delivered.
174
+ """
175
+ count = 0
176
+ for status in (BriefingStatus.DRAFT, BriefingStatus.QUEUED):
177
+ for briefing in self._store.list_by_status(status):
178
+ if not briefing.gateway:
179
+ briefing.gateway = self._resolve_home_channel()
180
+ # Persist the resolved gateway so the delivery engine uses it.
181
+ self._store.save(briefing)
182
+ self._store.mark_delivering(briefing.briefing_id)
183
+ result = self._delivery.deliver(briefing)
184
+ if result.success:
185
+ self._store.mark_delivered(briefing.briefing_id, result.gateway)
186
+ count += 1
187
+ import logging as _logging
188
+ _logging.getLogger(__name__).info(
189
+ "deliver_pending: delivered briefing %s via %s",
190
+ briefing.briefing_id,
191
+ result.gateway,
192
+ )
193
+ else:
194
+ # Revert to queued so the scheduler retries next cycle.
195
+ self._store.mark_queued(briefing.briefing_id)
196
+ import logging as _logging
197
+ _logging.getLogger(__name__).warning(
198
+ "deliver_pending: failed to deliver briefing %s: %s",
199
+ briefing.briefing_id,
200
+ result.error,
201
+ )
202
+ return count
203
+
204
+ def _resolve_home_channel(self) -> str:
205
+ """Return the home channel platform from delivery_bridge or env vars."""
206
+ if self._delivery_bridge is not None:
207
+ home = self._delivery_bridge.resolve_home_channel()
208
+ if home:
209
+ return home["platform"]
210
+ for platform in ("whatsapp", "telegram", "discord", "slack", "signal"):
211
+ if os.environ.get(f"{platform.upper()}_HOME_CHANNEL"):
212
+ return platform
213
+ return "api"
214
+
215
+ # ------------------------------------------------------------------
216
+ # Query
217
+ # ------------------------------------------------------------------
218
+
219
+ def get_pending(self) -> List[Briefing]:
220
+ return self._store.list_by_status(BriefingStatus.DRAFT)
221
+
222
+ def get_recent(self, limit: int = 10) -> List[Briefing]:
223
+ return self._store.list_recent(limit=limit)
224
+
225
+ # ------------------------------------------------------------------
226
+ # Engagement
227
+ # ------------------------------------------------------------------
228
+
229
+ def record_engagement(self, briefing_id: str, section_name: str, signal: str) -> None:
230
+ record = SectionEngagementRecord(
231
+ section_name=section_name,
232
+ briefing_id=briefing_id,
233
+ signal=signal,
234
+ recorded_at=datetime.now(timezone.utc),
235
+ )
236
+ self._engagement.record(record)
237
+ if signal == "read":
238
+ self._store.mark_read(briefing_id)
239
+
240
+ def get_suppression_candidates(self, **kwargs) -> List[str]:
241
+ return self._engagement.get_suppression_candidates(**kwargs)
242
+
243
+ def suppress_section(self, section: str, reason: str = "") -> None:
244
+ if section not in self._config.suppressed_sections:
245
+ self._config.suppressed_sections.append(section)
246
+
247
+ def emit_completion_signal(self, briefing: Briefing) -> BriefingCompletionSignal:
248
+ scores = self._engagement.get_section_scores()
249
+ active = briefing.active_sections()
250
+ engaged = [s.name for s in active if scores.get(s.name, 0.5) > 0.5]
251
+ return BriefingCompletionSignal(
252
+ briefing_id=briefing.briefing_id,
253
+ briefing_type=briefing.briefing_type,
254
+ sections=[s.name for s in active],
255
+ engaged_sections=engaged,
256
+ delivered_at=datetime.now(timezone.utc),
257
+ total_anomalies=0,
258
+ active_goals=0,
259
+ )
260
+
261
+ # ------------------------------------------------------------------
262
+ # Lifecycle
263
+ # ------------------------------------------------------------------
264
+
265
+ def attach_scheduler(self, scheduler) -> None:
266
+ self._scheduler = scheduler
267
+
268
+ def start(self) -> None:
269
+ if self._scheduler is not None:
270
+ self._scheduler.start()
271
+
272
+ def stop(self) -> None:
273
+ if self._scheduler is not None:
274
+ self._scheduler.stop()
@@ -0,0 +1,99 @@
1
+ """Colony Briefing System — LLM Enhancement Pass.
2
+
3
+ Generates natural-language narratives for briefing sections.
4
+ Falls back gracefully when no LLM client is provided or when
5
+ the LLM call fails.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import logging
12
+ from typing import Any, Dict, Optional, Protocol, runtime_checkable
13
+
14
+ from .models import Briefing, BriefingSection
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ from apsimo.cognition.charter import build_system_prompt as _charter_prompt
19
+
20
+ _SYSTEM_PROMPT = _charter_prompt("narrator")
21
+
22
+
23
+ @runtime_checkable
24
+ class LLMClientProtocol(Protocol):
25
+ """Minimal interface expected from an LLM client."""
26
+
27
+ def complete(self, system: str, prompt: str, max_tokens: int) -> str: ...
28
+
29
+
30
+ class BriefingLMEnhancer:
31
+ """Generate natural-language narratives for briefing sections."""
32
+
33
+ def __init__(
34
+ self,
35
+ llm_client: Optional[LLMClientProtocol] = None,
36
+ enabled: bool = True,
37
+ ) -> None:
38
+ self._client = llm_client
39
+ self._enabled = enabled
40
+ self._tokens_used = 0
41
+
42
+ @property
43
+ def tokens_used(self) -> int:
44
+ return self._tokens_used
45
+
46
+ def enhance_section(
47
+ self,
48
+ section_name: str,
49
+ structured_content: Dict[str, Any],
50
+ max_tokens: int = 150,
51
+ ) -> str:
52
+ """Generate a natural-language narrative for a single section.
53
+
54
+ Returns an empty string if LLM is disabled, unavailable, or if
55
+ the content has no notable information.
56
+ """
57
+ if not self._enabled or self._client is None:
58
+ return ""
59
+
60
+ if not structured_content:
61
+ return ""
62
+
63
+ prompt = (
64
+ f"Section: {section_name}\n"
65
+ f"Data: {json.dumps(structured_content, default=str)}\n\n"
66
+ "Write a 1–3 sentence briefing summary for this section. "
67
+ "Be concise and actionable. Do not repeat the raw data literally."
68
+ )
69
+ try:
70
+ narrative = self._client.complete(_SYSTEM_PROMPT, prompt, max_tokens)
71
+ self._tokens_used += max_tokens # conservative accounting
72
+ return narrative.strip()
73
+ except Exception as exc:
74
+ logger.warning("LLM enhancement failed for section '%s': %s", section_name, exc)
75
+ return ""
76
+
77
+ def enhance_briefing(
78
+ self,
79
+ briefing: Briefing,
80
+ max_tokens_per_section: int = 150,
81
+ ) -> Briefing:
82
+ """Run the LLM enhancement pass on all active sections.
83
+
84
+ Modifies section.narrative in-place. Returns the updated briefing.
85
+ Falls back to structured-only content on any LLM failure.
86
+ """
87
+ if not self._enabled or self._client is None:
88
+ return briefing
89
+
90
+ for section in briefing.active_sections():
91
+ if section.suppressed:
92
+ continue
93
+ section.narrative = self.enhance_section(
94
+ section.name,
95
+ section.content,
96
+ max_tokens=max_tokens_per_section,
97
+ )
98
+
99
+ return briefing
@@ -0,0 +1,183 @@
1
+ """Colony Briefing System — data models.
2
+
3
+ Defines the core Briefing, BriefingSection, and briefing content types
4
+ used throughout the briefing pipeline.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import uuid
10
+ from dataclasses import dataclass, field
11
+ from datetime import datetime, timezone
12
+ from enum import Enum
13
+ from typing import Any, Dict, List, Optional
14
+
15
+
16
+ class BriefingType(str, Enum):
17
+ DAILY = "daily"
18
+ TACTICAL = "tactical"
19
+ WEEKLY = "weekly"
20
+
21
+
22
+ class BriefingStatus(str, Enum):
23
+ DRAFT = "draft"
24
+ QUEUED = "queued"
25
+ DELIVERING = "delivering"
26
+ DELIVERED = "delivered"
27
+ READ = "read"
28
+ ARCHIVED = "archived"
29
+
30
+
31
+ class BriefingPriority(str, Enum):
32
+ LOW = "low"
33
+ NORMAL = "normal"
34
+ HIGH = "high"
35
+ URGENT = "urgent"
36
+
37
+
38
+ @dataclass
39
+ class BriefingSection:
40
+ """A single named content block within a briefing."""
41
+
42
+ section_id: str = field(default_factory=lambda: str(uuid.uuid4()))
43
+ name: str = ""
44
+ content: Dict[str, Any] = field(default_factory=dict)
45
+ narrative: str = ""
46
+ priority: int = 50
47
+ suppressed: bool = False
48
+ engagement: Optional[str] = None # "read" | "dismissed" | "acted"
49
+
50
+
51
+ @dataclass
52
+ class Briefing:
53
+ """A delivered summary document."""
54
+
55
+ briefing_id: str = field(default_factory=lambda: str(uuid.uuid4()))
56
+ briefing_type: BriefingType = BriefingType.DAILY
57
+ status: BriefingStatus = BriefingStatus.DRAFT
58
+ sections: List[BriefingSection] = field(default_factory=list)
59
+ priority: BriefingPriority = BriefingPriority.NORMAL
60
+ triggered_by: Optional[str] = None
61
+ gateway: Optional[str] = None
62
+ created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
63
+ delivered_at: Optional[datetime] = None
64
+ read_at: Optional[datetime] = None
65
+
66
+ def is_delivered(self) -> bool:
67
+ return self.status in {BriefingStatus.DELIVERED, BriefingStatus.READ}
68
+
69
+ def active_sections(self) -> List[BriefingSection]:
70
+ return [s for s in self.sections if not s.suppressed]
71
+
72
+
73
+ # ---------------------------------------------------------------------------
74
+ # Content types
75
+ # ---------------------------------------------------------------------------
76
+
77
+
78
+ @dataclass
79
+ class CalendarEvent:
80
+ time: str # HH:MM local time
81
+ title: str
82
+ participants: List[str]
83
+ prep_needed: bool = False
84
+ location: Optional[str] = None
85
+ duration_minutes: int = 30
86
+
87
+
88
+ @dataclass
89
+ class DailyBriefingContent:
90
+ date: str # ISO-8601 date
91
+ calendar: List[CalendarEvent]
92
+ tasks: Dict[str, Any] # overdue, due_today, blocked, highlights
93
+ relationships: Dict[str, Any] # changes list
94
+ health: Optional[Dict[str, Any]] = None
95
+ anomalies: Optional[Dict[str, Any]] = None
96
+ initiatives: Optional[Dict[str, Any]] = None
97
+
98
+
99
+ @dataclass
100
+ class TacticalBriefingContent:
101
+ trigger: str
102
+ severity: str # "critical" | "warning" | "info"
103
+ summary: str
104
+ details: str
105
+ suggested_actions: List[str] = field(default_factory=list)
106
+ related_entities: List[str] = field(default_factory=list)
107
+ requires_response: bool = False
108
+
109
+
110
+ @dataclass
111
+ class WeeklyBriefingContent:
112
+ period_start: str # ISO-8601 date
113
+ period_end: str # ISO-8601 date
114
+ task_completion_rate: float # 0.0–1.0
115
+ relationship_health: Dict[str, Any] # improved, declined, neglected
116
+ top_achievements: List[str]
117
+ areas_of_focus: List[str]
118
+ emerging_patterns: List[str]
119
+ upcoming_week: Dict[str, Any]
120
+ system_health: Dict[str, Any] # uptime, errors, backup_status
121
+
122
+
123
+ # ---------------------------------------------------------------------------
124
+ # Intelligence integration models
125
+ # ---------------------------------------------------------------------------
126
+
127
+
128
+ @dataclass
129
+ class BriefingCompletionSignal:
130
+ """Signal emitted to the synthesis engine after briefing delivery."""
131
+
132
+ briefing_id: str
133
+ briefing_type: BriefingType
134
+ sections: List[str]
135
+ engaged_sections: List[str]
136
+ delivered_at: datetime
137
+ total_anomalies: int
138
+ active_goals: int
139
+
140
+
141
+ @dataclass
142
+ class BriefingTelemetryEvent:
143
+ """Telemetry for MetaLearner briefing performance tracking."""
144
+
145
+ briefing_id: str
146
+ briefing_type: BriefingType
147
+ time_to_generate_ms: float
148
+ time_to_deliver_ms: float
149
+ lm_tokens_used: int
150
+ section_count: int
151
+ engagement_score: float
152
+ gateway: str
153
+ delivered_at: datetime
154
+
155
+
156
+ # ---------------------------------------------------------------------------
157
+ # Engagement
158
+ # ---------------------------------------------------------------------------
159
+
160
+
161
+ @dataclass
162
+ class SectionEngagementRecord:
163
+ """Record of user engagement with a briefing section."""
164
+
165
+ section_name: str
166
+ briefing_id: str
167
+ signal: str # "read" | "dismissed" | "acted" | "shared"
168
+ recorded_at: datetime
169
+ context: Optional[str] = None
170
+
171
+
172
+ # ---------------------------------------------------------------------------
173
+ # Schedule
174
+ # ---------------------------------------------------------------------------
175
+
176
+
177
+ @dataclass
178
+ class ScheduleEntry:
179
+ """Persisted schedule state for daily/weekly briefings."""
180
+
181
+ type: str # "daily" | "weekly"
182
+ last_run: Optional[datetime] = None
183
+ next_run: Optional[datetime] = None