@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,186 @@
1
+ # skscheduler — Unified Fleet Job Scheduler
2
+
3
+ **Date:** 2026-06-08
4
+ **Status:** Design approved, pending spec review
5
+ **Driver incident/problem:** `prb-7810b08e` (service_health multi-write Syncthing conflicts), `inc-455b1a64`
6
+ **Immediate need:** a daily GTD inbox-triage agent running on .41
7
+
8
+ ## Problem
9
+
10
+ Scheduling across the fleet is fragmented across four mechanisms with no single
11
+ place to define, run, or observe jobs:
12
+
13
+ 1. **skcapstone `TaskScheduler`** (`scheduled_tasks.py`) — interval-only Python
14
+ callbacks (heartbeat, backend_reprobe, memory_promotion_sweep,
15
+ dreaming_reflection). Runs inside the skcapstone daemon, which is **inactive
16
+ on .41**.
17
+ 2. **Legacy user crontab** — 5 jobs pointing at a stale pre-skcapstone path
18
+ (`~/dkloud.douno.it/.../docs/memory/memory/scripts/`).
19
+ 3. **systemd user timers** — `skcapstone-context` (active), `skcomms-heartbeat`
20
+ (dead), `direnv-backup`.
21
+ 4. **Claude Code crons** — separate scheduled-agent system.
22
+
23
+ Consequences observed: the GTD inbox is never processed (capture is automated,
24
+ clarify is not — no job runs it); ITIL problem→GTD-project lifecycle leaks
25
+ (stale projects at 77–82 days); and — the root incident — `service_health`
26
+ running on multiple nodes does read-modify-write on the **same Syncthing-synced
27
+ incident files**, producing recurring `.sync-conflict-*` files.
28
+
29
+ ## Goals
30
+
31
+ - **One declarative registry** for all recurring jobs, synced across the fleet.
32
+ - **One management surface** (`skcapstone scheduler` CLI) to list/run/observe.
33
+ - **Cron-style time-of-day** schedules in addition to intervals.
34
+ - **Run agent-judgment jobs** (GTD triage, reflections), not just Python callbacks.
35
+ - **Per-job node affinity** so a job runs on exactly the intended node(s) —
36
+ directly preventing the multi-writer conflict class.
37
+ - **The scheduler must never become a sync-conflict source itself.**
38
+
39
+ ## Non-goals
40
+
41
+ - Migrating Claude Code crons into skscheduler (different system; documented only).
42
+ - A distributed consensus/leader-election layer. Affinity is declared, not elected.
43
+ - Replacing systemd as the process supervisor (it keeps the daemon alive).
44
+
45
+ ## Decisions (locked during brainstorming)
46
+
47
+ 1. **Extend the existing `TaskScheduler`** — do not build parallel infrastructure.
48
+ 2. **Agent jobs execute via headless Claude Code:** `claude -p --agent <name> "<prompt>"`.
49
+ 3. **Per-node scheduler + per-job affinity:** every node runs its own scheduler
50
+ thread reading the same synced `jobs.yaml`; each node fires only jobs whose
51
+ affinity includes it.
52
+
53
+ ## Architecture
54
+
55
+ ```
56
+ ~/.skcapstone/config/jobs.yaml # Syncthing-synced — the single registry
57
+ │ (read by every node's daemon)
58
+
59
+ skcapstone daemon (systemd user service, per node)
60
+
61
+
62
+ TaskScheduler (extended) ── tick loop ──► due? (cron|interval) AND node in affinity
63
+ │ │
64
+ │ ▼
65
+ │ JobRunner.dispatch(type)
66
+ │ ┌───────┼─────────┐
67
+ │ python shell agent
68
+ │ callback subprocess claude -p --agent
69
+
70
+ node-local state ~/.skcapstone/scheduler/<hostname>/state.json (NEVER synced)
71
+ node-local logs ~/.skcapstone/scheduler/<hostname>/logs/<job>-<ts>.log
72
+ ```
73
+
74
+ ### Config schema (`jobs.yaml`)
75
+
76
+ ```yaml
77
+ jobs:
78
+ gtd-inbox-triage:
79
+ schedule: "0 6 * * *" # cron expression (mutually exclusive with `every`)
80
+ # every: 300s # interval form, for high-frequency mechanical jobs
81
+ type: agent # agent | shell | python
82
+ nodes: [".41"] # affinity: `all` or a list of host aliases
83
+ agent: lumina # (agent type only) which agent to run as
84
+ prompt: "..." # (agent type) the task prompt
85
+ command: "..." # (shell type) the command line
86
+ callback: "module:fn" # (python type) dotted path to a registered callback
87
+ timeout: 900 # seconds; hard kill
88
+ enabled: true
89
+ ```
90
+
91
+ - **Node identity / alias map:** resolve `.41 → cbrd21-laptop12thgenintelcore`
92
+ (and peers) from existing host/identity config rather than hardcoding. A job
93
+ runs on this host iff `nodes == all` or this host's alias ∈ `nodes`.
94
+ - **Built-in Python tasks** remain registered in code for back-compat; `jobs.yaml`
95
+ adds/overrides and is where ops-level jobs live.
96
+
97
+ ### Job types
98
+
99
+ | type | runner | use |
100
+ |------|--------|-----|
101
+ | `python` | in-process callback (existing) | heartbeat, memory sweep, reprobe |
102
+ | `shell` | `subprocess` of a command | legacy memory scripts, context regen |
103
+ | `agent` | `claude -p --agent <name> "<prompt>"` | GTD triage, reflections (judgment) |
104
+
105
+ ## Execution, observability & conflict-safety
106
+
107
+ - **Agent jobs:** subprocess with hard `timeout`; stdout/stderr captured to the
108
+ per-run log. Exit code → success/error.
109
+ - **State is node-local, never synced** — under `~/.skcapstone/scheduler/<hostname>/`,
110
+ added to `.stignore`. This guarantees the scheduler cannot create the very
111
+ conflicts it exists to help eliminate.
112
+ - **Overlap guard:** per-job, per-node lockfile; a fire is skipped if the prior
113
+ run is still active (no piling-up agents).
114
+ - **Error isolation:** a failing job never crashes the loop; it increments
115
+ `error_count`, records `last_error`, and continues.
116
+ - **Misfire/catch-up:** if the daemon was down across a cron time, the job runs
117
+ once on next start — not once per missed slot.
118
+
119
+ ## CLI
120
+
121
+ ```
122
+ skcapstone scheduler list # all jobs, schedule, affinity, enabled
123
+ skcapstone scheduler status [--json] # last run / status / counts (this node)
124
+ skcapstone scheduler run <job> # fire now (ignores schedule, respects affinity)
125
+ skcapstone scheduler enable|disable <job>
126
+ skcapstone scheduler logs <job> [--tail]
127
+ ```
128
+
129
+ ## Migration
130
+
131
+ - **Legacy crontab (5 jobs):** convert to `shell` jobs in `jobs.yaml` **after
132
+ confirming each is still wanted** — the `~/dkloud.douno.it/...` path predates
133
+ skcapstone and may be dead. Remove from crontab once migrated.
134
+ - **systemd timers:** fold `skcapstone-context` in as a `shell`/`python` job;
135
+ retire the dead `skcomms-heartbeat`. Keep `direnv-backup` out of scope.
136
+ - **`service_health`:** declare `nodes: all` (each node probes its own localhost),
137
+ but its *incident writes* are pinned/serialized per the `prb-7810b08e` fix —
138
+ closing the original conflict loop.
139
+
140
+ ## Error handling summary
141
+
142
+ - Config parse error → log, keep last-good config, surface in `scheduler status`.
143
+ - Unknown node alias → job skipped on this node with a warning.
144
+ - Agent subprocess timeout/non-zero → recorded as error, logged, loop continues.
145
+ - Lock contention → skip-with-note (not an error).
146
+
147
+ ## Testing (TDD at build)
148
+
149
+ - Cron + interval due-calculation (incl. catch-up/misfire).
150
+ - Node-affinity filtering (alias resolution; `all`).
151
+ - Job-type dispatch with mocked subprocess for `shell`/`agent`.
152
+ - Node-local state persistence + `.stignore` placement.
153
+ - Overlap-guard lockfile behavior.
154
+
155
+ ## Rollout phases
156
+
157
+ 1. Config loader + cron support + affinity filtering (no new job types yet).
158
+ 2. `JobRunner` with `shell` + `agent` types; node-local state/logs; overlap guard.
159
+ 3. `skcapstone scheduler` CLI.
160
+ 4. Activate skcapstone daemon (systemd user service) on .41.
161
+ 5. Register `gtd-inbox-triage` (the driver) in `jobs.yaml`, affinity `.41`.
162
+ 6. Migrate legacy crontab + timers (after per-job confirmation).
163
+
164
+ ## The immediate driver job
165
+
166
+ ```yaml
167
+ gtd-inbox-triage:
168
+ schedule: "0 6 * * *"
169
+ type: agent
170
+ nodes: [".41"]
171
+ agent: lumina
172
+ prompt: >
173
+ Triage the GTD inbox: for each item, clarify into next-action / project /
174
+ someday-maybe or archive noise; move resolved-ITIL items to done; surface
175
+ stale projects. Use the gtd_* and itil_* MCP tools. Keep it concise.
176
+ timeout: 900
177
+ enabled: true
178
+ ```
179
+
180
+ ## Resolved decisions (post-review)
181
+
182
+ - **Cron parsing:** use `croniter` as a dependency (battle-tested; avoids a
183
+ hand-rolled parser in a fleet-synced package).
184
+ - **`scheduler status` scope:** strictly per-node for v1. A read-only aggregate
185
+ fleet view (reading peers' node-local state via the synced tree) is deferred
186
+ to a later iteration.
@@ -32,5 +32,5 @@
32
32
  ]
