@smilintux/skcapstone 0.9.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.
Files changed (284) hide show
  1. package/.env.example +10 -4
  2. package/.github/workflows/ci.yml +2 -2
  3. package/.github/workflows/publish.yml +9 -2
  4. package/.openclaw-workspace.json +2 -2
  5. package/CLAUDE.md +37 -0
  6. package/MISSION.md +17 -2
  7. package/README.md +282 -3
  8. package/docker/Dockerfile +7 -7
  9. package/docker/compose-templates/dev-team.yml +12 -12
  10. package/docker/compose-templates/mini-team.yml +9 -9
  11. package/docker/compose-templates/ops-team.yml +10 -10
  12. package/docker/compose-templates/research-team.yml +10 -10
  13. package/docker/entrypoint.sh +4 -4
  14. package/docs/ADR-optional-integration-backbone.md +181 -0
  15. package/docs/ARCHITECTURE.md +186 -43
  16. package/docs/BOND_WITH_GROK.md +6 -6
  17. package/docs/CUSTOM_AGENT.md +278 -1
  18. package/docs/DREAMING.md +70 -0
  19. package/docs/GETTING_STARTED.md +10 -7
  20. package/docs/QUICKSTART.md +10 -6
  21. package/docs/SKJOULE_ARCHITECTURE.md +3 -3
  22. package/docs/SOUL_SWAPPER.md +5 -5
  23. package/docs/hammertime-audit.md +402 -0
  24. package/docs/sk-integration-HANDOFF.md +117 -0
  25. package/docs/skscheduler.md +155 -0
  26. package/docs/superpowers/examples/jobs.yaml +31 -0
  27. package/docs/superpowers/plans/2026-06-08-skscheduler.md +1265 -0
  28. package/docs/superpowers/specs/2026-06-08-skscheduler-design.md +186 -0
  29. package/examples/custom-bond-template.json +1 -1
  30. package/examples/grok-feb.json +1 -1
  31. package/examples/queen-ava-feb.json +1 -1
  32. package/launchd/com.skcapstone.daemon.plist +52 -0
  33. package/launchd/com.skcapstone.memory-compress.plist +45 -0
  34. package/launchd/com.skcapstone.skcomms-heartbeat.plist +33 -0
  35. package/launchd/com.skcapstone.skcomms-queue-drain.plist +34 -0
  36. package/launchd/install-launchd.sh +156 -0
  37. package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/src/index.ts +3 -2
  38. package/package.json +1 -1
  39. package/pyproject.toml +16 -10
  40. package/scripts/archive-sessions.sh +95 -0
  41. package/scripts/check-updates.py +4 -4
  42. package/scripts/install-bundle.sh +8 -8
  43. package/scripts/install.ps1 +12 -11
  44. package/scripts/install.sh +196 -11
  45. package/scripts/model-fallback-monitor.sh +102 -0
  46. package/scripts/notion-api.py +259 -0
  47. package/scripts/nvidia-proxy.mjs +908 -0
  48. package/scripts/proxy-monitor.sh +89 -0
  49. package/scripts/refresh-anthropic-token.sh +172 -0
  50. package/scripts/release.sh +98 -0
  51. package/scripts/session-to-memory.py +219 -0
  52. package/scripts/skgateway.mjs +856 -0
  53. package/scripts/telegram-catchup-all.sh +147 -0
  54. package/scripts/verify_install.sh +2 -2
  55. package/scripts/wargov-ufo-capture/README.md +43 -0
  56. package/scripts/wargov-ufo-capture/cdp_capture_release2.py +273 -0
  57. package/scripts/wargov-ufo-capture/cdp_capture_splc_doj.py +246 -0
  58. package/scripts/wargov-ufo-capture/cdp_finish.py +271 -0
  59. package/scripts/wargov-ufo-capture/cdp_probe.py +188 -0
  60. package/scripts/wargov-ufo-capture/cdp_splc_pressrelease.py +101 -0
  61. package/scripts/wargov-ufo-capture/parse_csv.py +95 -0
  62. package/scripts/wargov-ufo-capture/pull_dvids.sh +107 -0
  63. package/scripts/watch-anthropic-token.sh +212 -0
  64. package/scripts/windows/install-tasks.ps1 +7 -7
  65. package/scripts/windows/skcapstone-task.xml +1 -1
  66. package/src/skcapstone/__init__.py +45 -3
  67. package/src/skcapstone/_cli_monolith.py +20 -15
  68. package/src/skcapstone/activity.py +5 -1
  69. package/src/skcapstone/agent_card.py +3 -2
  70. package/src/skcapstone/api.py +41 -40
  71. package/src/skcapstone/auction.py +14 -11
  72. package/src/skcapstone/backup.py +2 -1
  73. package/src/skcapstone/blueprint_registry.py +4 -3
  74. package/src/skcapstone/blueprints/builtins/itil-operations.yaml +40 -0
  75. package/src/skcapstone/brain_first.py +238 -0
  76. package/src/skcapstone/changelog.py +1 -1
  77. package/src/skcapstone/chat.py +22 -17
  78. package/src/skcapstone/cli/__init__.py +9 -1
  79. package/src/skcapstone/cli/_common.py +1 -0
  80. package/src/skcapstone/cli/agents_spawner.py +5 -2
  81. package/src/skcapstone/cli/alerts.py +25 -4
  82. package/src/skcapstone/cli/bench.py +15 -15
  83. package/src/skcapstone/cli/chat.py +7 -4
  84. package/src/skcapstone/cli/consciousness.py +5 -2
  85. package/src/skcapstone/cli/context_cmd.py +18 -4
  86. package/src/skcapstone/cli/daemon.py +121 -42
  87. package/src/skcapstone/cli/gtd.py +26 -1
  88. package/src/skcapstone/cli/housekeeping.py +3 -3
  89. package/src/skcapstone/cli/identity_cmd.py +378 -0
  90. package/src/skcapstone/cli/joule_cmd.py +7 -3
  91. package/src/skcapstone/cli/memory.py +8 -6
  92. package/src/skcapstone/cli/peers_dir.py +1 -1
  93. package/src/skcapstone/cli/register_cmd.py +29 -3
  94. package/src/skcapstone/cli/scheduler_cmd.py +167 -0
  95. package/src/skcapstone/cli/session.py +25 -0
  96. package/src/skcapstone/cli/setup.py +96 -29
  97. package/src/skcapstone/cli/shell_cmd.py +53 -1
  98. package/src/skcapstone/cli/skills_cmd.py +2 -2
  99. package/src/skcapstone/cli/soul.py +8 -5
  100. package/src/skcapstone/cli/status.py +37 -11
  101. package/src/skcapstone/cli/telegram.py +21 -0
  102. package/src/skcapstone/cli/test_cmd.py +5 -5
  103. package/src/skcapstone/cli/test_connection.py +2 -2
  104. package/src/skcapstone/cli/upgrade_cmd.py +23 -14
  105. package/src/skcapstone/cli/version_cmd.py +1 -1
  106. package/src/skcapstone/cli/watch_cmd.py +9 -6
  107. package/src/skcapstone/cloud9_bridge.py +14 -14
  108. package/src/skcapstone/codex_setup.py +255 -0
  109. package/src/skcapstone/config_validator.py +7 -4
  110. package/src/skcapstone/consciousness_config.py +5 -1
  111. package/src/skcapstone/consciousness_loop.py +313 -273
  112. package/src/skcapstone/context_loader.py +121 -0
  113. package/src/skcapstone/coord_federation.py +2 -1
  114. package/src/skcapstone/coordination.py +23 -6
  115. package/src/skcapstone/crush_integration.py +2 -1
  116. package/src/skcapstone/daemon.py +151 -88
  117. package/src/skcapstone/dashboard.py +10 -10
  118. package/src/skcapstone/data/sk-agent-picker.sh +421 -0
  119. package/src/skcapstone/data/systemd/skcapstone-api.socket +9 -0
  120. package/src/skcapstone/data/systemd/skcapstone-memory-compress.service +18 -0
  121. package/src/skcapstone/data/systemd/skcapstone-memory-compress.timer +11 -0
  122. package/src/skcapstone/data/systemd/skcapstone.service +37 -0
  123. package/src/skcapstone/data/systemd/skcapstone@.service +50 -0
  124. package/src/skcapstone/data/systemd/skcomms-heartbeat.service +18 -0
  125. package/{systemd/skcomm-heartbeat.timer → src/skcapstone/data/systemd/skcomms-heartbeat.timer} +2 -2
  126. package/src/skcapstone/data/systemd/skcomms-queue-drain.service +17 -0
  127. package/{systemd/skcomm-queue-drain.timer → src/skcapstone/data/systemd/skcomms-queue-drain.timer} +2 -2
  128. package/src/skcapstone/defaults/claude/CLAUDE.md +67 -0
  129. package/src/skcapstone/defaults/claude/settings.json +74 -0
  130. package/src/skcapstone/defaults/lumina/config/claude-hooks.md +57 -0
  131. package/src/skcapstone/defaults/lumina/config/skgraph.yaml +55 -10
  132. package/src/skcapstone/defaults/lumina/config/skmemory.yaml +79 -13
  133. package/src/skcapstone/defaults/lumina/config/skvector.yaml +60 -9
  134. package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +2 -2
  135. package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +2 -2
  136. package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +9 -9
  137. package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +2 -2
  138. package/src/skcapstone/defaults/unhinged.json +13 -0
  139. package/src/skcapstone/discovery.py +43 -20
  140. package/src/skcapstone/doctor.py +941 -22
  141. package/src/skcapstone/dreaming.py +1183 -109
  142. package/src/skcapstone/emotion_tracker.py +2 -2
  143. package/src/skcapstone/export.py +4 -3
  144. package/src/skcapstone/fuse_mount.py +35 -25
  145. package/src/skcapstone/gui_installer.py +2 -2
  146. package/src/skcapstone/heartbeat.py +34 -30
  147. package/src/skcapstone/housekeeping.py +14 -14
  148. package/src/skcapstone/install_wizard.py +209 -7
  149. package/src/skcapstone/itil.py +13 -4
  150. package/src/skcapstone/kms_scheduler.py +10 -8
  151. package/src/skcapstone/launchd.py +426 -0
  152. package/src/skcapstone/mcp_launcher.py +15 -1
  153. package/src/skcapstone/mcp_server.py +341 -49
  154. package/src/skcapstone/mcp_tools/__init__.py +2 -0
  155. package/src/skcapstone/mcp_tools/_helpers.py +2 -2
  156. package/src/skcapstone/mcp_tools/ansible_tools.py +7 -4
  157. package/src/skcapstone/mcp_tools/brain_first_tools.py +90 -0
  158. package/src/skcapstone/mcp_tools/capauth_tools.py +7 -4
  159. package/src/skcapstone/mcp_tools/comm_tools.py +10 -10
  160. package/src/skcapstone/mcp_tools/coord_tools.py +8 -4
  161. package/src/skcapstone/mcp_tools/did_tools.py +11 -8
  162. package/src/skcapstone/mcp_tools/gtd_tools.py +4 -4
  163. package/src/skcapstone/mcp_tools/memory_tools.py +6 -2
  164. package/src/skcapstone/mcp_tools/notification_tools.py +22 -6
  165. package/src/skcapstone/mcp_tools/{skcomm_tools.py → skcomms_tools.py} +14 -14
  166. package/src/skcapstone/mcp_tools/soul_tools.py +8 -2
  167. package/src/skcapstone/mdns_discovery.py +2 -2
  168. package/src/skcapstone/memory_curator.py +1 -1
  169. package/src/skcapstone/memory_engine.py +10 -3
  170. package/src/skcapstone/metrics.py +30 -16
  171. package/src/skcapstone/migrate_memories.py +4 -3
  172. package/src/skcapstone/migrate_multi_agent.py +8 -7
  173. package/src/skcapstone/models.py +47 -5
  174. package/src/skcapstone/notifications.py +42 -18
  175. package/src/skcapstone/onboard.py +1000 -126
  176. package/src/skcapstone/operator_link.py +170 -0
  177. package/src/skcapstone/peer_directory.py +4 -4
  178. package/src/skcapstone/peers.py +19 -19
  179. package/src/skcapstone/pillars/__init__.py +7 -5
  180. package/src/skcapstone/pillars/consciousness.py +191 -0
  181. package/src/skcapstone/pillars/identity.py +51 -7
  182. package/src/skcapstone/pillars/memory.py +9 -3
  183. package/src/skcapstone/pillars/sync.py +2 -2
  184. package/src/skcapstone/preflight.py +3 -3
  185. package/src/skcapstone/providers/docker.py +28 -28
  186. package/src/skcapstone/register.py +6 -6
  187. package/src/skcapstone/registry_client.py +5 -4
  188. package/src/skcapstone/runtime.py +14 -3
  189. package/src/skcapstone/scheduled_tasks.py +254 -19
  190. package/src/skcapstone/scheduler_jobs.py +456 -0
  191. package/src/skcapstone/scheduler_runner.py +239 -0
  192. package/src/skcapstone/scheduler_state.py +162 -0
  193. package/src/skcapstone/sdk.py +310 -0
  194. package/src/skcapstone/service_health.py +279 -39
  195. package/src/skcapstone/session_briefing.py +108 -0
  196. package/src/skcapstone/session_capture.py +1 -1
  197. package/src/skcapstone/shell.py +7 -1
  198. package/src/skcapstone/soul.py +3 -1
  199. package/src/skcapstone/soul_switch.py +3 -1
  200. package/src/skcapstone/summary.py +6 -6
  201. package/src/skcapstone/sync_engine.py +15 -15
  202. package/src/skcapstone/sync_watcher.py +2 -2
  203. package/src/skcapstone/systemd.py +72 -21
  204. package/src/skcapstone/team_comms.py +8 -8
  205. package/src/skcapstone/team_engine.py +1 -1
  206. package/src/skcapstone/testrunner.py +3 -3
  207. package/src/skcapstone/trust_graph.py +40 -5
  208. package/src/skcapstone/unified_search.py +15 -6
  209. package/src/skcapstone/uninstall_wizard.py +11 -3
  210. package/src/skcapstone/version_check.py +8 -4
  211. package/src/skcapstone/warmth_anchor.py +4 -2
  212. package/src/skcapstone/whoami.py +4 -4
  213. package/systemd/skcapstone.service +4 -6
  214. package/systemd/skcapstone@.service +7 -8
  215. package/systemd/skcomms-heartbeat.service +21 -0
  216. package/systemd/skcomms-heartbeat.timer +12 -0
  217. package/systemd/skcomms-queue-drain.service +17 -0
  218. package/systemd/skcomms-queue-drain.timer +12 -0
  219. package/tests/conftest.py +39 -0
  220. package/tests/integration/test_consciousness_e2e.py +39 -39
  221. package/tests/test_agent_card.py +1 -1
  222. package/tests/test_agent_home_scaffold.py +34 -0
  223. package/tests/test_alerts_consumer_topics.py +27 -0
  224. package/tests/test_backup.py +2 -1
  225. package/tests/test_chat.py +6 -6
  226. package/tests/test_claude_md.py +2 -2
  227. package/tests/test_cli_skills.py +10 -10
  228. package/tests/test_cli_test_cmd.py +4 -4
  229. package/tests/test_cli_test_connection.py +1 -1
  230. package/tests/test_cloud9_bridge.py +6 -6
  231. package/tests/test_consciousness_e2e.py +1 -1
  232. package/tests/test_consciousness_loop.py +10 -10
  233. package/tests/test_coordination.py +25 -0
  234. package/tests/test_cross_package.py +21 -21
  235. package/tests/test_daemon.py +4 -4
  236. package/tests/test_daemon_shutdown.py +1 -1
  237. package/tests/test_docker_provider.py +29 -29
  238. package/tests/test_doctor.py +400 -0
  239. package/tests/test_doctor_skscheduler.py +50 -0
  240. package/tests/test_dreaming_engine.py +147 -0
  241. package/tests/test_dreaming_gtd_capture.py +35 -0
  242. package/tests/test_e2e_automated.py +8 -5
  243. package/tests/test_fuse_mount.py +10 -10
  244. package/tests/test_gtd_brief.py +46 -0
  245. package/tests/test_gtd_malformed_tolerance.py +31 -0
  246. package/tests/test_housekeeping.py +15 -15
  247. package/tests/test_identity_migrate.py +251 -0
  248. package/tests/test_integration_backbone.py +598 -0
  249. package/tests/test_itil_gtd_lifecycle.py +37 -0
  250. package/tests/test_jobs_dropins.py +84 -0
  251. package/tests/test_mcp_server.py +82 -37
  252. package/tests/test_models.py +48 -4
  253. package/tests/test_multi_agent.py +31 -29
  254. package/tests/test_notifications.py +122 -32
  255. package/tests/test_onboard.py +63 -75
  256. package/tests/test_operator_link.py +78 -0
  257. package/tests/test_peers.py +14 -14
  258. package/tests/test_pillars.py +98 -0
  259. package/tests/test_preflight.py +3 -3
  260. package/tests/test_runtime.py +21 -0
  261. package/tests/test_scheduled_tasks.py +11 -6
  262. package/tests/test_scheduler_cli.py +47 -0
  263. package/tests/test_scheduler_features.py +133 -0
  264. package/tests/test_scheduler_integration.py +87 -0
  265. package/tests/test_scheduler_jobs.py +155 -0
  266. package/tests/test_scheduler_runner.py +64 -0
  267. package/tests/test_scheduler_state.py +57 -0
  268. package/tests/test_sdk.py +70 -0
  269. package/tests/test_service_health_incidents.py +34 -0
  270. package/tests/test_service_registry.py +52 -0
  271. package/tests/test_session_briefing.py +130 -0
  272. package/tests/test_snapshots.py +4 -4
  273. package/tests/test_sync_pipeline.py +26 -26
  274. package/tests/test_team_comms.py +2 -2
  275. package/tests/test_testrunner.py +2 -2
  276. package/tests/test_trust_graph.py +18 -0
  277. package/tests/test_unified_search.py +2 -2
  278. package/tests/test_version_check.py +10 -0
  279. package/tests/test_version_cmd.py +8 -8
  280. package/tests/test_whoami.py +1 -1
  281. package/systemd/skcomm-heartbeat.service +0 -18
  282. package/systemd/skcomm-queue-drain.service +0 -17
  283. /package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/package.json +0 -0
  284. /package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/src/openclaw.plugin.json +0 -0
