contextsynapse 1.0.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 (776) hide show
  1. contextsynapse/__init__.py +107 -0
  2. contextsynapse/__main__.py +9 -0
  3. contextsynapse/a2a/__init__.py +28 -0
  4. contextsynapse/a2a/client.py +120 -0
  5. contextsynapse/a2a/discovery.py +128 -0
  6. contextsynapse/a2a/handlers.py +164 -0
  7. contextsynapse/a2a/models.py +246 -0
  8. contextsynapse/a2a/streaming.py +92 -0
  9. contextsynapse/a2a/task_manager.py +275 -0
  10. contextsynapse/adapters/__init__.py +98 -0
  11. contextsynapse/adapters/_base.py +298 -0
  12. contextsynapse/adapters/autogen/__init__.py +4 -0
  13. contextsynapse/adapters/autogen/tools.py +34 -0
  14. contextsynapse/adapters/crewai/__init__.py +4 -0
  15. contextsynapse/adapters/crewai/tools.py +63 -0
  16. contextsynapse/adapters/langchain/__init__.py +19 -0
  17. contextsynapse/adapters/langchain/message_history.py +17 -0
  18. contextsynapse/adapters/langchain/retriever.py +158 -0
  19. contextsynapse/adapters/langchain/tools.py +43 -0
  20. contextsynapse/adapters/langgraph/__init__.py +21 -0
  21. contextsynapse/adapters/langgraph/checkpoint.py +223 -0
  22. contextsynapse/adapters/langgraph/context_tools.py +341 -0
  23. contextsynapse/adapters/langgraph/message_history.py +138 -0
  24. contextsynapse/adapters/langgraph/tools.py +43 -0
  25. contextsynapse/adapters/llamaindex/__init__.py +4 -0
  26. contextsynapse/adapters/llamaindex/tools.py +64 -0
  27. contextsynapse/adapters/openai/__init__.py +24 -0
  28. contextsynapse/adapters/openai/tools.py +206 -0
  29. contextsynapse/adapters/pydantic_ai/__init__.py +4 -0
  30. contextsynapse/adapters/pydantic_ai/tools.py +36 -0
  31. contextsynapse/adapters/swarm/__init__.py +4 -0
  32. contextsynapse/adapters/swarm/tools.py +44 -0
  33. contextsynapse/agents/__init__.py +6 -0
  34. contextsynapse/agents/auto_capture.py +80 -0
  35. contextsynapse/agents/dispatcher.py +299 -0
  36. contextsynapse/agents/notifications.py +112 -0
  37. contextsynapse/aiql/__init__.py +71 -0
  38. contextsynapse/aiql/cache.py +341 -0
  39. contextsynapse/aiql/compiler/__init__.py +62 -0
  40. contextsynapse/aiql/compiler/optimizer.py +126 -0
  41. contextsynapse/aiql/compiler/planner.py +366 -0
  42. contextsynapse/aiql/compiler/statistics.py +235 -0
  43. contextsynapse/aiql/compiler/validator.py +425 -0
  44. contextsynapse/aiql/engine/__init__.py +11 -0
  45. contextsynapse/aiql/engine/chunk_storage.py +2584 -0
  46. contextsynapse/aiql/engine/executor.py +7737 -0
  47. contextsynapse/aiql/engine/extraction_integration.py +442 -0
  48. contextsynapse/aiql/engine/graph_builder.py +405 -0
  49. contextsynapse/aiql/engine/node_creation_from_normalized.py +691 -0
  50. contextsynapse/aiql/engine/performance_monitor.py +289 -0
  51. contextsynapse/aiql/engine/postprocessing.py +365 -0
  52. contextsynapse/aiql/engine/ray_stage_executors.py +918 -0
  53. contextsynapse/aiql/engine/redis_cache.py +106 -0
  54. contextsynapse/aiql/engine/streaming_json.py +366 -0
  55. contextsynapse/aiql/engine/streaming_parquet.py +568 -0
  56. contextsynapse/aiql/engine/streaming_ray_chunking.py +419 -0
  57. contextsynapse/aiql/grammar/__init__.py +14 -0
  58. contextsynapse/aiql/grammar/aiql_grammar.py +1822 -0
  59. contextsynapse/aiql/grammar/base.py +71 -0
  60. contextsynapse/aiql/parser/__init__.py +46 -0
  61. contextsynapse/aiql/parser/aiql_parser.py +11330 -0
  62. contextsynapse/aiql/parser/base_parser.py +47 -0
  63. contextsynapse/api/__init__.py +5 -0
  64. contextsynapse/api/a2a_router.py +233 -0
  65. contextsynapse/api/admin_router.py +140 -0
  66. contextsynapse/api/agent_worker_router.py +978 -0
  67. contextsynapse/api/algorithms_router.py +317 -0
  68. contextsynapse/api/api.py +4144 -0
  69. contextsynapse/api/audit.py +204 -0
  70. contextsynapse/api/auth.py +441 -0
  71. contextsynapse/api/auth_router.py +537 -0
  72. contextsynapse/api/billing.py +261 -0
  73. contextsynapse/api/billing_router.py +275 -0
  74. contextsynapse/api/boundary_router.py +452 -0
  75. contextsynapse/api/cognition_router.py +116 -0
  76. contextsynapse/api/connector_router.py +237 -0
  77. contextsynapse/api/context_router.py +1619 -0
  78. contextsynapse/api/dashboard_router.py +11367 -0
  79. contextsynapse/api/errors.py +183 -0
  80. contextsynapse/api/events.py +88 -0
  81. contextsynapse/api/experiment_bootstrap.py +321 -0
  82. contextsynapse/api/experiment_orchestrator.py +1078 -0
  83. contextsynapse/api/experiment_router.py +2089 -0
  84. contextsynapse/api/feature_gate.py +89 -0
  85. contextsynapse/api/federation_router.py +108 -0
  86. contextsynapse/api/integrations.py +567 -0
  87. contextsynapse/api/integrations_router.py +461 -0
  88. contextsynapse/api/intelligence_router.py +1028 -0
  89. contextsynapse/api/metering.py +155 -0
  90. contextsynapse/api/metrics.py +112 -0
  91. contextsynapse/api/models.py +38 -0
  92. contextsynapse/api/monitoring_router.py +174 -0
  93. contextsynapse/api/pipeline_router.py +1437 -0
  94. contextsynapse/api/playground_conn.py +116 -0
  95. contextsynapse/api/projects_router.py +131 -0
  96. contextsynapse/api/queries_router.py +282 -0
  97. contextsynapse/api/quota.py +95 -0
  98. contextsynapse/api/rate_limit.py +64 -0
  99. contextsynapse/api/search_router.py +261 -0
  100. contextsynapse/api/shield_router.py +447 -0
  101. contextsynapse/api/tenant_guard.py +103 -0
  102. contextsynapse/api/tenant_quotas.py +231 -0
  103. contextsynapse/api/tenants.py +305 -0
  104. contextsynapse/api/users.py +646 -0
  105. contextsynapse/api/v1.py +167 -0
  106. contextsynapse/api/vertical_builder_router.py +387 -0
  107. contextsynapse/benchmark/__init__.py +15 -0
  108. contextsynapse/benchmark/__main__.py +64 -0
  109. contextsynapse/benchmark/agents.py +338 -0
  110. contextsynapse/benchmark/live_ab.py +338 -0
  111. contextsynapse/benchmark/reporter.py +149 -0
  112. contextsynapse/benchmark/runner.py +264 -0
  113. contextsynapse/benchmark/savings.py +266 -0
  114. contextsynapse/benchmark/token_counter.py +212 -0
  115. contextsynapse/benchmark/workloads.py +289 -0
  116. contextsynapse/buffer/__init__.py +154 -0
  117. contextsynapse/buffer/base.py +257 -0
  118. contextsynapse/buffer/duckdb_buffer.py +246 -0
  119. contextsynapse/buffer/file_buffer.py +229 -0
  120. contextsynapse/buffer/lmdb_buffer.py +286 -0
  121. contextsynapse/buffer/local_buffer.py +154 -0
  122. contextsynapse/buffer/redis_buffer.py +211 -0
  123. contextsynapse/buffer/sqlite_buffer.py +266 -0
  124. contextsynapse/cache.py +2 -0
  125. contextsynapse/cli/__init__.py +40 -0
  126. contextsynapse/cli/cli.py +475 -0
  127. contextsynapse/cli/config_cli.py +177 -0
  128. contextsynapse/cli/scaffold.py +465 -0
  129. contextsynapse/cognition/__init__.py +31 -0
  130. contextsynapse/cognition/derivation.py +55 -0
  131. contextsynapse/cognition/events.py +135 -0
  132. contextsynapse/cognition/feedback.py +52 -0
  133. contextsynapse/cognition/hallucination.py +90 -0
  134. contextsynapse/cognition/invalidation.py +70 -0
  135. contextsynapse/cognition/read_tracker.py +50 -0
  136. contextsynapse/collaboration.py +2 -0
  137. contextsynapse/comparison.py +2 -0
  138. contextsynapse/config/__init__.py +10 -0
  139. contextsynapse/config/connectors/amfi_nav.yaml +18 -0
  140. contextsynapse/config/connectors/auto_sector.yaml +20 -0
  141. contextsynapse/config/connectors/banking_sector.yaml +20 -0
  142. contextsynapse/config/connectors/energy_sector.yaml +20 -0
  143. contextsynapse/config/connectors/fmcg_sector.yaml +20 -0
  144. contextsynapse/config/connectors/nsdl_fpi.yaml +9 -0
  145. contextsynapse/config/connectors/nse_price.yaml +61 -0
  146. contextsynapse/config/connectors/pharma_sector.yaml +20 -0
  147. contextsynapse/config/connectors/rbi_dbie.yaml +12 -0
  148. contextsynapse/config/context_presets/ai_research.json +25 -0
  149. contextsynapse/config/context_presets/chatgpt_conversations.json +19 -0
  150. contextsynapse/config/context_presets/claude_conversations.json +19 -0
  151. contextsynapse/config/context_presets/legal_compliance.json +21 -0
  152. contextsynapse/config/context_presets/meeting_notes.json +21 -0
  153. contextsynapse/config/context_presets/slack_engineering.json +21 -0
  154. contextsynapse/config/context_presets/tech_climate.json +24 -0
  155. contextsynapse/config/context_presets/toi_politics.json +25 -0
  156. contextsynapse/config/database_config.py +453 -0
  157. contextsynapse/config/deployment.py +221 -0
  158. contextsynapse/config/gpt_action_schema.json +164 -0
  159. contextsynapse/config/indicators/india_macro.yaml +213 -0
  160. contextsynapse/config/logging_config.py +88 -0
  161. contextsynapse/config/mode_config.py +223 -0
  162. contextsynapse/config/schemas/api_spec.yaml +48 -0
  163. contextsynapse/config/schemas/architecture_doc.yaml +51 -0
  164. contextsynapse/config/schemas/chat_history.yaml +90 -0
  165. contextsynapse/config/schemas/chatgpt_conversation.yaml +101 -0
  166. contextsynapse/config/schemas/claude_conversation.yaml +148 -0
  167. contextsynapse/config/schemas/contract.yaml +48 -0
  168. contextsynapse/config/schemas/conversation.yaml +167 -0
  169. contextsynapse/config/schemas/database.yaml +74 -0
  170. contextsynapse/config/schemas/decision.yaml +72 -0
  171. contextsynapse/config/schemas/ecommerce.yaml +56 -0
  172. contextsynapse/config/schemas/education.yaml +42 -0
  173. contextsynapse/config/schemas/healthcare.yaml +133 -0
  174. contextsynapse/config/schemas/hr_document.yaml +48 -0
  175. contextsynapse/config/schemas/invoice.yaml +40 -0
  176. contextsynapse/config/schemas/knowledge_base.yaml +75 -0
  177. contextsynapse/config/schemas/legal.yaml +42 -0
  178. contextsynapse/config/schemas/marketing_content.yaml +48 -0
  179. contextsynapse/config/schemas/meeting_notes.yaml +51 -0
  180. contextsynapse/config/schemas/news_article.yaml +61 -0
  181. contextsynapse/config/schemas/real_estate.yaml +49 -0
  182. contextsynapse/config/schemas/requirements_doc.yaml +48 -0
  183. contextsynapse/config/schemas/research_paper.yaml +56 -0
  184. contextsynapse/config/schemas/resume.yaml +49 -0
  185. contextsynapse/config/schemas/retail.yaml +42 -0
  186. contextsynapse/config/schemas/rule_meta.yaml +173 -0
  187. contextsynapse/config/schemas/rules.yaml +72 -0
  188. contextsynapse/config/schemas/screener_meta.yaml +236 -0
  189. contextsynapse/config/schemas/sdlc.yaml +103 -0
  190. contextsynapse/config/schemas/session_graph.yaml +172 -0
  191. contextsynapse/config/schemas/support_ticket.yaml +48 -0
  192. contextsynapse/config/schemas/web.yaml +64 -0
  193. contextsynapse/config/sensors/earnings_calendar.yaml +52 -0
  194. contextsynapse/config/sensors/global_risk.yaml +53 -0
  195. contextsynapse/config/sensors/government_policy.yaml +54 -0
  196. contextsynapse/config/sensors/supply_chain.yaml +50 -0
  197. contextsynapse/config/sensors/templates/behavioral.yaml +56 -0
  198. contextsynapse/config/sensors/templates/equity_sentiment.yaml +48 -0
  199. contextsynapse/config/sensors/templates/global_macro.yaml +47 -0
  200. contextsynapse/config/sensors/templates/market_data.yaml +118 -0
  201. contextsynapse/config/sensors/templates/sector_technical.yaml +47 -0
  202. contextsynapse/config/sensors/weather.yaml +52 -0
  203. contextsynapse/config/storage_strategy.py +202 -0
  204. contextsynapse/config/templates/competitive_intel.yaml +39 -0
  205. contextsynapse/config/templates/geopolitical_risk.yaml +46 -0
  206. contextsynapse/config/templates/market_analysis.yaml +58 -0
  207. contextsynapse/connectors/__init__.py +15 -0
  208. contextsynapse/connectors/api_router.py +121 -0
  209. contextsynapse/connectors/base.py +357 -0
  210. contextsynapse/connectors/financial/audio.py +170 -0
  211. contextsynapse/connectors/financial/youtube.py +272 -0
  212. contextsynapse/connectors/github.py +164 -0
  213. contextsynapse/connectors/jira.py +120 -0
  214. contextsynapse/connectors/kafka_connector.py +124 -0
  215. contextsynapse/connectors/pipeline_connector.py +747 -0
  216. contextsynapse/connectors/registry.py +116 -0
  217. contextsynapse/connectors/scheduler.py +87 -0
  218. contextsynapse/connectors/universal.py +360 -0
  219. contextsynapse/context/__init__.py +96 -0
  220. contextsynapse/context/__main__.py +4 -0
  221. contextsynapse/context/acl.py +125 -0
  222. contextsynapse/context/agent_card.py +201 -0
  223. contextsynapse/context/agent_memory.py +814 -0
  224. contextsynapse/context/agents.py +472 -0
  225. contextsynapse/context/agents_redis.py +391 -0
  226. contextsynapse/context/assembled.py +204 -0
  227. contextsynapse/context/attribution.py +113 -0
  228. contextsynapse/context/blob.py +184 -0
  229. contextsynapse/context/boundaries.py +187 -0
  230. contextsynapse/context/boundary.py +507 -0
  231. contextsynapse/context/bundle.py +155 -0
  232. contextsynapse/context/cli.py +519 -0
  233. contextsynapse/context/collaboration.py +165 -0
  234. contextsynapse/context/compiler.py +604 -0
  235. contextsynapse/context/composite.py +536 -0
  236. contextsynapse/context/compression.py +147 -0
  237. contextsynapse/context/context_manager.py +888 -0
  238. contextsynapse/context/context_schema.py +90 -0
  239. contextsynapse/context/context_schema.yaml +105 -0
  240. contextsynapse/context/context_units.py +891 -0
  241. contextsynapse/context/conversation.py +488 -0
  242. contextsynapse/context/dedup.py +207 -0
  243. contextsynapse/context/document_processor.py +698 -0
  244. contextsynapse/context/embedding_hooks.py +338 -0
  245. contextsynapse/context/execution_schema.py +274 -0
  246. contextsynapse/context/fan_out.py +138 -0
  247. contextsynapse/context/frozen.py +80 -0
  248. contextsynapse/context/gravity.py +227 -0
  249. contextsynapse/context/hub.py +1401 -0
  250. contextsynapse/context/ingest.py +391 -0
  251. contextsynapse/context/injection.py +226 -0
  252. contextsynapse/context/interaction_graphifier.py +562 -0
  253. contextsynapse/context/layers.py +574 -0
  254. contextsynapse/context/projection.py +1195 -0
  255. contextsynapse/context/promotion.py +634 -0
  256. contextsynapse/context/proof.py +131 -0
  257. contextsynapse/context/propagation.py +577 -0
  258. contextsynapse/context/pubsub.py +135 -0
  259. contextsynapse/context/quality.py +1054 -0
  260. contextsynapse/context/quality_tracker.py +270 -0
  261. contextsynapse/context/scoping.py +370 -0
  262. contextsynapse/context/seed.py +992 -0
  263. contextsynapse/context/session.py +1142 -0
  264. contextsynapse/context/session_graph.py +593 -0
  265. contextsynapse/context/session_memory.py +309 -0
  266. contextsynapse/context/session_resolver.py +111 -0
  267. contextsynapse/context/skill_learning.py +237 -0
  268. contextsynapse/context/smart_budget.py +129 -0
  269. contextsynapse/context/source_policy.py +242 -0
  270. contextsynapse/context/store_factory.py +53 -0
  271. contextsynapse/context/sync.py +648 -0
  272. contextsynapse/context/token.py +236 -0
  273. contextsynapse/context/vector_integration.py +297 -0
  274. contextsynapse/context/webhooks.py +194 -0
  275. contextsynapse/context/working_memory.py +224 -0
  276. contextsynapse/core/__init__.py +18 -0
  277. contextsynapse/core/archiver.py +237 -0
  278. contextsynapse/core/change_stream.py +282 -0
  279. contextsynapse/core/checkpoint.py +310 -0
  280. contextsynapse/core/cloud_storage.py +387 -0
  281. contextsynapse/core/context_state.py +651 -0
  282. contextsynapse/core/cron.py +324 -0
  283. contextsynapse/core/datasource.py +643 -0
  284. contextsynapse/core/db.py +289 -0
  285. contextsynapse/core/federation.py +283 -0
  286. contextsynapse/core/graph_coordinator.py +201 -0
  287. contextsynapse/core/graph_intelligence.py +388 -0
  288. contextsynapse/core/graph_structures.py +106 -0
  289. contextsynapse/core/graph_sync.py +157 -0
  290. contextsynapse/core/hybrid_graph_storage.py +2998 -0
  291. contextsynapse/core/lifecycle.py +691 -0
  292. contextsynapse/core/multiworker.py +378 -0
  293. contextsynapse/core/pruning.py +312 -0
  294. contextsynapse/core/redis_registry.py +524 -0
  295. contextsynapse/core/registry.py +1043 -0
  296. contextsynapse/core/registry_factory.py +51 -0
  297. contextsynapse/core/registry_metadata.py +294 -0
  298. contextsynapse/core/replay.py +354 -0
  299. contextsynapse/core/replication.py +339 -0
  300. contextsynapse/core/time_travel.py +260 -0
  301. contextsynapse/core/write_behind.py +152 -0
  302. contextsynapse/core/write_context.py +39 -0
  303. contextsynapse/db/__init__.py +1 -0
  304. contextsynapse/db/postgres.py +267 -0
  305. contextsynapse/db/profile.py +236 -0
  306. contextsynapse/db/rules.py +328 -0
  307. contextsynapse/demo/__init__.py +0 -0
  308. contextsynapse/demo/report.py +147 -0
  309. contextsynapse/demo/runner.py +520 -0
  310. contextsynapse/demo/scenario.py +165 -0
  311. contextsynapse/demo/session_demo.py +280 -0
  312. contextsynapse/demo/session_report.py +143 -0
  313. contextsynapse/demo/universal_runner.py +257 -0
  314. contextsynapse/engine/__init__.py +15 -0
  315. contextsynapse/engine/core.py +555 -0
  316. contextsynapse/extraction/__init__.py +69 -0
  317. contextsynapse/extraction/cli.py +274 -0
  318. contextsynapse/extraction/config.py +107 -0
  319. contextsynapse/extraction/examples/example_usage.py +118 -0
  320. contextsynapse/extraction/examples/sample_manifest.json +53 -0
  321. contextsynapse/extraction/examples/sample_normalized.json +185 -0
  322. contextsynapse/extraction/extract_engine.py +440 -0
  323. contextsynapse/extraction/extractors/__init__.py +37 -0
  324. contextsynapse/extraction/extractors/chat_export_extractor.py +189 -0
  325. contextsynapse/extraction/extractors/csv_extractor.py +83 -0
  326. contextsynapse/extraction/extractors/docx_extractor.py +129 -0
  327. contextsynapse/extraction/extractors/excel_extractor.py +152 -0
  328. contextsynapse/extraction/extractors/html_extractor.py +146 -0
  329. contextsynapse/extraction/extractors/pdf_extractor.py +635 -0
  330. contextsynapse/extraction/extractors/pdf_extractor_layoutparser.py +408 -0
  331. contextsynapse/extraction/extractors/register_extractors.py +63 -0
  332. contextsynapse/extraction/extractors/text_extractor.py +65 -0
  333. contextsynapse/extraction/extractors/txt_extractor.py +120 -0
  334. contextsynapse/extraction/extractors/website_extractor.py +246 -0
  335. contextsynapse/extraction/fact_extractor.py +236 -0
  336. contextsynapse/extraction/file_manager.py +353 -0
  337. contextsynapse/extraction/hierarchy.py +239 -0
  338. contextsynapse/extraction/id_generator.py +450 -0
  339. contextsynapse/extraction/layout_detector.py +409 -0
  340. contextsynapse/extraction/llm_entity_extractor.py +301 -0
  341. contextsynapse/extraction/normalized_store.py +480 -0
  342. contextsynapse/extraction/normalizer.py +594 -0
  343. contextsynapse/extraction/parquet_writer.py +598 -0
  344. contextsynapse/extraction/post_processors/__init__.py +40 -0
  345. contextsynapse/extraction/post_processors/column_reorganizer.py +507 -0
  346. contextsynapse/extraction/ray_normalization.py +233 -0
  347. contextsynapse/extraction/ray_runner.py +207 -0
  348. contextsynapse/extraction/redis_schema_registry.py +222 -0
  349. contextsynapse/extraction/registry.py +204 -0
  350. contextsynapse/extraction/schema_loader.py +663 -0
  351. contextsynapse/extraction/schema_registry.py +230 -0
  352. contextsynapse/extraction/semantic_normalizer.py +245 -0
  353. contextsynapse/extraction/version_manager.py +314 -0
  354. contextsynapse/gateway/__init__.py +24 -0
  355. contextsynapse/gateway/action_emitter.py +212 -0
  356. contextsynapse/gateway/cost_tracker.py +508 -0
  357. contextsynapse/gateway/gateway.py +377 -0
  358. contextsynapse/gateway/policy.py +303 -0
  359. contextsynapse/governance/__init__.py +13 -0
  360. contextsynapse/governance/layer.py +513 -0
  361. contextsynapse/ingestion/__init__.py +15 -0
  362. contextsynapse/ingestion/amplifier.py +288 -0
  363. contextsynapse/ingestion/async_ingest.py +463 -0
  364. contextsynapse/ingestion/chunker.py +303 -0
  365. contextsynapse/ingestion/chunking.py +58 -0
  366. contextsynapse/ingestion/cleaner.py +190 -0
  367. contextsynapse/ingestion/cleanse.py +252 -0
  368. contextsynapse/ingestion/connectors/__init__.py +38 -0
  369. contextsynapse/ingestion/connectors/base.py +300 -0
  370. contextsynapse/ingestion/connectors/chatgpt_memory.py +247 -0
  371. contextsynapse/ingestion/connectors/claude_memory.py +274 -0
  372. contextsynapse/ingestion/connectors/sap_ingestor.py +208 -0
  373. contextsynapse/ingestion/content_detector.py +80 -0
  374. contextsynapse/ingestion/content_monitor.py +502 -0
  375. contextsynapse/ingestion/dedup.py +106 -0
  376. contextsynapse/ingestion/feed.py +640 -0
  377. contextsynapse/ingestion/filters.py +461 -0
  378. contextsynapse/ingestion/graph_builder.py +705 -0
  379. contextsynapse/ingestion/input_classifier.py +307 -0
  380. contextsynapse/ingestion/job_manager.py +571 -0
  381. contextsynapse/ingestion/llm_extractor.py +610 -0
  382. contextsynapse/ingestion/orchestrator.py +116 -0
  383. contextsynapse/ingestion/parsers/__init__.py +19 -0
  384. contextsynapse/ingestion/parsers/graph_parser_registry.py +103 -0
  385. contextsynapse/ingestion/parsers/graphml_parser.py +141 -0
  386. contextsynapse/ingestion/parsers/jsonld_parser.py +171 -0
  387. contextsynapse/ingestion/parsers/rdf_parser.py +150 -0
  388. contextsynapse/ingestion/pipeline_context.py +228 -0
  389. contextsynapse/ingestion/pipeline_store.py +1195 -0
  390. contextsynapse/ingestion/queue.py +133 -0
  391. contextsynapse/ingestion/reprocess.py +179 -0
  392. contextsynapse/ingestion/scenario_router.py +224 -0
  393. contextsynapse/ingestion/schema_extractor.py +759 -0
  394. contextsynapse/ingestion/schema_validator.py +274 -0
  395. contextsynapse/ingestion/sdlc_ingest.py +87 -0
  396. contextsynapse/ingestion/smart_ingest.py +2451 -0
  397. contextsynapse/ingestion/source_connector.py +171 -0
  398. contextsynapse/ingestion/stage_executor.py +2095 -0
  399. contextsynapse/ingestion/stages/__init__.py +9 -0
  400. contextsynapse/ingestion/stages/tabular_to_graph.py +289 -0
  401. contextsynapse/ingestion/strategies.py +386 -0
  402. contextsynapse/ingestion/universal/__init__.py +4 -0
  403. contextsynapse/ingestion/universal/_operator_registry.py +59 -0
  404. contextsynapse/ingestion/universal/ingest_content.py +32 -0
  405. contextsynapse/ingestion/universal/operators/__init__.py +1 -0
  406. contextsynapse/ingestion/universal/operators/base.py +19 -0
  407. contextsynapse/ingestion/universal/operators/build_edges.py +75 -0
  408. contextsynapse/ingestion/universal/operators/cluster_topics.py +397 -0
  409. contextsynapse/ingestion/universal/operators/deduplicate.py +45 -0
  410. contextsynapse/ingestion/universal/operators/detect_signals.py +90 -0
  411. contextsynapse/ingestion/universal/operators/embed.py +80 -0
  412. contextsynapse/ingestion/universal/operators/extract_entities.py +253 -0
  413. contextsynapse/ingestion/universal/operators/extract_preferences.py +117 -0
  414. contextsynapse/ingestion/universal/operators/filter_content.py +69 -0
  415. contextsynapse/ingestion/universal/operators/index_bm25.py +52 -0
  416. contextsynapse/ingestion/universal/operators/infer_domains.py +69 -0
  417. contextsynapse/ingestion/universal/operators/link_cross_reference.py +210 -0
  418. contextsynapse/ingestion/universal/operators/parse_records.py +66 -0
  419. contextsynapse/ingestion/universal/operators/resolve_entities.py +261 -0
  420. contextsynapse/ingestion/universal/operators/scanners/__init__.py +16 -0
  421. contextsynapse/ingestion/universal/operators/scanners/edges.py +173 -0
  422. contextsynapse/ingestion/universal/operators/scanners/git.py +187 -0
  423. contextsynapse/ingestion/universal/operators/scanners/github.py +135 -0
  424. contextsynapse/ingestion/universal/operators/scanners/github_api.py +509 -0
  425. contextsynapse/ingestion/universal/operators/scanners/helpers.py +67 -0
  426. contextsynapse/ingestion/universal/operators/scanners/jira.py +65 -0
  427. contextsynapse/ingestion/universal/operators/scanners/llm_enrichment.py +82 -0
  428. contextsynapse/ingestion/universal/operators/scanners/repo.py +149 -0
  429. contextsynapse/ingestion/universal/operators/sdlc_scan.py +213 -0
  430. contextsynapse/ingestion/universal/operators/spec_scanner.py +149 -0
  431. contextsynapse/ingestion/universal/operators/store_documents.py +72 -0
  432. contextsynapse/ingestion/universal/operators/synthesize_cu.py +180 -0
  433. contextsynapse/ingestion/universal/operators/validate_gate.py +65 -0
  434. contextsynapse/ingestion/universal/parsers/__init__.py +5 -0
  435. contextsynapse/ingestion/universal/parsers/record_parser.py +203 -0
  436. contextsynapse/ingestion/universal/parsers/turn_parser.py +329 -0
  437. contextsynapse/ingestion/universal/shared_signals.py +161 -0
  438. contextsynapse/ingestion/universal/stage_executor.py +219 -0
  439. contextsynapse/ingestion/web_crawler.py +265 -0
  440. contextsynapse/intelligence/__init__.py +53 -0
  441. contextsynapse/intelligence/alerts.py +198 -0
  442. contextsynapse/intelligence/collector.py +655 -0
  443. contextsynapse/intelligence/comparison.py +198 -0
  444. contextsynapse/intelligence/config.py +56 -0
  445. contextsynapse/intelligence/conflict_detector.py +182 -0
  446. contextsynapse/intelligence/context_gaps.py +192 -0
  447. contextsynapse/intelligence/context_radar.py +135 -0
  448. contextsynapse/intelligence/correlation_engine.py +416 -0
  449. contextsynapse/intelligence/correlation_template.py +120 -0
  450. contextsynapse/intelligence/dedup.py +296 -0
  451. contextsynapse/intelligence/event_bus.py +91 -0
  452. contextsynapse/intelligence/feedback_loop.py +101 -0
  453. contextsynapse/intelligence/freshness.py +307 -0
  454. contextsynapse/intelligence/fundamental_feed.py +551 -0
  455. contextsynapse/intelligence/geo_data.py +170 -0
  456. contextsynapse/intelligence/geo_reference.py +112 -0
  457. contextsynapse/intelligence/graph_fusion.py +465 -0
  458. contextsynapse/intelligence/heuristics.py +176 -0
  459. contextsynapse/intelligence/impact_tracker.py +336 -0
  460. contextsynapse/intelligence/macro_indicators.py +319 -0
  461. contextsynapse/intelligence/ocr.py +104 -0
  462. contextsynapse/intelligence/persistence.py +267 -0
  463. contextsynapse/intelligence/pipeline_health.py +130 -0
  464. contextsynapse/intelligence/price_feed.py +221 -0
  465. contextsynapse/intelligence/rate_limiter.py +130 -0
  466. contextsynapse/intelligence/reactive.py +411 -0
  467. contextsynapse/intelligence/runtime_context.py +390 -0
  468. contextsynapse/intelligence/sentiment_decay.py +426 -0
  469. contextsynapse/intelligence/session.py +277 -0
  470. contextsynapse/intelligence/signal_hierarchy.py +438 -0
  471. contextsynapse/intelligence/signals.py +185 -0
  472. contextsynapse/intelligence/source_watcher.py +132 -0
  473. contextsynapse/intelligence/table_enricher.py +256 -0
  474. contextsynapse/intelligence/tagger.py +319 -0
  475. contextsynapse/intelligence/timeseries.py +209 -0
  476. contextsynapse/intelligence/tracker.py +318 -0
  477. contextsynapse/intelligence/watchdog.py +392 -0
  478. contextsynapse/intelligence/watchdog_manager.py +263 -0
  479. contextsynapse/intelligence/webhook_receiver.py +165 -0
  480. contextsynapse/intelligence/weight_learner.py +234 -0
  481. contextsynapse/llm/__init__.py +8 -0
  482. contextsynapse/llm/client.py +348 -0
  483. contextsynapse/llm/rate_limiter.py +166 -0
  484. contextsynapse/logging_config.py +2 -0
  485. contextsynapse/marketplace/__init__.py +7 -0
  486. contextsynapse/marketplace/registry.py +173 -0
  487. contextsynapse/mcp/__init__.py +11 -0
  488. contextsynapse/mcp/__main__.py +4 -0
  489. contextsynapse/mcp/auth_middleware.py +212 -0
  490. contextsynapse/mcp/connection_pool.py +128 -0
  491. contextsynapse/mcp/server.py +986 -0
  492. contextsynapse/mcp/session_context.py +67 -0
  493. contextsynapse/memory/__init__.py +34 -0
  494. contextsynapse/memory/engine.py +475 -0
  495. contextsynapse/memory/temporal.py +327 -0
  496. contextsynapse/metadata/__init__.py +12 -0
  497. contextsynapse/metadata/metadata_db.py +272 -0
  498. contextsynapse/metadata/metadata_query_tool.py +300 -0
  499. contextsynapse/metadata/metadata_tracker.py +425 -0
  500. contextsynapse/models/__init__.py +27 -0
  501. contextsynapse/models/embedding_service.py +360 -0
  502. contextsynapse/models/model_registry.py +228 -0
  503. contextsynapse/multiworker.py +2 -0
  504. contextsynapse/pipelines/__init__.py +1 -0
  505. contextsynapse/pipelines/executor.py +851 -0
  506. contextsynapse/pipelines/filters.py +189 -0
  507. contextsynapse/pipelines/models.py +176 -0
  508. contextsynapse/pipelines/scheduler.py +268 -0
  509. contextsynapse/playground/__init__.py +1 -0
  510. contextsynapse/playground/templates.py +85 -0
  511. contextsynapse/plugins/__init__.py +43 -0
  512. contextsynapse/plugins/api.py +66 -0
  513. contextsynapse/plugins/base.py +350 -0
  514. contextsynapse/plugins/domain_interface.py +508 -0
  515. contextsynapse/plugins/domain_loader.py +241 -0
  516. contextsynapse/plugins/loader.py +148 -0
  517. contextsynapse/plugins/registry.py +265 -0
  518. contextsynapse/project/__init__.py +11 -0
  519. contextsynapse/project/code_context.py +807 -0
  520. contextsynapse/project/connectors/__init__.py +4 -0
  521. contextsynapse/project/connectors/github_connector.py +113 -0
  522. contextsynapse/project/connectors/jira_connector.py +160 -0
  523. contextsynapse/project/graph.py +1023 -0
  524. contextsynapse/project/project_context.py +545 -0
  525. contextsynapse/project/scanner_registry.py +61 -0
  526. contextsynapse/project/schema_manager.py +322 -0
  527. contextsynapse/project/schemas/knowledge.yaml +59 -0
  528. contextsynapse/project/schemas/sdlc.yaml +369 -0
  529. contextsynapse/project/sdlc_schema.py +172 -0
  530. contextsynapse/project/spec_parser.py +85 -0
  531. contextsynapse/project/task_lock.py +181 -0
  532. contextsynapse/project/task_stream.py +203 -0
  533. contextsynapse/project/team_tools.py +537 -0
  534. contextsynapse/py.typed +0 -0
  535. contextsynapse/realtime/__init__.py +6 -0
  536. contextsynapse/realtime/collaboration.py +147 -0
  537. contextsynapse/rules/__init__.py +10 -0
  538. contextsynapse/rules/engine.py +116 -0
  539. contextsynapse/rules/evaluators/__init__.py +6 -0
  540. contextsynapse/rules/evaluators/aggregate.py +205 -0
  541. contextsynapse/rules/evaluators/custom.py +170 -0
  542. contextsynapse/rules/evaluators/pre_action.py +125 -0
  543. contextsynapse/rules/evaluators/temporal.py +129 -0
  544. contextsynapse/rules/loader.py +52 -0
  545. contextsynapse/rules/models.py +124 -0
  546. contextsynapse/rules/universal.py +393 -0
  547. contextsynapse/scheduler.py +229 -0
  548. contextsynapse/schema/__init__.py +42 -0
  549. contextsynapse/schema/compiler.py +252 -0
  550. contextsynapse/schema/composer.py +158 -0
  551. contextsynapse/schema/dedup.py +73 -0
  552. contextsynapse/schema/derivation.py +172 -0
  553. contextsynapse/schema/sdl.py +326 -0
  554. contextsynapse/schema/validation_gate.py +124 -0
  555. contextsynapse/sdk/__init__.py +63 -0
  556. contextsynapse/sdk/agent.py +214 -0
  557. contextsynapse/sdk/client.py +269 -0
  558. contextsynapse/sdk/exceptions.py +23 -0
  559. contextsynapse/sdk/models.py +78 -0
  560. contextsynapse/sdk/session.py +408 -0
  561. contextsynapse/sdk/tracked.py +218 -0
  562. contextsynapse/sdk/worker.py +266 -0
  563. contextsynapse/sdk/workspace_client.py +98 -0
  564. contextsynapse/sdk/ws.py +41 -0
  565. contextsynapse/search/__init__.py +20 -0
  566. contextsynapse/search/embedding_cache.py +140 -0
  567. contextsynapse/search/enhanced_search.py +152 -0
  568. contextsynapse/search/fulltext.py +130 -0
  569. contextsynapse/search/graph_search.py +634 -0
  570. contextsynapse/search/lmdb_index.py +1218 -0
  571. contextsynapse/search/nl_to_aiql.py +199 -0
  572. contextsynapse/search/rag.py +1346 -0
  573. contextsynapse/search/rag_cache.py +167 -0
  574. contextsynapse/search/reasoning_chain.py +231 -0
  575. contextsynapse/search/redis_search.py +207 -0
  576. contextsynapse/search/retrieval_quality.py +314 -0
  577. contextsynapse/search/semantic_query.py +455 -0
  578. contextsynapse/search/text_resolver.py +159 -0
  579. contextsynapse/search/whoosh_search.py +373 -0
  580. contextsynapse/security/__init__.py +17 -0
  581. contextsynapse/security/audit.py +297 -0
  582. contextsynapse/security/audit_logger.py +97 -0
  583. contextsynapse/security/audit_trail.py +270 -0
  584. contextsynapse/security/auth_unified.py +284 -0
  585. contextsynapse/security/auto_tagger.py +230 -0
  586. contextsynapse/security/data_security.py +218 -0
  587. contextsynapse/security/encryption.py +207 -0
  588. contextsynapse/security/identity.py +447 -0
  589. contextsynapse/security/jwt_identity.py +59 -0
  590. contextsynapse/security/middleware.py +336 -0
  591. contextsynapse/security/pii.py +233 -0
  592. contextsynapse/security/rbac.py +96 -0
  593. contextsynapse/security/rls.py +205 -0
  594. contextsynapse/security/sanitize.py +233 -0
  595. contextsynapse/security/scoped_encryption.py +131 -0
  596. contextsynapse/security/tenant.py +401 -0
  597. contextsynapse/shield/__init__.py +21 -0
  598. contextsynapse/shield/anomaly.py +56 -0
  599. contextsynapse/shield/permissions.py +99 -0
  600. contextsynapse/shield/profile.py +103 -0
  601. contextsynapse/shield/shield.py +108 -0
  602. contextsynapse/shield/trust_engine.py +69 -0
  603. contextsynapse/skills/__init__.py +14 -0
  604. contextsynapse/skills/engine.py +233 -0
  605. contextsynapse/skills/loader.py +59 -0
  606. contextsynapse/skills/models.py +139 -0
  607. contextsynapse/storage/__init__.py +7 -0
  608. contextsynapse/storage/cache.py +208 -0
  609. contextsynapse/storage/columnar_store_v2.py +178 -0
  610. contextsynapse/storage/csr_graph_storage.py +587 -0
  611. contextsynapse/storage/csr_store.py +388 -0
  612. contextsynapse/storage/document_store.py +491 -0
  613. contextsynapse/storage/hnsw_index.py +294 -0
  614. contextsynapse/storage/hybrid_store_v2.py +278 -0
  615. contextsynapse/storage/lmdb_graph_storage.py +366 -0
  616. contextsynapse/storage/migration.py +279 -0
  617. contextsynapse/storage/namespace_store.py +346 -0
  618. contextsynapse/storage/pure_graph_storage.py +185 -0
  619. contextsynapse/storage/redis_graph_adapter.py +186 -0
  620. contextsynapse/storage/redis_graph_storage.py +375 -0
  621. contextsynapse/storage/router/__init__.py +29 -0
  622. contextsynapse/storage/router/duckdb_store.py +398 -0
  623. contextsynapse/storage/router/factory.py +83 -0
  624. contextsynapse/storage/router/interface.py +125 -0
  625. contextsynapse/storage/router/postgres_store.py +339 -0
  626. contextsynapse/storage/router/resolver.py +192 -0
  627. contextsynapse/storage/router/router.py +300 -0
  628. contextsynapse/storage/single_file_storage.py +391 -0
  629. contextsynapse/storage/storage_manager.py +214 -0
  630. contextsynapse/storage/storage_query_optimizer.py +314 -0
  631. contextsynapse/storage/wal.py +359 -0
  632. contextsynapse/temporal/__init__.py +0 -0
  633. contextsynapse/temporal/storage.py +106 -0
  634. contextsynapse/tests/__init__.py +11 -0
  635. contextsynapse/tests/regression/__init__.py +1 -0
  636. contextsynapse/tests/regression/add_metadata.py +395 -0
  637. contextsynapse/tests/regression/add_skip_flags.py +85 -0
  638. contextsynapse/tests/regression/cases/test_basic_create_node.yaml +20 -0
  639. contextsynapse/tests/regression/cases/test_basic_select.yaml +21 -0
  640. contextsynapse/tests/regression/cases/test_blockchain_audit_trail.yaml +37 -0
  641. contextsynapse/tests/regression/cases/test_blockchain_audit_trail_filtered.yaml +39 -0
  642. contextsynapse/tests/regression/cases/test_blockchain_blocks_range.yaml +39 -0
  643. contextsynapse/tests/regression/cases/test_blockchain_get_block.yaml +35 -0
  644. contextsynapse/tests/regression/cases/test_blockchain_latest_block.yaml +35 -0
  645. contextsynapse/tests/regression/cases/test_blockchain_length.yaml +37 -0
  646. contextsynapse/tests/regression/cases/test_blockchain_merkle_root.yaml +37 -0
  647. contextsynapse/tests/regression/cases/test_blockchain_verify.yaml +35 -0
  648. contextsynapse/tests/regression/cases/test_blockchain_verify_block.yaml +35 -0
  649. contextsynapse/tests/regression/cases/test_create_edge.yaml +28 -0
  650. contextsynapse/tests/regression/cases/test_delete_edge_basic.yaml +29 -0
  651. contextsynapse/tests/regression/cases/test_delete_node_basic.yaml +29 -0
  652. contextsynapse/tests/regression/cases/test_evaluation_mrr.yaml +40 -0
  653. contextsynapse/tests/regression/cases/test_evaluation_ndcg.yaml +40 -0
  654. contextsynapse/tests/regression/cases/test_evaluation_precision.yaml +40 -0
  655. contextsynapse/tests/regression/cases/test_evaluation_recall.yaml +40 -0
  656. contextsynapse/tests/regression/cases/test_group_by_basic.yaml +56 -0
  657. contextsynapse/tests/regression/cases/test_match_node_basic.yaml +29 -0
  658. contextsynapse/tests/regression/cases/test_match_node_with_order_limit.yaml +31 -0
  659. contextsynapse/tests/regression/cases/test_namespace_switch.yaml +18 -0
  660. contextsynapse/tests/regression/cases/test_pipeline_cascaded.yaml +61 -0
  661. contextsynapse/tests/regression/cases/test_pipeline_fixed_size_chunking.yaml +48 -0
  662. contextsynapse/tests/regression/cases/test_pipeline_gpt4_chunking.yaml +54 -0
  663. contextsynapse/tests/regression/cases/test_pipeline_hybrid_indexing.yaml +57 -0
  664. contextsynapse/tests/regression/cases/test_pipeline_large_embedding.yaml +52 -0
  665. contextsynapse/tests/regression/cases/test_pipeline_paragraph_chunking.yaml +49 -0
  666. contextsynapse/tests/regression/cases/test_pipeline_recursive_chunking.yaml +47 -0
  667. contextsynapse/tests/regression/cases/test_pipeline_run_pipeline.yaml +56 -0
  668. contextsynapse/tests/regression/cases/test_pipeline_section_based_chunking.yaml +53 -0
  669. contextsynapse/tests/regression/cases/test_pipeline_semantic_chunking.yaml +51 -0
  670. contextsynapse/tests/regression/cases/test_pipeline_with_entity_extraction.yaml +57 -0
  671. contextsynapse/tests/regression/cases/test_pipeline_with_relationships.yaml +62 -0
  672. contextsynapse/tests/regression/cases/test_rag_evaluation.yaml +38 -0
  673. contextsynapse/tests/regression/cases/test_rag_graph_bfs_with_eval.yaml +48 -0
  674. contextsynapse/tests/regression/cases/test_rag_graph_centrality.yaml +40 -0
  675. contextsynapse/tests/regression/cases/test_rag_graph_centrality_eval.yaml +35 -0
  676. contextsynapse/tests/regression/cases/test_rag_graph_community.yaml +40 -0
  677. contextsynapse/tests/regression/cases/test_rag_graph_community_eval.yaml +35 -0
  678. contextsynapse/tests/regression/cases/test_rag_graph_dfs_with_eval.yaml +35 -0
  679. contextsynapse/tests/regression/cases/test_rag_graph_multi_hop_eval.yaml +35 -0
  680. contextsynapse/tests/regression/cases/test_rag_graph_path.yaml +40 -0
  681. contextsynapse/tests/regression/cases/test_rag_graph_search_basic.yaml +38 -0
  682. contextsynapse/tests/regression/cases/test_rag_graph_search_bfs.yaml +52 -0
  683. contextsynapse/tests/regression/cases/test_rag_graph_search_dfs.yaml +41 -0
  684. contextsynapse/tests/regression/cases/test_rag_graph_search_multi_hop.yaml +43 -0
  685. contextsynapse/tests/regression/cases/test_rag_graph_search_shortest_path.yaml +41 -0
  686. contextsynapse/tests/regression/cases/test_rag_graph_search_weighted.yaml +43 -0
  687. contextsynapse/tests/regression/cases/test_rag_graph_shortest_path_eval.yaml +35 -0
  688. contextsynapse/tests/regression/cases/test_rag_graph_traversal.yaml +30 -0
  689. contextsynapse/tests/regression/cases/test_rag_graph_weighted_eval.yaml +35 -0
  690. contextsynapse/tests/regression/cases/test_rag_hybrid_search.yaml +33 -0
  691. contextsynapse/tests/regression/cases/test_rag_hybrid_with_prompt_embedding.yaml +44 -0
  692. contextsynapse/tests/regression/cases/test_rag_keyword_search.yaml +32 -0
  693. contextsynapse/tests/regression/cases/test_rag_multi_hop_graph.yaml +32 -0
  694. contextsynapse/tests/regression/cases/test_rag_path_based.yaml +34 -0
  695. contextsynapse/tests/regression/cases/test_rag_profile_based.yaml +32 -0
  696. contextsynapse/tests/regression/cases/test_rag_vector_search.yaml +32 -0
  697. contextsynapse/tests/regression/cases/test_rag_weighted_graph.yaml +34 -0
  698. contextsynapse/tests/regression/cases/test_rag_weighted_hybrid.yaml +31 -0
  699. contextsynapse/tests/regression/cases/test_semantic_boundary_chunking.yaml +57 -0
  700. contextsynapse/tests/regression/cases/test_semantic_boundary_detection.yaml +33 -0
  701. contextsynapse/tests/regression/cases/test_semantic_hash_function.yaml +30 -0
  702. contextsynapse/tests/regression/cases/test_semantic_hash_with_model.yaml +31 -0
  703. contextsynapse/tests/regression/cases/test_tcs_ingestion_fixed_size.yaml +44 -0
  704. contextsynapse/tests/regression/cases/test_tcs_ingestion_recursive.yaml +46 -0
  705. contextsynapse/tests/regression/cases/test_tcs_ingestion_section.yaml +46 -0
  706. contextsynapse/tests/regression/cases/test_tcs_ingestion_semantic.yaml +44 -0
  707. contextsynapse/tests/regression/cases/test_time_travel_as_of.yaml +35 -0
  708. contextsynapse/tests/regression/cases/test_time_travel_at_commit.yaml +33 -0
  709. contextsynapse/tests/regression/cases/test_time_travel_at_timestamp.yaml +33 -0
  710. contextsynapse/tests/regression/cases/test_time_travel_for_system_time_all.yaml +37 -0
  711. contextsynapse/tests/regression/cases/test_time_travel_versions_between.yaml +39 -0
  712. contextsynapse/tests/regression/cases/test_traverse_basic.yaml +31 -0
  713. contextsynapse/tests/regression/cases/test_traverse_max_depth.yaml +34 -0
  714. contextsynapse/tests/regression/cases/test_update_edge_basic.yaml +29 -0
  715. contextsynapse/tests/regression/evaluation_metrics.py +227 -0
  716. contextsynapse/tests/regression/regression_runner.py +1081 -0
  717. contextsynapse/tests/regression/setup_regression_data.py +212 -0
  718. contextsynapse/tests/regression/test_basic_only.py +84 -0
  719. contextsynapse/tests/regression/test_namespace_creation.py +29 -0
  720. contextsynapse/tests/regression/test_single_fix.py +61 -0
  721. contextsynapse/tests/regression/test_single_query.py +20 -0
  722. contextsynapse/tests/regression/validate_test_syntax.py +179 -0
  723. contextsynapse/tests/test_advanced_features.py +347 -0
  724. contextsynapse/tests/test_aiql_summary.py +283 -0
  725. contextsynapse/tests/test_all_aiql_queries.py +948 -0
  726. contextsynapse/tests/test_all_create_queries.py +213 -0
  727. contextsynapse/tests/test_api_vs_native.py +280 -0
  728. contextsynapse/tests/test_chunking_dedup.py +199 -0
  729. contextsynapse/tests/test_connectors.py +171 -0
  730. contextsynapse/tests/test_edges_and_match.py +202 -0
  731. contextsynapse/tests/test_extraction_pipeline_integration.py +581 -0
  732. contextsynapse/tests/test_name_property.py +224 -0
  733. contextsynapse/tests/test_node_edge_metadata.py +250 -0
  734. contextsynapse/tests/test_playground_conn.py +114 -0
  735. contextsynapse/tests/test_query_cache.py +213 -0
  736. contextsynapse/tests/test_source_policy_auth.py +348 -0
  737. contextsynapse/tests/test_temporal_and_domain.py +224 -0
  738. contextsynapse/tests/test_time_travel_e2e.py +571 -0
  739. contextsynapse/tests/test_traversal_and_aggregation.py +275 -0
  740. contextsynapse/tools/__init__.py +36 -0
  741. contextsynapse/tools/a2a_tools.py +106 -0
  742. contextsynapse/tools/cognition_tools.py +118 -0
  743. contextsynapse/tools/context.py +905 -0
  744. contextsynapse/tools/formatting.py +92 -0
  745. contextsynapse/tools/gateway_tools.py +186 -0
  746. contextsynapse/tools/graph.py +1700 -0
  747. contextsynapse/tools/intelligence.py +235 -0
  748. contextsynapse/tools/memory.py +118 -0
  749. contextsynapse/tools/registry.py +373 -0
  750. contextsynapse/tools/shield_tools.py +159 -0
  751. contextsynapse/tools/tasks.py +341 -0
  752. contextsynapse/tools/workspace_tools.py +124 -0
  753. contextsynapse/utils/__init__.py +15 -0
  754. contextsynapse/utils/config_loader.py +198 -0
  755. contextsynapse/utils/env_loader.py +156 -0
  756. contextsynapse/utils/file_utils.py +288 -0
  757. contextsynapse/utils/logging_optimizer.py +119 -0
  758. contextsynapse/vector/__init__.py +30 -0
  759. contextsynapse/vector/chroma_vector_store.py +152 -0
  760. contextsynapse/vector/custom_vector_store.py +537 -0
  761. contextsynapse/vector/faiss_vector_store.py +296 -0
  762. contextsynapse/vector/qdrant_vector_store.py +163 -0
  763. contextsynapse/vector/vector_db.py +953 -0
  764. contextsynapse/vector/vector_db_manager.py +197 -0
  765. contextsynapse/workspace/__init__.py +27 -0
  766. contextsynapse/workspace/base.py +94 -0
  767. contextsynapse/workspace/git.py +228 -0
  768. contextsynapse/workspace/github.py +78 -0
  769. contextsynapse/workspace/local.py +73 -0
  770. contextsynapse/workspace/tools.py +222 -0
  771. contextsynapse-1.0.0.dist-info/METADATA +847 -0
  772. contextsynapse-1.0.0.dist-info/RECORD +776 -0
  773. contextsynapse-1.0.0.dist-info/WHEEL +5 -0
  774. contextsynapse-1.0.0.dist-info/entry_points.txt +4 -0
  775. contextsynapse-1.0.0.dist-info/licenses/LICENSE +200 -0
  776. contextsynapse-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,131 @@
