@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,51 @@
1
+ #!/usr/bin/env bash
2
+ # Unit tests for the Sýn PreToolUse seatbelts:
3
+ # bin/syn-arm-pretool-check.sh - the watcher arm is never backgrounded
4
+ # bin/syn-guard-pretool-check.sh - load-bearing invariants stay untouched
5
+ set -u
6
+
7
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
8
+ ARM="$ROOT/bin/syn-arm-pretool-check.sh"
9
+ GUARD="$ROOT/bin/syn-guard-pretool-check.sh"
10
+ fail=0
11
+
12
+ allows() { # <script> <command>
13
+ if "$1" --command "$2" >/dev/null 2>&1; then :
14
+ else printf 'not ok - should allow: %s\n' "$2" >&2; fail=1; fi
15
+ }
16
+ denies() { # <script> <command>
17
+ if "$1" --command "$2" >/dev/null 2>&1; then
18
+ printf 'not ok - should deny: %s\n' "$2" >&2; fail=1
19
+ fi
20
+ }
21
+
22
+ # --- arm seatbelt: real backgrounding vs chaining and syntax checks ----------
23
+
24
+ allows "$ARM" 'bash -n bin/syn-watch-arm.sh && echo "syntax OK"'
25
+ allows "$ARM" 'cat bin/syn-watch-arm.sh'
26
+ allows "$ARM" 'echo "chained" && ls'
27
+ denies "$ARM" 'bin/syn-watch-arm.sh --restart &'
28
+ denies "$ARM" 'nohup bin/syn-watch-arm.sh --restart'
29
+ denies "$ARM" 'setsid bin/syn-watch-arm.sh --restart'
30
+ denies "$ARM" 'disown; bin/syn-watch-arm.sh --restart'
31
+
32
+ # --- invariant seatbelt: destructive shapes are denied -----------------------
33
+
34
+ denies "$GUARD" 'rm -f state/.lock'
35
+ denies "$GUARD" 'echo 123 > state/.supervision-armed'
36
+ denies "$GUARD" 'sed -i s/x/y/ workspace/memory/runes_audit.md'
37
+ denies "$GUARD" 'rm -f bin/syn-watch-arm.sh'
38
+ denies "$GUARD" 'cat .env.local'
39
+ denies "$GUARD" 'git add .env.realm'
40
+ denies "$GUARD" 'echo x > config/cron.yaml'
41
+
42
+ # --- invariant seatbelt: reads and ordinary work are allowed -----------------
43
+
44
+ allows "$GUARD" 'cat state/.lock'
45
+ allows "$GUARD" 'rg wake state/.wake-queue'
46
+ allows "$GUARD" 'git status'
47
+ allows "$GUARD" 'bin/runes-append.sh brokk test --message hi'
48
+ allows "$GUARD" 'bash -n bin/syn-guard-pretool-check.sh'
49
+
50
+ [ "$fail" = 0 ] && echo "ALL PASS" || echo "FAILURES"
51
+ exit "$fail"
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env bash
2
+ # Unit tests for the machine-scoped primary session lock (bin/gleipnir-lock-lib.sh).
3
+ #
4
+ # The primary holds ONE machine-global lock so a second checkout of the same
5
+ # machine cannot run a competing session; an Eindri-home keeps its own per-home
6
+ # lock so workers run in parallel. A pre-contract session lives at the legacy
7
+ # state/.lock and must still resolve during migration.
8
+ set -u
9
+
10
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
11
+ LIB="$ROOT/bin/gleipnir-lock-lib.sh"
12
+ fail=0
13
+ ok() { printf 'ok - %s\n' "$1"; }
14
+ bad() { printf 'not ok - %s\n' "$1" >&2; fail=1; }
15
+
16
+ TMP="$(mktemp -d)"
17
+ trap 'rm -rf "$TMP"' EXIT
18
+
19
+ # --- path resolution ---------------------------------------------------------
20
+
21
+ out=$(BROKK_HOME="$TMP/home" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
22
+ bash -c '. "$0"; gleipnir_lock_path p; printf "%s" "$p"' "$LIB")
23
+ [ "$out" = "$TMP/machine/brokk.lock" ] && ok "primary lock is machine-global" \
24
+ || bad "primary lock path: $out"
25
+
26
+ mkdir -p "$TMP/ehome/data"; : > "$TMP/ehome/data/eindri-home"
27
+ out=$(BROKK_HOME="$TMP/ehome" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
28
+ bash -c '. "$0"; gleipnir_lock_path p; printf "%s" "$p"' "$LIB")
29
+ [ "$out" = "$TMP/ehome/state/.lock" ] && ok "Eindri-home marker keeps a per-home lock" \
30
+ || bad "Eindri-home lock path: $out"
31
+
32
+ out=$(BROKK_HOME_KIND=eindri BROKK_HOME="$TMP/ehome2" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
33
+ bash -c '. "$0"; gleipnir_lock_path p; printf "%s" "$p"' "$LIB")
34
+ [ "$out" = "$TMP/ehome2/state/.lock" ] && ok "BROKK_HOME_KIND=eindri keeps a per-home lock" \
35
+ || bad "env Eindri-home lock path: $out"
36
+
37
+ # --- acquire writes the machine lock and the pointer -------------------------
38
+
39
+ mkdir -p "$TMP/home/state"
40
+ BROKK_HOME="$TMP/home" BROKK_MACHINE_STATE_DIR="$TMP/machine" BROKK_SESSION_PID="$$" \
41
+ bash -c '. "$0"; gleipnir_lock_acquire; gleipnir_lock_owner o; printf "%s" "$o"' "$LIB" > "$TMP/owner"
42
+ [ "$(cat "$TMP/owner")" = "$$" ] && ok "acquire records the session pid" \
43
+ || bad "owner: $(cat "$TMP/owner")"
44
+ [ -f "$TMP/machine/brokk.lock" ] && ok "machine lock file written" \
45
+ || bad "machine lock file missing"
46
+ [ "$(cat "$TMP/home/state/.lock-path" 2>/dev/null)" = "$TMP/machine/brokk.lock" ] \
47
+ && ok "pointer records the resolved lock path" \
48
+ || bad "pointer missing or wrong"
49
+
50
+ # --- a second session on the same machine is refused -------------------------
51
+
52
+ out=$(BROKK_HOME="$TMP/other" BROKK_MACHINE_STATE_DIR="$TMP/machine" BROKK_SESSION_PID="1" \
53
+ bash -c '. "$0"; if gleipnir_lock_acquire; then printf acquired; else printf refused; fi' "$LIB")
54
+ [ "$out" = "refused" ] && ok "a live machine lock refuses a second session" \
55
+ || bad "second session: $out"
56
+
57
+ # --- migration: a legacy home lock is still honored --------------------------
58
+
59
+ rm -f "$TMP/machine/brokk.lock"; mkdir -p "$TMP/home2/state"; printf '%s\n' "$$" > "$TMP/home2/state/.lock"
60
+ out=$(BROKK_HOME="$TMP/home2" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
61
+ bash -c '. "$0"; gleipnir_lock_owner o; printf "%s" "$o"' "$LIB")
62
+ [ "$out" = "$$" ] && ok "legacy home lock is honored during migration" \
63
+ || bad "legacy owner: $out"
64
+
65
+ # --- reap clears a dead machine lock -----------------------------------------
66
+
67
+ mkdir -p "$TMP/machine"; printf '999999\n' > "$TMP/machine/brokk.lock"
68
+ BROKK_HOME="$TMP/home" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
69
+ bash -c '. "$0"; gleipnir_lock_reap' "$LIB" >/dev/null 2>&1
70
+ [ -e "$TMP/machine/brokk.lock" ] && bad "stale machine lock not reaped" \
71
+ || ok "a dead machine lock is reaped"
72
+
73
+ # --- acquire records a starttime sidecar --------------------------------------
74
+
75
+ BROKK_HOME="$TMP/home" BROKK_MACHINE_STATE_DIR="$TMP/machine" BROKK_SESSION_PID="$$" \
76
+ bash -c '. "$0"; gleipnir_lock_acquire' "$LIB" >/dev/null 2>&1
77
+ [ -s "$TMP/machine/brokk.lock.starttime" ] && ok "acquire records a starttime sidecar" \
78
+ || bad "starttime sidecar missing after acquire"
79
+
80
+ # --- reap clears a lock whose recorded starttime no longer matches (pid reuse) --
81
+
82
+ # Use a live unrelated process (this shell) with a deliberately wrong starttime:
83
+ # liveness sees the pid "alive" via kill(0) but the recorded starttime belongs
84
+ # to a process that is no longer the owner — i.e. the kernel recycled the pid.
85
+ mkdir -p "$TMP/machine"; printf '%s\n' "$$" > "$TMP/machine/brokk.lock"
86
+ printf '0\n' > "$TMP/machine/brokk.lock.starttime"
87
+ BROKK_HOME="$TMP/home" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
88
+ bash -c '. "$0"; gleipnir_lock_reap' "$LIB" >/dev/null 2>&1
89
+ [ -e "$TMP/machine/brokk.lock" ] && bad "recycled-pid lock not reaped" \
90
+ || ok "a lock whose pid was recycled is reaped"
91
+
92
+ # --- reap clears a lock held by a real zombie ---------------------------------
93
+
94
+ # Fork a child, kill it, and keep the parent alive WITHOUT waiting: the child
95
+ # becomes a zombie. kill(0) on a zombie succeeds — the old liveness checked
96
+ # only that and missed the death; reap must now see the Z state and clear it.
97
+ python3 -c '
98
+ import os, signal, sys, time
99
+ p = os.fork()
100
+ if p == 0:
101
+ time.sleep(10); os._exit(0)
102
+ else:
103
+ time.sleep(0.3)
104
+ os.kill(p, signal.SIGKILL)
105
+ time.sleep(0.3)
106
+ with open(sys.argv[1], "w") as h:
107
+ h.write(str(p))
108
+ time.sleep(30)
109
+ ' "$TMP/zombie.pid" &
110
+ zombie_keeper=$!
111
+ for _i in 1 2 3 4 5 6 7 8 9 10; do
112
+ [ -s "$TMP/zombie.pid" ] && break
113
+ sleep 0.2
114
+ done
115
+ zombie_pid=$(cat "$TMP/zombie.pid" 2>/dev/null || true)
116
+ state=$(awk '{print $3}' "/proc/$zombie_pid/stat" 2>/dev/null)
117
+ if [ -n "$zombie_pid" ] && [ "$state" = "Z" ]; then
118
+ printf '%s\n' "$zombie_pid" > "$TMP/machine/brokk.lock"
119
+ rm -f "$TMP/machine/brokk.lock.starttime"
120
+ BROKK_HOME="$TMP/home" BROKK_MACHINE_STATE_DIR="$TMP/machine" \
121
+ bash -c '. "$0"; gleipnir_lock_reap' "$LIB" >/dev/null 2>&1
122
+ [ -e "$TMP/machine/brokk.lock" ] && bad "zombie-held lock not reaped" \
123
+ || ok "a zombie-held lock is reaped (kill(0) alone cannot see this)"
124
+ else
125
+ bad "test setup: expected a zombie child (got state ${state:-none})"
126
+ fi
127
+ kill "$zombie_keeper" 2>/dev/null || true
128
+
129
+ [ "$fail" = 0 ] && echo "ALL PASS" || echo "FAILURES"
130
+ exit "$fail"
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+ # Compatibility source for real-Herdr tests.
3
+ # The production owner of the isolation, refuse-default, teardown, and
4
+ # fleet-state tripwire contract is bin/fm-herdr-lab.sh.
5
+ set -u
6
+
7
+ # Herdr backend tests drive the real fm-spawn/fm-teardown but do not source
8
+ # tests/lib.sh, so exempt them from the gate-lifecycle refusal here too (see
9
+ # tests/lib.sh and bin/fm-gate-refuse-lib.sh for why firstmate's own suite,
10
+ # which the no-mistakes gate runs from a gate worktree, must be exempt).
11
+ export FM_GATE_REFUSE_BYPASS=1
12
+
13
+ HERDR_TEST_SAFETY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
14
+ # shellcheck source=/dev/null
15
+ . "$HERDR_TEST_SAFETY_DIR/bin/fm-herdr-lab.sh"
16
+
17
+ # herdr_forget_inherited_pane: drop the Herdr PANE identity this test process
18
+ # inherited from whatever terminal it was started in.
19
+ #
20
+ # Herdr injects HERDR_ENV, HERDR_PANE_ID, HERDR_TAB_ID, HERDR_WORKSPACE_ID,
21
+ # HERDR_SOCKET_PATH, and HERDR_SESSION into every process it manages a pane for
22
+ # (verified 0.7.5 - docs/verification/runtime-backends.md), and a test run from
23
+ # inside a Herdr pane inherits all of them. Spawn now treats that pane as the
24
+ # authoritative parent to place workers next to, so a leaked identity from the
25
+ # developer's own session would follow the test into its isolated lab session
26
+ # and be refused there as a cross-session parent - a result that depends on
27
+ # where the suite was launched from, not on what it asserts.
28
+ #
29
+ # Call this before exporting the lab HERDR_SESSION in any suite whose subject is
30
+ # the per-home container path. A suite that means to exercise a launcher-bound
31
+ # spawn sets HERDR_PANE_ID itself, to a pane it created in its own lab session.
32
+ herdr_forget_inherited_pane() {
33
+ unset HERDR_ENV HERDR_PANE_ID HERDR_TAB_ID HERDR_WORKSPACE_ID HERDR_SOCKET_PATH HERDR_SESSION
34
+ }
35
+
36
+ herdr_refuse_if_default() { # <session>
37
+ fm_herdr_lab_refuse_if_default "$1"
38
+ }
39
+
40
+ herdr_safe_stop_and_delete() { # <session>
41
+ fm_herdr_lab_teardown "$1"
42
+ }
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env bash
2
+ # tests/lib.sh - shared primitives for firstmate behavior tests.
3
+ #
4
+ # Source this from a test file:
5
+ # # shellcheck source=tests/lib.sh
6
+ # . "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
7
+ #
8
+ # It provides the boilerplate every test file used to re-roll: ok/not-ok
9
+ # reporters, a self-cleaning temp root, fakebin/PATH-shim helpers, deterministic
10
+ # git identity and fixture builders, state/<id>.meta writers, and the common
11
+ # string/exit-code/file assertions. Shared fake-toolchain and spawn-world
12
+ # builders live in tests/fixtures.sh; wake-queue mocks in wake-helpers.sh;
13
+ # secondmate-lifecycle mocks in secondmate-helpers.sh. Suite-specific fakes
14
+ # that encode a single test's terminal or lifecycle assumptions still belong
15
+ # with the tests that own them.
16
+ #
17
+ # ROOT is exported as the firstmate repo root (this file lives in tests/), so a
18
+ # sourcing test can use "$ROOT/bin/..." without recomputing it.
19
+
20
+ # Idempotent guard: behavior-area helper files (secondmate-helpers.sh,
21
+ # wake-helpers.sh, fixtures.sh) source this library for ROOT/fail/pass, and the
22
+ # test that includes them may also source it directly. Re-sourcing must not wipe
23
+ # the registered-cleanup array or reset state.
24
+ if [ -n "${FM_TEST_LIB_SOURCED:-}" ]; then
25
+ return 0
26
+ fi
27
+ FM_TEST_LIB_SOURCED=1
28
+
29
+ # Exempt firstmate's own test suite from the gate-lifecycle refusal
30
+ # (bin/fm-gate-refuse-lib.sh). The no-mistakes gate runs this suite FROM a gate
31
+ # worktree - the exact environment that guard refuses - so without this every
32
+ # test that drives the real fm-spawn/fm-send/fm-teardown would be refused during
33
+ # firstmate's own validation. A confused gate agent never sources this helper, so
34
+ # the boundary against the real hazard is unaffected. tests/fm-gate-refuse.test.sh
35
+ # strips this to verify real refusal.
36
+ export FM_GATE_REFUSE_BYPASS=1
37
+
38
+ # Resolve the repo root from this library's own location. Consumed by sourcing
39
+ # test files, not by this library, so it reads as "unused" here.
40
+ # shellcheck disable=SC2034
41
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
42
+
43
+ # --- reporters --------------------------------------------------------------
44
+
45
+ fail() {
46
+ printf 'not ok - %s\n' "$1" >&2
47
+ exit 1
48
+ }
49
+
50
+ pass() {
51
+ printf 'ok - %s\n' "$1"
52
+ }
53
+
54
+ # --- self-cleaning temp root ------------------------------------------------
55
+ #
56
+ # fm_test_tmproot <prefix> echoes a fresh temp dir and registers it for removal
57
+ # on EXIT/INT/TERM. A test file that needs extra teardown (e.g. killing a
58
+ # daemon) should define its own EXIT trap and call fm_test_cleanup from inside
59
+ # it so registered dirs are still removed.
60
+ #
61
+ # The call site is almost always `TMP_ROOT=$(fm_test_tmproot prefix)`, which
62
+ # forks a subshell to capture stdout. Anything that function does to the
63
+ # current shell's state - an array append, a trap - dies with that subshell
64
+ # and never reaches the real caller, so registration cannot go through
65
+ # in-process state. `$$` is the one thing bash keeps stable across that
66
+ # boundary (it always resolves to the invoking shell's PID, not the
67
+ # subshell's - see `man bash` on `$$`), so fm_test_tmproot records the
68
+ # directory in a `$$`-keyed registry file instead, and the trap that reaps
69
+ # that file is armed once, here, at source time - which always runs in the
70
+ # real caller, never a subshell.
71
+
72
+ FM_TEST_CLEANUP_DIRS=()
73
+ FM_TEST_CLEANUP_REGISTRY=$(mktemp "${TMPDIR:-/tmp}/.fm-test-cleanup.$$.XXXXXX") || return 1
74
+
75
+ fm_test_pid_identity() {
76
+ local pid=$1
77
+ FM_STATE_OVERRIDE="${TMPDIR:-/tmp}" bash -c \
78
+ '. "$1"; fm_pid_identity "$2"' _ "$ROOT/bin/fm-wake-lib.sh" "$pid"
79
+ }
80
+
81
+ FM_TEST_OWNER_IDENTITY=$(fm_test_pid_identity "$$") || {
82
+ rm -f "$FM_TEST_CLEANUP_REGISTRY"
83
+ return 1
84
+ }
85
+
86
+ fm_test_cleanup() {
87
+ local d
88
+ for d in "${FM_TEST_CLEANUP_DIRS[@]:-}"; do
89
+ [ -n "$d" ] && rm -rf "$d"
90
+ done
91
+ if [ -f "$FM_TEST_CLEANUP_REGISTRY" ]; then
92
+ while IFS= read -r d; do
93
+ [ -n "$d" ] && rm -rf "$d"
94
+ done < "$FM_TEST_CLEANUP_REGISTRY"
95
+ rm -f "$FM_TEST_CLEANUP_REGISTRY"
96
+ fi
97
+ }
98
+
99
+ fm_test_tmproot() {
100
+ local prefix=${1:-fm-test} root
101
+ root=$(mktemp -d "${TMPDIR:-/tmp}/${prefix}.XXXXXX") || return 1
102
+ if ! printf '%s\n%s\n' "$$" "$FM_TEST_OWNER_IDENTITY" > "$root/.fm-test-fixture" ||
103
+ ! printf '%s\n' "$root" >> "$FM_TEST_CLEANUP_REGISTRY"; then
104
+ rm -rf "$root"
105
+ return 1
106
+ fi
107
+ printf '%s\n' "$root"
108
+ }
109
+
110
+ trap fm_test_cleanup EXIT
111
+ trap 'fm_test_cleanup; exit 130' INT
112
+ trap 'fm_test_cleanup; exit 143' TERM
113
+
114
+ # fm_test_reap_orphans: best-effort sweep for fixture roots left behind by a
115
+ # prior run that was killed hard enough to skip the traps above (e.g. a
116
+ # SIGKILL timeout). Only removes directories carrying the .fm-test-fixture
117
+ # marker fm_test_tmproot writes, so it never touches unrelated fm-* tmp dirs
118
+ # from real (non-test) firstmate commands. The marker identifies the owning
119
+ # shell across PID reuse, so the same live owner always wins over the age
120
+ # fallback for dead or unowned roots.
121
+ FM_TEST_ORPHAN_MAX_AGE_SECONDS=${FM_TEST_ORPHAN_MAX_AGE_SECONDS:-3600}
122
+
123
+ fm_test_reap_orphans() {
124
+ local marker dir mtime now owner_pid owner_identity current_identity
125
+ now=$(date +%s)
126
+ for marker in "${TMPDIR:-/tmp}"/fm-*/.fm-test-fixture; do
127
+ [ -e "$marker" ] || continue
128
+ owner_pid=$(sed -n '1p' "$marker" 2>/dev/null) || owner_pid=
129
+ owner_identity=$(sed -n '2,$p' "$marker" 2>/dev/null) || owner_identity=
130
+ case "$owner_pid" in
131
+ '' | *[!0-9]*) ;;
132
+ *)
133
+ current_identity=$(fm_test_pid_identity "$owner_pid" 2>/dev/null) || current_identity=
134
+ if [ -n "$owner_identity" ] && [ "$current_identity" = "$owner_identity" ]; then
135
+ continue
136
+ fi
137
+ ;;
138
+ esac
139
+ mtime=$(stat -c %Y "$marker" 2>/dev/null || stat -f %m "$marker" 2>/dev/null) || continue
140
+ [ $((now - mtime)) -ge "$FM_TEST_ORPHAN_MAX_AGE_SECONDS" ] || continue
141
+ dir=$(dirname "$marker")
142
+ if [ -d "$dir" ] && [ ! -L "$dir" ]; then
143
+ find "$dir" -type d -exec chmod u+rwx {} + 2>/dev/null || true
144
+ fi
145
+ rm -rf "$dir"
146
+ done
147
+ }
148
+
149
+ # A parent coordinator can reap once before it starts isolated child sections.
150
+ # Those children use their own EXIT cleanup and must not spend their bounded
151
+ # execution window repeating the same global stale-fixture scan.
152
+ if [ "${FM_TEST_SKIP_ORPHAN_REAP:-0}" != 1 ]; then
153
+ fm_test_reap_orphans
154
+ fi
155
+
156
+ # --- fakebin / PATH shims ---------------------------------------------------
157
+ #
158
+ # fm_fakebin <dir> creates <dir>/fakebin and echoes it; prepend it to PATH to
159
+ # shadow real tools with stubs. fm_fake_exit0 drops trivial exit-0 stubs for the
160
+ # named tools into a fakebin dir. fm_fake_version_tool drops a stub for a tool
161
+ # whose installed version bootstrap gates, so a fixture cannot be reported as an
162
+ # unparseable build simply for answering `--version` with nothing.
163
+
164
+ fm_fakebin() {
165
+ local dir=$1 fakebin="$1/fakebin"
166
+ mkdir -p "$fakebin"
167
+ printf '%s\n' "$fakebin"
168
+ }
169
+
170
+ fm_fake_exit0() {
171
+ local fakebin=$1 tool
172
+ shift
173
+ for tool in "$@"; do
174
+ cat > "$fakebin/$tool" <<'SH'
175
+ #!/usr/bin/env bash
176
+ exit 0
177
+ SH
178
+ chmod +x "$fakebin/$tool"
179
+ done
180
+ }
181
+
182
+ # fm_fake_version_tool <fakebin> <tool> <override-env-var> <default-version>
183
+ # The stub answers `--version` with <override-env-var> when that variable is set
184
+ # and non-empty, and with <default-version> otherwise; every other invocation
185
+ # exits 0. A case that needs to drive a version floor exports the variable.
186
+ fm_fake_version_tool() {
187
+ local fakebin=$1 tool=$2 override=$3 default=$4
188
+ cat > "$fakebin/$tool" <<SH
189
+ #!/usr/bin/env bash
190
+ if [ "\${1:-}" = --version ]; then
191
+ printf '%s\n' "\${$override:-$default}"
192
+ exit 0
193
+ fi
194
+ exit 0
195
+ SH
196
+ chmod +x "$fakebin/$tool"
197
+ }
198
+
199
+ # --- deterministic git identity and fixtures --------------------------------
200
+
201
+ # fm_git_identity [name] [email]: export a fixed author/committer identity so
202
+ # fixture commits never depend on the host git config.
203
+ fm_git_identity() {
204
+ export GIT_AUTHOR_NAME=${1:-fmtest} GIT_AUTHOR_EMAIL=${2:-fmtest@example.invalid}
205
+ export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
206
+ }
207
+
208
+ # fm_git_init_commit <dir>: create a git repo at <dir> with a README and one
209
+ # commit. Uses an inline identity so it works whether or not fm_git_identity was
210
+ # called.
211
+ fm_git_init_commit() {
212
+ local dir=$1
213
+ mkdir -p "$dir"
214
+ git -C "$dir" init -q
215
+ printf '# %s\n' "$(basename "$dir")" > "$dir/README.md"
216
+ git -C "$dir" add README.md
217
+ git -C "$dir" -c user.name='Firstmate Tests' -c user.email='tests@example.invalid' commit -qm initial
218
+ }
219
+
220
+ # fm_git_add_origin <repo> <bare>: clone <repo> bare into <bare> and register it
221
+ # as <repo>'s origin via a file:// URL (so later clones resolve an absolute path).
222
+ fm_git_add_origin() {
223
+ local repo=$1 remote=$2 remote_abs
224
+ git clone --quiet --bare "$repo" "$remote"
225
+ remote_abs=$(cd "$remote" && pwd)
226
+ git -C "$repo" remote add origin "file://$remote_abs"
227
+ }
228
+
229
+ # fm_git_worktree <repo> <worktree> <branch>: initialize <repo> with one commit
230
+ # and a local bare origin, then add a worktree on a fresh branch.
231
+ fm_git_worktree() {
232
+ local repo=$1 worktree=$2 branch=$3
233
+ fm_git_init_commit "$repo"
234
+ fm_git_add_origin "$repo" "$repo.origin.git"
235
+ git -C "$repo" worktree add --quiet -b "$branch" "$worktree"
236
+ }
237
+
238
+ # --- state/<id>.meta writers ------------------------------------------------
239
+
240
+ # fm_write_meta <file> <key=val> ...: write the given key=val lines to a meta
241
+ # file (truncating any prior content).
242
+ fm_write_meta() {
243
+ local file=$1 kv
244
+ shift
245
+ : > "$file"
246
+ for kv in "$@"; do
247
+ printf '%s\n' "$kv" >> "$file"
248
+ done
249
+ }
250
+
251
+ # fm_write_secondmate_meta <file> <home> [window] [projects] [harness]: write the
252
+ # standard kind=secondmate meta block used across the secondmate suites. Window
253
+ # defaults to firstmate:fm-<id>, projects defaults to alpha, and harness defaults
254
+ # to echo to match the common case.
255
+ fm_write_secondmate_meta() {
256
+ local file=$1 home=$2 id window projects=${4:-alpha} harness=${5:-echo}
257
+ id=$(basename "$file" .meta)
258
+ window=${3:-firstmate:fm-$id}
259
+ fm_write_meta "$file" \
260
+ "window=$window" \
261
+ "endpoint_task_id=$id" \
262
+ "worktree=$home" \
263
+ "project=$home" \
264
+ "harness=$harness" \
265
+ "kind=secondmate" \
266
+ "mode=secondmate" \
267
+ "yolo=off" \
268
+ "home=$home" \
269
+ "projects=$projects"
270
+ }
271
+
272
+ # --- common assertions ------------------------------------------------------
273
+
274
+ # assert_contains <haystack> <needle> <msg>
275
+ assert_contains() {
276
+ case "$1" in
277
+ *"$2"*) : ;;
278
+ *) fail "$3 (missing: '$2')"$'\n'"--- output ---"$'\n'"$1" ;;
279
+ esac
280
+ }
281
+
282
+ # assert_not_contains <haystack> <needle> <msg>
283
+ assert_not_contains() {
284
+ case "$1" in
285
+ *"$2"*) fail "$3 (unexpected: '$2')"$'\n'"--- output ---"$'\n'"$1" ;;
286
+ *) : ;;
287
+ esac
288
+ }
289
+
290
+ # expect_code <expected> <actual> <label>
291
+ expect_code() {
292
+ local expected=$1 actual=$2 label=$3
293
+ [ "$actual" = "$expected" ] || fail "$label: expected exit $expected, got $actual"
294
+ }
295
+
296
+ # assert_grep <pattern> <file> <msg>: fixed-string grep must match in <file>.
297
+ # `--` guards patterns that begin with '-' (e.g. backlog/registry lines).
298
+ assert_grep() {
299
+ grep -F -- "$1" "$2" >/dev/null || fail "$3"
300
+ }
301
+
302
+ # assert_no_grep <pattern> <file> <msg>: fixed-string grep must NOT match.
303
+ assert_no_grep() {
304
+ ! grep -F -- "$1" "$2" >/dev/null || fail "$3"
305
+ }
306
+
307
+ # assert_absent <path> <msg>: path must not exist.
308
+ assert_absent() {
309
+ [ ! -e "$1" ] || fail "$2"
310
+ }
311
+
312
+ # assert_present <path> <msg>: path must exist.
313
+ assert_present() {
314
+ [ -e "$1" ] || fail "$2"
315
+ }
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env bash
2
+ # tests/remote-herdr-fixture.sh - the stateful herdr CLI fixture the remote
3
+ # second-mate suites install on their fake remote host.
4
+ #
5
+ # A remote second mate always launches on the Herdr backend
6
+ # (docs/remote-secondmates.md), so a remote-route test needs a herdr CLI on the
7
+ # remote code root's own bin directory. This fixture models the workspace, tab,
8
+ # pane, and agent facts bin/backends/herdr.sh actually reads, backed by a JSON
9
+ # state file mutated with real jq, using the same verified herdr behaviors as
10
+ # tests/fm-backend-herdr.test.sh's stateful fake: workspace create seeds one
11
+ # default tab and returns its tab and root pane in the same response, closing a
12
+ # tab's only pane closes the tab, and agent get reports agent_not_found for a
13
+ # pane no agent has registered on.
14
+ #
15
+ # Beyond that it models the pane IO a real launch performs. A pane reports a
16
+ # registered agent once anything has been typed into it, and submitting starts
17
+ # one turn: the next agent read reports working and the pane settles back to
18
+ # idle, which is the native transition the adapter confirms a submit with.
19
+ #
20
+ # Usage:
21
+ # . "$(dirname "${BASH_SOURCE[0]}")/remote-herdr-fixture.sh"
22
+ # install_remote_herdr_fixture <remote-root> <state-file> <log-file> \
23
+ # <send-fail-flag> <socket-path>
24
+ #
25
+ # Every invocation is appended verbatim to <log-file>, so a test reads back what
26
+ # the remote pane received. Creating <send-fail-flag> makes every pane write
27
+ # fail, which is how a test simulates an endpoint that cannot be reached.
28
+
29
+ install_remote_herdr_fixture() { # <remote-root> <state> <log> <send-fail> <socket>
30
+ local remote_root=$1 state=$2 log=$3 send_fail=$4 socket=$5 script="$1/bin/herdr"
31
+ mkdir -p "$remote_root/bin"
32
+ cat > "$script" <<SH
33
+ #!/usr/bin/env bash
34
+ set -u
35
+ STATE='$state'
36
+ LOG='$log'
37
+ SEND_FAIL='$send_fail'
38
+ SOCKET='$socket'
39
+ SH
40
+ cat >> "$script" <<'SH'
41
+ printf '%s\n' "$*" >> "$LOG"
42
+ jq_state() { jq "$@" "$STATE"; }
43
+ save() { tmp="$STATE.tmp.$$"; cat > "$tmp" && mv "$tmp" "$STATE"; }
44
+ ws=""; label=""; cwd=""
45
+ args=("$@")
46
+ for ((i=0; i<${#args[@]}; i++)); do
47
+ case "${args[$i]}" in
48
+ --workspace) ws=${args[$((i+1))]:-} ;;
49
+ --label) label=${args[$((i+1))]:-} ;;
50
+ --cwd) cwd=${args[$((i+1))]:-} ;;
51
+ esac
52
+ done
53
+ case "${1:-} ${2:-}" in
54
+ "status --json")
55
+ printf '{"client":{"version":"0.7.5","protocol":16},"server":{"running":true}}\n' ;;
56
+ "server "*|"server") : ;;
57
+ "workspace list") jq_state '{result:{workspaces:.workspaces}}' ;;
58
+ "workspace create")
59
+ n=$(jq_state -r '.next'); wsid="w$n"; dn=$((n + 1))
60
+ jq_state --arg wsid "$wsid" --arg wlabel "$label" --arg cwd "$cwd" \
61
+ --arg tabid "$wsid:t$dn" --arg paneid "$wsid:p$dn" \
62
+ '.workspaces += [{workspace_id:$wsid, label:$wlabel, cwd:$cwd}]
63
+ | .tabs += [{tab_id:$tabid, label:"1", workspace_id:$wsid, pane_id:$paneid}]
64
+ | .next = (.next + 2)' | save
65
+ printf '{"result":{"workspace":{"workspace_id":"%s","label":"%s"},"tab":{"tab_id":"%s"},"root_pane":{"pane_id":"%s"}}}\n' \
66
+ "$wsid" "$label" "$wsid:t$dn" "$wsid:p$dn"
67
+ ;;
68
+ "tab list") jq_state --arg w "$ws" '{result:{tabs:[.tabs[]|select(.workspace_id==$w)]}}' ;;
69
+ "tab create")
70
+ n=$(jq_state -r '.next'); tabid="$ws:t$n"; paneid="$ws:p$n"
71
+ jq_state --arg w "$ws" --arg wlabel "$label" --arg cwd "$cwd" --arg tabid "$tabid" --arg paneid "$paneid" \
72
+ '.tabs += [{tab_id:$tabid, label:$wlabel, workspace_id:$w, pane_id:$paneid, cwd:$cwd}]
73
+ | .next = (.next + 1)' | save
74
+ printf '{"result":{"tab":{"tab_id":"%s"},"root_pane":{"pane_id":"%s"}}}\n' "$tabid" "$paneid"
75
+ ;;
76
+ "tab close")
77
+ jq_state --arg t "${3:-}" '.tabs |= [.[]|select(.tab_id != $t)]' | save ;;
78
+ "pane list")
79
+ jq_state --arg w "$ws" '{result:{panes:[.tabs[]|select(.workspace_id==$w)|{pane_id:.pane_id, tab_id:.tab_id}]}}' ;;
80
+ "pane get")
81
+ pane=${3:-}
82
+ if [ "$(jq_state -r --arg p "$pane" '[.tabs[]|select(.pane_id==$p)]|length')" = 0 ]; then
83
+ printf '{"error":{"code":"pane_not_found","message":"%s"}}\n' "$pane"
84
+ else
85
+ printf '{"result":{"pane":{"pane_id":"%s"}}}\n' "$pane"
86
+ fi
87
+ ;;
88
+ "pane close")
89
+ jq_state --arg p "${3:-}" \
90
+ '.tabs |= [.[]|select(.pane_id != $p)]
91
+ | .typed |= with_entries(select(.key != $p))
92
+ | .working |= with_entries(select(.key != $p))' | save ;;
93
+ "pane send-text")
94
+ [ ! -f "$SEND_FAIL" ] || exit 1
95
+ jq_state --arg p "${3:-}" '.typed[$p] = true' | save ;;
96
+ "pane send-keys")
97
+ [ ! -f "$SEND_FAIL" ] || exit 1
98
+ jq_state --arg p "${3:-}" '.typed[$p] = true | .working[$p] = true' | save ;;
99
+ "pane read") printf '\n' ;;
100
+ "pane process-info") printf '{"result":{"process":{"name":"codex"}}}\n' ;;
101
+ "agent get")
102
+ pane=${3:-}
103
+ if [ "$(jq_state -r --arg p "$pane" '.working[$p] // false')" = true ]; then
104
+ jq_state --arg p "$pane" '.working |= with_entries(select(.key != $p))' | save
105
+ printf '{"result":{"agent":{"agent_status":"working"}}}\n'
106
+ elif [ "$(jq_state -r --arg p "$pane" '.typed[$p] // false')" = true ]; then
107
+ printf '{"result":{"agent":{"agent_status":"idle"}}}\n'
108
+ else
109
+ printf '{"error":{"code":"agent_not_found","message":"%s"}}\n' "$pane"
110
+ fi
111
+ ;;
112
+ "session list"*)
113
+ printf '{"sessions":[{"name":"default","running":true,"socket_path":"%s"},{"name":"fm-remote","running":true,"socket_path":"%s"}]}\n' "$SOCKET" "$SOCKET" ;;
114
+ esac
115
+ exit 0
116
+ SH
117
+ chmod +x "$script"
118
+ reset_remote_herdr_fixture "$state"
119
+ }
120
+
121
+ # reset_remote_herdr_fixture <state>: return the fake host to "no workspaces,
122
+ # tabs, or panes", which is what a test means by "the previous endpoint is gone".
123
+ reset_remote_herdr_fixture() { # <state>
124
+ printf '{"next":1,"workspaces":[],"tabs":[],"typed":{},"working":{}}\n' > "$1"
125
+ }