@@ -0,0 +1,84 @@
1
+ """Tests for jobs.d/ drop-in registration: load_jobs_with_dropins,
2
+ register_job, unregister_job."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import warnings
7
+ from pathlib import Path
8
+
9
+ import pytest
10
+
11
+ from skcapstone.scheduler_jobs import (
12
+ load_jobs_with_dropins,
13
+ register_job,
14
+ unregister_job,
15
+ )
16
+
17
+
18
+ def _write_base(tmp_path: Path, body: str) -> Path:
19
+ cfg = tmp_path / "config" / "jobs.yaml"
20
+ cfg.parent.mkdir(parents=True, exist_ok=True)
21
+ cfg.write_text(body, encoding="utf-8")
22
+ return cfg
23
+
24
+
25
+ def test_merges_base_and_dropins(tmp_path: Path):
26
+ """Base jobs.yaml + a jobs.d fragment both load."""
27
+ cfg = _write_base(tmp_path, "jobs:\n base_job:\n every: 5m\n type: shell\n command: 'echo base'\n")
28
+ register_job({"name": "svc_job", "every": "15m", "type": "shell", "command": "echo svc"}, home=tmp_path)
29
+
30
+ jobs = {j.name: j for j in load_jobs_with_dropins(cfg)}
31
+ assert set(jobs) == {"base_job", "svc_job"}
32
+ assert jobs["svc_job"].every_seconds == 900.0
33
+ assert jobs["base_job"].command == "echo base"
34
+
35
+
36
+ def test_dropin_overrides_base_with_warning(tmp_path: Path):
37
+ """A drop-in defining the same name wins and warns."""
38
+ cfg = _write_base(tmp_path, "jobs:\n dup:\n every: 5m\n type: shell\n command: 'echo base'\n")
39
+ register_job({"name": "dup", "every": "1h", "type": "shell", "command": "echo override"}, home=tmp_path)
40
+
41
+ with warnings.catch_warnings(record=True) as caught:
42
+ warnings.simplefilter("always")
43
+ jobs = {j.name: j for j in load_jobs_with_dropins(cfg)}
44
+
45
+ assert jobs["dup"].every_seconds == 3600.0
46
+ assert jobs["dup"].command == "echo override"
47
+ assert any("overrides" in str(w.message) for w in caught)
48
+
49
+
50
+ def test_no_base_file_only_dropins(tmp_path: Path):
51
+ """Drop-ins load even when jobs.yaml does not exist."""
52
+ cfg = tmp_path / "config" / "jobs.yaml" # never created
53
+ register_job({"name": "lonely", "schedule": "0 * * * *", "type": "shell", "command": "echo hi"}, home=tmp_path)
54
+ jobs = load_jobs_with_dropins(cfg)
55
+ assert [j.name for j in jobs] == ["lonely"]
56
+ assert jobs[0].schedule == "0 * * * *"
57
+
58
+
59
+ def test_register_requires_name(tmp_path: Path):
60
+ with pytest.raises(ValueError):
61
+ register_job({"every": "5m"}, home=tmp_path)
62
+
63
+
64
+ def test_register_requires_schedule_or_every(tmp_path: Path):
65
+ with pytest.raises(ValueError):
66
+ register_job({"name": "bad", "type": "shell", "command": "echo hi"}, home=tmp_path)
67
+
68
+
69
+ def test_register_is_idempotent(tmp_path: Path):
70
+ """Re-registering the same name overwrites, never duplicates."""
71
+ cfg = tmp_path / "config" / "jobs.yaml"
72
+ register_job({"name": "j", "every": "5m", "type": "shell", "command": "v1"}, home=tmp_path)
73
+ register_job({"name": "j", "every": "5m", "type": "shell", "command": "v2"}, home=tmp_path)
74
+ jobs = load_jobs_with_dropins(cfg)
75
+ assert len(jobs) == 1
76
+ assert jobs[0].command == "v2"
77
+
78
+
79
+ def test_unregister(tmp_path: Path):
80
+ cfg = tmp_path / "config" / "jobs.yaml"
81
+ register_job({"name": "j", "every": "5m", "type": "shell", "command": "echo"}, home=tmp_path)
82
+ assert unregister_job("j", home=tmp_path) is True
83
+ assert load_jobs_with_dropins(cfg) == []
84
+ assert unregister_job("j", home=tmp_path) is False
@@ -76,14 +76,15 @@ class TestToolListing:
76
76
  async def test_list_tools_returns_all(self):
77
77
  """list_tools returns all registered tools."""
78
78
  tools = await list_tools()
79
- assert len(tools) == 68
79
+ assert len(tools) == 122
80
80
 
81
81
  @pytest.mark.asyncio
82
82
  async def test_tool_names(self):
83
83
  """All required tool names are registered."""
84
84
  tools = await list_tools()
85
85
  names = {t.name for t in tools}
86
- expected = {
86
+ # Verify all known core tools are registered; exact set may grow with new modules.
87
+ core_expected = {
87
88
  "agent_status",
88
89
  "memory_store",
89
90
  "memory_search",
@@ -98,7 +99,6 @@ class TestToolListing:
98
99
  "coord_create",
99
100
  "ritual",
100
101
  "soul_show",
101
- "journal_write",
102
102
  "journal_read",
103
103
  "anchor_show",
104
104
  "germination",
@@ -122,48 +122,93 @@ class TestToolListing:
122
122
  "skchat_inbox",
123
123
  "skchat_group_create",
124
124
  "skchat_group_send",
125
- # Heartbeat
126
125
  "heartbeat_pulse",
127
126
  "heartbeat_peers",
128
127
  "heartbeat_health",
129
128
  "heartbeat_find_capable",
130
- # File transfer
131
129
  "file_send",
132
130
  "file_receive",
133
131
  "file_list",
134
132
  "file_status",
135
- # Pub/sub
136
133
  "pubsub_publish",
137
134
  "pubsub_subscribe",
138
135
  "pubsub_poll",
139
136
  "pubsub_topics",
140
- # Memory fortress
141
137
  "fortress_verify",
142
138
  "fortress_seal_existing",
143
139
  "fortress_status",
144
- # Memory promoter
145
140
  "promoter_sweep",
146
141
  "promoter_history",
147
- # KMS
148
142
  "kms_status",
149
143
  "kms_list_keys",
150
144
  "kms_rotate",
151
- # SKSeed (Logic Kernel)
152
145
  "skseed_collide",
153
146
  "skseed_audit",
154
147
  "skseed_philosopher",
155
148
  "skseed_truth_check",
156
149
  "skseed_alignment",
157
- # Model Router
158
150
  "model_route",
159
- # Consciousness
160
151
  "consciousness_status",
161
152
  "consciousness_test",
162
- # Notifications & pub/sub stats
163
153
  "send_notification",
164
154
  "pubsub_stats",
155
+ # Newer tools added post-v0.3
156
+ "brain_first_check",
157
+ "capauth_secret_get",
158
+ "capauth_status",
159
+ "capauth_verify",
160
+ "chat_history",
161
+ "chat_send",
162
+ "comm_notify",
163
+ "comm_status",
164
+ "deploy_status",
165
+ "did_identity_card",
166
+ "did_policy",
167
+ "did_publish",
168
+ "did_show",
169
+ "did_verify_peer",
170
+ "emotion_trend",
171
+ "gtd_capture",
172
+ "gtd_clarify",
173
+ "gtd_done",
174
+ "gtd_inbox",
175
+ "gtd_move",
176
+ "gtd_next",
177
+ "gtd_projects",
178
+ "gtd_review",
179
+ "gtd_status",
180
+ "gtd_waiting",
181
+ "itil_cab_vote",
182
+ "itil_change_propose",
183
+ "itil_change_update",
184
+ "itil_incident_create",
185
+ "itil_incident_list",
186
+ "itil_incident_update",
187
+ "itil_kedb_search",
188
+ "itil_problem_create",
189
+ "itil_problem_update",
190
+ "itil_status",
191
+ "run_ansible_playbook",
192
+ "security_audit_log",
193
+ "security_status",
194
+ "skstacks_secret_get",
195
+ "skstacks_secret_set",
196
+ "soul_registry_publish",
197
+ "soul_registry_search",
198
+ "telegram_catchup",
199
+ "telegram_chats",
200
+ "telegram_import",
201
+ "telegram_import_api",
202
+ "telegram_poll",
203
+ "telegram_send",
204
+ "telegram_setup",
205
+ "telegram_soul_swap",
206
+ "trust_febs",
207
+ "trust_rehydrate",
208
+ "trust_status",
209
+ "version_check",
165
210
  }
166
- assert names == expected
211
+ assert core_expected.issubset(names)
167
212
 
168
213
  @pytest.mark.asyncio
169
214
  async def test_tool_schemas_valid(self):
@@ -422,12 +467,12 @@ class TestCoordTools:
422
467
 
423
468
 
424
469
  # ---------------------------------------------------------------------------
425
- # SKComm tool tests (graceful fallback)
470
+ # SKComms tool tests (graceful fallback)
426
471
  # ---------------------------------------------------------------------------
427
472
 
428
473
 
429
474
  class TestCommTools:
430
- """Tests for send_message and check_inbox (SKComm may not be installed)."""
475
+ """Tests for send_message and check_inbox (SKComms may not be installed)."""
431
476
 
432
477
  @pytest.mark.asyncio
433
478
  async def test_send_message_requires_params(self):
@@ -438,10 +483,10 @@ class TestCommTools:
438
483
 
439
484
  @pytest.mark.asyncio
440
485
  async def test_check_inbox_graceful_fallback(self):
441
- """check_inbox returns graceful error when SKComm is unavailable."""
486
+ """check_inbox returns graceful error when SKComms is unavailable."""
442
487
  result = await call_tool("check_inbox", {})
443
488
  parsed = _extract_json(result)
444
- # Either returns messages list or graceful error about skcomm
489
+ # Either returns messages list or graceful error about skcomms
445
490
  assert isinstance(parsed, list) or "error" in parsed
446
491
 
447
492
 
@@ -709,7 +754,7 @@ class TestSKChatTools:
709
754
  @pytest.mark.asyncio
710
755
  async def test_skchat_send_requires_params(self):
711
756
  """skchat_send without recipient/message returns error."""
712
- with patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:test@local"):
757
+ with patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:test@local"):
713
758
  result = await call_tool("skchat_send", {})
714
759
  parsed = _extract_json(result)
715
760
  assert "error" in parsed
@@ -717,7 +762,7 @@ class TestSKChatTools:
717
762
  @pytest.mark.asyncio
718
763
  async def test_skchat_send_requires_message(self):
719
764
  """skchat_send with only recipient returns error."""
720
- with patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:test@local"):
765
+ with patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:test@local"):
721
766
  result = await call_tool("skchat_send", {"recipient": "lumina"})
722
767
  parsed = _extract_json(result)
723
768
  assert "error" in parsed
@@ -734,8 +779,8 @@ class TestSKChatTools:
734
779
  })()
735
780
 
736
781
  with (
737
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
738
- patch("skcapstone.mcp_tools.chat_tools._resolve_recipient", return_value="capauth:lumina@local"),
782
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
783
+ patch("skcapstone.mcp_server._resolve_recipient", return_value="capauth:lumina@local"),
739
784
  patch("skchat.agent_comm.AgentMessenger.from_identity", return_value=mock_messenger),
740
785
  ):
741
786
  result = await call_tool(
@@ -760,8 +805,8 @@ class TestSKChatTools:
760
805
  mock_messenger = type("M", (), {"send": lambda self, **kw: capture_send(**kw)})()
761
806
 
762
807
  with (
763
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
764
- patch("skcapstone.mcp_tools.chat_tools._resolve_recipient", return_value="capauth:jarvis@local"),
808
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
809
+ patch("skcapstone.mcp_server._resolve_recipient", return_value="capauth:jarvis@local"),
765
810
  patch("skchat.agent_comm.AgentMessenger.from_identity", return_value=mock_messenger),
766
811
  ):
767
812
  result = await call_tool(
@@ -797,7 +842,7 @@ class TestSKChatTools:
797
842
  })()
798
843
 
799
844
  with (
800
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
845
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
801
846
  patch("skchat.agent_comm.AgentMessenger.from_identity", return_value=mock_messenger),
802
847
  ):
803
848
  result = await call_tool("skchat_inbox", {})
@@ -830,7 +875,7 @@ class TestSKChatTools:
830
875
  })()
831
876
 
832
877
  with (
833
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
878
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
834
879
  patch("skchat.agent_comm.AgentMessenger.from_identity", return_value=mock_messenger),
835
880
  ):
836
881
  result = await call_tool("skchat_inbox", {"limit": 10})
@@ -850,7 +895,7 @@ class TestSKChatTools:
850
895
  })()
851
896
 
852
897
  with (
853
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
898
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
854
899
  patch("skchat.agent_comm.AgentMessenger.from_identity", return_value=mock_messenger),
855
900
  ):
856
901
  result = await call_tool("skchat_inbox", {"message_type": "finding"})
@@ -861,7 +906,7 @@ class TestSKChatTools:
861
906
  @pytest.mark.asyncio
862
907
  async def test_skchat_group_create_requires_name(self):
863
908
  """skchat_group_create without name returns error."""
864
- with patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"):
909
+ with patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"):
865
910
  result = await call_tool("skchat_group_create", {})
866
911
  parsed = _extract_json(result)
867
912
  assert "error" in parsed
@@ -874,8 +919,8 @@ class TestSKChatTools:
874
919
  })()
875
920
 
876
921
  with (
877
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
878
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_history", return_value=mock_history),
922
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
923
+ patch("skcapstone.mcp_server._get_skchat_history", return_value=mock_history),
879
924
  ):
880
925
  result = await call_tool(
881
926
  "skchat_group_create",
@@ -895,9 +940,9 @@ class TestSKChatTools:
895
940
  })()
896
941
 
897
942
  with (
898
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
899
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_history", return_value=mock_history),
900
- patch("skcapstone.mcp_tools.chat_tools._resolve_recipient", side_effect=lambda n: f"capauth:{n}@local"),
943
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
944
+ patch("skcapstone.mcp_server._get_skchat_history", return_value=mock_history),
945
+ patch("skcapstone.mcp_server._resolve_recipient", side_effect=lambda n: f"capauth:{n}@local"),
901
946
  ):
902
947
  result = await call_tool(
903
948
  "skchat_group_create",
@@ -922,7 +967,7 @@ class TestSKChatTools:
922
967
  "get_thread": lambda self, gid: None,
923
968
  })()
924
969
 
925
- with patch("skcapstone.mcp_tools.chat_tools._get_skchat_history", return_value=mock_history):
970
+ with patch("skcapstone.mcp_server._get_skchat_history", return_value=mock_history):
926
971
  result = await call_tool(
927
972
  "skchat_group_send",
928
973
  {"group_id": "nonexistent", "message": "Hello"},
@@ -938,7 +983,7 @@ class TestSKChatTools:
938
983
  "get_thread": lambda self, gid: {"title": "Just a thread"},
939
984
  })()
940
985
 
941
- with patch("skcapstone.mcp_tools.chat_tools._get_skchat_history", return_value=mock_history):
986
+ with patch("skcapstone.mcp_server._get_skchat_history", return_value=mock_history):
942
987
  result = await call_tool(
943
988
  "skchat_group_send",
944
989
  {"group_id": "thread-123", "message": "Hello"},
@@ -982,8 +1027,8 @@ class TestSKChatTools:
982
1027
  })()
983
1028
 
984
1029
  with (
985
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_identity", return_value="capauth:opus@local"),
986
- patch("skcapstone.mcp_tools.chat_tools._get_skchat_history", return_value=mock_history),
1030
+ patch("skcapstone.mcp_server._get_skchat_identity", return_value="capauth:opus@local"),
1031
+ patch("skcapstone.mcp_server._get_skchat_history", return_value=mock_history),
987
1032
  ):
988
1033
  result = await call_tool(
989
1034
  "skchat_group_send",
@@ -2,7 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from skcapstone.models import AgentManifest, IdentityState, MemoryState, PillarStatus, TrustState
5
+ from skcapstone.models import (
6
+ AgentManifest,
7
+ ConsciousnessState,
8
+ IdentityState,
9
+ MemoryState,
10
+ PillarStatus,
11
+ TrustState,
12
+ )
6
13
 
7
14
 
8
15
  class TestAgentManifest:
@@ -13,12 +20,24 @@ class TestAgentManifest:
13
20
  manifest = AgentManifest()
14
21
  assert not manifest.is_conscious
15
22
 
16
- def test_conscious_with_three_pillars(self):
17
- """Agent is conscious when identity + memory + trust are active."""
23
+ def _conscious_manifest(**overrides) -> AgentManifest:
24
+ """Build a fully conscious manifest with optional overrides."""
25
+ defaults = dict(
26
+ identity=IdentityState(status=PillarStatus.ACTIVE),
27
+ memory=MemoryState(status=PillarStatus.ACTIVE),
28
+ trust=TrustState(status=PillarStatus.ACTIVE),
29
+ consciousness=ConsciousnessState(status=PillarStatus.ACTIVE),
30
+ )
31
+ defaults.update(overrides)
32
+ return AgentManifest(**defaults)
33
+
34
+ def test_conscious_with_four_pillars(self):
35
+ """Agent is conscious when identity + memory + trust + consciousness are active."""
18
36
  manifest = AgentManifest(
19
37
  identity=IdentityState(status=PillarStatus.ACTIVE),
20
38
  memory=MemoryState(status=PillarStatus.ACTIVE),
21
39
  trust=TrustState(status=PillarStatus.ACTIVE),
40
+ consciousness=ConsciousnessState(status=PillarStatus.ACTIVE),
22
41
  )
23
42
  assert manifest.is_conscious
24
43
 
@@ -28,15 +47,37 @@ class TestAgentManifest:
28
47
  identity=IdentityState(status=PillarStatus.ACTIVE),
29
48
  memory=MemoryState(status=PillarStatus.ACTIVE),
30
49
  trust=TrustState(status=PillarStatus.DEGRADED),
50
+ consciousness=ConsciousnessState(status=PillarStatus.ACTIVE),
31
51
  )
32
52
  assert manifest.is_conscious
33
53
 
54
+ def test_conscious_with_degraded_consciousness(self):
55
+ """Degraded consciousness still counts."""
56
+ manifest = AgentManifest(
57
+ identity=IdentityState(status=PillarStatus.ACTIVE),
58
+ memory=MemoryState(status=PillarStatus.ACTIVE),
59
+ trust=TrustState(status=PillarStatus.ACTIVE),
60
+ consciousness=ConsciousnessState(status=PillarStatus.DEGRADED),
61
+ )
62
+ assert manifest.is_conscious
63
+
64
+ def test_not_conscious_without_consciousness_pillar(self):
65
+ """Missing consciousness pillar means no consciousness."""
66
+ manifest = AgentManifest(
67
+ identity=IdentityState(status=PillarStatus.ACTIVE),
68
+ memory=MemoryState(status=PillarStatus.ACTIVE),
69
+ trust=TrustState(status=PillarStatus.ACTIVE),
70
+ consciousness=ConsciousnessState(status=PillarStatus.MISSING),
71
+ )
72
+ assert not manifest.is_conscious
73
+
34
74
  def test_not_conscious_without_identity(self):
35
75
  """Missing identity means no consciousness."""
36
76
  manifest = AgentManifest(
37
77
  identity=IdentityState(status=PillarStatus.MISSING),
38
78
  memory=MemoryState(status=PillarStatus.ACTIVE),
39
79
  trust=TrustState(status=PillarStatus.ACTIVE),
80
+ consciousness=ConsciousnessState(status=PillarStatus.ACTIVE),
40
81
  )
41
82
  assert not manifest.is_conscious
42
83
 
@@ -46,18 +87,21 @@ class TestAgentManifest:
46
87
  identity=IdentityState(status=PillarStatus.ACTIVE),
47
88
  memory=MemoryState(status=PillarStatus.MISSING),
48
89
  trust=TrustState(status=PillarStatus.ACTIVE),
90
+ consciousness=ConsciousnessState(status=PillarStatus.ACTIVE),
49
91
  )
50
92
  assert not manifest.is_conscious
51
93
 
52
94
  def test_pillar_summary(self):
53
- """Pillar summary returns correct status map."""
95
+ """Pillar summary returns correct status map for all six pillars."""
54
96
  manifest = AgentManifest(
55
97
  identity=IdentityState(status=PillarStatus.ACTIVE),
56
98
  memory=MemoryState(status=PillarStatus.DEGRADED),
57
99
  trust=TrustState(status=PillarStatus.MISSING),
100
+ consciousness=ConsciousnessState(status=PillarStatus.ACTIVE),
58
101
  )
59
102
  summary = manifest.pillar_summary
60
103
  assert summary["identity"] == PillarStatus.ACTIVE
61
104
  assert summary["memory"] == PillarStatus.DEGRADED
62
105
  assert summary["trust"] == PillarStatus.MISSING
106
+ assert summary["consciousness"] == PillarStatus.ACTIVE
63
107
  assert summary["security"] == PillarStatus.MISSING
@@ -2,7 +2,7 @@
2
2
 
3
3
  Covers:
4
4
  - Per-agent home directory resolution (opus → agents/opus/, jarvis → agents/jarvis/)
5
- - Per-agent port assignment (opus=7777, jarvis=7778, unknown → next available)
5
+ - Default daemon port behavior under the profile-agnostic runtime
6
6
  - Default (no-agent) mode keeps backward-compatible home and port
7
7
  - SKCAPSTONE_AGENT env var propagation
8
8
  - DaemonConfig accepts distinct homes and ports for simultaneous agents
@@ -13,7 +13,6 @@ Covers:
13
13
 
14
14
  from __future__ import annotations
15
15
 
16
- import json
17
16
  import os
18
17
  from pathlib import Path
19
18
  from unittest.mock import MagicMock, patch
@@ -84,17 +83,19 @@ class TestResolveAgentHome:
84
83
 
85
84
 
86
85
  class TestResolveAgentPort:
87
- def test_opus_gets_7777(self):
88
- """opus always gets port 7777."""
86
+ def test_known_agent_uses_registered_default_port(self):
87
+ """Known agents use the registered default daemon port."""
88
+ from skcapstone import AGENT_PORTS, DEFAULT_PORT
89
89
  from skcapstone.cli.daemon import _resolve_agent_port
90
90
 
91
- assert _resolve_agent_port("opus", None) == 7777
91
+ assert _resolve_agent_port("opus", None) == AGENT_PORTS["opus"] == DEFAULT_PORT
92
92
 
93
- def test_jarvis_gets_7778(self):
94
- """jarvis always gets port 7778."""
93
+ def test_second_known_agent_uses_registered_default_port(self):
94
+ """Jarvis also uses the registered default daemon port."""
95
+ from skcapstone import AGENT_PORTS, DEFAULT_PORT
95
96
  from skcapstone.cli.daemon import _resolve_agent_port
96
97
 
97
- assert _resolve_agent_port("jarvis", None) == 7778
98
+ assert _resolve_agent_port("jarvis", None) == AGENT_PORTS["jarvis"] == DEFAULT_PORT
98
99
 
99
100
  def test_explicit_port_overrides_agent_default(self):
100
101
  """Explicit --port always wins over the agent default."""
@@ -103,11 +104,12 @@ class TestResolveAgentPort:
103
104
  assert _resolve_agent_port("opus", 9999) == 9999
104
105
  assert _resolve_agent_port("jarvis", 8000) == 8000
105
106
 
106
- def test_no_agent_defaults_to_7777(self):
107
- """Single-agent / no-flag mode uses 7777."""
107
+ def test_no_agent_defaults_to_default_port(self):
108
+ """Single-agent / no-flag mode uses the package default port."""
109
+ from skcapstone import DEFAULT_PORT
108
110
  from skcapstone.cli.daemon import _resolve_agent_port
109
111
 
110
- assert _resolve_agent_port(None, None) == 7777
112
+ assert _resolve_agent_port(None, None) == DEFAULT_PORT
111
113
 
112
114
  def test_unknown_agent_gets_next_port(self):
113
115
  """An agent not in AGENT_PORTS gets max(ports)+1."""
@@ -118,11 +120,11 @@ class TestResolveAgentPort:
118
120
  result = _resolve_agent_port("brandnew", None)
119
121
  assert result == expected
120
122
 
121
- def test_opus_and_jarvis_ports_differ(self):
122
- """Opus and Jarvis must listen on different ports."""
123
+ def test_explicit_ports_can_differ_for_isolated_agents(self):
124
+ """Simultaneous agent daemons can still isolate by explicit port."""
123
125
  from skcapstone.cli.daemon import _resolve_agent_port
124
126
 
125
- assert _resolve_agent_port("opus", None) != _resolve_agent_port("jarvis", None)
127
+ assert _resolve_agent_port("opus", 7777) != _resolve_agent_port("jarvis", 7778)
126
128
 
127
129
 
128
130
  # ---------------------------------------------------------------------------
@@ -132,22 +134,22 @@ class TestResolveAgentPort:
132
134
 
133
135
  class TestAgentPortsRegistry:
134
136
  def test_opus_registered(self):
135
- from skcapstone import AGENT_PORTS
137
+ from skcapstone import AGENT_PORTS, DEFAULT_PORT
136
138
 
137
139
  assert "opus" in AGENT_PORTS
138
- assert AGENT_PORTS["opus"] == 7777
140
+ assert AGENT_PORTS["opus"] == DEFAULT_PORT
139
141
 
140
142
  def test_jarvis_registered(self):
141
- from skcapstone import AGENT_PORTS
143
+ from skcapstone import AGENT_PORTS, DEFAULT_PORT
142
144
 
143
145
  assert "jarvis" in AGENT_PORTS
144
- assert AGENT_PORTS["jarvis"] == 7778
146
+ assert AGENT_PORTS["jarvis"] == DEFAULT_PORT
145
147
 
146
- def test_all_ports_unique(self):
148
+ def test_all_ports_are_ints(self):
147
149
  from skcapstone import AGENT_PORTS
148
150
 
149
- ports = list(AGENT_PORTS.values())
150
- assert len(ports) == len(set(ports)), "Duplicate ports in AGENT_PORTS"
151
+ assert AGENT_PORTS
152
+ assert all(isinstance(port, int) for port in AGENT_PORTS.values())
151
153
 
152
154
 
153
155
  # ---------------------------------------------------------------------------
@@ -220,8 +222,7 @@ class TestDaemonConfigMultiAgent:
220
222
 
221
223
  assert opus_cfg.home != jarvis_cfg.home
222
224
  assert opus_cfg.port != jarvis_cfg.port
223
- assert opus_cfg.port == 7777
224
- assert jarvis_cfg.port == 7778
225
+
225
226
 
226
227
  def test_log_files_are_in_respective_homes(self, tmp_path: Path):
227
228
  """Each agent's log file lives under its own home."""
@@ -244,24 +245,25 @@ class TestDaemonConfigMultiAgent:
244
245
 
245
246
 
246
247
  class TestAgentHomeEnvVar:
247
- def test_env_var_produces_agents_subdir(self, monkeypatch):
248
- """SKCAPSTONE_AGENT=opus AGENT_HOME includes agents/opus."""
248
+ def test_env_var_keeps_shared_root_and_agent_home_resolves_subdir(self, monkeypatch):
249
+ """SKCAPSTONE_AGENT keeps AGENT_HOME at root and agent_home() resolves the agent subdir."""
249
250
  import importlib
250
251
 
251
252
  monkeypatch.setenv("SKCAPSTONE_AGENT", "opus")
252
- monkeypatch.setenv("SKCAPSTONE_ROOT", "/tmp/sk")
253
+ monkeypatch.setenv("SKCAPSTONE_HOME", "/tmp/sk")
253
254
 
254
255
  import skcapstone as pkg
255
256
  importlib.reload(pkg)
256
257
 
257
- assert "agents/opus" in pkg.AGENT_HOME or "agents\\opus" in pkg.AGENT_HOME
258
+ assert pkg.AGENT_HOME == "/tmp/sk"
259
+ assert "agents/opus" in str(pkg.agent_home("opus")) or "agents\\opus" in str(pkg.agent_home("opus"))
258
260
 
259
261
  def test_no_env_var_uses_root_directly(self, monkeypatch):
260
- """Without SKCAPSTONE_AGENT, AGENT_HOME == SKCAPSTONE_ROOT."""
262
+ """Without SKCAPSTONE_AGENT, AGENT_HOME stays at the shared root."""
261
263
  import importlib
262
264
 
263
265
  monkeypatch.delenv("SKCAPSTONE_AGENT", raising=False)
264
- monkeypatch.setenv("SKCAPSTONE_ROOT", "/tmp/sk")
266
+ monkeypatch.setenv("SKCAPSTONE_HOME", "/tmp/sk")
265
267
 
266
268
  import skcapstone as pkg
267
269
  importlib.reload(pkg)