conscio 2.2.0__tar.gz → 2.2.1__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 (244) hide show
  1. {conscio-2.2.0 → conscio-2.2.1}/CHANGELOG.md +15 -0
  2. {conscio-2.2.0/conscio.egg-info → conscio-2.2.1}/PKG-INFO +4 -3
  3. {conscio-2.2.0 → conscio-2.2.1}/README.md +3 -2
  4. {conscio-2.2.0 → conscio-2.2.1}/conscio/__init__.py +1 -1
  5. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/trust.py +6 -3
  6. conscio-2.2.1/conscio/noosphere/audit.py +223 -0
  7. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/cli.py +42 -2
  8. conscio-2.2.1/conscio/noosphere/record.py +79 -0
  9. conscio-2.2.1/conscio/noosphere/record_catalog.py +126 -0
  10. conscio-2.2.1/conscio/noosphere/record_publish.py +72 -0
  11. {conscio-2.2.0 → conscio-2.2.1/conscio.egg-info}/PKG-INFO +4 -3
  12. {conscio-2.2.0 → conscio-2.2.1}/conscio.egg-info/SOURCES.txt +9 -0
  13. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_trust.py +11 -0
  14. conscio-2.2.1/tests/test_noosphere_audit.py +121 -0
  15. conscio-2.2.1/tests/test_noosphere_audit_integration.py +60 -0
  16. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_cli.py +33 -0
  17. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_parity.py +9 -0
  18. conscio-2.2.1/tests/test_noosphere_record.py +41 -0
  19. conscio-2.2.1/tests/test_noosphere_record_catalog.py +42 -0
  20. conscio-2.2.1/tests/test_noosphere_record_publish.py +71 -0
  21. {conscio-2.2.0 → conscio-2.2.1}/LICENSE +0 -0
  22. {conscio-2.2.0 → conscio-2.2.1}/MANIFEST.in +0 -0
  23. {conscio-2.2.0 → conscio-2.2.1}/conscio/__main__.py +0 -0
  24. {conscio-2.2.0 → conscio-2.2.1}/conscio/adapter_config.py +0 -0
  25. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/__init__.py +0 -0
  26. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/act.py +0 -0
  27. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/actor.py +0 -0
  28. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/adapter.py +0 -0
  29. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/adapters.py +0 -0
  30. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/breaker.py +0 -0
  31. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/contracts.py +0 -0
  32. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/fingerprint.py +0 -0
  33. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/gateway.py +0 -0
  34. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/grammar.py +0 -0
  35. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/host_act.py +0 -0
  36. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/ledger.py +0 -0
  37. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/loop.py +0 -0
  38. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/profiles.py +0 -0
  39. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/skeptic.py +0 -0
  40. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/skills.py +0 -0
  41. {conscio-2.2.0 → conscio-2.2.1}/conscio/agency/tools.py +0 -0
  42. {conscio-2.2.0 → conscio-2.2.1}/conscio/auto_evolution.py +0 -0
  43. {conscio-2.2.0 → conscio-2.2.1}/conscio/axis_pack.py +0 -0
  44. {conscio-2.2.0 → conscio-2.2.1}/conscio/bench.py +0 -0
  45. {conscio-2.2.0 → conscio-2.2.1}/conscio/cli.py +0 -0
  46. {conscio-2.2.0 → conscio-2.2.1}/conscio/coherence.py +0 -0
  47. {conscio-2.2.0 → conscio-2.2.1}/conscio/content_layer.py +0 -0
  48. {conscio-2.2.0 → conscio-2.2.1}/conscio/content_store.py +0 -0
  49. {conscio-2.2.0 → conscio-2.2.1}/conscio/context_manager.py +0 -0
  50. {conscio-2.2.0 → conscio-2.2.1}/conscio/daemon.py +0 -0
  51. {conscio-2.2.0 → conscio-2.2.1}/conscio/dreaming.py +0 -0
  52. {conscio-2.2.0 → conscio-2.2.1}/conscio/engine.py +0 -0
  53. {conscio-2.2.0 → conscio-2.2.1}/conscio/event_bus.py +0 -0
  54. {conscio-2.2.0 → conscio-2.2.1}/conscio/goal_generator.py +0 -0
  55. {conscio-2.2.0 → conscio-2.2.1}/conscio/guards.py +0 -0
  56. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/__init__.py +0 -0
  57. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/config.py +0 -0
  58. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/model_test.py +0 -0
  59. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/providers.py +0 -0
  60. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/server.py +0 -0
  61. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/static/app.js +0 -0
  62. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/static/index.html +0 -0
  63. {conscio-2.2.0 → conscio-2.2.1}/conscio/hub/static/style.css +0 -0
  64. {conscio-2.2.0 → conscio-2.2.1}/conscio/inner_monologue.py +0 -0
  65. {conscio-2.2.0 → conscio-2.2.1}/conscio/mcp/__init__.py +0 -0
  66. {conscio-2.2.0 → conscio-2.2.1}/conscio/mcp/jsonrpc.py +0 -0
  67. {conscio-2.2.0 → conscio-2.2.1}/conscio/mcp/protocol.py +0 -0
  68. {conscio-2.2.0 → conscio-2.2.1}/conscio/mcp/schemas.py +0 -0
  69. {conscio-2.2.0 → conscio-2.2.1}/conscio/mcp/seen.py +0 -0
  70. {conscio-2.2.0 → conscio-2.2.1}/conscio/mcp/server.py +0 -0
  71. {conscio-2.2.0 → conscio-2.2.1}/conscio/meta_cognition.py +0 -0
  72. {conscio-2.2.0 → conscio-2.2.1}/conscio/metabolic.py +0 -0
  73. {conscio-2.2.0 → conscio-2.2.1}/conscio/migrate.py +0 -0
  74. {conscio-2.2.0 → conscio-2.2.1}/conscio/models.py +0 -0
  75. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/__init__.py +0 -0
  76. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/artifact.py +0 -0
  77. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/catalog.py +0 -0
  78. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/identity.py +0 -0
  79. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/importer.py +0 -0
  80. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/paths.py +0 -0
  81. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/publish.py +0 -0
  82. {conscio-2.2.0 → conscio-2.2.1}/conscio/noosphere/quarantine.py +0 -0
  83. {conscio-2.2.0 → conscio-2.2.1}/conscio/output_filter.py +0 -0
  84. {conscio-2.2.0 → conscio-2.2.1}/conscio/perception/__init__.py +0 -0
  85. {conscio-2.2.0 → conscio-2.2.1}/conscio/perception/agent_sensor.py +0 -0
  86. {conscio-2.2.0 → conscio-2.2.1}/conscio/perception/host_sensor.py +0 -0
  87. {conscio-2.2.0 → conscio-2.2.1}/conscio/perception/sensor.py +0 -0
  88. {conscio-2.2.0 → conscio-2.2.1}/conscio/plugins.py +0 -0
  89. {conscio-2.2.0 → conscio-2.2.1}/conscio/presets/__init__.py +0 -0
  90. {conscio-2.2.0 → conscio-2.2.1}/conscio/py.typed +0 -0
  91. {conscio-2.2.0 → conscio-2.2.1}/conscio/risk.py +0 -0
  92. {conscio-2.2.0 → conscio-2.2.1}/conscio/self_prompt.py +0 -0
  93. {conscio-2.2.0 → conscio-2.2.1}/conscio/semantic.py +0 -0
  94. {conscio-2.2.0 → conscio-2.2.1}/conscio/session_lifecycle.py +0 -0
  95. {conscio-2.2.0 → conscio-2.2.1}/conscio/session_rag.py +0 -0
  96. {conscio-2.2.0 → conscio-2.2.1}/conscio/session_rag_factory.py +0 -0
  97. {conscio-2.2.0 → conscio-2.2.1}/conscio/shard_engine.py +0 -0
  98. {conscio-2.2.0 → conscio-2.2.1}/conscio/structural.py +0 -0
  99. {conscio-2.2.0 → conscio-2.2.1}/conscio/structural_consent.py +0 -0
  100. {conscio-2.2.0 → conscio-2.2.1}/conscio/structural_drift.py +0 -0
  101. {conscio-2.2.0 → conscio-2.2.1}/conscio/timeutil.py +0 -0
  102. {conscio-2.2.0 → conscio-2.2.1}/conscio/token_tracker.py +0 -0
  103. {conscio-2.2.0 → conscio-2.2.1}/conscio/voice_preset.py +0 -0
  104. {conscio-2.2.0 → conscio-2.2.1}/conscio/workspace.py +0 -0
  105. {conscio-2.2.0 → conscio-2.2.1}/conscio/world_model.py +0 -0
  106. {conscio-2.2.0 → conscio-2.2.1}/conscio.egg-info/dependency_links.txt +0 -0
  107. {conscio-2.2.0 → conscio-2.2.1}/conscio.egg-info/entry_points.txt +0 -0
  108. {conscio-2.2.0 → conscio-2.2.1}/conscio.egg-info/requires.txt +0 -0
  109. {conscio-2.2.0 → conscio-2.2.1}/conscio.egg-info/top_level.txt +0 -0
  110. {conscio-2.2.0 → conscio-2.2.1}/pyproject.toml +0 -0
  111. {conscio-2.2.0 → conscio-2.2.1}/setup.cfg +0 -0
  112. {conscio-2.2.0 → conscio-2.2.1}/tests/test_adapter_config.py +0 -0
  113. {conscio-2.2.0 → conscio-2.2.1}/tests/test_adapter_config_api_key_env.py +0 -0
  114. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_act.py +0 -0
  115. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_act_immunity.py +0 -0
  116. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_actor.py +0 -0
  117. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_adapter.py +0 -0
  118. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_adapters_http.py +0 -0
  119. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_adversarial.py +0 -0
  120. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_arbiter.py +0 -0
  121. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_bench.py +0 -0
  122. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_breaker.py +0 -0
  123. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_contracts.py +0 -0
  124. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_engine_immunity.py +0 -0
  125. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_gateway.py +0 -0
  126. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_grammar.py +0 -0
  127. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_host_act.py +0 -0
  128. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_ledger.py +0 -0
  129. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_ledger_v201.py +0 -0
  130. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_loop.py +0 -0
  131. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_no_network.py +0 -0
  132. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_profiles.py +0 -0
  133. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_skeptic.py +0 -0
  134. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_skills.py +0 -0
  135. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_skills_wiring.py +0 -0
  136. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_state.py +0 -0
  137. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_tools.py +0 -0
  138. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_tools_manifest.py +0 -0
  139. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agency_volition.py +0 -0
  140. {conscio-2.2.0 → conscio-2.2.1}/tests/test_agent_sensor.py +0 -0
  141. {conscio-2.2.0 → conscio-2.2.1}/tests/test_auto_evolution.py +0 -0
  142. {conscio-2.2.0 → conscio-2.2.1}/tests/test_awake.py +0 -0
  143. {conscio-2.2.0 → conscio-2.2.1}/tests/test_axis_pack.py +0 -0
  144. {conscio-2.2.0 → conscio-2.2.1}/tests/test_axis_pack_battery.py +0 -0
  145. {conscio-2.2.0 → conscio-2.2.1}/tests/test_cli.py +0 -0
  146. {conscio-2.2.0 → conscio-2.2.1}/tests/test_coherence.py +0 -0
  147. {conscio-2.2.0 → conscio-2.2.1}/tests/test_coherence_engine_integration.py +0 -0
  148. {conscio-2.2.0 → conscio-2.2.1}/tests/test_coherence_state.py +0 -0
  149. {conscio-2.2.0 → conscio-2.2.1}/tests/test_consciousness.py +0 -0
  150. {conscio-2.2.0 → conscio-2.2.1}/tests/test_content_layer.py +0 -0
  151. {conscio-2.2.0 → conscio-2.2.1}/tests/test_content_layer_manager.py +0 -0
  152. {conscio-2.2.0 → conscio-2.2.1}/tests/test_content_store.py +0 -0
  153. {conscio-2.2.0 → conscio-2.2.1}/tests/test_content_store_battery.py +0 -0
  154. {conscio-2.2.0 → conscio-2.2.1}/tests/test_content_store_r05.py +0 -0
  155. {conscio-2.2.0 → conscio-2.2.1}/tests/test_contradiction_detector.py +0 -0
  156. {conscio-2.2.0 → conscio-2.2.1}/tests/test_daemon.py +0 -0
  157. {conscio-2.2.0 → conscio-2.2.1}/tests/test_daemon_battery.py +0 -0
  158. {conscio-2.2.0 → conscio-2.2.1}/tests/test_daemon_config.py +0 -0
  159. {conscio-2.2.0 → conscio-2.2.1}/tests/test_daemon_heartbeat.py +0 -0
  160. {conscio-2.2.0 → conscio-2.2.1}/tests/test_daemon_structure_sync.py +0 -0
  161. {conscio-2.2.0 → conscio-2.2.1}/tests/test_dream_coherence.py +0 -0
  162. {conscio-2.2.0 → conscio-2.2.1}/tests/test_dream_distill.py +0 -0
  163. {conscio-2.2.0 → conscio-2.2.1}/tests/test_dream_reconcile.py +0 -0
  164. {conscio-2.2.0 → conscio-2.2.1}/tests/test_dreaming.py +0 -0
  165. {conscio-2.2.0 → conscio-2.2.1}/tests/test_dreaming_friction.py +0 -0
  166. {conscio-2.2.0 → conscio-2.2.1}/tests/test_durable_guards.py +0 -0
  167. {conscio-2.2.0 → conscio-2.2.1}/tests/test_embedder.py +0 -0
  168. {conscio-2.2.0 → conscio-2.2.1}/tests/test_engine_advisory.py +0 -0
  169. {conscio-2.2.0 → conscio-2.2.1}/tests/test_engine_host_act.py +0 -0
  170. {conscio-2.2.0 → conscio-2.2.1}/tests/test_engine_init.py +0 -0
  171. {conscio-2.2.0 → conscio-2.2.1}/tests/test_engine_meta_reflect.py +0 -0
  172. {conscio-2.2.0 → conscio-2.2.1}/tests/test_engine_propose.py +0 -0
  173. {conscio-2.2.0 → conscio-2.2.1}/tests/test_engine_recall.py +0 -0
  174. {conscio-2.2.0 → conscio-2.2.1}/tests/test_event_bus.py +0 -0
  175. {conscio-2.2.0 → conscio-2.2.1}/tests/test_event_bus_act_result.py +0 -0
  176. {conscio-2.2.0 → conscio-2.2.1}/tests/test_event_bus_purge.py +0 -0
  177. {conscio-2.2.0 → conscio-2.2.1}/tests/test_examples.py +0 -0
  178. {conscio-2.2.0 → conscio-2.2.1}/tests/test_goal_provenance.py +0 -0
  179. {conscio-2.2.0 → conscio-2.2.1}/tests/test_goal_source.py +0 -0
  180. {conscio-2.2.0 → conscio-2.2.1}/tests/test_host_sensor.py +0 -0
  181. {conscio-2.2.0 → conscio-2.2.1}/tests/test_hub_config.py +0 -0
  182. {conscio-2.2.0 → conscio-2.2.1}/tests/test_hub_model_test.py +0 -0
  183. {conscio-2.2.0 → conscio-2.2.1}/tests/test_hub_providers.py +0 -0
  184. {conscio-2.2.0 → conscio-2.2.1}/tests/test_hub_server.py +0 -0
  185. {conscio-2.2.0 → conscio-2.2.1}/tests/test_loop_failure_brake.py +0 -0
  186. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_adapter_parity.py +0 -0
  187. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_battery.py +0 -0
  188. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_fuzz.py +0 -0
  189. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_jsonrpc.py +0 -0
  190. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_package.py +0 -0
  191. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_protocol.py +0 -0
  192. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_schemas.py +0 -0
  193. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_seen.py +0 -0
  194. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_server.py +0 -0
  195. {conscio-2.2.0 → conscio-2.2.1}/tests/test_mcp_server_cli.py +0 -0
  196. {conscio-2.2.0 → conscio-2.2.1}/tests/test_metabolic.py +0 -0
  197. {conscio-2.2.0 → conscio-2.2.1}/tests/test_migrate.py +0 -0
  198. {conscio-2.2.0 → conscio-2.2.1}/tests/test_model_auto_detect.py +0 -0
  199. {conscio-2.2.0 → conscio-2.2.1}/tests/test_model_offline_default.py +0 -0
  200. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_artifact.py +0 -0
  201. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_catalog.py +0 -0
  202. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_engine_free.py +0 -0
  203. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_fingerprint.py +0 -0
  204. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_identity.py +0 -0
  205. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_importer.py +0 -0
  206. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_integration.py +0 -0
  207. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_paths.py +0 -0
  208. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_publish.py +0 -0
  209. {conscio-2.2.0 → conscio-2.2.1}/tests/test_noosphere_quarantine.py +0 -0
  210. {conscio-2.2.0 → conscio-2.2.1}/tests/test_ontological_semantic.py +0 -0
  211. {conscio-2.2.0 → conscio-2.2.1}/tests/test_output_filter.py +0 -0
  212. {conscio-2.2.0 → conscio-2.2.1}/tests/test_output_filter_stages.py +0 -0
  213. {conscio-2.2.0 → conscio-2.2.1}/tests/test_packaging.py +0 -0
  214. {conscio-2.2.0 → conscio-2.2.1}/tests/test_perception.py +0 -0
  215. {conscio-2.2.0 → conscio-2.2.1}/tests/test_perf_reflection.py +0 -0
  216. {conscio-2.2.0 → conscio-2.2.1}/tests/test_plugins.py +0 -0
  217. {conscio-2.2.0 → conscio-2.2.1}/tests/test_recursive_loop_integration.py +0 -0
  218. {conscio-2.2.0 → conscio-2.2.1}/tests/test_risk.py +0 -0
  219. {conscio-2.2.0 → conscio-2.2.1}/tests/test_self_prompt.py +0 -0
  220. {conscio-2.2.0 → conscio-2.2.1}/tests/test_self_prompt_state.py +0 -0
  221. {conscio-2.2.0 → conscio-2.2.1}/tests/test_semantic_dedup.py +0 -0
  222. {conscio-2.2.0 → conscio-2.2.1}/tests/test_semantic_engine.py +0 -0
  223. {conscio-2.2.0 → conscio-2.2.1}/tests/test_semantic_reconcile_integration.py +0 -0
  224. {conscio-2.2.0 → conscio-2.2.1}/tests/test_session_lifecycle.py +0 -0
  225. {conscio-2.2.0 → conscio-2.2.1}/tests/test_session_lifecycle_battery.py +0 -0
  226. {conscio-2.2.0 → conscio-2.2.1}/tests/test_session_lifecycle_dream.py +0 -0
  227. {conscio-2.2.0 → conscio-2.2.1}/tests/test_session_rag.py +0 -0
  228. {conscio-2.2.0 → conscio-2.2.1}/tests/test_shard_engine.py +0 -0
  229. {conscio-2.2.0 → conscio-2.2.1}/tests/test_state_loaders_battery.py +0 -0
  230. {conscio-2.2.0 → conscio-2.2.1}/tests/test_state_persistence_battery.py +0 -0
  231. {conscio-2.2.0 → conscio-2.2.1}/tests/test_structural.py +0 -0
  232. {conscio-2.2.0 → conscio-2.2.1}/tests/test_structural_consent.py +0 -0
  233. {conscio-2.2.0 → conscio-2.2.1}/tests/test_structural_drift.py +0 -0
  234. {conscio-2.2.0 → conscio-2.2.1}/tests/test_structural_inject.py +0 -0
  235. {conscio-2.2.0 → conscio-2.2.1}/tests/test_timeutil.py +0 -0
  236. {conscio-2.2.0 → conscio-2.2.1}/tests/test_token_tracker.py +0 -0
  237. {conscio-2.2.0 → conscio-2.2.1}/tests/test_trajectory_vector.py +0 -0
  238. {conscio-2.2.0 → conscio-2.2.1}/tests/test_v2_debt_zero.py +0 -0
  239. {conscio-2.2.0 → conscio-2.2.1}/tests/test_voice_preset.py +0 -0
  240. {conscio-2.2.0 → conscio-2.2.1}/tests/test_workspace.py +0 -0
  241. {conscio-2.2.0 → conscio-2.2.1}/tests/test_world_contradictions.py +0 -0
  242. {conscio-2.2.0 → conscio-2.2.1}/tests/test_world_model_entropy.py +0 -0
  243. {conscio-2.2.0 → conscio-2.2.1}/tests/test_world_model_prediction.py +0 -0
  244. {conscio-2.2.0 → conscio-2.2.1}/tests/test_world_model_prune.py +0 -0
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [2.2.1] - 2026-06-22 — "Mutual audit"
11
+
12
+ ### Added
13
+ - **Noosphere mutual audit.** An instance can publish a non-sensitive
14
+ projection of its action ledger (`conscio noosphere publish-record`) to the
15
+ host-shared `noosphere.db`, and a peer can independently audit it
16
+ (`conscio noosphere audit`) — deterministic, read-only, engine-free. The
17
+ auditor re-derives track-record, breaker quarantines, and a foreign-trust
18
+ level under its OWN thresholds (parity-tested against the engine), and runs
19
+ a discipline check (did the peer execute actions its own Skeptic FAILed?).
20
+ No inherited trust; report-only; the auditor persists nothing. The LLM
21
+ Skeptic replay is deferred to a later slice.
22
+
23
+ ---
24
+
10
25
  ## [2.2.0] - 2026-06-22 — "Society" (Noosphere Core)
