@zerwiz/ymir 0.1.3 → 0.1.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 (850) hide show
  1. package/.agents/README.md +291 -0
  2. package/.agents/agents/bragi-marketer.md +111 -0
  3. package/.agents/agents/brokk.md +352 -0
  4. package/.agents/agents/forseti-reviewer.md +93 -0
  5. package/.agents/agents/frigg-consent.md +77 -0
  6. package/.agents/agents/groa-update.md +77 -0
  7. package/.agents/agents/hnoss-designer.md +69 -0
  8. package/.agents/agents/huginn-researcher.md +99 -0
  9. package/.agents/agents/jord-projects.md +78 -0
  10. package/.agents/agents/kvasir-scout.md +91 -0
  11. package/.agents/agents/mimir-planner.md +92 -0
  12. package/.agents/agents/muninn-stow.md +77 -0
  13. package/.agents/agents/saga-bearings.md +78 -0
  14. package/.agents/agents/sindri-developer.md +114 -0
  15. package/.agents/agents/snotra-documenter.md +105 -0
  16. package/.agents/agents/syn-recovery.md +78 -0
  17. package/.agents/agents/tyr-check.md +78 -0
  18. package/.agents/agents/urdh-hold.md +77 -0
  19. package/.agents/agents/volundr-smith.md +80 -0
  20. package/.agents/agents/vor-diagnostics.md +77 -0
  21. package/.agents/assets/agents/naming.md +50 -0
  22. package/.agents/assets/agents/registry.md +93 -0
  23. package/.agents/assets/agents/runtime.md +36 -0
  24. package/.agents/assets/agents/toon-tasks-cli.md +42 -0
  25. package/.agents/assets/templates/company_entity.template.md +37 -0
  26. package/.agents/backend/backends/cmux.sh +649 -0
  27. package/.agents/backend/backends/herdr-eventwait.py +157 -0
  28. package/.agents/backend/backends/herdr-workspace-move.py +114 -0
  29. package/.agents/backend/backends/herdr.sh +3386 -0
  30. package/.agents/backend/backends/orca.sh +290 -0
  31. package/.agents/backend/backends/tmux.sh +357 -0
  32. package/.agents/backend/backends/zellij.sh +700 -0
  33. package/.agents/backend/fm-afk-launch.sh +654 -0
  34. package/.agents/backend/fm-afk-return.sh +241 -0
  35. package/.agents/backend/fm-afk-start.sh +172 -0
  36. package/.agents/backend/fm-arm-command-policy.mjs +960 -0
  37. package/.agents/backend/fm-arm-pretool-check.sh +200 -0
  38. package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
  39. package/.agents/backend/fm-backend.sh +981 -0
  40. package/.agents/backend/fm-backlog-handoff.sh +909 -0
  41. package/.agents/backend/fm-backlog-receive.sh +187 -0
  42. package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
  43. package/.agents/backend/fm-bearings-board.sh +204 -0
  44. package/.agents/backend/fm-bearings-snapshot.sh +546 -0
  45. package/.agents/backend/fm-bootstrap.sh +1568 -0
  46. package/.agents/backend/fm-branch-outcome.sh +203 -0
  47. package/.agents/backend/fm-branch-prompt.sh +101 -0
  48. package/.agents/backend/fm-brief.sh +452 -0
  49. package/.agents/backend/fm-busy-event.sh +234 -0
  50. package/.agents/backend/fm-busy-lib.sh +986 -0
  51. package/.agents/backend/fm-captain-hold.sh +1001 -0
  52. package/.agents/backend/fm-cd-command-policy.mjs +153 -0
  53. package/.agents/backend/fm-cd-pretool-check.sh +190 -0
  54. package/.agents/backend/fm-check-lib.sh +74 -0
  55. package/.agents/backend/fm-check-register.sh +42 -0
  56. package/.agents/backend/fm-check-unregister.sh +52 -0
  57. package/.agents/backend/fm-classify-lib.sh +1770 -0
  58. package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
  59. package/.agents/backend/fm-composer-lib.sh +1416 -0
  60. package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
  61. package/.agents/backend/fm-config-push.sh +254 -0
  62. package/.agents/backend/fm-control-lib.sh +251 -0
  63. package/.agents/backend/fm-control.sh +878 -0
  64. package/.agents/backend/fm-crew-state.sh +625 -0
  65. package/.agents/backend/fm-cursor-lib.sh +243 -0
  66. package/.agents/backend/fm-decision-hold.sh +232 -0
  67. package/.agents/backend/fm-doc-audience-check.sh +269 -0
  68. package/.agents/backend/fm-dod-lib.sh +67 -0
  69. package/.agents/backend/fm-ensure-agents-md.sh +253 -0
  70. package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
  71. package/.agents/backend/fm-extension.mjs +2577 -0
  72. package/.agents/backend/fm-extension.sh +16 -0
  73. package/.agents/backend/fm-ff-lib.sh +420 -0
  74. package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
  75. package/.agents/backend/fm-fleet-sync.sh +458 -0
  76. package/.agents/backend/fm-fleet-view.sh +96 -0
  77. package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
  78. package/.agents/backend/fm-guard.sh +242 -0
  79. package/.agents/backend/fm-harness.sh +195 -0
  80. package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
  81. package/.agents/backend/fm-herdr-lab.sh +346 -0
  82. package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
  83. package/.agents/backend/fm-home-seed.sh +984 -0
  84. package/.agents/backend/fm-home-summary-refresh.sh +255 -0
  85. package/.agents/backend/fm-hook-host-lib.sh +36 -0
  86. package/.agents/backend/fm-inactive-reconcile.sh +531 -0
  87. package/.agents/backend/fm-inbox.sh +399 -0
  88. package/.agents/backend/fm-install-actionlint.sh +84 -0
  89. package/.agents/backend/fm-install-herdr.sh +96 -0
  90. package/.agents/backend/fm-install-shellcheck.sh +84 -0
  91. package/.agents/backend/fm-install-treehouse.sh +95 -0
  92. package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
  93. package/.agents/backend/fm-lease-lib.sh +218 -0
  94. package/.agents/backend/fm-lease.sh +189 -0
  95. package/.agents/backend/fm-line-cap-lib.sh +51 -0
  96. package/.agents/backend/fm-lint-workflows.sh +137 -0
  97. package/.agents/backend/fm-lint.sh +591 -0
  98. package/.agents/backend/fm-lock-lib.sh +104 -0
  99. package/.agents/backend/fm-lock.sh +107 -0
  100. package/.agents/backend/fm-marker-lib.sh +12 -0
  101. package/.agents/backend/fm-merge-local.sh +74 -0
  102. package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
  103. package/.agents/backend/fm-nm-run-lib.sh +124 -0
  104. package/.agents/backend/fm-on.sh +125 -0
  105. package/.agents/backend/fm-operational-input.sh +253 -0
  106. package/.agents/backend/fm-peek.sh +46 -0
  107. package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
  108. package/.agents/backend/fm-pr-check.sh +135 -0
  109. package/.agents/backend/fm-pr-lib.sh +1016 -0
  110. package/.agents/backend/fm-pr-merge.sh +707 -0
  111. package/.agents/backend/fm-pr-poll.sh +110 -0
  112. package/.agents/backend/fm-primary-scope-lib.sh +33 -0
  113. package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
  114. package/.agents/backend/fm-procevent-lavish.sh +628 -0
  115. package/.agents/backend/fm-procevent-lib.sh +892 -0
  116. package/.agents/backend/fm-procevent-quota.sh +290 -0
  117. package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
  118. package/.agents/backend/fm-procevent-when.sh +504 -0
  119. package/.agents/backend/fm-procevent.sh +1466 -0
  120. package/.agents/backend/fm-project-mode.sh +92 -0
  121. package/.agents/backend/fm-project-origin-lib.sh +180 -0
  122. package/.agents/backend/fm-promote.sh +282 -0
  123. package/.agents/backend/fm-public-followup-emit.sh +260 -0
  124. package/.agents/backend/fm-public-followup-lib.sh +398 -0
  125. package/.agents/backend/fm-public-followup.sh +1330 -0
  126. package/.agents/backend/fm-push-transition-lib.sh +168 -0
  127. package/.agents/backend/fm-quota-axi-lib.sh +93 -0
  128. package/.agents/backend/fm-quota-choose.sh +384 -0
  129. package/.agents/backend/fm-remote-delta-read.sh +189 -0
  130. package/.agents/backend/fm-remote-doctor.sh +800 -0
  131. package/.agents/backend/fm-remote-entrypoint.sh +193 -0
  132. package/.agents/backend/fm-remote-file.sh +234 -0
  133. package/.agents/backend/fm-remote-home-provision.sh +259 -0
  134. package/.agents/backend/fm-remote-home-seed.sh +259 -0
  135. package/.agents/backend/fm-remote-inherit-push.sh +90 -0
  136. package/.agents/backend/fm-remote-inherit.sh +179 -0
  137. package/.agents/backend/fm-remote-job-lib.sh +1241 -0
  138. package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
  139. package/.agents/backend/fm-remote-job-worker.sh +1124 -0
  140. package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
  141. package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
  142. package/.agents/backend/fm-review-diff.sh +158 -0
  143. package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
  144. package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
  145. package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
  146. package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
  147. package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
  148. package/.agents/backend/fm-secondmate-report.sh +88 -0
  149. package/.agents/backend/fm-send.sh +1059 -0
  150. package/.agents/backend/fm-session-lock-lib.sh +176 -0
  151. package/.agents/backend/fm-session-start.sh +970 -0
  152. package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
  153. package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
  154. package/.agents/backend/fm-sessionstart-run.sh +145 -0
  155. package/.agents/backend/fm-spawn.sh +3153 -0
  156. package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
  157. package/.agents/backend/fm-startup-memory-budget.sh +94 -0
  158. package/.agents/backend/fm-startup-network.sh +642 -0
  159. package/.agents/backend/fm-stow-cascade.sh +251 -0
  160. package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
  161. package/.agents/backend/fm-supervise-daemon.sh +1732 -0
  162. package/.agents/backend/fm-supervision-instructions.sh +215 -0
  163. package/.agents/backend/fm-supervision-lib.sh +90 -0
  164. package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
  165. package/.agents/backend/fm-tangle-lib.sh +53 -0
  166. package/.agents/backend/fm-task-inbox-lib.sh +402 -0
  167. package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
  168. package/.agents/backend/fm-teardown.sh +2922 -0
  169. package/.agents/backend/fm-test-isolation-proof.sh +588 -0
  170. package/.agents/backend/fm-test-run.sh +2191 -0
  171. package/.agents/backend/fm-timeout-lib.sh +141 -0
  172. package/.agents/backend/fm-timing-lib.sh +179 -0
  173. package/.agents/backend/fm-tmux-lib.sh +291 -0
  174. package/.agents/backend/fm-tool-update-check.sh +898 -0
  175. package/.agents/backend/fm-trace-context-lib.sh +227 -0
  176. package/.agents/backend/fm-transition-lib.sh +103 -0
  177. package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
  178. package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
  179. package/.agents/backend/fm-turnend-guard.sh +432 -0
  180. package/.agents/backend/fm-update.sh +110 -0
  181. package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
  182. package/.agents/backend/fm-voice-client.py +1373 -0
  183. package/.agents/backend/fm-voice-relay.py +1256 -0
  184. package/.agents/backend/fm-wake-drain.sh +592 -0
  185. package/.agents/backend/fm-wake-grant.sh +127 -0
  186. package/.agents/backend/fm-wake-lib.sh +1849 -0
  187. package/.agents/backend/fm-watch-arm.sh +602 -0
  188. package/.agents/backend/fm-watch-checkpoint.sh +109 -0
  189. package/.agents/backend/fm-watch.sh +1962 -0
  190. package/.agents/backend/fm-x-dismiss.sh +116 -0
  191. package/.agents/backend/fm-x-followup.sh +286 -0
  192. package/.agents/backend/fm-x-lib.sh +1000 -0
  193. package/.agents/backend/fm-x-link.sh +234 -0
  194. package/.agents/backend/fm-x-poll.sh +185 -0
  195. package/.agents/backend/fm-x-reply.sh +385 -0
  196. package/.agents/backend/fm_voice_frame.py +166 -0
  197. package/.agents/backend/fm_voice_records.py +574 -0
  198. package/.agents/backend/model-bridge.py +290 -0
  199. package/.agents/backend/opencode-go-bridge.py +30 -0
  200. package/.agents/bus/README.md +12 -0
  201. package/.agents/bus/messages.json +1 -0
  202. package/.agents/config/agents.machine.example.yaml +16 -0
  203. package/.agents/config/agents.yaml +50 -0
  204. package/.agents/config/agents.yaml.example +72 -0
  205. package/.agents/config/crew-dispatch.json +22 -0
  206. package/.agents/config/cron.yaml +9 -0
  207. package/.agents/config/eindri-dispatch.json +67 -0
  208. package/.agents/config/eindri-harness +1 -0
  209. package/.agents/config/startup-memory-budget +1 -0
  210. package/.agents/config/tailscale-sync.yaml +27 -0
  211. package/.agents/filebrowser/.filebrowser.json +6 -0
  212. package/.agents/filebrowser/README.md +11 -0
  213. package/.agents/gateway/README.md +12 -0
  214. package/.agents/github/README.md +15 -0
  215. package/.agents/github/webhooks/.gitkeep +0 -0
  216. package/.agents/github/workflows/.gitkeep +0 -0
  217. package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
  218. package/.agents/harness/opencode/plugins/package.json +4 -0
  219. package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
  220. package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
  221. package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
  222. package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
  223. package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
  224. package/.agents/memory/README.md +46 -0
  225. package/.agents/memory/kaia.engram +0 -0
  226. package/.agents/memory/kaia.engram-shm +0 -0
  227. package/.agents/memory/kaia.engram-wal +0 -0
  228. package/.agents/memory/runes_audit.md +5 -0
  229. package/.agents/memory/well/episodes.jsonl +367 -0
  230. package/.agents/memory/well/workspace.jsonl +27 -0
  231. package/.agents/migrations/0001-hodd-layout.sh +38 -0
  232. package/.agents/migrations/0002-a2a-mcp.sh +27 -0
  233. package/.agents/migrations/0003-private-data-separation.sh +111 -0
  234. package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
  235. package/.agents/sandbox/Dockerfile.utgard +19 -0
  236. package/.agents/sandbox/README.md +14 -0
  237. package/.agents/sandbox/utgard.config.json +14 -0
  238. package/.agents/skills/README.md +59 -0
  239. package/.agents/skills/bragi-marketing/README.md +3 -0
  240. package/.agents/skills/bragi-marketing/SKILL.md +82 -0
  241. package/.agents/skills/eindri-homes/README.md +3 -0
  242. package/.agents/skills/eindri-homes/SKILL.md +291 -0
  243. package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
  244. package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
  245. package/.agents/skills/frigg-consent/README.md +3 -0
  246. package/.agents/skills/frigg-consent/SKILL.md +56 -0
  247. package/.agents/skills/galdr-ymirsystem/README.md +3 -0
  248. package/.agents/skills/galdr-ymirsystem/SKILL.md +158 -0
  249. package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
  250. package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
  251. package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
  252. package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
  253. package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
  254. package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
  255. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +673 -0
  256. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
  257. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
  258. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
  259. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
  260. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
  261. package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +496 -0
  262. package/.agents/skills/galdr-ymirsystem/assets/installation.md +571 -0
  263. package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
  264. package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
  265. package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +161 -0
  266. package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +377 -0
  267. package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
  268. package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +129 -0
  269. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
  270. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
  271. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +96 -0
  272. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
  273. package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
  274. package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
  275. package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
  276. package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
  277. package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
  278. package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
  279. package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
  280. package/.agents/skills/galdr-ymirsystem/assets/smidja.md +175 -0
  281. package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
  282. package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
  283. package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
  284. package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +360 -0
  285. package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
  286. package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
  287. package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
  288. package/.agents/skills/gjallarhorn-relay/README.md +3 -0
  289. package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
  290. package/.agents/skills/groa-update/SKILL.md +70 -0
  291. package/.agents/skills/hamr-adapters/README.md +3 -0
  292. package/.agents/skills/hamr-adapters/SKILL.md +123 -0
  293. package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
  294. package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
  295. package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
  296. package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
  297. package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
  298. package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
  299. package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
  300. package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
  301. package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
  302. package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
  303. package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
  304. package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
  305. package/.agents/skills/herdr-panes/README.md +3 -0
  306. package/.agents/skills/herdr-panes/SKILL.md +92 -0
  307. package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
  308. package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
  309. package/.agents/skills/hnoss-design/DESIGN.md +19 -0
  310. package/.agents/skills/hnoss-design/README.md +3 -0
  311. package/.agents/skills/hnoss-design/SKILL.md +83 -0
  312. package/.agents/skills/hvild-afk/README.md +3 -0
  313. package/.agents/skills/hvild-afk/SKILL.md +241 -0
  314. package/.agents/skills/jord-projects/README.md +3 -0
  315. package/.agents/skills/jord-projects/SKILL.md +92 -0
  316. package/.agents/skills/lifecycle/SKILL.md +56 -0
  317. package/.agents/skills/lifecycle/smoke_test.sh +52 -0
  318. package/.agents/skills/lifecycle/start.sh +21 -0
  319. package/.agents/skills/lifecycle/status.sh +35 -0
  320. package/.agents/skills/lifecycle/stop.sh +16 -0
  321. package/.agents/skills/muninn-stow/README.md +3 -0
  322. package/.agents/skills/muninn-stow/SKILL.md +309 -0
  323. package/.agents/skills/no-mistakes/SKILL.md +379 -0
  324. package/.agents/skills/nornir-schedule/README.md +3 -0
  325. package/.agents/skills/nornir-schedule/SKILL.md +25 -0
  326. package/.agents/skills/nornir-schedule/assets/events.md +137 -0
  327. package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
  328. package/.agents/skills/nsr-compliance/README.md +3 -0
  329. package/.agents/skills/nsr-compliance/SKILL.md +29 -0
  330. package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
  331. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
  332. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
  333. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
  334. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
  335. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
  336. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
  337. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
  338. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
  339. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
  340. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
  341. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
  342. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
  343. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
  344. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
  345. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
  346. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
  347. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
  348. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
  349. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
  350. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
  351. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
  352. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
  353. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
  354. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
  355. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
  356. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
  357. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
  358. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
  359. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
  360. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
  361. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
  362. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
  363. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
  364. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
  365. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
  366. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
  367. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
  368. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
  369. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
  370. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
  371. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
  372. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
  373. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
  374. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
  375. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
  376. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
  377. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
  378. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
  379. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
  380. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
  381. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
  382. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
  383. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
  384. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
  385. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
  386. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
  387. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
  388. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
  389. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
  390. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
  391. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
  392. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
  393. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
  394. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
  395. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
  396. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
  397. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
  398. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
  399. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
  400. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
  401. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
  402. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
  403. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
  404. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
  405. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
  406. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
  407. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
  408. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
  409. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
  410. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
  411. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
  412. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
  413. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
  414. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
  415. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
  416. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
  417. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
  418. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
  419. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
  420. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
  421. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
  422. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
  423. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
  424. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
  425. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
  426. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
  427. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
  428. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
  429. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
  430. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
  431. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
  432. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
  433. package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
  434. package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
  435. package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
  436. package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
  437. package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
  438. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
  439. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
  440. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
  441. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
  442. package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
  443. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
  444. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
  445. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
  446. package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
  447. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
  448. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
  449. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
  450. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
  451. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
  452. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
  453. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
  454. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
  455. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
  456. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
  457. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
  458. package/.agents/skills/pr-ops/README.md +3 -0
  459. package/.agents/skills/pr-ops/SKILL.md +109 -0
  460. package/.agents/skills/ratatoskr-a2a/README.md +3 -0
  461. package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
  462. package/.agents/skills/rules-check-drift/SKILL.md +81 -0
  463. package/.agents/skills/saga-bearings/README.md +3 -0
  464. package/.agents/skills/saga-bearings/SKILL.md +26 -0
  465. package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
  466. package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
  467. package/.agents/skills/saga-bearings/assets/recap.md +56 -0
  468. package/.agents/skills/syn-recovery/README.md +3 -0
  469. package/.agents/skills/syn-recovery/SKILL.md +54 -0
  470. package/.agents/skills/tyr-check/README.md +3 -0
  471. package/.agents/skills/tyr-check/SKILL.md +218 -0
  472. package/.agents/skills/urdh-hold/README.md +3 -0
  473. package/.agents/skills/urdh-hold/SKILL.md +25 -0
  474. package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
  475. package/.agents/skills/urdh-hold/assets/hold.md +54 -0
  476. package/.agents/skills/vor-diagnostics/README.md +3 -0
  477. package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
  478. package/.agents/skills/ymir-host/README.md +3 -0
  479. package/.agents/skills/ymir-host/SKILL.md +34 -0
  480. package/.agents/skills/ymir-host/assets/desktop.md +36 -0
  481. package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
  482. package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
  483. package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
  484. package/.agents/skills/ymir-host/assets/update.md +64 -0
  485. package/.agents/tests/assets/board-render-harness.mjs +117 -0
  486. package/.agents/tests/cmux-test-safety.sh +51 -0
  487. package/.agents/tests/fixtures.sh +291 -0
  488. package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
  489. package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
  490. package/.agents/tests/fm-afk-launch.test.sh +961 -0
  491. package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
  492. package/.agents/tests/fm-afk-return.test.sh +283 -0
  493. package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
  494. package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
  495. package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
  496. package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
  497. package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
  498. package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
  499. package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
  500. package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
  501. package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
  502. package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
  503. package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
  504. package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
  505. package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
  506. package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
  507. package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
  508. package/.agents/tests/fm-backend-orca.test.sh +1357 -0
  509. package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
  510. package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
  511. package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
  512. package/.agents/tests/fm-backend.test.sh +1142 -0
  513. package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
  514. package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
  515. package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
  516. package/.agents/tests/fm-bearings-board.test.sh +414 -0
  517. package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
  518. package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
  519. package/.agents/tests/fm-bootstrap.test.sh +1178 -0
  520. package/.agents/tests/fm-branch-supervision.test.sh +552 -0
  521. package/.agents/tests/fm-brief.test.sh +785 -0
  522. package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
  523. package/.agents/tests/fm-busy-state.test.sh +465 -0
  524. package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
  525. package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
  526. package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
  527. package/.agents/tests/fm-check-unregister.test.sh +198 -0
  528. package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
  529. package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
  530. package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
  531. package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
  532. package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
  533. package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
  534. package/.agents/tests/fm-composer-ghost.test.sh +716 -0
  535. package/.agents/tests/fm-composer-lib.test.sh +666 -0
  536. package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
  537. package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
  538. package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
  539. package/.agents/tests/fm-control.test.sh +910 -0
  540. package/.agents/tests/fm-crew-state.test.sh +1610 -0
  541. package/.agents/tests/fm-cursor-harness.test.sh +404 -0
  542. package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
  543. package/.agents/tests/fm-cursor-primary.test.sh +708 -0
  544. package/.agents/tests/fm-daemon.test.sh +2740 -0
  545. package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
  546. package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
  547. package/.agents/tests/fm-extension-binding.test.sh +2187 -0
  548. package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
  549. package/.agents/tests/fm-fleet-sync.test.sh +721 -0
  550. package/.agents/tests/fm-gate-refuse.test.sh +356 -0
  551. package/.agents/tests/fm-gitignore-config.test.sh +89 -0
  552. package/.agents/tests/fm-gotmp.test.sh +230 -0
  553. package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
  554. package/.agents/tests/fm-grok-harness.test.sh +117 -0
  555. package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
  556. package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
  557. package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
  558. package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
  559. package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
  560. package/.agents/tests/fm-herdr-lab.test.sh +243 -0
  561. package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
  562. package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
  563. package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
  564. package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
  565. package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
  566. package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
  567. package/.agents/tests/fm-kimi-harness.test.sh +687 -0
  568. package/.agents/tests/fm-lint-workflows.test.sh +532 -0
  569. package/.agents/tests/fm-lint.test.sh +1023 -0
  570. package/.agents/tests/fm-muse-harness.test.sh +932 -0
  571. package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
  572. package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
  573. package/.agents/tests/fm-on.test.sh +507 -0
  574. package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
  575. package/.agents/tests/fm-operational-input.test.sh +160 -0
  576. package/.agents/tests/fm-peek-remote.test.sh +110 -0
  577. package/.agents/tests/fm-pending-reply.test.sh +1288 -0
  578. package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
  579. package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
  580. package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
  581. package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
  582. package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
  583. package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
  584. package/.agents/tests/fm-pr-merge.test.sh +2135 -0
  585. package/.agents/tests/fm-procevent-quota.test.sh +225 -0
  586. package/.agents/tests/fm-procevent-when.test.sh +406 -0
  587. package/.agents/tests/fm-procevent.test.sh +1745 -0
  588. package/.agents/tests/fm-project-origin.test.sh +110 -0
  589. package/.agents/tests/fm-public-followup.test.sh +2272 -0
  590. package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
  591. package/.agents/tests/fm-quota-choose.test.sh +626 -0
  592. package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
  593. package/.agents/tests/fm-remote-doctor.test.sh +625 -0
  594. package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
  595. package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
  596. package/.agents/tests/fm-remote-job.test.sh +768 -0
  597. package/.agents/tests/fm-remote-reply.test.sh +520 -0
  598. package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
  599. package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
  600. package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
  601. package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
  602. package/.agents/tests/fm-review-diff.test.sh +176 -0
  603. package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
  604. package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
  605. package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
  606. package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
  607. package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
  608. package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
  609. package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
  610. package/.agents/tests/fm-send-inbox.test.sh +352 -0
  611. package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
  612. package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
  613. package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
  614. package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
  615. package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
  616. package/.agents/tests/fm-send-settle.test.sh +147 -0
  617. package/.agents/tests/fm-send-strict.test.sh +241 -0
  618. package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
  619. package/.agents/tests/fm-session-start.test.sh +2515 -0
  620. package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
  621. package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
  622. package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
  623. package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
  624. package/.agents/tests/fm-spawn-batch.test.sh +148 -0
  625. package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
  626. package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
  627. package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
  628. package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
  629. package/.agents/tests/fm-startup-network.test.sh +712 -0
  630. package/.agents/tests/fm-stow-cascade.test.sh +370 -0
  631. package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
  632. package/.agents/tests/fm-supervision-events.test.sh +156 -0
  633. package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
  634. package/.agents/tests/fm-tangle-guard.test.sh +277 -0
  635. package/.agents/tests/fm-task-delivery.test.sh +420 -0
  636. package/.agents/tests/fm-task-inbox.test.sh +513 -0
  637. package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
  638. package/.agents/tests/fm-teardown.test.sh +2665 -0
  639. package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
  640. package/.agents/tests/fm-test-fixtures.test.sh +132 -0
  641. package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
  642. package/.agents/tests/fm-test-run.test.sh +1196 -0
  643. package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
  644. package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
  645. package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
  646. package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
  647. package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
  648. package/.agents/tests/fm-transition-lib.test.sh +54 -0
  649. package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
  650. package/.agents/tests/fm-update.test.sh +304 -0
  651. package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
  652. package/.agents/tests/fm-voice-relay.test.sh +4741 -0
  653. package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
  654. package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
  655. package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
  656. package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
  657. package/.agents/tests/fm-wake-queue.test.sh +1224 -0
  658. package/.agents/tests/fm-watch-arm.test.sh +821 -0
  659. package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
  660. package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
  661. package/.agents/tests/fm-watch-triage.test.sh +3889 -0
  662. package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
  663. package/.agents/tests/fm-x-mode.test.sh +3042 -0
  664. package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
  665. package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
  666. package/.agents/tests/herdr-test-safety.sh +42 -0
  667. package/.agents/tests/lib.sh +315 -0
  668. package/.agents/tests/remote-herdr-fixture.sh +125 -0
  669. package/.agents/tests/secondmate-helpers.sh +193 -0
  670. package/.agents/tests/smoke.test.sh +93 -0
  671. package/.agents/tests/wake-helpers.sh +338 -0
  672. package/.agents/tests/zellij-test-safety.sh +60 -0
  673. package/.agents/tools/README.md +10 -0
  674. package/.agents/tools/bin/tasks-cli +267 -0
  675. package/.agents/tools/tasks-cli.ts +216 -0
  676. package/AGENTS.md +454 -0
  677. package/CHANGELOG.md +881 -0
  678. package/LICENSE +1 -1
  679. package/NOTICE +63 -0
  680. package/README.md +113 -39
  681. package/RULES/01-domains.md +51 -0
  682. package/RULES/02-agents.md +78 -0
  683. package/RULES/03-houses.md +61 -0
  684. package/RULES/04-hoard.md +65 -0
  685. package/RULES/05-platforms.md +67 -0
  686. package/RULES/06-append-only.md +58 -0
  687. package/RULES/07-config.md +45 -0
  688. package/RULES/08-delivery-gate.md +75 -0
  689. package/RULES/README.md +20 -0
  690. package/bin/README.md +107 -0
  691. package/bin/a2a-mcp.sh +98 -0
  692. package/bin/a2a-serve.py +103 -0
  693. package/bin/a2a-serve.sh +8 -0
  694. package/bin/a2a-talk.sh +50 -0
  695. package/bin/a2abridge-ensure.sh +108 -0
  696. package/bin/agent-run.sh +43 -0
  697. package/bin/agents-config.sh +233 -0
  698. package/bin/apodex-smoke-test.sh +92 -0
  699. package/bin/bifrost-bridge.sh +112 -0
  700. package/bin/bifrost-ingress.sh +77 -0
  701. package/bin/bootstrap-macos.sh +107 -0
  702. package/bin/bootstrap-windows.ps1 +112 -0
  703. package/bin/branch-guard.sh +64 -0
  704. package/bin/brokk +73 -0
  705. package/bin/brokk-classify-lib.sh +1770 -0
  706. package/bin/brokk-lease-lib.sh +222 -0
  707. package/bin/brokk-lease.sh +193 -0
  708. package/bin/brokk-lint.sh +65 -0
  709. package/bin/brokk-send.sh +38 -0
  710. package/bin/brokk-update.sh +9 -0
  711. package/bin/brokk-wake-grant.sh +127 -0
  712. package/bin/brokk-wake-lib.sh +1849 -0
  713. package/bin/changelog-guard.sh +165 -0
  714. package/bin/crash-sense.sh +160 -0
  715. package/bin/desktop-place.sh +224 -0
  716. package/bin/docs-guard.sh +39 -0
  717. package/bin/editor-place.sh +207 -0
  718. package/bin/eindri-acclaim.sh +34 -0
  719. package/bin/eindri-control.sh +28 -0
  720. package/bin/eindri-role.sh +83 -0
  721. package/bin/eindri-seen.sh +41 -0
  722. package/bin/eindri-send.sh +15 -0
  723. package/bin/eindri-start.sh +85 -0
  724. package/bin/eindri-watch.sh +57 -0
  725. package/bin/einherjar-spawn.sh +576 -0
  726. package/bin/eir-doctor.sh +112 -0
  727. package/bin/erindi-brief.sh +271 -0
  728. package/bin/fleet-apply.sh +68 -0
  729. package/bin/github-deploy.sh +81 -0
  730. package/bin/gjallarhorn-expose.sh +102 -0
  731. package/bin/gjallarhorn-notify.sh +58 -0
  732. package/bin/gjallarhorn-purge.sh +54 -0
  733. package/bin/gjallarhorn-tunnel.sh +72 -0
  734. package/bin/gleipnir-lock-lib.sh +284 -0
  735. package/bin/groa-update.sh +122 -0
  736. package/bin/hall-snapshot.sh +92 -0
  737. package/bin/hamr-harness.sh +246 -0
  738. package/bin/heimdall-ssh-keys.sh +374 -0
  739. package/bin/herdr-agents.py +44 -0
  740. package/bin/herdr-ensure.sh +104 -0
  741. package/bin/herdr-run.sh +431 -0
  742. package/bin/hermes-ensure.sh +88 -0
  743. package/bin/hoard-lib.sh +25 -0
  744. package/bin/hodd.sh +78 -0
  745. package/bin/host-sense.sh +199 -0
  746. package/bin/huginn-research-worker.sh +108 -0
  747. package/bin/local-model-lock.sh +51 -0
  748. package/bin/mimir-bridge.py +226 -0
  749. package/bin/mimir-bridge.sh +87 -0
  750. package/bin/mimir-ingest.sh +131 -0
  751. package/bin/mimir.sh +113 -0
  752. package/bin/mjollnir-webhook.sh +59 -0
  753. package/bin/mjollnir.sh +85 -0
  754. package/bin/model-hardware.sh +82 -0
  755. package/bin/model-resolve.sh +147 -0
  756. package/bin/models-detect.sh +178 -0
  757. package/bin/nornir-cron-start.sh +162 -0
  758. package/bin/nornir-job-daily-briefing.sh +191 -0
  759. package/bin/nornir-job-git-sync.sh +152 -0
  760. package/bin/nornir-job-memory-housekeeping.sh +114 -0
  761. package/bin/nornir-job-observer.sh +166 -0
  762. package/bin/nornir-job-skillopt-sleep.sh +76 -0
  763. package/bin/omarchy-hook-install.sh +60 -0
  764. package/bin/omarchy-install.sh +148 -0
  765. package/bin/omarchy-plugins.sh +174 -0
  766. package/bin/omarchy-sense.sh +149 -0
  767. package/bin/perm-guard.sh +30 -0
  768. package/bin/pi-agent.sh +68 -0
  769. package/bin/pi-ensure.sh +77 -0
  770. package/bin/pi-local.sh +37 -0
  771. package/bin/pi-seat.sh +63 -0
  772. package/bin/prereq-ensure.sh +166 -0
  773. package/bin/private-guard.sh +38 -0
  774. package/bin/project-git.sh +55 -0
  775. package/bin/public-guard.sh +70 -0
  776. package/bin/ratatoskr.sh +49 -0
  777. package/bin/realm-lib.sh +32 -0
  778. package/bin/repo-scrub.sh +62 -0
  779. package/bin/rodd-operational-input.sh +250 -0
  780. package/bin/runes-append.sh +198 -0
  781. package/bin/saga-session-start.sh +172 -0
  782. package/bin/saga-sessionstart-run.sh +79 -0
  783. package/bin/saga-wake-drain.sh +41 -0
  784. package/bin/secret-guard.sh +63 -0
  785. package/bin/sessrumnir-ensure.sh +100 -0
  786. package/bin/sessrumnir-sync.sh +237 -0
  787. package/bin/sessrumnir.sh +91 -0
  788. package/bin/skillopt-setup.sh +76 -0
  789. package/bin/skuld-branch-outcome.sh +203 -0
  790. package/bin/skuld-branch-prompt.sh +101 -0
  791. package/bin/smidja-bootstrap.sh +90 -0
  792. package/bin/smidja-observe.sh +86 -0
  793. package/bin/syn-arm-pretool-check.sh +57 -0
  794. package/bin/syn-asset-pretool-check.sh +76 -0
  795. package/bin/syn-cd-pretool-check.sh +28 -0
  796. package/bin/syn-guard-pretool-check.sh +83 -0
  797. package/bin/syn-turnend-guard.sh +36 -0
  798. package/bin/syn-watch-arm.sh +99 -0
  799. package/bin/tailscale-sync.sh +190 -0
  800. package/bin/telegram-bot.sh +69 -0
  801. package/bin/toolchain.sh +74 -0
  802. package/bin/utgard.sh +111 -0
  803. package/bin/valhalla.sh +115 -0
  804. package/bin/valknut-load.sh +260 -0
  805. package/bin/vor-crew-state.sh +124 -0
  806. package/bin/wedge-notify.sh +47 -0
  807. package/bin/workspace-provision.sh +80 -0
  808. package/bin/workspace-rag.sh +150 -0
  809. package/bin/wyrd-db.sh +47 -0
  810. package/bin/yggdrasil.sh +152 -0
  811. package/bin/ymir-edit.sh +145 -0
  812. package/bin/ymir-install.sh +641 -0
  813. package/bin/ymir-invite.sh +93 -0
  814. package/bin/ymir-isolation.sh +88 -0
  815. package/bin/ymir-migrate.sh +61 -0
  816. package/bin/ymir-platform.sh +348 -0
  817. package/bin/ymir-say.sh +97 -0
  818. package/bin/ymir-setup-auth.sh +108 -0
  819. package/bin/ymir-validate.sh +173 -0
  820. package/bin/ymir.js +74 -16
  821. package/docs/Architecture.md +339 -0
  822. package/docs/design.md +351 -0
  823. package/docs/installations/README.md +63 -0
  824. package/docs/installations/ymir-home.md +93 -0
  825. package/docs/integration.md +105 -0
  826. package/docs/lore.md +1056 -0
  827. package/docs/research/agent-harnesses.md +290 -0
  828. package/docs/runbooks/README.md +19 -0
  829. package/docs/runbooks/a2a.md +91 -0
  830. package/docs/runbooks/agent-permissions.md +99 -0
  831. package/docs/runbooks/agents.md +57 -0
  832. package/docs/runbooks/models.md +69 -0
  833. package/docs/runbooks/realm-onboarding.md +60 -0
  834. package/docs/runbooks/secrets-and-hoard.md +60 -0
  835. package/docs/runbooks/updates-and-migrations.md +110 -0
  836. package/docs/runbooks/worktrees-isolation.md +72 -0
  837. package/docs/session-start.md +105 -0
  838. package/docs/skillopt-integration.md +321 -0
  839. package/docs/sync-system.md +66 -0
  840. package/docs/workspaces.md +104 -0
  841. package/docs/ymir-rut.md +260 -0
  842. package/package.json +44 -14
  843. package/packaging/build.sh +74 -0
  844. package/packaging/macos/Ymir Installer.command +43 -0
  845. package/packaging/windows/ymir-setup.nsi +74 -0
  846. package/scripts/README.md +22 -0
  847. package/scripts/electron.sh +210 -0
  848. package/scripts/start.sh +167 -0
  849. package/scripts/stop.sh +113 -0
  850. package/install.sh +0 -35
