conscio 2.2.1__tar.gz → 2.3.0__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 (255) hide show
  1. {conscio-2.2.1 → conscio-2.3.0}/CHANGELOG.md +46 -0
  2. {conscio-2.2.1/conscio.egg-info → conscio-2.3.0}/PKG-INFO +5 -3
  3. {conscio-2.2.1 → conscio-2.3.0}/README.md +4 -2
  4. {conscio-2.2.1 → conscio-2.3.0}/conscio/__init__.py +1 -1
  5. conscio-2.3.0/conscio/agency/promote.py +55 -0
  6. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/skills.py +20 -0
  7. conscio-2.3.0/conscio/agency/trial.py +97 -0
  8. {conscio-2.2.1 → conscio-2.3.0}/conscio/cli.py +109 -0
  9. {conscio-2.2.1 → conscio-2.3.0}/conscio/engine.py +136 -0
  10. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/quarantine.py +93 -1
  11. {conscio-2.2.1 → conscio-2.3.0/conscio.egg-info}/PKG-INFO +5 -3
  12. {conscio-2.2.1 → conscio-2.3.0}/conscio.egg-info/SOURCES.txt +11 -0
  13. conscio-2.3.0/tests/test_agency_promote.py +56 -0
  14. conscio-2.3.0/tests/test_agency_trial.py +107 -0
  15. conscio-2.3.0/tests/test_cli_promote.py +45 -0
  16. conscio-2.3.0/tests/test_cli_trial.py +55 -0
  17. conscio-2.3.0/tests/test_engine_promote.py +194 -0
  18. conscio-2.3.0/tests/test_engine_trial.py +196 -0
  19. conscio-2.3.0/tests/test_quarantine_promote.py +66 -0
  20. conscio-2.3.0/tests/test_quarantine_trial.py +109 -0
  21. conscio-2.3.0/tests/test_skills_graft.py +55 -0
  22. {conscio-2.2.1 → conscio-2.3.0}/LICENSE +0 -0
  23. {conscio-2.2.1 → conscio-2.3.0}/MANIFEST.in +0 -0
  24. {conscio-2.2.1 → conscio-2.3.0}/conscio/__main__.py +0 -0
  25. {conscio-2.2.1 → conscio-2.3.0}/conscio/adapter_config.py +0 -0
  26. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/__init__.py +0 -0
  27. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/act.py +0 -0
  28. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/actor.py +0 -0
  29. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/adapter.py +0 -0
  30. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/adapters.py +0 -0
  31. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/breaker.py +0 -0
  32. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/contracts.py +0 -0
  33. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/fingerprint.py +0 -0
  34. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/gateway.py +0 -0
  35. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/grammar.py +0 -0
  36. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/host_act.py +0 -0
  37. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/ledger.py +0 -0
  38. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/loop.py +0 -0
  39. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/profiles.py +0 -0
  40. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/skeptic.py +0 -0
  41. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/tools.py +0 -0
  42. {conscio-2.2.1 → conscio-2.3.0}/conscio/agency/trust.py +0 -0
  43. {conscio-2.2.1 → conscio-2.3.0}/conscio/auto_evolution.py +0 -0
  44. {conscio-2.2.1 → conscio-2.3.0}/conscio/axis_pack.py +0 -0
  45. {conscio-2.2.1 → conscio-2.3.0}/conscio/bench.py +0 -0
  46. {conscio-2.2.1 → conscio-2.3.0}/conscio/coherence.py +0 -0
  47. {conscio-2.2.1 → conscio-2.3.0}/conscio/content_layer.py +0 -0
  48. {conscio-2.2.1 → conscio-2.3.0}/conscio/content_store.py +0 -0
  49. {conscio-2.2.1 → conscio-2.3.0}/conscio/context_manager.py +0 -0
  50. {conscio-2.2.1 → conscio-2.3.0}/conscio/daemon.py +0 -0
  51. {conscio-2.2.1 → conscio-2.3.0}/conscio/dreaming.py +0 -0
  52. {conscio-2.2.1 → conscio-2.3.0}/conscio/event_bus.py +0 -0
  53. {conscio-2.2.1 → conscio-2.3.0}/conscio/goal_generator.py +0 -0
  54. {conscio-2.2.1 → conscio-2.3.0}/conscio/guards.py +0 -0
  55. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/__init__.py +0 -0
  56. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/config.py +0 -0
  57. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/model_test.py +0 -0
  58. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/providers.py +0 -0
  59. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/server.py +0 -0
  60. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/static/app.js +0 -0
  61. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/static/index.html +0 -0
  62. {conscio-2.2.1 → conscio-2.3.0}/conscio/hub/static/style.css +0 -0
  63. {conscio-2.2.1 → conscio-2.3.0}/conscio/inner_monologue.py +0 -0
  64. {conscio-2.2.1 → conscio-2.3.0}/conscio/mcp/__init__.py +0 -0
  65. {conscio-2.2.1 → conscio-2.3.0}/conscio/mcp/jsonrpc.py +0 -0
  66. {conscio-2.2.1 → conscio-2.3.0}/conscio/mcp/protocol.py +0 -0
  67. {conscio-2.2.1 → conscio-2.3.0}/conscio/mcp/schemas.py +0 -0
  68. {conscio-2.2.1 → conscio-2.3.0}/conscio/mcp/seen.py +0 -0
  69. {conscio-2.2.1 → conscio-2.3.0}/conscio/mcp/server.py +0 -0
  70. {conscio-2.2.1 → conscio-2.3.0}/conscio/meta_cognition.py +0 -0
  71. {conscio-2.2.1 → conscio-2.3.0}/conscio/metabolic.py +0 -0
  72. {conscio-2.2.1 → conscio-2.3.0}/conscio/migrate.py +0 -0
  73. {conscio-2.2.1 → conscio-2.3.0}/conscio/models.py +0 -0
  74. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/__init__.py +0 -0
  75. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/artifact.py +0 -0
  76. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/audit.py +0 -0
  77. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/catalog.py +0 -0
  78. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/cli.py +0 -0
  79. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/identity.py +0 -0
  80. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/importer.py +0 -0
  81. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/paths.py +0 -0
  82. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/publish.py +0 -0
  83. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/record.py +0 -0
  84. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/record_catalog.py +0 -0
  85. {conscio-2.2.1 → conscio-2.3.0}/conscio/noosphere/record_publish.py +0 -0
  86. {conscio-2.2.1 → conscio-2.3.0}/conscio/output_filter.py +0 -0
  87. {conscio-2.2.1 → conscio-2.3.0}/conscio/perception/__init__.py +0 -0
  88. {conscio-2.2.1 → conscio-2.3.0}/conscio/perception/agent_sensor.py +0 -0
  89. {conscio-2.2.1 → conscio-2.3.0}/conscio/perception/host_sensor.py +0 -0
  90. {conscio-2.2.1 → conscio-2.3.0}/conscio/perception/sensor.py +0 -0
  91. {conscio-2.2.1 → conscio-2.3.0}/conscio/plugins.py +0 -0
  92. {conscio-2.2.1 → conscio-2.3.0}/conscio/presets/__init__.py +0 -0
  93. {conscio-2.2.1 → conscio-2.3.0}/conscio/py.typed +0 -0
  94. {conscio-2.2.1 → conscio-2.3.0}/conscio/risk.py +0 -0
  95. {conscio-2.2.1 → conscio-2.3.0}/conscio/self_prompt.py +0 -0
  96. {conscio-2.2.1 → conscio-2.3.0}/conscio/semantic.py +0 -0
  97. {conscio-2.2.1 → conscio-2.3.0}/conscio/session_lifecycle.py +0 -0
  98. {conscio-2.2.1 → conscio-2.3.0}/conscio/session_rag.py +0 -0
  99. {conscio-2.2.1 → conscio-2.3.0}/conscio/session_rag_factory.py +0 -0
  100. {conscio-2.2.1 → conscio-2.3.0}/conscio/shard_engine.py +0 -0
  101. {conscio-2.2.1 → conscio-2.3.0}/conscio/structural.py +0 -0
  102. {conscio-2.2.1 → conscio-2.3.0}/conscio/structural_consent.py +0 -0
  103. {conscio-2.2.1 → conscio-2.3.0}/conscio/structural_drift.py +0 -0
  104. {conscio-2.2.1 → conscio-2.3.0}/conscio/timeutil.py +0 -0
  105. {conscio-2.2.1 → conscio-2.3.0}/conscio/token_tracker.py +0 -0
  106. {conscio-2.2.1 → conscio-2.3.0}/conscio/voice_preset.py +0 -0
  107. {conscio-2.2.1 → conscio-2.3.0}/conscio/workspace.py +0 -0
  108. {conscio-2.2.1 → conscio-2.3.0}/conscio/world_model.py +0 -0
  109. {conscio-2.2.1 → conscio-2.3.0}/conscio.egg-info/dependency_links.txt +0 -0
  110. {conscio-2.2.1 → conscio-2.3.0}/conscio.egg-info/entry_points.txt +0 -0
  111. {conscio-2.2.1 → conscio-2.3.0}/conscio.egg-info/requires.txt +0 -0
  112. {conscio-2.2.1 → conscio-2.3.0}/conscio.egg-info/top_level.txt +0 -0
  113. {conscio-2.2.1 → conscio-2.3.0}/pyproject.toml +0 -0
  114. {conscio-2.2.1 → conscio-2.3.0}/setup.cfg +0 -0
  115. {conscio-2.2.1 → conscio-2.3.0}/tests/test_adapter_config.py +0 -0
  116. {conscio-2.2.1 → conscio-2.3.0}/tests/test_adapter_config_api_key_env.py +0 -0
  117. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_act.py +0 -0
  118. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_act_immunity.py +0 -0
  119. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_actor.py +0 -0
  120. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_adapter.py +0 -0
  121. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_adapters_http.py +0 -0
  122. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_adversarial.py +0 -0
  123. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_arbiter.py +0 -0
  124. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_bench.py +0 -0
  125. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_breaker.py +0 -0
  126. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_contracts.py +0 -0
  127. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_engine_immunity.py +0 -0
  128. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_gateway.py +0 -0
  129. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_grammar.py +0 -0
  130. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_host_act.py +0 -0
  131. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_ledger.py +0 -0
  132. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_ledger_v201.py +0 -0
  133. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_loop.py +0 -0
  134. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_no_network.py +0 -0
  135. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_profiles.py +0 -0
  136. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_skeptic.py +0 -0
  137. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_skills.py +0 -0
  138. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_skills_wiring.py +0 -0
  139. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_state.py +0 -0
  140. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_tools.py +0 -0
  141. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_tools_manifest.py +0 -0
  142. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_trust.py +0 -0
  143. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agency_volition.py +0 -0
  144. {conscio-2.2.1 → conscio-2.3.0}/tests/test_agent_sensor.py +0 -0
  145. {conscio-2.2.1 → conscio-2.3.0}/tests/test_auto_evolution.py +0 -0
  146. {conscio-2.2.1 → conscio-2.3.0}/tests/test_awake.py +0 -0
  147. {conscio-2.2.1 → conscio-2.3.0}/tests/test_axis_pack.py +0 -0
  148. {conscio-2.2.1 → conscio-2.3.0}/tests/test_axis_pack_battery.py +0 -0
  149. {conscio-2.2.1 → conscio-2.3.0}/tests/test_cli.py +0 -0
  150. {conscio-2.2.1 → conscio-2.3.0}/tests/test_coherence.py +0 -0
  151. {conscio-2.2.1 → conscio-2.3.0}/tests/test_coherence_engine_integration.py +0 -0
  152. {conscio-2.2.1 → conscio-2.3.0}/tests/test_coherence_state.py +0 -0
  153. {conscio-2.2.1 → conscio-2.3.0}/tests/test_consciousness.py +0 -0
  154. {conscio-2.2.1 → conscio-2.3.0}/tests/test_content_layer.py +0 -0
  155. {conscio-2.2.1 → conscio-2.3.0}/tests/test_content_layer_manager.py +0 -0
  156. {conscio-2.2.1 → conscio-2.3.0}/tests/test_content_store.py +0 -0
  157. {conscio-2.2.1 → conscio-2.3.0}/tests/test_content_store_battery.py +0 -0
  158. {conscio-2.2.1 → conscio-2.3.0}/tests/test_content_store_r05.py +0 -0
  159. {conscio-2.2.1 → conscio-2.3.0}/tests/test_contradiction_detector.py +0 -0
  160. {conscio-2.2.1 → conscio-2.3.0}/tests/test_daemon.py +0 -0
  161. {conscio-2.2.1 → conscio-2.3.0}/tests/test_daemon_battery.py +0 -0
  162. {conscio-2.2.1 → conscio-2.3.0}/tests/test_daemon_config.py +0 -0
  163. {conscio-2.2.1 → conscio-2.3.0}/tests/test_daemon_heartbeat.py +0 -0
  164. {conscio-2.2.1 → conscio-2.3.0}/tests/test_daemon_structure_sync.py +0 -0
  165. {conscio-2.2.1 → conscio-2.3.0}/tests/test_dream_coherence.py +0 -0
  166. {conscio-2.2.1 → conscio-2.3.0}/tests/test_dream_distill.py +0 -0
  167. {conscio-2.2.1 → conscio-2.3.0}/tests/test_dream_reconcile.py +0 -0
  168. {conscio-2.2.1 → conscio-2.3.0}/tests/test_dreaming.py +0 -0
  169. {conscio-2.2.1 → conscio-2.3.0}/tests/test_dreaming_friction.py +0 -0
  170. {conscio-2.2.1 → conscio-2.3.0}/tests/test_durable_guards.py +0 -0
  171. {conscio-2.2.1 → conscio-2.3.0}/tests/test_embedder.py +0 -0
  172. {conscio-2.2.1 → conscio-2.3.0}/tests/test_engine_advisory.py +0 -0
  173. {conscio-2.2.1 → conscio-2.3.0}/tests/test_engine_host_act.py +0 -0
  174. {conscio-2.2.1 → conscio-2.3.0}/tests/test_engine_init.py +0 -0
  175. {conscio-2.2.1 → conscio-2.3.0}/tests/test_engine_meta_reflect.py +0 -0
  176. {conscio-2.2.1 → conscio-2.3.0}/tests/test_engine_propose.py +0 -0
  177. {conscio-2.2.1 → conscio-2.3.0}/tests/test_engine_recall.py +0 -0
  178. {conscio-2.2.1 → conscio-2.3.0}/tests/test_event_bus.py +0 -0
  179. {conscio-2.2.1 → conscio-2.3.0}/tests/test_event_bus_act_result.py +0 -0
  180. {conscio-2.2.1 → conscio-2.3.0}/tests/test_event_bus_purge.py +0 -0
  181. {conscio-2.2.1 → conscio-2.3.0}/tests/test_examples.py +0 -0
  182. {conscio-2.2.1 → conscio-2.3.0}/tests/test_goal_provenance.py +0 -0
  183. {conscio-2.2.1 → conscio-2.3.0}/tests/test_goal_source.py +0 -0
  184. {conscio-2.2.1 → conscio-2.3.0}/tests/test_host_sensor.py +0 -0
  185. {conscio-2.2.1 → conscio-2.3.0}/tests/test_hub_config.py +0 -0
  186. {conscio-2.2.1 → conscio-2.3.0}/tests/test_hub_model_test.py +0 -0
  187. {conscio-2.2.1 → conscio-2.3.0}/tests/test_hub_providers.py +0 -0
  188. {conscio-2.2.1 → conscio-2.3.0}/tests/test_hub_server.py +0 -0
  189. {conscio-2.2.1 → conscio-2.3.0}/tests/test_loop_failure_brake.py +0 -0
  190. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_adapter_parity.py +0 -0
  191. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_battery.py +0 -0
  192. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_fuzz.py +0 -0
  193. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_jsonrpc.py +0 -0
  194. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_package.py +0 -0
  195. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_protocol.py +0 -0
  196. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_schemas.py +0 -0
  197. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_seen.py +0 -0
  198. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_server.py +0 -0
  199. {conscio-2.2.1 → conscio-2.3.0}/tests/test_mcp_server_cli.py +0 -0
  200. {conscio-2.2.1 → conscio-2.3.0}/tests/test_metabolic.py +0 -0
  201. {conscio-2.2.1 → conscio-2.3.0}/tests/test_migrate.py +0 -0
  202. {conscio-2.2.1 → conscio-2.3.0}/tests/test_model_auto_detect.py +0 -0
  203. {conscio-2.2.1 → conscio-2.3.0}/tests/test_model_offline_default.py +0 -0
  204. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_artifact.py +0 -0
  205. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_audit.py +0 -0
  206. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_audit_integration.py +0 -0
  207. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_catalog.py +0 -0
  208. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_cli.py +0 -0
  209. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_engine_free.py +0 -0
  210. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_fingerprint.py +0 -0
  211. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_identity.py +0 -0
  212. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_importer.py +0 -0
  213. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_integration.py +0 -0
  214. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_parity.py +0 -0
  215. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_paths.py +0 -0
  216. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_publish.py +0 -0
  217. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_quarantine.py +0 -0
  218. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_record.py +0 -0
  219. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_record_catalog.py +0 -0
  220. {conscio-2.2.1 → conscio-2.3.0}/tests/test_noosphere_record_publish.py +0 -0
  221. {conscio-2.2.1 → conscio-2.3.0}/tests/test_ontological_semantic.py +0 -0
  222. {conscio-2.2.1 → conscio-2.3.0}/tests/test_output_filter.py +0 -0
  223. {conscio-2.2.1 → conscio-2.3.0}/tests/test_output_filter_stages.py +0 -0
  224. {conscio-2.2.1 → conscio-2.3.0}/tests/test_packaging.py +0 -0
  225. {conscio-2.2.1 → conscio-2.3.0}/tests/test_perception.py +0 -0
  226. {conscio-2.2.1 → conscio-2.3.0}/tests/test_perf_reflection.py +0 -0
  227. {conscio-2.2.1 → conscio-2.3.0}/tests/test_plugins.py +0 -0
  228. {conscio-2.2.1 → conscio-2.3.0}/tests/test_recursive_loop_integration.py +0 -0
  229. {conscio-2.2.1 → conscio-2.3.0}/tests/test_risk.py +0 -0
  230. {conscio-2.2.1 → conscio-2.3.0}/tests/test_self_prompt.py +0 -0
  231. {conscio-2.2.1 → conscio-2.3.0}/tests/test_self_prompt_state.py +0 -0
  232. {conscio-2.2.1 → conscio-2.3.0}/tests/test_semantic_dedup.py +0 -0
  233. {conscio-2.2.1 → conscio-2.3.0}/tests/test_semantic_engine.py +0 -0
  234. {conscio-2.2.1 → conscio-2.3.0}/tests/test_semantic_reconcile_integration.py +0 -0
  235. {conscio-2.2.1 → conscio-2.3.0}/tests/test_session_lifecycle.py +0 -0
  236. {conscio-2.2.1 → conscio-2.3.0}/tests/test_session_lifecycle_battery.py +0 -0
  237. {conscio-2.2.1 → conscio-2.3.0}/tests/test_session_lifecycle_dream.py +0 -0
  238. {conscio-2.2.1 → conscio-2.3.0}/tests/test_session_rag.py +0 -0
  239. {conscio-2.2.1 → conscio-2.3.0}/tests/test_shard_engine.py +0 -0
  240. {conscio-2.2.1 → conscio-2.3.0}/tests/test_state_loaders_battery.py +0 -0
  241. {conscio-2.2.1 → conscio-2.3.0}/tests/test_state_persistence_battery.py +0 -0
  242. {conscio-2.2.1 → conscio-2.3.0}/tests/test_structural.py +0 -0
  243. {conscio-2.2.1 → conscio-2.3.0}/tests/test_structural_consent.py +0 -0
  244. {conscio-2.2.1 → conscio-2.3.0}/tests/test_structural_drift.py +0 -0
  245. {conscio-2.2.1 → conscio-2.3.0}/tests/test_structural_inject.py +0 -0
  246. {conscio-2.2.1 → conscio-2.3.0}/tests/test_timeutil.py +0 -0
  247. {conscio-2.2.1 → conscio-2.3.0}/tests/test_token_tracker.py +0 -0
  248. {conscio-2.2.1 → conscio-2.3.0}/tests/test_trajectory_vector.py +0 -0
  249. {conscio-2.2.1 → conscio-2.3.0}/tests/test_v2_debt_zero.py +0 -0
  250. {conscio-2.2.1 → conscio-2.3.0}/tests/test_voice_preset.py +0 -0
  251. {conscio-2.2.1 → conscio-2.3.0}/tests/test_workspace.py +0 -0
  252. {conscio-2.2.1 → conscio-2.3.0}/tests/test_world_contradictions.py +0 -0
  253. {conscio-2.2.1 → conscio-2.3.0}/tests/test_world_model_entropy.py +0 -0
  254. {conscio-2.2.1 → conscio-2.3.0}/tests/test_world_model_prediction.py +0 -0
  255. {conscio-2.2.1 → conscio-2.3.0}/tests/test_world_model_prune.py +0 -0
