@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,363 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sync pipeline engine — comms path alignment for Syncthing ↔ consciousness loop.
|
|
3
|
+
|
|
4
|
+
Verifies that the inbox/outbox directories used by the consciousness loop
|
|
5
|
+
inotify watcher and the SKComm Syncthing transport are aligned under the
|
|
6
|
+
Syncthing-synced comms root, and reports pipeline health.
|
|
7
|
+
|
|
8
|
+
Pipeline:
|
|
9
|
+
Syncthing → {shared_root}/sync/comms/inbox/{peer}/*.skc.json
|
|
10
|
+
↓ inotify (ConsciousnessLoop._INBOX_DIR = "sync/comms/inbox")
|
|
11
|
+
ConsciousnessLoop.process_envelope()
|
|
12
|
+
↓ skcomm.send() — must route to SyncthingTransport with
|
|
13
|
+
comms_root = {shared_root}/sync/comms
|
|
14
|
+
SyncthingTransport → {shared_root}/sync/comms/outbox/{peer}/*.skc.json
|
|
15
|
+
↓ Syncthing propagates to peer
|
|
16
|
+
Peer inbox
|
|
17
|
+
|
|
18
|
+
Path alignment requirement
|
|
19
|
+
--------------------------
|
|
20
|
+
The SKComm Syncthing transport must be configured with::
|
|
21
|
+
|
|
22
|
+
comms_root: ~/.skcapstone/sync/comms
|
|
23
|
+
|
|
24
|
+
in ~/.skcomm/config.yml so its outbox and inbox paths match the paths the
|
|
25
|
+
consciousness loop watches via inotify. This module provides
|
|
26
|
+
:func:`verify_pipeline_paths` to detect mismatches and
|
|
27
|
+
:func:`get_sync_pipeline_status` for the daemon health loop.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import json
|
|
33
|
+
import logging
|
|
34
|
+
import re
|
|
35
|
+
import time
|
|
36
|
+
from datetime import datetime, timezone
|
|
37
|
+
from pathlib import Path
|
|
38
|
+
from typing import Optional
|
|
39
|
+
|
|
40
|
+
logger = logging.getLogger("skcapstone.sync_engine")
|
|
41
|
+
|
|
42
|
+
# Relative paths under SHARED_ROOT — must stay in sync with
|
|
43
|
+
# _INBOX_DIR in consciousness_loop.py ("sync/comms/inbox")
|
|
44
|
+
COMMS_SUBPATH = "sync/comms"
|
|
45
|
+
INBOX_SUBPATH = "sync/comms/inbox"
|
|
46
|
+
OUTBOX_SUBPATH = "sync/comms/outbox"
|
|
47
|
+
ENVELOPE_SUFFIX = ".skc.json"
|
|
48
|
+
|
|
49
|
+
# Character allowlist for peer/recipient names (mirrors _sanitize_peer_name)
|
|
50
|
+
_PEER_SAFE_RE = re.compile(r"[^a-zA-Z0-9_\-@\.]")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _sanitize_peer(name: str) -> str:
|
|
54
|
+
"""Sanitize a peer name for use as a filesystem subdirectory.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
name: Raw peer / recipient string.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Filesystem-safe name, max 64 chars, defaults to "unknown".
|
|
61
|
+
"""
|
|
62
|
+
if not name or not isinstance(name, str):
|
|
63
|
+
return "unknown"
|
|
64
|
+
cleaned = name.replace("\x00", "").replace("/", "").replace("\\", "")
|
|
65
|
+
cleaned = _PEER_SAFE_RE.sub("", cleaned).strip(".")
|
|
66
|
+
return cleaned[:64] or "unknown"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
# Path helpers
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_comms_root(shared_root: Path) -> Path:
|
|
75
|
+
"""Return the comms root directory for the sync pipeline.
|
|
76
|
+
|
|
77
|
+
This is the directory that Syncthing syncs, containing inbox/ and outbox/.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
shared_root: The agent SHARED_ROOT (``~/.skcapstone`` by default).
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
``{shared_root}/sync/comms``
|
|
84
|
+
"""
|
|
85
|
+
return Path(shared_root).expanduser() / COMMS_SUBPATH
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_inbox_dir(shared_root: Path) -> Path:
|
|
89
|
+
"""Return the inbox directory watched by the consciousness loop inotify.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
shared_root: The agent SHARED_ROOT.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
``{shared_root}/sync/comms/inbox``
|
|
96
|
+
"""
|
|
97
|
+
return Path(shared_root).expanduser() / INBOX_SUBPATH
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_outbox_dir(shared_root: Path) -> Path:
|
|
101
|
+
"""Return the outbox directory where responses are written for Syncthing.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
shared_root: The agent SHARED_ROOT.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
``{shared_root}/sync/comms/outbox``
|
|
108
|
+
"""
|
|
109
|
+
return Path(shared_root).expanduser() / OUTBOX_SUBPATH
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def ensure_comms_dirs(shared_root: Path) -> None:
|
|
113
|
+
"""Create inbox, outbox, and archive directories if they do not exist.
|
|
114
|
+
|
|
115
|
+
Safe to call on every daemon startup.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
shared_root: The agent SHARED_ROOT.
|
|
119
|
+
"""
|
|
120
|
+
root = get_comms_root(shared_root)
|
|
121
|
+
for sub in ("inbox", "outbox", "archive"):
|
|
122
|
+
(root / sub).mkdir(parents=True, exist_ok=True)
|
|
123
|
+
logger.debug("Comms dirs ensured under %s", root)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# ---------------------------------------------------------------------------
|
|
127
|
+
# Pipeline verification
|
|
128
|
+
# ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def verify_pipeline_paths(shared_root: Path, skcomm=None) -> dict:
|
|
132
|
+
"""Verify inbox/outbox path alignment for the full sync pipeline.
|
|
133
|
+
|
|
134
|
+
Checks:
|
|
135
|
+
|
|
136
|
+
1. The consciousness loop's watched inbox dir exists.
|
|
137
|
+
2. The outbox dir exists so responses can be written and synced.
|
|
138
|
+
3. (Optional) The active SKComm Syncthing transport's ``comms_root``
|
|
139
|
+
matches ``{shared_root}/sync/comms``.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
shared_root: The agent SHARED_ROOT.
|
|
143
|
+
skcomm: Optional :class:`SKComm` instance to inspect transport config.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Dict with keys:
|
|
147
|
+
|
|
148
|
+
- ``inbox_ok`` (bool) — inbox dir exists.
|
|
149
|
+
- ``outbox_ok`` (bool) — outbox dir exists.
|
|
150
|
+
- ``transport_aligned`` (bool | None) — transport comms_root matches
|
|
151
|
+
(None if skcomm not provided or check failed).
|
|
152
|
+
- ``inbox_path`` (str) — absolute inbox path.
|
|
153
|
+
- ``outbox_path`` (str) — absolute outbox path.
|
|
154
|
+
- ``expected_comms_root`` (str) — the expected comms root.
|
|
155
|
+
- ``issues`` (list[str]) — human-readable problem descriptions.
|
|
156
|
+
"""
|
|
157
|
+
inbox = get_inbox_dir(shared_root)
|
|
158
|
+
outbox = get_outbox_dir(shared_root)
|
|
159
|
+
expected_root = get_comms_root(shared_root)
|
|
160
|
+
issues: list[str] = []
|
|
161
|
+
|
|
162
|
+
inbox_ok = inbox.exists()
|
|
163
|
+
if not inbox_ok:
|
|
164
|
+
issues.append(f"Inbox dir missing: {inbox}")
|
|
165
|
+
|
|
166
|
+
outbox_ok = outbox.exists()
|
|
167
|
+
if not outbox_ok:
|
|
168
|
+
issues.append(f"Outbox dir missing: {outbox}")
|
|
169
|
+
|
|
170
|
+
transport_aligned: Optional[bool] = None
|
|
171
|
+
if skcomm is not None:
|
|
172
|
+
try:
|
|
173
|
+
transport_aligned = _check_transport_alignment(skcomm, expected_root, issues)
|
|
174
|
+
except Exception as exc:
|
|
175
|
+
logger.debug("Transport alignment check failed: %s", exc)
|
|
176
|
+
issues.append(f"Transport alignment check error: {exc}")
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
"inbox_ok": inbox_ok,
|
|
180
|
+
"outbox_ok": outbox_ok,
|
|
181
|
+
"transport_aligned": transport_aligned,
|
|
182
|
+
"inbox_path": str(inbox),
|
|
183
|
+
"outbox_path": str(outbox),
|
|
184
|
+
"expected_comms_root": str(expected_root),
|
|
185
|
+
"issues": issues,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _check_transport_alignment(skcomm, expected_root: Path, issues: list[str]) -> bool:
|
|
190
|
+
"""Walk SKComm router transports and check the Syncthing transport's root.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
skcomm: SKComm instance (has ``router`` or ``_router`` attribute).
|
|
194
|
+
expected_root: The expected comms root path.
|
|
195
|
+
issues: Mutable list; problem strings are appended here.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
``True`` if aligned (or no Syncthing transport registered),
|
|
199
|
+
``False`` on mismatch.
|
|
200
|
+
"""
|
|
201
|
+
router = getattr(skcomm, "router", None) or getattr(skcomm, "_router", None)
|
|
202
|
+
if router is None:
|
|
203
|
+
return True # can't check — assume ok
|
|
204
|
+
|
|
205
|
+
transports = getattr(router, "transports", [])
|
|
206
|
+
aligned = True
|
|
207
|
+
for transport in transports:
|
|
208
|
+
if getattr(transport, "name", "") != "syncthing":
|
|
209
|
+
continue
|
|
210
|
+
actual_root = getattr(transport, "_root", None)
|
|
211
|
+
if actual_root is None:
|
|
212
|
+
continue
|
|
213
|
+
if Path(actual_root).resolve() != expected_root.resolve():
|
|
214
|
+
issues.append(
|
|
215
|
+
f"SyncthingTransport comms_root mismatch — "
|
|
216
|
+
f"expected {expected_root}, got {actual_root}. "
|
|
217
|
+
f"Set comms_root: {expected_root} in ~/.skcomm/config.yml"
|
|
218
|
+
)
|
|
219
|
+
aligned = False
|
|
220
|
+
return aligned
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# ---------------------------------------------------------------------------
|
|
224
|
+
# Pipeline status
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def get_sync_pipeline_status(shared_root: Path) -> dict:
|
|
229
|
+
"""Collect comms pipeline health: inbox/outbox file counts and path checks.
|
|
230
|
+
|
|
231
|
+
Suitable for inclusion in the daemon health snapshot.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
shared_root: The agent SHARED_ROOT.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Dict with keys:
|
|
238
|
+
|
|
239
|
+
- ``inbox_files`` (int) — pending inbox envelope count.
|
|
240
|
+
- ``outbox_files`` (int) — pending outbox envelope count.
|
|
241
|
+
- ``inbox_peers`` (list[str]) — peers with pending inbox files.
|
|
242
|
+
- ``outbox_peers`` (list[str]) — peers with pending outbox files.
|
|
243
|
+
- ``inbox_path`` (str), ``outbox_path`` (str) — absolute paths.
|
|
244
|
+
- ``inbox_exists`` (bool), ``outbox_exists`` (bool).
|
|
245
|
+
- ``checked_at`` (str) — ISO-8601 UTC timestamp.
|
|
246
|
+
"""
|
|
247
|
+
inbox = get_inbox_dir(shared_root)
|
|
248
|
+
outbox = get_outbox_dir(shared_root)
|
|
249
|
+
|
|
250
|
+
def _count(base: Path) -> tuple[int, list[str]]:
|
|
251
|
+
if not base.exists():
|
|
252
|
+
return 0, []
|
|
253
|
+
total = 0
|
|
254
|
+
peers: list[str] = []
|
|
255
|
+
try:
|
|
256
|
+
for peer_dir in base.iterdir():
|
|
257
|
+
if not peer_dir.is_dir():
|
|
258
|
+
continue
|
|
259
|
+
count = len(list(peer_dir.glob(f"*{ENVELOPE_SUFFIX}")))
|
|
260
|
+
if count:
|
|
261
|
+
total += count
|
|
262
|
+
peers.append(peer_dir.name)
|
|
263
|
+
except OSError as exc:
|
|
264
|
+
logger.debug("Error counting envelopes in %s: %s", base, exc)
|
|
265
|
+
return total, peers
|
|
266
|
+
|
|
267
|
+
inbox_count, inbox_peers = _count(inbox)
|
|
268
|
+
outbox_count, outbox_peers = _count(outbox)
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
"inbox_files": inbox_count,
|
|
272
|
+
"outbox_files": outbox_count,
|
|
273
|
+
"inbox_peers": inbox_peers,
|
|
274
|
+
"outbox_peers": outbox_peers,
|
|
275
|
+
"inbox_path": str(inbox),
|
|
276
|
+
"outbox_path": str(outbox),
|
|
277
|
+
"inbox_exists": inbox.exists(),
|
|
278
|
+
"outbox_exists": outbox.exists(),
|
|
279
|
+
"checked_at": datetime.now(timezone.utc).isoformat(),
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
# ---------------------------------------------------------------------------
|
|
284
|
+
# Outbox write helper
|
|
285
|
+
# ---------------------------------------------------------------------------
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def write_outbox_envelope(
|
|
289
|
+
shared_root: Path,
|
|
290
|
+
recipient: str,
|
|
291
|
+
envelope: dict,
|
|
292
|
+
sign: bool = False,
|
|
293
|
+
pgp_key_id: Optional[str] = None,
|
|
294
|
+
) -> Path:
|
|
295
|
+
"""Write a response envelope to the outbox for Syncthing to sync.
|
|
296
|
+
|
|
297
|
+
Uses atomic write (tmp → rename) to prevent Syncthing from picking up
|
|
298
|
+
partial files. Optionally attaches a PGP detached signature in the
|
|
299
|
+
``payload.signature`` field via CapAuth.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
shared_root: The agent SHARED_ROOT.
|
|
303
|
+
recipient: Recipient agent name (used as subdirectory; sanitized).
|
|
304
|
+
envelope: Envelope dict to serialize as JSON.
|
|
305
|
+
sign: Whether to attempt PGP signing via CapAuth.
|
|
306
|
+
pgp_key_id: Optional PGP key ID. Uses the default CapAuth key if
|
|
307
|
+
``None``.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
:class:`Path` to the written ``.skc.json`` file.
|
|
311
|
+
"""
|
|
312
|
+
peer = _sanitize_peer(recipient)
|
|
313
|
+
outbox_peer = get_outbox_dir(shared_root) / peer
|
|
314
|
+
outbox_peer.mkdir(parents=True, exist_ok=True)
|
|
315
|
+
|
|
316
|
+
if sign:
|
|
317
|
+
try:
|
|
318
|
+
_sign_envelope(envelope, pgp_key_id)
|
|
319
|
+
except Exception as exc:
|
|
320
|
+
logger.warning("PGP signing failed — writing unsigned envelope: %s", exc)
|
|
321
|
+
|
|
322
|
+
envelope_id = (
|
|
323
|
+
envelope.get("envelope_id")
|
|
324
|
+
or envelope.get("message_id")
|
|
325
|
+
or str(int(time.time() * 1000))
|
|
326
|
+
)
|
|
327
|
+
filename = f"{envelope_id}{ENVELOPE_SUFFIX}"
|
|
328
|
+
target = outbox_peer / filename
|
|
329
|
+
tmp = outbox_peer / f".{filename}.tmp"
|
|
330
|
+
|
|
331
|
+
payload_bytes = json.dumps(envelope, ensure_ascii=False, indent=2).encode("utf-8")
|
|
332
|
+
tmp.write_bytes(payload_bytes)
|
|
333
|
+
tmp.rename(target)
|
|
334
|
+
|
|
335
|
+
logger.info("Outbox: wrote %s → %s", envelope_id[:8], target)
|
|
336
|
+
return target
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def _sign_envelope(envelope: dict, key_id: Optional[str] = None) -> None:
|
|
340
|
+
"""Attach a PGP detached signature to the envelope payload in-place.
|
|
341
|
+
|
|
342
|
+
Signs the ``payload.content`` (or ``payload.message``) field and stores
|
|
343
|
+
the armored ASCII signature in ``payload.signature``.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
envelope: Envelope dict. Modified in-place.
|
|
347
|
+
key_id: Optional PGP key ID. Uses the default CapAuth key if ``None``.
|
|
348
|
+
"""
|
|
349
|
+
from capauth.crypto import get_backend
|
|
350
|
+
|
|
351
|
+
payload = envelope.get("payload", envelope)
|
|
352
|
+
content = payload.get("content") or payload.get("message") or ""
|
|
353
|
+
if not content:
|
|
354
|
+
return
|
|
355
|
+
|
|
356
|
+
backend = get_backend()
|
|
357
|
+
content_bytes = content.encode("utf-8") if isinstance(content, str) else content
|
|
358
|
+
kwargs: dict = {}
|
|
359
|
+
if key_id:
|
|
360
|
+
kwargs["key_id"] = key_id
|
|
361
|
+
signature = backend.sign(data=content_bytes, **kwargs)
|
|
362
|
+
payload["signature"] = signature
|
|
363
|
+
logger.debug("Envelope signed (key_id=%s)", key_id or "default")
|