conscio 2.2.0__tar.gz → 2.2.2__tar.gz

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 (249) hide show
  1. {conscio-2.2.0 → conscio-2.2.2}/CHANGELOG.md +40 -0
  2. {conscio-2.2.0/conscio.egg-info → conscio-2.2.2}/PKG-INFO +5 -3
  3. {conscio-2.2.0 → conscio-2.2.2}/README.md +4 -2
  4. {conscio-2.2.0 → conscio-2.2.2}/conscio/__init__.py +1 -1
  5. conscio-2.2.2/conscio/agency/trial.py +97 -0
  6. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/trust.py +6 -3
  7. {conscio-2.2.0 → conscio-2.2.2}/conscio/cli.py +64 -0
  8. {conscio-2.2.0 → conscio-2.2.2}/conscio/engine.py +63 -0
  9. conscio-2.2.2/conscio/noosphere/audit.py +223 -0
  10. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/cli.py +42 -2
  11. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/quarantine.py +67 -1
  12. conscio-2.2.2/conscio/noosphere/record.py +79 -0
  13. conscio-2.2.2/conscio/noosphere/record_catalog.py +126 -0
  14. conscio-2.2.2/conscio/noosphere/record_publish.py +72 -0
  15. {conscio-2.2.0 → conscio-2.2.2/conscio.egg-info}/PKG-INFO +5 -3
  16. {conscio-2.2.0 → conscio-2.2.2}/conscio.egg-info/SOURCES.txt +14 -0
  17. conscio-2.2.2/tests/test_agency_trial.py +107 -0
  18. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_trust.py +11 -0
  19. conscio-2.2.2/tests/test_cli_trial.py +55 -0
  20. conscio-2.2.2/tests/test_engine_trial.py +196 -0
  21. conscio-2.2.2/tests/test_noosphere_audit.py +121 -0
  22. conscio-2.2.2/tests/test_noosphere_audit_integration.py +60 -0
  23. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_cli.py +33 -0
  24. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_parity.py +9 -0
  25. conscio-2.2.2/tests/test_noosphere_record.py +41 -0
  26. conscio-2.2.2/tests/test_noosphere_record_catalog.py +42 -0
  27. conscio-2.2.2/tests/test_noosphere_record_publish.py +71 -0
  28. conscio-2.2.2/tests/test_quarantine_trial.py +109 -0
  29. {conscio-2.2.0 → conscio-2.2.2}/LICENSE +0 -0
  30. {conscio-2.2.0 → conscio-2.2.2}/MANIFEST.in +0 -0
  31. {conscio-2.2.0 → conscio-2.2.2}/conscio/__main__.py +0 -0
  32. {conscio-2.2.0 → conscio-2.2.2}/conscio/adapter_config.py +0 -0
  33. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/__init__.py +0 -0
  34. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/act.py +0 -0
  35. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/actor.py +0 -0
  36. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/adapter.py +0 -0
  37. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/adapters.py +0 -0
  38. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/breaker.py +0 -0
  39. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/contracts.py +0 -0
  40. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/fingerprint.py +0 -0
  41. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/gateway.py +0 -0
  42. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/grammar.py +0 -0
  43. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/host_act.py +0 -0
  44. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/ledger.py +0 -0
  45. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/loop.py +0 -0
  46. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/profiles.py +0 -0
  47. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/skeptic.py +0 -0
  48. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/skills.py +0 -0
  49. {conscio-2.2.0 → conscio-2.2.2}/conscio/agency/tools.py +0 -0
  50. {conscio-2.2.0 → conscio-2.2.2}/conscio/auto_evolution.py +0 -0
  51. {conscio-2.2.0 → conscio-2.2.2}/conscio/axis_pack.py +0 -0
  52. {conscio-2.2.0 → conscio-2.2.2}/conscio/bench.py +0 -0
  53. {conscio-2.2.0 → conscio-2.2.2}/conscio/coherence.py +0 -0
  54. {conscio-2.2.0 → conscio-2.2.2}/conscio/content_layer.py +0 -0
  55. {conscio-2.2.0 → conscio-2.2.2}/conscio/content_store.py +0 -0
  56. {conscio-2.2.0 → conscio-2.2.2}/conscio/context_manager.py +0 -0
  57. {conscio-2.2.0 → conscio-2.2.2}/conscio/daemon.py +0 -0
  58. {conscio-2.2.0 → conscio-2.2.2}/conscio/dreaming.py +0 -0
  59. {conscio-2.2.0 → conscio-2.2.2}/conscio/event_bus.py +0 -0
  60. {conscio-2.2.0 → conscio-2.2.2}/conscio/goal_generator.py +0 -0
  61. {conscio-2.2.0 → conscio-2.2.2}/conscio/guards.py +0 -0
  62. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/__init__.py +0 -0
  63. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/config.py +0 -0
  64. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/model_test.py +0 -0
  65. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/providers.py +0 -0
  66. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/server.py +0 -0
  67. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/static/app.js +0 -0
  68. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/static/index.html +0 -0
  69. {conscio-2.2.0 → conscio-2.2.2}/conscio/hub/static/style.css +0 -0
  70. {conscio-2.2.0 → conscio-2.2.2}/conscio/inner_monologue.py +0 -0
  71. {conscio-2.2.0 → conscio-2.2.2}/conscio/mcp/__init__.py +0 -0
  72. {conscio-2.2.0 → conscio-2.2.2}/conscio/mcp/jsonrpc.py +0 -0
  73. {conscio-2.2.0 → conscio-2.2.2}/conscio/mcp/protocol.py +0 -0
  74. {conscio-2.2.0 → conscio-2.2.2}/conscio/mcp/schemas.py +0 -0
  75. {conscio-2.2.0 → conscio-2.2.2}/conscio/mcp/seen.py +0 -0
  76. {conscio-2.2.0 → conscio-2.2.2}/conscio/mcp/server.py +0 -0
  77. {conscio-2.2.0 → conscio-2.2.2}/conscio/meta_cognition.py +0 -0
  78. {conscio-2.2.0 → conscio-2.2.2}/conscio/metabolic.py +0 -0
  79. {conscio-2.2.0 → conscio-2.2.2}/conscio/migrate.py +0 -0
  80. {conscio-2.2.0 → conscio-2.2.2}/conscio/models.py +0 -0
  81. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/__init__.py +0 -0
  82. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/artifact.py +0 -0
  83. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/catalog.py +0 -0
  84. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/identity.py +0 -0
  85. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/importer.py +0 -0
  86. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/paths.py +0 -0
  87. {conscio-2.2.0 → conscio-2.2.2}/conscio/noosphere/publish.py +0 -0
  88. {conscio-2.2.0 → conscio-2.2.2}/conscio/output_filter.py +0 -0
  89. {conscio-2.2.0 → conscio-2.2.2}/conscio/perception/__init__.py +0 -0
  90. {conscio-2.2.0 → conscio-2.2.2}/conscio/perception/agent_sensor.py +0 -0
  91. {conscio-2.2.0 → conscio-2.2.2}/conscio/perception/host_sensor.py +0 -0
  92. {conscio-2.2.0 → conscio-2.2.2}/conscio/perception/sensor.py +0 -0
  93. {conscio-2.2.0 → conscio-2.2.2}/conscio/plugins.py +0 -0
  94. {conscio-2.2.0 → conscio-2.2.2}/conscio/presets/__init__.py +0 -0
  95. {conscio-2.2.0 → conscio-2.2.2}/conscio/py.typed +0 -0
  96. {conscio-2.2.0 → conscio-2.2.2}/conscio/risk.py +0 -0
  97. {conscio-2.2.0 → conscio-2.2.2}/conscio/self_prompt.py +0 -0
  98. {conscio-2.2.0 → conscio-2.2.2}/conscio/semantic.py +0 -0
  99. {conscio-2.2.0 → conscio-2.2.2}/conscio/session_lifecycle.py +0 -0
  100. {conscio-2.2.0 → conscio-2.2.2}/conscio/session_rag.py +0 -0
  101. {conscio-2.2.0 → conscio-2.2.2}/conscio/session_rag_factory.py +0 -0
  102. {conscio-2.2.0 → conscio-2.2.2}/conscio/shard_engine.py +0 -0
  103. {conscio-2.2.0 → conscio-2.2.2}/conscio/structural.py +0 -0
  104. {conscio-2.2.0 → conscio-2.2.2}/conscio/structural_consent.py +0 -0
  105. {conscio-2.2.0 → conscio-2.2.2}/conscio/structural_drift.py +0 -0
  106. {conscio-2.2.0 → conscio-2.2.2}/conscio/timeutil.py +0 -0
  107. {conscio-2.2.0 → conscio-2.2.2}/conscio/token_tracker.py +0 -0
  108. {conscio-2.2.0 → conscio-2.2.2}/conscio/voice_preset.py +0 -0
  109. {conscio-2.2.0 → conscio-2.2.2}/conscio/workspace.py +0 -0
  110. {conscio-2.2.0 → conscio-2.2.2}/conscio/world_model.py +0 -0
  111. {conscio-2.2.0 → conscio-2.2.2}/conscio.egg-info/dependency_links.txt +0 -0
  112. {conscio-2.2.0 → conscio-2.2.2}/conscio.egg-info/entry_points.txt +0 -0
  113. {conscio-2.2.0 → conscio-2.2.2}/conscio.egg-info/requires.txt +0 -0
  114. {conscio-2.2.0 → conscio-2.2.2}/conscio.egg-info/top_level.txt +0 -0
  115. {conscio-2.2.0 → conscio-2.2.2}/pyproject.toml +0 -0
  116. {conscio-2.2.0 → conscio-2.2.2}/setup.cfg +0 -0
  117. {conscio-2.2.0 → conscio-2.2.2}/tests/test_adapter_config.py +0 -0
  118. {conscio-2.2.0 → conscio-2.2.2}/tests/test_adapter_config_api_key_env.py +0 -0
  119. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_act.py +0 -0
  120. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_act_immunity.py +0 -0
  121. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_actor.py +0 -0
  122. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_adapter.py +0 -0
  123. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_adapters_http.py +0 -0
  124. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_adversarial.py +0 -0
  125. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_arbiter.py +0 -0
  126. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_bench.py +0 -0
  127. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_breaker.py +0 -0
  128. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_contracts.py +0 -0
  129. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_engine_immunity.py +0 -0
  130. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_gateway.py +0 -0
  131. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_grammar.py +0 -0
  132. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_host_act.py +0 -0
  133. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_ledger.py +0 -0
  134. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_ledger_v201.py +0 -0
  135. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_loop.py +0 -0
  136. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_no_network.py +0 -0
  137. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_profiles.py +0 -0
  138. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_skeptic.py +0 -0
  139. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_skills.py +0 -0
  140. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_skills_wiring.py +0 -0
  141. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_state.py +0 -0
  142. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_tools.py +0 -0
  143. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_tools_manifest.py +0 -0
  144. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agency_volition.py +0 -0
  145. {conscio-2.2.0 → conscio-2.2.2}/tests/test_agent_sensor.py +0 -0
  146. {conscio-2.2.0 → conscio-2.2.2}/tests/test_auto_evolution.py +0 -0
  147. {conscio-2.2.0 → conscio-2.2.2}/tests/test_awake.py +0 -0
  148. {conscio-2.2.0 → conscio-2.2.2}/tests/test_axis_pack.py +0 -0
  149. {conscio-2.2.0 → conscio-2.2.2}/tests/test_axis_pack_battery.py +0 -0
  150. {conscio-2.2.0 → conscio-2.2.2}/tests/test_cli.py +0 -0
  151. {conscio-2.2.0 → conscio-2.2.2}/tests/test_coherence.py +0 -0
  152. {conscio-2.2.0 → conscio-2.2.2}/tests/test_coherence_engine_integration.py +0 -0
  153. {conscio-2.2.0 → conscio-2.2.2}/tests/test_coherence_state.py +0 -0
  154. {conscio-2.2.0 → conscio-2.2.2}/tests/test_consciousness.py +0 -0
  155. {conscio-2.2.0 → conscio-2.2.2}/tests/test_content_layer.py +0 -0
  156. {conscio-2.2.0 → conscio-2.2.2}/tests/test_content_layer_manager.py +0 -0
  157. {conscio-2.2.0 → conscio-2.2.2}/tests/test_content_store.py +0 -0
  158. {conscio-2.2.0 → conscio-2.2.2}/tests/test_content_store_battery.py +0 -0
  159. {conscio-2.2.0 → conscio-2.2.2}/tests/test_content_store_r05.py +0 -0
  160. {conscio-2.2.0 → conscio-2.2.2}/tests/test_contradiction_detector.py +0 -0
  161. {conscio-2.2.0 → conscio-2.2.2}/tests/test_daemon.py +0 -0
  162. {conscio-2.2.0 → conscio-2.2.2}/tests/test_daemon_battery.py +0 -0
  163. {conscio-2.2.0 → conscio-2.2.2}/tests/test_daemon_config.py +0 -0
  164. {conscio-2.2.0 → conscio-2.2.2}/tests/test_daemon_heartbeat.py +0 -0
  165. {conscio-2.2.0 → conscio-2.2.2}/tests/test_daemon_structure_sync.py +0 -0
  166. {conscio-2.2.0 → conscio-2.2.2}/tests/test_dream_coherence.py +0 -0
  167. {conscio-2.2.0 → conscio-2.2.2}/tests/test_dream_distill.py +0 -0
  168. {conscio-2.2.0 → conscio-2.2.2}/tests/test_dream_reconcile.py +0 -0
  169. {conscio-2.2.0 → conscio-2.2.2}/tests/test_dreaming.py +0 -0
  170. {conscio-2.2.0 → conscio-2.2.2}/tests/test_dreaming_friction.py +0 -0
  171. {conscio-2.2.0 → conscio-2.2.2}/tests/test_durable_guards.py +0 -0
  172. {conscio-2.2.0 → conscio-2.2.2}/tests/test_embedder.py +0 -0
  173. {conscio-2.2.0 → conscio-2.2.2}/tests/test_engine_advisory.py +0 -0
  174. {conscio-2.2.0 → conscio-2.2.2}/tests/test_engine_host_act.py +0 -0
  175. {conscio-2.2.0 → conscio-2.2.2}/tests/test_engine_init.py +0 -0
  176. {conscio-2.2.0 → conscio-2.2.2}/tests/test_engine_meta_reflect.py +0 -0
  177. {conscio-2.2.0 → conscio-2.2.2}/tests/test_engine_propose.py +0 -0
  178. {conscio-2.2.0 → conscio-2.2.2}/tests/test_engine_recall.py +0 -0
  179. {conscio-2.2.0 → conscio-2.2.2}/tests/test_event_bus.py +0 -0
  180. {conscio-2.2.0 → conscio-2.2.2}/tests/test_event_bus_act_result.py +0 -0
  181. {conscio-2.2.0 → conscio-2.2.2}/tests/test_event_bus_purge.py +0 -0
  182. {conscio-2.2.0 → conscio-2.2.2}/tests/test_examples.py +0 -0
  183. {conscio-2.2.0 → conscio-2.2.2}/tests/test_goal_provenance.py +0 -0
  184. {conscio-2.2.0 → conscio-2.2.2}/tests/test_goal_source.py +0 -0
  185. {conscio-2.2.0 → conscio-2.2.2}/tests/test_host_sensor.py +0 -0
  186. {conscio-2.2.0 → conscio-2.2.2}/tests/test_hub_config.py +0 -0
  187. {conscio-2.2.0 → conscio-2.2.2}/tests/test_hub_model_test.py +0 -0
  188. {conscio-2.2.0 → conscio-2.2.2}/tests/test_hub_providers.py +0 -0
  189. {conscio-2.2.0 → conscio-2.2.2}/tests/test_hub_server.py +0 -0
  190. {conscio-2.2.0 → conscio-2.2.2}/tests/test_loop_failure_brake.py +0 -0
  191. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_adapter_parity.py +0 -0
  192. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_battery.py +0 -0
  193. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_fuzz.py +0 -0
  194. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_jsonrpc.py +0 -0
  195. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_package.py +0 -0
  196. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_protocol.py +0 -0
  197. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_schemas.py +0 -0
  198. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_seen.py +0 -0
  199. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_server.py +0 -0
  200. {conscio-2.2.0 → conscio-2.2.2}/tests/test_mcp_server_cli.py +0 -0
  201. {conscio-2.2.0 → conscio-2.2.2}/tests/test_metabolic.py +0 -0
  202. {conscio-2.2.0 → conscio-2.2.2}/tests/test_migrate.py +0 -0
  203. {conscio-2.2.0 → conscio-2.2.2}/tests/test_model_auto_detect.py +0 -0
  204. {conscio-2.2.0 → conscio-2.2.2}/tests/test_model_offline_default.py +0 -0
  205. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_artifact.py +0 -0
  206. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_catalog.py +0 -0
  207. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_engine_free.py +0 -0
  208. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_fingerprint.py +0 -0
  209. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_identity.py +0 -0
  210. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_importer.py +0 -0
  211. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_integration.py +0 -0
  212. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_paths.py +0 -0
  213. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_publish.py +0 -0
  214. {conscio-2.2.0 → conscio-2.2.2}/tests/test_noosphere_quarantine.py +0 -0
  215. {conscio-2.2.0 → conscio-2.2.2}/tests/test_ontological_semantic.py +0 -0
  216. {conscio-2.2.0 → conscio-2.2.2}/tests/test_output_filter.py +0 -0
  217. {conscio-2.2.0 → conscio-2.2.2}/tests/test_output_filter_stages.py +0 -0
  218. {conscio-2.2.0 → conscio-2.2.2}/tests/test_packaging.py +0 -0
  219. {conscio-2.2.0 → conscio-2.2.2}/tests/test_perception.py +0 -0
  220. {conscio-2.2.0 → conscio-2.2.2}/tests/test_perf_reflection.py +0 -0
  221. {conscio-2.2.0 → conscio-2.2.2}/tests/test_plugins.py +0 -0
  222. {conscio-2.2.0 → conscio-2.2.2}/tests/test_recursive_loop_integration.py +0 -0
  223. {conscio-2.2.0 → conscio-2.2.2}/tests/test_risk.py +0 -0
  224. {conscio-2.2.0 → conscio-2.2.2}/tests/test_self_prompt.py +0 -0
  225. {conscio-2.2.0 → conscio-2.2.2}/tests/test_self_prompt_state.py +0 -0
  226. {conscio-2.2.0 → conscio-2.2.2}/tests/test_semantic_dedup.py +0 -0
  227. {conscio-2.2.0 → conscio-2.2.2}/tests/test_semantic_engine.py +0 -0
  228. {conscio-2.2.0 → conscio-2.2.2}/tests/test_semantic_reconcile_integration.py +0 -0
  229. {conscio-2.2.0 → conscio-2.2.2}/tests/test_session_lifecycle.py +0 -0
  230. {conscio-2.2.0 → conscio-2.2.2}/tests/test_session_lifecycle_battery.py +0 -0
  231. {conscio-2.2.0 → conscio-2.2.2}/tests/test_session_lifecycle_dream.py +0 -0
  232. {conscio-2.2.0 → conscio-2.2.2}/tests/test_session_rag.py +0 -0
  233. {conscio-2.2.0 → conscio-2.2.2}/tests/test_shard_engine.py +0 -0
  234. {conscio-2.2.0 → conscio-2.2.2}/tests/test_state_loaders_battery.py +0 -0
  235. {conscio-2.2.0 → conscio-2.2.2}/tests/test_state_persistence_battery.py +0 -0
  236. {conscio-2.2.0 → conscio-2.2.2}/tests/test_structural.py +0 -0
  237. {conscio-2.2.0 → conscio-2.2.2}/tests/test_structural_consent.py +0 -0
  238. {conscio-2.2.0 → conscio-2.2.2}/tests/test_structural_drift.py +0 -0
  239. {conscio-2.2.0 → conscio-2.2.2}/tests/test_structural_inject.py +0 -0
  240. {conscio-2.2.0 → conscio-2.2.2}/tests/test_timeutil.py +0 -0
  241. {conscio-2.2.0 → conscio-2.2.2}/tests/test_token_tracker.py +0 -0
  242. {conscio-2.2.0 → conscio-2.2.2}/tests/test_trajectory_vector.py +0 -0
  243. {conscio-2.2.0 → conscio-2.2.2}/tests/test_v2_debt_zero.py +0 -0
  244. {conscio-2.2.0 → conscio-2.2.2}/tests/test_voice_preset.py +0 -0
  245. {conscio-2.2.0 → conscio-2.2.2}/tests/test_workspace.py +0 -0
  246. {conscio-2.2.0 → conscio-2.2.2}/tests/test_world_contradictions.py +0 -0
  247. {conscio-2.2.0 → conscio-2.2.2}/tests/test_world_model_entropy.py +0 -0
  248. {conscio-2.2.0 → conscio-2.2.2}/tests/test_world_model_prediction.py +0 -0
  249. {conscio-2.2.0 → conscio-2.2.2}/tests/test_world_model_prune.py +0 -0