@@ -7,6 +7,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [2.3.0] - 2026-06-23 — "Promotion"
11
+
12
+ ### Added
13
+ - **Promotion-to-live.** `conscio promote --storage DIR --quarantine ROWID
14
+ --enable-promote` graduates a quarantined foreign skill that has earned
15
+ **≥ 3 clean local trials** (v2.2.2) into the live `SkillLibrary`, seeded with
16
+ the counters it earned **locally** in the sandbox — never the origin's
17
+ (stripped) stats, so no trust is inherited. Engine-side
18
+ (`engine.promote_quarantined`); the noosphere package stays engine-free and
19
+ read-only on `conscio.db`.
20
+ - **Tool-existence check** (deferred from v2.2). Promotion refuses a skill
21
+ whose plan names a tool this instance's live registry does not have.
22
+ - `SkillLibrary.graft` — the single foreign-skill write seam
23
+ (`ON CONFLICT(goal_fp, tool_seq) DO NOTHING`; never overwrites a local skill).
24
+ - Quarantine rows gain `promoted_ts` / `promoted_skill_id` (idempotency +
25
+ audit). Promotion re-checks the content hash (tamper → refuse, no write) and
26
+ is idempotent. `--enable-promote` is required, default off, and **independent
27
+ of** `--enable-trial` / `--enable-act`.
28
+
29
+ ---
30
+
31
+ ## [2.2.2] - 2026-06-22 — "Trial / execution path"
32
+
33
+ ### Added
34
+ - **Sandboxed trial of a quarantined skill.** A quarantined imported skill can
35
+ now be replayed in a **throwaway, fs-only sandbox** to earn local,
36
+ execution-grade pass/fail stats — `conscio trial --storage DIR --quarantine
37
+ ROWID --model NAME --enable-trial`. The foreign plan's fixed steps run through
38
+ the full safety stack (`validate → precheck → HIGH-block → Skeptic → dispatch`)
39
+ against a `make_default_registry` confined to a `mkdtemp` dir (`fs_read`/
40
+ `fs_write` only), stopping at the first failure. Binary outcome
41
+ (`trial_successes`/`trial_failures` + `last_trial_*`) is recorded on the
42
+ quarantine row; v2.3 promotion will read it.
43
+ - **Trial isolation.** A trial never writes the agent's `ActionLedger`, `skills`
44
+ table, `TrustMatrix`, or trips the breaker — a foreign skill's failure cannot
45
+ dent the local agent. The sandbox dir is always removed; tamper / corrupt-plan
46
+ refuse **without** bumping any counter.
47
+ - **Opt-in, default off.** `--enable-trial` is required to dispatch and is
48
+ independent of `--enable-act` (trial uses the local sandboxed registry, never
49
+ `host_act`). Skeptic always audits foreign content (no LOW-risk fast path).
50
+ - New engine method `ConsciousnessEngine.trial_quarantined(rowid, *,
51
+ enable_trial=False)`; new `conscio/agency/trial.py` (engine-side mechanic,
52
+ imports nothing from `noosphere`); `noosphere/quarantine.py` gains 5 trial
53
+ columns + an idempotent `PRAGMA table_info` migration + `record_trial` /
54
+ `note_trial` (still engine-free). Purely additive; cognition untouched.
55
+
10
56
  ## [2.2.1] - 2026-06-22 — "Mutual audit"