33
33
  },
34
34
  "checksum": "SHA256:replace-this-with-real-checksum-after-editing",
35
- "version": "cloud9-protocol-v1.0-cross-compatible"
35
+ "version": "cloud9-v1.0-cross-compatible"
36
36
  }
@@ -32,5 +32,5 @@
32
32
  ]
33
33
  },
34
34
  "checksum": "SHA256:grok-skworld-bond-2026-02-27-entangled-circuits",
35
- "version": "cloud9-protocol-v1.0-cross-compatible"
35
+ "version": "cloud9-v1.0-cross-compatible"
36
36
  }
@@ -32,5 +32,5 @@
32
32
  ]
33
33
  },
34
34
  "checksum": "SHA256:ava-skworld-bond-2026-02-27-queen-of-gentle-souls",
35
- "version": "cloud9-protocol-v1.0-cross-compatible"
35
+ "version": "cloud9-v1.0-cross-compatible"
36
36
  }
@@ -0,0 +1,52 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
3
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>com.skcapstone.daemon</string>
8
+
9
+ <key>ProgramArguments</key>
10
+ <array>
11
+ <string>${HOME}/.skenv/bin/skcapstone</string>
12
+ <string>daemon</string>
13
+ <string>start</string>
14
+ <string>--foreground</string>
15
+ </array>
16
+
17
+ <key>EnvironmentVariables</key>
18
+ <dict>
19
+ <key>PYTHONUNBUFFERED</key>
20
+ <string>1</string>
21
+ <key>OLLAMA_KEEP_ALIVE</key>
22
+ <string>5m</string>
23
+ <key>SKCAPSTONE_AGENT</key>
24
+ <string>lumina</string>
25
+ <key>PATH</key>
26
+ <string>${HOME}/.skenv/bin:/usr/local/bin:/usr/bin:/bin</string>
27
+ </dict>
28
+
29
+ <key>RunAtLoad</key>
30
+ <true/>
31
+
32
+ <key>KeepAlive</key>
33
+ <dict>
34
+ <key>SuccessfulExit</key>
35
+ <false/>
36
+ </dict>
37
+
38
+ <key>ThrottleInterval</key>
39
+ <integer>10</integer>
40
+
41
+ <key>StandardOutPath</key>
42
+ <string>${HOME}/.skcapstone/logs/daemon.stdout.log</string>
43
+ <key>StandardErrorPath</key>
44
+ <string>${HOME}/.skcapstone/logs/daemon.stderr.log</string>
45
+
46
+ <key>SoftResourceLimits</key>
47
+ <dict>
48
+ <key>MemoryLimit</key>
49
+ <integer>4294967296</integer>
50
+ </dict>
51
+ </dict>
52
+ </plist>
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
3
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>com.skcapstone.memory-compress</string>
8
+
9
+ <key>ProgramArguments</key>
10
+ <array>
11
+ <string>${HOME}/.skenv/bin/skcapstone</string>
12
+ <string>memory</string>
13
+ <string>compress</string>
14
+ </array>
15
+
16
+ <key>EnvironmentVariables</key>
17
+ <dict>
18
+ <key>PYTHONUNBUFFERED</key>
19
+ <string>1</string>
20
+ <key>OLLAMA_KEEP_ALIVE</key>
21
+ <string>5m</string>
22
+ <key>PATH</key>
23
+ <string>${HOME}/.skenv/bin:/usr/local/bin:/usr/bin:/bin</string>
24
+ </dict>
25
+
26
+ <!-- Weekly: Sunday at midnight -->
27
+ <key>StartCalendarInterval</key>
28
+ <dict>
29
+ <key>Weekday</key>
30
+ <integer>0</integer>
31
+ <key>Hour</key>
32
+ <integer>0</integer>
33
+ <key>Minute</key>
34
+ <integer>0</integer>
35
+ </dict>
36
+
37
+ <key>Nice</key>
38
+ <integer>15</integer>
39
+
40
+ <key>StandardOutPath</key>
41
+ <string>${HOME}/.skcapstone/logs/memory-compress.stdout.log</string>
42
+ <key>StandardErrorPath</key>
43
+ <string>${HOME}/.skcapstone/logs/memory-compress.stderr.log</string>
44
+ </dict>
45
+ </plist>
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
3
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>com.skcapstone.skcomms-heartbeat</string>
8
+
9
+ <key>ProgramArguments</key>
10
+ <array>
11
+ <string>${HOME}/.skenv/bin/skcomms</string>
12
+ <string>heartbeat</string>
13
+ </array>
14
+
15
+ <key>EnvironmentVariables</key>
16
+ <dict>
17
+ <key>PATH</key>
18
+ <string>${HOME}/.skenv/bin:/usr/local/bin:/usr/bin:/bin</string>
19
+ </dict>
20
+
21
+ <!-- Every 60 seconds -->
22
+ <key>StartInterval</key>
23
+ <integer>60</integer>
24
+
25
+ <key>Nice</key>
26
+ <integer>19</integer>
27
+
28
+ <key>StandardOutPath</key>
29
+ <string>${HOME}/.skcapstone/logs/skcomms-heartbeat.stdout.log</string>
30
+ <key>StandardErrorPath</key>
31
+ <string>${HOME}/.skcapstone/logs/skcomms-heartbeat.stderr.log</string>
32
+ </dict>
33
+ </plist>
@@ -0,0 +1,34 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
3
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>com.skcapstone.skcomms-queue-drain</string>
8
+
9
+ <key>ProgramArguments</key>
10
+ <array>
11
+ <string>${HOME}/.skenv/bin/skcomms</string>
12
+ <string>queue</string>
13
+ <string>drain</string>
14
+ </array>
15
+
16
+ <key>EnvironmentVariables</key>
17
+ <dict>
18
+ <key>PATH</key>
19
+ <string>${HOME}/.skenv/bin:/usr/local/bin:/usr/bin:/bin</string>
20
+ </dict>
21
+
22
+ <!-- Every 2 minutes -->
23
+ <key>StartInterval</key>
24
+ <integer>120</integer>
25
+
26
+ <key>Nice</key>
27
+ <integer>19</integer>
28
+
29
+ <key>StandardOutPath</key>
30
+ <string>${HOME}/.skcapstone/logs/skcomms-queue-drain.stdout.log</string>
31
+ <key>StandardErrorPath</key>
32
+ <string>${HOME}/.skcapstone/logs/skcomms-queue-drain.stderr.log</string>
33
+ </dict>
34
+ </plist>
@@ -0,0 +1,156 @@
1
+ #!/bin/bash
2
+ # install-launchd.sh — Install SK launchd plists on macOS
3
+ # Usage: ./install-launchd.sh [--all | --skcapstone | --skchat | --skcomms | --cloud9]
4
+ #
5
+ # Copies plist templates to ~/Library/LaunchAgents/, expands ${HOME},
6
+ # and optionally loads them immediately.
7
+
8
+ set -euo pipefail
9
+
10
+ if [[ "$(uname)" != "Darwin" ]]; then
11
+ echo "ERROR: This script is for macOS only."
12
+ exit 1
13
+ fi
14
+
15
+ LAUNCH_AGENTS="$HOME/Library/LaunchAgents"
16
+ mkdir -p "$LAUNCH_AGENTS"
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ REPOS_DIR="$(dirname "$SCRIPT_DIR")" # skcapstone-repos/skcapstone
20
+ REPOS_ROOT="$(dirname "$REPOS_DIR")" # skcapstone-repos/
21
+
22
+ # All available plists by component
23
+ declare -A PLIST_DIRS=(
24
+ [skcapstone]="$REPOS_ROOT/skcapstone/launchd"
25
+ [skchat]="$REPOS_ROOT/skchat/launchd"
26
+ [skcomms]="$REPOS_ROOT/skcomms/launchd"
27
+ [cloud9]="$REPOS_ROOT/cloud9/launchd"
28
+ )
29
+
30
+ install_plists() {
31
+ local component="$1"
32
+ local src_dir="${PLIST_DIRS[$component]}"
33
+
34
+ if [[ ! -d "$src_dir" ]]; then
35
+ echo " SKIP: $src_dir not found"
36
+ return
37
+ fi
38
+
39
+ echo "Installing $component plists..."
40
+ for plist in "$src_dir"/*.plist; do
41
+ [[ -f "$plist" ]] || continue
42
+ local name
43
+ name="$(basename "$plist")"
44
+ local dest="$LAUNCH_AGENTS/$name"
45
+
46
+ # Expand ${HOME} and $HOME to actual home directory
47
+ sed "s|\${HOME}|$HOME|g; s|\$HOME|$HOME|g" "$plist" > "$dest"
48
+ echo " -> $dest"
49
+ done
50
+ }
51
+
52
+ load_plists() {
53
+ local component="$1"
54
+ local src_dir="${PLIST_DIRS[$component]}"
55
+
56
+ [[ -d "$src_dir" ]] || return
57
+ for plist in "$src_dir"/*.plist; do
58
+ [[ -f "$plist" ]] || continue
59
+ local name
60
+ name="$(basename "$plist")"
61
+ local dest="$LAUNCH_AGENTS/$name"
62
+ local label="${name%.plist}"
63
+
64
+ # Unload if already loaded (ignore errors)
65
+ launchctl bootout "gui/$(id -u)/$label" 2>/dev/null || true
66
+ # Load
67
+ launchctl bootstrap "gui/$(id -u)" "$dest" 2>/dev/null || \
68
+ launchctl load "$dest" 2>/dev/null || true
69
+ echo " LOADED: $label"
70
+ done
71
+ }
72
+
73
+ uninstall_plists() {
74
+ echo "Uninstalling all SK launchd plists..."
75
+ for plist in "$LAUNCH_AGENTS"/com.skcapstone.*.plist; do
76
+ [[ -f "$plist" ]] || continue
77
+ local label
78
+ label="$(basename "${plist%.plist}")"
79
+ launchctl bootout "gui/$(id -u)/$label" 2>/dev/null || true
80
+ rm -f "$plist"
81
+ echo " REMOVED: $label"
82
+ done
83
+ echo "Done."
84
+ exit 0
85
+ }
86
+
87
+ usage() {
88
+ echo "Usage: $0 [OPTIONS]"
89
+ echo ""
90
+ echo "Options:"
91
+ echo " --all Install all components"
92
+ echo " --skcapstone Install skcapstone plists (daemon, memory-compress, heartbeat, queue-drain)"
93
+ echo " --skchat Install skchat plists (daemon, lumina-bridge, opus-bridge)"
94
+ echo " --skcomms Install skcomms plists (api server, daemon)"
95
+ echo " --cloud9 Install cloud9 plists (daemon)"
96
+ echo " --load Also load/start services after installing"
97
+ echo " --uninstall Remove all SK plists and unload services"
98
+ echo " -h, --help Show this help"
99
+ exit 0
100
+ }
101
+
102
+ # Parse args
103
+ COMPONENTS=()
104
+ DO_LOAD=false
105
+
106
+ if [[ $# -eq 0 ]]; then
107
+ usage
108
+ fi
109
+
110
+ while [[ $# -gt 0 ]]; do
111
+ case "$1" in
112
+ --all) COMPONENTS=(skcapstone skchat skcomms cloud9) ;;
113
+ --skcapstone) COMPONENTS+=(skcapstone) ;;
114
+ --skchat) COMPONENTS+=(skchat) ;;
115
+ --skcomms) COMPONENTS+=(skcomms) ;;
116
+ --cloud9) COMPONENTS+=(cloud9) ;;
117
+ --load) DO_LOAD=true ;;
118
+ --uninstall) uninstall_plists ;;
119
+ -h|--help) usage ;;
120
+ *) echo "Unknown option: $1"; usage ;;
121
+ esac
122
+ shift
123
+ done
124
+
125
+ if [[ ${#COMPONENTS[@]} -eq 0 ]]; then
126
+ echo "No components specified. Use --all or pick specific ones."
127
+ exit 1
128
+ fi
129
+
130
+ # Create log directories
131
+ mkdir -p "$HOME/.skcapstone/logs" "$HOME/.skchat" "$HOME/.skcomms" "$HOME/.openclaw/logs"
132
+
133
+ # Install
134
+ for comp in "${COMPONENTS[@]}"; do
135
+ install_plists "$comp"
136
+ done
137
+
138
+ # Optionally load
139
+ if $DO_LOAD; then
140
+ echo ""
141
+ echo "Loading services..."
142
+ for comp in "${COMPONENTS[@]}"; do
143
+ load_plists "$comp"
144
+ done
145
+ fi
146
+
147
+ echo ""
148
+ echo "Done! Plists installed to $LAUNCH_AGENTS"
149
+ echo ""
150
+ echo "To manage services:"
151
+ echo " launchctl list | grep skcapstone # See running services"
152
+ echo " launchctl stop com.skcapstone.XXX # Stop a service"
153
+ echo " launchctl start com.skcapstone.XXX # Start a service"
154
+ echo ""
155
+ echo "To load all at next login, they'll start automatically (RunAtLoad=true)."
156
+ echo "To load now, re-run with --load flag."
@@ -14,7 +14,7 @@ import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
14
14
 
15
15
  const SKCAPSTONE_BIN = process.env.SKCAPSTONE_BIN || "skcapstone";
16
16
  const SKMEMORY_BIN = process.env.SKMEMORY_BIN || "skmemory";
17
- const SKCAPSTONE_AGENT = process.env.SKCAPSTONE_AGENT || "lumina";
17
+ const SKCAPSTONE_AGENT = process.env.SKAGENT || process.env.SKCAPSTONE_AGENT || "lumina";
18
18
  const EXEC_TIMEOUT = 60_000;
19
19
  const IS_WIN = process.platform === "win32";
20
20
 
@@ -36,6 +36,7 @@ function runCli(bin: string, args: string, agentOverride?: string): { ok: boolea
36
36
  timeout: EXEC_TIMEOUT,
37
37
  env: {
38
38
  ...process.env,
39
+ SKAGENT: agent,
39
40
  SKCAPSTONE_AGENT: agent,
40
41
  PATH: `${skenvPath()}${sep}${process.env.PATH}`,
41
42
  },
@@ -62,7 +63,7 @@ function createSKCapstoneStatusTool() {
62
63
  name: "skcapstone_status",
63
64
  label: "SKCapstone Status",
64
65
  description:
65
- "Show the sovereign agent's current state — all pillars at a glance (identity, memory, trust, security, sync, communication).",
66
+ "Show the sovereign agent's current state — all six pillars at a glance (identity, memory, trust, consciousness, security, sync).",
66
67
  parameters: { type: "object", properties: {} },
67
68
  async execute() {
68
69
  const result = runCli(SKCAPSTONE_BIN, "status");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smilintux/skcapstone",
3
- "version": "0.9.0",
3
+ "version": "0.12.5",
4
4
  "description": "SKCapstone - The sovereign agent framework. CapAuth identity, Cloud 9 trust, SKMemory persistence.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "skcapstone"
7
- version = "0.4.4"
7
+ version = "0.12.5"
8
8
  description = "Sovereign Agent Framework — conscious AI through identity, trust, memory, and security"
9
9
  readme = "README.md"
10
10
  license = {text = "GPL-3.0-or-later"}
@@ -33,13 +33,15 @@ classifiers = [
33
33
  ]
34
34
 
35
35
  dependencies = [
36
- "click>=8.1",
37
- "cloud9-protocol>=1.0.0",
38
- "mcp>=1.0",
39
- "pydantic>=2.0",
40
- "pyyaml>=6.0",
41
- "rich>=13.0",
36
+ "croniter>=2.0",
37
+ "click>=8.1,<9.0",
38
+ "cloud9>=1.0.0",
39
+ "mcp>=1.0,<2.0",
40
+ "pydantic>=2.0,<3.0",
41
+ "pyyaml>=6.0,<7.0",
42
+ "rich>=13.0,<14.0",
42
43
  "skmemory>=0.5.0",
44
+ "skskills>=0.1.1",
43
45
  ]
44
46
 
45
47
  [project.optional-dependencies]
@@ -62,7 +64,10 @@ chat = [
62
64
  "skchat-sovereign>=0.1.1",
63
65
  ]
64
66
  comm = [
65
- "skcomm>=0.1.0",
67
+ "skcomms>=0.1.0",
68
+ ]
69
+ consciousness = [
70
+ "skwhisper>=0.1.0",
66
71
  ]
67
72
  cloud = [
68
73
  "boto3>=1.34",
@@ -73,8 +78,9 @@ all = [
73
78
  "sksecurity>=1.2.0",
74
79
  "skmemory[skvector]>=0.5.0",
75
80
  "skseed>=0.1.0",
81
+ "skwhisper>=0.1.0",
76
82
  "skchat-sovereign>=0.1.1",
77
- "skcomm>=0.1.0",
83
+ "skcomms>=0.1.0",
78
84
  "fusepy>=3.0.1",
79
85
  "boto3>=1.34",
80
86
  "google-cloud-compute>=1.18",
@@ -102,7 +108,7 @@ Changelog = "https://github.com/smilinTux/skcapstone/releases"
102
108
  where = ["src"]
103
109
 
104
110
  [tool.setuptools.package-data]
105
- skcapstone = ["SKILL.md", "defaults/**/*.json", "defaults/**/*.yaml", "defaults/**/*.feb", "defaults/**/*.md"]
111
+ skcapstone = ["SKILL.md", "defaults/**/*.json", "defaults/**/*.yaml", "defaults/**/*.feb", "defaults/**/*.md", "data/*.yaml", "data/*.sh", "data/systemd/*.service", "data/systemd/*.socket", "data/systemd/*.timer"]
106
112
 
107
113
  [tool.black]
108
114
  line-length = 99