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