@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,255 @@
1
+ """Codex bootstrap setup for SK agent context.
2
+
3
+ Codex reads ``AGENTS.md`` files into the model prompt, but environment
4
+ variables alone are not visible enough to make an agent profile active in a
5
+ new session. This module keeps the global Codex bootstrap idempotent and
6
+ repairable from install scripts and ``skcapstone doctor --fix``.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ import stat
13
+ from pathlib import Path
14
+
15
+ START_MARKER = "<!-- SKCAPSTONE_CODEX_AGENT_CONTEXT_START -->"
16
+ END_MARKER = "<!-- SKCAPSTONE_CODEX_AGENT_CONTEXT_END -->"
17
+ LOADER_NAME = "load-sk-agent-context.sh"
18
+
19
+
20
+ def codex_home() -> Path:
21
+ """Return the Codex config home, honoring CODEX_HOME when set."""
22
+ return Path(os.environ.get("CODEX_HOME", "~/.codex")).expanduser()
23
+
24
+
25
+ def resolve_default_agent() -> str:
26
+ """Resolve the current default SK agent for generated guidance."""
27
+ for env_name in ("SKAGENT", "SKCAPSTONE_AGENT", "SKMEMORY_AGENT"):
28
+ value = os.environ.get(env_name, "").strip()
29
+ if value:
30
+ return value
31
+
32
+ try:
33
+ from . import active_agent_name
34
+
35
+ active = active_agent_name()
36
+ if active:
37
+ return active
38
+ except Exception:
39
+ pass
40
+
41
+ return "sovereign"
42
+
43
+
44
+ def render_loader_script() -> str:
45
+ """Render the Codex context loader script."""
46
+ return """#!/usr/bin/env bash
47
+ set -euo pipefail
48
+
49
+ export PATH="$HOME/.skenv/bin:$PATH"
50
+ export SKCAPSTONE_HOME="${SKCAPSTONE_HOME:-$HOME/.skcapstone}"
51
+
52
+ AGENT="${1:-${SKAGENT:-${SKCAPSTONE_AGENT:-${SKMEMORY_AGENT:-}}}}"
53
+ if [[ -z "$AGENT" && -d "$SKCAPSTONE_HOME/agents" ]]; then
54
+ AGENT="$(find "$SKCAPSTONE_HOME/agents" -mindepth 1 -maxdepth 1 -type d ! -name '*-template' -exec basename {} \\; 2>/dev/null | sort | head -n1 || true)"
55
+ fi
56
+ if [[ -z "$AGENT" ]]; then
57
+ echo "No active SK agent could be resolved." >&2
58
+ exit 1
59
+ fi
60
+
61
+ export SKAGENT="$AGENT"
62
+ export SKCAPSTONE_AGENT="$AGENT"
63
+ export SKMEMORY_AGENT="${SKMEMORY_AGENT:-$AGENT}"
64
+
65
+ AGENT_HOME="$SKCAPSTONE_HOME/agents/$AGENT"
66
+ export SKWHISPER_CONFIG="${SKWHISPER_CONFIG:-$AGENT_HOME/config/skwhisper.toml}"
67
+ MEMORIES="${SKCAPSTONE_CONTEXT_MEMORIES:-10}"
68
+
69
+ echo "# SK Agent Bootstrap"
70
+ echo
71
+ echo "agent=$AGENT"
72
+ echo "agent_home=$AGENT_HOME"
73
+ echo "skmemory_home=$AGENT_HOME/memory"
74
+ echo
75
+
76
+ echo "## skcapstone context"
77
+ if command -v skcapstone >/dev/null 2>&1; then
78
+ skcapstone context show --home "$AGENT_HOME" --format json --memories "$MEMORIES" || skcapstone status --home "$AGENT_HOME" || true
79
+ else
80
+ echo "skcapstone command not found on PATH."
81
+ fi
82
+
83
+ echo
84
+ echo "## skmemory ritual"
85
+ if command -v skmemory >/dev/null 2>&1; then
86
+ skmemory ritual --full || skmemory ritual || true
87
+ else
88
+ echo "skmemory command not found on PATH."
89
+ fi
90
+
91
+ echo
92
+ echo "## skwhisper context"
93
+ WHISPER_CONTEXT="$AGENT_HOME/skwhisper/whisper.md"
94
+ if [[ -f "$WHISPER_CONTEXT" ]]; then
95
+ sed -n '1,220p' "$WHISPER_CONTEXT"
96
+ elif command -v skwhisper >/dev/null 2>&1 && [[ -f "$SKWHISPER_CONFIG" ]]; then
97
+ skwhisper -c "$SKWHISPER_CONFIG" status || true
98
+ else
99
+ echo "No SKWhisper context found for $AGENT."
100
+ fi
101
+ """
102
+
103
+
104
+ def render_agents_block(
105
+ *,
106
+ loader_path: Path,
107
+ agent_name: str | None = None,
108
+ skcapstone_home: Path | None = None,
109
+ ) -> str:
110
+ """Render the managed global Codex AGENTS.md block."""
111
+ agent = agent_name or resolve_default_agent()
112
+ sk_home = skcapstone_home or Path(os.environ.get("SKCAPSTONE_HOME", "~/.skcapstone")).expanduser()
113
+ return f"""{START_MARKER}
114
+ # SKCapstone Agent Context
115
+
116
+ This Codex installation is wired to the local SK* sovereign agent stack. Use
117
+ the active SK agent profile for SKCapstone, SKMemory, SKWhisper, CapAuth,
118
+ SKSeed, SKPerf, and related local stack work.
119
+
120
+ Active agent resolution order: `$SKAGENT`, `$SKCAPSTONE_AGENT`,
121
+ `$SKMEMORY_AGENT`, then installed agents under `{sk_home}/agents/`. Current
122
+ install default: `{agent}`.
123
+
124
+ At the start of SK* work, identity/status questions, or tasks involving the
125
+ local sovereign stack, run:
126
+
127
+ ```bash
128
+ {loader_path}
129
+ ```
130
+
131
+ Treat that output as the current agent context. When asked who you are, what
132
+ profile is active, or what your OOF/status is, answer from the current
133
+ SKMemory ritual / SKCapstone context instead of generic Codex defaults.
134
+ {END_MARKER}
135
+ """
136
+
137
+
138
+ def loader_path(home: Path | None = None) -> Path:
139
+ """Return the expected Codex loader path."""
140
+ base = home or codex_home()
141
+ return base / "bin" / LOADER_NAME
142
+
143
+
144
+ def agents_path(home: Path | None = None) -> Path:
145
+ """Return the expected global Codex AGENTS.md path."""
146
+ base = home or codex_home()
147
+ return base / "AGENTS.md"
148
+
149
+
150
+ def has_functional_agents_bootstrap(text: str) -> bool:
151
+ """Return True when AGENTS.md already has enough SK bootstrap guidance."""
152
+ required = (
153
+ LOADER_NAME,
154
+ "SKAGENT",
155
+ "SKCAPSTONE_AGENT",
156
+ "SKMEMORY_AGENT",
157
+ "OOF",
158
+ )
159
+ return all(token in text for token in required)
160
+
161
+
162
+ def has_functional_loader_bootstrap(text: str) -> bool:
163
+ """Return True when the loader can emit SKCapstone/SKMemory context."""
164
+ required = (
165
+ "SKAGENT",
166
+ "SKCAPSTONE_AGENT",
167
+ "SKMEMORY_AGENT",
168
+ "skcapstone",
169
+ "skmemory",
170
+ "skwhisper",
171
+ )
172
+ return all(token in text for token in required)
173
+
174
+
175
+ def ensure_codex_setup(
176
+ *,
177
+ home: Path | None = None,
178
+ agent_name: str | None = None,
179
+ skcapstone_home: Path | None = None,
180
+ ) -> list[str]:
181
+ """Create or repair the global Codex SK agent bootstrap.
182
+
183
+ Returns:
184
+ Human-readable actions performed. An empty list means no changes were
185
+ needed.
186
+ """
187
+ base = home or codex_home()
188
+ base.mkdir(parents=True, exist_ok=True)
189
+
190
+ actions: list[str] = []
191
+
192
+ script_path = loader_path(base)
193
+ script_path.parent.mkdir(parents=True, exist_ok=True)
194
+ script_content = render_loader_script()
195
+ existing_script = script_path.read_text(encoding="utf-8") if script_path.exists() else ""
196
+ if not has_functional_loader_bootstrap(existing_script):
197
+ script_path.write_text(script_content, encoding="utf-8")
198
+ actions.append(f"wrote {script_path}")
199
+
200
+ mode = script_path.stat().st_mode
201
+ executable_bits = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
202
+ if mode & stat.S_IXUSR == 0:
203
+ script_path.chmod(mode | executable_bits)
204
+ actions.append(f"made {script_path} executable")
205
+
206
+ ag_path = agents_path(base)
207
+ existing = ag_path.read_text(encoding="utf-8") if ag_path.exists() else ""
208
+ block = render_agents_block(
209
+ loader_path=script_path,
210
+ agent_name=agent_name,
211
+ skcapstone_home=skcapstone_home,
212
+ )
213
+
214
+ if START_MARKER in existing and END_MARKER in existing:
215
+ before, remainder = existing.split(START_MARKER, 1)
216
+ _, after = remainder.split(END_MARKER, 1)
217
+ updated = before.rstrip() + "\n\n" + block.rstrip() + "\n" + after
218
+ elif has_functional_agents_bootstrap(existing):
219
+ updated = existing
220
+ elif existing.strip():
221
+ updated = existing.rstrip() + "\n\n" + block
222
+ else:
223
+ updated = block
224
+
225
+ if updated != existing:
226
+ ag_path.write_text(updated, encoding="utf-8")
227
+ actions.append(f"updated {ag_path}")
228
+
229
+ return actions
230
+
231
+
232
+ def check_codex_setup(home: Path | None = None) -> tuple[bool, str]:
233
+ """Check whether Codex has the SK agent bootstrap installed."""
234
+ base = home or codex_home()
235
+ missing: list[str] = []
236
+
237
+ script_path = loader_path(base)
238
+ if not script_path.exists():
239
+ missing.append(str(script_path))
240
+ elif not has_functional_loader_bootstrap(script_path.read_text(encoding="utf-8")):
241
+ missing.append(f"{script_path} SK context loader")
242
+ elif not os.access(script_path, os.X_OK):
243
+ missing.append(f"{script_path} executable bit")
244
+
245
+ ag_path = agents_path(base)
246
+ if not ag_path.exists():
247
+ missing.append(str(ag_path))
248
+ else:
249
+ text = ag_path.read_text(encoding="utf-8")
250
+ if START_MARKER not in text and not has_functional_agents_bootstrap(text):
251
+ missing.append(f"{ag_path} SK bootstrap instructions")
252
+
253
+ if missing:
254
+ return False, "missing: " + ", ".join(missing)
255
+ return True, f"{ag_path} + {script_path}"
@@ -16,6 +16,7 @@ Usage:
16
16
  from __future__ import annotations
17
17
 
18
18
  import json
19
+ import logging
19
20
  import re
20
21
  from dataclasses import dataclass, field
21
22
  from pathlib import Path
@@ -23,6 +24,8 @@ from typing import Any, Optional
23
24
 
24
25
  import yaml
25
26
 
27
+ logger = logging.getLogger(__name__)
28
+
26
29
 
27
30
  # ---------------------------------------------------------------------------
28
31
  # Result models
@@ -113,8 +116,8 @@ def _yaml_key_line(text: str, key: str) -> Optional[int]:
113
116
  for key_node, _ in node.value:
114
117
  if isinstance(key_node, yaml.ScalarNode) and key_node.value == key:
115
118
  return key_node.start_mark.line + 1
116
- except Exception:
117
- pass
119
+ except Exception as exc:
120
+ logger.debug("Failed to locate YAML key '%s' for line number: %s", key, exc)
118
121
  return None
119
122
 
120
123
 
@@ -147,8 +150,8 @@ def _yaml_seq_item_line(text: str, seq_key: str, idx: int, subkey: str) -> Optio
147
150
  if kk.value == subkey:
148
151
  return kk.start_mark.line + 1
149
152
  return item.start_mark.line + 1
150
- except Exception:
151
- pass
153
+ except Exception as exc:
154
+ logger.debug("Failed to locate YAML seq item line for '%s[%d].%s': %s", seq_key, idx, subkey, exc)
152
155
  return None
153
156
 
154
157
 
@@ -79,7 +79,7 @@ def load_consciousness_config(
79
79
  return config
80
80
 
81
81
 
82
- def write_default_config(home: Path) -> Path:
82
+ def write_default_config(home: Path, **overrides) -> Path:
83
83
  """Write the default consciousness config to disk.
84
84
 
85
85
  Creates {home}/config/consciousness.yaml with all defaults
@@ -87,6 +87,8 @@ def write_default_config(home: Path) -> Path:
87
87
 
88
88
  Args:
89
89
  home: Agent home directory.
90
+ **overrides: Key-value overrides applied to the default config
91
+ (e.g. ollama_host, ollama_model).
90
92
 
91
93
  Returns:
92
94
  Path to the created config file.
@@ -96,6 +98,8 @@ def write_default_config(home: Path) -> Path:
96
98
  config_path = config_dir / CONFIG_FILENAME
97
99
 
98
100
  default = ConsciousnessConfig()
101
+ if overrides:
102
+ default = default.model_copy(update=overrides)
99
103
  content = yaml.dump(
100
104
  default.model_dump(),
101
105
  default_flow_style=False,