1
+ """ProofToken — immutable proof anchoring a context bundle to a trade decision.
2
+
3
+ Created when a trade is proposed. Stores the bundle's Merkle root and chain
4
+ anchors (which version of each entity was seen). Tamper-proof via SHA-256.
5
+
6
+ Redis key for lookup: proof:{trade_id} → JSON
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import json
12
+ from dataclasses import dataclass
13
+ from datetime import datetime, timezone
14
+ from typing import Any, Dict, List, Optional
15
+
16
+ from .bundle import BundleToken, TokenRef
17
+
18
+
19
+ def _sha256(data: str) -> str:
20
+ return hashlib.sha256(data.encode("utf-8")).hexdigest()
21
+
22
+
23
+ def _canonical(data: Any) -> str:
24
+ return json.dumps(data, sort_keys=True, default=str)
25
+
26
+
27
+ @dataclass
28
+ class ChainAnchor:
29
+ """Reference to a specific version in an entity's chain."""
30
+ entity: str
31
+ version: int
32
+ block_hash: str
33
+
34
+
35
+ @dataclass
36
+ class ProofToken:
37
+ """Immutable proof of a trade decision's context."""
38
+ proof_id: str
39
+ trade_id: str
40
+
41
+ # Bundle provenance
42
+ bundle_id: str
43
+ bundle_hash: str
44
+ merkle_root: str
45
+
46
+ # Which entity chain versions were in scope
47
+ anchors: List[ChainAnchor]
48
+
49
+ # The decision payload
50
+ decision: Dict[str, Any]
51
+ decided_by: str
52
+ decided_at: str
53
+
54
+ # Tamper-proof seal
55
+ proof_hash: str
56
+
57
+ # Filled in post-trade
58
+ trade_pnl: Optional[float] = None
59
+ attribution_score: Optional[float] = None
60
+
61
+
62
+ def _compute_proof_hash(bundle_hash: str, decision: Dict, decided_at: str) -> str:
63
+ data = f"{bundle_hash}:{_canonical(decision)}:{decided_at}"
64
+ return _sha256(data)
65
+
66
+
67
+ def create_proof_token(
68
+ trade_id: str,
69
+ bundle: BundleToken,
70
+ decision: Dict[str, Any],
71
+ decided_by: str,
72
+ ) -> ProofToken:
73
+ """Create a proof token anchoring a bundle to a trade decision."""
74
+ decided_at = datetime.now(timezone.utc).isoformat()
75
+ proof_hash = _compute_proof_hash(bundle.bundle_hash, decision, decided_at)
76
+
77
+ anchors = [
78
+ ChainAnchor(entity=ref.entity, version=ref.version, block_hash=ref.block_hash)
79
+ for ref in bundle.token_refs
80
+ ]
81
+
82
+ return ProofToken(
83
+ proof_id=f"pt:{trade_id}",
84
+ trade_id=trade_id,
85
+ bundle_id=bundle.bundle_id,
86
+ bundle_hash=bundle.bundle_hash,
87
+ merkle_root=bundle.merkle_root,
88
+ anchors=anchors,
89
+ decision=decision,
90
+ decided_by=decided_by,
91
+ decided_at=decided_at,
92
+ proof_hash=proof_hash,
93
+ )
94
+
95
+
96
+ def verify_proof(proof: ProofToken) -> bool:
97
+ """Verify that a proof token hasn't been tampered with."""
98
+ expected = _compute_proof_hash(proof.bundle_hash, proof.decision, proof.decided_at)
99
+ return expected == proof.proof_hash
100
+
101
+
102
+ def store_proof(redis_client, proof: ProofToken) -> None:
103
+ """Persist a proof token to Redis."""
104
+ data = json.dumps({
105
+ "proof_id": proof.proof_id,
106
+ "trade_id": proof.trade_id,
107
+ "bundle_id": proof.bundle_id,
108
+ "bundle_hash": proof.bundle_hash,
109
+ "merkle_root": proof.merkle_root,
110
+ "anchors": [
111
+ {"entity": a.entity, "version": a.version, "block_hash": a.block_hash}
112
+ for a in proof.anchors
113
+ ],
114
+ "decision": proof.decision,
115
+ "decided_by": proof.decided_by,
116
+ "decided_at": proof.decided_at,
117
+ "proof_hash": proof.proof_hash,
118
+ "trade_pnl": proof.trade_pnl,
119
+ "attribution_score": proof.attribution_score,
120
+ }, default=str)
121
+ redis_client.set(f"proof:{proof.trade_id}", data)
122
+
123
+
124
+ def retrieve_proof(redis_client, trade_id: str) -> Optional[ProofToken]:
125
+ """Retrieve a proof token from Redis."""
126
+ raw = redis_client.get(f"proof:{trade_id}")
127
+ if raw is None:
128
+ return None
129
+ data = json.loads(raw)
130
+ data["anchors"] = [ChainAnchor(**a) for a in data["anchors"]]
131
+ return ProofToken(**data)
@@ -0,0 +1,577 @@
1
+ """Signal Propagation Engine — traverses the context graph to find affected entities.
2
+
3
+ When a signal arrives (e.g., "crude oil +$5"), this engine:
4
+ 1. Identifies the source entity (crude_oil)
5
+ 2. Walks all outgoing edges (IMPACTS, DEPENDS_ON, etc.)
6
+ 3. Applies propagation_weight and decay_per_hop
7
+ 4. Returns all affected entities with propagated signal strength
8
+
9
+ This is how cross-domain effects are discovered automatically.
10
+ No LLM needed — just graph traversal with weighted edges.
11
+
12
+ Example:
13
+ Signal: "RBI raises repo rate by 25bps"
14
+ Source: rbi_policy (macro layer)
15
+
16
+ Hop 1: rbi_policy --REGULATED_BY--> banking_sector (weight=0.9)
17
+ Hop 2: banking_sector --CONTAINS--> HDFC Bank (weight=0.8)
18
+ banking_sector --CONTAINS--> ICICI Bank (weight=0.8)
19
+ Hop 3: banking_sector --IMPACTS--> real_estate (weight=0.6)
20
+ banking_sector --IMPACTS--> auto (weight=0.4, via EMI rates)
21
+
22
+ Result:
23
+ HDFC Bank: signal_strength = 0.9 * 0.8 = 0.72
24
+ ICICI Bank: signal_strength = 0.9 * 0.8 = 0.72
25
+ Real estate: signal_strength = 0.9 * 0.6 = 0.54
26
+ Auto: signal_strength = 0.9 * 0.4 = 0.36
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import logging
32
+ import time
33
+ from collections import defaultdict, deque
34
+ from dataclasses import dataclass, field
35
+ from typing import Any, Dict, List, Optional, Set, Tuple
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ # ---------------------------------------------------------------------------
41
+ # Propagation edge types we traverse
42
+ # ---------------------------------------------------------------------------
43
+
44
+ # These are the edge labels the engine scans when building the dependency
45
+ # graph. Any edge with one of these labels is treated as a propagation
46
+ # channel. This list is domain-agnostic — layers create these edges.
47
+ PROPAGATION_EDGE_LABELS: Set[str] = {
48
+ "DEPENDS_ON",
49
+ "IMPACTS",
50
+ "REGULATED_BY",
51
+ "SUPPLIES_TO",
52
+ "COMPETES_WITH",
53
+ "CONTAINS",
54
+ "PART_OF",
55
+ "AFFECTED_BY",
56
+ "DRIVES",
57
+ "CORRELATED_WITH",
58
+ }
59
+
60
+ # Node labels we index as entities in the dependency graph
61
+ ENTITY_NODE_LABELS: Set[str] = {
62
+ "Entity",
63
+ "CompanyIdentity",
64
+ "Sector",
65
+ "SupplyChainInput",
66
+ "Regulator",
67
+ "Competitor",
68
+ "MacroDependency",
69
+ "SharedEntity",
70
+ "Brand",
71
+ "Person",
72
+ }
73
+
74
+
75
+ # ---------------------------------------------------------------------------
76
+ # Result data class
77
+ # ---------------------------------------------------------------------------
78
+
79
+
80
+ @dataclass
81
+ class PropagatedSignal:
82
+ """An entity affected by signal propagation through the graph."""
83
+
84
+ entity: str # affected entity name or namespace
85
+ signal_strength: float # 0-1 after propagation
86
+ hops: int # how many edges traversed
87
+ path: List[str] # traversal path ["source", "hop1", "hop2"]
88
+ edge_types: List[str] # edge types used at each hop
89
+ source_signal: str # original signal description
90
+ reasoning: str # human-readable explanation
91
+
92
+ def to_dict(self) -> Dict[str, Any]:
93
+ return {
94
+ "entity": self.entity,
95
+ "signal_strength": round(self.signal_strength, 4),
96
+ "hops": self.hops,
97
+ "path": list(self.path),
98
+ "edge_types": list(self.edge_types),
99
+ "source_signal": self.source_signal,
100
+ "reasoning": self.reasoning,
101
+ }
102
+
103
+
104
+ # ---------------------------------------------------------------------------
105
+ # Signal Propagation Engine
106
+ # ---------------------------------------------------------------------------
107
+
108
+
109
+ class SignalPropagationEngine:
110
+ """Propagates signals through the context graph via weighted edges.
111
+
112
+ The engine builds an in-memory adjacency list from the graph registry
113
+ and performs BFS traversal with signal decay to discover affected
114
+ entities. No LLM calls — pure graph traversal.
115
+
116
+ Usage::
117
+
118
+ engine = SignalPropagationEngine(registry=my_registry)
119
+ engine.build_dependency_graph()
120
+
121
+ affected = engine.propagate(
122
+ source_entity="crude_oil",
123
+ signal_value=0.8,
124
+ signal_description="crude oil rises 10%",
125
+ )
126
+ for sig in affected:
127
+ print(f"{sig.entity}: {sig.signal_strength:.2f} ({sig.reasoning})")
128
+
129
+ Performance:
130
+ Graph build: O(nodes + edges), typically < 200ms for 10k nodes.
131
+ Propagation: O(V + E) BFS, typically < 5ms per signal.
132
+ """
133
+
134
+ def __init__(self, registry):
135
+ """
136
+ Args:
137
+ registry: GraphRegistry (or RedisGraphRegistry) for graph access.
138
+ """
139
+ self._registry = registry
140
+
141
+ # Adjacency list: entity_key -> [(target_key, edge_type, weight, decay)]
142
+ self._adjacency: Dict[str, List[Tuple[str, str, float, float]]] = defaultdict(list)
143
+ # Reverse adjacency for "depended_by" queries
144
+ self._reverse: Dict[str, List[Tuple[str, str, float, float]]] = defaultdict(list)
145
+ # Entity metadata: entity_key -> {name, label, namespace, ...}
146
+ self._entity_meta: Dict[str, Dict[str, Any]] = {}
147
+ # Build timestamp
148
+ self._built_at: Optional[str] = None
149
+ self._build_time_ms: float = 0.0
150
+
151
+ # ------------------------------------------------------------------
152
+ # Graph construction
153
+ # ------------------------------------------------------------------
154
+
155
+ def build_dependency_graph(self) -> None:
156
+ """Build in-memory adjacency list from all dependency edges.
157
+
158
+ Scans every graph namespace for entity-like nodes and propagation
159
+ edges. Builds both forward and reverse adjacency lists.
160
+
161
+ This is built ONCE and cached. Call again to refresh.
162
+ """
163
+ from datetime import datetime, timezone
164
+
165
+ t0 = time.monotonic()
166
+
167
+ adjacency: Dict[str, List[Tuple[str, str, float, float]]] = defaultdict(list)
168
+ reverse: Dict[str, List[Tuple[str, str, float, float]]] = defaultdict(list)
169
+ entity_meta: Dict[str, Dict[str, Any]] = {}
170
+
171
+ graphs = self._registry.list_graphs()
172
+ for graph_info in graphs:
173
+ namespace = graph_info.get("name", "")
174
+ if not namespace or namespace.startswith("_"):
175
+ continue
176
+
177
+ graph = self._registry.get_graph(namespace, load_if_missing=False)
178
+ if graph is None:
179
+ continue
180
+
181
+ self._index_graph(graph, namespace, adjacency, reverse, entity_meta)
182
+
183
+ self._adjacency = dict(adjacency)
184
+ self._reverse = dict(reverse)
185
+ self._entity_meta = entity_meta
186
+ self._built_at = datetime.now(timezone.utc).isoformat()
187
+ self._build_time_ms = (time.monotonic() - t0) * 1000
188
+
189
+ logger.info(
190
+ "Dependency graph built: %d entities, %d forward edges, %d reverse edges in %.1fms",
191
+ len(self._entity_meta),
192
+ sum(len(v) for v in self._adjacency.values()),
193
+ sum(len(v) for v in self._reverse.values()),
194
+ self._build_time_ms,
195
+ )
196
+
197
+ def _index_graph(
198
+ self,
199
+ graph,
200
+ namespace: str,
201
+ adjacency: Dict[str, List[Tuple[str, str, float, float]]],
202
+ reverse: Dict[str, List[Tuple[str, str, float, float]]],
203
+ entity_meta: Dict[str, Dict[str, Any]],
204
+ ) -> None:
205
+ """Index nodes and edges from a single graph namespace."""
206
+ # Index entity nodes
207
+ node_id_to_key: Dict[str, str] = {}
208
+ for label in ENTITY_NODE_LABELS:
209
+ try:
210
+ nodes = graph.get_all_nodes(label=label)
211
+ except Exception:
212
+ continue
213
+ for node in nodes:
214
+ props = node.properties or {}
215
+ name = props.get("name", "")
216
+ if not name:
217
+ continue
218
+ key = _entity_key(name)
219
+ node_id_to_key[node.id] = key
220
+ if key not in entity_meta:
221
+ entity_meta[key] = {
222
+ "name": name,
223
+ "label": label,
224
+ "namespace": namespace,
225
+ "node_id": node.id,
226
+ }
227
+
228
+ # Index edges that connect known entity nodes
229
+ try:
230
+ all_edges = graph.get_all_edges() if hasattr(graph, "get_all_edges") else []
231
+ except Exception:
232
+ all_edges = []
233
+
234
+ for edge in all_edges:
235
+ edge_label = getattr(edge, "label", "") or ""
236
+ if edge_label not in PROPAGATION_EDGE_LABELS:
237
+ continue
238
+
239
+ source_key = node_id_to_key.get(edge.source)
240
+ target_key = node_id_to_key.get(edge.target)
241
+ if not source_key or not target_key or source_key == target_key:
242
+ continue
243
+
244
+ # Extract weight/decay from edge properties or use defaults
245
+ eprops = edge.properties or {}
246
+ weight = float(eprops.get("propagation_weight", eprops.get("weight", 0.8)))
247
+ decay = float(eprops.get("decay_per_hop", 0.3))
248
+
249
+ adjacency[source_key].append((target_key, edge_label, weight, decay))
250
+ reverse[target_key].append((source_key, edge_label, weight, decay))
251
+
252
+ # ------------------------------------------------------------------
253
+ # Signal propagation
254
+ # ------------------------------------------------------------------
255
+
256
+ def propagate(
257
+ self,
258
+ source_entity: str,
259
+ signal_value: float,
260
+ signal_description: str = "",
261
+ max_hops: int = 3,
262
+ min_strength: float = 0.1,
263
+ ) -> List[PropagatedSignal]:
264
+ """Propagate a signal from source through dependency edges.
265
+
266
+ Uses BFS with signal decay. At each hop the signal strength is
267
+ multiplied by the edge's propagation_weight and reduced by
268
+ (1 - decay_per_hop).
269
+
270
+ Args:
271
+ source_entity: Entity name where the signal originates.
272
+ signal_value: Signal strength (-1 to +1).
273
+ signal_description: Human-readable description of the signal.
274
+ max_hops: Maximum traversal depth (default 3).
275
+ min_strength: Stop propagating below this threshold (default 0.1).
276
+
277
+ Returns:
278
+ List of PropagatedSignal sorted by signal_strength descending.
279
+ """
280
+ source_key = _entity_key(source_entity)
281
+ if source_key not in self._adjacency and source_key not in self._entity_meta:
282
+ # Try partial match
283
+ source_key = self._resolve_entity(source_entity)
284
+ if not source_key:
285
+ return []
286
+
287
+ abs_value = abs(signal_value)
288
+ results: List[PropagatedSignal] = []
289
+ visited: Set[str] = {source_key}
290
+
291
+ # BFS queue: (entity_key, current_strength, hop_count, path, edge_types)
292
+ queue: deque = deque()
293
+
294
+ # Seed the queue with direct neighbors
295
+ for target_key, edge_type, weight, decay in self._adjacency.get(source_key, []):
296
+ new_strength = abs_value * weight * (1.0 - decay)
297
+ if new_strength >= min_strength:
298
+ queue.append((
299
+ target_key,
300
+ new_strength,
301
+ 1,
302
+ [source_key, target_key],
303
+ [edge_type],
304
+ ))
305
+
306
+ while queue:
307
+ current_key, strength, hops, path, edge_types = queue.popleft()
308
+
309
+ if current_key in visited:
310
+ continue
311
+ visited.add(current_key)
312
+
313
+ # Record this affected entity
314
+ meta = self._entity_meta.get(current_key, {})
315
+ entity_name = meta.get("name", current_key)
316
+ reasoning = self._build_reasoning(
317
+ path, edge_types, strength, signal_description
318
+ )
319
+
320
+ results.append(PropagatedSignal(
321
+ entity=entity_name,
322
+ signal_strength=round(strength, 4),
323
+ hops=hops,
324
+ path=[self._entity_meta.get(k, {}).get("name", k) for k in path],
325
+ edge_types=list(edge_types),
326
+ source_signal=signal_description,
327
+ reasoning=reasoning,
328
+ ))
329
+
330
+ # Continue propagation if within hop limit
331
+ if hops < max_hops:
332
+ for next_key, edge_type, weight, decay in self._adjacency.get(current_key, []):
333
+ if next_key in visited:
334
+ continue
335
+ new_strength = strength * weight * (1.0 - decay)
336
+ if new_strength >= min_strength:
337
+ queue.append((
338
+ next_key,
339
+ new_strength,
340
+ hops + 1,
341
+ path + [next_key],
342
+ edge_types + [edge_type],
343
+ ))
344
+
345
+ # Sort by signal strength descending
346
+ results.sort(key=lambda s: s.signal_strength, reverse=True)
347
+ return results
348
+
349
+ # ------------------------------------------------------------------
350
+ # Dependency map
351
+ # ------------------------------------------------------------------
352
+
353
+ def get_dependency_map(self, entity: str) -> Dict[str, List[Dict[str, Any]]]:
354
+ """Return all dependencies for an entity.
355
+
356
+ Queries both forward and reverse adjacency lists to build a
357
+ complete picture of what the entity depends on, what depends on
358
+ it, its regulators, competitors, and macro factors.
359
+
360
+ Returns::
361
+
362
+ {
363
+ "depends_on": [{"entity": "crude_oil", "edge": "DEPENDS_ON", "weight": 0.9}],
364
+ "depended_by": [{"entity": "petrol_pump", "edge": "SUPPLIES_TO", "weight": 0.5}],
365
+ "regulators": [{"entity": "sebi", "edge": "REGULATED_BY", "weight": 0.8}],
366
+ "competitors": [{"entity": "ongc", "edge": "COMPETES_WITH", "weight": 0.7}],
367
+ "macro": [{"entity": "india_gdp", "edge": "IMPACTS", "weight": 0.6}],
368
+ }
369
+ """
370
+ entity_key = _entity_key(entity)
371
+ if entity_key not in self._entity_meta:
372
+ entity_key = self._resolve_entity(entity) or entity_key
373
+
374
+ dep_map: Dict[str, List[Dict[str, Any]]] = {
375
+ "depends_on": [],
376
+ "depended_by": [],
377
+ "regulators": [],
378
+ "competitors": [],
379
+ "macro": [],
380
+ }
381
+
382
+ # Categorize edge types
383
+ edge_category_map = {
384
+ "DEPENDS_ON": "depends_on",
385
+ "SUPPLIES_TO": "depends_on",
386
+ "PART_OF": "depends_on",
387
+ "REGULATED_BY": "regulators",
388
+ "COMPETES_WITH": "competitors",
389
+ "IMPACTS": "macro",
390
+ "AFFECTED_BY": "macro",
391
+ "DRIVES": "macro",
392
+ "CORRELATED_WITH": "macro",
393
+ "CONTAINS": "depends_on",
394
+ }
395
+
396
+ # Forward edges: what this entity connects to
397
+ for target_key, edge_type, weight, _decay in self._adjacency.get(entity_key, []):
398
+ target_name = self._entity_meta.get(target_key, {}).get("name", target_key)
399
+ category = edge_category_map.get(edge_type, "depends_on")
400
+ dep_map[category].append({
401
+ "entity": target_name,
402
+ "edge": edge_type,
403
+ "weight": round(weight, 2),
404
+ })
405
+
406
+ # Reverse edges: what connects to this entity
407
+ for source_key, edge_type, weight, _decay in self._reverse.get(entity_key, []):
408
+ source_name = self._entity_meta.get(source_key, {}).get("name", source_key)
409
+ dep_map["depended_by"].append({
410
+ "entity": source_name,
411
+ "edge": edge_type,
412
+ "weight": round(weight, 2),
413
+ })
414
+
415
+ return dep_map
416
+
417
+ # ------------------------------------------------------------------
418
+ # What-if analysis
419
+ # ------------------------------------------------------------------
420
+
421
+ def what_if(
422
+ self,
423
+ signal_description: str,
424
+ signal_value: float,
425
+ max_hops: int = 3,
426
+ min_strength: float = 0.1,
427
+ ) -> List[PropagatedSignal]:
428
+ """Given a hypothetical signal, show what would be affected.
429
+
430
+ Resolves the signal description to a source entity via text
431
+ matching against entity names in the dependency graph, then
432
+ propagates the signal.
433
+
434
+ Args:
435
+ signal_description: Natural language description (e.g.
436
+ "crude oil rises 10%").
437
+ signal_value: Signal strength (-1 to +1).
438
+ max_hops: Maximum traversal depth.
439
+ min_strength: Minimum signal threshold.
440
+
441
+ Returns:
442
+ List of PropagatedSignal sorted by strength descending.
443
+ Empty list if no source entity could be resolved.
444
+ """
445
+ source_key = self._resolve_from_text(signal_description)
446
+ if not source_key:
447
+ logger.warning(
448
+ "what_if: could not resolve source entity from '%s'",
449
+ signal_description[:100],
450
+ )
451
+ return []
452
+
453
+ source_name = self._entity_meta.get(source_key, {}).get("name", source_key)
454
+ return self.propagate(
455
+ source_entity=source_name,
456
+ signal_value=signal_value,
457
+ signal_description=signal_description,
458
+ max_hops=max_hops,
459
+ min_strength=min_strength,
460
+ )
461
+
462
+ # ------------------------------------------------------------------
463
+ # Stats
464
+ # ------------------------------------------------------------------
465
+
466
+ def stats(self) -> Dict[str, Any]:
467
+ """Return graph statistics."""
468
+ total_entities = len(self._entity_meta)
469
+ total_forward = sum(len(v) for v in self._adjacency.values())
470
+ total_reverse = sum(len(v) for v in self._reverse.values())
471
+ connected = sum(1 for k in self._entity_meta if k in self._adjacency or k in self._reverse)
472
+ avg_connectivity = (
473
+ (total_forward + total_reverse) / total_entities
474
+ if total_entities > 0
475
+ else 0.0
476
+ )
477
+
478
+ return {
479
+ "total_entities": total_entities,
480
+ "total_forward_edges": total_forward,
481
+ "total_reverse_edges": total_reverse,
482
+ "connected_entities": connected,
483
+ "isolated_entities": total_entities - connected,
484
+ "avg_connectivity": round(avg_connectivity, 2),
485
+ "built_at": self._built_at,
486
+ "build_time_ms": round(self._build_time_ms, 1),
487
+ }
488
+
489
+ # ------------------------------------------------------------------
490
+ # Internals
491
+ # ------------------------------------------------------------------
492
+
493
+ def _resolve_entity(self, entity_name: str) -> Optional[str]:
494
+ """Resolve entity name to a key via partial matching."""
495
+ lower = entity_name.lower().strip()
496
+ # Exact match
497
+ key = _entity_key(entity_name)
498
+ if key in self._entity_meta:
499
+ return key
500
+ # Substring match
501
+ for k, meta in self._entity_meta.items():
502
+ name = meta.get("name", "").lower()
503
+ if lower in name or name in lower:
504
+ return k
505
+ return None
506
+
507
+ def _resolve_from_text(self, text: str) -> Optional[str]:
508
+ """Find the best matching entity from a text description.
509
+
510
+ Scores each entity by how many of its name words appear in the
511
+ text. Returns the highest-scoring entity key.
512
+ """
513
+ lower_text = text.lower()
514
+ best_key: Optional[str] = None
515
+ best_score = 0
516
+
517
+ for key, meta in self._entity_meta.items():
518
+ name = meta.get("name", "").lower()
519
+ # Check if full name appears
520
+ if name in lower_text:
521
+ score = len(name) * 2
522
+ if score > best_score:
523
+ best_score = score
524
+ best_key = key
525
+ continue
526
+ # Check individual words
527
+ words = [w for w in name.split("_") if len(w) > 2]
528
+ if not words:
529
+ continue
530
+ hits = sum(1 for w in words if w in lower_text)
531
+ if hits > 0:
532
+ score = hits
533
+ if score > best_score:
534
+ best_score = score
535
+ best_key = key
536
+
537
+ return best_key
538
+
539
+ def _build_reasoning(
540
+ self,
541
+ path: List[str],
542
+ edge_types: List[str],
543
+ strength: float,
544
+ signal_description: str,
545
+ ) -> str:
546
+ """Build a human-readable reasoning string for a propagated signal."""
547
+ if not path or not edge_types:
548
+ return ""
549
+
550
+ parts = []
551
+ source_name = self._entity_meta.get(path[0], {}).get("name", path[0])
552
+
553
+ if signal_description:
554
+ parts.append(f"Signal: {signal_description}")
555
+
556
+ # Describe the traversal
557
+ for i, edge_type in enumerate(edge_types):
558
+ from_name = self._entity_meta.get(path[i], {}).get("name", path[i])
559
+ to_name = self._entity_meta.get(path[i + 1], {}).get("name", path[i + 1])
560
+ parts.append(f"{from_name} --{edge_type}--> {to_name}")
561
+
562
+ parts.append(f"Propagated strength: {strength:.2f}")
563
+
564
+ return " | ".join(parts)
565
+
566
+
567
+ # ---------------------------------------------------------------------------
568
+ # Helpers
569
+ # ---------------------------------------------------------------------------
570
+
571
+
572
+ def _entity_key(name: str) -> str:
573
+ """Normalize entity name to a stable lookup key."""
574
+ import re
575
+ key = name.lower().strip()
576
+ key = re.sub(r"[^a-z0-9]+", "_", key)
577
+ return key.strip("_") or "unknown"