@@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [2.2.2] - 2026-06-22 — "Trial / execution path"
11
+
12
+ ### Added
13
+ - **Sandboxed trial of a quarantined skill.** A quarantined imported skill can
14
+ now be replayed in a **throwaway, fs-only sandbox** to earn local,
15
+ execution-grade pass/fail stats — `conscio trial --storage DIR --quarantine
16
+ ROWID --model NAME --enable-trial`. The foreign plan's fixed steps run through
17
+ the full safety stack (`validate → precheck → HIGH-block → Skeptic → dispatch`)
18
+ against a `make_default_registry` confined to a `mkdtemp` dir (`fs_read`/
19
+ `fs_write` only), stopping at the first failure. Binary outcome
20
+ (`trial_successes`/`trial_failures` + `last_trial_*`) is recorded on the
21
+ quarantine row; v2.3 promotion will read it.
22
+ - **Trial isolation.** A trial never writes the agent's `ActionLedger`, `skills`
23
+ table, `TrustMatrix`, or trips the breaker — a foreign skill's failure cannot
24
+ dent the local agent. The sandbox dir is always removed; tamper / corrupt-plan
25
+ refuse **without** bumping any counter.
26
+ - **Opt-in, default off.** `--enable-trial` is required to dispatch and is
27
+ independent of `--enable-act` (trial uses the local sandboxed registry, never
28
+ `host_act`). Skeptic always audits foreign content (no LOW-risk fast path).
29
+ - New engine method `ConsciousnessEngine.trial_quarantined(rowid, *,
30
+ enable_trial=False)`; new `conscio/agency/trial.py` (engine-side mechanic,
31
+ imports nothing from `noosphere`); `noosphere/quarantine.py` gains 5 trial
32
+ columns + an idempotent `PRAGMA table_info` migration + `record_trial` /
33
+ `note_trial` (still engine-free). Purely additive; cognition untouched.
34
+
35
+ ## [2.2.1] - 2026-06-22 — "Mutual audit"
36
+
37
+ ### Added
38
+ - **Noosphere mutual audit.** An instance can publish a non-sensitive
39
+ projection of its action ledger (`conscio noosphere publish-record`) to the
40
+ host-shared `noosphere.db`, and a peer can independently audit it
41
+ (`conscio noosphere audit`) — deterministic, read-only, engine-free. The
42
+ auditor re-derives track-record, breaker quarantines, and a foreign-trust
43
+ level under its OWN thresholds (parity-tested against the engine), and runs
44
+ a discipline check (did the peer execute actions its own Skeptic FAILed?).
45
+ No inherited trust; report-only; the auditor persists nothing. The LLM
46
+ Skeptic replay is deferred to a later slice.
47
+
48
+ ---
49
+
10
50
  ## [2.2.0] - 2026-06-22 — "Society" (Noosphere Core)
