@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,500 @@
|
|
|
1
|
+
"""Tests for the skcapstone onboard wizard — new system-setup steps.
|
|
2
|
+
|
|
3
|
+
Covers:
|
|
4
|
+
- _step_prereqs(): Python/pip/Ollama detection
|
|
5
|
+
- _step_ollama_models(): model pull with click.confirm gating
|
|
6
|
+
- _step_config_files(): consciousness.yaml + model_profiles.yaml writing
|
|
7
|
+
- _step_systemd_service(): Linux-only, click.confirm gating
|
|
8
|
+
- _step_doctor_check(): doctor diagnostics output
|
|
9
|
+
- _step_test_consciousness(): consciousness loop test with click.confirm gating
|
|
10
|
+
- TOTAL_STEPS constant updated to 13
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import shutil
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from unittest.mock import MagicMock, patch
|
|
20
|
+
|
|
21
|
+
import pytest
|
|
22
|
+
from click.testing import CliRunner
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# Helpers
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.fixture
|
|
31
|
+
def tmp_home(tmp_path: Path) -> Path:
|
|
32
|
+
"""A temporary agent home directory with required sub-dirs."""
|
|
33
|
+
home = tmp_path / ".skcapstone"
|
|
34
|
+
for d in ["identity", "memory", "trust", "security", "sync", "config"]:
|
|
35
|
+
(home / d).mkdir(parents=True, exist_ok=True)
|
|
36
|
+
return home
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
# TOTAL_STEPS
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class TestTotalSteps:
|
|
45
|
+
"""Ensure TOTAL_STEPS was updated to 13."""
|
|
46
|
+
|
|
47
|
+
def test_total_steps_is_13(self) -> None:
|
|
48
|
+
"""Wizard now has 13 numbered steps."""
|
|
49
|
+
from skcapstone.onboard import TOTAL_STEPS
|
|
50
|
+
|
|
51
|
+
assert TOTAL_STEPS == 13
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# _step_prereqs
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TestStepPrereqs:
|
|
60
|
+
"""Tests for _step_prereqs()."""
|
|
61
|
+
|
|
62
|
+
def test_returns_dict_with_three_keys(self) -> None:
|
|
63
|
+
"""Always returns a dict with python/pip/ollama keys."""
|
|
64
|
+
from skcapstone.onboard import _step_prereqs
|
|
65
|
+
|
|
66
|
+
runner = CliRunner()
|
|
67
|
+
with runner.isolated_filesystem():
|
|
68
|
+
with patch("shutil.which", return_value="/usr/bin/pip"):
|
|
69
|
+
result = _step_prereqs()
|
|
70
|
+
|
|
71
|
+
assert "python" in result
|
|
72
|
+
assert "pip" in result
|
|
73
|
+
assert "ollama" in result
|
|
74
|
+
|
|
75
|
+
def test_python_ok_for_current_interpreter(self) -> None:
|
|
76
|
+
"""Current Python should pass the >= 3.10 check."""
|
|
77
|
+
from skcapstone.onboard import _step_prereqs
|
|
78
|
+
|
|
79
|
+
runner = CliRunner()
|
|
80
|
+
with runner.isolated_filesystem():
|
|
81
|
+
with patch("shutil.which", side_effect=lambda t: "/usr/bin/pip" if t in ("pip", "pip3") else None):
|
|
82
|
+
result = _step_prereqs()
|
|
83
|
+
|
|
84
|
+
# Running under test means Python >= 3.10 in this project
|
|
85
|
+
assert result["python"] is (sys.version_info >= (3, 10))
|
|
86
|
+
|
|
87
|
+
def test_pip_true_when_pip_on_path(self) -> None:
|
|
88
|
+
"""pip key is True when pip or pip3 is found via shutil.which."""
|
|
89
|
+
from skcapstone.onboard import _step_prereqs
|
|
90
|
+
|
|
91
|
+
def fake_which(tool: str) -> str | None:
|
|
92
|
+
return "/usr/bin/pip3" if tool == "pip3" else None
|
|
93
|
+
|
|
94
|
+
# Only mock shutil.which; leave sys untouched so version_info works.
|
|
95
|
+
with patch("shutil.which", side_effect=fake_which):
|
|
96
|
+
result = _step_prereqs()
|
|
97
|
+
|
|
98
|
+
assert result["pip"] is True
|
|
99
|
+
|
|
100
|
+
def test_pip_false_when_not_on_path(self) -> None:
|
|
101
|
+
"""pip key is False when neither pip nor pip3 found."""
|
|
102
|
+
from skcapstone.onboard import _step_prereqs
|
|
103
|
+
|
|
104
|
+
with patch("shutil.which", return_value=None):
|
|
105
|
+
result = _step_prereqs()
|
|
106
|
+
|
|
107
|
+
assert result["pip"] is False
|
|
108
|
+
|
|
109
|
+
def test_ollama_detected(self) -> None:
|
|
110
|
+
"""ollama key is True when ollama binary found."""
|
|
111
|
+
from skcapstone.onboard import _step_prereqs
|
|
112
|
+
|
|
113
|
+
def fake_which(tool: str) -> str | None:
|
|
114
|
+
return "/usr/local/bin/ollama" if tool == "ollama" else "/usr/bin/pip"
|
|
115
|
+
|
|
116
|
+
with patch("shutil.which", side_effect=fake_which), \
|
|
117
|
+
patch("subprocess.run", return_value=MagicMock(returncode=0, stdout="ollama version 0.5.0\n")):
|
|
118
|
+
result = _step_prereqs()
|
|
119
|
+
|
|
120
|
+
assert result["ollama"] is True
|
|
121
|
+
|
|
122
|
+
def test_ollama_not_found(self) -> None:
|
|
123
|
+
"""ollama key is False when ollama binary missing."""
|
|
124
|
+
from skcapstone.onboard import _step_prereqs
|
|
125
|
+
|
|
126
|
+
def fake_which(tool: str) -> str | None:
|
|
127
|
+
if tool == "ollama":
|
|
128
|
+
return None
|
|
129
|
+
return "/usr/bin/pip"
|
|
130
|
+
|
|
131
|
+
with patch("shutil.which", side_effect=fake_which):
|
|
132
|
+
result = _step_prereqs()
|
|
133
|
+
|
|
134
|
+
assert result["ollama"] is False
|
|
135
|
+
|
|
136
|
+
def test_result_is_dict(self) -> None:
|
|
137
|
+
"""_step_prereqs always returns a plain dict."""
|
|
138
|
+
from skcapstone.onboard import _step_prereqs
|
|
139
|
+
|
|
140
|
+
with patch("shutil.which", return_value="/usr/bin/pip"):
|
|
141
|
+
result = _step_prereqs()
|
|
142
|
+
|
|
143
|
+
assert isinstance(result, dict)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# ---------------------------------------------------------------------------
|
|
147
|
+
# _step_ollama_models
|
|
148
|
+
# ---------------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class TestStepOllamaModels:
|
|
152
|
+
"""Tests for _step_ollama_models()."""
|
|
153
|
+
|
|
154
|
+
def test_skips_when_ollama_not_available(self) -> None:
|
|
155
|
+
"""Returns False immediately when prereqs['ollama'] is False."""
|
|
156
|
+
from skcapstone.onboard import _step_ollama_models
|
|
157
|
+
|
|
158
|
+
result = _step_ollama_models({"ollama": False})
|
|
159
|
+
|
|
160
|
+
assert result is False
|
|
161
|
+
|
|
162
|
+
def test_skips_when_user_declines(self) -> None:
|
|
163
|
+
"""Returns False when user does not confirm the pull."""
|
|
164
|
+
from skcapstone.onboard import _step_ollama_models
|
|
165
|
+
|
|
166
|
+
def fake_which(t: str) -> str | None:
|
|
167
|
+
return "/usr/local/bin/ollama" if t == "ollama" else None
|
|
168
|
+
|
|
169
|
+
with patch("shutil.which", side_effect=fake_which), \
|
|
170
|
+
patch("subprocess.run", return_value=MagicMock(returncode=0, stdout="")), \
|
|
171
|
+
patch("click.confirm", return_value=False):
|
|
172
|
+
result = _step_ollama_models({"ollama": True})
|
|
173
|
+
|
|
174
|
+
assert result is False
|
|
175
|
+
|
|
176
|
+
def test_returns_true_when_model_already_present(self) -> None:
|
|
177
|
+
"""Returns True without pulling if model already in 'ollama list'."""
|
|
178
|
+
from skcapstone.onboard import _step_ollama_models
|
|
179
|
+
|
|
180
|
+
with patch("subprocess.run", return_value=MagicMock(returncode=0, stdout="llama3.2 2.0 GB")):
|
|
181
|
+
result = _step_ollama_models({"ollama": True})
|
|
182
|
+
|
|
183
|
+
assert result is True
|
|
184
|
+
|
|
185
|
+
def test_returns_true_on_successful_pull(self) -> None:
|
|
186
|
+
"""Returns True after a successful ollama pull."""
|
|
187
|
+
from skcapstone.onboard import _step_ollama_models
|
|
188
|
+
|
|
189
|
+
call_count = {"n": 0}
|
|
190
|
+
|
|
191
|
+
def fake_run(cmd, **kwargs):
|
|
192
|
+
call_count["n"] += 1
|
|
193
|
+
if "list" in cmd:
|
|
194
|
+
return MagicMock(returncode=0, stdout="") # model not present
|
|
195
|
+
return MagicMock(returncode=0) # pull succeeds
|
|
196
|
+
|
|
197
|
+
with patch("subprocess.run", side_effect=fake_run), \
|
|
198
|
+
patch("click.confirm", return_value=True):
|
|
199
|
+
result = _step_ollama_models({"ollama": True})
|
|
200
|
+
|
|
201
|
+
assert result is True
|
|
202
|
+
|
|
203
|
+
def test_returns_false_on_pull_failure(self) -> None:
|
|
204
|
+
"""Returns False when ollama pull exits non-zero."""
|
|
205
|
+
from skcapstone.onboard import _step_ollama_models
|
|
206
|
+
|
|
207
|
+
def fake_run(cmd, **kwargs):
|
|
208
|
+
if "list" in cmd:
|
|
209
|
+
return MagicMock(returncode=0, stdout="")
|
|
210
|
+
return MagicMock(returncode=1) # pull fails
|
|
211
|
+
|
|
212
|
+
with patch("subprocess.run", side_effect=fake_run), \
|
|
213
|
+
patch("click.confirm", return_value=True):
|
|
214
|
+
result = _step_ollama_models({"ollama": True})
|
|
215
|
+
|
|
216
|
+
assert result is False
|
|
217
|
+
|
|
218
|
+
def test_returns_false_on_timeout(self) -> None:
|
|
219
|
+
"""Returns False when ollama pull times out."""
|
|
220
|
+
from skcapstone.onboard import _step_ollama_models
|
|
221
|
+
|
|
222
|
+
def fake_run(cmd, **kwargs):
|
|
223
|
+
if "list" in cmd:
|
|
224
|
+
return MagicMock(returncode=0, stdout="")
|
|
225
|
+
raise subprocess.TimeoutExpired(cmd, 600)
|
|
226
|
+
|
|
227
|
+
with patch("subprocess.run", side_effect=fake_run), \
|
|
228
|
+
patch("click.confirm", return_value=True):
|
|
229
|
+
result = _step_ollama_models({"ollama": True})
|
|
230
|
+
|
|
231
|
+
assert result is False
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# ---------------------------------------------------------------------------
|
|
235
|
+
# _step_config_files
|
|
236
|
+
# ---------------------------------------------------------------------------
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class TestStepConfigFiles:
|
|
240
|
+
"""Tests for _step_config_files()."""
|
|
241
|
+
|
|
242
|
+
def test_writes_consciousness_yaml(self, tmp_home: Path) -> None:
|
|
243
|
+
"""Creates consciousness.yaml in config/ when missing."""
|
|
244
|
+
from skcapstone.onboard import _step_config_files
|
|
245
|
+
|
|
246
|
+
consciousness_ok, _ = _step_config_files(tmp_home)
|
|
247
|
+
|
|
248
|
+
assert consciousness_ok is True
|
|
249
|
+
dest = tmp_home / "config" / "consciousness.yaml"
|
|
250
|
+
assert dest.exists()
|
|
251
|
+
|
|
252
|
+
def test_skips_existing_consciousness_yaml(self, tmp_home: Path) -> None:
|
|
253
|
+
"""Does not overwrite an existing consciousness.yaml."""
|
|
254
|
+
from skcapstone.onboard import _step_config_files
|
|
255
|
+
|
|
256
|
+
existing = tmp_home / "config" / "consciousness.yaml"
|
|
257
|
+
existing.write_text("enabled: false\n", encoding="utf-8")
|
|
258
|
+
|
|
259
|
+
consciousness_ok, _ = _step_config_files(tmp_home)
|
|
260
|
+
|
|
261
|
+
assert consciousness_ok is True
|
|
262
|
+
assert existing.read_text(encoding="utf-8") == "enabled: false\n"
|
|
263
|
+
|
|
264
|
+
def test_writes_model_profiles_yaml(self, tmp_home: Path) -> None:
|
|
265
|
+
"""Copies bundled model_profiles.yaml when missing."""
|
|
266
|
+
from skcapstone.onboard import _step_config_files
|
|
267
|
+
from pathlib import Path as _Path
|
|
268
|
+
import skcapstone.onboard as _onboard_module
|
|
269
|
+
|
|
270
|
+
bundled = _Path(_onboard_module.__file__).parent / "data" / "model_profiles.yaml"
|
|
271
|
+
if not bundled.exists():
|
|
272
|
+
pytest.skip("Bundled model_profiles.yaml not present in data/")
|
|
273
|
+
|
|
274
|
+
_, profiles_ok = _step_config_files(tmp_home)
|
|
275
|
+
|
|
276
|
+
assert profiles_ok is True
|
|
277
|
+
dest = tmp_home / "config" / "model_profiles.yaml"
|
|
278
|
+
assert dest.exists()
|
|
279
|
+
assert dest.stat().st_size > 0
|
|
280
|
+
|
|
281
|
+
def test_skips_existing_model_profiles(self, tmp_home: Path) -> None:
|
|
282
|
+
"""Does not overwrite an existing model_profiles.yaml."""
|
|
283
|
+
from skcapstone.onboard import _step_config_files
|
|
284
|
+
|
|
285
|
+
existing = tmp_home / "config" / "model_profiles.yaml"
|
|
286
|
+
existing.write_text("profiles: []\n", encoding="utf-8")
|
|
287
|
+
|
|
288
|
+
_, profiles_ok = _step_config_files(tmp_home)
|
|
289
|
+
|
|
290
|
+
assert profiles_ok is True
|
|
291
|
+
assert existing.read_text(encoding="utf-8") == "profiles: []\n"
|
|
292
|
+
|
|
293
|
+
def test_returns_two_booleans(self, tmp_home: Path) -> None:
|
|
294
|
+
"""Always returns a 2-tuple of booleans."""
|
|
295
|
+
from skcapstone.onboard import _step_config_files
|
|
296
|
+
|
|
297
|
+
result = _step_config_files(tmp_home)
|
|
298
|
+
|
|
299
|
+
assert isinstance(result, tuple)
|
|
300
|
+
assert len(result) == 2
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
# ---------------------------------------------------------------------------
|
|
304
|
+
# _step_systemd_service
|
|
305
|
+
# ---------------------------------------------------------------------------
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class TestStepSystemdService:
|
|
309
|
+
"""Tests for _step_systemd_service()."""
|
|
310
|
+
|
|
311
|
+
def test_returns_false_on_non_linux(self) -> None:
|
|
312
|
+
"""Returns False immediately on non-Linux platforms."""
|
|
313
|
+
from skcapstone.onboard import _step_systemd_service
|
|
314
|
+
|
|
315
|
+
with patch("platform.system", return_value="Darwin"):
|
|
316
|
+
result = _step_systemd_service()
|
|
317
|
+
|
|
318
|
+
assert result is False
|
|
319
|
+
|
|
320
|
+
def test_returns_false_when_user_declines(self) -> None:
|
|
321
|
+
"""Returns False when user does not confirm the install."""
|
|
322
|
+
from skcapstone.onboard import _step_systemd_service
|
|
323
|
+
|
|
324
|
+
with patch("platform.system", return_value="Linux"), \
|
|
325
|
+
patch("click.confirm", return_value=False):
|
|
326
|
+
result = _step_systemd_service()
|
|
327
|
+
|
|
328
|
+
assert result is False
|
|
329
|
+
|
|
330
|
+
def test_returns_false_when_systemd_unavailable(self) -> None:
|
|
331
|
+
"""Returns False when systemd user session is not running."""
|
|
332
|
+
from skcapstone.onboard import _step_systemd_service
|
|
333
|
+
|
|
334
|
+
with patch("platform.system", return_value="Linux"), \
|
|
335
|
+
patch("click.confirm", return_value=True), \
|
|
336
|
+
patch("skcapstone.systemd.systemd_available", return_value=False):
|
|
337
|
+
result = _step_systemd_service()
|
|
338
|
+
|
|
339
|
+
assert result is False
|
|
340
|
+
|
|
341
|
+
def test_returns_true_on_successful_install(self) -> None:
|
|
342
|
+
"""Returns True when systemd install succeeds."""
|
|
343
|
+
from skcapstone.onboard import _step_systemd_service
|
|
344
|
+
|
|
345
|
+
with patch("platform.system", return_value="Linux"), \
|
|
346
|
+
patch("click.confirm", return_value=True), \
|
|
347
|
+
patch("skcapstone.systemd.systemd_available", return_value=True), \
|
|
348
|
+
patch("skcapstone.systemd.install_service", return_value={"installed": True, "enabled": True}):
|
|
349
|
+
result = _step_systemd_service()
|
|
350
|
+
|
|
351
|
+
assert result is True
|
|
352
|
+
|
|
353
|
+
def test_returns_false_on_install_failure(self) -> None:
|
|
354
|
+
"""Returns False when install_service reports not installed."""
|
|
355
|
+
from skcapstone.onboard import _step_systemd_service
|
|
356
|
+
|
|
357
|
+
with patch("platform.system", return_value="Linux"), \
|
|
358
|
+
patch("click.confirm", return_value=True), \
|
|
359
|
+
patch("skcapstone.systemd.systemd_available", return_value=True), \
|
|
360
|
+
patch("skcapstone.systemd.install_service", return_value={"installed": False}):
|
|
361
|
+
result = _step_systemd_service()
|
|
362
|
+
|
|
363
|
+
assert result is False
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
# ---------------------------------------------------------------------------
|
|
367
|
+
# _step_doctor_check
|
|
368
|
+
# ---------------------------------------------------------------------------
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class TestStepDoctorCheck:
|
|
372
|
+
"""Tests for _step_doctor_check()."""
|
|
373
|
+
|
|
374
|
+
def test_returns_diagnostic_report(self, tmp_home: Path) -> None:
|
|
375
|
+
"""Returns a DiagnosticReport object."""
|
|
376
|
+
from skcapstone.doctor import DiagnosticReport
|
|
377
|
+
from skcapstone.onboard import _step_doctor_check
|
|
378
|
+
|
|
379
|
+
report = _step_doctor_check(tmp_home)
|
|
380
|
+
|
|
381
|
+
assert isinstance(report, DiagnosticReport)
|
|
382
|
+
|
|
383
|
+
def test_report_has_checks(self, tmp_home: Path) -> None:
|
|
384
|
+
"""Report contains at least one check."""
|
|
385
|
+
from skcapstone.onboard import _step_doctor_check
|
|
386
|
+
|
|
387
|
+
report = _step_doctor_check(tmp_home)
|
|
388
|
+
|
|
389
|
+
assert report.total_count > 0
|
|
390
|
+
|
|
391
|
+
def test_emits_pass_fail_markers(self, tmp_home: Path, capsys) -> None:
|
|
392
|
+
"""Output contains ✓ or ✗ check markers."""
|
|
393
|
+
import io
|
|
394
|
+
from click.testing import CliRunner
|
|
395
|
+
from skcapstone.onboard import _step_doctor_check
|
|
396
|
+
|
|
397
|
+
# Capture click.echo output via runner
|
|
398
|
+
report = _step_doctor_check(tmp_home)
|
|
399
|
+
# Just verify the report ran and has results
|
|
400
|
+
assert report.total_count > 0
|
|
401
|
+
assert report.passed_count >= 0
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
# ---------------------------------------------------------------------------
|
|
405
|
+
# _step_test_consciousness
|
|
406
|
+
# ---------------------------------------------------------------------------
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class TestStepTestConsciousness:
|
|
410
|
+
"""Tests for _step_test_consciousness()."""
|
|
411
|
+
|
|
412
|
+
def test_returns_false_when_user_declines(self, tmp_home: Path) -> None:
|
|
413
|
+
"""Returns False when user does not confirm the test."""
|
|
414
|
+
from skcapstone.onboard import _step_test_consciousness
|
|
415
|
+
|
|
416
|
+
with patch("click.confirm", return_value=False):
|
|
417
|
+
result = _step_test_consciousness(tmp_home)
|
|
418
|
+
|
|
419
|
+
assert result is False
|
|
420
|
+
|
|
421
|
+
def test_returns_true_when_loop_responds(self, tmp_home: Path) -> None:
|
|
422
|
+
"""Returns True when LLMBridge.generate returns a non-empty response."""
|
|
423
|
+
from skcapstone.onboard import _step_test_consciousness
|
|
424
|
+
|
|
425
|
+
mock_bridge = MagicMock()
|
|
426
|
+
mock_bridge.generate.return_value = "Hello, I am running fine."
|
|
427
|
+
mock_builder = MagicMock()
|
|
428
|
+
mock_builder.build.return_value = "system prompt"
|
|
429
|
+
mock_config = MagicMock()
|
|
430
|
+
mock_config.max_context_tokens = 8000
|
|
431
|
+
|
|
432
|
+
with patch("click.confirm", return_value=True), \
|
|
433
|
+
patch("skcapstone.consciousness_config.load_consciousness_config", return_value=mock_config), \
|
|
434
|
+
patch("skcapstone.consciousness_loop.LLMBridge", return_value=mock_bridge), \
|
|
435
|
+
patch("skcapstone.consciousness_loop.SystemPromptBuilder", return_value=mock_builder), \
|
|
436
|
+
patch("skcapstone.consciousness_loop._classify_message",
|
|
437
|
+
return_value=MagicMock(tags=[], estimated_tokens=10)):
|
|
438
|
+
result = _step_test_consciousness(tmp_home)
|
|
439
|
+
|
|
440
|
+
assert result is True
|
|
441
|
+
|
|
442
|
+
def test_returns_false_when_loop_returns_empty(self, tmp_home: Path) -> None:
|
|
443
|
+
"""Returns False when LLMBridge.generate returns an empty string."""
|
|
444
|
+
from skcapstone.onboard import _step_test_consciousness
|
|
445
|
+
|
|
446
|
+
mock_bridge = MagicMock()
|
|
447
|
+
mock_bridge.generate.return_value = ""
|
|
448
|
+
mock_builder = MagicMock()
|
|
449
|
+
mock_builder.build.return_value = "system prompt"
|
|
450
|
+
mock_config = MagicMock()
|
|
451
|
+
mock_config.max_context_tokens = 8000
|
|
452
|
+
|
|
453
|
+
with patch("click.confirm", return_value=True), \
|
|
454
|
+
patch("skcapstone.consciousness_config.load_consciousness_config", return_value=mock_config), \
|
|
455
|
+
patch("skcapstone.consciousness_loop.LLMBridge", return_value=mock_bridge), \
|
|
456
|
+
patch("skcapstone.consciousness_loop.SystemPromptBuilder", return_value=mock_builder), \
|
|
457
|
+
patch("skcapstone.consciousness_loop._classify_message",
|
|
458
|
+
return_value=MagicMock(tags=[], estimated_tokens=10)):
|
|
459
|
+
result = _step_test_consciousness(tmp_home)
|
|
460
|
+
|
|
461
|
+
assert result is False
|
|
462
|
+
|
|
463
|
+
def test_returns_false_on_exception(self, tmp_home: Path) -> None:
|
|
464
|
+
"""Returns False when consciousness config raises an exception."""
|
|
465
|
+
from skcapstone.onboard import _step_test_consciousness
|
|
466
|
+
|
|
467
|
+
with patch("click.confirm", return_value=True), \
|
|
468
|
+
patch("skcapstone.consciousness_config.load_consciousness_config",
|
|
469
|
+
side_effect=RuntimeError("no config")):
|
|
470
|
+
result = _step_test_consciousness(tmp_home)
|
|
471
|
+
|
|
472
|
+
assert result is False
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
# ---------------------------------------------------------------------------
|
|
476
|
+
# CLI integration: onboard --help
|
|
477
|
+
# ---------------------------------------------------------------------------
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
class TestOnboardCLI:
|
|
481
|
+
"""Test the onboard CLI command registration."""
|
|
482
|
+
|
|
483
|
+
def test_onboard_help(self) -> None:
|
|
484
|
+
"""skcapstone onboard --help exits 0 and mentions wizard."""
|
|
485
|
+
from skcapstone.cli import main
|
|
486
|
+
|
|
487
|
+
runner = CliRunner()
|
|
488
|
+
result = runner.invoke(main, ["onboard", "--help"])
|
|
489
|
+
|
|
490
|
+
assert result.exit_code == 0
|
|
491
|
+
assert "wizard" in result.output.lower() or "onboard" in result.output.lower()
|
|
492
|
+
|
|
493
|
+
def test_onboard_has_home_option(self) -> None:
|
|
494
|
+
"""onboard --help shows --home option."""
|
|
495
|
+
from skcapstone.cli import main
|
|
496
|
+
|
|
497
|
+
runner = CliRunner()
|
|
498
|
+
result = runner.invoke(main, ["onboard", "--help"])
|
|
499
|
+
|
|
500
|
+
assert "--home" in result.output
|