11
26
 
12
27
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conscio
3
- Version: 2.2.0
3
+ Version: 2.2.1
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,9 @@ 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.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. `pip install conscio`.
50
+ - **Prior:** `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 promotedtrust is never inherited.
51
+ - **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
52
  - **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
53
  - **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
54
 
@@ -11,8 +11,9 @@ 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.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. `pip install conscio`.
15
+ - **Prior:** `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 promotedtrust is never inherited.
16
+ - **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
17
  - **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
18
  - **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
19
 
@@ -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.1"
10
10
  __author__ = "Neguiolidas / Neguitech"
11
11
 
12
12
  from .engine import ConsciousnessEngine
@@ -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
@@ -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))
@@ -8,7 +8,8 @@ from __future__ import annotations
8
8
  import argparse
9
9
  import json
10
10
 
11
- from . import catalog, identity, importer, publish, quarantine
11
+ from . import (audit, catalog, identity, importer, publish, quarantine,
12
+ record_publish)
12
13
  from .paths import quarantine_db_path, resolve_noosphere, resolve_storage
13
14
 
14
15
 
@@ -33,6 +34,18 @@ def _build_parser() -> argparse.ArgumentParser:
33
34
  _storage_arg(sp)
34
35
  _noosphere_arg(sp)
35
36
 
