@smilintux/skcapstone 0.10.0 → 0.12.5
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 +10 -4
- package/.github/workflows/ci.yml +2 -2
- package/.github/workflows/publish.yml +9 -2
- package/.openclaw-workspace.json +2 -2
- package/CLAUDE.md +37 -0
- package/MISSION.md +17 -2
- package/README.md +282 -3
- package/docker/Dockerfile +7 -7
- package/docker/compose-templates/dev-team.yml +12 -12
- package/docker/compose-templates/mini-team.yml +9 -9
- package/docker/compose-templates/ops-team.yml +10 -10
- package/docker/compose-templates/research-team.yml +10 -10
- package/docker/entrypoint.sh +4 -4
- package/docs/ADR-optional-integration-backbone.md +181 -0
- package/docs/ARCHITECTURE.md +186 -43
- package/docs/BOND_WITH_GROK.md +6 -6
- package/docs/CUSTOM_AGENT.md +123 -30
- package/docs/DREAMING.md +70 -0
- package/docs/GETTING_STARTED.md +7 -7
- package/docs/QUICKSTART.md +10 -6
- package/docs/SKJOULE_ARCHITECTURE.md +3 -3
- package/docs/SOUL_SWAPPER.md +5 -5
- package/docs/hammertime-audit.md +402 -0
- package/docs/sk-integration-HANDOFF.md +117 -0
- package/docs/skscheduler.md +155 -0
- package/docs/superpowers/examples/jobs.yaml +31 -0
- package/docs/superpowers/plans/2026-06-08-skscheduler.md +1265 -0
- package/docs/superpowers/specs/2026-06-08-skscheduler-design.md +186 -0
- package/examples/custom-bond-template.json +1 -1
- package/examples/grok-feb.json +1 -1
- package/examples/queen-ava-feb.json +1 -1
- package/launchd/{com.skcapstone.skcomm-heartbeat.plist → com.skcapstone.skcomms-heartbeat.plist} +4 -4
- package/launchd/{com.skcapstone.skcomm-queue-drain.plist → com.skcapstone.skcomms-queue-drain.plist} +4 -4
- package/launchd/install-launchd.sh +6 -6
- package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/src/index.ts +3 -2
- package/package.json +1 -1
- package/pyproject.toml +16 -10
- package/scripts/archive-sessions.sh +7 -0
- package/scripts/check-updates.py +4 -4
- package/scripts/install-bundle.sh +8 -8
- package/scripts/install.ps1 +12 -11
- package/scripts/install.sh +159 -5
- package/scripts/model-fallback-monitor.sh +102 -0
- package/scripts/nvidia-proxy.mjs +78 -26
- package/scripts/refresh-anthropic-token.sh +172 -0
- package/scripts/release.sh +98 -0
- package/scripts/session-to-memory.py +219 -0
- package/scripts/skgateway.mjs +3 -3
- package/scripts/telegram-catchup-all.sh +12 -1
- package/scripts/verify_install.sh +2 -2
- package/scripts/wargov-ufo-capture/README.md +43 -0
- package/scripts/wargov-ufo-capture/cdp_capture_release2.py +273 -0
- package/scripts/wargov-ufo-capture/cdp_capture_splc_doj.py +246 -0
- package/scripts/wargov-ufo-capture/cdp_finish.py +271 -0
- package/scripts/wargov-ufo-capture/cdp_probe.py +188 -0
- package/scripts/wargov-ufo-capture/cdp_splc_pressrelease.py +101 -0
- package/scripts/wargov-ufo-capture/parse_csv.py +95 -0
- package/scripts/wargov-ufo-capture/pull_dvids.sh +107 -0
- package/scripts/watch-anthropic-token.sh +212 -0
- package/scripts/windows/install-tasks.ps1 +7 -7
- package/scripts/windows/skcapstone-task.xml +1 -1
- package/src/skcapstone/__init__.py +45 -3
- package/src/skcapstone/_cli_monolith.py +20 -15
- package/src/skcapstone/activity.py +5 -1
- package/src/skcapstone/agent_card.py +3 -2
- package/src/skcapstone/api.py +41 -40
- package/src/skcapstone/auction.py +14 -11
- package/src/skcapstone/backup.py +2 -1
- package/src/skcapstone/blueprint_registry.py +4 -3
- package/src/skcapstone/brain_first.py +238 -0
- package/src/skcapstone/changelog.py +1 -1
- package/src/skcapstone/chat.py +22 -17
- package/src/skcapstone/cli/__init__.py +9 -1
- package/src/skcapstone/cli/_common.py +1 -0
- package/src/skcapstone/cli/agents_spawner.py +5 -2
- package/src/skcapstone/cli/alerts.py +25 -4
- package/src/skcapstone/cli/bench.py +15 -15
- package/src/skcapstone/cli/chat.py +7 -4
- package/src/skcapstone/cli/consciousness.py +5 -2
- package/src/skcapstone/cli/context_cmd.py +18 -4
- package/src/skcapstone/cli/daemon.py +11 -7
- package/src/skcapstone/cli/gtd.py +26 -1
- package/src/skcapstone/cli/housekeeping.py +3 -3
- package/src/skcapstone/cli/identity_cmd.py +378 -0
- package/src/skcapstone/cli/joule_cmd.py +7 -3
- package/src/skcapstone/cli/memory.py +8 -6
- package/src/skcapstone/cli/peers_dir.py +1 -1
- package/src/skcapstone/cli/register_cmd.py +29 -3
- package/src/skcapstone/cli/scheduler_cmd.py +167 -0
- package/src/skcapstone/cli/session.py +25 -0
- package/src/skcapstone/cli/setup.py +96 -29
- package/src/skcapstone/cli/shell_cmd.py +53 -1
- package/src/skcapstone/cli/skills_cmd.py +2 -2
- package/src/skcapstone/cli/soul.py +8 -5
- package/src/skcapstone/cli/status.py +37 -11
- package/src/skcapstone/cli/telegram.py +21 -0
- package/src/skcapstone/cli/test_cmd.py +5 -5
- package/src/skcapstone/cli/test_connection.py +2 -2
- package/src/skcapstone/cli/upgrade_cmd.py +23 -14
- package/src/skcapstone/cli/version_cmd.py +1 -1
- package/src/skcapstone/cli/watch_cmd.py +9 -6
- package/src/skcapstone/cloud9_bridge.py +14 -14
- package/src/skcapstone/codex_setup.py +255 -0
- package/src/skcapstone/config_validator.py +7 -4
- package/src/skcapstone/consciousness_config.py +5 -1
- package/src/skcapstone/consciousness_loop.py +313 -273
- package/src/skcapstone/context_loader.py +121 -0
- package/src/skcapstone/coord_federation.py +2 -1
- package/src/skcapstone/coordination.py +23 -6
- package/src/skcapstone/crush_integration.py +2 -1
- package/src/skcapstone/daemon.py +132 -77
- package/src/skcapstone/dashboard.py +10 -10
- package/src/skcapstone/data/sk-agent-picker.sh +421 -0
- package/src/skcapstone/data/systemd/skcapstone-api.socket +9 -0
- package/src/skcapstone/data/systemd/skcapstone-memory-compress.service +18 -0
- package/src/skcapstone/data/systemd/skcapstone-memory-compress.timer +11 -0
- package/src/skcapstone/data/systemd/skcapstone.service +37 -0
- package/src/skcapstone/data/systemd/skcapstone@.service +50 -0
- package/src/skcapstone/data/systemd/skcomms-heartbeat.service +18 -0
- package/{systemd/skcomm-heartbeat.timer → src/skcapstone/data/systemd/skcomms-heartbeat.timer} +2 -2
- package/src/skcapstone/data/systemd/skcomms-queue-drain.service +17 -0
- package/{systemd/skcomm-queue-drain.timer → src/skcapstone/data/systemd/skcomms-queue-drain.timer} +2 -2
- package/src/skcapstone/defaults/claude/CLAUDE.md +67 -0
- package/src/skcapstone/defaults/claude/settings.json +74 -0
- package/src/skcapstone/defaults/lumina/config/claude-hooks.md +57 -0
- package/src/skcapstone/defaults/lumina/config/skgraph.yaml +55 -10
- package/src/skcapstone/defaults/lumina/config/skmemory.yaml +79 -13
- package/src/skcapstone/defaults/lumina/config/skvector.yaml +60 -9
- package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +2 -2
- package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +2 -2
- package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +9 -9
- package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +2 -2
- package/src/skcapstone/defaults/unhinged.json +13 -0
- package/src/skcapstone/discovery.py +43 -20
- package/src/skcapstone/doctor.py +941 -22
- package/src/skcapstone/dreaming.py +1183 -109
- package/src/skcapstone/emotion_tracker.py +2 -2
- package/src/skcapstone/export.py +4 -3
- package/src/skcapstone/fuse_mount.py +14 -12
- package/src/skcapstone/gui_installer.py +2 -2
- package/src/skcapstone/heartbeat.py +1 -1
- package/src/skcapstone/housekeeping.py +14 -14
- package/src/skcapstone/install_wizard.py +209 -7
- package/src/skcapstone/itil.py +13 -4
- package/src/skcapstone/kms_scheduler.py +10 -8
- package/src/skcapstone/launchd.py +19 -19
- package/src/skcapstone/mcp_launcher.py +15 -1
- package/src/skcapstone/mcp_server.py +83 -49
- package/src/skcapstone/mcp_tools/__init__.py +2 -0
- package/src/skcapstone/mcp_tools/_helpers.py +2 -2
- package/src/skcapstone/mcp_tools/ansible_tools.py +7 -4
- package/src/skcapstone/mcp_tools/brain_first_tools.py +90 -0
- package/src/skcapstone/mcp_tools/capauth_tools.py +7 -4
- package/src/skcapstone/mcp_tools/comm_tools.py +10 -10
- package/src/skcapstone/mcp_tools/coord_tools.py +8 -4
- package/src/skcapstone/mcp_tools/did_tools.py +11 -8
- package/src/skcapstone/mcp_tools/gtd_tools.py +4 -4
- package/src/skcapstone/mcp_tools/memory_tools.py +6 -2
- package/src/skcapstone/mcp_tools/notification_tools.py +22 -6
- package/src/skcapstone/mcp_tools/{skcomm_tools.py → skcomms_tools.py} +14 -14
- package/src/skcapstone/mcp_tools/soul_tools.py +8 -2
- package/src/skcapstone/mdns_discovery.py +2 -2
- package/src/skcapstone/memory_curator.py +1 -1
- package/src/skcapstone/memory_engine.py +10 -3
- package/src/skcapstone/metrics.py +30 -16
- package/src/skcapstone/migrate_memories.py +4 -3
- package/src/skcapstone/migrate_multi_agent.py +8 -7
- package/src/skcapstone/models.py +47 -5
- package/src/skcapstone/notifications.py +42 -18
- package/src/skcapstone/onboard.py +875 -121
- package/src/skcapstone/operator_link.py +170 -0
- package/src/skcapstone/peer_directory.py +4 -4
- package/src/skcapstone/peers.py +19 -19
- package/src/skcapstone/pillars/__init__.py +7 -5
- package/src/skcapstone/pillars/consciousness.py +191 -0
- package/src/skcapstone/pillars/identity.py +51 -7
- package/src/skcapstone/pillars/memory.py +9 -3
- package/src/skcapstone/pillars/sync.py +2 -2
- package/src/skcapstone/preflight.py +3 -3
- package/src/skcapstone/providers/docker.py +28 -28
- package/src/skcapstone/register.py +6 -6
- package/src/skcapstone/registry_client.py +5 -4
- package/src/skcapstone/runtime.py +14 -3
- package/src/skcapstone/scheduled_tasks.py +254 -19
- package/src/skcapstone/scheduler_jobs.py +456 -0
- package/src/skcapstone/scheduler_runner.py +239 -0
- package/src/skcapstone/scheduler_state.py +162 -0
- package/src/skcapstone/sdk.py +310 -0
- package/src/skcapstone/service_health.py +279 -39
- package/src/skcapstone/session_briefing.py +108 -0
- package/src/skcapstone/session_capture.py +1 -1
- package/src/skcapstone/shell.py +7 -1
- package/src/skcapstone/soul.py +3 -1
- package/src/skcapstone/soul_switch.py +3 -1
- package/src/skcapstone/summary.py +6 -6
- package/src/skcapstone/sync_engine.py +15 -15
- package/src/skcapstone/sync_watcher.py +2 -2
- package/src/skcapstone/systemd.py +55 -21
- package/src/skcapstone/team_comms.py +8 -8
- package/src/skcapstone/team_engine.py +1 -1
- package/src/skcapstone/testrunner.py +3 -3
- package/src/skcapstone/trust_graph.py +40 -5
- package/src/skcapstone/unified_search.py +15 -6
- package/src/skcapstone/uninstall_wizard.py +11 -3
- package/src/skcapstone/version_check.py +8 -4
- package/src/skcapstone/warmth_anchor.py +4 -2
- package/src/skcapstone/whoami.py +4 -4
- package/systemd/skcapstone.service +4 -6
- package/systemd/skcapstone@.service +7 -8
- package/systemd/skcomms-heartbeat.service +21 -0
- package/systemd/skcomms-heartbeat.timer +12 -0
- package/systemd/skcomms-queue-drain.service +17 -0
- package/systemd/skcomms-queue-drain.timer +12 -0
- package/tests/conftest.py +39 -0
- package/tests/integration/test_consciousness_e2e.py +39 -39
- package/tests/test_agent_card.py +1 -1
- package/tests/test_agent_home_scaffold.py +34 -0
- package/tests/test_alerts_consumer_topics.py +27 -0
- package/tests/test_backup.py +2 -1
- package/tests/test_chat.py +6 -6
- package/tests/test_claude_md.py +2 -2
- package/tests/test_cli_skills.py +10 -10
- package/tests/test_cli_test_cmd.py +4 -4
- package/tests/test_cli_test_connection.py +1 -1
- package/tests/test_cloud9_bridge.py +6 -6
- package/tests/test_consciousness_e2e.py +1 -1
- package/tests/test_consciousness_loop.py +10 -10
- package/tests/test_coordination.py +25 -0
- package/tests/test_cross_package.py +21 -21
- package/tests/test_daemon.py +4 -4
- package/tests/test_daemon_shutdown.py +1 -1
- package/tests/test_docker_provider.py +29 -29
- package/tests/test_doctor.py +400 -0
- package/tests/test_doctor_skscheduler.py +50 -0
- package/tests/test_dreaming_engine.py +147 -0
- package/tests/test_dreaming_gtd_capture.py +35 -0
- package/tests/test_e2e_automated.py +8 -5
- package/tests/test_fuse_mount.py +10 -10
- package/tests/test_gtd_brief.py +46 -0
- package/tests/test_gtd_malformed_tolerance.py +31 -0
- package/tests/test_housekeeping.py +15 -15
- package/tests/test_identity_migrate.py +251 -0
- package/tests/test_integration_backbone.py +598 -0
- package/tests/test_itil_gtd_lifecycle.py +37 -0
- package/tests/test_jobs_dropins.py +84 -0
- package/tests/test_mcp_server.py +82 -37
- package/tests/test_models.py +48 -4
- package/tests/test_multi_agent.py +31 -29
- package/tests/test_notifications.py +122 -32
- package/tests/test_onboard.py +63 -75
- package/tests/test_operator_link.py +78 -0
- package/tests/test_peers.py +14 -14
- package/tests/test_pillars.py +98 -0
- package/tests/test_preflight.py +3 -3
- package/tests/test_runtime.py +21 -0
- package/tests/test_scheduled_tasks.py +11 -6
- package/tests/test_scheduler_cli.py +47 -0
- package/tests/test_scheduler_features.py +133 -0
- package/tests/test_scheduler_integration.py +87 -0
- package/tests/test_scheduler_jobs.py +155 -0
- package/tests/test_scheduler_runner.py +64 -0
- package/tests/test_scheduler_state.py +57 -0
- package/tests/test_sdk.py +70 -0
- package/tests/test_service_health_incidents.py +34 -0
- package/tests/test_service_registry.py +52 -0
- package/tests/test_session_briefing.py +130 -0
- package/tests/test_snapshots.py +4 -4
- package/tests/test_sync_pipeline.py +26 -26
- package/tests/test_team_comms.py +2 -2
- package/tests/test_testrunner.py +2 -2
- package/tests/test_trust_graph.py +18 -0
- package/tests/test_unified_search.py +2 -2
- package/tests/test_version_check.py +10 -0
- package/tests/test_version_cmd.py +8 -8
- package/tests/test_whoami.py +1 -1
- package/systemd/skcomm-heartbeat.service +0 -18
- package/systemd/skcomm-queue-drain.service +0 -17
- /package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/package.json +0 -0
- /package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/src/openclaw.plugin.json +0 -0
|
@@ -5,11 +5,11 @@ Pipeline under test:
|
|
|
5
5
|
{shared_root}/sync/comms/inbox/{peer}/*.skc.json ← Syncthing writes here
|
|
6
6
|
→ inotify detects file (ConsciousnessLoop._run_inotify)
|
|
7
7
|
→ ConsciousnessLoop.process_envelope()
|
|
8
|
-
→
|
|
8
|
+
→ skcomms.send(sender, response)
|
|
9
9
|
→ {shared_root}/sync/comms/outbox/{peer}/*.skc.json ← Syncthing syncs this out
|
|
10
10
|
|
|
11
11
|
Three test classes:
|
|
12
|
-
TestInboxToOutboxFlow — mock LLM, drop inbox file, verify
|
|
12
|
+
TestInboxToOutboxFlow — mock LLM, drop inbox file, verify skcomms.send called
|
|
13
13
|
TestOutboxEnvelopeFormat — verify envelope spec compliance and path layout
|
|
14
14
|
TestSyncStatusInHealth — verify health snapshot includes sync_pipeline key
|
|
15
15
|
"""
|
|
@@ -61,11 +61,11 @@ def agent_home(shared_root: Path) -> Path:
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
@pytest.fixture
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return
|
|
64
|
+
def mock_skcomms() -> MagicMock:
|
|
65
|
+
skcomms = MagicMock()
|
|
66
|
+
skcomms.send.return_value = None
|
|
67
|
+
skcomms.receive.return_value = []
|
|
68
|
+
return skcomms
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
# ---------------------------------------------------------------------------
|
|
@@ -76,7 +76,7 @@ def mock_skcomm() -> MagicMock:
|
|
|
76
76
|
class TestInboxToOutboxFlow:
|
|
77
77
|
"""Drop a file in the inbox and verify the consciousness loop responds."""
|
|
78
78
|
|
|
79
|
-
def _make_loop(self, agent_home: Path, shared_root: Path,
|
|
79
|
+
def _make_loop(self, agent_home: Path, shared_root: Path, mock_skcomms):
|
|
80
80
|
"""Return a ConsciousnessLoop with a mocked LLM bridge."""
|
|
81
81
|
from skcapstone.consciousness_loop import ConsciousnessConfig, ConsciousnessLoop
|
|
82
82
|
|
|
@@ -100,14 +100,14 @@ class TestInboxToOutboxFlow:
|
|
|
100
100
|
shared_root=shared_root,
|
|
101
101
|
)
|
|
102
102
|
|
|
103
|
-
loop.
|
|
103
|
+
loop.set_skcomms(mock_skcomms)
|
|
104
104
|
return loop
|
|
105
105
|
|
|
106
106
|
def test_inbox_to_outbox_flow(
|
|
107
|
-
self, shared_root: Path, agent_home: Path,
|
|
107
|
+
self, shared_root: Path, agent_home: Path, mock_skcomms: MagicMock
|
|
108
108
|
):
|
|
109
|
-
"""File dropped in inbox triggers process_envelope and
|
|
110
|
-
loop = self._make_loop(agent_home, shared_root,
|
|
109
|
+
"""File dropped in inbox triggers process_envelope and skcomms.send."""
|
|
110
|
+
loop = self._make_loop(agent_home, shared_root, mock_skcomms)
|
|
111
111
|
|
|
112
112
|
peer = "alice"
|
|
113
113
|
inbox_peer = get_inbox_dir(shared_root) / peer
|
|
@@ -130,15 +130,15 @@ class TestInboxToOutboxFlow:
|
|
|
130
130
|
loop._on_inbox_file(inbox_file)
|
|
131
131
|
loop._executor.shutdown(wait=True)
|
|
132
132
|
|
|
133
|
-
assert
|
|
134
|
-
recipient_arg =
|
|
133
|
+
assert mock_skcomms.send.called, "skcomms.send() must be called with the LLM response"
|
|
134
|
+
recipient_arg = mock_skcomms.send.call_args[0][0]
|
|
135
135
|
assert recipient_arg == peer, "Response must be addressed to the original sender"
|
|
136
136
|
|
|
137
137
|
def test_skipped_when_sender_missing(
|
|
138
|
-
self, shared_root: Path, agent_home: Path,
|
|
138
|
+
self, shared_root: Path, agent_home: Path, mock_skcomms: MagicMock
|
|
139
139
|
):
|
|
140
140
|
"""Envelopes without a sender field are silently dropped."""
|
|
141
|
-
loop = self._make_loop(agent_home, shared_root,
|
|
141
|
+
loop = self._make_loop(agent_home, shared_root, mock_skcomms)
|
|
142
142
|
|
|
143
143
|
inbox_peer = get_inbox_dir(shared_root) / "ghost"
|
|
144
144
|
inbox_peer.mkdir(parents=True, exist_ok=True)
|
|
@@ -149,13 +149,13 @@ class TestInboxToOutboxFlow:
|
|
|
149
149
|
loop._on_inbox_file(inbox_file)
|
|
150
150
|
loop._executor.shutdown(wait=True)
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
mock_skcomms.send.assert_not_called()
|
|
153
153
|
|
|
154
154
|
def test_duplicate_envelope_not_reprocessed(
|
|
155
|
-
self, shared_root: Path, agent_home: Path,
|
|
155
|
+
self, shared_root: Path, agent_home: Path, mock_skcomms: MagicMock
|
|
156
156
|
):
|
|
157
157
|
"""The same envelope_id is never processed twice."""
|
|
158
|
-
loop = self._make_loop(agent_home, shared_root,
|
|
158
|
+
loop = self._make_loop(agent_home, shared_root, mock_skcomms)
|
|
159
159
|
|
|
160
160
|
peer = "bob"
|
|
161
161
|
inbox_peer = get_inbox_dir(shared_root) / peer
|
|
@@ -173,7 +173,7 @@ class TestInboxToOutboxFlow:
|
|
|
173
173
|
# First call
|
|
174
174
|
loop._on_inbox_file(inbox_file)
|
|
175
175
|
loop._executor.shutdown(wait=True)
|
|
176
|
-
first_count =
|
|
176
|
+
first_count = mock_skcomms.send.call_count
|
|
177
177
|
|
|
178
178
|
# Recreate the loop's executor for a second submission attempt
|
|
179
179
|
from concurrent.futures import ThreadPoolExecutor
|
|
@@ -184,7 +184,7 @@ class TestInboxToOutboxFlow:
|
|
|
184
184
|
loop._executor.shutdown(wait=True)
|
|
185
185
|
|
|
186
186
|
# Exactly the same number of sends — second call was deduped
|
|
187
|
-
assert
|
|
187
|
+
assert mock_skcomms.send.call_count == first_count
|
|
188
188
|
|
|
189
189
|
|
|
190
190
|
# ---------------------------------------------------------------------------
|
|
@@ -193,7 +193,7 @@ class TestInboxToOutboxFlow:
|
|
|
193
193
|
|
|
194
194
|
|
|
195
195
|
class TestOutboxEnvelopeFormat:
|
|
196
|
-
"""Verify that outbox envelopes comply with the
|
|
196
|
+
"""Verify that outbox envelopes comply with the SKComms envelope spec."""
|
|
197
197
|
|
|
198
198
|
def test_required_fields_preserved(self, shared_root: Path):
|
|
199
199
|
"""write_outbox_envelope writes all envelope fields to the .skc.json."""
|
|
@@ -348,7 +348,7 @@ class TestSyncStatusInHealth:
|
|
|
348
348
|
|
|
349
349
|
def test_verify_pipeline_detects_transport_misalignment(self, shared_root: Path):
|
|
350
350
|
"""verify_pipeline_paths flags a SyncthingTransport with a wrong comms_root."""
|
|
351
|
-
# Build a mock
|
|
351
|
+
# Build a mock SKComms with a Syncthing transport pointing to the wrong path
|
|
352
352
|
wrong_transport = MagicMock()
|
|
353
353
|
wrong_transport.name = "syncthing"
|
|
354
354
|
wrong_transport._root = Path("/tmp/wrong/path")
|
|
@@ -356,9 +356,9 @@ class TestSyncStatusInHealth:
|
|
|
356
356
|
mock_router = MagicMock()
|
|
357
357
|
mock_router.transports = [wrong_transport]
|
|
358
358
|
|
|
359
|
-
|
|
360
|
-
|
|
359
|
+
mock_skcomms = MagicMock()
|
|
360
|
+
mock_skcomms.router = mock_router
|
|
361
361
|
|
|
362
|
-
result = verify_pipeline_paths(shared_root,
|
|
362
|
+
result = verify_pipeline_paths(shared_root, skcomms=mock_skcomms)
|
|
363
363
|
assert result["transport_aligned"] is False
|
|
364
364
|
assert any("mismatch" in issue.lower() for issue in result["issues"])
|
package/tests/test_team_comms.py
CHANGED
|
@@ -301,9 +301,9 @@ class TestBuildEnvelope:
|
|
|
301
301
|
"""Tests for the internal _build_envelope helper."""
|
|
302
302
|
|
|
303
303
|
def test_required_fields_present(self) -> None:
|
|
304
|
-
"""Envelope dict has all required
|
|
304
|
+
"""Envelope dict has all required SKComms fields."""
|
|
305
305
|
env = _build_envelope("agent-a", "agent-b", "hello")
|
|
306
|
-
assert env["
|
|
306
|
+
assert env["skcomms_version"] == "1.0.0"
|
|
307
307
|
assert env["sender"] == "agent-a"
|
|
308
308
|
assert env["recipient"] == "agent-b"
|
|
309
309
|
assert env["payload"]["content"] == "hello"
|
package/tests/test_testrunner.py
CHANGED
|
@@ -233,6 +233,6 @@ class TestRunAllTests:
|
|
|
233
233
|
|
|
234
234
|
def test_filter_by_package_names(self, tmp_path: Path):
|
|
235
235
|
"""Only requested packages appear in the report."""
|
|
236
|
-
report = run_all_tests(tmp_path, packages=["
|
|
236
|
+
report = run_all_tests(tmp_path, packages=["skcomms", "skchat"])
|
|
237
237
|
names = [r.name for r in report.results]
|
|
238
|
-
assert names == ["
|
|
238
|
+
assert names == ["skcomms", "skchat"]
|
|
@@ -121,6 +121,24 @@ class TestBuildGraph:
|
|
|
121
121
|
sync_edges = [e for e in graph.edges if e.edge_type == "sync"]
|
|
122
122
|
assert len(sync_edges) >= 1
|
|
123
123
|
|
|
124
|
+
def test_manifest_operator_creates_human_link(self, tmp_agent_home: Path):
|
|
125
|
+
"""Manifest operator metadata appears as an explicit trust relationship."""
|
|
126
|
+
_init_agent(tmp_agent_home, "operator-graph")
|
|
127
|
+
manifest_path = tmp_agent_home / "manifest.json"
|
|
128
|
+
manifest = json.loads(manifest_path.read_text())
|
|
129
|
+
manifest["operator"] = {
|
|
130
|
+
"name": "Casey",
|
|
131
|
+
"fingerprint": "FP1234567890",
|
|
132
|
+
"relationship": "human-operator",
|
|
133
|
+
"entity_type": "human",
|
|
134
|
+
}
|
|
135
|
+
manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
|
|
136
|
+
|
|
137
|
+
graph = build_trust_graph(tmp_agent_home)
|
|
138
|
+
|
|
139
|
+
assert any(n.label == "Casey" for n in graph.nodes)
|
|
140
|
+
assert any(e.edge_type == "operator" and e.label == "human-operator" for e in graph.edges)
|
|
141
|
+
|
|
124
142
|
|
|
125
143
|
class TestFormatDot:
|
|
126
144
|
"""Tests for DOT format output."""
|
|
@@ -232,10 +232,10 @@ class TestSearchConversations:
|
|
|
232
232
|
# ---------------------------------------------------------------------------
|
|
233
233
|
|
|
234
234
|
class TestSearchMessages:
|
|
235
|
-
"""Tests for searching
|
|
235
|
+
"""Tests for searching SKComms messages."""
|
|
236
236
|
|
|
237
237
|
def test_finds_skc_message(self, agent_home: Path):
|
|
238
|
-
"""Search should find text inside an archived
|
|
238
|
+
"""Search should find text inside an archived SKComms envelope."""
|
|
239
239
|
_write_message(agent_home, "env001", "jarvis", "lumina",
|
|
240
240
|
"Queen Lumina — welcome to the coordination board!")
|
|
241
241
|
results = search(agent_home, "coordination", sources=frozenset({"message"}))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Tests for ecosystem package version checks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from skcapstone.version_check import _get_installed_version
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_missing_package_returns_none_without_name_error():
|
|
9
|
+
"""Missing package lookup should not raise when logging the fallback failure."""
|
|
10
|
+
assert _get_installed_version("definitely-not-an-sk-package") is None
|
|
@@ -181,7 +181,7 @@ class TestGatherVersionInfo:
|
|
|
181
181
|
assert "daemon_pid" in info
|
|
182
182
|
|
|
183
183
|
def test_optional_deps_has_four_packages(self, agent_home: Path):
|
|
184
|
-
"""optional_deps covers watchdog,
|
|
184
|
+
"""optional_deps covers watchdog, skcomms, skchat, skseed."""
|
|
185
185
|
from skcapstone.cli.version_cmd import gather_version_info
|
|
186
186
|
|
|
187
187
|
with patch("urllib.request.urlopen", side_effect=OSError), \
|
|
@@ -189,7 +189,7 @@ class TestGatherVersionInfo:
|
|
|
189
189
|
info = gather_version_info(agent_home)
|
|
190
190
|
|
|
191
191
|
deps = info["optional_deps"]
|
|
192
|
-
assert set(deps.keys()) == {"watchdog", "
|
|
192
|
+
assert set(deps.keys()) == {"watchdog", "skcomms", "skchat", "skseed"}
|
|
193
193
|
|
|
194
194
|
def test_package_version_matches_module(self, agent_home: Path):
|
|
195
195
|
"""package_version matches skcapstone.__version__."""
|
|
@@ -214,7 +214,7 @@ class TestVersionCommand:
|
|
|
214
214
|
def _run(self, args: list[str], agent_home: Path):
|
|
215
215
|
from skcapstone.cli import main
|
|
216
216
|
|
|
217
|
-
runner = CliRunner(
|
|
217
|
+
runner = CliRunner()
|
|
218
218
|
with patch("urllib.request.urlopen", side_effect=OSError), \
|
|
219
219
|
patch("skcapstone.daemon.read_pid", return_value=None):
|
|
220
220
|
return runner.invoke(
|
|
@@ -235,7 +235,7 @@ class TestVersionCommand:
|
|
|
235
235
|
"""Normal output lists all four optional dep names."""
|
|
236
236
|
result = self._run([], agent_home)
|
|
237
237
|
assert result.exit_code == 0
|
|
238
|
-
for pkg in ("watchdog", "
|
|
238
|
+
for pkg in ("watchdog", "skcomms", "skchat", "skseed"):
|
|
239
239
|
assert pkg in result.output
|
|
240
240
|
|
|
241
241
|
def test_json_output_is_valid_and_complete(self, agent_home: Path):
|
|
@@ -253,7 +253,7 @@ class TestVersionCommand:
|
|
|
253
253
|
"""Shows running + PID when daemon is alive."""
|
|
254
254
|
from skcapstone.cli import main
|
|
255
255
|
|
|
256
|
-
runner = CliRunner(
|
|
256
|
+
runner = CliRunner()
|
|
257
257
|
with patch("urllib.request.urlopen", side_effect=OSError), \
|
|
258
258
|
patch("skcapstone.daemon.read_pid", return_value=42001):
|
|
259
259
|
result = runner.invoke(
|
|
@@ -276,7 +276,7 @@ class TestVersionCommand:
|
|
|
276
276
|
mock_resp.__exit__ = MagicMock(return_value=False)
|
|
277
277
|
mock_resp.read.return_value = payload
|
|
278
278
|
|
|
279
|
-
runner = CliRunner(
|
|
279
|
+
runner = CliRunner()
|
|
280
280
|
with patch("urllib.request.urlopen", return_value=mock_resp), \
|
|
281
281
|
patch("skcapstone.daemon.read_pid", return_value=None):
|
|
282
282
|
result = runner.invoke(
|
|
@@ -299,7 +299,7 @@ class TestDoctorVerbose:
|
|
|
299
299
|
def _run_doctor(self, args: list[str], agent_home: Path):
|
|
300
300
|
from skcapstone.cli import main
|
|
301
301
|
|
|
302
|
-
runner = CliRunner(
|
|
302
|
+
runner = CliRunner()
|
|
303
303
|
return runner.invoke(
|
|
304
304
|
main,
|
|
305
305
|
["doctor", "--home", str(agent_home)] + args,
|
|
@@ -349,7 +349,7 @@ class TestDoctorVerbose:
|
|
|
349
349
|
"""--help output documents the --verbose flag."""
|
|
350
350
|
from skcapstone.cli import main
|
|
351
351
|
|
|
352
|
-
runner = CliRunner(
|
|
352
|
+
runner = CliRunner()
|
|
353
353
|
result = runner.invoke(main, ["doctor", "--help"])
|
|
354
354
|
assert result.exit_code == 0
|
|
355
355
|
assert "--verbose" in result.output
|
package/tests/test_whoami.py
CHANGED
|
@@ -81,7 +81,7 @@ class TestIdentityCard:
|
|
|
81
81
|
name="Opus",
|
|
82
82
|
fingerprint="AABB1122",
|
|
83
83
|
entity_type="ai",
|
|
84
|
-
capabilities=["capauth:identity", "
|
|
84
|
+
capabilities=["capauth:identity", "skcomms:messaging"],
|
|
85
85
|
contact_uris=["capauth:AABB1122"],
|
|
86
86
|
)
|
|
87
87
|
json_str = card.model_dump_json()
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
[Unit]
|
|
2
|
-
Description=SKComm Heartbeat Emission
|
|
3
|
-
Documentation=https://github.com/smilinTux/skcomm
|
|
4
|
-
After=network-online.target
|
|
5
|
-
|
|
6
|
-
[Service]
|
|
7
|
-
Type=oneshot
|
|
8
|
-
ExecStart=skcomm heartbeat --no-emit
|
|
9
|
-
ExecStart=skcomm heartbeat
|
|
10
|
-
Nice=19
|
|
11
|
-
|
|
12
|
-
NoNewPrivileges=true
|
|
13
|
-
ProtectSystem=strict
|
|
14
|
-
ProtectHome=read-only
|
|
15
|
-
ReadWritePaths=%h/.skcapstone %h/.skcomm
|
|
16
|
-
PrivateTmp=true
|
|
17
|
-
|
|
18
|
-
Environment=PYTHONUNBUFFERED=1
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
[Unit]
|
|
2
|
-
Description=SKComm Queue Drain — retry undelivered messages
|
|
3
|
-
Documentation=https://github.com/smilinTux/skcomm
|
|
4
|
-
After=network-online.target
|
|
5
|
-
|
|
6
|
-
[Service]
|
|
7
|
-
Type=oneshot
|
|
8
|
-
ExecStart=skcomm queue drain
|
|
9
|
-
Nice=19
|
|
10
|
-
|
|
11
|
-
NoNewPrivileges=true
|
|
12
|
-
ProtectSystem=strict
|
|
13
|
-
ProtectHome=read-only
|
|
14
|
-
ReadWritePaths=%h/.skcapstone %h/.skcomm
|
|
15
|
-
PrivateTmp=true
|
|
16
|
-
|
|
17
|
-
Environment=PYTHONUNBUFFERED=1
|
|
File without changes
|
|
File without changes
|