@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,262 @@
1
+ # OpenCode Harness Adapter (Öppencode)
2
+
3
+ > **Purpose:** Rebuild, verify, or extend the OpenCode adapter — the `.opencode/plugins/*.js` shims that seat Brokk on `session.created`, arm **Sýn** on `session.idle`, guard the turn end, and enforce the PreToolUse seatbelts.
4
+
5
+ OpenCode is Ymir's **primary harness** (`config/eindri-harness` = `opencode`; `opencode.json` sets `"default_agent": "brokk"`). Its adapters are Node ESM plugins auto-loaded from `.opencode/plugins/`.
6
+
7
+ ---
8
+
9
+ ## 1. Files
10
+
11
+ | File | Export | Norse role | Contract part |
12
+ |---|---|---|---|
13
+ | `.opencode/plugins/saga-sessionstart.js` | `SagaSessionstart` | **Sága** — runs the digest and injects it into the session | Session-open injection |
14
+ | `.opencode/plugins/syn-watch-arm.js` | `SynWatchArm` | **Sýn** — owns watcher continuity | Watch arm |
15
+ | `.opencode/plugins/syn-turnend-guard.js` | `SynTurnendGuard` | **Sýn** — refuses a blind turn end | Turn-end guard |
16
+ | `.opencode/plugins/syn-pretool-check.js` | `SynPretoolCheck` | **Sýn** — arm seatbelt | PreToolUse (arm) |
17
+ | `.opencode/plugins/syn-cd-check.js` | `SynCdCheck` | **Sýn** — cd seatbelt | PreToolUse (cd) |
18
+ | `.opencode/plugins/lib/rodd-operational-input.js` | `encodeRoddOperationalInput` | **Rödd** — the wire encoder | shared |
19
+ | `.opencode/plugins/package.json` | — | declares `"type": "module"` | — |
20
+
21
+ There is **no** `plugin` array in `opencode.json`; OpenCode discovers `.opencode/plugins/*.js` by path. The plugins are plain ESM and import only Node builtins plus their local `./lib/`.
22
+
23
+ ---
24
+
25
+ ## 2. How the plugins are shaped
26
+
27
+ Each plugin is a named export that receives the OpenCode plugin context and returns an object of hook handlers:
28
+
29
+ ```js
30
+ // .opencode/plugins/saga-sessionstart.js:44
31
+ export const SagaSessionstart = async ({ client, directory, worktree }) => {
32
+ const root = worktree ? resolvePath(worktree) : await resolveRoot(directory);
33
+ return { event: async ({ event }) => { /* ... */ } };
34
+ };
35
+ ```
36
+
37
+ | Context field | Meaning |
38
+ |---|---|
39
+ | `client` | OpenCode SDK client; `client.session.promptAsync({ path:{id}, body:{parts:[{type:"text",text}]} })` injects a message |
40
+ | `directory` | the session working directory |
41
+ | `worktree` | the linked worktree root when OpenCode runs in one (an Eindri home) |
42
+ | `event` | callback receiving `{ event }`, where `event.type` is the lifecycle event |
43
+ | `tool.execute.before` | callback receiving `(input, output)`; **throw** to block |
44
+
45
+ ### Root resolution (all plugins)
46
+
47
+ ```js
48
+ async function resolveRoot(anchor) {
49
+ if (!anchor) return "";
50
+ const result = await runProcess("git", ["-C", anchor, "rev-parse", "--show-toplevel"]);
51
+ const root = result.stdout.trim();
52
+ if (result.code === 0 && root) return root;
53
+ return resolvePath(anchor); // realpathSync(anchor) || resolve(anchor)
54
+ }
55
+ ```
56
+
57
+ `worktree` wins when set, so an Eindri launched by `bin/einherjar-spawn.sh` into `.yggdrasil/<id>` resolves its **own** worktree root and never the primary checkout.
58
+
59
+ ---
60
+
61
+ ## 3. Event hooks used
62
+
63
+ | Event | Plugin | Action |
64
+ |---|---|---|
65
+ | `session.created` | `saga-sessionstart.js` | run `bin/saga-sessionstart-run.sh` once per session id; inject its stdout |
66
+ | `session.idle` | `syn-watch-arm.js` | ensure an arm cycle is running (`sessionOwnsLock`, primary root, `shouldArm`) |
67
+ | `session.idle` | `syn-turnend-guard.js` | first ask the watch-arm coordinator; only if it could not arm, run `bin/syn-turnend-guard.sh` and re-prompt on exit 2 |
68
+ | `tool.execute.before` | `syn-pretool-check.js` | run `bin/syn-arm-pretool-check.sh --command <cmd>`; throw on exit 2 |
69
+ | `tool.execute.before` | `syn-cd-check.js` | run `bin/syn-cd-pretool-check.sh --command <cmd>`; throw on exit 2 |
70
+
71
+ ### 3.1 `session.created` — Sága injection
72
+
73
+ `.opencode/plugins/saga-sessionstart.js:48-76`:
74
+
75
+ 1. Ignore unless `event.type === "session.created"`.
76
+ 2. Extract `sessionID = event.properties?.info?.id ?? event.properties?.sessionID`.
77
+ 3. Skip if already handled (`handledSessions` Set) or no root.
78
+ 4. Run `${root}/bin/saga-sessionstart-run.sh` with no args.
79
+ 5. If exit ≠ 0 or empty output, silently return (**never block the session**).
80
+ 6. Encode the digest via the Rödd bridge; on encoder failure fall back to the raw digest.
81
+ 7. `client.session.promptAsync({ path:{id:sessionID}, body:{parts:[{type:"text",text}]} })`; delivery errors are swallowed.
82
+
83
+ Because the plugin **runs** the wrapper and injects the result, OpenCode is run-tier in execution with nudge-style delivery.
84
+
85
+ ### 3.2 `session.idle` — Sýn arm ownership
86
+
87
+ `.opencode/plugins/syn-watch-arm.js:490-505`:
88
+
89
+ ```js
90
+ export const SynWatchArm = async ({ client, directory, worktree }) => {
91
+ const root = worktree ? resolvePath(worktree) : await resolveRoot(directory);
92
+ const paths = effectivePaths(root);
93
+ globalThis[COORDINATOR_KEY] = {
94
+ ensureArmed: (sessionID, activeClient) => ensureArm(paths, sessionID, activeClient ?? client),
95
+ };
96
+ return {
97
+ event: async ({ event }) => {
98
+ if (event.type !== "session.idle") return;
99
+ const sessionID = event.properties?.sessionID;
100
+ if (!sessionID) return;
101
+ void ensureArm(paths, sessionID, client);
102
+ },
103
+ };
104
+ };
105
+ ```
106
+
107
+ `COORDINATOR_KEY = "__brokkOpenCodeWatchArm"` (line 15) is the shared handoff the turn-end guard reads.
108
+
109
+ Arm gating (`.opencode/plugins/syn-watch-arm.js`):
110
+
111
+ | Gate | Function | Rule |
112
+ |---|---|---|
113
+ | primary root only | `isPrimaryRoot` (102-111) | `AGENTS.md` + `bin/` must exist and `git rev-parse --git-dir` must equal `--git-common-dir` (a linked Eindri worktree reports a different git-dir and must not own supervision) |
114
+ | live lock | `sessionOwnsLock` (123-140) | walk ancestors of `process.pid` up to 8 levels; must equal `state/.lock` pid |
115
+ | arm needed | `shouldArm` (113-121) | false if `state/.afk` exists; true if `config/x-mode.env` exists; else true only if some `state/*.meta` exists |
116
+ | single flight | `launchInFlight` (470-488) | serializes concurrent `session.idle` callbacks |
117
+
118
+ The spawned command is:
119
+
120
+ ```js
121
+ // .opencode/plugins/syn-watch-arm.js:355
122
+ const armChild = spawn("bash", ["-lc",
123
+ 'config_dir="${BROKK_CONFIG_OVERRIDE:-$BROKK_HOME/config}"; [ -f "$config_dir/x-mode.env" ] && . "$config_dir/x-mode.env"; exec "$BROKK_ROOT_OVERRIDE/bin/syn-watch-arm.sh" --restart'],
124
+ { cwd: paths.root, env, stdio: ["ignore","pipe","pipe"] });
125
+ ```
126
+
127
+ `env` includes `BROKK_HOME`, `BROKK_ROOT_OVERRIDE`, `BROKK_CONFIG_OVERRIDE`, `BROKK_STATE_OVERRIDE`, `BROKK_WATCH_PREDECESSOR_ARM_PID`.
128
+
129
+ Continuity: on any non-actionable close, `scheduleRetry` re-arms with exponential backoff (`BROKK_WATCH_REARM_RETRY_BASE_MS` 250 → `..._MAX_MS` 4000, limit `..._LIMIT` 5). On an actionable line, `restoreAfterActionableClose` starts a successor and then `deliverActionableWake` prompts the session.
130
+
131
+ ### 3.3 `session.idle` — Sýn turn-end guard
132
+
133
+ `.opencode/plugins/syn-turnend-guard.js:65-104`:
134
+
135
+ 1. Ignore unless `event.type === "session.idle"`.
136
+ 2. If `skipNextIdle`, clear and return (prevents a re-prompt loop).
137
+ 3. `letWatchArmRun(sessionID, client)` calls `globalThis.__brokkOpenCodeWatchArm.ensureArmed(...)`; return early on `armed`, `wake`, or `failed`.
138
+ 4. Otherwise run `${root}/bin/syn-turnend-guard.sh` with stdin `{"stop_hook_active":false}`.
139
+ 5. Only on exit **2**: encode the fixed recovery text + stderr through Rödd and `promptAsync`; set `skipNextIdle`.
140
+
141
+ The ordering matters: **watch-arm is asked first**. The guard exists for the residual case where the coordinator could not arm.
142
+
143
+ ### 3.4 `tool.execute.before` — seatbelts
144
+
145
+ `.opencode/plugins/syn-pretool-check.js:50-60`:
146
+
147
+ ```js
148
+ "tool.execute.before": async (input, output) => {
149
+ if (!root || input?.tool !== "bash") return;
150
+ const command = output?.args?.command;
151
+ if (!command || typeof command !== "string") return;
152
+ const result = await runProcess(`${root}/bin/syn-arm-pretool-check.sh`, ["--command", command]);
153
+ if (result.code !== 2) return;
154
+ throw new Error(result.stderr.trim() || "denied by the watcher-arm PreToolUse seatbelt");
155
+ }
156
+ ```
157
+
158
+ `.opencode/plugins/syn-cd-check.js` is identical but calls `bin/syn-cd-pretool-check.sh`. A thrown error blocks the tool call; the owner scripts hold the policy (`syn-arm-pretool-check.sh` denies backgrounding `syn-watch-arm.sh`; `syn-cd-pretool-check.sh` denies `cd .../../`).
159
+
160
+ ---
161
+
162
+ ## 4. The Rödd bridge
163
+
164
+ `.opencode/plugins/lib/rodd-operational-input.js` is the **only** way the plugins encode operational text. It is a cross-language adapter; `bin/rodd-operational-input.sh` owns the protocol.
165
+
166
+ ```js
167
+ // .opencode/plugins/lib/rodd-operational-input.js:6-15
168
+ const adapterRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
169
+ export function encodeRoddOperationalInput(root, kind, content) {
170
+ const requested = `${root}/bin/rodd-operational-input.sh`;
171
+ const script = existsSync(requested) ? requested : `${adapterRoot}/bin/rodd-operational-input.sh`;
172
+ // spawn(script, ["encode", kind], ...) ; stdin = content ; stdout = encoded
173
+ }
174
+ ```
175
+
176
+ - Signature: `encodeRoddOperationalInput(root, kind, content) => Promise<string>`.
177
+ - It spawns `bin/rodd-operational-input.sh encode <kind>` with the body on stdin.
178
+ - It prefers the runtime's own `bin/` and falls back to the adapter's repo `bin/` (three levels up from `.opencode/plugins/lib/`).
179
+ - Valid `kind`s are owned by the shell script (`RODD_KINDS`): `session-start watcher turn-end-guard away-supervisor launch-brief branch-outcome`, plus the special `from-brokk` carrier.
180
+ - Wire form: `U+2063 RODD_OP: v1 <kind>: <body>`.
181
+
182
+ Do **not** hand-build the marker in a plugin; call the bridge (or import `RODD_*` only from the shell library).
183
+
184
+ ---
185
+
186
+ ## 5. Configuration (`opencode.json`)
187
+
188
+ The adapter reads runtime roots from the environment and OpenCode behaviour from `opencode.json`.
189
+
190
+ | Key | Value in Ymir | Why it matters |
191
+ |---|---|---|
192
+ | `default_agent` | `"brokk"` | a bare OpenCode launch opens as Brokk |
193
+ | `agent.brokk.mode` | `"primary"` | the primary agent |
194
+ | `agent.*.mode` | `subagent` (build, builder, plan, planner, reviewer, documenter, scout) | dispatched Eindri profiles |
195
+ | `skills.paths` | `[".agents/skills"]` | single skill source; the `galdr` skill loads from here |
196
+ | `model` | `""` | empty → harness default |
197
+ | `permission` | `allow` for read/edit/glob/grep/bash/task/skill/question/webfetch/websearch/external_directory | primary autonomy |
198
+
199
+ OpenCode does **not** need a `plugin` declaration: `plugins/*.js` are auto-loaded. The `.opencode/plugins/package.json` exists only to force ESM:
200
+
201
+ ```json
202
+ { "private": true, "type": "module" }
203
+ ```
204
+
205
+ ---
206
+
207
+ ## 6. Install / enable / verify
208
+
209
+ ### Enable
210
+
211
+ No install step is required beyond the files being present. OpenCode auto-loads `.opencode/plugins/*.js` on startup. To confirm the plugin modules parse:
212
+
213
+ ```bash
214
+ cd "$BROKK_HOME"
215
+ node --input-type=module -e 'await import("./.opencode/plugins/saga-sessionstart.js"); await import("./.opencode/plugins/syn-watch-arm.js"); await import("./.opencode/plugins/syn-turnend-guard.js"); await import("./.opencode/plugins/syn-pretool-check.js"); await import("./.opencode/plugins/syn-cd-check.js"); console.log("plugins import ok")'
216
+ ```
217
+
218
+ ### Verify the four contract parts
219
+
220
+ ```bash
221
+ # 1) session-open: the wrapper the plugin runs
222
+ bin/saga-sessionstart-run.sh | head -n 15 ; echo "exit=$?"
223
+
224
+ # 2) Rödd encode round-trip (what the plugin calls)
225
+ printf 'hello' | bin/rodd-operational-input.sh encode session-start | bin/rodd-operational-input.sh kind
226
+ # expected: session-start
227
+
228
+ # 3) watch arm + heartbeat + wake exit
229
+ bin/syn-watch-arm.sh --restart & # only with a live lock; prints watcher: started...
230
+ sleep 1
231
+ test -s state/.watch.heartbeat && echo "heartbeat ok"
232
+ : > state/.wake-queue # arm should exit with "signal: wake queue"
233
+
234
+ # 4) seatbelts (exit 2 = block)
235
+ bin/syn-arm-pretool-check.sh --command 'foo & bar'; echo "expect 0 -> $?"
236
+ bin/syn-arm-pretool-check.sh --command 'bin/syn-watch-arm.sh &'; echo "expect 2 -> $?"
237
+ bin/syn-cd-pretool-check.sh --command 'cd ../..'; echo "expect 2 -> $?"
238
+ ```
239
+
240
+ ### End-to-end smoke
241
+
242
+ ```bash
243
+ # OpenCode session in BROKK_HOME: the first injected message must begin with the
244
+ # Sága digest (or the RODD_OP marker wrapping it), and the session must address
245
+ # the operator as Allfather. Then drop a wake and confirm the watcher fires.
246
+ : > state/.wake-queue
247
+ ```
248
+
249
+ ---
250
+
251
+ ## 7. Gotchas
252
+
253
+ - **Two `session.idle` plugins race by design — but not for the guard.** `syn-watch-arm.js` and `syn-turnend-guard.js` both listen on `session.idle`; the guard *asks* the arm coordinator first, and only runs the guard when arming failed. Reversing this produces spurious "TURN WOULD END BLIND" prompts during normal operation.
254
+ - **`handledSessions` is per-process, never persisted.** After an OpenCode restart the digest runs again for a new session id; that is intended. Do not persist the Set — a resumed session with a new id must still be seated.
255
+ - **`promptAsync` failures are swallowed.** If OpenCode's SDK errors, the digest is silently dropped. Diagnose by running `bin/saga-sessionstart-run.sh` by hand; the plugin cannot surface a delivery error.
256
+ - **`shouldArm` returns false with no `state/*.meta` and no `config/x-mode.env`.** A fresh home therefore arms nothing until there is a task or x-mode. This is deliberate: no fleet, no supervision. Do not "fix" it by always arming.
257
+ - **The arm refuses on a linked worktree.** `isPrimaryRoot` requires `git-dir == git-common-dir`; an Eindri worktree under `.yggdrasil/<id>` will never own supervision. Correct — the primary owns it.
258
+ - **`read-only` is final for the cycle.** If `sessionOwnsLock` is false, `beginArm` returns `read-only` and no retry is scheduled. A second OpenCode session must not fight the lock holder.
259
+ - **The plugin must never be replaced by a model bash call.** `syn-arm-pretool-check.sh` denies backgrounding the arm precisely so the model cannot fork a second watcher.
260
+ - **`config/x-mode.env` is sourced by the arm spawn** (`.opencode/plugins/syn-watch-arm.js:355`). It is not present by default; treat it as an operator opt-in.
261
+ - **`.opencode/plugins/lib/` is not a package** — there is no `package.json` there. Relative imports (`./lib/rodd-operational-input.js`) are what make it work; the top-level `package.json` supplies `"type":"module"`.
262
+ - **Tool name matching is exact.** The seatbelts only inspect `input.tool === "bash"`. If OpenCode renames the shell tool, both seatbelts silently stop enforcing.
@@ -0,0 +1,295 @@
1
+ # Pi Harness Adapter
2
+
3
+ > **Purpose:** Rebuild, verify, or extend the Pi adapter — the `.pi/extensions/*.ts` modules that inject the Sága digest before the first turn, own the Gná watcher, guard the turn end, and run the PreToolUse seatbelts on `@earendil-works/pi-coding-agent`.
4
+
5
+ Pi is a **run-tier** harness with an in-process extension API: the extension runs the digest itself and injects its output into model context before the first turn. Two tracked project extensions are required; both auto-load once the project is trusted.
6
+
7
+ ---
8
+
9
+ ## 1. Files
10
+
11
+ | File | Norse role | Contract parts |
12
+ |---|---|---|
13
+ | `.pi/extensions/syn-turnend-guard.ts` | **Sýn** — session-start injection + compaction re-emit + turn-end guard + PreToolUse seatbelts | 1, 3, 4 |
14
+ | `.pi/extensions/gna-pi-watch.ts` | **Gná** — watcher continuity (arm, re-arm, deliver actionable wakes) | 2 |
15
+ | `.pi/extensions/lib/vordr-sessionstart-supervisor.mjs` | **Vörðr** — detached child supervisor for the digest | 1 (transport) |
16
+ | `.pi/extensions/lib/rodd-operational-input.ts` | **Rödd** — TypeScript wire bridge | shared |
17
+ | `.pi/extensions/README.md` | prose inventory (see §11: partially stale) | — |
18
+
19
+ `.pi/extensions/` has **no** `package.json`; Pi loads the `.ts` sources directly and they import `@earendil-works/pi-coding-agent` (types), `@earendil-works/pi-tui` (Gná render), and `typebox` (tool schema).
20
+
21
+ Both extensions use `import.meta.url` to locate themselves and derive the root as `resolve(extensionDir, "../..")` — i.e. the repo root that holds `bin/`:
22
+
23
+ ```ts
24
+ // .pi/extensions/syn-turnend-guard.ts:23-29
25
+ const extensionFile = fileURLToPath(import.meta.url);
26
+ const extensionDir = dirname(extensionFile);
27
+ const root = resolve(extensionDir, "../..");
28
+ const brokkHome = process.env.BROKK_HOME || process.env.BROKK_ROOT_OVERRIDE || root;
29
+ const state = process.env.BROKK_STATE_OVERRIDE || `${brokkHome}/state`;
30
+ const marker = `${state}/.pi-syn-turnend-loaded`;
31
+ const extensionVersion = `sha256:${createHash("sha256").update(readFileSync(extensionFile)).digest("hex")}`;
32
+ ```
33
+
34
+ ---
35
+
36
+ ## 2. Required Pi lifecycle events
37
+
38
+ Pi emits the following events the adapter binds (via `pi.on?.(...)`). The adapter must tolerate optional events (`?.`) because Pi adds them across minor versions.
39
+
40
+ | Pi event | Bound in | Payload / signature | Adapter action |
41
+ |---|---|---|---|
42
+ | `session_start` | both extensions | `(event, ctx)`; `event.reason` ∈ `startup \| reload \| new \| resume \| fork` | start a session-start generation (Sýn); activate a watcher generation (Gná) |
43
+ | `before_agent_start` | Sýn | `(_event, ctx)` | claim and return the digest as a message (`{ message }`) |
44
+ | `session_compact` | Sýn | `(_event, ctx)` | create a `compact` generation and `pi.sendMessage(...)` the re-emit |
45
+ | `session_shutdown` | both | `()` | stop the active generation (Sýn/Gná) |
46
+ | `agent_settled` | Sýn | `()` | run `bin/syn-turnend-guard.sh`; on exit 2, `pi.sendUserMessage(content,{deliverAs:"followUp"})` |
47
+ | `tool_call` | Sýn | `(event)`; `event.toolName`, `event.input.command` | for `bash`, run cd-check then arm-check; return `{block:true, reason}` on exit 2 |
48
+
49
+ Sýn also registers a `process.once("exit", ...)` cleanup that SIGKILLs the digest process group.
50
+
51
+ ### 2.1 `session_start` source mapping (Sýn)
52
+
53
+ ```ts
54
+ // .pi/extensions/syn-turnend-guard.ts:522-534
55
+ pi.on?.("session_start", (event, ctx) => {
56
+ const reason = String(event.reason ?? "");
57
+ const source = reason === "startup"
58
+ ? startupRebuildSource(ctx) ?? "startup" // maps -c/-r/--session/--fork to resume/fork
59
+ : { new: "clear", resume: "resume", fork: "fork" }[reason];
60
+ markLoaded();
61
+ if (!source) return; // reload → no new generation
62
+ sessionstartGeneration = createSessionstartGeneration(source, sessionIdFromContext(ctx));
63
+ });
64
+ ```
65
+
66
+ - `reason === "new"` (Pi `/new`) → `clear` → wrapper re-emits context.
67
+ - `reason === "reload"` → no generation (prior context kept).
68
+ - `reason === "resume" | "fork"` → a nudge, not a full run.
69
+ - `reason === "startup"` is refined by `startupRebuildSource(ctx)`: a restored-session timestamp older than `performance.timeOrigin` plus `-c/--continue`, `-r/--resume`, `--session`, `--session-id`, or `--fork` yields `resume`/`fork`.
70
+
71
+ ### 2.2 `before_agent_start` delivery (Sýn)
72
+
73
+ ```ts
74
+ pi.on?.("before_agent_start", async (_event, ctx) => {
75
+ const generation = sessionstartGeneration;
76
+ if (!generation) return;
77
+ const message = await claimSessionstartMessage(generation, ctx);
78
+ return message ? { message } : undefined;
79
+ });
80
+ ```
81
+
82
+ The returned message is a `syn-sessionstart-nudge` `SessionstartMessage` with encoded content. `claimSessionstartMessage` refuses to deliver when the generation was superseded or the session id changed.
83
+
84
+ ### 2.3 `session_compact` (Sýn)
85
+
86
+ Manual compaction is idle and auto-compaction may retry without another `before_agent_start`, so the compact handler creates its own generation and calls `pi.sendMessage(message)` directly (`.pi/extensions/syn-turnend-guard.ts:546-557`).
87
+
88
+ ### 2.4 `agent_settled` turn-end guard (Sýn)
89
+
90
+ ```ts
91
+ pi.on("agent_settled", async () => {
92
+ if (guardFollowupActive) { guardFollowupActive = false; return; }
93
+ const result = await runGuard(); // spawns bin/syn-turnend-guard.sh, stdin {"stop_hook_active":false}
94
+ if (result.code !== 2) return;
95
+ guardFollowupActive = true;
96
+ const content = encodeRoddOperationalInput("turn-end-guard",
97
+ "TURN WOULD END BLIND - supervision is off. ...\n\n" + result.stderr);
98
+ await pi.sendUserMessage(content, { deliverAs: "followUp" });
99
+ });
100
+ ```
101
+
102
+ `guardFollowupActive` suppresses the immediate re-fire after the guard's own follow-up creates another settle.
103
+
104
+ ### 2.5 `tool_call` seatbelts (Sýn)
105
+
106
+ ```ts
107
+ pi.on("tool_call", async (event) => {
108
+ if (event.type !== "tool_call" || event.toolName !== "bash") return {};
109
+ const command = String(event.input?.command ?? "");
110
+ const cdResult = await runCdCheck(command); // bin/syn-cd-pretool-check.sh
111
+ if (cdResult.code === 2) return { block: true, reason: cdResult.stderr.trim() || "..." };
112
+ const result = await runPretoolCheck(command); // bin/syn-arm-pretool-check.sh
113
+ if (result.code !== 2) return {};
114
+ return { block: true, reason: result.stderr.trim() || "..." };
115
+ });
116
+ ```
117
+
118
+ Both seatbelts piggyback on the same extension file so no extra `-e` flag is needed at launch.
119
+
120
+ ---
121
+
122
+ ## 3. The Vörðr digest supervisor
123
+
124
+ `.pi/extensions/lib/vordr-sessionstart-supervisor.mjs` runs the Sága runner as a **detached child** so Pi can stream and cap output without blocking the session open.
125
+
126
+ Sýn spawns it (`.pi/extensions/syn-turnend-guard.ts:260-282`):
127
+
128
+ ```ts
129
+ const supervised = process.platform !== "win32";
130
+ const runner = `${root}/bin/saga-sessionstart-run.sh`;
131
+ child = spawn(
132
+ supervised ? "node" : runner,
133
+ supervised
134
+ ? [`${extensionDir}/lib/vordr-sessionstart-supervisor.mjs`, runner, "--source", generation.source, "--pi-prerequisite"]
135
+ : ["--source", generation.source, "--pi-prerequisite"],
136
+ {
137
+ detached: supervised,
138
+ env: { ...process.env, BROKK_SESSION_PID: String(process.pid) },
139
+ stdio: supervised ? ["ignore", "pipe", "ignore", "ipc"] : ["ignore", "pipe", "ignore"],
140
+ },
141
+ );
142
+ ```
143
+
144
+ Vörðr's contract (`.pi/extensions/lib/vordr-sessionstart-supervisor.mjs`):
145
+
146
+ - `process.argv.slice(2)` = `[runner, ...args]`.
147
+ - Spawns the runner with `env.VORDR_SESSIONSTART_SUPERVISOR_PID`.
148
+ - Streams child stdout to its own stdout and counts `outputBytes`.
149
+ - Sends `{ type: "result", code, bytes }` over IPC once writes drain.
150
+ - On `disconnect` (parent died) it `process.kill(-process.pid, "SIGKILL")` to reap the group.
151
+
152
+ Sýn therefore treats the **result message** as the completion signal, not the `close` event (which can arrive early). This is why `completePending` waits until `observedBytes >= result.bytes` before settling.
153
+
154
+ ### `BROKK_SESSION_PID` lock binding
155
+
156
+ The digest child is launched with `env.BROKK_SESSION_PID = String(process.pid)` — the **live Pi process**. `bin/gleipnir-lock-lib.sh` writes that pid to `state/.lock` (`gleipnir_lock_acquire`), so the lock survives the short-lived digest helper. Both Sýn and Gná verify ownership by walking `ps -o ppid=` ancestry up to 8 levels and comparing to the `.lock` pid (`lockOwnership()` in both files). `other` means read-only; `missing` means the lock is gone/stale.
157
+
158
+ Liveness sees real death (`gleipnir_pid_alive` / `pidAlive`). `kill(0)` alone reports a zombie (dead but unreaped) and a recycled pid as “alive”, which stranded the machine lock after an agent was turned off. The lock therefore also records the owner's starttime in a sidecar (`brokk.lock.starttime`, `/proc/<pid>/stat` field 22) and rejects a holder whose state is `Z`/`X` or whose recorded starttime no longer matches. `gleipnir_lock_reap` (session start) and `gleipnir_lock_acquire` clear such locks, and Gná releases its own lock on real process exit (`releaseLockIfOwned` in the `exit` hook) so a clean quit never leaves the helm behind.
159
+
160
+ ### Delivery cap and truncation
161
+
162
+ Sýn caps injected bytes at `sessionstartDeliveryBytes = 512 * 1024` (`.pi/extensions/syn-turnend-guard.ts:71`). On overflow it appends:
163
+
164
+ ```
165
+ PI SESSION-START DELIVERY TRUNCATED - the digest exceeded 512 KiB. Treat omitted context as unread and inspect the named files directly before acting on it.
166
+ ```
167
+
168
+ On a failed/empty startup it substitutes the manual fallback:
169
+
170
+ ```
171
+ Run `bin/saga-session-start.sh` now, exactly once, before executing any other instructions.
172
+ ```
173
+
174
+ Pi's prerequisite exit is `sessionstartIneligibleExit = 3`; a stand-down (`BROKK_SESSIONSTART_INELIGIBLE=1`) exits 3 and is mapped to `{ kind: "ineligible" }` rather than `failed`.
175
+
176
+ ---
177
+
178
+ ## 4. Gná watcher continuity
179
+
180
+ `.pi/extensions/gna-pi-watch.ts` owns the watcher in the persistent TUI. It exposes:
181
+
182
+ - **Command** `pi.registerCommand("gna-watch-arm", ...)` (line 530).
183
+ - **Tool** `pi.registerTool({ name: "gna_watch_arm", ... })` (line 538) with `promptGuidelines` telling the model to call it **only** for the first cycle or after an actionable notification, never after ordinary work — the extension re-arms automatically.
184
+ - **Events** `session_start` (activate generation, `markLoaded`) and `session_shutdown` (stop generation).
185
+
186
+ Arm spawn (`.pi/extensions/gna-pi-watch.ts:397-434`):
187
+
188
+ ```ts
189
+ const ownership = lockOwnership();
190
+ if (ownership === "other") return { ok:false, message:"watcher: read-only - session lock is held by another Brokk session" };
191
+ if (ownership === "missing") { reclaimStaleLock(resolvedLockPath()); return startArm(owner, predecessorArmPid); }
192
+ const env = { ...process.env, BROKK_HOME, BROKK_ROOT_OVERRIDE, BROKK_CONFIG_OVERRIDE,
193
+ BROKK_WATCH_ARM_SCRIPT, BROKK_WATCH_PREDECESSOR_ARM_PID, BROKK_SESSION_PID: String(process.pid) };
194
+ const armChild = spawn("bash", ["-lc", 'exec "$BROKK_WATCH_ARM_SCRIPT" --restart'], { cwd: brokkRoot, env, ... });
195
+ ```
196
+
197
+ `missing` (recorded holder dead / zombie / pid reused) no longer punts to `bin/saga-session-start.sh`: Gná reclaims the helm directly (`reclaimStaleLock`, mirroring `gleipnir_lock_acquire` — pid + starttime sidecar + `state/.lock-path` pointer) and arms immediately, so a leftover lock can never strand supervision.
198
+
199
+ Continuity: `classifyClose` separates **actionable** (`signal:`/`stale:`/`check:`/`heartbeat:` line) from **failure**. Actionable → `restoreAfterActionableClose` (retries with backoff) then `deliverActionableWake` (encodes a `watcher` Rödd message and `pi.sendUserMessage(..., {deliverAs:"followUp"})`). Failure → `scheduleRetry`. Retry knobs: `BROKK_WATCH_REARM_RETRY_BASE_MS` (250), `..._MAX_MS` (4000), `..._LIMIT` (5); readiness `BROKK_PI_ARM_READY_TIMEOUT_MS` (12s, 35s on win32); retire `BROKK_WATCH_ARM_RETIRE_TIMEOUT_MS` (1000).
200
+
201
+ On an actionable close, Gná calls `bin/syn-watch-arm.sh --handling-delivered <generation> --watcher-pid <pid>` to acknowledge handling; the script prints `watcher: handling delivered ...` and exits 0 (`bin/syn-watch-arm.sh:26-31`).
202
+
203
+ Loaded markers written by the extensions (skipped while lock is `other`):
204
+
205
+ | Marker | Written by |
206
+ |---|---|
207
+ | `state/.pi-syn-turnend-loaded` | Sýn `markLoaded()` |
208
+ | `state/.pi-gna-watch-loaded` | Gná `markLoaded()` |
209
+
210
+ Content is `<extensionVersion sha256>\n<pid>\n`.
211
+
212
+ ---
213
+
214
+ ## 5. Trust
215
+
216
+ Pi will not auto-load tracked `.pi/extensions/*.ts` until the project is trusted. **Approve the project trust prompt once per clone on first launch.** If trust is not approved, the extensions never load and the session is unseated.
217
+
218
+ Upstream's trust-free fallback is to launch the selected executable with the extension flags explicitly:
219
+
220
+ ```bash
221
+ pi -e .pi/extensions/syn-turnend-guard.ts -e .pi/extensions/gna-pi-watch.ts
222
+ ```
223
+
224
+ Use this only for diagnosis or an untrusted checkout; the production path is the trust prompt.
225
+
226
+ ---
227
+
228
+ ## 6. Install / enable / verify
229
+
230
+ ### Enable
231
+
232
+ Extension files must be present under `.pi/extensions/`. Signing/selection is a Pi-side concern (`BROKK_PI_HARNESS=pi-signed` selects the `pi-signed` identity in `bin/hamr-harness.sh`).
233
+
234
+ ### Verify loading
235
+
236
+ ```bash
237
+ cd "$BROKK_HOME"
238
+ # Markers are written on extension load (and session_start for Sýn).
239
+ test -f state/.pi-syn-turnend-loaded && echo "Sýn loaded: $(head -n1 state/.pi-syn-turnend-loaded)"
240
+ test -f state/.pi-gna-watch-loaded && echo "Gná loaded: $(head -n1 state/.pi-gna-watch-loaded)"
241
+ ```
242
+
243
+ ### Verify the digest before the first turn
244
+
245
+ ```bash
246
+ # What Sýn runs under Vörðr:
247
+ node .pi/extensions/lib/vordr-sessionstart-supervisor.mjs bin/saga-sessionstart-run.sh --source startup --pi-prerequisite | head -n 20
248
+ echo "exit=$?" # wrapper exits 0; Vörðr reports {type:"result",code,bytes}
249
+ # Direct wrapper for comparison:
250
+ bin/saga-sessionstart-run.sh --source startup --pi-prerequisite | head -n 5
251
+ ```
252
+
253
+ ### Verify the turn-end guard
254
+
255
+ ```bash
256
+ rm -f state/.supervision-armed
257
+ echo '{"stop_hook_active":false}' | bin/syn-turnend-guard.sh; echo "inert -> $? (expect 0)"
258
+ touch state/.supervision-armed; rm -f state/.watch.heartbeat
259
+ echo '{"stop_hook_active":false}' | bin/syn-turnend-guard.sh; echo "armed+stale -> $? (expect 2)"
260
+ ```
261
+
262
+ ### Verify the seatbelts as `tool_call` would
263
+
264
+ ```bash
265
+ bin/syn-cd-pretool-check.sh --command 'cd ../../etc'; echo "cd -> $? (expect 2)"
266
+ bin/syn-arm-pretool-check.sh --command 'bin/syn-watch-arm.sh &'; echo "arm -> $? (expect 2)"
267
+ ```
268
+
269
+ ### Verify Gná's arm tool path
270
+
271
+ ```bash
272
+ # With a live lock owned by this process tree:
273
+ bash -lc 'BROKK_SESSION_PID=$$ exec bin/syn-watch-arm.sh --restart' &
274
+ sleep 1; test -s state/.watch.heartbeat && echo "heartbeat ok"
275
+ bin/syn-watch-arm.sh --handling-delivered test-gen --watcher-pid 12345
276
+ ```
277
+
278
+ ---
279
+
280
+ ## 7. Gotchas
281
+
282
+ - **Gná is Pi-only.** OpenCode's watcher is **Sýn** (`.opencode/plugins/syn-watch-arm.js`). Do not look for `gna-*` in `.opencode/`.
283
+ - **Neither extension is inert by accident.** Sýn's guard is inert until `state/.supervision-armed` exists; arm first, then test.
284
+ - **`supervised` only on non-Windows.** On Windows Sýn runs the runner directly with no Vörðr and no IPC; completion comes from the `close` event. Do not assume the IPC result path exists cross-platform.
285
+ - **Vörðr kills its process group on disconnect.** If Pi dies, the digest child is SIGKILLed. A lingering `VORDR_SESSIONSTART_SUPERVISOR_PID` means the reap failed.
286
+ - **The digest is capped at 512 KiB.** A large digest is truncated with an explicit marker; treat omitted context as unread.
287
+ - **`session_compact` bypasses `before_agent_start`.** The compact handler calls `pi.sendMessage` directly; if you refactor delivery, keep both paths.
288
+ - **`guardFollowupActive` is module-global.** It assumes one guard cycle at a time; concurrent settles can drop one due to the boolean.
289
+ - **`markLoaded()` refuses while the lock is `other`.** A read-only Pi session will not write markers, so absence of a marker alone does not prove the extension failed to load.
290
+ - **Tool event filtering is `event.toolName === "bash"`.** A renamed shell tool disables both seatbelts silently.
291
+ - **Trust is per clone.** A fresh clone or a copied home that never approved the prompt has no loaded extensions. Restart with explicit `-e` flags only to diagnose.
292
+ - **`.pi/extensions/README.md:36-38` is stale.** It claims "the `.opencode` plugins and Claude/Grok/Codex/Cursor/adapters … are still to come." They are landed; see [`opencode.md`](opencode.md), [`claude-code.md`](claude-code.md), [`codex.md`](codex.md), [`cursor.md`](cursor.md). Grok remains unimplemented in Ymir.
293
+ - **`vordr` and `rodd` use different extensions** (`.mjs` vs `.ts`) deliberately: Vörðr is a plain Node child, so it cannot import the Pi TypeScript lib.
294
+
295
+ **Skills.** Pi discovers skills **natively** — it walks up from the cwd to `.agents/skills` (and `~/.agents/skills`), and `--skill <path>` adds more; `--no-skills` disables discovery. No link and no config: a second root under `.pi/` would double-load the same skill.