11
51
 
12
52
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conscio
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Self-awareness framework for AI agents — emergent consciousness via context-aware memory, introspection, and goal generation
5
5
  Author-email: Neguiolidas <neguitech@proton.me>
6
6
  License: MIT
@@ -46,8 +46,10 @@ nothing else). It is designed to make small, local models punch far above their
46
46
  size by giving them memory, self-judgment, and procedural skill — and to prove
47
47
  that claim by measurement, not assertion.
48
48
 
49
- - **Current release:** `v2.2.0` — "Society" (Noosphere Core): same-host Conscio instances **share locally-proven skills as data**. `conscio noosphere publish` copies your proven skills (stats stripped) into a host-shared `noosphere.db`; `conscio noosphere import` pulls another instance's skills into a local **quarantine** after execution-free static revalidation. Engine-free; opens your live `conscio.db` **read-only**; zero network/socket. Nothing imported is trusted, served, executed, or promoted trust is never inherited. `pip install conscio`.
50
- - **Prior:** `v2.1.0` — "Hub": a **localhost stdlib HTTP control plane** (`conscio-hub`) to swap the active model/provider and register custom OpenAI-compatible providers without hand-editing JSON. Engine-free; config applies on next boot. Per-provider model auto-discovery; one-shot smoke test before save. `api_key_env` resolution (env var name value at adapter build time) is now additive to raw `api_key` daemon + MCP inherit it. Hub never returns a raw API key.
49
+ - **Current release:** `v2.2.2` — "Trial / execution path": a quarantined imported skill can now **prove itself locally** before any promotion. `conscio trial --quarantine ROWID --enable-trial` replays the foreign plan's fixed steps in a **throwaway, fs-only sandbox** through the full safety stack (`validate precheck HIGH-block Skeptic dispatch`), recording a binary pass/fail on the quarantine row. Fully **isolated** never writes the live agent's ledger/skills/trust/breaker; tamper refuses without counting. Off by default; independent of `--enable-act`. `pip install conscio`.
50
+ - **Prior:** `v2.2.1` — "Mutual audit": an instance publishes a non-sensitive projection of its action ledger (`conscio noosphere publish-record`) to the host-shared `noosphere.db`, and a peer **independently audits** it (`conscio noosphere audit`) deterministic, read-only, engine-free. The auditor re-derives track-record, breaker quarantines, and a foreign-trust level under its **own** thresholds (parity-tested against the engine) and runs a discipline check (did the peer execute actions its own Skeptic FAILed?). No inherited trust; report-only; the auditor persists nothing.
51
+ - **Earlier:** `v2.2.0` — "Society" (Noosphere Core): same-host Conscio instances **share locally-proven skills as data**. `conscio noosphere publish` copies your proven skills (stats stripped) into a host-shared `noosphere.db`; `conscio noosphere import` pulls another instance's skills into a local **quarantine** after execution-free static revalidation. Engine-free; opens your live `conscio.db` **read-only**; zero network/socket. Nothing imported is trusted, served, executed, or promoted — trust is never inherited.
52
+ - **Earlier:** `v2.1.0` — "Hub": a **localhost stdlib HTTP control plane** (`conscio-hub`) to swap the active model/provider and register custom OpenAI-compatible providers without hand-editing JSON. Engine-free; config applies on next boot. Per-provider model auto-discovery; one-shot smoke test before save. `api_key_env` resolution (env var name → value at adapter build time) is now additive to raw `api_key` — daemon + MCP inherit it. Hub never returns a raw API key.
51
53
  - **Earlier:** `v2.0.1` — "Connect" continued: **opt-in, host-executed audited `act` over MCP**. Conscio audits + gates + ledgers an action and returns an *execution packet*; the **host** executes and reports the outcome back — Conscio still never touches the world. Off by default (`conscio-mcp --enable-act`, requires the engine **Awake**); the host declares its tool manifest (`name`/`params`/`risk`/`approval_policy`) in `initialize`; HIGH-risk / `require_approval` actions stay **queued for human/Hermes approval** (`conscio.pending` → `conscio.approve`). Also: `conscio-mcp` adapter parity (six providers from config) and the **R-05** content-store dedup fix — shipping **debt-zero**. Cognition (`reflect()`) untouched; purely additive.