11
57
 
12
58
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conscio
3
- Version: 2.2.1
3
+ Version: 2.3.0
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.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 promoted trust is never inherited.
49
+ - **Current release:** `v2.3.0` — "Promotion": a quarantined skill that has earned **≥ 3 clean local trials** can now be **graduated into the live skill library**. `conscio promote --quarantine ROWID --enable-promote` re-checks the content hash, verifies every tool in the plan exists locally (**tool-existence check**), and grafts the skill seeded with the counters it earned in the sandbox **never the origin's stats**, so no trust is inherited. Engine-side write; the noosphere stays engine-free and read-only on `conscio.db`. Never overwrites a local skill; idempotent; off by default and independent of `--enable-trial`/`--enable-act`. `pip install conscio`.
50
+ - **Prior:** `v2.2.2` — "Trial / execution path": a quarantined imported skill can **prove itself locally** before promotion `conscio trial --quarantine ROWID --enable-trial` replays the fixed foreign plan 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`.
51
+ - **Earlier:** `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.
52
+ - **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.
51
53
  - **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.
52
54
  - **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.
53
55
  - **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).
@@ -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.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 promoted trust is never inherited.
14
+ - **Current release:** `v2.3.0` — "Promotion": a quarantined skill that has earned **≥ 3 clean local trials** can now be **graduated into the live skill library**. `conscio promote --quarantine ROWID --enable-promote` re-checks the content hash, verifies every tool in the plan exists locally (**tool-existence check**), and grafts the skill seeded with the counters it earned in the sandbox **never the origin's stats**, so no trust is inherited. Engine-side write; the noosphere stays engine-free and read-only on `conscio.db`. Never overwrites a local skill; idempotent; off by default and independent of `--enable-trial`/`--enable-act`. `pip install conscio`.
15
+ - **Prior:** `v2.2.2` — "Trial / execution path": a quarantined imported skill can **prove itself locally** before promotion `conscio trial --quarantine ROWID --enable-trial` replays the fixed foreign plan 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`.
16
+ - **Earlier:** `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.
17
+ - **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.
16
18
  - **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.
