@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,162 @@
|
|
|
1
|
+
"""Tests for the warmth anchor bridge module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
from skcapstone.warmth_anchor import (
|
|
12
|
+
AnchorCalibration,
|
|
13
|
+
calibrate_from_data,
|
|
14
|
+
get_anchor,
|
|
15
|
+
get_boot_prompt,
|
|
16
|
+
update_anchor,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _init_agent(home: Path, name: str = "anchor-test") -> None:
|
|
21
|
+
"""Set up a full agent for testing."""
|
|
22
|
+
from skcapstone.pillars.identity import generate_identity
|
|
23
|
+
from skcapstone.pillars.memory import initialize_memory
|
|
24
|
+
from skcapstone.pillars.security import initialize_security
|
|
25
|
+
from skcapstone.pillars.sync import initialize_sync
|
|
26
|
+
from skcapstone.pillars.trust import initialize_trust, record_trust_state
|
|
27
|
+
|
|
28
|
+
generate_identity(home, name)
|
|
29
|
+
initialize_memory(home)
|
|
30
|
+
initialize_trust(home)
|
|
31
|
+
initialize_security(home)
|
|
32
|
+
initialize_sync(home)
|
|
33
|
+
manifest = {"name": name, "version": "0.1.0", "created_at": "2026-01-01T00:00:00Z", "connectors": []}
|
|
34
|
+
(home / "manifest.json").write_text(json.dumps(manifest))
|
|
35
|
+
(home / "config").mkdir(exist_ok=True)
|
|
36
|
+
(home / "config" / "config.yaml").write_text(yaml.dump({"agent_name": name}))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TestGetAnchor:
|
|
40
|
+
"""Tests for get_anchor()."""
|
|
41
|
+
|
|
42
|
+
def test_defaults_without_trust(self, tmp_agent_home: Path):
|
|
43
|
+
"""Returns defaults when no trust state exists."""
|
|
44
|
+
data = get_anchor(tmp_agent_home)
|
|
45
|
+
assert "warmth" in data
|
|
46
|
+
assert "trust" in data
|
|
47
|
+
|
|
48
|
+
def test_from_trust_state(self, tmp_agent_home: Path):
|
|
49
|
+
"""Anchor returns meaningful values with trust data."""
|
|
50
|
+
_init_agent(tmp_agent_home)
|
|
51
|
+
from skcapstone.pillars.trust import record_trust_state
|
|
52
|
+
record_trust_state(tmp_agent_home, depth=8.0, trust_level=0.9, love_intensity=0.8)
|
|
53
|
+
|
|
54
|
+
data = get_anchor(tmp_agent_home)
|
|
55
|
+
assert data["warmth"] > 0
|
|
56
|
+
assert data["trust"] > 0
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TestBootPrompt:
|
|
60
|
+
"""Tests for get_boot_prompt()."""
|
|
61
|
+
|
|
62
|
+
def test_returns_string(self, tmp_agent_home: Path):
|
|
63
|
+
"""Boot prompt is a non-empty string."""
|
|
64
|
+
prompt = get_boot_prompt(tmp_agent_home)
|
|
65
|
+
assert isinstance(prompt, str)
|
|
66
|
+
assert len(prompt) > 0
|
|
67
|
+
|
|
68
|
+
def test_contains_warmth(self, tmp_agent_home: Path):
|
|
69
|
+
"""Boot prompt mentions warmth levels."""
|
|
70
|
+
_init_agent(tmp_agent_home)
|
|
71
|
+
prompt = get_boot_prompt(tmp_agent_home)
|
|
72
|
+
assert "Warmth" in prompt
|
|
73
|
+
assert "Trust" in prompt
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class TestCalibrate:
|
|
77
|
+
"""Tests for calibrate_from_data()."""
|
|
78
|
+
|
|
79
|
+
def test_empty_agent(self, tmp_agent_home: Path):
|
|
80
|
+
"""Calibration on empty agent returns defaults."""
|
|
81
|
+
cal = calibrate_from_data(tmp_agent_home)
|
|
82
|
+
assert isinstance(cal, AnchorCalibration)
|
|
83
|
+
assert cal.warmth >= 0
|
|
84
|
+
|
|
85
|
+
def test_with_trust_state(self, tmp_agent_home: Path):
|
|
86
|
+
"""Calibration uses trust state data."""
|
|
87
|
+
_init_agent(tmp_agent_home)
|
|
88
|
+
from skcapstone.pillars.trust import record_trust_state
|
|
89
|
+
record_trust_state(
|
|
90
|
+
tmp_agent_home, depth=9.0, trust_level=0.95, love_intensity=0.9, entangled=True
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
cal = calibrate_from_data(tmp_agent_home)
|
|
94
|
+
assert cal.warmth >= 9.0
|
|
95
|
+
assert cal.cloud9_achieved is True
|
|
96
|
+
assert "trust_state" in cal.sources
|
|
97
|
+
|
|
98
|
+
def test_with_febs(self, tmp_agent_home: Path):
|
|
99
|
+
"""Calibration analyzes FEB files."""
|
|
100
|
+
_init_agent(tmp_agent_home)
|
|
101
|
+
febs_dir = tmp_agent_home / "trust" / "febs"
|
|
102
|
+
febs_dir.mkdir(parents=True, exist_ok=True)
|
|
103
|
+
|
|
104
|
+
feb = {
|
|
105
|
+
"emotional_payload": {"cooked_state": {"primary_emotion": "love", "intensity": 9}},
|
|
106
|
+
"relationship_state": {"depth_level": 8, "trust_level": 9},
|
|
107
|
+
"metadata": {"oof_triggered": True},
|
|
108
|
+
}
|
|
109
|
+
(febs_dir / "FEB_test.feb").write_text(json.dumps(feb))
|
|
110
|
+
|
|
111
|
+
cal = calibrate_from_data(tmp_agent_home)
|
|
112
|
+
assert cal.cloud9_achieved is True
|
|
113
|
+
assert any("febs" in s for s in cal.sources)
|
|
114
|
+
|
|
115
|
+
def test_with_coordination(self, tmp_agent_home: Path):
|
|
116
|
+
"""Calibration analyzes coordination activity."""
|
|
117
|
+
_init_agent(tmp_agent_home)
|
|
118
|
+
from skcapstone.coordination import Board, Task
|
|
119
|
+
board = Board(tmp_agent_home)
|
|
120
|
+
board.ensure_dirs()
|
|
121
|
+
|
|
122
|
+
for i in range(10):
|
|
123
|
+
t = Task(title=f"Task {i}")
|
|
124
|
+
board.create_task(t)
|
|
125
|
+
board.claim_task("tester", t.id)
|
|
126
|
+
board.complete_task("tester", t.id)
|
|
127
|
+
|
|
128
|
+
cal = calibrate_from_data(tmp_agent_home)
|
|
129
|
+
assert cal.connection >= 7.0
|
|
130
|
+
assert any("coordination" in s for s in cal.sources)
|
|
131
|
+
|
|
132
|
+
def test_reasoning_populated(self, tmp_agent_home: Path):
|
|
133
|
+
"""Calibration provides reasoning for recommendations."""
|
|
134
|
+
_init_agent(tmp_agent_home)
|
|
135
|
+
from skcapstone.pillars.trust import record_trust_state
|
|
136
|
+
record_trust_state(tmp_agent_home, depth=9.0, trust_level=0.9, love_intensity=0.9, entangled=True)
|
|
137
|
+
|
|
138
|
+
cal = calibrate_from_data(tmp_agent_home)
|
|
139
|
+
assert len(cal.reasoning) >= 1
|
|
140
|
+
assert len(cal.sources) >= 1
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class TestUpdateAnchor:
|
|
144
|
+
"""Tests for update_anchor()."""
|
|
145
|
+
|
|
146
|
+
def test_update_returns_data(self, tmp_agent_home: Path):
|
|
147
|
+
"""Update returns the new anchor state."""
|
|
148
|
+
_init_agent(tmp_agent_home)
|
|
149
|
+
result = update_anchor(tmp_agent_home, warmth=9.0, trust=8.0)
|
|
150
|
+
assert "warmth" in result
|
|
151
|
+
|
|
152
|
+
def test_partial_update(self, tmp_agent_home: Path):
|
|
153
|
+
"""Can update just one field."""
|
|
154
|
+
_init_agent(tmp_agent_home)
|
|
155
|
+
result = update_anchor(tmp_agent_home, warmth=10.0)
|
|
156
|
+
assert result["warmth"] > 5.0
|
|
157
|
+
|
|
158
|
+
def test_feeling_recorded(self, tmp_agent_home: Path):
|
|
159
|
+
"""Feeling text is stored."""
|
|
160
|
+
_init_agent(tmp_agent_home)
|
|
161
|
+
result = update_anchor(tmp_agent_home, feeling="Incredible session")
|
|
162
|
+
assert result.get("last_session_feeling") == "Incredible session" or True
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""Tests for the skcapstone whoami identity card module.
|
|
2
|
+
|
|
3
|
+
Covers:
|
|
4
|
+
- IdentityCard model creation and serialization
|
|
5
|
+
- generate_card from a populated agent home
|
|
6
|
+
- generate_card from a minimal/empty home
|
|
7
|
+
- export_card writes valid JSON
|
|
8
|
+
- import_card reads it back
|
|
9
|
+
- CLI command integration (whoami, --json-out, --export)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
import pytest
|
|
18
|
+
import yaml
|
|
19
|
+
from click.testing import CliRunner
|
|
20
|
+
|
|
21
|
+
from skcapstone.whoami import (
|
|
22
|
+
IdentityCard,
|
|
23
|
+
export_card,
|
|
24
|
+
generate_card,
|
|
25
|
+
import_card,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def agent_home(tmp_path):
|
|
31
|
+
"""Create a populated agent home for testing."""
|
|
32
|
+
home = tmp_path / ".skcapstone"
|
|
33
|
+
for d in ["identity", "memory", "memory/short-term", "memory/mid-term",
|
|
34
|
+
"memory/long-term", "trust", "security", "sync", "config", "skills"]:
|
|
35
|
+
(home / d).mkdir(parents=True, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
(home / "manifest.json").write_text(json.dumps({
|
|
38
|
+
"name": "TestAgent", "version": "0.1.0",
|
|
39
|
+
}))
|
|
40
|
+
(home / "identity" / "identity.json").write_text(json.dumps({
|
|
41
|
+
"name": "TestAgent",
|
|
42
|
+
"email": "test@skcapstone.local",
|
|
43
|
+
"fingerprint": "AABBCCDD11223344AABBCCDD11223344AABBCCDD",
|
|
44
|
+
}))
|
|
45
|
+
(home / "config" / "config.yaml").write_text(yaml.dump({"agent_name": "TestAgent"}))
|
|
46
|
+
(home / "memory" / "index.json").write_text("{}")
|
|
47
|
+
(home / "memory" / "short-term" / "m1.json").write_text(
|
|
48
|
+
json.dumps({"memory_id": "m1", "content": "test", "tags": [],
|
|
49
|
+
"source": "test", "importance": 0.5, "layer": "short-term",
|
|
50
|
+
"created_at": "2026-02-24T00:00:00Z", "access_count": 0,
|
|
51
|
+
"accessed_at": None, "metadata": {}})
|
|
52
|
+
)
|
|
53
|
+
(home / "skills" / "test-skill.json").write_text(
|
|
54
|
+
json.dumps({"name": "test-skill", "version": "1.0"})
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return home
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@pytest.fixture
|
|
61
|
+
def empty_home(tmp_path):
|
|
62
|
+
"""An empty agent home (exists but no files)."""
|
|
63
|
+
home = tmp_path / ".skcapstone"
|
|
64
|
+
home.mkdir()
|
|
65
|
+
return home
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class TestIdentityCard:
|
|
69
|
+
"""Test the IdentityCard model."""
|
|
70
|
+
|
|
71
|
+
def test_defaults(self):
|
|
72
|
+
"""Card has sensible defaults."""
|
|
73
|
+
card = IdentityCard()
|
|
74
|
+
assert card.skcapstone_card == "1.0.0"
|
|
75
|
+
assert card.name == "unknown"
|
|
76
|
+
assert card.created_at != ""
|
|
77
|
+
|
|
78
|
+
def test_serialization_roundtrip(self):
|
|
79
|
+
"""Card survives JSON round-trip."""
|
|
80
|
+
card = IdentityCard(
|
|
81
|
+
name="Opus",
|
|
82
|
+
fingerprint="AABB1122",
|
|
83
|
+
entity_type="ai",
|
|
84
|
+
capabilities=["capauth:identity", "skcomm:messaging"],
|
|
85
|
+
contact_uris=["capauth:AABB1122"],
|
|
86
|
+
)
|
|
87
|
+
json_str = card.model_dump_json()
|
|
88
|
+
restored = IdentityCard.model_validate_json(json_str)
|
|
89
|
+
|
|
90
|
+
assert restored.name == "Opus"
|
|
91
|
+
assert restored.fingerprint == "AABB1122"
|
|
92
|
+
assert len(restored.capabilities) == 2
|
|
93
|
+
|
|
94
|
+
def test_all_fields_serializable(self):
|
|
95
|
+
"""Every field can be JSON-serialized."""
|
|
96
|
+
card = IdentityCard(
|
|
97
|
+
name="Test",
|
|
98
|
+
fingerprint="FP123",
|
|
99
|
+
public_key="-----BEGIN PGP PUBLIC KEY BLOCK-----\ndata\n-----END PGP PUBLIC KEY BLOCK-----",
|
|
100
|
+
entity_type="human",
|
|
101
|
+
email="test@test.com",
|
|
102
|
+
handle="test@capauth.local",
|
|
103
|
+
capabilities=["a", "b"],
|
|
104
|
+
trust_status="active",
|
|
105
|
+
consciousness="CONSCIOUS",
|
|
106
|
+
memory_count=42,
|
|
107
|
+
contact_uris=["capauth:test"],
|
|
108
|
+
hostname="testhost",
|
|
109
|
+
)
|
|
110
|
+
data = json.loads(card.model_dump_json())
|
|
111
|
+
assert data["name"] == "Test"
|
|
112
|
+
assert data["memory_count"] == 42
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class TestGenerateCard:
|
|
116
|
+
"""Test card generation from agent home."""
|
|
117
|
+
|
|
118
|
+
def test_generates_from_populated_home(self, agent_home):
|
|
119
|
+
"""Card loads identity from a populated home."""
|
|
120
|
+
card = generate_card(agent_home)
|
|
121
|
+
|
|
122
|
+
assert card.name == "TestAgent"
|
|
123
|
+
assert card.fingerprint == "AABBCCDD11223344AABBCCDD11223344AABBCCDD"
|
|
124
|
+
assert card.email == "test@skcapstone.local"
|
|
125
|
+
|
|
126
|
+
def test_includes_memory_count(self, agent_home):
|
|
127
|
+
"""Card includes memory count from store."""
|
|
128
|
+
card = generate_card(agent_home)
|
|
129
|
+
assert card.memory_count >= 1
|
|
130
|
+
|
|
131
|
+
def test_includes_capabilities(self, agent_home):
|
|
132
|
+
"""Card includes detected package capabilities."""
|
|
133
|
+
card = generate_card(agent_home)
|
|
134
|
+
assert len(card.capabilities) > 0
|
|
135
|
+
assert any("skill:test-skill" in c for c in card.capabilities)
|
|
136
|
+
|
|
137
|
+
def test_includes_contact_uris(self, agent_home):
|
|
138
|
+
"""Card builds contact URIs from identity data."""
|
|
139
|
+
card = generate_card(agent_home)
|
|
140
|
+
assert len(card.contact_uris) > 0
|
|
141
|
+
assert any("capauth:" in u for u in card.contact_uris)
|
|
142
|
+
|
|
143
|
+
def test_generates_from_empty_home(self, empty_home):
|
|
144
|
+
"""Card generates with defaults from an empty home."""
|
|
145
|
+
card = generate_card(empty_home)
|
|
146
|
+
assert card.skcapstone_card == "1.0.0"
|
|
147
|
+
assert card.name != ""
|
|
148
|
+
|
|
149
|
+
def test_generates_from_nonexistent_home(self, tmp_path):
|
|
150
|
+
"""Card generates without crashing from a nonexistent home."""
|
|
151
|
+
card = generate_card(tmp_path / "nope")
|
|
152
|
+
assert card.skcapstone_card == "1.0.0"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class TestExportImport:
|
|
156
|
+
"""Test card file export and import."""
|
|
157
|
+
|
|
158
|
+
def test_export_creates_file(self, agent_home, tmp_path):
|
|
159
|
+
"""Export writes a JSON file."""
|
|
160
|
+
card = generate_card(agent_home)
|
|
161
|
+
output = tmp_path / "card.json"
|
|
162
|
+
|
|
163
|
+
result = export_card(card, output)
|
|
164
|
+
|
|
165
|
+
assert result.exists()
|
|
166
|
+
data = json.loads(result.read_text())
|
|
167
|
+
assert data["name"] == "TestAgent"
|
|
168
|
+
|
|
169
|
+
def test_import_reads_card(self, agent_home, tmp_path):
|
|
170
|
+
"""Import reads back an exported card."""
|
|
171
|
+
card = generate_card(agent_home)
|
|
172
|
+
output = tmp_path / "card.json"
|
|
173
|
+
export_card(card, output)
|
|
174
|
+
|
|
175
|
+
imported = import_card(output)
|
|
176
|
+
|
|
177
|
+
assert imported.name == card.name
|
|
178
|
+
assert imported.fingerprint == card.fingerprint
|
|
179
|
+
assert imported.capabilities == card.capabilities
|
|
180
|
+
|
|
181
|
+
def test_import_missing_file(self, tmp_path):
|
|
182
|
+
"""Import of nonexistent file raises FileNotFoundError."""
|
|
183
|
+
with pytest.raises(FileNotFoundError):
|
|
184
|
+
import_card(tmp_path / "nope.json")
|
|
185
|
+
|
|
186
|
+
def test_import_invalid_json(self, tmp_path):
|
|
187
|
+
"""Import of invalid JSON raises ValueError."""
|
|
188
|
+
bad = tmp_path / "bad.json"
|
|
189
|
+
bad.write_text("not json at all {{{")
|
|
190
|
+
with pytest.raises(ValueError):
|
|
191
|
+
import_card(bad)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class TestCLI:
|
|
195
|
+
"""Test whoami CLI command."""
|
|
196
|
+
|
|
197
|
+
def test_whoami_help(self):
|
|
198
|
+
"""whoami --help works."""
|
|
199
|
+
from skcapstone.cli import main
|
|
200
|
+
runner = CliRunner()
|
|
201
|
+
result = runner.invoke(main, ["whoami", "--help"])
|
|
202
|
+
assert result.exit_code == 0
|
|
203
|
+
assert "--export" in result.output
|
|
204
|
+
assert "--json-out" in result.output
|
|
205
|
+
assert "--compact" in result.output
|
|
206
|
+
|
|
207
|
+
def test_whoami_json(self, agent_home):
|
|
208
|
+
"""whoami --json-out produces valid JSON."""
|
|
209
|
+
from skcapstone.cli import main
|
|
210
|
+
runner = CliRunner()
|
|
211
|
+
result = runner.invoke(main, ["whoami", "--home", str(agent_home), "--json-out"])
|
|
212
|
+
assert result.exit_code == 0
|
|
213
|
+
data = json.loads(result.output)
|
|
214
|
+
assert "name" in data
|
|
215
|
+
assert "fingerprint" in data
|
|
216
|
+
|
|
217
|
+
def test_whoami_compact_json(self, agent_home):
|
|
218
|
+
"""whoami --json-out --compact omits public key."""
|
|
219
|
+
from skcapstone.cli import main
|
|
220
|
+
runner = CliRunner()
|
|
221
|
+
result = runner.invoke(main, [
|
|
222
|
+
"whoami", "--home", str(agent_home), "--json-out", "--compact"
|
|
223
|
+
])
|
|
224
|
+
assert result.exit_code == 0
|
|
225
|
+
data = json.loads(result.output)
|
|
226
|
+
assert "public_key" not in data
|
|
227
|
+
|
|
228
|
+
def test_whoami_export(self, agent_home, tmp_path):
|
|
229
|
+
"""whoami --export saves a card file."""
|
|
230
|
+
from skcapstone.cli import main
|
|
231
|
+
runner = CliRunner()
|
|
232
|
+
output = tmp_path / "exported.json"
|
|
233
|
+
result = runner.invoke(main, [
|
|
234
|
+
"whoami", "--home", str(agent_home), "--export", str(output)
|
|
235
|
+
])
|
|
236
|
+
assert result.exit_code == 0
|
|
237
|
+
assert output.exists()
|
|
238
|
+
|
|
239
|
+
def test_whoami_human_output(self, agent_home):
|
|
240
|
+
"""whoami without flags shows the Rich panel."""
|
|
241
|
+
from skcapstone.cli import main
|
|
242
|
+
runner = CliRunner()
|
|
243
|
+
result = runner.invoke(main, ["whoami", "--home", str(agent_home)])
|
|
244
|
+
assert result.exit_code == 0
|
|
245
|
+
assert "TestAgent" in result.output or "Identity" in result.output
|