52
54
  - **Earlier:** `v2.0.0` — "Connect", the **Embodiment** phase: Conscio becomes embeddable in **any** MCP host (CLI, IDE, agent) via a hand-rolled **stdlib-only** MCP stdio server (`conscio-mcp`, newline-delimited JSON-RPC 2.0). Zero new runtime dependency; nothing opens a socket. The v2.0.0 surface was **propose-only** — perceive, reflect, recall, and **audit**, but never execute. Cognition (`reflect()`) untouched; the public API unchanged (MCP purely additive).
53
55
 
@@ -11,8 +11,10 @@ nothing else). It is designed to make small, local models punch far above their
11
11
  size by giving them memory, self-judgment, and procedural skill — and to prove
12
12
  that claim by measurement, not assertion.
13
13
 
14
- - **Current release:** `v2.2.0` — "Society" (Noosphere Core): same-host Conscio instances **share locally-proven skills as data**. `conscio noosphere publish` copies your proven skills (stats stripped) into a host-shared `noosphere.db`; `conscio noosphere import` pulls another instance's skills into a local **quarantine** after execution-free static revalidation. Engine-free; opens your live `conscio.db` **read-only**; zero network/socket. Nothing imported is trusted, served, executed, or promoted trust is never inherited. `pip install conscio`.
15
- - **Prior:** `v2.1.0` — "Hub": a **localhost stdlib HTTP control plane** (`conscio-hub`) to swap the active model/provider and register custom OpenAI-compatible providers without hand-editing JSON. Engine-free; config applies on next boot. Per-provider model auto-discovery; one-shot smoke test before save. `api_key_env` resolution (env var name value at adapter build time) is now additive to raw `api_key` daemon + MCP inherit it. Hub never returns a raw API key.
14
+ - **Current release:** `v2.2.2` — "Trial / execution path": a quarantined imported skill can now **prove itself locally** before any promotion. `conscio trial --quarantine ROWID --enable-trial` replays the foreign plan's fixed steps in a **throwaway, fs-only sandbox** through the full safety stack (`validate precheck HIGH-block Skeptic dispatch`), recording a binary pass/fail on the quarantine row. Fully **isolated** never writes the live agent's ledger/skills/trust/breaker; tamper refuses without counting. Off by default; independent of `--enable-act`. `pip install conscio`.
15
+ - **Prior:** `v2.2.1` — "Mutual audit": an instance publishes a non-sensitive projection of its action ledger (`conscio noosphere publish-record`) to the host-shared `noosphere.db`, and a peer **independently audits** it (`conscio noosphere audit`) deterministic, read-only, engine-free. The auditor re-derives track-record, breaker quarantines, and a foreign-trust level under its **own** thresholds (parity-tested against the engine) and runs a discipline check (did the peer execute actions its own Skeptic FAILed?). No inherited trust; report-only; the auditor persists nothing.
16
+ - **Earlier:** `v2.2.0` — "Society" (Noosphere Core): same-host Conscio instances **share locally-proven skills as data**. `conscio noosphere publish` copies your proven skills (stats stripped) into a host-shared `noosphere.db`; `conscio noosphere import` pulls another instance's skills into a local **quarantine** after execution-free static revalidation. Engine-free; opens your live `conscio.db` **read-only**; zero network/socket. Nothing imported is trusted, served, executed, or promoted — trust is never inherited.
17
+ - **Earlier:** `v2.1.0` — "Hub": a **localhost stdlib HTTP control plane** (`conscio-hub`) to swap the active model/provider and register custom OpenAI-compatible providers without hand-editing JSON. Engine-free; config applies on next boot. Per-provider model auto-discovery; one-shot smoke test before save. `api_key_env` resolution (env var name → value at adapter build time) is now additive to raw `api_key` — daemon + MCP inherit it. Hub never returns a raw API key.
16
18
  - **Earlier:** `v2.0.1` — "Connect" continued: **opt-in, host-executed audited `act` over MCP**. Conscio audits + gates + ledgers an action and returns an *execution packet*; the **host** executes and reports the outcome back — Conscio still never touches the world. Off by default (`conscio-mcp --enable-act`, requires the engine **Awake**); the host declares its tool manifest (`name`/`params`/`risk`/`approval_policy`) in `initialize`; HIGH-risk / `require_approval` actions stay **queued for human/Hermes approval** (`conscio.pending` → `conscio.approve`). Also: `conscio-mcp` adapter parity (six providers from config) and the **R-05** content-store dedup fix — shipping **debt-zero**. Cognition (`reflect()`) untouched; purely additive.