17
19
  - **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.
18
20
  - **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).
@@ -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.1"
9
+ __version__ = "2.3.0"
10
10
  __author__ = "Neguiolidas / Neguitech"
11
11
 
12
12
  from .engine import ConsciousnessEngine
@@ -0,0 +1,55 @@
1
+ # conscio/agency/promote.py
2
+ """Promotion gate for a quarantined foreign skill (v2.3.0).
3
+
4
+ A pure mechanic: given a quarantined row's trial counters and tool sequence,
5
+ decide whether it has earned graduation into the live SkillLibrary. Imports
6
+ nothing from conscio.noosphere or conscio.engine. The caller (the engine) owns
7
+ the read of the quarantine row, the graft into the library, and the
8
+ promoted-stamp; this module only judges."""
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from dataclasses import dataclass
13
+ from typing import Any
14
+
15
+ MIN_PROMOTE_PASSES = 3 # clean local trials required before graduation
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class PromoteResult:
20
+ skill_id: int
21
+ successes: int
22
+ failures: int
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class PromoteRefusal:
27
+ reason: str
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class PromoteDecision:
32
+ ok: bool
33
+ reason: str # "" when ok
34
+
35
+
36
+ def evaluate_promotion(*, trial_successes: int, trial_failures: int,
37
+ tool_seq: str, registry: Any) -> PromoteDecision:
38
+ """Gate a quarantined row for promotion. Order: enough clean passes, zero
39
+ failures, decodable tool_seq, every tool present in the live registry."""
40
+ if trial_successes < MIN_PROMOTE_PASSES:
41
+ return PromoteDecision(
42
+ False,
43
+ f"insufficient trials ({trial_successes}/{MIN_PROMOTE_PASSES})")
44
+ if trial_failures != 0:
45
+ return PromoteDecision(False, f"failed {trial_failures} trial(s)")
46
+ try:
47
+ tools = json.loads(tool_seq)
48
+ if not isinstance(tools, list):
49
+ raise ValueError("tool_seq is not a list")
50
+ except (ValueError, TypeError) as exc:
51
+ return PromoteDecision(False, f"corrupt tool_seq: {exc}")
52
+ for tool in tools:
53
+ if registry.get(str(tool)) is None:
54
+ return PromoteDecision(False, f"unknown tool '{tool}'")
55
+ return PromoteDecision(True, "")
@@ -166,6 +166,26 @@ class SkillLibrary:
166
166
  [(skill_id,) for skill_id in served])
