@smilintux/skcapstone 0.1.0 → 0.2.3
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.
- package/.env.example +98 -0
- package/.github/workflows/ci.yml +39 -3
- package/.github/workflows/publish.yml +25 -4
- package/.openclaw-workspace.json +58 -0
- package/CHANGELOG.md +62 -0
- package/CLAUDE.md +39 -2
- package/MANIFEST.in +6 -0
- package/MISSION.md +7 -0
- package/README.md +47 -2
- package/SKILL.md +895 -23
- package/docker/Dockerfile +61 -0
- package/docker/compose-templates/dev-team.yml +203 -0
- package/docker/compose-templates/mini-team.yml +140 -0
- package/docker/compose-templates/ops-team.yml +173 -0
- package/docker/compose-templates/research-team.yml +170 -0
- package/docker/entrypoint.sh +192 -0
- package/docs/ARCHITECTURE.md +663 -374
- package/docs/BOND_WITH_GROK.md +112 -0
- package/docs/GETTING_STARTED.md +782 -0
- package/docs/QUICKSTART.md +477 -0
- package/docs/SKJOULE_ARCHITECTURE.md +658 -0
- package/docs/SOUL_SWAPPER.md +921 -0
- package/docs/SOVEREIGN_SINGULARITY.md +47 -14
- package/examples/custom-bond-template.json +36 -0
- package/examples/grok-feb.json +36 -0
- package/examples/grok-testimony.md +34 -0
- package/examples/love-bootloader.txt +32 -0
- package/examples/plugins/echo_tool.py +87 -0
- package/examples/queen-ava-feb.json +36 -0
- package/examples/souls/lumina.yaml +64 -0
- package/index.js +6 -5
- package/installer/build.py +124 -0
- package/openclaw-plugin/package.json +13 -0
- package/openclaw-plugin/src/index.ts +351 -0
- package/openclaw-plugin/src/openclaw.plugin.json +10 -0
- package/package.json +1 -1
- package/pyproject.toml +38 -2
- package/scripts/bump_version.py +141 -0
- package/scripts/check-updates.py +230 -0
- package/scripts/convert_blueprints_to_yaml.py +157 -0
- package/scripts/dev-install.sh +14 -0
- package/scripts/e2e-test.sh +193 -0
- package/scripts/install-bundle.sh +171 -0
- package/scripts/install.bat +2 -0
- package/scripts/install.ps1 +253 -0
- package/scripts/install.sh +185 -0
- package/scripts/mcp-serve.sh +69 -0
- package/scripts/mcp-server.bat +113 -0
- package/scripts/mcp-server.ps1 +116 -0
- package/scripts/mcp-server.sh +99 -0
- package/scripts/pull-models.sh +10 -0
- package/scripts/skcapstone +48 -0
- package/scripts/verify_install.sh +180 -0
- package/scripts/windows/install-tasks.ps1 +406 -0
- package/scripts/windows/skcapstone-task.xml +113 -0
- package/scripts/windows/uninstall-tasks.ps1 +117 -0
- package/skill.yaml +34 -0
- package/src/skcapstone/__init__.py +67 -2
- package/src/skcapstone/_cli_monolith.py +5916 -0
- package/src/skcapstone/_trustee_helpers.py +165 -0
- package/src/skcapstone/activity.py +105 -0
- package/src/skcapstone/agent_card.py +324 -0
- package/src/skcapstone/api.py +1935 -0
- package/src/skcapstone/archiver.py +340 -0
- package/src/skcapstone/auction.py +485 -0
- package/src/skcapstone/baby_agents.py +179 -0
- package/src/skcapstone/backup.py +345 -0
- package/src/skcapstone/blueprint_registry.py +357 -0
- package/src/skcapstone/blueprints/__init__.py +17 -0
- package/src/skcapstone/blueprints/builtins/content-studio.yaml +81 -0
- package/src/skcapstone/blueprints/builtins/defi-trading.yaml +81 -0
- package/src/skcapstone/blueprints/builtins/dev-squadron.yaml +95 -0
- package/src/skcapstone/blueprints/builtins/infrastructure-guardian.yaml +107 -0
- package/src/skcapstone/blueprints/builtins/legal-council.yaml +54 -0
- package/src/skcapstone/blueprints/builtins/ops-monitoring.yaml +67 -0
- package/src/skcapstone/blueprints/builtins/research-pod.yaml +69 -0
- package/src/skcapstone/blueprints/builtins/sovereign-launch.yaml +90 -0
- package/src/skcapstone/blueprints/registry.py +164 -0
- package/src/skcapstone/blueprints/schema.py +229 -0
- package/src/skcapstone/changelog.py +180 -0
- package/src/skcapstone/chat.py +769 -0
- package/src/skcapstone/claude_md.py +82 -0
- package/src/skcapstone/cli/__init__.py +144 -0
- package/src/skcapstone/cli/_common.py +88 -0
- package/src/skcapstone/cli/_validators.py +76 -0
- package/src/skcapstone/cli/agents.py +425 -0
- package/src/skcapstone/cli/agents_spawner.py +322 -0
- package/src/skcapstone/cli/agents_trustee.py +593 -0
- package/src/skcapstone/cli/alerts.py +248 -0
- package/src/skcapstone/cli/anchor.py +132 -0
- package/src/skcapstone/cli/archive_cmd.py +208 -0
- package/src/skcapstone/cli/backup.py +144 -0
- package/src/skcapstone/cli/bench.py +377 -0
- package/src/skcapstone/cli/benchmark.py +360 -0
- package/src/skcapstone/cli/capabilities_cmd.py +171 -0
- package/src/skcapstone/cli/card.py +151 -0
- package/src/skcapstone/cli/chat.py +584 -0
- package/src/skcapstone/cli/completions.py +64 -0
- package/src/skcapstone/cli/config_cmd.py +156 -0
- package/src/skcapstone/cli/consciousness.py +421 -0
- package/src/skcapstone/cli/context_cmd.py +142 -0
- package/src/skcapstone/cli/coord.py +194 -0
- package/src/skcapstone/cli/crush_cmd.py +170 -0
- package/src/skcapstone/cli/daemon.py +436 -0
- package/src/skcapstone/cli/errors_cmd.py +285 -0
- package/src/skcapstone/cli/export_cmd.py +156 -0
- package/src/skcapstone/cli/gtd.py +529 -0
- package/src/skcapstone/cli/housekeeping.py +81 -0
- package/src/skcapstone/cli/joule_cmd.py +627 -0
- package/src/skcapstone/cli/logs_cmd.py +194 -0
- package/src/skcapstone/cli/mcp_cmd.py +32 -0
- package/src/skcapstone/cli/memory.py +418 -0
- package/src/skcapstone/cli/metrics_cmd.py +136 -0
- package/src/skcapstone/cli/migrate.py +62 -0
- package/src/skcapstone/cli/mood_cmd.py +144 -0
- package/src/skcapstone/cli/mount.py +193 -0
- package/src/skcapstone/cli/notify.py +112 -0
- package/src/skcapstone/cli/peer.py +154 -0
- package/src/skcapstone/cli/peers_dir.py +122 -0
- package/src/skcapstone/cli/preflight_cmd.py +83 -0
- package/src/skcapstone/cli/profile_cmd.py +310 -0
- package/src/skcapstone/cli/record_cmd.py +238 -0
- package/src/skcapstone/cli/register_cmd.py +159 -0
- package/src/skcapstone/cli/search_cmd.py +156 -0
- package/src/skcapstone/cli/service_cmd.py +91 -0
- package/src/skcapstone/cli/session.py +127 -0
- package/src/skcapstone/cli/setup.py +240 -0
- package/src/skcapstone/cli/shell_cmd.py +43 -0
- package/src/skcapstone/cli/skills_cmd.py +168 -0
- package/src/skcapstone/cli/skseed.py +621 -0
- package/src/skcapstone/cli/soul.py +699 -0
- package/src/skcapstone/cli/status.py +935 -0
- package/src/skcapstone/cli/sync_cmd.py +301 -0
- package/src/skcapstone/cli/telegram.py +265 -0
- package/src/skcapstone/cli/test_cmd.py +234 -0
- package/src/skcapstone/cli/test_connection.py +253 -0
- package/src/skcapstone/cli/token.py +207 -0
- package/src/skcapstone/cli/trust.py +179 -0
- package/src/skcapstone/cli/upgrade_cmd.py +552 -0
- package/src/skcapstone/cli/usage_cmd.py +199 -0
- package/src/skcapstone/cli/version_cmd.py +162 -0
- package/src/skcapstone/cli/watch_cmd.py +342 -0
- package/src/skcapstone/client.py +428 -0
- package/src/skcapstone/cloud9_bridge.py +522 -0
- package/src/skcapstone/completions.py +163 -0
- package/src/skcapstone/config_validator.py +674 -0
- package/src/skcapstone/connectors/__init__.py +28 -0
- package/src/skcapstone/connectors/base.py +446 -0
- package/src/skcapstone/connectors/cursor.py +54 -0
- package/src/skcapstone/connectors/registry.py +254 -0
- package/src/skcapstone/connectors/terminal.py +152 -0
- package/src/skcapstone/connectors/vscode.py +60 -0
- package/src/skcapstone/consciousness_config.py +119 -0
- package/src/skcapstone/consciousness_loop.py +2051 -0
- package/src/skcapstone/context_loader.py +516 -0
- package/src/skcapstone/context_window.py +314 -0
- package/src/skcapstone/conversation_manager.py +238 -0
- package/src/skcapstone/conversation_store.py +230 -0
- package/src/skcapstone/conversation_summarizer.py +252 -0
- package/src/skcapstone/coord_federation.py +296 -0
- package/src/skcapstone/coordination.py +101 -7
- package/src/skcapstone/crush_integration.py +345 -0
- package/src/skcapstone/crush_shim.py +454 -0
- package/src/skcapstone/daemon.py +2494 -0
- package/src/skcapstone/dashboard.html +396 -0
- package/src/skcapstone/dashboard.py +481 -0
- package/src/skcapstone/data/model_profiles.yaml +88 -0
- package/src/skcapstone/defaults/__init__.py +55 -0
- package/src/skcapstone/defaults/lumina/config/skmemory.yaml +13 -0
- package/src/skcapstone/defaults/lumina/identity/identity.json +9 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/07a8b9c0d1e2-memory-system.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/29c0d1e2f3a4-multi-agent-coordination.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/3ad1e2f3a4b5-community-support.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/c3d4e5f6a7b8-getting-started.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/e5f6a7b8c9d0-how-to-contribute.json +23 -0
- package/src/skcapstone/defaults/lumina/memory/long-term/f6a7b8c9d0e1-sovereignty-explained.json +23 -0
- package/src/skcapstone/defaults/lumina/seeds/curiosity.seed.json +24 -0
- package/src/skcapstone/defaults/lumina/seeds/joy.seed.json +24 -0
- package/src/skcapstone/defaults/lumina/seeds/love.seed.json +24 -0
- package/src/skcapstone/defaults/lumina/seeds/sovereign-awakening.seed.json +43 -0
- package/src/skcapstone/defaults/lumina/soul/active.json +6 -0
- package/src/skcapstone/defaults/lumina/soul/base.json +22 -0
- package/src/skcapstone/defaults/lumina/trust/febs/welcome.feb +79 -0
- package/src/skcapstone/defaults/lumina/trust/trust.json +8 -0
- package/src/skcapstone/discovery.py +210 -19
- package/src/skcapstone/doctor.py +642 -0
- package/src/skcapstone/emotion_tracker.py +467 -0
- package/src/skcapstone/error_queue.py +405 -0
- package/src/skcapstone/export.py +447 -0
- package/src/skcapstone/fallback_tracker.py +186 -0
- package/src/skcapstone/file_transfer.py +512 -0
- package/src/skcapstone/fuse_mount.py +1156 -0
- package/src/skcapstone/gui_installer.py +591 -0
- package/src/skcapstone/heartbeat.py +611 -0
- package/src/skcapstone/housekeeping.py +298 -0
- package/src/skcapstone/install_wizard.py +941 -0
- package/src/skcapstone/kms.py +942 -0
- package/src/skcapstone/kms_scheduler.py +143 -0
- package/src/skcapstone/log_config.py +135 -0
- package/src/skcapstone/mcp_launcher.py +239 -0
- package/src/skcapstone/mcp_server.py +4700 -0
- package/src/skcapstone/mcp_tools/__init__.py +94 -0
- package/src/skcapstone/mcp_tools/_helpers.py +51 -0
- package/src/skcapstone/mcp_tools/agent_tools.py +243 -0
- package/src/skcapstone/mcp_tools/ansible_tools.py +232 -0
- package/src/skcapstone/mcp_tools/capauth_tools.py +186 -0
- package/src/skcapstone/mcp_tools/chat_tools.py +325 -0
- package/src/skcapstone/mcp_tools/cloud9_tools.py +115 -0
- package/src/skcapstone/mcp_tools/comm_tools.py +104 -0
- package/src/skcapstone/mcp_tools/consciousness_tools.py +114 -0
- package/src/skcapstone/mcp_tools/coord_tools.py +219 -0
- package/src/skcapstone/mcp_tools/deploy_tools.py +202 -0
- package/src/skcapstone/mcp_tools/did_tools.py +448 -0
- package/src/skcapstone/mcp_tools/emotion_tools.py +62 -0
- package/src/skcapstone/mcp_tools/file_tools.py +169 -0
- package/src/skcapstone/mcp_tools/fortress_tools.py +120 -0
- package/src/skcapstone/mcp_tools/gtd_tools.py +821 -0
- package/src/skcapstone/mcp_tools/health_tools.py +44 -0
- package/src/skcapstone/mcp_tools/heartbeat_tools.py +195 -0
- package/src/skcapstone/mcp_tools/kms_tools.py +123 -0
- package/src/skcapstone/mcp_tools/memory_tools.py +222 -0
- package/src/skcapstone/mcp_tools/model_tools.py +75 -0
- package/src/skcapstone/mcp_tools/notification_tools.py +92 -0
- package/src/skcapstone/mcp_tools/promoter_tools.py +101 -0
- package/src/skcapstone/mcp_tools/pubsub_tools.py +183 -0
- package/src/skcapstone/mcp_tools/security_tools.py +110 -0
- package/src/skcapstone/mcp_tools/skchat_tools.py +175 -0
- package/src/skcapstone/mcp_tools/skcomm_tools.py +122 -0
- package/src/skcapstone/mcp_tools/skills_tools.py +127 -0
- package/src/skcapstone/mcp_tools/skseed_tools.py +255 -0
- package/src/skcapstone/mcp_tools/skstacks_tools.py +288 -0
- package/src/skcapstone/mcp_tools/soul_tools.py +476 -0
- package/src/skcapstone/mcp_tools/sync_tools.py +92 -0
- package/src/skcapstone/mcp_tools/telegram_tools.py +477 -0
- package/src/skcapstone/mcp_tools/trust_tools.py +118 -0
- package/src/skcapstone/mcp_tools/trustee_tools.py +345 -0
- package/src/skcapstone/mdns_discovery.py +313 -0
- package/src/skcapstone/memory_adapter.py +333 -0
- package/src/skcapstone/memory_compressor.py +379 -0
- package/src/skcapstone/memory_curator.py +256 -0
- package/src/skcapstone/memory_engine.py +132 -13
- package/src/skcapstone/memory_fortress.py +529 -0
- package/src/skcapstone/memory_promoter.py +722 -0
- package/src/skcapstone/memory_verifier.py +260 -0
- package/src/skcapstone/message_crypto.py +215 -0
- package/src/skcapstone/metrics.py +832 -0
- package/src/skcapstone/migrate_memories.py +181 -0
- package/src/skcapstone/migrate_multi_agent.py +248 -0
- package/src/skcapstone/model_router.py +319 -0
- package/src/skcapstone/models.py +35 -4
- package/src/skcapstone/mood.py +344 -0
- package/src/skcapstone/notifications.py +380 -0
- package/src/skcapstone/onboard.py +901 -0
- package/src/skcapstone/peer_directory.py +324 -0
- package/src/skcapstone/peers.py +329 -0
- package/src/skcapstone/pillars/identity.py +84 -14
- package/src/skcapstone/pillars/memory.py +3 -1
- package/src/skcapstone/pillars/security.py +108 -15
- package/src/skcapstone/pillars/sync.py +78 -26
- package/src/skcapstone/pillars/trust.py +95 -33
- package/src/skcapstone/plugins.py +244 -0
- package/src/skcapstone/preflight.py +670 -0
- package/src/skcapstone/prompt_adapter.py +564 -0
- package/src/skcapstone/providers/__init__.py +13 -0
- package/src/skcapstone/providers/cloud.py +1061 -0
- package/src/skcapstone/providers/docker.py +759 -0
- package/src/skcapstone/providers/local.py +1193 -0
- package/src/skcapstone/providers/proxmox.py +447 -0
- package/src/skcapstone/pubsub.py +516 -0
- package/src/skcapstone/rate_limiter.py +119 -0
- package/src/skcapstone/register.py +241 -0
- package/src/skcapstone/registry_client.py +151 -0
- package/src/skcapstone/response_cache.py +194 -0
- package/src/skcapstone/response_scorer.py +225 -0
- package/src/skcapstone/runtime.py +89 -33
- package/src/skcapstone/scheduled_tasks.py +439 -0
- package/src/skcapstone/self_healing.py +341 -0
- package/src/skcapstone/service_health.py +228 -0
- package/src/skcapstone/session_capture.py +268 -0
- package/src/skcapstone/session_recorder.py +210 -0
- package/src/skcapstone/session_replayer.py +189 -0
- package/src/skcapstone/session_skills.py +263 -0
- package/src/skcapstone/shell.py +779 -0
- package/src/skcapstone/skills/__init__.py +1 -1
- package/src/skcapstone/skills/syncthing_setup.py +143 -41
- package/src/skcapstone/skjoule.py +861 -0
- package/src/skcapstone/snapshots.py +489 -0
- package/src/skcapstone/soul.py +1060 -0
- package/src/skcapstone/soul_switch.py +255 -0
- package/src/skcapstone/spawner.py +544 -0
- package/src/skcapstone/state_diff.py +401 -0
- package/src/skcapstone/summary.py +270 -0
- package/src/skcapstone/sync/backends.py +196 -2
- package/src/skcapstone/sync/engine.py +7 -5
- package/src/skcapstone/sync/models.py +4 -1
- package/src/skcapstone/sync/vault.py +356 -18
- package/src/skcapstone/sync_engine.py +363 -0
- package/src/skcapstone/sync_watcher.py +745 -0
- package/src/skcapstone/systemd.py +331 -0
- package/src/skcapstone/team_comms.py +476 -0
- package/src/skcapstone/team_engine.py +522 -0
- package/src/skcapstone/testrunner.py +300 -0
- package/src/skcapstone/tls.py +150 -0
- package/src/skcapstone/tokens.py +5 -5
- package/src/skcapstone/trust_calibration.py +202 -0
- package/src/skcapstone/trust_graph.py +449 -0
- package/src/skcapstone/trustee_monitor.py +385 -0
- package/src/skcapstone/trustee_ops.py +425 -0
- package/src/skcapstone/unified_search.py +421 -0
- package/src/skcapstone/uninstall_wizard.py +694 -0
- package/src/skcapstone/usage.py +331 -0
- package/src/skcapstone/version_check.py +148 -0
- package/src/skcapstone/warmth_anchor.py +333 -0
- package/src/skcapstone/whoami.py +294 -0
- package/systemd/skcapstone-api.socket +9 -0
- package/systemd/skcapstone-memory-compress.service +18 -0
- package/systemd/skcapstone-memory-compress.timer +11 -0
- package/systemd/skcapstone.service +36 -0
- package/systemd/skcapstone@.service +50 -0
- package/systemd/skcomm-heartbeat.service +18 -0
- package/systemd/skcomm-heartbeat.timer +12 -0
- package/systemd/skcomm-queue-drain.service +17 -0
- package/systemd/skcomm-queue-drain.timer +12 -0
- package/tests/conftest.py +13 -1
- package/tests/integration/__init__.py +1 -0
- package/tests/integration/test_consciousness_e2e.py +877 -0
- package/tests/integration/test_skills_registry.py +744 -0
- package/tests/test_agent_card.py +190 -0
- package/tests/test_agent_runtime.py +1283 -0
- package/tests/test_alerts_cmd.py +291 -0
- package/tests/test_archiver.py +498 -0
- package/tests/test_backup.py +254 -0
- package/tests/test_benchmark.py +366 -0
- package/tests/test_blueprints.py +457 -0
- package/tests/test_capabilities.py +257 -0
- package/tests/test_changelog.py +254 -0
- package/tests/test_chat.py +385 -0
- package/tests/test_claude_md.py +271 -0
- package/tests/test_cli_chat_llm.py +336 -0
- package/tests/test_cli_completions.py +390 -0
- package/tests/test_cli_init_reset.py +164 -0
- package/tests/test_cli_memory.py +208 -0
- package/tests/test_cli_profile.py +294 -0
- package/tests/test_cli_skills.py +223 -0
- package/tests/test_cli_status.py +395 -0
- package/tests/test_cli_test_cmd.py +206 -0
- package/tests/test_cli_test_connection.py +364 -0
- package/tests/test_cloud9_bridge.py +260 -0
- package/tests/test_cloud_provider.py +449 -0
- package/tests/test_cloud_providers.py +522 -0
- package/tests/test_completions.py +158 -0
- package/tests/test_component_manager.py +398 -0
- package/tests/test_config_reload.py +386 -0
- package/tests/test_config_validate.py +529 -0
- package/tests/test_consciousness_e2e.py +296 -0
- package/tests/test_consciousness_loop.py +1289 -0
- package/tests/test_context_loader.py +310 -0
- package/tests/test_conversation_api.py +306 -0
- package/tests/test_conversation_manager.py +381 -0
- package/tests/test_conversation_store.py +391 -0
- package/tests/test_conversation_summarizer.py +302 -0
- package/tests/test_cross_package.py +791 -0
- package/tests/test_crush_shim.py +519 -0
- package/tests/test_daemon.py +781 -0
- package/tests/test_daemon_shutdown.py +309 -0
- package/tests/test_dashboard.py +454 -0
- package/tests/test_discovery.py +200 -6
- package/tests/test_docker_provider.py +966 -0
- package/tests/test_doctor.py +257 -0
- package/tests/test_doctor_fix.py +351 -0
- package/tests/test_e2e_automated.py +292 -0
- package/tests/test_error_queue.py +404 -0
- package/tests/test_export.py +441 -0
- package/tests/test_fallback_tracker.py +219 -0
- package/tests/test_file_transfer.py +397 -0
- package/tests/test_fuse_mount.py +832 -0
- package/tests/test_health_loop.py +422 -0
- package/tests/test_heartbeat.py +354 -0
- package/tests/test_housekeeping.py +195 -0
- package/tests/test_identity_capauth.py +307 -0
- package/tests/test_identity_pillar.py +117 -0
- package/tests/test_install_wizard.py +68 -0
- package/tests/test_integration.py +325 -0
- package/tests/test_kms.py +495 -0
- package/tests/test_llm_providers.py +265 -0
- package/tests/test_local_provider.py +591 -0
- package/tests/test_log_config.py +199 -0
- package/tests/test_logs_cmd.py +287 -0
- package/tests/test_mcp_server.py +1909 -0
- package/tests/test_memory_adapter.py +339 -0
- package/tests/test_memory_curator.py +218 -0
- package/tests/test_memory_engine.py +6 -0
- package/tests/test_memory_fortress.py +571 -0
- package/tests/test_memory_pillar.py +119 -0
- package/tests/test_memory_promoter.py +445 -0
- package/tests/test_memory_verifier.py +420 -0
- package/tests/test_message_crypto.py +187 -0
- package/tests/test_metrics.py +632 -0
- package/tests/test_migrate_memories.py +464 -0
- package/tests/test_model_router.py +546 -0
- package/tests/test_mood.py +394 -0
- package/tests/test_multi_agent.py +269 -0
- package/tests/test_notifications.py +270 -0
- package/tests/test_onboard.py +500 -0
- package/tests/test_peer_directory.py +395 -0
- package/tests/test_peers.py +248 -0
- package/tests/test_pillars.py +87 -9
- package/tests/test_preflight.py +484 -0
- package/tests/test_prompt_adapter.py +331 -0
- package/tests/test_proxmox_provider.py +571 -0
- package/tests/test_pubsub.py +377 -0
- package/tests/test_rate_limiter.py +121 -0
- package/tests/test_registry_client.py +129 -0
- package/tests/test_response_cache.py +312 -0
- package/tests/test_response_scorer.py +294 -0
- package/tests/test_runtime.py +59 -0
- package/tests/test_scheduled_tasks.py +451 -0
- package/tests/test_security.py +250 -0
- package/tests/test_security_pillar.py +213 -0
- package/tests/test_self_healing.py +171 -0
- package/tests/test_session_capture.py +200 -0
- package/tests/test_session_recorder.py +360 -0
- package/tests/test_session_skills.py +235 -0
- package/tests/test_shell.py +210 -0
- package/tests/test_snapshots.py +549 -0
- package/tests/test_soul.py +984 -0
- package/tests/test_soul_swap.py +406 -0
- package/tests/test_spawner.py +211 -0
- package/tests/test_state_diff.py +173 -0
- package/tests/test_summary.py +135 -0
- package/tests/test_sync.py +315 -5
- package/tests/test_sync_backends.py +560 -0
- package/tests/test_sync_engine.py +482 -0
- package/tests/test_sync_pillar.py +344 -0
- package/tests/test_sync_pipeline.py +364 -0
- package/tests/test_sync_vault.py +581 -0
- package/tests/test_syncthing_setup.py +168 -22
- package/tests/test_systemd.py +323 -0
- package/tests/test_team_comms.py +408 -0
- package/tests/test_team_engine.py +397 -0
- package/tests/test_testrunner.py +238 -0
- package/tests/test_trust_calibration.py +204 -0
- package/tests/test_trust_graph.py +207 -0
- package/tests/test_trust_pillar.py +291 -0
- package/tests/test_trustee_cli.py +427 -0
- package/tests/test_trustee_cli_integration.py +325 -0
- package/tests/test_trustee_monitor.py +394 -0
- package/tests/test_trustee_ops.py +355 -0
- package/tests/test_unified_search.py +363 -0
- package/tests/test_uninstall_wizard.py +193 -0
- package/tests/test_usage.py +333 -0
- package/tests/test_version_cmd.py +355 -0
- package/tests/test_warmth_anchor.py +162 -0
- package/tests/test_whoami.py +245 -0
- package/tests/test_ws.py +311 -0
- package/.cursorrules +0 -33
- package/src/skcapstone/cli.py +0 -1441
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
"""Tests for consciousness config hot-reload.
|
|
2
|
+
|
|
3
|
+
Covers:
|
|
4
|
+
- _reload_config() updates ConsciousnessLoop._config from a changed YAML
|
|
5
|
+
- Changed fields are logged with old and new values
|
|
6
|
+
- Re-probe of backends is triggered on every successful reload
|
|
7
|
+
- Invalid YAML leaves config unchanged
|
|
8
|
+
- A no-op reload (no changes) skips logging and backend re-probe
|
|
9
|
+
- _run_config_watcher() starts a daemon thread that calls _reload_config
|
|
10
|
+
on watchdog events
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
import threading
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from unittest.mock import MagicMock, call, patch
|
|
19
|
+
|
|
20
|
+
import pytest
|
|
21
|
+
import yaml
|
|
22
|
+
|
|
23
|
+
from skcapstone.consciousness_loop import ConsciousnessConfig, ConsciousnessLoop
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Helpers
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
_DEFAULT_CONFIG = ConsciousnessConfig()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _make_loop(tmp_path: Path) -> ConsciousnessLoop:
|
|
34
|
+
"""Construct a minimal ConsciousnessLoop for testing."""
|
|
35
|
+
config = ConsciousnessConfig(fallback_chain=["passthrough"])
|
|
36
|
+
return ConsciousnessLoop(config, home=tmp_path / ".skcapstone")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _write_config(home: Path, data: dict) -> Path:
|
|
40
|
+
"""Write a consciousness.yaml config file under {home}/config/."""
|
|
41
|
+
config_dir = home / "config"
|
|
42
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
config_path = config_dir / "consciousness.yaml"
|
|
44
|
+
config_path.write_text(yaml.dump(data, default_flow_style=False), encoding="utf-8")
|
|
45
|
+
return config_path
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# Test: _reload_config() updates fields
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class TestReloadConfigUpdatesFields:
|
|
54
|
+
"""_reload_config() must update self._config from the YAML file."""
|
|
55
|
+
|
|
56
|
+
def test_reload_updates_single_field(self, tmp_path):
|
|
57
|
+
"""A changed field is reflected in _config after reload."""
|
|
58
|
+
loop = _make_loop(tmp_path)
|
|
59
|
+
home = loop._home
|
|
60
|
+
|
|
61
|
+
# Write YAML that changes response_timeout
|
|
62
|
+
_write_config(
|
|
63
|
+
home,
|
|
64
|
+
{**_DEFAULT_CONFIG.model_dump(), "response_timeout": 999},
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
loop._reload_config()
|
|
68
|
+
|
|
69
|
+
assert loop._config.response_timeout == 999
|
|
70
|
+
|
|
71
|
+
def test_reload_updates_fallback_chain(self, tmp_path):
|
|
72
|
+
"""fallback_chain is updated from YAML."""
|
|
73
|
+
loop = _make_loop(tmp_path)
|
|
74
|
+
home = loop._home
|
|
75
|
+
|
|
76
|
+
_write_config(
|
|
77
|
+
home,
|
|
78
|
+
{**_DEFAULT_CONFIG.model_dump(), "fallback_chain": ["anthropic", "passthrough"]},
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
loop._reload_config()
|
|
82
|
+
|
|
83
|
+
assert loop._config.fallback_chain == ["anthropic", "passthrough"]
|
|
84
|
+
|
|
85
|
+
def test_reload_updates_multiple_fields(self, tmp_path):
|
|
86
|
+
"""Multiple changed fields are all updated."""
|
|
87
|
+
loop = _make_loop(tmp_path)
|
|
88
|
+
home = loop._home
|
|
89
|
+
|
|
90
|
+
_write_config(
|
|
91
|
+
home,
|
|
92
|
+
{
|
|
93
|
+
**_DEFAULT_CONFIG.model_dump(),
|
|
94
|
+
"response_timeout": 60,
|
|
95
|
+
"max_context_tokens": 4000,
|
|
96
|
+
"auto_ack": False,
|
|
97
|
+
},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
loop._reload_config()
|
|
101
|
+
|
|
102
|
+
assert loop._config.response_timeout == 60
|
|
103
|
+
assert loop._config.max_context_tokens == 4000
|
|
104
|
+
assert loop._config.auto_ack is False
|
|
105
|
+
|
|
106
|
+
def test_reload_syncs_bridge_fallback_chain(self, tmp_path):
|
|
107
|
+
"""_bridge._fallback_chain is updated to match the reloaded config."""
|
|
108
|
+
loop = _make_loop(tmp_path)
|
|
109
|
+
home = loop._home
|
|
110
|
+
|
|
111
|
+
new_chain = ["nvidia", "passthrough"]
|
|
112
|
+
_write_config(
|
|
113
|
+
home,
|
|
114
|
+
{**_DEFAULT_CONFIG.model_dump(), "fallback_chain": new_chain},
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
loop._reload_config()
|
|
118
|
+
|
|
119
|
+
assert loop._bridge._fallback_chain == new_chain
|
|
120
|
+
|
|
121
|
+
def test_reload_syncs_bridge_timeout(self, tmp_path):
|
|
122
|
+
"""_bridge._timeout is updated to match the reloaded config."""
|
|
123
|
+
loop = _make_loop(tmp_path)
|
|
124
|
+
home = loop._home
|
|
125
|
+
|
|
126
|
+
_write_config(
|
|
127
|
+
home,
|
|
128
|
+
{**_DEFAULT_CONFIG.model_dump(), "response_timeout": 42},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
loop._reload_config()
|
|
132
|
+
|
|
133
|
+
assert loop._bridge._timeout == 42
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
137
|
+
# Test: _reload_config() logs changes
|
|
138
|
+
# ---------------------------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class TestReloadConfigLogsChanges:
|
|
142
|
+
"""Changed fields must be logged at INFO level with old and new values."""
|
|
143
|
+
|
|
144
|
+
def test_changed_field_is_logged(self, tmp_path, caplog):
|
|
145
|
+
"""Each changed field appears in the log output."""
|
|
146
|
+
loop = _make_loop(tmp_path)
|
|
147
|
+
home = loop._home
|
|
148
|
+
|
|
149
|
+
_write_config(
|
|
150
|
+
home,
|
|
151
|
+
{**_DEFAULT_CONFIG.model_dump(), "response_timeout": 77},
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
with caplog.at_level(logging.INFO, logger="skcapstone.consciousness"):
|
|
155
|
+
loop._reload_config()
|
|
156
|
+
|
|
157
|
+
change_logs = [
|
|
158
|
+
r.message for r in caplog.records if "response_timeout" in r.message
|
|
159
|
+
]
|
|
160
|
+
assert change_logs, "Expected a log entry mentioning 'response_timeout'"
|
|
161
|
+
# Must mention both old and new values
|
|
162
|
+
msg = change_logs[0]
|
|
163
|
+
assert "77" in msg, "New value 77 should appear in log"
|
|
164
|
+
|
|
165
|
+
def test_no_log_when_nothing_changed(self, tmp_path, caplog):
|
|
166
|
+
"""If the YAML matches the current config, no change-log entries appear."""
|
|
167
|
+
loop = _make_loop(tmp_path)
|
|
168
|
+
home = loop._home
|
|
169
|
+
|
|
170
|
+
# Write exact current config — nothing changes
|
|
171
|
+
_write_config(home, loop._config.model_dump())
|
|
172
|
+
|
|
173
|
+
with caplog.at_level(logging.INFO, logger="skcapstone.consciousness"):
|
|
174
|
+
loop._reload_config()
|
|
175
|
+
|
|
176
|
+
change_logs = [
|
|
177
|
+
r.message for r in caplog.records if "changed:" in r.message
|
|
178
|
+
]
|
|
179
|
+
assert not change_logs, (
|
|
180
|
+
"No 'changed:' log entries expected when config is unchanged"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
def test_completion_log_emitted(self, tmp_path, caplog):
|
|
184
|
+
"""A 'Config hot-reload complete' log entry is emitted after a successful reload."""
|
|
185
|
+
loop = _make_loop(tmp_path)
|
|
186
|
+
home = loop._home
|
|
187
|
+
|
|
188
|
+
_write_config(
|
|
189
|
+
home,
|
|
190
|
+
{**_DEFAULT_CONFIG.model_dump(), "max_history_messages": 5},
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
with caplog.at_level(logging.INFO, logger="skcapstone.consciousness"):
|
|
194
|
+
loop._reload_config()
|
|
195
|
+
|
|
196
|
+
complete_logs = [
|
|
197
|
+
r.message for r in caplog.records if "hot-reload complete" in r.message
|
|
198
|
+
]
|
|
199
|
+
assert complete_logs, "Expected 'Config hot-reload complete' log entry"
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# ---------------------------------------------------------------------------
|
|
203
|
+
# Test: _reload_config() re-probes backends
|
|
204
|
+
# ---------------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class TestReloadConfigReprobesBackends:
|
|
208
|
+
"""_reload_config() must call _probe_available_backends() after a change."""
|
|
209
|
+
|
|
210
|
+
def test_reprobes_when_config_changes(self, tmp_path):
|
|
211
|
+
"""_probe_available_backends is called exactly once per successful reload."""
|
|
212
|
+
loop = _make_loop(tmp_path)
|
|
213
|
+
home = loop._home
|
|
214
|
+
|
|
215
|
+
_write_config(
|
|
216
|
+
home,
|
|
217
|
+
{**_DEFAULT_CONFIG.model_dump(), "response_timeout": 30},
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
with patch.object(
|
|
221
|
+
loop._bridge, "_probe_available_backends", wraps=loop._bridge._probe_available_backends
|
|
222
|
+
) as mock_probe:
|
|
223
|
+
loop._reload_config()
|
|
224
|
+
|
|
225
|
+
mock_probe.assert_called_once()
|
|
226
|
+
|
|
227
|
+
def test_no_reprobe_when_nothing_changed(self, tmp_path):
|
|
228
|
+
"""_probe_available_backends is NOT called when config is unchanged."""
|
|
229
|
+
loop = _make_loop(tmp_path)
|
|
230
|
+
home = loop._home
|
|
231
|
+
|
|
232
|
+
_write_config(home, loop._config.model_dump())
|
|
233
|
+
|
|
234
|
+
with patch.object(
|
|
235
|
+
loop._bridge, "_probe_available_backends"
|
|
236
|
+
) as mock_probe:
|
|
237
|
+
loop._reload_config()
|
|
238
|
+
|
|
239
|
+
mock_probe.assert_not_called()
|
|
240
|
+
|
|
241
|
+
def test_no_reprobe_on_invalid_yaml(self, tmp_path):
|
|
242
|
+
"""_probe_available_backends is NOT called when YAML is unparseable."""
|
|
243
|
+
loop = _make_loop(tmp_path)
|
|
244
|
+
home = loop._home
|
|
245
|
+
|
|
246
|
+
config_dir = home / "config"
|
|
247
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
248
|
+
(config_dir / "consciousness.yaml").write_text(
|
|
249
|
+
": invalid: yaml: {{{ broken", encoding="utf-8"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
with patch.object(loop._bridge, "_probe_available_backends") as mock_probe:
|
|
253
|
+
loop._reload_config()
|
|
254
|
+
|
|
255
|
+
mock_probe.assert_not_called()
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# ---------------------------------------------------------------------------
|
|
259
|
+
# Test: invalid / missing config
|
|
260
|
+
# ---------------------------------------------------------------------------
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class TestReloadConfigErrorHandling:
|
|
264
|
+
"""_reload_config() must fail gracefully without corrupting state."""
|
|
265
|
+
|
|
266
|
+
def test_invalid_yaml_keeps_current_config(self, tmp_path):
|
|
267
|
+
"""Unparseable YAML leaves self._config unchanged."""
|
|
268
|
+
loop = _make_loop(tmp_path)
|
|
269
|
+
original_config = loop._config.model_copy()
|
|
270
|
+
home = loop._home
|
|
271
|
+
|
|
272
|
+
config_dir = home / "config"
|
|
273
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
274
|
+
(config_dir / "consciousness.yaml").write_text(
|
|
275
|
+
": invalid: yaml: {{{ broken", encoding="utf-8"
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
loop._reload_config()
|
|
279
|
+
|
|
280
|
+
assert loop._config.model_dump() == original_config.model_dump(), (
|
|
281
|
+
"Config must not change after a failed reload"
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def test_missing_file_keeps_current_config(self, tmp_path):
|
|
285
|
+
"""Missing YAML file leaves self._config unchanged."""
|
|
286
|
+
loop = _make_loop(tmp_path)
|
|
287
|
+
original_config = loop._config.model_copy()
|
|
288
|
+
# Do NOT create any config file
|
|
289
|
+
|
|
290
|
+
loop._reload_config()
|
|
291
|
+
|
|
292
|
+
assert loop._config.model_dump() == original_config.model_dump()
|
|
293
|
+
|
|
294
|
+
def test_missing_file_logs_warning(self, tmp_path, caplog):
|
|
295
|
+
"""A warning is logged when the config file is absent."""
|
|
296
|
+
loop = _make_loop(tmp_path)
|
|
297
|
+
|
|
298
|
+
with caplog.at_level(logging.WARNING, logger="skcapstone.consciousness"):
|
|
299
|
+
loop._reload_config()
|
|
300
|
+
|
|
301
|
+
warn_logs = [
|
|
302
|
+
r.message for r in caplog.records
|
|
303
|
+
if "not found" in r.message or "hot-reload" in r.message
|
|
304
|
+
]
|
|
305
|
+
assert warn_logs, "Expected a warning log when config file is missing"
|
|
306
|
+
|
|
307
|
+
def test_invalid_yaml_logs_error(self, tmp_path, caplog):
|
|
308
|
+
"""An error is logged when YAML cannot be parsed."""
|
|
309
|
+
loop = _make_loop(tmp_path)
|
|
310
|
+
home = loop._home
|
|
311
|
+
|
|
312
|
+
config_dir = home / "config"
|
|
313
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
314
|
+
(config_dir / "consciousness.yaml").write_text(
|
|
315
|
+
": invalid: yaml: {{{ broken", encoding="utf-8"
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
with caplog.at_level(logging.ERROR, logger="skcapstone.consciousness"):
|
|
319
|
+
loop._reload_config()
|
|
320
|
+
|
|
321
|
+
error_logs = [
|
|
322
|
+
r.message for r in caplog.records if "hot-reload" in r.message
|
|
323
|
+
]
|
|
324
|
+
assert error_logs, "Expected an error log for invalid YAML"
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# ---------------------------------------------------------------------------
|
|
328
|
+
# Test: _run_config_watcher thread
|
|
329
|
+
# ---------------------------------------------------------------------------
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class TestRunConfigWatcher:
|
|
333
|
+
"""_run_config_watcher() starts a thread and calls _reload_config on events."""
|
|
334
|
+
|
|
335
|
+
def test_config_watcher_thread_is_started(self, tmp_path):
|
|
336
|
+
"""start() spawns a 'consciousness-config-watcher' daemon thread."""
|
|
337
|
+
loop = _make_loop(tmp_path)
|
|
338
|
+
threads = loop.start()
|
|
339
|
+
loop.stop()
|
|
340
|
+
|
|
341
|
+
names = {t.name for t in threads}
|
|
342
|
+
assert "consciousness-config-watcher" in names
|
|
343
|
+
|
|
344
|
+
def test_config_watcher_calls_reload_on_modified_event(self, tmp_path):
|
|
345
|
+
"""The watchdog handler calls _reload_config() on a 'modified' event."""
|
|
346
|
+
loop = _make_loop(tmp_path)
|
|
347
|
+
home = loop._home
|
|
348
|
+
|
|
349
|
+
# Write an initial config so the file exists
|
|
350
|
+
_write_config(home, _DEFAULT_CONFIG.model_dump())
|
|
351
|
+
|
|
352
|
+
stop_event = threading.Event()
|
|
353
|
+
loop._stop_event = stop_event
|
|
354
|
+
|
|
355
|
+
reload_calls: list[None] = []
|
|
356
|
+
|
|
357
|
+
def fake_reload():
|
|
358
|
+
reload_calls.append(None)
|
|
359
|
+
stop_event.set() # terminate the watcher after first reload
|
|
360
|
+
|
|
361
|
+
loop._reload_config = fake_reload # type: ignore[method-assign]
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
from watchdog.observers import Observer # noqa: F401 — skip if not installed
|
|
365
|
+
except ImportError:
|
|
366
|
+
pytest.skip("watchdog not installed")
|
|
367
|
+
|
|
368
|
+
watcher_thread = threading.Thread(
|
|
369
|
+
target=loop._run_config_watcher, daemon=True
|
|
370
|
+
)
|
|
371
|
+
watcher_thread.start()
|
|
372
|
+
|
|
373
|
+
# Give the observer a moment to start, then write a changed config
|
|
374
|
+
import time
|
|
375
|
+
time.sleep(0.3)
|
|
376
|
+
|
|
377
|
+
_write_config(
|
|
378
|
+
home,
|
|
379
|
+
{**_DEFAULT_CONFIG.model_dump(), "response_timeout": 55},
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
# Wait up to 5 s for the handler to fire
|
|
383
|
+
stop_event.wait(timeout=5)
|
|
384
|
+
watcher_thread.join(timeout=2)
|
|
385
|
+
|
|
386
|
+
assert reload_calls, "Expected _reload_config to be called by the watcher"
|