@@ -0,0 +1,673 @@
1
+ # Harness Integration — the Ymir harness adapter matrix and adapter contract
2
+
3
+ > **Purpose:** Define how each agent harness (OpenCode, Pi, Claude Code, Cursor, Codex, Grok) seats **Brokk** before the first turn, arms **Sýn** supervision, guards the turn end, and enforces the PreToolUse seatbelts — and give a step-by-step recipe to add a new harness.
4
+
5
+ This is the reference an agent reads to add a harness adapter or rebuild one from scratch. It is paired with one deep-dive file per harness:
6
+
7
+ | Deep dive | Harness |
8
+ |---|---|
9
+ | [`opencode.md`](opencode.md) | OpenCode (Öppencode) |
10
+ | [`pi.md`](pi.md) | Pi (`@earendil-works/pi-coding-agent`) |
11
+ | [`claude-code.md`](claude-code.md) | Claude Code |
12
+ | [`cursor.md`](cursor.md) | Cursor |
13
+ | [`codex.md`](codex.md) | Codex |
14
+ | *(none — not implemented)* | Grok |
15
+
16
+ Runtime inventory that every adapter calls: [`../runtime-components.md`](../runtime-components.md).
17
+ The governing plan is [`docs/plans/29-brokk-distro-runtime.md`](../../../../../docs/plans/29-brokk-distro-runtime.md) (referred to below as **plan 29**), whose §12 carries the Norse naming law.
18
+
19
+ ---
20
+
21
+ ## 1. What a harness adapter is
22
+
23
+ > **MCP scope (Ymir's well + A2A mesh).** `bin/a2a-mcp.sh install` wires the
24
+ > `engram` (memory well) and `a2abridge` (A2A mesh) MCP servers into OpenCode's
25
+ > repo `opencode.json` **and** Pi. By default the Pi side writes the **global**
26
+ > `~/.pi/agent/mcp.json`; `bin/a2a-mcp.sh install --project` writes the repo's
27
+ > `.pi/mcp.json` instead, leaving a Pi used elsewhere untouched (launch with
28
+ > `pi --mcp-config .pi/mcp.json`). Prefer `--project` when integrating Ymir into
29
+ > an existing workflow.
30
+
31
+
32
+ The Ymir runtime is a **distro**: a directory of instructions, skills, tooling and conventions that turns a general-purpose agent into a specialized one. Launching a supported harness inside `BROKK_HOME` is supposed to instantiate **Brokk** and address the operator as the **Allfather** *before the model's first turn*.
33
+
34
+ A harness will not do that on its own. Each harness exposes a different set of lifecycle hooks, and each adapter is a thin, harness-specific shim that binds those hooks to **harness-agnostic runtime scripts** in `bin/`. The shim never re-implements runtime logic: it only decides *when* to call a script and *how* to deliver the result.
35
+
36
+ ```
37
+ harness lifecycle event ──► adapter shim ──► bin/<owner script> ──► state/ data/
38
+ (session open / idle / (.opencode, (Sága, Sýn, Rödd,
39
+ turn end / tool call) .pi, hooks.json) Gleipnir, ...)
40
+ ```
41
+
42
+ Every adapter must satisfy the **four-part adapter contract** (§3). A harness with no adapter is *unverified* and must never be used for a dispatched Eindri (`bin/einherjar-spawn.sh` fails closed).
43
+
44
+ ---
45
+
46
+ ## 2. Run-tier vs nudge-tier
47
+
48
+ The tier answers **how the session-start digest reaches model context**.
49
+
50
+ | Tier | Meaning | Contract |
51
+ |---|---|---|
52
+ | **run-tier** | The harness's session-open adapter can **execute** a command and inject its stdout into model context (or as the session's first context) before the model acts. | Adapter calls `bin/saga-sessionstart-run.sh`; the digest text is delivered natively. Nothing is left to the model's discretion. |
53
+ | **nudge-tier** | The harness can only post a message into the session and **ask** the model to take the helm. The model can defer. | Adapter calls `bin/saga-sessionstart-run.sh` (which emits the digest *or* a one-line "run `bin/saga-session-start.sh` now" instruction) and delivers it as a prompt/follow-up. |
54
+
55
+ Important nuance: **tier is per-event, not per-harness.** All current harnesses are run-tier for the session-open digest *except* the disabled/Grok path. But `bin/saga-sessionstart-run.sh` deliberately emits a **nudge** for context-preserving opens (`resume`, `reload`, `fork`) even on a run-tier harness, because re-running the whole digest is redundant when prior context is restored:
56
+
57
+ ```bash
58
+ # bin/saga-sessionstart-run.sh:70-72
59
+ resume|reload|fork)
60
+ printf 'Run `%s` exactly once now, before executing any other instructions.\n' "bash $SCRIPT_DIR/saga-session-start.sh"
61
+ ;;
62
+ ```
63
+
64
+ So the digest is *run* on `startup`/`new`, *re-emitted* on `clear`/`compact` after a completed startup, and *nudged* on `resume`/`reload`/`fork`.
65
+
66
+ ### Tier + mechanism per harness
67
+
68
+ | Harness | Tier | Session-open mechanism | Source value(s) seen |
69
+ |---|---|---|---|
70
+ | OpenCode | run (nudge delivery) | plugin `session.created` runs `saga-sessionstart-run.sh`, injects stdout through `client.session.promptAsync` | (wrapper chooses from no payload) |
71
+ | Pi | run | extension `before_agent_start` returns a `syn-sessionstart-nudge` message built from the wrapper | `startup`, `clear`, `resume`, `fork`, `compact` |
72
+ | Claude Code | run | `SessionStart` hook stdout is injected; wrapper reads `source` from the hook JSON on stdin | `startup`, `resume`, `clear`, `compact` |
73
+ | Cursor | run | `sessionStart` hook returns JSON `{"additional_context": "..."}` | `--source startup` (explicit) |
74
+ | Codex | run | `SessionStart` hook pipes the JSON payload into `saga-sessionstart-run.sh` | parsed from payload |
75
+ | Grok | nudge (upstream only) | upstream uses `.grok/hooks/*sessionstart-nudge.json` | — (not implemented in Ymir) |
76
+
77
+ ---
78
+
79
+ ## 3. The adapter contract (four required parts + one optional)
80
+
81
+ Every production adapter implements the same four responsibilities. The harness-specific *how* lives in the deep-dive files; the *what* is fixed here.
82
+
83
+ ### Part 1 — Session-open injection
84
+
85
+ Bind the harness's "session is opening" event to `bin/saga-sessionstart-run.sh`.
86
+
87
+ ```bash
88
+ # The one command every session-open adapter invokes.
89
+ "$BROKK_ROOT/bin/saga-sessionstart-run.sh" [--source <src>] [--pi-prerequisite]
90
+ ```
91
+
92
+ - `--source` ∈ `startup|new|clear|compact|resume|reload|fork`; absent → parse a Claude/Codex-shaped JSON hook payload on stdin, default `startup`.
93
+ - `--pi-prerequisite` is Pi-only: an intentional stand-down exits **3** so Pi provider preflight can tell it apart from an eligible attempt that produced nothing.
94
+ - **Every ordinary transport path exits 0.** A failed session start must reach the agent as digest text it can act on, never as a refusal to open the session. (Claude `SessionStart` exit 2 blocks initialization.)
95
+ - The script records `state/.session-start-complete` so `clear`/`compact` can re-emit instead of re-running.
96
+
97
+ ### Part 2 — Watch arm (Sýn supervision)
98
+
99
+ Bind a "session is idle / turn ended" event to arm **one** `bin/syn-watch-arm.sh` cycle, and let the adapter own **continuity** (re-arming) so no model tokens are spent on ordinary re-arms.
100
+
101
+ ```bash
102
+ bin/syn-watch-arm.sh --restart
103
+ ```
104
+
105
+ The arm script polls `state/` every `BROKK_WATCH_POLL_SECONDS` (default 5), writes `state/.watch.heartbeat`, and exits with an actionable line when the wake queue or a `*.signal`/`*.check`/`.watcher-stop` appears:
106
+
107
+ ```
108
+ signal: wake queue
109
+ signal: <name>
110
+ check: <name>
111
+ stale: watcher stopped by operator
112
+ ```
113
+
114
+ It refuses to arm with exit 0 and a `watcher: read-only - the session helm is held by
115
+ another live session` message **only** when a genuinely live other session holds the helm.
116
+ A **vacant** helm — no owner, a dead/zombie/recycled owner, or a truncated/empty
117
+ lock — is entered in place: the arm script runs `gleipnir_lock_acquire` (which
118
+ refuses only a verifiably live owner), and the Pi extension classifies an empty
119
+ lock as `missing` so `gna_watch_arm`'s reclaim takes it directly. A vacant helm
120
+ is never punted to a manual session start; only a real live contender is refused.
121
+
122
+ - **Pi** owns continuity in `gna-pi-watch.ts` (Gná); the model gets a **tool** `gna_watch_arm` and a command `/gna-watch-arm` for the first cycle or a repair, never for ordinary re-arms. Gná's liveness is **zombie-aware**: `kill(pid, 0)` alone passes a zombie and a recycled pid, so the watcher reads `/proc/<pid>/stat` — the state character (Z/X = dead) and the starttime recorded at lock acquire (field 22; a mismatch means the kernel handed the pid to an unrelated process) — answers every ordinary wake: a **vacant** helm is taken (arm script via `gleipnir_lock_acquire`; Gná classifies an empty lock as `missing` so the reclaim takes it in place), while only a verifiably live other owner is refused as read-only. It drops its own lock on real process exit (`releaseLockIfOwned`). Gná's wake delivery is **echo-guarded**: an identical watcher message is sent at most once per drained state — when both durable queues (`state/.wake-queue` and the FM runner's `.agents/state/.wake-queue`) are empty, a repeat is the same news the primary already drained and is not re-delivered, so a long stale window cannot flood the follow-up queue.
123
+ - **OpenCode** owns continuity in `syn-watch-arm.js` (Sýn); the coordinator is published under `globalThis.__brokkOpenCodeWatchArm` so the turn-end guard can consult it first.
124
+ - **Claude Code** uses the `Stop` hook with `"asyncRewake": true` and a long timeout to keep the arm running out of band.
125
+ - **Codex / Cursor** run `syn-turnend-guard.sh` at Stop; they do **not** own a long-lived arm (no auto re-arm).
126
+
127
+ ### Part 3 — Turn-end guard
128
+
129
+ Bind the harness's "turn is about to end" event to `bin/syn-turnend-guard.sh`. If the guard prints the recovery instruction and exits **2**, the adapter must re-prompt instead of letting the turn end blind.
130
+
131
+ ```bash
132
+ bin/syn-turnend-guard.sh [--claude]
133
+ # reads Claude/Codex-shaped {"stop_hook_active":false} on stdin (ignored)
134
+ # exit 0 = supervision healthy OR never armed (inert)
135
+ # exit 2 = supervision was armed and the watcher is missing/stale; stderr carries recovery
136
+ ```
137
+
138
+ The guard is **inert until the first successful arm** writes `state/.supervision-armed`:
139
+
140
+ ```bash
141
+ # bin/syn-turnend-guard.sh:20
142
+ [ -f "$STATE/.supervision-armed" ] || exit 0
143
+ ```
144
+
145
+ It goes stale when `now - state/.watch.heartbeat > BROKK_WATCH_HEARTBEAT_STALE_SECONDS` (default 60).
146
+
147
+ ### Part 4 — PreToolUse seatbelts
148
+
149
+ Bind the harness's pre-tool event for shell commands to the two owner scripts. Exit **2** (or throw) blocks the tool call.
150
+
151
+ ```bash
152
+ bin/syn-arm-pretool-check.sh --command "<bash command>" # denies backgrounding the watcher arm
153
+ bin/syn-cd-pretool-check.sh --command "<bash command>" # denies a persistent escaping `cd`
154
+ ```
155
+
156
+ Both are **v0 inert-by-default** contracts: `syn-arm-pretool-check.sh` blocks only a command that backgrounds `syn-watch-arm.sh`; `syn-cd-pretool-check.sh` blocks only `cd .../../`. Owner scripts hold the policy; adapters only relay.
157
+
158
+ **A third seatbelt guards the assets** — `bin/syn-asset-pretool-check.sh` denies an
159
+ `edit`/`write` of a governed path until its owning asset has been read in the
160
+ session (reads are recorded in `state/asset-reads`).
161
+
162
+ ```bash
163
+ bin/syn-asset-pretool-check.sh --path "<file>" # exit 2 when the asset is not loaded
164
+ bin/syn-asset-pretool-check.sh --note "<asset path>" # record an asset as read
165
+ ```
166
+
167
+ Who governs what:
168
+
169
+ ```
170
+ governed[6]{path,load_first}:
171
+ "bin/ymir-install.sh",".agents/skills/galdr-ymirsystem/assets/installation.md"
172
+ "apps/hlidskjalf/**",".agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md"
173
+ "bin/mimir*",".agents/skills/galdr-ymirsystem/assets/memory-well.md"
174
+ "bin/nornir-* | config/cron.yaml",".agents/skills/galdr-ymirsystem/assets/nornir-jobs.md"
175
+ "bin/valknut-load.sh | .pi/** | .opencode/**",".agents/skills/galdr-ymirsystem/assets/harness-integration/README.md"
176
+ "bin/smidja* | .agents/skills/smidja/**",".agents/skills/galdr-ymirsystem/assets/smidja.md"
177
+ ```
178
+
179
+ The Pi extension `.pi/extensions/syn-turnend-guard.ts` relays it: `read` of an
180
+ asset is recorded, and an `edit`/`write` of a governed path is blocked with the
181
+ reason. The guard's own liveness check is **zombie-aware** too — `/proc/<pid>/stat`
182
+ field 3 (Z/X = a killed-but-unreaped or dead holder) fails a stale lock even when
183
+ `kill(0)` would report the pid alive, with `kill(0)` as the fallback when `/proc`
184
+ is unavailable. The same routes are stated in `AGENTS.md` and printed in the session
185
+ digest under `ASSET ROUTING`, and `compliance-check.sh` fails on a governed file
186
+ changed without its asset (the `assets` gate).
187
+
188
+ ### Part 5 (optional) — Re-arm / stop auto-arm
189
+
190
+ Some harnesses cannot synchronously own the watcher at Stop. The supported pattern is an **async rewrite** hook (Claude Code `"asyncRewake": true`; Cursor `followup_message` loop) that re-runs the arm and surfaces actionable output on stderr. If the harness has no such mechanism, do not fake it — declare the harness **turn-end-only** (Codex, Cursor) and rely on `einherjar-spawn.sh` fail-closed dispatch.
191
+
192
+ ---
193
+
194
+ ## 4. The adapter matrix
195
+
196
+ Legend: ✅ implemented · ⚠️ partial/inert-by-design · ❌ not implemented.
197
+
198
+ | Harness | Session-open injection | Watch arm owner | Turn-end guard | Pretool (arm) | Pretool (cd) | Re-arm |
199
+ |---|---|---|---|---|---|---|
200
+ | **OpenCode** | ✅ `.agents/harness/opencode/plugins/saga-sessionstart.js` | ✅ `.agents/harness/opencode/plugins/syn-watch-arm.js` (`session.idle`, coordinator key) | ✅ `.agents/harness/opencode/plugins/syn-turnend-guard.js` | ✅ `syn-pretool-check.js` | ✅ `syn-cd-check.js` | ✅ plugin-owned retries |
201
+ | **Pi** | ✅ `.pi/extensions/syn-turnend-guard.ts` (`before_agent_start`) | ✅ `.pi/extensions/gna-pi-watch.ts` (`gna_watch_arm` tool) | ✅ same extension (`agent_settled`) | ✅ same extension (`tool_call`) | ✅ same extension (`tool_call`) | ✅ Gná retry/backoff |
202
+ | **Claude Code** | ✅ `.claude/settings.json` `SessionStart` | ✅ `Stop` + `syn-watch-arm.sh --restart` (`asyncRewake`) | ✅ `Stop` + `syn-turnend-guard.sh --claude` | ❌ | ❌ | ✅ async rewake |
203
+ | **Codex** | ✅ `.codex/hooks.json` `SessionStart` | ⚠️ no long-lived arm | ✅ `Stop` + `syn-turnend-guard.sh` | ✅ `PreToolUse` matcher `Bash` | ✅ `PreToolUse` matcher `Bash` | ❌ |
204
+ | **Cursor** | ✅ `.cursor/hooks.json` `sessionStart` | ⚠️ interactive only | ✅ `stop` → `{"followup_message":...}` | ✅ `preToolUse` matcher `Shell` | ✅ `preToolUse` matcher `Shell` | ❌ |
205
+ | **Grok** | ❌ no `.grok/` in Ymir | ❌ | ❌ | ❌ | ❌ | ❌ |
206
+
207
+ ### Adapter files at a glance
208
+
209
+ | Path | Exports / shape | Contract parts |
210
+ |---|---|---|
211
+ | `.agents/harness/opencode/plugins/saga-sessionstart.js` | `export const SagaSessionstart` | 1 |
212
+ | `.agents/harness/opencode/plugins/syn-watch-arm.js` | `export const SynWatchArm` | 2 |
213
+ | `.agents/harness/opencode/plugins/syn-turnend-guard.js` | `export const SynTurnendGuard` | 2 (consult coordinator), 3 |
214
+ | `.agents/harness/opencode/plugins/syn-pretool-check.js` | `export const SynPretoolCheck` | 4 (arm) |
215
+ | `.agents/harness/opencode/plugins/syn-cd-check.js` | `export const SynCdCheck` | 4 (cd) |
216
+ | `.agents/harness/opencode/plugins/lib/rodd-operational-input.js` | `encodeRoddOperationalInput(root, kind, content)` | shared wire |
217
+ | `.pi/extensions/syn-turnend-guard.ts` | `export default function (pi: ExtensionAPI)` | 1, 3, 4 |
218
+ | `.pi/extensions/gna-pi-watch.ts` | `export default function (pi: ExtensionAPI)` | 2 |
219
+ | `.pi/extensions/ro.ts` | Ró — the calm presentation preference (`/calm`), state/ro | user |
220
+ | `.pi/shared/extensions/open-editor.ts` | `/edit [path]` and `ctrl+shift+e` — opens files from cwd in the Allfather's editor; strictly user-facing, no LLM tool. **Resolution:** `$VISUAL` → `$EDITOR` → the first editor that exists (`code cursor zed subl nvim vim hx helix nano micro emacs vi`), so a host that is not Omarchy — where Omarchy's own launcher or a bare `vi` may be absent — still gets a working editor instead of an ENOENT | user |
221
+ | `.pi/shared/extensions/herdr-agent-state.ts` | reports pane agent lifecycle state to herdr | 2 |
222
+ | `.pi/shared/extensions/todo.ts` | the todo surface | user |
223
+ | `.pi/shared/extensions/lib/rodd-operational-input.ts` | `encodeRoddOperationalInput`, `classifyRoddOperationalText`, `classifyRoddCurrentOperationalText` | shared wire |
224
+ | `.pi/extensions/lib/vordr-sessionstart-supervisor.mjs` | detached child supervisor (Vörðr) | 1 (transport) |
225
+ | `.claude/settings.json` | `hooks.SessionStart[]`, `hooks.Stop[]` | 1, 3, 5 |
226
+ | `.codex/hooks.json` | `hooks.SessionStart[]`, `hooks.PreToolUse[]`, `hooks.Stop[]` | 1, 3, 4 |
227
+ | `.cursor/hooks.json` | `hooks.sessionStart[]`, `hooks.preToolUse[]`, `hooks.stop[]` | 1, 3, 4 |
228
+
229
+ ---
230
+
231
+ ## 5. The environment contract
232
+
233
+ Every adapter and script resolves the same runtime roots. The overrides exist so tests and realm homes can relocate the runtime without touching the launcher.
234
+
235
+ | Variable | Meaning | Default |
236
+ |---|---|---|
237
+ | `BROKK_ROOT_OVERRIDE` | tracked code root (holds `bin/`, `AGENTS.md`) | resolved from script location |
238
+ | `BROKK_HOME` | private home (holds `data/ state/ config/`) | `BROKK_ROOT_OVERRIDE` or repo root |
239
+ | `BROKK_STATE_OVERRIDE` | state dir | `$BROKK_HOME/state` |
240
+ | `BROKK_DATA_OVERRIDE` | data dir | `$BROKK_HOME/data` |
241
+ | `BROKK_CONFIG_OVERRIDE` | config dir | `$BROKK_HOME/config` |
242
+ | `BROKK_REALM` | active realm | `data/realm.md` line 1, else `way-of` |
243
+ | `BROKK_SESSION_PID` | **live harness PID** bound by the session lock | `${BROKK_SESSION_PID:-$$}` |
244
+ | `BROKK_SESSIONSTART_INELIGIBLE` | `1` makes Pi's prerequisite exit 3 | unset |
245
+
246
+ `BROKK_SESSION_PID` is the load-bearing variable. The lock must bind to the **live harness process**, not the short-lived digest helper: Pi/OpenCode adapters pass `BROKK_SESSION_PID=String(process.pid)` into the spawned digest/arm child (`.pi/extensions/syn-turnend-guard.ts:277`, `.agents/harness/opencode/plugins/syn-watch-arm.js:428`). `bin/gleipnir-lock-lib.sh` writes it to `state/.lock`.
247
+
248
+ Full variable inventory: [`../runtime-components.md`](../runtime-components.md) §5.
249
+
250
+ ---
251
+
252
+ ## 6. Fail-closed dispatch rules
253
+
254
+ Dispatch is owned by `bin/einherjar-spawn.sh` (Norse: **Einherjar**). It **never silently falls back** to an unverified harness.
255
+
256
+ | Rule | Where | Behavior |
257
+ |---|---|---|
258
+ | Verified adapter set | `bin/einherjar-spawn.sh:53` | `VERIFIED_HARNESSES='opencode pi pi-signed'` |
259
+ | Unverified harness | `bin/einherjar-spawn.sh:224-232` | `error: harness '<h>' is not verified for direct launch` → exit 1 |
260
+ | Missing executable | `bin/einherjar-spawn.sh:233-236` | `error: harness '<h>' executable not found on PATH` → exit 1 |
261
+ | Missing auth/dependency | adapter scripts | report a plain reason; never a silent fallback |
262
+ | Raw launch escape hatch | `bin/einherjar-spawn.sh:207-211` | a `--harness` value containing whitespace is treated as a raw command, warns loudly, and is *not* on the verified set |
263
+ | Active dispatch profiles | `bin/einherjar-spawn.sh:212-214` | if `config/eindri-dispatch.json` exists, a fresh spawn **must** pass an explicit `--harness` resolved from its rules |
264
+ | Brief/flag drift | `bin/einherjar-spawn.sh:327-335` | refuses a ship launch whose brief's `Delivery contract: mode=<m>` disagrees with `--mode` |
265
+ | Isolation dependency | `bin/einherjar-spawn.sh:340-359` | `--isolation on` requires docker + `utgard-runner:latest`, else exit 1; `auto` reports the decision |
266
+
267
+ **Adding a harness to the verified set is a deliberate act:** implement all four contract parts, smoke-test them, then add the adapter name to `VERIFIED_HARNESSES` in `bin/einherjar-spawn.sh` (see §8).
268
+
269
+ ---
270
+
271
+ ## 7. How to add a new harness (step-by-step)
272
+
273
+ A harness is a runtime that can host Brokk. Adding one is a five-stage task.
274
+
275
+ ### Stage 0 — Inventory the harness's lifecycle
276
+
277
+ Answer these before writing anything:
278
+
279
+ 1. Does a **session-open** hook exist, and can it inject stdout into context (run-tier) or only post a message (nudge-tier)?
280
+ 2. Does an **idle/turn-end** event exist for the guard?
281
+ 3. Can a **long-lived arm process** be spawned at Stop, or only a synchronous hook?
282
+ 4. Is there a **pre-tool / before-tool** event for shell commands, and can it block?
283
+ 5. What env var names does the harness export (project dir, workspace root, agent marker)?
284
+
285
+ ### Stage 1 — Add detection to Hamr
286
+
287
+ `bin/hamr-harness.sh` (Norse: **Hamr**, "the shape a being wears") is the single source of harness identity. Two layers, in precedence order:
288
+
289
+ - **Layer 1 — verified env markers** (`bin/hamr-harness.sh:112-135`). Add your marker *after* the Cursor/Claude/Pi/Grok markers, documenting the version you verified it on.
290
+ - **Layer 2 — process ancestry** (`bin/hamr-harness.sh:136-169`). Add a `*<name>*` case to the `comm` matcher and to the bare-interpreter `args` matcher.
291
+
292
+ ```bash
293
+ # bin/hamr-harness.sh — Layer 1 pattern
294
+ [ "${MYHARNESS_AGENT:-}" = "1" ] && { echo myharness; return; }
295
+ # Layer 2 pattern
296
+ case "$(basename -- "$comm")" in
297
+ *myharness*) echo myharness; return ;;
298
+ esac
299
+ ```
300
+
301
+ Reuse the shared Cursor identity helpers (`hamr_cursor_process_matches`, `hamr_cursor_argv0_for_pid`) if your harness shares an interpreter.
302
+
303
+ ### Stage 2 — Write the adapter
304
+
305
+ Pick the closest existing adapter in the table (§4) and mirror its structure. The rules are non-negotiable:
306
+
307
+ - **Resolve the root** the same way: prefer `worktree` → `git -C <dir> rev-parse --show-toplevel` → `realpathSync(dir)`.
308
+ - **Call only `bin/` owner scripts.** Never re-implement digest, arm, guard, or classification logic.
309
+ - **Session-open:** call `bin/saga-sessionstart-run.sh`. Never `bin/saga-session-start.sh` directly from an adapter.
310
+ - **Watch arm:** require a live lock. If the arm reports `read-only`, stop; do not retry.
311
+ - **Turn-end:** re-prompt on exit 2. On any other exit, do nothing.
312
+ - **Seatbelts:** relay exit 2 as a block.
313
+ - **Encode operational text** with the Rödd bridge (`lib/rodd-operational-input.*`) before delivery.
314
+
315
+ ### Stage 3 — Register the hooks
316
+
317
+ Create the harness's config file (`.<harness>/...`) matching the real schema. See the deep-dive file for the exact JSON shape per harness. The absolute rule: **the hook must be self-locating** (use the harness's own project-dir env var or `pwd -P`) and must **no-op safely** when the runtime is absent.
318
+
319
+ ### Stage 4 — Verify (all four parts)
320
+
321
+ Run the commands in §9 and confirm the four contract parts. Do not mark the adapter done on a happy-path session-open alone; a guard that never fires is indistinguishable from a guard that is not wired.
322
+
323
+ ### Stage 5 — Mark verified + document
324
+
325
+ 1. Add the harness name to `VERIFIED_HARNESSES` in `bin/einherjar-spawn.sh:53`.
326
+ 2. Add a row to the matrix in §4 of this file and a deep-dive file next to it.
327
+ 3. If you want it as the default for dispatched Eindri, set `config/eindri-harness` (one line: `<harness> [<model>] [<effort>]`).
328
+ 4. Record the verified version and any marker quirks in this file's Gotchas and in `data/learnings.md`.
329
+
330
+ ---
331
+
332
+ ## 8. Adding a new harness to `VERIFIED_HARNESSES`
333
+
334
+ The verified set is the fail-closed gate. Edit exactly this line and nothing else:
335
+
336
+ ```bash
337
+ # bin/einherjar-spawn.sh:53
338
+ VERIFIED_HARNESSES='opencode pi pi-signed'
339
+ ```
340
+
341
+ Notes:
342
+
343
+ - `pi-signed` is a Pi variant (`BROKK_PI_HARNESS=pi-signed` / `FM_PI_HARNESS`); it maps to `pi` in `einherjar-spawn.sh`'s inline fallback but is a distinct token for the launch command (`bin/einherjar-spawn.sh:419-430`).
344
+ - Adding a raw command is **not** a substitute: `--harness "mycmd --flag"` bypasses verification and warns.
345
+
346
+ ---
347
+
348
+ ## 9. Verification
349
+
350
+ ### Syntax and schema
351
+
352
+ ```bash
353
+ cd "$BROKK_HOME"
354
+ for f in bin/*.sh; do bash -n "$f" || echo "SYNTAX FAIL: $f"; done
355
+ python3 -m json.tool config/eindri-dispatch.json >/dev/null && echo "dispatch JSON ok"
356
+ python3 -m json.tool .claude/settings.json >/dev/null && echo "claude JSON ok"
357
+ python3 -m json.tool .codex/hooks.json >/dev/null && echo "codex JSON ok"
358
+ python3 -m json.tool .cursor/hooks.json >/dev/null && echo "cursor JSON ok"
359
+ ```
360
+
361
+ ### Session-open injects, Go digest
362
+
363
+ ```bash
364
+ # Run as the harness would; it must print the Sága digest and exit 0.
365
+ bin/saga-sessionstart-run.sh --source startup | head -n 20
366
+ echo "exit=$?"
367
+
368
+ # Re-emit path after a completed startup:
369
+ test -f state/.session-start-complete && bin/saga-sessionstart-run.sh --source compact | head -n 3
370
+ ```
371
+
372
+ ### Watch arm arms, heartbeat, and exits on a wake
373
+
374
+ ```bash
375
+ # In one shell (must own the lock):
376
+ bin/syn-watch-arm.sh --restart # prints "watcher: started pid=... recovery-generation=..."
377
+ test -f state/.supervision-armed && echo "armed marker written"
378
+ test -s state/.watch.heartbeat && echo "heartbeat written"
379
+ # In another shell, drop a wake and watch the arm exit with "signal: wake queue":
380
+ : > state/.wake-queue
381
+ ```
382
+
383
+ ### Turn-end guard
384
+
385
+ ```bash
386
+ # Inert before first arm:
387
+ rm -f state/.supervision-armed
388
+ echo '{"stop_hook_active":false}' | bin/syn-turnend-guard.sh; echo "expected 0, got $?"
389
+ # Armed but stale heartbeat → exit 2:
390
+ touch state/.supervision-armed
391
+ rm -f state/.watch.heartbeat
392
+ echo '{"stop_hook_active":false}' | bin/syn-turnend-guard.sh; echo "expected 2, got $?"
393
+ ```
394
+
395
+ ### Seatbelts
396
+
397
+ ```bash
398
+ bin/syn-arm-pretool-check.sh --command 'bin/syn-watch-arm.sh --restart &'; echo "expected 2, got $?"
399
+ bin/syn-arm-pretool-check.sh --command 'bin/syn-watch-arm.sh --restart'; echo "expected 0, got $?"
400
+ bin/syn-cd-pretool-check.sh --command 'cd ../../etc'; echo "expected 2, got $?"
401
+ bin/syn-cd-pretool-check.sh --command 'ls -la'; echo "expected 0, got $?"
402
+ ```
403
+
404
+ ### Session lock ownership
405
+
406
+ ```bash
407
+ bin/saga-session-start.sh | sed -n '1,12p' # LOCK section: held vs READ-ONLY
408
+ ```
409
+
410
+ ---
411
+
412
+ ## 10. Gotchas
413
+
414
+ - **The digest helper must never hold the lock.** Bind `BROKK_SESSION_PID` to the live harness process or a second session will read the lock as stale and mutate shared state.
415
+ - **`saga-session-start.sh` acquires the lock but never releases it.** Release is the harness's business (process exit). A refused lock means **read-only**: no spawn, steer, merge, drain, or repair.
416
+ - **Don't call `bin/saga-session-start.sh` directly from an adapter.** Use `bin/saga-sessionstart-run.sh`; only the wrapper knows the source-routing rules (`startup` runs, `clear`/`compact` re-emits, `resume`/`reload`/`fork` nudges).
417
+ - **The turn-end guard is inert until `.supervision-armed` exists.** A guard test that never arms proves nothing. Arm first, then force a stale heartbeat.
418
+ - **`session.idle` fires often.** On OpenCode, the watch-arm plugin acts first and publishes `globalThis.__brokkOpenCodeWatchArm`; the guard plugin consults it and only calls `bin/syn-turnend-guard.sh` when the coordinator could not arm. Calling the guard first produces a false "turn would end blind" prompt during normal re-arms.
419
+ - **Never background the arm from the model's bash tool.** `syn-arm-pretool-check.sh` denies it; the adapter owns continuity. The arm is a plugin/extension child, not a tool call.
420
+ - **Exit-code semantics differ by host.** Claude's `SessionStart` exit 2 blocks initialization, so the run wrapper always exits 0 on the transport path; Pi's prerequisite uses exit 3 internally so preflight can distinguish a stand-down from a silent failure.
421
+ - **`hamr-harness.sh` has no `crew` subcommand — its subcommand is `eindri`.** `bin/einherjar-spawn.sh:170` calls `hamr-harness.sh crew`, which falls through to `detect_own` (`bin/hamr-harness.sh:231-236`); see §11. Until that call is fixed, `config/eindri-harness` is only honoured by the inline fallback, not the Hamr path.
422
+ - **Plugin auto-loading is path-based, not declared.** OpenCode loads `.agents/harness/opencode/plugins/*.js` automatically; there is no `plugin` array in `opencode.json`. The `package.json` only declares `"type": "module"`.
423
+ - **Grok is not wired in Ymir.** Upstream Brokk ships `.grok/hooks/*.json`; Ymir has no `.grok/`. Treat Grok as unverified (see §11).
424
+ - **Windows timing.** OpenCode and Pi raise the arm-ready budget to 35s on `win32` so a slow Git Bash cold start is not SIGTERMed mid-confirmation (`.agents/harness/opencode/plugins/syn-watch-arm.js:17-19`, `.pi/extensions/gna-pi-watch.ts:91-94`).
425
+
426
+ ---
427
+
428
+ ## 11. Known code-vs-doc disagreements (truth is the code)
429
+
430
+ | Plan 29 says | Code says (truth) |
431
+ |---|---|
432
+ | `.agents/harness/opencode/plugins/syn-sessionstart.js` | actual file is `.agents/harness/opencode/plugins/saga-sessionstart.js` |
433
+ | `.agents/harness/opencode/plugins/gna-watch-arm.js` (plan §1) | actual file is `.agents/harness/opencode/plugins/syn-watch-arm.js` (OpenCode's watcher is **Sýn**, not Gná; Gná exists only on Pi) |
434
+ | Plan §13 "still to build: `bin/hamr-harness.sh`; the `.opencode`/Claude/Codex/Cursor adapters; `bin/einherjar-spawn.sh`; …" | all of these are **now landed**; plan §13 is stale |
435
+ | Digest §6 lists 9 stages including **NETWORK CHECKS** and **FLEET DIGEST from `data/backlog.md`** | `bin/saga-session-start.sh` currently prints **8** sections (LOCK, BOOTSTRAP, WAKE QUEUE, SUPERVISION, FLEET DIGEST, CONTEXT DIGEST, CRON START, NEXT STEP); there is **no NETWORK CHECKS section**, and the fleet digest counts `state/*.meta` + `docs/masterplan.md` orders, not `data/backlog.md` |
436
+ | Plan §7 "Cursor … run interactive only (no headless turn-end)" | `.cursor/hooks.json` **does** implement `sessionStart` (`additional_context`) and `stop` (`followup_message`) |
437
+ | Plan §7 "Codex … bounded foreground checkpoint … nudge-tier" | `.codex/hooks.json` implements run-tier `SessionStart` + `PreToolUse` + `Stop` |
438
+ | Plan §7 "Grok — project hooks (`grok --trust`)" | no `.grok/` exists in Ymir; Grok is unimplemented |
439
+ | Plan §7 "Claude Code … SessionStart + Stop hooks" | correct, but Ymir's `.claude/settings.json` has **no `PreToolUse`** seatbelt entries (upstream Brokk does) |
440
+
441
+ The authoritative interface is always the code listed in [`../runtime-components.md`](../runtime-components.md); report drift there.
442
+
443
+ ---
444
+
445
+ ## 12. Provenance
446
+
447
+ The adapter pattern is ported from the validated upstream **Brokk** agent-distro harness adapters (`bin/fm-harness.sh`, `bin/fm-sessionstart-run.sh`, `.agents/harness/opencode/plugins/fm-primary-*.js`, `.pi/extensions/fm-primary-*.ts`, `.claude/settings.json`, `.codex/hooks.json`, `.cursor/hooks.json`, `.grok/hooks/*.json`). Ymir adopts the *mechanism* and renames every component per plan 29 §12 (Sága, Sýn, Gná, Vörðr, Rödd, Gleipnir, Hamr, Einherjar, Erindi, Vör, Nornir). The upstream names (`fm-*`, "Allfather") are provenance only and must never name a Ymir component.
448
+
449
+ ---
450
+
451
+ ## 13. The Well — memory for every harness (engram)
452
+
453
+ The well is **Mimirsbrunn**, backed by the validated OSS engine **engram**. It is
454
+ one repo-local store, `.agents/memory/kaia.engram`, reached two ways:
455
+
456
+ **HTTP bridge (`:4602`)** — `bin/mimir-bridge.py`, raised by
457
+ `bin/mimir-bridge.sh` (and by `scripts/start.sh` + `bin/saga-session-start.sh`).
458
+ It wraps the engram library so the gate API, `bin/mimir.sh`, and
459
+ `bin/mimir-ingest.sh` can drink over the small HTTP contract:
460
+
461
+ ```
462
+ GET /health -> {status, store, episodes, agents}
463
+ GET /recall?q&k&mode -> {results:[{score, distance, episode}]}
464
+ GET /recent?limit -> {episodes:[...]}
465
+ GET /timeline?entity -> {facts:[...]}
466
+ GET /inspect -> {episodes, agents, store}
467
+ POST /observe {content,...} -> {id}
468
+ ```
469
+
470
+ **MCP server (stdio)** — `engram-mcp --db <store> --agent-id <harness>`, so any
471
+ MCP-capable harness gets `remember`, `recall`, `why`, `forget`, `stats` with no
472
+ integration code. Registered per harness (each writes under its own agent id):
473
+
474
+ | Harness | Config | Agent id |
475
+ |---|---|---|
476
+ | OpenCode | `opencode.json` → `mcp.engram` (+ `~/.config/opencode/opencode.json`) | `opencode` |
477
+ | Pi | `.pi/mcp.json` (pass `pi --mcp-config .pi/mcp.json`) | `pi` |
478
+ | Claude Code | `~/.claude.json` → `mcpServers.engram` | `claude` |
479
+ | Cursor | `~/.cursor/mcp.json` → `mcpServers.engram` | `cursor` |
480
+ | Codex | `~/.codex/config.toml` → `[mcp_servers.engram]` | `codex` |
481
+
482
+ The engine needs the `mcp<2` SDK for `engram-mcp` (v2 renamed `FastMCP` to
483
+ `MCPServer`, which breaks engram 1.x/2.x):
484
+ `python3 -m pip install --user --break-system-packages 'mcp<2'`.
485
+
486
+ Rule: **drink before you act, water it after** — recall on the way in, and
487
+ `POST /observe` (or the `remember` MCP tool) after a lesson lands.
488
+
489
+ ---
490
+
491
+ ## 14. Agent locations — `.agents/agents` is the source of truth
492
+
493
+ Agent profiles live **only** in `.agents/agents/*.md` (the canonical, with the
494
+ harness config like `mode`/`model`/`permission` in their frontmatter). The
495
+ harness directories **bind** them by symlink — they are never hand-written
496
+ duplicates:
497
+
498
+ - OpenCode: `.opencode/agent/<name>.md` → `../../.agents/agents/<profile>.md`
499
+ - Pi: `.pi/agents/<profile>.md` → the same canonical files
500
+
501
+ `bin/valknut-load.sh` creates the symlinks (`--opencode`, `--pi`, `--global`,
502
+ `--all`). **Every harness gets EVERY agent** — claude, codex, cursor and opencode
503
+ are bound by the same loader pass as pi, so no harness is left holding a
504
+ hand-made subset. Naming differs by harness and must be respected:
505
+
506
+ ```
507
+ agent_binding[5]{harness,dir,name_rule}:
508
+ "opencode",".opencode/agent/","the frontmatter `name:` — bragi.md -> bragi-marketer.md"
509
+ "pi",".pi/agents/","the profile file name — bragi-marketer.md"
510
+ "claude",".claude/agents/","the profile file name"
511
+ "codex",".codex/agents/","the profile file name"
512
+ "cursor",".cursor/agents/","the profile file name"
513
+ ```
514
+
515
+ To change an agent, edit `.agents/agents/*.md` and re-run the loader; never edit
516
+ a harness directory (they are all links).
517
+
518
+ ### Skill location — the same law, one tree
519
+
520
+ Skills have **one** tree too: `.agents/skills/`. Every harness reaches it, each
521
+ by the mechanism that harness actually reads — and a harness that silently
522
+ loads nothing is invisible from the code, so `compliance-check.sh`'s `harnesses`
523
+ gate asserts all four:
524
+
525
+ | Harness | How it reaches `.agents/skills` |
526
+ |---|---|
527
+ | **opencode** | `skills.paths: [".agents/skills"]` in `opencode.json` (the loader merges it in and re-asserts it on every run) |
528
+ | **pi** | **native discovery** — it walks up from the cwd to `.agents/skills` (and `~/.agents/skills`). No link, no config: a second root under `.pi/` would invite double-loading, exactly as the extensions rule warns |
529
+ | **claude · codex · cursor** | `<harness>/skills -> ../.agents/skills`, created by `bin/valknut-load.sh` (their project scope is their own directory) |
530
+
531
+ **Do not** copy a `SKILL.md` into a harness directory: a copy is drift, and a
532
+ nested `SKILL.md` carrying frontmatter is loaded as a *second, phantom* skill by
533
+ every recursive scanner (the `harnesses` gate refuses it).
534
+
535
+ ### opencode.json has two writers — and neither may overwrite
536
+
537
+ `opencode.json` is untracked (it carries absolute paths) and two things write it:
538
+
539
+ ```
540
+ writers[2]{writer,owns}:
541
+ "bin/valknut-load.sh","STRUCTURE — the base keys, the agent blocks, the skills path; rendered from opencode.json.example"
542
+ "bin/agents-config.sh apply","the ROSTER — providers and per-agent models, from config/agents.yaml"
543
+ ```
544
+
545
+ **Both merge; neither overwrites.** The loader's `config_out` adds missing keys (
546
+ deep, `setdefault`-style), ensures `skills.paths`, and re-asserts nothing else;
547
+ `agents-config` does the same for providers and models. This is not tidiness —
548
+ the loader used to re-render from the example with `sed` + `mv`, and because the
549
+ example carried only `llama.cpp`, **every loader run deleted the Apodex
550
+ provider**, which lived only in the live file. A blind render of a file two
551
+ writers share is a silent data loss; the merge is the fix.
552
+
553
+ ## 15. The Eindri roster (bound agents)
554
+
555
+ Every skill names an owner agent in `.agents/skills/README.md`; the fleet below
556
+ is the full set of canonical profiles, all bound into all five harnesses.
557
+
558
+ Canonical profiles in `.agents/agents/*.md`, bound as symlinks:
559
+
560
+ ```
561
+ einherjar[20]{figure,craft,domain,engine}:
562
+ "Brokk","primary — the bellows","ymirlabs","—"
563
+ "Sindri","developer / smith","brokkforge","Chrome DevTools"
564
+ "Bragi","marketer / skald","utgard","Firecrawl + browser-use (+ Scrapy)"
565
+ "Hnoss","designer / shaper","utgard","OpenDesign"
566
+ "Huginn","researcher / sage","muninn","—"
567
+ "Mímir","planner / the wise","ymirlabs","—"
568
+ "Forseti","reviewer / the just","runestone","—"
569
+ "Snotra","documenter / the wise-woman","runestone","—"
570
+ "Kvasir","scout / the knowing","ymirlabs","—"
571
+ "Galdr","builder — CLI ergonomics","ymirlabs","—"
572
+ "Týr","judge — the 10 principles + the gates","runestone","—"
573
+ "Sága","seeress — bearings + recap","ymirlabs","—"
574
+ "Muninn","rememberer — memory curation","muninn","—"
575
+ "Urðr","fate — the hold lifecycle","ymirlabs","—"
576
+ "Frigg","knowing — consent gate","ymirlabs","—"
577
+ "Vör","aware — diagnostics","ymirlabs","—"
578
+ "Sýn","seeing — stuck-worker recovery","ymirlabs","—"
579
+ "Jörð","grounded — project registry","ymirlabs","—"
580
+ "Gróa","renewer — self-update","ymirlabs","—"
581
+ "Völundr","master smith — Smíðja's orchestrator","brokkforge","—"
582
+ ```
583
+
584
+ Bind with `bin/valknut-load.sh --all` (OpenCode: `.opencode/agent/<name>.md`; Pi:
585
+ `.pi/agents/<profile>.md`) — never edit the harness dirs.
586
+
587
+ ## Pi extension single-home (2026-09-12)
588
+
589
+ Pi loads **both** the project `.pi/extensions/` and the global
590
+ `~/.pi/agent/extensions/` directories; because it does not de-duplicate by
591
+ extension or tool name, an extension present in both makes `pi` exit with
592
+ `Tool "<name>" conflicts with …` and **no agent can be seated** (herdr reports
593
+ "the pane must sit at an interactive shell prompt", a confusing symptom).
594
+
595
+ Rule: **one home per extension.**
596
+
597
+ - Shared extensions (`todo.ts`, `herdr-agent-state.ts`, `open-editor.ts`) live
598
+ **only** in `~/.pi/agent/extensions/` — used by every project, Ymir and
599
+ Omarchy alike.
600
+ - The repo `.pi/extensions/` holds **only Ymir-unique** extensions
601
+ (`gna-pi-watch.ts`, `ro.ts`, `skuld-branch-supervision.ts`,
602
+ `syn-turnend-guard.ts`, `lib/`).
603
+ - Never copy a shared extension back into the repo; that re-arms the collision.
604
+
605
+ **Shipping the shared extensions (added 2026-09-12).** A rule that keeps the
606
+ extensions outside the repo would also keep them from every new operator, so the
607
+ repo carries their **source** at `.pi/shared/extensions/` — a path pi does not
608
+ load, therefore collision-free — and the loader deploys it into the single home:
609
+
610
+ ```bash
611
+ bin/valknut-load.sh --pi # deploys .pi/shared/extensions/*.ts -> ~/.pi/agent/extensions/
612
+ ```
613
+
614
+ The deploy copies (never links: a broken link would silently disable a tool),
615
+ skips files that are already identical, and reports what it placed. It runs
616
+ whenever the Pi surface is bound, with or without `--global`. Adding a shared
617
+ extension is therefore two steps: put the source in `.pi/shared/extensions/`, and
618
+ let the loader place it — **never** place it in `.pi/extensions/`.
619
+
620
+ ## OpenCode agent `tools` key (2026-09-12)
621
+
622
+ OpenCode requires the frontmatter `tools:` key to be an **object** of its own
623
+ built-in tools. Our profiles list Ymir capabilities (`vector_db`,
624
+ `hermes_runner`, `herder`, `yggdrasil`, `supabase`, `opendesign`,
625
+ `chrome_devtools`), which are not OpenCode tools and which OpenCode rejects as
626
+ `Expected object | undefined, got [...] tools`. Those lists are therefore carried
627
+ under **`ymir_tools:`**; permission is expressed by the `permission:` block.
628
+
629
+ ## Canonical layout — the ONE remap (authoritative; do not redo)
630
+
631
+ **Source of truth is `.agents/`. Harness directories are symlinks, never copies.**
632
+
633
+ ```
634
+ canonical[3]{kind,canonical,load_path}:
635
+ "agent profiles",".agents/agents/<profile>.md",".opencode/agent/<name>.md · .pi/agents/<name>.md (symlinks)"
636
+ "OpenCode plugins",".agents/harness/opencode/plugins/",".opencode/plugins (symlink)"
637
+ "skills",".agents/skills/","loaded via opencode.json skills.paths"
638
+ ```
639
+
640
+ Rules:
641
+ - **Edit only `.agents/`.** Never edit a file under `.opencode/` or `.pi/` — those are
642
+ symlinks to `.agents/` (e.g. `.opencode/agent/bragi.md` links to
643
+ `.agents/agents/bragi-marketer.md`).
644
+ - After any change: `bin/valknut-load.sh --all` to rebind.
645
+ - **OpenCode requires REAL `.opencode/{node_modules,package.json,.gitignore}`** — the
646
+ dependency store. Symlinking them hit ELOOP + untracked files and was reverted.
647
+ - So `.opencode` holds: symlinked `agent/` + `plugins`, and the real dep store. It
648
+ cannot be deleted; it is already minimized. No agent/profile content lives there.
649
+
650
+ ## Asking the Allfather — `ask_user_question` (2026-09-12)
651
+
652
+ The system can ask the Allfather instead of guessing. Adopted (open-source-first)
653
+ from `@juicesharp/rpiv-ask-user-question` (MIT), pinned **project-locally** in
654
+ `.pi/settings.json` so every machine/user that has the repo gets it.
655
+
656
+ - Gives Pi one tool, `ask_user_question`: a terminal dialog of up to four
657
+ questions with authored options (+ descriptions/previews), a free-text row,
658
+ per-question and global notes, and a Submit review tab.
659
+ - Non-interactive runs simply don't see the tool (never a failing call).
660
+ - Config (read-only): `~/.config/rpiv-ask-user-question/config.json`.
661
+ - Use it at real decision points — where a wrong assumption costs a rework.
662
+
663
+ **Two extension paths, and they are not interchangeable** (2026-09-12):
664
+
665
+ | Path | Loaded by | Holds |
666
+ |---|---|---|
667
+ | `.pi/extensions/` | pi, as **project-local** extensions | the governance set: `syn-turnend-guard.ts`, `gna-pi-watch.ts`, `ro.ts`, `skuld-branch-supervision.ts` |
668
+ | `.pi/shared/extensions/` | **deployed** by `bin/valknut-load.sh --pi` into `${HOME}/.pi/agent/extensions/` | the user-facing trio: `open-editor.ts`, `herdr-agent-state.ts`, `todo.ts` |
669
+
670
+ The same extension in **both** paths makes pi exit with a tool-name conflict and
671
+ no agent can be seated — which is why the shared trio has exactly one home and is
672
+ deployed, never duplicated. Editing a path from the table above without checking
673
+ which of the two it is will edit a file that is not there.