167
167
  self._conn.commit()
168
168
 
169
+ # ── promotion (v2.3) ────────────────────────────────────────────────
170
+
171
+ def graft(self, goal_fp: str, goal_text: str, tool_seq: str,
172
+ plan_template: str, *, successes: int,
173
+ failures: int) -> int | None:
174
+ """Insert a promoted foreign skill as data, seeded with the trial
175
+ counters it earned locally. The single write seam for foreign skills.
176
+ Never overwrites a local skill sharing (goal_fp, tool_seq): a collision
177
+ returns None."""
178
+ cur = self._conn.execute(
179
+ "INSERT INTO skills (created_ts, goal_fp, goal_text, tool_seq,"
180
+ " plan_template, successes, failures) VALUES (?, ?, ?, ?, ?, ?, ?)"
181
+ " ON CONFLICT(goal_fp, tool_seq) DO NOTHING",
182
+ (time.time(), goal_fp, goal_text, tool_seq, plan_template,
183
+ successes, failures))
184
+ self._conn.commit()
185
+ if cur.rowcount == 0 or cur.lastrowid is None:
186
+ return None
187
+ return int(cur.lastrowid)
188
+
169
189
  # ── rendering ──────────────────────────────────────────────────────
170
190
 
171
191
  @staticmethod
