@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,309 @@
|
|
|
1
|
+
"""Tests for graceful shutdown with state persistence in DaemonService.
|
|
2
|
+
|
|
3
|
+
Covers:
|
|
4
|
+
- _save_shutdown_state writes correct JSON with inflight + metrics + timestamp
|
|
5
|
+
- _load_startup_state restores metrics and removes the state file
|
|
6
|
+
- _load_startup_state is a no-op when no state file exists
|
|
7
|
+
- _resume_inflight_messages replays messages via consciousness loop
|
|
8
|
+
- _resume_inflight_messages drops messages gracefully when consciousness unavailable
|
|
9
|
+
- DaemonState inflight tracking (add / remove / get)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import uuid
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from types import SimpleNamespace
|
|
18
|
+
from unittest.mock import MagicMock, patch
|
|
19
|
+
|
|
20
|
+
import pytest
|
|
21
|
+
|
|
22
|
+
from skcapstone.daemon import DaemonConfig, DaemonService, DaemonState, SHUTDOWN_STATE_FILE
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# Helpers
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
def _make_service(tmp_path: Path) -> DaemonService:
|
|
30
|
+
"""Create a DaemonService backed by a temp directory (no real threads)."""
|
|
31
|
+
config = DaemonConfig(
|
|
32
|
+
home=tmp_path,
|
|
33
|
+
shared_root=tmp_path / "shared",
|
|
34
|
+
poll_interval=10,
|
|
35
|
+
sync_interval=300,
|
|
36
|
+
consciousness_enabled=False,
|
|
37
|
+
)
|
|
38
|
+
return DaemonService(config)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _make_fake_envelope(sender: str = "peer-a", content: str = "hello") -> SimpleNamespace:
|
|
42
|
+
"""Build a minimal fake SKComm envelope."""
|
|
43
|
+
return SimpleNamespace(
|
|
44
|
+
message_id=str(uuid.uuid4()),
|
|
45
|
+
sender=sender,
|
|
46
|
+
payload=SimpleNamespace(
|
|
47
|
+
content=content,
|
|
48
|
+
content_type=SimpleNamespace(value="text"),
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
# DaemonState — inflight tracking
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
class TestDaemonStateInflight:
|
|
58
|
+
"""Unit tests for add/remove/get inflight on DaemonState."""
|
|
59
|
+
|
|
60
|
+
def test_add_inflight_stores_data(self) -> None:
|
|
61
|
+
"""add_inflight stores the message data under its ID."""
|
|
62
|
+
state = DaemonState()
|
|
63
|
+
state.add_inflight("msg-1", {"sender": "alice", "content": "hi"})
|
|
64
|
+
assert len(state.get_inflight()) == 1
|
|
65
|
+
assert state.get_inflight()[0]["sender"] == "alice"
|
|
66
|
+
|
|
67
|
+
def test_remove_inflight_clears_entry(self) -> None:
|
|
68
|
+
"""remove_inflight removes the entry; subsequent get returns empty list."""
|
|
69
|
+
state = DaemonState()
|
|
70
|
+
state.add_inflight("msg-1", {"sender": "alice"})
|
|
71
|
+
state.remove_inflight("msg-1")
|
|
72
|
+
assert state.get_inflight() == []
|
|
73
|
+
|
|
74
|
+
def test_remove_inflight_unknown_id_is_noop(self) -> None:
|
|
75
|
+
"""remove_inflight with an unknown ID does not raise."""
|
|
76
|
+
state = DaemonState()
|
|
77
|
+
state.remove_inflight("nonexistent") # should not raise
|
|
78
|
+
|
|
79
|
+
def test_get_inflight_returns_snapshot(self) -> None:
|
|
80
|
+
"""get_inflight returns a list copy — mutations don't affect stored state."""
|
|
81
|
+
state = DaemonState()
|
|
82
|
+
state.add_inflight("a", {"x": 1})
|
|
83
|
+
state.add_inflight("b", {"x": 2})
|
|
84
|
+
result = state.get_inflight()
|
|
85
|
+
assert len(result) == 2
|
|
86
|
+
result.clear() # mutate the returned list
|
|
87
|
+
assert len(state.get_inflight()) == 2 # stored state unchanged
|
|
88
|
+
|
|
89
|
+
def test_snapshot_includes_inflight_count(self) -> None:
|
|
90
|
+
"""DaemonState.snapshot() includes inflight_count."""
|
|
91
|
+
state = DaemonState()
|
|
92
|
+
state.add_inflight("m1", {"content": "test"})
|
|
93
|
+
snap = state.snapshot()
|
|
94
|
+
assert snap["inflight_count"] == 1
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# ---------------------------------------------------------------------------
|
|
98
|
+
# _save_shutdown_state
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
|
|
101
|
+
class TestSaveShutdownState:
|
|
102
|
+
"""Tests for _save_shutdown_state."""
|
|
103
|
+
|
|
104
|
+
def test_writes_json_file(self, tmp_path: Path) -> None:
|
|
105
|
+
"""Shutdown state file is created with correct structure."""
|
|
106
|
+
svc = _make_service(tmp_path)
|
|
107
|
+
svc.state.messages_received = 7
|
|
108
|
+
svc.state.syncs_completed = 2
|
|
109
|
+
svc.state.add_inflight("m1", {"message_id": "m1", "sender": "bob", "content": "hey"})
|
|
110
|
+
|
|
111
|
+
svc._save_shutdown_state()
|
|
112
|
+
|
|
113
|
+
state_file = tmp_path / SHUTDOWN_STATE_FILE
|
|
114
|
+
assert state_file.exists()
|
|
115
|
+
data = json.loads(state_file.read_text())
|
|
116
|
+
assert data["metrics"]["messages_received"] == 7
|
|
117
|
+
assert data["metrics"]["syncs_completed"] == 2
|
|
118
|
+
assert len(data["inflight_messages"]) == 1
|
|
119
|
+
assert data["inflight_messages"][0]["sender"] == "bob"
|
|
120
|
+
assert "shutdown_at" in data
|
|
121
|
+
|
|
122
|
+
def test_writes_empty_inflight_when_no_messages_pending(self, tmp_path: Path) -> None:
|
|
123
|
+
"""Shutdown state is still written when no messages are in flight."""
|
|
124
|
+
svc = _make_service(tmp_path)
|
|
125
|
+
svc._save_shutdown_state()
|
|
126
|
+
|
|
127
|
+
data = json.loads((tmp_path / SHUTDOWN_STATE_FILE).read_text())
|
|
128
|
+
assert data["inflight_messages"] == []
|
|
129
|
+
|
|
130
|
+
def test_handles_write_error_gracefully(self, tmp_path: Path) -> None:
|
|
131
|
+
"""_save_shutdown_state logs an error and does not raise on write failure."""
|
|
132
|
+
svc = _make_service(tmp_path)
|
|
133
|
+
# Point home at a path whose parent doesn't exist so write fails
|
|
134
|
+
svc.config.home = tmp_path / "no_such_dir" / "nope" # type: ignore[assignment]
|
|
135
|
+
svc._save_shutdown_state() # should log error, not raise
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# ---------------------------------------------------------------------------
|
|
139
|
+
# _load_startup_state
|
|
140
|
+
# ---------------------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
class TestLoadStartupState:
|
|
143
|
+
"""Tests for _load_startup_state."""
|
|
144
|
+
|
|
145
|
+
def test_no_op_when_file_missing(self, tmp_path: Path) -> None:
|
|
146
|
+
"""_load_startup_state does nothing when no shutdown state file exists."""
|
|
147
|
+
svc = _make_service(tmp_path)
|
|
148
|
+
svc._load_startup_state() # should not raise
|
|
149
|
+
assert svc.state.messages_received == 0
|
|
150
|
+
|
|
151
|
+
def test_restores_metrics_from_file(self, tmp_path: Path) -> None:
|
|
152
|
+
"""metrics are accumulated from the state file into current state."""
|
|
153
|
+
state_file = tmp_path / SHUTDOWN_STATE_FILE
|
|
154
|
+
state_file.write_text(json.dumps({
|
|
155
|
+
"shutdown_at": "2026-03-01T00:00:00+00:00",
|
|
156
|
+
"inflight_messages": [],
|
|
157
|
+
"metrics": {"messages_received": 42, "syncs_completed": 5},
|
|
158
|
+
}), encoding="utf-8")
|
|
159
|
+
|
|
160
|
+
svc = _make_service(tmp_path)
|
|
161
|
+
svc._load_startup_state()
|
|
162
|
+
|
|
163
|
+
assert svc.state.messages_received == 42
|
|
164
|
+
assert svc.state.syncs_completed == 5
|
|
165
|
+
|
|
166
|
+
def test_removes_state_file_after_load(self, tmp_path: Path) -> None:
|
|
167
|
+
"""The shutdown_state.json is deleted after successful load."""
|
|
168
|
+
state_file = tmp_path / SHUTDOWN_STATE_FILE
|
|
169
|
+
state_file.write_text(json.dumps({
|
|
170
|
+
"shutdown_at": "2026-03-01T00:00:00+00:00",
|
|
171
|
+
"inflight_messages": [],
|
|
172
|
+
"metrics": {},
|
|
173
|
+
}), encoding="utf-8")
|
|
174
|
+
|
|
175
|
+
svc = _make_service(tmp_path)
|
|
176
|
+
svc._load_startup_state()
|
|
177
|
+
|
|
178
|
+
assert not state_file.exists()
|
|
179
|
+
|
|
180
|
+
def test_corrupted_file_does_not_raise(self, tmp_path: Path) -> None:
|
|
181
|
+
"""Corrupt JSON in shutdown_state.json is handled gracefully."""
|
|
182
|
+
(tmp_path / SHUTDOWN_STATE_FILE).write_text("not json{{{", encoding="utf-8")
|
|
183
|
+
svc = _make_service(tmp_path)
|
|
184
|
+
svc._load_startup_state() # should log warning and return
|
|
185
|
+
assert svc.state.messages_received == 0
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# ---------------------------------------------------------------------------
|
|
189
|
+
# _resume_inflight_messages
|
|
190
|
+
# ---------------------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
class TestResumeInflightMessages:
|
|
193
|
+
"""Tests for _resume_inflight_messages."""
|
|
194
|
+
|
|
195
|
+
def test_drops_messages_when_consciousness_unavailable(
|
|
196
|
+
self, tmp_path: Path, caplog: pytest.LogCaptureFixture
|
|
197
|
+
) -> None:
|
|
198
|
+
"""Messages are logged as dropped when consciousness is not loaded."""
|
|
199
|
+
svc = _make_service(tmp_path)
|
|
200
|
+
svc._consciousness = None
|
|
201
|
+
|
|
202
|
+
inflight = [
|
|
203
|
+
{"message_id": "x1", "sender": "alice", "content": "hi", "content_type": "text"},
|
|
204
|
+
]
|
|
205
|
+
svc._resume_inflight_messages(inflight) # should not raise
|
|
206
|
+
|
|
207
|
+
def test_replays_messages_through_consciousness(self, tmp_path: Path) -> None:
|
|
208
|
+
"""In-flight messages are replayed via consciousness.process_envelope."""
|
|
209
|
+
svc = _make_service(tmp_path)
|
|
210
|
+
|
|
211
|
+
mock_consciousness = MagicMock()
|
|
212
|
+
mock_consciousness._config.enabled = True
|
|
213
|
+
svc._consciousness = mock_consciousness
|
|
214
|
+
|
|
215
|
+
inflight = [
|
|
216
|
+
{"message_id": "m1", "sender": "bob", "content": "test msg", "content_type": "text"},
|
|
217
|
+
{"message_id": "m2", "sender": "carol", "content": "another", "content_type": "text"},
|
|
218
|
+
]
|
|
219
|
+
svc._resume_inflight_messages(inflight)
|
|
220
|
+
|
|
221
|
+
assert mock_consciousness.process_envelope.call_count == 2
|
|
222
|
+
calls = mock_consciousness.process_envelope.call_args_list
|
|
223
|
+
senders = {c.args[0].sender for c in calls}
|
|
224
|
+
assert senders == {"bob", "carol"}
|
|
225
|
+
|
|
226
|
+
def test_replayed_envelope_has_correct_content(self, tmp_path: Path) -> None:
|
|
227
|
+
"""The reconstructed envelope carries the original content and sender."""
|
|
228
|
+
svc = _make_service(tmp_path)
|
|
229
|
+
captured: list = []
|
|
230
|
+
|
|
231
|
+
mock_consciousness = MagicMock()
|
|
232
|
+
mock_consciousness._config.enabled = True
|
|
233
|
+
mock_consciousness.process_envelope.side_effect = lambda env: captured.append(env)
|
|
234
|
+
svc._consciousness = mock_consciousness
|
|
235
|
+
|
|
236
|
+
inflight = [
|
|
237
|
+
{"message_id": "q1", "sender": "dave", "content": "resume me", "content_type": "text"},
|
|
238
|
+
]
|
|
239
|
+
svc._resume_inflight_messages(inflight)
|
|
240
|
+
|
|
241
|
+
assert len(captured) == 1
|
|
242
|
+
env = captured[0]
|
|
243
|
+
assert env.sender == "dave"
|
|
244
|
+
assert env.payload.content == "resume me"
|
|
245
|
+
assert env.payload.content_type.value == "text"
|
|
246
|
+
|
|
247
|
+
def test_resume_error_on_one_message_continues_others(self, tmp_path: Path) -> None:
|
|
248
|
+
"""A failure on one message does not prevent the rest from being resumed."""
|
|
249
|
+
svc = _make_service(tmp_path)
|
|
250
|
+
processed: list = []
|
|
251
|
+
|
|
252
|
+
def side_effect(env):
|
|
253
|
+
if env.sender == "bad":
|
|
254
|
+
raise RuntimeError("boom")
|
|
255
|
+
processed.append(env.sender)
|
|
256
|
+
|
|
257
|
+
mock_consciousness = MagicMock()
|
|
258
|
+
mock_consciousness._config.enabled = True
|
|
259
|
+
mock_consciousness.process_envelope.side_effect = side_effect
|
|
260
|
+
svc._consciousness = mock_consciousness
|
|
261
|
+
|
|
262
|
+
inflight = [
|
|
263
|
+
{"message_id": "a", "sender": "bad", "content": "x", "content_type": "text"},
|
|
264
|
+
{"message_id": "b", "sender": "good", "content": "y", "content_type": "text"},
|
|
265
|
+
]
|
|
266
|
+
svc._resume_inflight_messages(inflight)
|
|
267
|
+
|
|
268
|
+
assert "good" in processed
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
# ---------------------------------------------------------------------------
|
|
272
|
+
# Integration: save → load round-trip
|
|
273
|
+
# ---------------------------------------------------------------------------
|
|
274
|
+
|
|
275
|
+
class TestShutdownStartupRoundTrip:
|
|
276
|
+
"""End-to-end: save state then load it back."""
|
|
277
|
+
|
|
278
|
+
def test_round_trip_preserves_inflight_content(self, tmp_path: Path) -> None:
|
|
279
|
+
"""State saved on shutdown is accurately restored on the next start."""
|
|
280
|
+
svc = _make_service(tmp_path)
|
|
281
|
+
svc.state.messages_received = 10
|
|
282
|
+
svc.state.syncs_completed = 3
|
|
283
|
+
svc.state.add_inflight("rt1", {
|
|
284
|
+
"message_id": "rt1",
|
|
285
|
+
"sender": "peer-x",
|
|
286
|
+
"content": "round trip payload",
|
|
287
|
+
"content_type": "text",
|
|
288
|
+
"received_at": "2026-03-02T00:00:00+00:00",
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
svc._save_shutdown_state()
|
|
292
|
+
|
|
293
|
+
# Simulate a fresh service startup
|
|
294
|
+
svc2 = _make_service(tmp_path)
|
|
295
|
+
resumed: list = []
|
|
296
|
+
|
|
297
|
+
mock_consciousness = MagicMock()
|
|
298
|
+
mock_consciousness._config.enabled = True
|
|
299
|
+
mock_consciousness.process_envelope.side_effect = lambda env: resumed.append(env)
|
|
300
|
+
svc2._consciousness = mock_consciousness
|
|
301
|
+
|
|
302
|
+
svc2._load_startup_state()
|
|
303
|
+
|
|
304
|
+
assert svc2.state.messages_received == 10
|
|
305
|
+
assert svc2.state.syncs_completed == 3
|
|
306
|
+
assert len(resumed) == 1
|
|
307
|
+
assert resumed[0].payload.content == "round trip payload"
|
|
308
|
+
assert resumed[0].sender == "peer-x"
|
|
309
|
+
assert not (tmp_path / SHUTDOWN_STATE_FILE).exists()
|