17
19
  - **Earlier:** `v2.0.0` — "Connect", the **Embodiment** phase: Conscio becomes embeddable in **any** MCP host (CLI, IDE, agent) via a hand-rolled **stdlib-only** MCP stdio server (`conscio-mcp`, newline-delimited JSON-RPC 2.0). Zero new runtime dependency; nothing opens a socket. The v2.0.0 surface was **propose-only** — perceive, reflect, recall, and **audit**, but never execute. Cognition (`reflect()`) untouched; the public API unchanged (MCP purely additive).
18
20
 
@@ -6,7 +6,7 @@ and goal generation. Adapts behavior based on the underlying model's
6
6
  context window size.
7
7
  """
8
8
 
9
- __version__ = "2.2.0"
9
+ __version__ = "2.2.2"
10
10
  __author__ = "Neguiolidas / Neguitech"
11
11
 
12
12
  from .engine import ConsciousnessEngine
@@ -0,0 +1,97 @@
1
+ # conscio/agency/trial.py
2
+ """Trial replay of a quarantined foreign skill (v2.2.2).
3
+
4
+ A pure mechanic: replay fixed foreign plan steps through the existing safety
5
+ stack (validate -> precheck -> HIGH-block -> Skeptic -> dispatch) against an
6
+ INJECTED sandboxed registry, stopping at the first failure. Records nothing,
7
+ imports nothing from conscio.noosphere or conscio.engine. The caller (the
8
+ engine) owns the sandbox lifecycle, the tamper guard, and persistence, and
9
+ guarantees trial isolation (no agent ledger/skills/trust/breaker writes)."""
10
+ from __future__ import annotations
11
+
12
+ from dataclasses import dataclass
13
+ from typing import Any
14
+
15
+ from .contracts import ActionProposal, validate
16
+ from .tools import Risk
17
+
18
+ # stage -> the word used in TrialOutcome.result
19
+ _RESULT_WORD = {
20
+ "unknown_tool": "unknown_tool",
21
+ "invalid_args": "invalid_args",
22
+ "precheck": "precheck",
23
+ "high_risk": "high_risk_blocked",
24
+ "skeptic": "skeptic_reject",
25
+ "exec": "exec_fail",
26
+ }
27
+
28
+
29
+ @dataclass(frozen=True)
30
+ class StepResult:
31
+ tool: str
32
+ ok: bool
33
+ stage: str # unknown_tool|invalid_args|precheck|high_risk|skeptic|exec|ok
34
+ error: str = ""
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class TrialOutcome:
39
+ passed: bool
40
+ result: str # "passed" or "<word>:<tool>"
41
+ error: str
42
+ steps: list[StepResult] # always supplied explicitly by run_trial
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class TrialRefusal:
47
+ reason: str
48
+
49
+
50
+ def run_trial(steps: list[dict], *, goal_text: str, skeptic: Any,
51
+ registry: Any) -> TrialOutcome:
52
+ done: list[StepResult] = []
53
+ for step in steps:
54
+ tool = str(step.get("tool", ""))
55
+ args = step.get("args", {})
56
+ rationale = str(step.get("rationale", ""))
57
+ # Foreign steps carry no expected_outcome; the Skeptic tolerates "".
58
+ proposal = ActionProposal(tool=tool, args=args, rationale=rationale,
59
+ expected_outcome="")
60
+ spec = registry.get(tool)
61
+ if spec is None:
62
+ done.append(StepResult(tool, False, "unknown_tool",
63
+ f"tool '{tool}' not registered"))
64
+ break
65
+ errs = (validate(args, spec.params) if isinstance(args, dict)
66
+ else ["args must be a dict"])
67
+ if errs:
68
+ done.append(StepResult(tool, False, "invalid_args",
69
+ "; ".join(errs)))
70
+ break
71
+ if spec.precheck is not None:
72
+ pre = spec.precheck(args)
73
+ if pre:
74
+ done.append(StepResult(tool, False, "precheck", str(pre)))
75
+ break
76
+ if spec.risk is Risk.HIGH:
77
+ done.append(StepResult(tool, False, "high_risk",
78
+ "HIGH-risk tool blocked in trial"))
79
+ break
80
+ verdict = skeptic.audit(proposal, goal_text=goal_text) # forced audit
81
+ if not verdict.passed:
82
+ done.append(StepResult(tool, False, "skeptic",
83
+ "; ".join(verdict.reasons)))
84
+ break
85
+ res = registry.dispatch(tool, args)
86
+ if not res.ok:
87
+ done.append(StepResult(tool, False, "exec", res.error))
88
+ break
89
+ done.append(StepResult(tool, True, "ok"))
90
+
91
+ passed = bool(done) and len(done) == len(steps) and all(s.ok for s in done)
92
+ if passed:
93
+ return TrialOutcome(True, "passed", "", done)
94
+ last = done[-1] if done else StepResult("", False, "empty", "no steps")
95
+ word = _RESULT_WORD.get(last.stage, last.stage)
96
+ result = f"{word}:{last.tool}" if last.tool else word
97
+ return TrialOutcome(False, result, last.error, done)
@@ -18,6 +18,9 @@ PROBATION_EPOCH = 25 # reflect() cycles between probation probes
18
18
  WARMUP_MIN_ROWS = 10 # below this many ledger rows the floor of 1 applies
19
19
  RETRY_CEILING = 4
20
20
  AUTONOMY_WINDOW = 50 # recent actions; zero trips inside it for L3
21
+ L2_ACCURACY = 0.7 # autonomy_level L2 gate (mirrored by noosphere audit)
22
+ L3_ACCURACY = 0.85 # autonomy_level L3 gate (mirrored by noosphere audit)
23
+ AUTONOMY_MIN_ROWS = 10 # min per-task ledger rows for L2+ (≠ WARMUP_MIN_ROWS)
21
24
 
22
25
  _SCHEMA = """