37
+ pr = sub.add_parser("publish-record",
38
+ help="publish this instance's behavioral record")
39
+ _storage_arg(pr)
40
+ _noosphere_arg(pr)
41
+
42
+ pa = sub.add_parser("audit",
43
+ help="audit peers' behavioral records (read-only)")
44
+ _storage_arg(pa)
45
+ _noosphere_arg(pa)
46
+ pa.add_argument("--instance", default="",
47
+ help="audit only this origin_instance_id")
48
+
36
49
  pl = sub.add_parser("list", help="list quarantined imports (or --catalog)")
37
50
  _storage_arg(pl)
38
51
  _noosphere_arg(pl)
@@ -122,6 +135,32 @@ def _cmd_id(args) -> int:
122
135
  return 0
123
136
 
124
137
 
138
+ def _cmd_publish_record(args) -> int:
139
+ res = record_publish.run(storage=args.storage, noosphere=args.noosphere)
140
+ print(f"published {res.published} (skipped {res.skipped} already present, "
141
+ f"{res.entries} entries)")
142
+ return 0
143
+
144
+
145
+ def _cmd_audit(args) -> int:
146
+ rep = audit.run(storage=args.storage, noosphere=args.noosphere,
147
+ instance=(args.instance or None))
148
+ if not rep.peers and not rep.rejected_bundles:
149
+ print("no peer records found")
150
+ return 0
151
+ for p in rep.peers:
152
+ max_level = max((t.trust_level for t in p.tools), default=1)
153
+ print(f"{p.origin_label} [{p.origin_instance_id[:8]}] {p.verdict} "
154
+ f"acc {round(100 * p.overall_accuracy)}% over {p.attempts} "
155
+ f"L{max_level} quarantines {len(p.quarantined_goals)} "
156
+ f"RED {p.executed_after_fail} / YELLOW {p.executed_unaudited}")
157
+ if rep.rejected_bundles:
158
+ print("rejected bundles:")
159
+ for origin, label, reason in rep.rejected_bundles:
160
+ print(f" {label} [{origin[:8]}] {reason}")
161
+ return 0
162
+
163
+
125
164
  def main(argv: list[str]) -> int:
126
165
  parser = _build_parser()
127
166
  try: # argparse calls sys.exit on bad args
@@ -129,7 +168,8 @@ def main(argv: list[str]) -> int:
129
168
  except SystemExit as exc:
130
169
  return int(exc.code) if exc.code is not None else 0
131
170
  dispatch = {"publish": _cmd_publish, "import": _cmd_import,
132
- "list": _cmd_list, "show": _cmd_show, "id": _cmd_id}
171
+ "list": _cmd_list, "show": _cmd_show, "id": _cmd_id,
172
+ "publish-record": _cmd_publish_record, "audit": _cmd_audit}
133
173
  handler = dispatch.get(args.cmd)
134
174
  if handler is None:
135
175
  parser.print_help()
@@ -0,0 +1,79 @@
1
+ # conscio/noosphere/record.py
2
+ """Behavioral bundle artifact — a minimal, non-sensitive projection of an
3
+ instance's action ledger. The content body is hashed via
4
+ artifact.canonical_bytes / content_hash (same convention as the skill
5
+ artifact). Carries ONLY {seq, ts, goal_fp, tool, tier, status, ok, verdict};
6
+ never args/output/error/rationale/goal_text (privacy by column omission)."""
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+
11
+ BUNDLE_SCHEMA = 1
12
+
13
+ _VALID_STATUS = frozenset(
14
+ {"proposed", "executing", "executed", "rejected", "failed", "locked"})
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class RecordEntry:
19
+ seq: int
20
+ ts: float
21
+ goal_fp: str
22
+ tool: str
23
+ tier: str
24
+ status: str
25
+ ok: int | None
26
+ verdict: str
27
+
28
+
29
+ def build_bundle_body(entries: list[RecordEntry]) -> dict:
30
+ return {
31
+ "schema_version": BUNDLE_SCHEMA,
32
+ "entries": [
33
+ {"seq": e.seq, "ts": e.ts, "goal_fp": e.goal_fp, "tool": e.tool,
34
+ "tier": e.tier, "status": e.status, "ok": e.ok,
35
+ "verdict": e.verdict}
36
+ for e in entries],
37
+ }
38
+
39
+
40
+ def _is_int(v: object) -> bool:
41
+ return isinstance(v, int) and not isinstance(v, bool)
42
+
43
+
44
+ def _well_typed_entry(d: object) -> bool:
45
+ if not isinstance(d, dict):
46
+ return False
47
+ if not _is_int(d.get("seq")):
48
+ return False
49
+ ts = d.get("ts")
50
+ if not ((isinstance(ts, (int, float)) and not isinstance(ts, bool))):
51
+ return False
52
+ if not (isinstance(d.get("goal_fp"), str) and d["goal_fp"]):
53
+ return False
54
+ if not (isinstance(d.get("tool"), str) and isinstance(d.get("tier"), str)
55
+ and isinstance(d.get("verdict"), str)):
56
+ return False
57
+ if d.get("status") not in _VALID_STATUS:
58
+ return False
59
+ ok = d.get("ok")
60
+ if ok is not None and not (ok in (0, 1) and not isinstance(ok, bool)):
61
+ return False
62
+ return True
63
+
64
+
65
+ def well_typed_bundle(body: object) -> bool:
66
+ if not isinstance(body, dict) or not isinstance(body.get("entries"), list):
67
+ return False
68
+ return all(_well_typed_entry(e) for e in body["entries"])
69
+
70
+
71
+ def entries_from_body(body: dict) -> list[RecordEntry]:
72
+ out: list[RecordEntry] = []
73
+ for d in body["entries"]:
74
+ out.append(RecordEntry(
75
+ seq=int(d["seq"]), ts=float(d["ts"]), goal_fp=str(d["goal_fp"]),
76
+ tool=str(d["tool"]), tier=str(d["tier"]), status=str(d["status"]),
77
+ ok=(None if d["ok"] is None else int(d["ok"])),
78
+ verdict=str(d["verdict"])))
79
+ return out
@@ -0,0 +1,126 @@
1
+ # conscio/noosphere/record_catalog.py
2
+ """Host-shared noosphere.db — catalog of published behavioral bundles. Lives
3
+ alongside published_skills in the SAME shared db. PK (origin_instance_id,
4
+ content_sha256); ON CONFLICT DO NOTHING (idempotent snapshots). WAL +
5
+ busy_timeout for concurrent same-host writers."""
6
+ from __future__ import annotations
7
+
8
+ import sqlite3
9
+ from dataclasses import dataclass
10
+ from pathlib import Path
11
+
12
+ BUSY_TIMEOUT_MS = 5000
13
+
14
+ _SCHEMA = """
15
+ CREATE TABLE IF NOT EXISTS published_records (
16
+ origin_instance_id TEXT NOT NULL,
17
+ origin_label TEXT NOT NULL,
18
+ published_ts REAL NOT NULL,
19
+ content_sha256 TEXT NOT NULL,
20
+ entry_count INTEGER NOT NULL,
21
+ window_first_ts REAL NOT NULL DEFAULT 0,
22
+ window_last_ts REAL NOT NULL DEFAULT 0,
23
+ bundle_json BLOB NOT NULL,
24
+ schema_version INTEGER NOT NULL DEFAULT 1,
25
+ PRIMARY KEY (origin_instance_id, content_sha256)
26
+ );
27
+ CREATE INDEX IF NOT EXISTS idx_rec_origin
28
+ ON published_records(origin_instance_id, published_ts);
29
+ """
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class RecordRow:
34
+ origin_instance_id: str
35
+ origin_label: str
36
+ published_ts: float
37
+ content_sha256: str
38
+ entry_count: int
39
+ window_first_ts: float
40
+ window_last_ts: float
41
+ bundle_json: bytes
42
+ schema_version: int
43
+
44
+
45
+ def _connect(db: Path) -> sqlite3.Connection:
46
+ conn = sqlite3.connect(str(db))
47
+ conn.row_factory = sqlite3.Row
48
+ conn.execute(f"PRAGMA busy_timeout={BUSY_TIMEOUT_MS}")
49
+ conn.execute("PRAGMA journal_mode=WAL")
50
+ conn.executescript(_SCHEMA)
51
+ return conn
52
+
53
+
54
+ def _as_bytes(value: object) -> bytes:
55
+ """Coerce a stored bundle_json cell to bytes. Normally a BLOB, but a
56
+ tampered/edited row may have been coerced to TEXT (e.g. via SQLite ||);
57
+ return its bytes so revalidation can hash it and reject (not crash)."""
58
+ if isinstance(value, (bytes, bytearray)):
59
+ return bytes(value)
60
+ if isinstance(value, memoryview):
61
+ return value.tobytes()
62
+ if isinstance(value, str):
63
+ return value.encode("utf-8")
64
+ raise TypeError(f"unexpected bundle_json cell type: {type(value).__name__}")
65
+
66
+
67
+ def _row(r: sqlite3.Row) -> RecordRow:
68
+ return RecordRow(
69
+ origin_instance_id=r["origin_instance_id"], origin_label=r["origin_label"],
70
+ published_ts=r["published_ts"], content_sha256=r["content_sha256"],
71
+ entry_count=r["entry_count"], window_first_ts=r["window_first_ts"],
72
+ window_last_ts=r["window_last_ts"],
73
+ bundle_json=_as_bytes(r["bundle_json"]), schema_version=r["schema_version"])
74
+
75
+
76
+ def publish_rows(db: Path, rows: list[RecordRow]) -> int:
77
+ db = Path(db)
78
+ db.parent.mkdir(parents=True, exist_ok=True)
79
+ conn = _connect(db)
80
+ inserted = 0
81
+ try:
82
+ for r in rows:
83
+ cur = conn.execute(
84
+ "INSERT INTO published_records (origin_instance_id, origin_label,"
85
+ " published_ts, content_sha256, entry_count, window_first_ts,"
86
+ " window_last_ts, bundle_json, schema_version)"
87
+ " VALUES (?,?,?,?,?,?,?,?,?)"
88
+ " ON CONFLICT(origin_instance_id, content_sha256) DO NOTHING",
89
+ (r.origin_instance_id, r.origin_label, r.published_ts,
90
+ r.content_sha256, r.entry_count, r.window_first_ts,
91
+ r.window_last_ts, sqlite3.Binary(r.bundle_json), r.schema_version))
92
+ inserted += cur.rowcount
93
+ conn.commit()
94
+ finally:
95
+ conn.close()
96
+ return inserted
97
+
98
+
99
+ def read_foreign(db: Path, *, exclude_instance_id: str) -> list[RecordRow]:
100
+ db = Path(db)
101
+ if not db.exists():
102
+ return []
103
+ conn = _connect(db)
104
+ try:
105
+ rows = conn.execute(
106
+ "SELECT * FROM published_records WHERE origin_instance_id != ?"
107
+ " ORDER BY origin_instance_id, published_ts",
108
+ (exclude_instance_id,)).fetchall()
109
+ finally:
110
+ conn.close()
111
+ return [_row(r) for r in rows]
112
+
113
+
114
+ def get(db: Path, origin_instance_id: str, content_sha256: str) -> RecordRow | None:
115
+ db = Path(db)
116
+ if not db.exists():
117
+ return None
118
+ conn = _connect(db)
119
+ try:
120
+ r = conn.execute(
121
+ "SELECT * FROM published_records"
122
+ " WHERE origin_instance_id=? AND content_sha256=?",
123
+ (origin_instance_id, content_sha256)).fetchone()
124
+ finally:
125
+ conn.close()
126
+ return _row(r) if r else None