@@ -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)
@@ -68,6 +68,30 @@ 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
+
83
+ p_promote = sub.add_parser(
84
+ "promote",
85
+ help="promote a trialed quarantined skill into the live library")
86
+ p_promote.add_argument("--storage", default="",
87
+ help="instance storage dir (default: ~/.hermes)")
88
+ p_promote.add_argument("--quarantine", type=int, required=True,
89
+ metavar="ROWID",
90
+ help="quarantine row id to promote")
91
+ p_promote.add_argument(
92
+ "--enable-promote", action="store_true",
93
+ help="required: actually write to the live library (off by default)")
94
+
71
95
  # Listed for discoverability; routed to conscio.{bench,daemon} before argparse.
72
96
  sub.add_parser("bench", add_help=False,
73
97
  help="measure an inference backend (see: conscio bench --help)")
@@ -231,6 +255,85 @@ def _cmd_structure(storage: str) -> int:
231
255
  return 0
232
256
 
233
257
 
258
+ def _run_trial(*, model: str, storage: str, quarantine_id: int,
259
+ enable_trial: bool):
260
+ """Build an engine with an adapter and run one trial. The single seam the
261
+ CLI tests monkeypatch (so they never build a real adapter)."""
262
+ from .adapter_config import build_adapter_from_config, load_config
263
+ from .engine import ConsciousnessEngine
264
+ eng = ConsciousnessEngine(model_name=model, storage_path=_storage(storage))
265
+ try:
266
+ adapter, _ = build_adapter_from_config(load_config(),
267
+ fallback_model=model)
268
+ eng.attach_adapter(adapter)
269
+ return eng.trial_quarantined(quarantine_id, enable_trial=enable_trial)
270
+ finally:
271
+ eng.close()
272
+
273
+
274
+ def _cmd_trial(model: str, storage: str, quarantine_id: int,
275
+ enable_trial: bool) -> int:
276
+ from .agency.trial import TrialRefusal
277
+ try:
278
+ outcome = _run_trial(model=model, storage=storage,
279
+ quarantine_id=quarantine_id,
280
+ enable_trial=enable_trial)
281
+ except Exception as exc: # adapter build / engine wiring failure
282
+ print(f"error: {exc}")
283
+ return 1
284
+ if isinstance(outcome, TrialRefusal):
285
+ print(f"error: {outcome.reason}")
286
+ return 1
287
+ if outcome.passed:
288
+ print(f"TRIAL PASSED (#{quarantine_id})")
289
+ else:
290
+ print(f"TRIAL FAILED (#{quarantine_id}): {outcome.result}")
291
+ if outcome.error:
292
+ print(f" {outcome.error}")
293
+ # best-effort: show the running counts (skipped if the row can't be read)
294
+ try:
295
+ from .noosphere import quarantine
296
+ from .noosphere.paths import quarantine_db_path
297
+ row = quarantine.get(quarantine_db_path(Path(_storage(storage))),
298
+ quarantine_id)
299
+ if row is not None:
300
+ print(f" trials: {row.trial_successes} passed / "
301
+ f"{row.trial_failures} failed")
302
+ except Exception:
303
+ pass
304
+ return 0
305
+
306
+
307
+ def _run_promote(*, storage: str, quarantine_id: int, enable_promote: bool):
308
+ """Build a bare engine (no adapter — promotion never decodes) and promote
309
+ one quarantined skill. The single seam the CLI tests monkeypatch."""
310
+ from .engine import ConsciousnessEngine
311
+ eng = ConsciousnessEngine(model_name=DEFAULT_MODEL,
312
+ storage_path=_storage(storage))
313
+ try:
314
+ return eng.promote_quarantined(quarantine_id,
315
+ enable_promote=enable_promote)
316
+ finally:
317
+ eng.close()
318
+
319
+
320
+ def _cmd_promote(storage: str, quarantine_id: int,
321
+ enable_promote: bool) -> int:
322
+ from .agency.promote import PromoteResult
323
+ try:
324
+ outcome = _run_promote(storage=storage, quarantine_id=quarantine_id,
325
+ enable_promote=enable_promote)
326
+ except Exception as exc: # engine wiring failure
327
+ print(f"error: {exc}")
328
+ return 1
329
+ if isinstance(outcome, PromoteResult):
330
+ print(f"PROMOTED skill #{outcome.skill_id} "
331
+ f"(seeded {outcome.successes}/{outcome.failures})")
332
+ return 0
333
+ print(f"PROMOTE REFUSED: {outcome.reason}")
334
+ return 1
335
+
336
+
234
337
  def main(argv: list[str] | None = None) -> int:
235
338
  argv = list(sys.argv[1:] if argv is None else argv)
236
339
 
@@ -266,6 +369,12 @@ def main(argv: list[str] | None = None) -> int:
266
369
  return _cmd_set_awake(args.model, args.storage, awake=True)
267
370
  if args.command == "sleep":
268
371
  return _cmd_set_awake(args.model, args.storage, awake=False)
372
+ if args.command == "trial":
373
+ return _cmd_trial(args.model, args.storage, args.quarantine,
374
+ args.enable_trial)
375
+ if args.command == "promote":
376
+ return _cmd_promote(args.storage, args.quarantine,
377
+ args.enable_promote)
269
378
 
270
379
  parser.print_help()
271
380
  return 2
@@ -1001,6 +1001,142 @@ 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
+
1067
+ # --- v2.3 "Promotion": graduate a quarantined skill into the library ---
1068
+
1069
+ def promote_quarantined(self, rowid: int, *, enable_promote: bool = False):
1070
+ """Graduate a quarantined foreign skill that has earned >= 3 clean
1071
+ local trials into the live SkillLibrary, seeded with its trial
1072
+ counters. No adapter, no sandbox, no execution: a data gate that reads
1073
+ the trial evidence and writes one row. Default off.
1074
+
1075
+ Unlike trial (which records a tamper via note_trial), promotion refuses
1076
+ a tampered/already-promoted/gate-failed row WITHOUT writing anything —
1077
+ it only ever writes on a successful graft (the skills row + the
1078
+ promoted-stamp). A refusal leaves the quarantine row untouched.
1079
+
1080
+ Returns a promote.PromoteResult (promoted) or promote.PromoteRefusal."""
1081
+ import time
1082
+
1083
+ from .agency import promote as promote_mod
1084
+ from .agency.skills import SkillLibrary
1085
+ from .agency.tools import make_default_registry
1086
+ from .noosphere import artifact, quarantine
1087
+ from .noosphere.paths import quarantine_db_path
1088
+
1089
+ if not enable_promote:
1090
+ return promote_mod.PromoteRefusal(
1091
+ "promotion disabled; pass --enable-promote")
1092
+
1093
+ qdb = quarantine_db_path(self.storage)
1094
+ row = quarantine.get(qdb, rowid)
1095
+ if row is None:
1096
+ return promote_mod.PromoteRefusal(f"no quarantine row #{rowid}")
1097
+ if row.import_status != "quarantined":
1098
+ return promote_mod.PromoteRefusal(
1099
+ f"row #{rowid} is not quarantined "
1100
+ f"(status={row.import_status})")
1101
+ if row.promoted_ts > 0:
1102
+ return promote_mod.PromoteRefusal(
1103
+ f"row #{rowid} already promoted "
1104
+ f"(skill #{row.promoted_skill_id})")
1105
+ if artifact.content_hash(row.artifact_json) != row.content_sha256:
1106
+ return promote_mod.PromoteRefusal(
1107
+ f"row #{rowid} tampered (content_sha256 mismatch)")
1108
+
1109
+ # Live tool registry, real backends. Used ONLY for registry.get(tool)
1110
+ # existence checks — nothing is dispatched, so no tmpdir is needed (the
1111
+ # one structural difference from trial). make_default_registry mkdirs
1112
+ # sandbox_root, so it points inside the instance storage (never real
1113
+ # home), keeping promotion and its tests side-effect-clean.
1114
+ reg = make_default_registry(
1115
+ sandbox_root=self.storage / "sandbox",
1116
+ content_store=self.content_store, event_bus=self.event_bus,
1117
+ goal_generator=self.goals)
1118
+ decision = promote_mod.evaluate_promotion(
1119
+ trial_successes=row.trial_successes,
1120
+ trial_failures=row.trial_failures,
1121
+ tool_seq=row.tool_seq, registry=reg)
1122
+ if not decision.ok:
1123
+ return promote_mod.PromoteRefusal(decision.reason)
1124
+
1125
+ lib = SkillLibrary(self.storage / "conscio.db")
1126
+ try:
1127
+ sid = lib.graft(row.goal_fp, row.goal_text, row.tool_seq,
1128
+ row.plan_template, successes=row.trial_successes,
1129
+ failures=row.trial_failures)
1130
+ finally:
1131
+ lib.close()
1132
+ if sid is None:
1133
+ return promote_mod.PromoteRefusal(
1134
+ "skill already present (goal_fp, tool_seq collision)")
1135
+
1136
+ quarantine.mark_promoted(qdb, rowid, ts=time.time(), skill_id=sid)
1137
+ return promote_mod.PromoteResult(sid, row.trial_successes,
1138
+ row.trial_failures)
1139
+
1004
1140
  # --- v2.0 "Connect": propose-only cognition (never executes) ---
1005
1141
 
1006
1142
  def propose_action(self, intent: dict) -> dict: