@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,408 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for skcapstone.team_comms — agent-to-agent communication layer.
|
|
3
|
+
|
|
4
|
+
Covers:
|
|
5
|
+
- Channel bootstrapping (directory creation)
|
|
6
|
+
- send_to_teammate happy path
|
|
7
|
+
- send_to_teammate with unknown recipient raises ValueError
|
|
8
|
+
- receive_messages drains inbox and archives files
|
|
9
|
+
- broadcast_to_team from queen delivers to all members
|
|
10
|
+
- broadcast_to_team from non-queen raises PermissionError
|
|
11
|
+
- receive_broadcast returns queen messages for non-queen members
|
|
12
|
+
- Board logging is invoked when a board is provided
|
|
13
|
+
- TeamEngine.deploy() populates comms_channel
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import List, Optional
|
|
21
|
+
from unittest.mock import MagicMock, patch
|
|
22
|
+
|
|
23
|
+
import pytest
|
|
24
|
+
|
|
25
|
+
from skcapstone.team_comms import (
|
|
26
|
+
TeamChannel,
|
|
27
|
+
bootstrap_team_channel,
|
|
28
|
+
broadcast_to_team,
|
|
29
|
+
receive_broadcast,
|
|
30
|
+
receive_messages,
|
|
31
|
+
send_to_teammate,
|
|
32
|
+
_ENVELOPE_SUFFIX,
|
|
33
|
+
_build_envelope,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
# Fixtures
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.fixture
|
|
43
|
+
def comms_root(tmp_path: Path) -> Path:
|
|
44
|
+
"""Return a temporary comms root directory."""
|
|
45
|
+
root = tmp_path / "comms"
|
|
46
|
+
root.mkdir()
|
|
47
|
+
return root
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.fixture
|
|
51
|
+
def channel(comms_root: Path) -> TeamChannel:
|
|
52
|
+
"""A bootstrapped three-agent channel with 'alpha' as queen."""
|
|
53
|
+
return bootstrap_team_channel(
|
|
54
|
+
team_slug="test-team",
|
|
55
|
+
agent_names=["alpha", "beta", "gamma"],
|
|
56
|
+
comms_root=comms_root,
|
|
57
|
+
queen="alpha",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
# bootstrap_team_channel
|
|
63
|
+
# ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class TestBootstrapTeamChannel:
|
|
67
|
+
"""Tests for bootstrap_team_channel()."""
|
|
68
|
+
|
|
69
|
+
def test_creates_inbox_and_archive_for_each_agent(
|
|
70
|
+
self, comms_root: Path
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Inbox and archive directories are created for every agent."""
|
|
73
|
+
channel = bootstrap_team_channel(
|
|
74
|
+
team_slug="myteam",
|
|
75
|
+
agent_names=["worker1", "worker2"],
|
|
76
|
+
comms_root=comms_root,
|
|
77
|
+
)
|
|
78
|
+
for agent in ["worker1", "worker2"]:
|
|
79
|
+
assert channel.inbox_for(agent).is_dir()
|
|
80
|
+
assert channel.archive_for(agent).is_dir()
|
|
81
|
+
|
|
82
|
+
def test_broadcast_dir_created_when_queen_set(
|
|
83
|
+
self, comms_root: Path
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Broadcast directory exists when queen is specified."""
|
|
86
|
+
channel = bootstrap_team_channel(
|
|
87
|
+
team_slug="queenteam",
|
|
88
|
+
agent_names=["queen", "minion"],
|
|
89
|
+
comms_root=comms_root,
|
|
90
|
+
queen="queen",
|
|
91
|
+
)
|
|
92
|
+
assert channel.broadcast_dir.is_dir()
|
|
93
|
+
|
|
94
|
+
def test_broadcast_dir_not_created_without_queen(
|
|
95
|
+
self, comms_root: Path
|
|
96
|
+
) -> None:
|
|
97
|
+
"""No broadcast directory when no queen is set."""
|
|
98
|
+
channel = bootstrap_team_channel(
|
|
99
|
+
team_slug="peerteam",
|
|
100
|
+
agent_names=["a", "b"],
|
|
101
|
+
comms_root=comms_root,
|
|
102
|
+
queen=None,
|
|
103
|
+
)
|
|
104
|
+
assert not channel.broadcast_dir.exists()
|
|
105
|
+
|
|
106
|
+
def test_idempotent(self, comms_root: Path) -> None:
|
|
107
|
+
"""Calling bootstrap twice does not raise or corrupt state."""
|
|
108
|
+
bootstrap_team_channel("idempotent", ["x"], comms_root, queen="x")
|
|
109
|
+
channel = bootstrap_team_channel("idempotent", ["x"], comms_root, queen="x")
|
|
110
|
+
assert channel.inbox_for("x").is_dir()
|
|
111
|
+
|
|
112
|
+
def test_channel_members_and_queen(self, comms_root: Path) -> None:
|
|
113
|
+
"""Channel reports correct members and queen."""
|
|
114
|
+
channel = bootstrap_team_channel(
|
|
115
|
+
team_slug="t",
|
|
116
|
+
agent_names=["a", "b", "c"],
|
|
117
|
+
comms_root=comms_root,
|
|
118
|
+
queen="a",
|
|
119
|
+
)
|
|
120
|
+
assert channel.members == ["a", "b", "c"]
|
|
121
|
+
assert channel.queen == "a"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ---------------------------------------------------------------------------
|
|
125
|
+
# send_to_teammate
|
|
126
|
+
# ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class TestSendToTeammate:
|
|
130
|
+
"""Tests for send_to_teammate()."""
|
|
131
|
+
|
|
132
|
+
def test_happy_path_writes_envelope(self, channel: TeamChannel) -> None:
|
|
133
|
+
"""A valid send writes exactly one .skc.json file to the inbox."""
|
|
134
|
+
send_to_teammate("alpha", "beta", "Hello beta!", channel)
|
|
135
|
+
inbox = channel.inbox_for("beta")
|
|
136
|
+
files = list(inbox.glob(f"*{_ENVELOPE_SUFFIX}"))
|
|
137
|
+
assert len(files) == 1
|
|
138
|
+
|
|
139
|
+
def test_envelope_content_is_valid_json(self, channel: TeamChannel) -> None:
|
|
140
|
+
"""The written file is parseable and has correct sender/recipient."""
|
|
141
|
+
eid = send_to_teammate("alpha", "gamma", "Hi gamma", channel)
|
|
142
|
+
inbox = channel.inbox_for("gamma")
|
|
143
|
+
files = list(inbox.glob(f"*{_ENVELOPE_SUFFIX}"))
|
|
144
|
+
data = json.loads(files[0].read_text())
|
|
145
|
+
assert data["sender"] == "alpha"
|
|
146
|
+
assert data["recipient"] == "gamma"
|
|
147
|
+
assert data["payload"]["content"] == "Hi gamma"
|
|
148
|
+
assert data["envelope_id"] == eid
|
|
149
|
+
|
|
150
|
+
def test_thread_id_propagated(self, channel: TeamChannel) -> None:
|
|
151
|
+
"""thread_id is stored in envelope metadata."""
|
|
152
|
+
send_to_teammate("beta", "gamma", "msg", channel, thread_id="t-001")
|
|
153
|
+
files = list(channel.inbox_for("gamma").glob(f"*{_ENVELOPE_SUFFIX}"))
|
|
154
|
+
data = json.loads(files[0].read_text())
|
|
155
|
+
assert data["metadata"]["thread_id"] == "t-001"
|
|
156
|
+
|
|
157
|
+
def test_unknown_recipient_raises(self, channel: TeamChannel) -> None:
|
|
158
|
+
"""Sending to a non-member raises ValueError."""
|
|
159
|
+
with pytest.raises(ValueError, match="not a member"):
|
|
160
|
+
send_to_teammate("alpha", "unknown-bot", "hi", channel)
|
|
161
|
+
|
|
162
|
+
def test_board_log_called(self, channel: TeamChannel) -> None:
|
|
163
|
+
"""Board.save_agent is called when board is provided."""
|
|
164
|
+
mock_board = MagicMock()
|
|
165
|
+
mock_board.load_agent.return_value = None
|
|
166
|
+
send_to_teammate("alpha", "beta", "msg", channel, board=mock_board)
|
|
167
|
+
mock_board.save_agent.assert_called_once()
|
|
168
|
+
|
|
169
|
+
def test_board_failure_does_not_raise(self, channel: TeamChannel) -> None:
|
|
170
|
+
"""A broken board never prevents message delivery."""
|
|
171
|
+
broken_board = MagicMock()
|
|
172
|
+
broken_board.load_agent.side_effect = RuntimeError("db down")
|
|
173
|
+
# Should not raise
|
|
174
|
+
eid = send_to_teammate("alpha", "beta", "msg", channel, board=broken_board)
|
|
175
|
+
assert eid
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ---------------------------------------------------------------------------
|
|
179
|
+
# receive_messages
|
|
180
|
+
# ---------------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class TestReceiveMessages:
|
|
184
|
+
"""Tests for receive_messages()."""
|
|
185
|
+
|
|
186
|
+
def test_returns_empty_when_no_messages(self, channel: TeamChannel) -> None:
|
|
187
|
+
"""Empty inbox returns empty list."""
|
|
188
|
+
assert receive_messages("beta", channel) == []
|
|
189
|
+
|
|
190
|
+
def test_drains_all_messages(self, channel: TeamChannel) -> None:
|
|
191
|
+
"""All messages in inbox are returned and then archived."""
|
|
192
|
+
send_to_teammate("alpha", "beta", "msg1", channel)
|
|
193
|
+
send_to_teammate("gamma", "beta", "msg2", channel)
|
|
194
|
+
received = receive_messages("beta", channel)
|
|
195
|
+
assert len(received) == 2
|
|
196
|
+
# Inbox now empty
|
|
197
|
+
assert receive_messages("beta", channel) == []
|
|
198
|
+
|
|
199
|
+
def test_messages_moved_to_archive(self, channel: TeamChannel) -> None:
|
|
200
|
+
"""Processed messages are moved to archive, not deleted."""
|
|
201
|
+
send_to_teammate("alpha", "beta", "archived?", channel)
|
|
202
|
+
receive_messages("beta", channel)
|
|
203
|
+
archive = channel.archive_for("beta")
|
|
204
|
+
files = list(archive.glob(f"*{_ENVELOPE_SUFFIX}"))
|
|
205
|
+
assert len(files) == 1
|
|
206
|
+
|
|
207
|
+
def test_returns_correct_content(self, channel: TeamChannel) -> None:
|
|
208
|
+
"""Returned envelopes contain the correct message content."""
|
|
209
|
+
send_to_teammate("alpha", "beta", "specific content", channel)
|
|
210
|
+
msgs = receive_messages("beta", channel)
|
|
211
|
+
assert msgs[0]["payload"]["content"] == "specific content"
|
|
212
|
+
|
|
213
|
+
def test_corrupted_file_skipped(self, channel: TeamChannel) -> None:
|
|
214
|
+
"""A malformed envelope file is skipped without crashing."""
|
|
215
|
+
inbox = channel.inbox_for("beta")
|
|
216
|
+
inbox.mkdir(parents=True, exist_ok=True)
|
|
217
|
+
bad_file = inbox / f"corrupt{_ENVELOPE_SUFFIX}"
|
|
218
|
+
bad_file.write_text("not valid json")
|
|
219
|
+
# Valid message also present
|
|
220
|
+
send_to_teammate("alpha", "beta", "valid", channel)
|
|
221
|
+
msgs = receive_messages("beta", channel)
|
|
222
|
+
assert len(msgs) == 1
|
|
223
|
+
assert msgs[0]["payload"]["content"] == "valid"
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# ---------------------------------------------------------------------------
|
|
227
|
+
# broadcast_to_team
|
|
228
|
+
# ---------------------------------------------------------------------------
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class TestBroadcastToTeam:
|
|
232
|
+
"""Tests for broadcast_to_team()."""
|
|
233
|
+
|
|
234
|
+
def test_queen_can_broadcast(self, channel: TeamChannel) -> None:
|
|
235
|
+
"""Queen can broadcast; all non-queen members receive the message."""
|
|
236
|
+
eids = broadcast_to_team("alpha", "All hands!", channel)
|
|
237
|
+
assert len(eids) == 2 # beta and gamma
|
|
238
|
+
assert len(receive_messages("beta", channel)) == 1
|
|
239
|
+
assert len(receive_messages("gamma", channel)) == 1
|
|
240
|
+
|
|
241
|
+
def test_queen_does_not_receive_own_broadcast(
|
|
242
|
+
self, channel: TeamChannel
|
|
243
|
+
) -> None:
|
|
244
|
+
"""The queen's inbox is not written to during a broadcast."""
|
|
245
|
+
broadcast_to_team("alpha", "Hello team", channel)
|
|
246
|
+
assert receive_messages("alpha", channel) == []
|
|
247
|
+
|
|
248
|
+
def test_broadcast_written_to_audit_dir(self, channel: TeamChannel) -> None:
|
|
249
|
+
"""Broadcast envelope is also written to the broadcast directory."""
|
|
250
|
+
broadcast_to_team("alpha", "Audit this", channel)
|
|
251
|
+
files = list(channel.broadcast_dir.glob(f"*{_ENVELOPE_SUFFIX}"))
|
|
252
|
+
assert len(files) == 1
|
|
253
|
+
|
|
254
|
+
def test_non_queen_broadcast_raises(self, channel: TeamChannel) -> None:
|
|
255
|
+
"""Non-queen agent attempting broadcast raises PermissionError."""
|
|
256
|
+
with pytest.raises(PermissionError, match="queen"):
|
|
257
|
+
broadcast_to_team("beta", "I am not the queen", channel)
|
|
258
|
+
|
|
259
|
+
def test_no_queen_allows_any_broadcast(self, comms_root: Path) -> None:
|
|
260
|
+
"""When channel has no queen, any member may broadcast."""
|
|
261
|
+
ch = bootstrap_team_channel(
|
|
262
|
+
"open-team", ["x", "y", "z"], comms_root, queen=None
|
|
263
|
+
)
|
|
264
|
+
eids = broadcast_to_team("x", "peer broadcast", ch)
|
|
265
|
+
# y and z each get one message
|
|
266
|
+
assert len(eids) == 2
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# ---------------------------------------------------------------------------
|
|
270
|
+
# receive_broadcast
|
|
271
|
+
# ---------------------------------------------------------------------------
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class TestReceiveBroadcast:
|
|
275
|
+
"""Tests for receive_broadcast()."""
|
|
276
|
+
|
|
277
|
+
def test_non_queen_reads_broadcast(self, channel: TeamChannel) -> None:
|
|
278
|
+
"""A member agent can read broadcast messages."""
|
|
279
|
+
broadcast_to_team("alpha", "Broadcast content", channel)
|
|
280
|
+
msgs = receive_broadcast("beta", channel)
|
|
281
|
+
assert len(msgs) == 1
|
|
282
|
+
assert msgs[0]["payload"]["content"] == "Broadcast content"
|
|
283
|
+
|
|
284
|
+
def test_sender_filtered_from_broadcast(self, channel: TeamChannel) -> None:
|
|
285
|
+
"""The queen's own broadcast is not returned to herself."""
|
|
286
|
+
broadcast_to_team("alpha", "self-filter test", channel)
|
|
287
|
+
msgs = receive_broadcast("alpha", channel)
|
|
288
|
+
assert msgs == []
|
|
289
|
+
|
|
290
|
+
def test_empty_when_no_broadcasts(self, channel: TeamChannel) -> None:
|
|
291
|
+
"""Returns empty list when broadcast directory is empty."""
|
|
292
|
+
assert receive_broadcast("beta", channel) == []
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
# ---------------------------------------------------------------------------
|
|
296
|
+
# _build_envelope
|
|
297
|
+
# ---------------------------------------------------------------------------
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class TestBuildEnvelope:
|
|
301
|
+
"""Tests for the internal _build_envelope helper."""
|
|
302
|
+
|
|
303
|
+
def test_required_fields_present(self) -> None:
|
|
304
|
+
"""Envelope dict has all required SKComm fields."""
|
|
305
|
+
env = _build_envelope("agent-a", "agent-b", "hello")
|
|
306
|
+
assert env["skcomm_version"] == "1.0.0"
|
|
307
|
+
assert env["sender"] == "agent-a"
|
|
308
|
+
assert env["recipient"] == "agent-b"
|
|
309
|
+
assert env["payload"]["content"] == "hello"
|
|
310
|
+
assert "envelope_id" in env
|
|
311
|
+
|
|
312
|
+
def test_unique_ids(self) -> None:
|
|
313
|
+
"""Two envelopes have distinct envelope_ids."""
|
|
314
|
+
e1 = _build_envelope("a", "b", "msg")
|
|
315
|
+
e2 = _build_envelope("a", "b", "msg")
|
|
316
|
+
assert e1["envelope_id"] != e2["envelope_id"]
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
# ---------------------------------------------------------------------------
|
|
320
|
+
# TeamEngine integration
|
|
321
|
+
# ---------------------------------------------------------------------------
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class TestTeamEngineCommsIntegration:
|
|
325
|
+
"""Verify TeamEngine.deploy() wires comms correctly."""
|
|
326
|
+
|
|
327
|
+
def test_deploy_populates_comms_channel(self, tmp_path: Path) -> None:
|
|
328
|
+
"""After deploy(), TeamDeployment.comms_channel is a TeamChannel."""
|
|
329
|
+
from skcapstone.blueprints.schema import (
|
|
330
|
+
AgentRole,
|
|
331
|
+
AgentSpec,
|
|
332
|
+
BlueprintManifest,
|
|
333
|
+
CoordinationConfig,
|
|
334
|
+
)
|
|
335
|
+
from skcapstone.team_engine import TeamEngine
|
|
336
|
+
|
|
337
|
+
blueprint = BlueprintManifest(
|
|
338
|
+
name="Test Team",
|
|
339
|
+
slug="test-team",
|
|
340
|
+
description="Unit test team",
|
|
341
|
+
agents={
|
|
342
|
+
"queen": AgentSpec(role=AgentRole.MANAGER),
|
|
343
|
+
"worker": AgentSpec(role=AgentRole.WORKER),
|
|
344
|
+
},
|
|
345
|
+
coordination=CoordinationConfig(queen="queen"),
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
engine = TeamEngine(
|
|
349
|
+
home=tmp_path / ".skcapstone",
|
|
350
|
+
comms_root=tmp_path / "comms",
|
|
351
|
+
)
|
|
352
|
+
deployment = engine.deploy(blueprint)
|
|
353
|
+
|
|
354
|
+
assert deployment.comms_channel is not None
|
|
355
|
+
assert isinstance(deployment.comms_channel, TeamChannel)
|
|
356
|
+
assert len(deployment.comms_channel.members) == 2
|
|
357
|
+
|
|
358
|
+
def test_deploy_without_comms_root_skips_channel(
|
|
359
|
+
self, tmp_path: Path
|
|
360
|
+
) -> None:
|
|
361
|
+
"""When comms_root is explicitly None, comms_channel stays None."""
|
|
362
|
+
from skcapstone.blueprints.schema import AgentSpec, BlueprintManifest
|
|
363
|
+
from skcapstone.team_engine import TeamEngine
|
|
364
|
+
|
|
365
|
+
blueprint = BlueprintManifest(
|
|
366
|
+
name="No Comms",
|
|
367
|
+
slug="no-comms",
|
|
368
|
+
description="Team without comms",
|
|
369
|
+
agents={"solo": AgentSpec()},
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Monkeypatch: set _comms_root to None directly after construction
|
|
373
|
+
engine = TeamEngine(home=tmp_path / ".skcapstone")
|
|
374
|
+
engine._comms_root = None
|
|
375
|
+
deployment = engine.deploy(blueprint)
|
|
376
|
+
|
|
377
|
+
assert deployment.comms_channel is None
|
|
378
|
+
|
|
379
|
+
def test_deploy_queen_identified_from_role(self, tmp_path: Path) -> None:
|
|
380
|
+
"""Queen is detected from AgentRole.MANAGER when coordination.queen unset."""
|
|
381
|
+
from skcapstone.blueprints.schema import (
|
|
382
|
+
AgentRole,
|
|
383
|
+
AgentSpec,
|
|
384
|
+
BlueprintManifest,
|
|
385
|
+
CoordinationConfig,
|
|
386
|
+
)
|
|
387
|
+
from skcapstone.team_engine import TeamEngine
|
|
388
|
+
|
|
389
|
+
blueprint = BlueprintManifest(
|
|
390
|
+
name="Role Team",
|
|
391
|
+
slug="role-team",
|
|
392
|
+
description="Queen via role",
|
|
393
|
+
agents={
|
|
394
|
+
"boss": AgentSpec(role=AgentRole.MANAGER),
|
|
395
|
+
"minion": AgentSpec(role=AgentRole.WORKER),
|
|
396
|
+
},
|
|
397
|
+
coordination=CoordinationConfig(queen=None),
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
engine = TeamEngine(
|
|
401
|
+
home=tmp_path / ".skcapstone",
|
|
402
|
+
comms_root=tmp_path / "comms",
|
|
403
|
+
)
|
|
404
|
+
deployment = engine.deploy(blueprint)
|
|
405
|
+
channel = deployment.comms_channel
|
|
406
|
+
assert channel is not None
|
|
407
|
+
assert channel.queen is not None
|
|
408
|
+
assert "boss" in channel.queen
|