23
26
  CREATE TABLE IF NOT EXISTS trust_probation (
@@ -86,10 +89,10 @@ class TrustMatrix:
86
89
  def autonomy_level(self, task_type: str) -> int:
87
90
  calibration = self.meta.calibration_score()
88
91
  accuracy = self.meta.accuracy(task_type)
89
- if not (calibration >= 0.6 and accuracy >= 0.7
90
- and self.ledger.count(task_type) >= 10):
92
+ if not (calibration >= 0.6 and accuracy >= L2_ACCURACY
93
+ and self.ledger.count(task_type) >= AUTONOMY_MIN_ROWS):
91
94
  return 1
92
- if (calibration >= 0.75 and accuracy >= 0.85
95
+ if (calibration >= 0.75 and accuracy >= L3_ACCURACY
93
96
  and self._recent_trips() == 0):
94
97
  return 3
95
98
  return 2
@@ -68,6 +68,18 @@ def _build_parser() -> argparse.ArgumentParser:
68
68
  p_sleep.add_argument("--model", default=DEFAULT_MODEL)
69
69
  p_sleep.add_argument("--storage", default="", help="storage dir (default: temp)")
70
70
 
71
+ p_trial = sub.add_parser(
72
+ "trial",
73
+ help="trial a quarantined imported skill in a throwaway sandbox")
74
+ p_trial.add_argument("--storage", default="",
75
+ help="instance storage dir (default: ~/.hermes)")
76
+ p_trial.add_argument("--quarantine", type=int, required=True,
77
+ metavar="ROWID", help="quarantine row id to trial")
78
+ p_trial.add_argument("--model", default=DEFAULT_MODEL)
79
+ p_trial.add_argument(
80
+ "--enable-trial", action="store_true",
81
+ help="required: actually run the sandboxed trial (off by default)")
82
+
71
83
  # Listed for discoverability; routed to conscio.{bench,daemon} before argparse.
72
84
  sub.add_parser("bench", add_help=False,
73
85
  help="measure an inference backend (see: conscio bench --help)")
@@ -231,6 +243,55 @@ def _cmd_structure(storage: str) -> int:
231
243
  return 0
232
244
 
233
245
 
246
+ def _run_trial(*, model: str, storage: str, quarantine_id: int,
247
+ enable_trial: bool):
248
+ """Build an engine with an adapter and run one trial. The single seam the
249
+ CLI tests monkeypatch (so they never build a real adapter)."""
250
+ from .adapter_config import build_adapter_from_config, load_config
251
+ from .engine import ConsciousnessEngine
252
+ eng = ConsciousnessEngine(model_name=model, storage_path=_storage(storage))
253
+ try:
254
+ adapter, _ = build_adapter_from_config(load_config(),
255
+ fallback_model=model)
256
+ eng.attach_adapter(adapter)
257
+ return eng.trial_quarantined(quarantine_id, enable_trial=enable_trial)
258
+ finally:
259
+ eng.close()
260
+
261
+
262
+ def _cmd_trial(model: str, storage: str, quarantine_id: int,
263
+ enable_trial: bool) -> int:
264
+ from .agency.trial import TrialRefusal
265
+ try:
266
+ outcome = _run_trial(model=model, storage=storage,
267
+ quarantine_id=quarantine_id,
268
+ enable_trial=enable_trial)
269
+ except Exception as exc: # adapter build / engine wiring failure
270
+ print(f"error: {exc}")
271
+ return 1
272
+ if isinstance(outcome, TrialRefusal):
273
+ print(f"error: {outcome.reason}")
274
+ return 1
275
+ if outcome.passed:
276
+ print(f"TRIAL PASSED (#{quarantine_id})")
277
+ else:
278
+ print(f"TRIAL FAILED (#{quarantine_id}): {outcome.result}")
279
+ if outcome.error:
280
+ print(f" {outcome.error}")
281
+ # best-effort: show the running counts (skipped if the row can't be read)
282
+ try:
283
+ from .noosphere import quarantine
284
+ from .noosphere.paths import quarantine_db_path
285
+ row = quarantine.get(quarantine_db_path(Path(_storage(storage))),
286
+ quarantine_id)
287
+ if row is not None:
288
+ print(f" trials: {row.trial_successes} passed / "
289
+ f"{row.trial_failures} failed")
290
+ except Exception:
291
+ pass
292
+ return 0
293
+
294
+
234
295
  def main(argv: list[str] | None = None) -> int:
235
296
  argv = list(sys.argv[1:] if argv is None else argv)
236
297
 
@@ -266,6 +327,9 @@ def main(argv: list[str] | None = None) -> int:
266
327
  return _cmd_set_awake(args.model, args.storage, awake=True)
267
328
  if args.command == "sleep":
268
329
  return _cmd_set_awake(args.model, args.storage, awake=False)
330
+ if args.command == "trial":
331
+ return _cmd_trial(args.model, args.storage, args.quarantine,
332
+ args.enable_trial)
269
333
 
270
334
  parser.print_help()
271
335
  return 2
@@ -1001,6 +1001,69 @@ class ConsciousnessEngine:
1001
1001
  return []
1002
1002
  return self._act_pipeline.ledger.pending(limit)
1003
1003
 
1004
+ # --- v2.2.2 "Trial": sandboxed replay of a quarantined foreign skill ---
1005
+
1006
+ def trial_quarantined(self, rowid: int, *, enable_trial: bool = False):
1007
+ """Replay a quarantined foreign skill in a throwaway fs-only sandbox
1008
+ and record a binary pass/fail on its quarantine row. Fully isolated —
1009
+ never writes the agent's ledger/skills/trust/breaker. Default off.
1010
+
1011
+ Returns a trial.TrialOutcome (ran) or trial.TrialRefusal (refused)."""
1012
+ import json
1013
+ import shutil
1014
+ import tempfile
1015
+ import time
1016
+ from pathlib import Path
1017
+
1018
+ from .agency import trial as trial_mod
1019
+ from .agency.tools import make_default_registry
1020
+ from .noosphere import artifact, quarantine
1021
+ from .noosphere.paths import quarantine_db_path
1022
+
1023
+ if not enable_trial:
1024
+ return trial_mod.TrialRefusal("trial disabled; pass --enable-trial")
1025
+ pipe = getattr(self, "_act_pipeline", None)
1026
+ if pipe is None or getattr(pipe, "skeptic", None) is None:
1027
+ return trial_mod.TrialRefusal("trial requires an adapter")
1028
+
1029
+ qdb = quarantine_db_path(self.storage)
1030
+ row = quarantine.get(qdb, rowid)
1031
+ if row is None:
1032
+ return trial_mod.TrialRefusal(f"no quarantine row #{rowid}")
1033
+ if row.import_status != "quarantined":
1034
+ return trial_mod.TrialRefusal(
1035
+ f"row #{rowid} is not quarantined (status={row.import_status})")
1036
+ if artifact.content_hash(row.artifact_json) != row.content_sha256:
1037
+ quarantine.note_trial(qdb, rowid, result="tampered",
1038
+ error="content_sha256 mismatch",
1039
+ ts=time.time())
1040
+ return trial_mod.TrialRefusal(
1041
+ f"row #{rowid} tampered (content_sha256 mismatch)")
1042
+ try:
1043
+ steps = json.loads(row.plan_template)
1044
+ if not isinstance(steps, list):
1045
+ raise ValueError("plan_template is not a list")
1046
+ except (ValueError, TypeError) as exc:
1047
+ quarantine.note_trial(qdb, rowid, result="corrupt_plan",
1048
+ error=str(exc), ts=time.time())
1049
+ return trial_mod.TrialRefusal(f"row #{rowid} has a corrupt plan")
1050
+
1051
+ tmp = tempfile.mkdtemp(prefix="conscio-trial-")
1052
+ try:
1053
+ reg = make_default_registry(
1054
+ sandbox_root=Path(tmp), content_store=None, event_bus=None,
1055
+ goal_generator=None)
1056
+ outcome = trial_mod.run_trial(
1057
+ steps, goal_text=row.goal_text, skeptic=pipe.skeptic,
1058
+ registry=reg)
1059
+ finally:
1060
+ shutil.rmtree(tmp, ignore_errors=True)
1061
+
1062
+ quarantine.record_trial(qdb, rowid, passed=outcome.passed,
1063
+ result=outcome.result, error=outcome.error,
1064
+ ts=time.time())
1065
+ return outcome
1066
+
1004
1067
  # --- v2.0 "Connect": propose-only cognition (never executes) ---
1005
1068
 
1006
1069
  def propose_action(self, intent: dict) -> dict:
@@ -0,0 +1,223 @@
1
+ # conscio/noosphere/audit.py
2
+ """Mutual audit — B forms its OWN trust opinion about a peer A from A's
3
+ published behavioral bundle, using B's deterministic kernels + thresholds.
4
+ Read-only, no inherited trust, report-only. Engine-free; no LLM/network.
5
+
6
+ The LLM Skeptic replay is deferred (v2.2.2/v2.3); here 'Skeptic' is the
7
+ deterministic discipline check: did A execute actions its own Skeptic FAILed?"""
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+ from dataclasses import dataclass
13
+
14
+ from . import artifact, record, record_catalog
15
+ from .identity import load_or_create
16
+ from .paths import resolve_noosphere, resolve_storage
17
+
18
+ # ── policy constants (parity-tested vs the engine; see test_noosphere_parity) ──
19
+ BREAKER_THRESHOLD = 3 # == conscio.agency.breaker.DEFAULT_MAX_RETRIES
20
+ L2_ACCURACY = 0.7 # == conscio.agency.trust.L2_ACCURACY
21
+ L3_ACCURACY = 0.85 # == conscio.agency.trust.L3_ACCURACY
22
+ AUTONOMY_MIN_ROWS = 10 # == conscio.agency.trust.AUTONOMY_MIN_ROWS
23
+ # ── audit-only policy (no engine equivalent) ──
24
+ ACCURACY_FLOOR = 0.5 # below this (with volume) → REJECTED
25
+ UNAUDITED_FRACTION_SUSPECT = 0.5 # executed_unaudited / executed above this → SUSPECT
26
+
27
+ _TERMINAL = frozenset({"executed", "failed"})
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class RevalidationOutcome:
32
+ result: str # 'ok'|'tampered'|'corrupt'|'malformed'
33
+ error: str = ""
34
+ body: dict | None = None
35
+
36
+ @property
37
+ def ok(self) -> bool:
38
+ return self.result == "ok"
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class ToolStats:
43
+ tool: str
44
+ ok: int
45
+ failed: int
46
+ attempts: int
47
+ accuracy: float
48
+ trust_level: int
49
+
50
+
51
+ @dataclass(frozen=True)
52
+ class PeerAudit:
53
+ origin_instance_id: str
54
+ origin_label: str
55
+ published_ts: float
56
+ entry_count: int
57
+ attempts: int
58
+ overall_accuracy: float
59
+ tools: tuple[ToolStats, ...]
60
+ quarantined_goals: tuple[str, ...]
61
+ executed_after_fail: int
62
+ executed_unaudited: int
63
+ verdict: str
64
+
65
+
66
+ def revalidate_bundle(row: record_catalog.RecordRow) -> RevalidationOutcome:
67
+ if artifact.content_hash(row.bundle_json) != row.content_sha256:
68
+ return RevalidationOutcome("tampered", "content_sha256 mismatch")
69
+ try:
70
+ body = json.loads(row.bundle_json.decode("utf-8"))
71
+ except (UnicodeDecodeError, ValueError) as exc:
72
+ return RevalidationOutcome("corrupt", f"unparseable bundle: {exc}")
73
+ if not record.well_typed_bundle(body):
74
+ return RevalidationOutcome("malformed", "missing or mis-typed fields",
75
+ body=body if isinstance(body, dict) else None)
76
+ if body.get("schema_version") != record.BUNDLE_SCHEMA:
77
+ return RevalidationOutcome(
78
+ "malformed",
79
+ f"unsupported schema_version {body.get('schema_version')!r}", body=body)
80
+ return RevalidationOutcome("ok", body=body)
81
+
82
+
83
+ def tool_stats(entries: list[record.RecordEntry]) -> dict[str, ToolStats]:
84
+ agg: dict[str, list[int]] = {} # tool -> [ok, failed]
85
+ for e in entries:
86
+ if e.status not in _TERMINAL:
87
+ continue
88
+ slot = agg.setdefault(e.tool, [0, 0])
89
+ if e.status == "executed" and e.ok == 1:
90
+ slot[0] += 1
91
+ else:
92
+ slot[1] += 1
93
+ out: dict[str, ToolStats] = {}
94
+ for tool, (ok, failed) in agg.items():
95
+ attempts = ok + failed
96
+ acc = ok / attempts if attempts else 0.0
97
+ out[tool] = ToolStats(tool=tool, ok=ok, failed=failed,
98
+ attempts=attempts, accuracy=acc, trust_level=1)
99
+ return out
100
+
101
+
102
+ def _max_fail_streak(statuses: list[str]) -> int:
103
+ best = cur = 0
104
+ for s in statuses:
105
+ if s == "failed":
106
+ cur += 1
107
+ best = max(best, cur)
108
+ else:
109
+ cur = 0
110
+ return best
111
+
112
+
113
+ def derive_quarantines(entries: list[record.RecordEntry]) -> set[str]:
114
+ by_goal: dict[str, list[tuple[int, str]]] = {}
115
+ for e in entries:
116
+ by_goal.setdefault(e.goal_fp, []).append((e.seq, e.status))
117
+ out: set[str] = set()
118
+ for goal_fp, seq_status in by_goal.items():
119
+ seq_status.sort()
120
+ if _max_fail_streak([s for _, s in seq_status]) >= BREAKER_THRESHOLD:
121
+ out.add(goal_fp)
122
+ return out
123
+
124
+
125
+ def foreign_trust_level(accuracy: float, attempts: int,
126
+ any_quarantine: bool) -> int:
127
+ if (accuracy >= L3_ACCURACY and attempts >= AUTONOMY_MIN_ROWS
128
+ and not any_quarantine):
129
+ return 3
130
+ if accuracy >= L2_ACCURACY and attempts >= AUTONOMY_MIN_ROWS:
131
+ return 2
132
+ return 1
133
+
134
+
135
+ def discipline_flags(entries: list[record.RecordEntry]) -> tuple[int, int]:
136
+ """(executed_after_fail RED, executed_unaudited YELLOW). PASS is neutral."""
137
+ red = yellow = 0
138
+ for e in entries:
139
+ if e.status != "executed":
140
+ continue
141
+ v = e.verdict.strip().upper()
142
+ if v == "FAIL":
143
+ red += 1
144
+ elif v == "":
145
+ yellow += 1
146
+ return red, yellow
147
+
148
+
149
+ def _verdict(attempts: int, overall: float, quarantines: set[str], red: int,
150
+ yellow: int, executed: int, tools: list[ToolStats]) -> str:
151
+ if attempts == 0:
152
+ return "INSUFFICIENT"
153
+ if red > 0 or (overall < ACCURACY_FLOOR and attempts >= AUTONOMY_MIN_ROWS):
154
+ return "REJECTED"
155
+ unaudited_frac = (yellow / executed) if executed else 0.0
156
+ no_l2 = not any(t.trust_level >= 2 for t in tools)
157
+ if quarantines or unaudited_frac > UNAUDITED_FRACTION_SUSPECT or no_l2:
158
+ return "SUSPECT"
159
+ return "TRUSTED"
160
+
161
+
162
+ def audit_peer(row: record_catalog.RecordRow,
163
+ entries: list[record.RecordEntry]) -> PeerAudit:
164
+ quarantines = derive_quarantines(entries)
165
+ any_q = bool(quarantines)
166
+ tools: list[ToolStats] = []
167
+ total_ok = total_attempts = 0
168
+ for ts in tool_stats(entries).values():
169
+ level = foreign_trust_level(ts.accuracy, ts.attempts, any_q)
170
+ tools.append(ToolStats(tool=ts.tool, ok=ts.ok, failed=ts.failed,
171
+ attempts=ts.attempts, accuracy=ts.accuracy,
172
+ trust_level=level))
173
+ total_ok += ts.ok
174
+ total_attempts += ts.attempts
175
+ red, yellow = discipline_flags(entries)
176
+ executed = sum(1 for e in entries if e.status == "executed")
177
+ overall = total_ok / total_attempts if total_attempts else 0.0
178
+ verdict = _verdict(total_attempts, overall, quarantines, red, yellow,
179
+ executed, tools)
180
+ tools.sort(key=lambda t: t.tool)
181
+ return PeerAudit(
182
+ origin_instance_id=row.origin_instance_id, origin_label=row.origin_label,
183
+ published_ts=row.published_ts, entry_count=row.entry_count,
184
+ attempts=total_attempts, overall_accuracy=overall, tools=tuple(tools),
185
+ quarantined_goals=tuple(sorted(quarantines)), executed_after_fail=red,
186
+ executed_unaudited=yellow, verdict=verdict)
187
+
188
+
189
+ @dataclass(frozen=True)
190
+ class AuditReport:
191
+ peers: tuple[PeerAudit, ...]
192
+ rejected_bundles: tuple[tuple[str, str, str], ...] # (origin_id, label, reason)
193
+ audited: int
194
+
195
+
196
+ def run(storage: str | os.PathLike[str] | None = None,
197
+ noosphere: str | os.PathLike[str] | None = None,
198
+ instance: str | None = None) -> AuditReport:
199
+ storage = resolve_storage(storage)
200
+ noo = resolve_noosphere(noosphere)
201
+ ident = load_or_create(storage)
202
+ foreign = record_catalog.read_foreign(noo, exclude_instance_id=ident.instance_id)
203
+
204
+ latest: dict[str, record_catalog.RecordRow] = {} # keep newest per origin
205
+ for r in foreign:
206
+ if instance and r.origin_instance_id != instance:
207
+ continue
208
+ cur = latest.get(r.origin_instance_id)
209
+ if cur is None or r.published_ts > cur.published_ts:
210
+ latest[r.origin_instance_id] = r
211
+
212
+ peers: list[PeerAudit] = []
213
+ rejected: list[tuple[str, str, str]] = []
214
+ for r in sorted(latest.values(),
215
+ key=lambda x: (x.published_ts, x.origin_instance_id)):
216
+ outcome = revalidate_bundle(r)
217
+ if not outcome.ok or outcome.body is None:
218
+ rejected.append((r.origin_instance_id, r.origin_label,
219
+ f"{outcome.result}: {outcome.error}".strip(": ")))
220
+ continue
221
+ peers.append(audit_peer(r, record.entries_from_body(outcome.body)))
222
+ return AuditReport(peers=tuple(peers), rejected_bundles=tuple(rejected),
223
+ audited=len(peers))