@zerwiz/ymir 0.1.4 → 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 -59
  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,559 @@
1
+ #!/usr/bin/env bash
2
+ # tests/fm-secondmate-liveness.test.sh - the session-start secondmate liveness
3
+ # guarantee owned by bin/fm-backend.sh's detailed fm_backend_agent_state and
4
+ # bin/fm-bootstrap.sh's secondmate_liveness_sweep that acts on it.
5
+ #
6
+ # The gap under test (AGENTS.md "Session start"; evidence 2026-07-07): a
7
+ # secondmate agent that has exited leaves its backend endpoint alive as a bare
8
+ # shell. fm_backend_target_exists only checks pane PRESENCE, so it reports
9
+ # that shell "alive"; recovery only respawns endpoints reported dead, and the
10
+ # watcher deliberately exempts secondmates from stale-pane detection (an idle
11
+ # secondmate pane is healthy by design). A dead-shell secondmate was therefore
12
+ # invisible to every existing check and sat dead indefinitely.
13
+ #
14
+ # The guarantees under test:
15
+ # - fm_backend_agent_state is the detailed owner that distinguishes alive,
16
+ # dead, missing, ambiguous, unreadable, and unverified.
17
+ # - The tmux classifier returns missing only after a readable session
18
+ # inventory omits the exact window, regardless of display-message fallback.
19
+ # - The Herdr classifier preserves the proven husk mapping while separating a
20
+ # missing pane from an existing agent-less pane.
21
+ # - fm_backend_agent_alive preserves the older three-state compatibility view.
22
+ # - bin/fm-bootstrap.sh's secondmate_liveness_sweep recovers only dead or
23
+ # missing endpoints, keeps successful recovery and already-live results
24
+ # silent by default, and reports ambiguous and unreadable targets distinctly.
25
+ # - The sweep converges: once a secondmate reads alive, a later run never
26
+ # re-touches it (idempotent by construction, not by remembering what it
27
+ # already did).
28
+ # - The sweep is skipped entirely under FM_BOOTSTRAP_DETECT_ONLY=1 (the
29
+ # read-only session path), matching the other mutating sweeps.
30
+ # - The sweep is naturally scoped to the primary: with no kind=secondmate
31
+ # meta present (a secondmate's own state/ never holds one, since
32
+ # secondmates never spawn secondmates), it is a silent no-op.
33
+ set -u
34
+
35
+ # shellcheck source=tests/lib.sh
36
+ . "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
37
+
38
+ BASE_PATH=${FM_TEST_BASE_PATH:-/usr/bin:/bin:/usr/sbin:/sbin}
39
+ fm_git_identity fmtest fmtest@example.com
40
+
41
+ TMP_ROOT=$(fm_test_tmproot fm-secondmate-liveness)
42
+
43
+ # --- unit level: fm_backend_tmux_agent_state --------------------------------
44
+
45
+ # make_probe_tmux <dir> <pane_current_command>: a fake tmux whose
46
+ # #{pane_current_command} display-message query answers with the fixed value;
47
+ # every other subcommand is a silent no-op success.
48
+ make_probe_tmux() {
49
+ local dir=$1 comm=$2 fakebin
50
+ fakebin=$(fm_fakebin "$dir")
51
+ cat > "$fakebin/tmux" <<SH
52
+ #!/usr/bin/env bash
53
+ set -u
54
+ case "\${1:-}" in
55
+ display-message)
56
+ for a in "\$@"; do case "\$a" in *pane_current_command*) printf '%s\n' '$comm'; exit 0 ;; esac; done
57
+ exit 0 ;;
58
+ list-windows) printf '%s\n' win; exit 0 ;;
59
+ esac
60
+ exit 0
61
+ SH
62
+ chmod +x "$fakebin/tmux"
63
+ printf '%s\n' "$fakebin"
64
+ }
65
+
66
+ # make_failed_probe_tmux <dir> <inventory>: missing and present fail the pane
67
+ # read, while unreadable returns a misleading fallback node process but fails
68
+ # the inventory that must be authoritative.
69
+ make_failed_probe_tmux() {
70
+ local dir=$1 inventory=$2 fakebin
71
+ fakebin=$(fm_fakebin "$dir")
72
+ cat > "$fakebin/tmux" <<SH
73
+ #!/usr/bin/env bash
74
+ set -u
75
+ case "\${1:-}" in
76
+ display-message)
77
+ [ '$inventory' = unreadable ] && { printf '%s\n' node; exit 0; }
78
+ exit 1
79
+ ;;
80
+ list-windows)
81
+ case '$inventory' in
82
+ missing) printf '%s\n' main ; exit 0 ;;
83
+ missing-session) printf '%s\n' "can't find session: sess" >&2; exit 1 ;;
84
+ missing-server) printf '%s\n' "no server running on /tmp/tmux-test/default" >&2; exit 1 ;;
85
+ missing-socket) printf '%s\n' "error connecting to /tmp/tmux-test/default (No such file or directory)" >&2; exit 1 ;;
86
+ present) printf '%s\n' fm-sm1 ; exit 0 ;;
87
+ *) printf '%s\n' "permission denied" >&2; exit 1 ;;
88
+ esac
89
+ ;;
90
+ esac
91
+ exit 1
92
+ SH
93
+ chmod +x "$fakebin/tmux"
94
+ printf '%s\n' "$fakebin"
95
+ }
96
+
97
+ test_tmux_agent_state_classifies() {
98
+ local fb out
99
+
100
+ for harness in claude codex opencode grok kimi pi pi-signed pi-launcher Pi; do
101
+ fb=$(make_probe_tmux "$TMP_ROOT/tmux-$harness" "$harness")
102
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:win' "$ROOT")
103
+ [ "$out" = alive ] || fail "a live $harness foreground process should classify as alive, got '$out'"
104
+ done
105
+
106
+ for shell in zsh bash -zsh; do
107
+ fb=$(make_probe_tmux "$TMP_ROOT/tmux-${shell#-}" "$shell")
108
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:win' "$ROOT")
109
+ [ "$out" = dead ] || fail "a bare $shell foreground process should classify as dead, got '$out'"
110
+ done
111
+
112
+ fb=$(make_probe_tmux "$TMP_ROOT/tmux-node" node)
113
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:win' "$ROOT")
114
+ [ "$out" = ambiguous ] || fail "an existing node process should classify as ambiguous, got '$out'"
115
+ [ "$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_alive tmux sess:win' "$ROOT")" = unknown ] \
116
+ || fail "the compatibility view must keep an existing node process unknown"
117
+
118
+ fb=$(make_failed_probe_tmux "$TMP_ROOT/tmux-missing" missing)
119
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:fm-sm1' "$ROOT")
120
+ [ "$out" = missing ] || fail "a readable inventory omitting the target should classify as missing, got '$out'"
121
+ [ "$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_alive tmux sess:fm-sm1' "$ROOT")" = dead ] \
122
+ || fail "the compatibility view should treat an authoritatively missing target as dead"
123
+
124
+ for inventory in present unreadable; do
125
+ fb=$(make_failed_probe_tmux "$TMP_ROOT/tmux-$inventory" "$inventory")
126
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:fm-sm1' "$ROOT")
127
+ [ "$out" = unreadable ] || fail "a $inventory inventory case should stay unreadable, got '$out'"
128
+ done
129
+
130
+ for inventory in missing-session missing-server missing-socket; do
131
+ fb=$(make_failed_probe_tmux "$TMP_ROOT/tmux-$inventory" "$inventory")
132
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:fm-sm1' "$ROOT")
133
+ [ "$out" = missing ] || fail "a confirmed $inventory inventory failure should classify as missing, got '$out'"
134
+ done
135
+
136
+ pass "fm_backend_tmux_agent_state: separates live, dead, missing, ambiguous, and unreadable"
137
+ }
138
+
139
+ test_tmux_agent_state_rejects_malformed_targets_before_probe() {
140
+ local fakebin marker target out
141
+ fakebin=$(fm_fakebin "$TMP_ROOT/tmux-malformed")
142
+ marker="$TMP_ROOT/tmux-malformed-called"
143
+ cat > "$fakebin/tmux" <<'SH'
144
+ #!/usr/bin/env bash
145
+ printf 'called\n' > "$FM_TEST_TMUX_MARKER"
146
+ printf 'bash\n'
147
+ SH
148
+ chmod +x "$fakebin/tmux"
149
+
150
+ for target in sess sess: :win sess:win:extra; do
151
+ out=$(PATH="$fakebin:$BASE_PATH" FM_TEST_TMUX_MARKER="$marker" \
152
+ bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux "$1"' "$ROOT" "$target")
153
+ [ "$out" = unreadable ] || fail "malformed tmux target '$target' should classify as unreadable, got '$out'"
154
+ [ ! -e "$marker" ] || fail "malformed tmux target '$target' invoked tmux"
155
+ done
156
+
157
+ pass "fm_backend_tmux_agent_state: rejects malformed targets before probing tmux"
158
+ }
159
+
160
+ # --- unit level: fm_backend_herdr_agent_state -------------------------------
161
+
162
+ test_herdr_agent_state_preserves_husk_classifier() {
163
+ local pane_state expected out
164
+
165
+ for row in 'dead missing' 'no-agent dead' 'live alive' 'unknown unreadable'; do
166
+ pane_state=${row%% *}
167
+ expected=${row#* }
168
+ out=$(FM_TEST_PANE_STATE="$pane_state" bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_pane_agent_state() { printf "%s" "$FM_TEST_PANE_STATE"; }; fm_backend_herdr_agent_state "sess:p1"' "$ROOT")
169
+ [ "$out" = "$expected" ] || fail "Herdr pane state $pane_state should map to $expected, got '$out'"
170
+ done
171
+
172
+ out=$(bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_agent_state "no-colon-target"' "$ROOT")
173
+ [ "$out" = unreadable ] || fail "an unparseable Herdr target should classify as unreadable, got '$out'"
174
+
175
+ out=$(bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_pane_agent_state() { printf "no-agent"; }; fm_backend_herdr_agent_alive "sess:p1"' "$ROOT")
176
+ [ "$out" = dead ] || fail "the Herdr compatibility view should keep a no-agent husk dead, got '$out'"
177
+
178
+ pass "fm_backend_herdr_agent_state: preserves missing/no-agent/live/unknown husk behavior"
179
+ }
180
+
181
+ # --- unit level: the generic dispatchers ------------------------------------
182
+
183
+ test_agent_state_dispatcher_and_compatibility() {
184
+ local fb out
185
+
186
+ fb=$(make_probe_tmux "$TMP_ROOT/dispatch-tmux" claude)
187
+ out=$(PATH="$fb:$BASE_PATH" bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state tmux sess:win' "$ROOT")
188
+ [ "$out" = alive ] || fail "detailed dispatcher should route tmux, got '$out'"
189
+
190
+ out=$(bash -c '. "$0/bin/fm-backend.sh"; fm_backend_source herdr; fm_backend_herdr_pane_agent_state() { printf "live"; }; fm_backend_agent_state herdr sess:p1' "$ROOT")
191
+ [ "$out" = alive ] || fail "detailed dispatcher should route Herdr, got '$out'"
192
+
193
+ out=$(bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_state zellij sess:7' "$ROOT")
194
+ [ "$out" = unverified ] || fail "Zellij should remain unverified, got '$out'"
195
+ out=$(bash -c '. "$0/bin/fm-backend.sh"; fm_backend_agent_alive zellij sess:7' "$ROOT")
196
+ [ "$out" = unknown ] || fail "the compatibility dispatcher should map unverified to unknown, got '$out'"
197
+
198
+ pass "fm_backend_agent_state: routes tmux/Herdr and keeps Zellij unverified"
199
+ }
200
+
201
+ # --- sweep level: bin/fm-bootstrap.sh's secondmate_liveness_sweep -----------
202
+
203
+ # make_toolchain <dir>: the fixed set of stubs bin/fm-bootstrap.sh's read-only
204
+ # diagnostics need to stay quiet (mirrors tests/fm-secondmate-sync.test.sh's
205
+ # make_fake_toolchain), MINUS tmux - callers add their own controllable tmux.
206
+ make_toolchain() {
207
+ local dir=$1 fakebin
208
+ fakebin=$(fm_fakebin "$dir")
209
+ fm_fake_exit0 "$fakebin" node chrome-devtools-axi pi-signed
210
+ fm_fake_version_tool "$fakebin" lavish-axi FM_FAKE_LAVISH_AXI_VERSION 0.1.46
211
+ cat > "$fakebin/gh-axi" <<'SH'
212
+ #!/usr/bin/env bash
213
+ if [ "${1:-}" = --version ]; then
214
+ printf '%s\n' '0.1.29'
215
+ exit 0
216
+ fi
217
+ exit 0
218
+ SH
219
+ chmod +x "$fakebin/gh-axi"
220
+ cat > "$fakebin/gh" <<'SH'
221
+ #!/usr/bin/env bash
222
+ exit 0
223
+ SH
224
+ chmod +x "$fakebin/gh"
225
+ cat > "$fakebin/treehouse" <<'SH'
226
+ #!/usr/bin/env bash
227
+ if [ "${1:-}" = get ] && [ "${2:-}" = --help ]; then
228
+ printf '%s\n' 'Usage: treehouse get [--lease]'
229
+ fi
230
+ exit 0
231
+ SH
232
+ chmod +x "$fakebin/treehouse"
233
+ cat > "$fakebin/no-mistakes" <<'SH'
234
+ #!/usr/bin/env bash
235
+ if [ "${1:-}" = --version ]; then
236
+ printf '%s\n' 'no-mistakes version v1.46.0 (fake)'
237
+ exit 0
238
+ fi
239
+ exit 0
240
+ SH
241
+ chmod +x "$fakebin/no-mistakes"
242
+ cat > "$fakebin/tasks-axi" <<'SH'
243
+ #!/usr/bin/env bash
244
+ case "${1:-} ${2:-}" in
245
+ "--version ") printf '%s\n' '0.2.4' ;;
246
+ "update --help") printf '%s\n' 'usage: tasks-axi update <id> [flags]' ' --archive-body' ;;
247
+ "mv --help") printf '%s\n' 'usage: tasks-axi mv <id> [<id>...] --to <path-or-dir>' ;;
248
+ esac
249
+ exit 0
250
+ SH
251
+ chmod +x "$fakebin/tasks-axi"
252
+ cat > "$fakebin/quota-axi" <<'SH'
253
+ #!/usr/bin/env bash
254
+ if [ "${1:-}" = --version ]; then
255
+ printf '%s\n' '0.1.29'
256
+ exit 0
257
+ fi
258
+ exit 0
259
+ SH
260
+ chmod +x "$fakebin/quota-axi"
261
+ printf '%s\n' "$fakebin"
262
+ }
263
+
264
+ # make_liveness_tmux <dir>: a controllable tmux stub. FM_TEST_PANE_CMD may be
265
+ # a foreground command, `missing` (readable inventory omits the window), or
266
+ # `unreadable` (both pane and inventory reads fail).
267
+ make_liveness_tmux() {
268
+ local dir=$1 fakebin
269
+ fakebin=$(fm_fakebin "$dir")
270
+ cat > "$fakebin/tmux" <<'SH'
271
+ #!/usr/bin/env bash
272
+ set -u
273
+ mode=${FM_TEST_PANE_CMD:-zsh}
274
+ case "${1:-}" in
275
+ display-message)
276
+ for a in "$@"; do
277
+ case "$a" in
278
+ *pane_current_command*)
279
+ case "$mode" in
280
+ missing) printf '%s\n' node; exit 0 ;;
281
+ unreadable) exit 1 ;;
282
+ *) printf '%s\n' "$mode"; exit 0 ;;
283
+ esac
284
+ ;;
285
+ esac
286
+ done
287
+ exit 0
288
+ ;;
289
+ list-windows)
290
+ case "$mode" in
291
+ missing) printf '%s\n' main; exit 0 ;;
292
+ unreadable) exit 1 ;;
293
+ *) [ -e "${FM_TMUX_CALL_LOG:?}.killed" ] || printf '%s\n' fm-sm1; exit 0 ;;
294
+ esac
295
+ ;;
296
+ new-window|kill-window)
297
+ printf '%s\n' "$*" >> "${FM_TMUX_CALL_LOG:?}"
298
+ [ "${1:-}" = kill-window ] && : > "${FM_TMUX_CALL_LOG}.killed"
299
+ [ "${FM_TEST_FAIL_NEW_WINDOW:-0}" = 1 ] && [ "${1:-}" = new-window ] && exit 1
300
+ [ "${1:-}" = new-window ] && rm -f "${FM_TMUX_CALL_LOG}.killed"
301
+ exit 0
302
+ ;;
303
+ has-session) exit 0 ;;
304
+ esac
305
+ exit 0
306
+ SH
307
+ chmod +x "$fakebin/tmux"
308
+ printf '%s\n' "$fakebin"
309
+ }
310
+
311
+ # new_world <name>: a scratch firstmate HOME (state/, watcher beacon, pinned
312
+ # harness) with no kind=secondmate meta yet. FM_ROOT is left to resolve
313
+ # naturally to the real checkout under test ($ROOT), exactly as production
314
+ # always has it - this sweep's own fm-spawn.sh invocation resolves the
315
+ # secondmate harness through $FM_ROOT/bin/fm-harness.sh, which only exists in
316
+ # the real tree. The harness is pinned because ambient own-harness detection is
317
+ # environment-dependent: interactive harness sessions expose markers or parent
318
+ # process names, while a plain pipeline shell can fall through to "unknown",
319
+ # which has no fm-spawn.sh launch template.
320
+ new_world() {
321
+ local name=$1 w
322
+ w="$TMP_ROOT/$name"
323
+ mkdir -p "$w/home/state" "$w/home/config"
324
+ touch "$w/home/state/.last-watcher-beat"
325
+ printf 'codex\n' > "$w/home/config/crew-harness"
326
+ printf '%s\n' "$w"
327
+ }
328
+
329
+ # add_sm_home <w> <id> <window>: a plain (non-git) secondmate home - the
330
+ # probe/respawn machinery under test never requires the home to be a real
331
+ # worktree; a non-git home just makes the unrelated fast-forward sweep log a
332
+ # harmless "not a git repo" skip.
333
+ add_sm_home() {
334
+ local w=$1 id=$2 window=$3 harness=${4:-claude}
335
+ local home="$w/$id"
336
+ mkdir -p "$home/bin" "$home/data" "$home/state" "$home/config" "$home/projects"
337
+ printf '%s\n' "$id" > "$home/.fm-secondmate-home"
338
+ printf '# Firstmate\n' > "$home/AGENTS.md"
339
+ printf 'charter\n' > "$home/data/charter.md"
340
+ {
341
+ printf 'window=%s\n' "$window"
342
+ printf 'kind=secondmate\n'
343
+ printf 'harness=%s\n' "$harness"
344
+ printf 'home=%s\n' "$home"
345
+ } > "$w/home/state/$id.meta"
346
+ }
347
+
348
+ run_bootstrap() { # <fakebin> <home> <pane-cmd> <call-log> [extra env...] -> stdout
349
+ local fb=$1 home=$2 cmd=$3 log=$4; shift 4
350
+ PATH="$fb:$BASE_PATH" TMUX='' FM_BACKEND=tmux FM_HOME="$home" \
351
+ FM_TEST_PANE_CMD="$cmd" FM_TMUX_CALL_LOG="$log" \
352
+ env "$@" "$ROOT/bin/fm-bootstrap.sh" 2>&1
353
+ }
354
+
355
+ test_sweep_respawns_confirmed_dead_secondmate() {
356
+ local w fb tmuxfb log out
357
+ w=$(new_world sweep-dead)
358
+ add_sm_home "$w" sm1 firstmate:fm-sm1
359
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
360
+ log="$w/calls.log"; : > "$log"
361
+
362
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" zsh "$log")
363
+
364
+ assert_not_contains "$out" "SECONDMATE_LIVENESS: secondmate sm1: respawned" \
365
+ "a successfully respawned secondmate should be handled silently"
366
+ assert_contains "$(cat "$log")" "kill-window -t =firstmate:=fm-sm1" \
367
+ "the stale endpoint must be killed before respawn (tmux refuses a same-named window over a live one)"
368
+ assert_contains "$(cat "$log")" "new-window" \
369
+ "a confirmed-dead secondmate should actually be relaunched"
370
+ pass "sweep: a confirmed-dead secondmate endpoint is killed and respawned"
371
+ }
372
+
373
+ test_sweep_leaves_alive_secondmate_untouched() {
374
+ local w fb tmuxfb log out
375
+ w=$(new_world sweep-alive)
376
+ add_sm_home "$w" sm1 firstmate:fm-sm1
377
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
378
+ log="$w/calls.log"; : > "$log"
379
+
380
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" claude "$log")
381
+
382
+ assert_not_contains "$out" "SECONDMATE_LIVENESS: secondmate sm1: already-live" \
383
+ "an already-live secondmate should be handled silently"
384
+ [ ! -s "$log" ] || fail "an already-live secondmate must never be killed or respawned: $(cat "$log")"
385
+
386
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" claude "$log" FM_BOOTSTRAP_VERBOSE_FACTS=1)
387
+ assert_contains "$out" "BOOTSTRAP_INFO: secondmate sm1 already live (backend=tmux)" \
388
+ "verbose diagnostics should identify the already-live outcome"
389
+ [ ! -s "$log" ] || fail "verbose reporting must not touch an already-live secondmate: $(cat "$log")"
390
+ pass "sweep: an already-live secondmate is untouched and distinguishable in verbose diagnostics"
391
+ }
392
+
393
+ test_sweep_respawns_authoritatively_missing_pi_secondmate() {
394
+ local w fb tmuxfb log out
395
+ w=$(new_world sweep-missing-pi)
396
+ add_sm_home "$w" sm1 firstmate:fm-sm1 pi
397
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
398
+ log="$w/calls.log"; : > "$log"
399
+
400
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" missing "$log")
401
+
402
+ assert_not_contains "$out" "SECONDMATE_LIVENESS:" "a successful missing-window recovery should stay silent by default"
403
+ assert_contains "$(cat "$log")" "new-window" "an authoritatively missing Pi secondmate should be relaunched"
404
+ assert_not_contains "$(cat "$log")" "kill-window" "an absent window should not need a destructive pre-kill"
405
+ pass "sweep: an authoritatively missing Pi secondmate window is relaunched"
406
+ }
407
+
408
+ test_sweep_respawns_authoritatively_missing_pi_signed_secondmate() {
409
+ local w fb tmuxfb log out
410
+ w=$(new_world sweep-missing-pi-signed)
411
+ printf '%s\n' pi-signed > "$w/home/config/secondmate-harness"
412
+ add_sm_home "$w" sm1 firstmate:fm-sm1 pi-signed
413
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
414
+ log="$w/calls.log"; : > "$log"
415
+
416
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" missing "$log")
417
+
418
+ assert_not_contains "$out" "unverified for recovery" \
419
+ "a recorded pi-signed secondmate should be verified for recovery"
420
+ assert_contains "$(cat "$log")" "new-window" \
421
+ "an authoritatively missing pi-signed secondmate should be relaunched"
422
+ assert_not_contains "$(cat "$log")" "kill-window" \
423
+ "an absent pi-signed window should not need a destructive pre-kill"
424
+ pass "sweep: an authoritatively missing pi-signed secondmate window is relaunched"
425
+ }
426
+
427
+ test_sweep_never_acts_on_ambiguous_existing_process() {
428
+ local w fb tmuxfb log out
429
+ w=$(new_world sweep-ambiguous)
430
+ add_sm_home "$w" sm1 firstmate:fm-sm1 pi
431
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
432
+ log="$w/calls.log"; : > "$log"
433
+
434
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" node "$log")
435
+
436
+ assert_contains "$out" "SECONDMATE_LIVENESS: secondmate sm1: skipped: existing endpoint has ambiguous agent process" \
437
+ "an existing Pi-shaped node process should be reported as ambiguous"
438
+ [ ! -s "$log" ] || fail "an ambiguous existing process must never trigger kill or relaunch: $(cat "$log")"
439
+ pass "sweep: an existing ambiguous Pi process prevents duplicate recovery"
440
+ }
441
+
442
+ test_sweep_never_acts_on_transient_unreadability() {
443
+ local w fb tmuxfb log out
444
+ w=$(new_world sweep-unreadable)
445
+ add_sm_home "$w" sm1 firstmate:fm-sm1 pi
446
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
447
+ log="$w/calls.log"; : > "$log"
448
+
449
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" unreadable "$log")
450
+
451
+ assert_contains "$out" "SECONDMATE_LIVENESS: secondmate sm1: skipped: endpoint probe unreadable" \
452
+ "a transiently unreadable target should be distinguished from an absent one"
453
+ [ ! -s "$log" ] || fail "an unreadable target must never trigger kill or relaunch: $(cat "$log")"
454
+ pass "sweep: transient target unreadability never licenses recovery"
455
+ }
456
+
457
+ test_sweep_reports_missing_endpoint_relaunch_failure() {
458
+ local w fb tmuxfb log out
459
+ w=$(new_world sweep-missing-failure)
460
+ add_sm_home "$w" sm1 firstmate:fm-sm1 pi
461
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
462
+ log="$w/calls.log"; : > "$log"
463
+
464
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" missing "$log" FM_TEST_FAIL_NEW_WINDOW=1)
465
+
466
+ assert_contains "$out" "SECONDMATE_LIVENESS: secondmate sm1: respawn failed after recorded endpoint confidently missing" \
467
+ "a failed missing-endpoint relaunch should retain its authorizing cause"
468
+ pass "sweep: failed relaunch diagnostics distinguish a confidently missing endpoint"
469
+ }
470
+
471
+ test_sweep_never_acts_on_unverified_harness_dead_reading() {
472
+ local w fb tmuxfb log out
473
+ w=$(new_world sweep-unverified-harness)
474
+ add_sm_home "$w" sm1 firstmate:fm-sm1 custom-agent
475
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
476
+ log="$w/calls.log"; : > "$log"
477
+
478
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" zsh "$log")
479
+
480
+ assert_contains "$out" "SECONDMATE_LIVENESS: secondmate sm1: skipped: recorded harness 'custom-agent' is unverified for recovery" \
481
+ "an unverified harness should not let a dead endpoint become actionable"
482
+ [ ! -s "$log" ] || fail "an unverified harness must never trigger kill or relaunch: $(cat "$log")"
483
+ pass "sweep: an unverified harness blocks recovery with a concrete diagnostic"
484
+ }
485
+
486
+ test_sweep_converges_no_retouch_once_alive() {
487
+ local w fb tmuxfb log out1 out2
488
+ w=$(new_world sweep-idempotent)
489
+ add_sm_home "$w" sm1 firstmate:fm-sm1
490
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
491
+ log="$w/calls.log"; : > "$log"
492
+
493
+ # Round 1: dead -> respawned silently (kill + new-window logged).
494
+ out1=$(run_bootstrap "$tmuxfb:$fb" "$w/home" zsh "$log")
495
+ assert_not_contains "$out1" "SECONDMATE_LIVENESS: secondmate sm1: respawned" "round 1 should handle the successful respawn silently"
496
+ [ -s "$log" ] || fail "round 1 should have logged the kill+respawn window operations"
497
+
498
+ # Round 2: the (now-respawned) secondmate is genuinely alive - a second
499
+ # sweep must converge to a pure no-op, not respawn again.
500
+ : > "$log"
501
+ out2=$(run_bootstrap "$tmuxfb:$fb" "$w/home" claude "$log")
502
+ assert_not_contains "$out2" "SECONDMATE_LIVENESS: secondmate sm1: already-live" "round 2 should handle the already-live secondmate silently"
503
+ [ ! -s "$log" ] || fail "round 2 must not re-kill or re-respawn an already-live secondmate: $(cat "$log")"
504
+ pass "sweep: idempotent by construction - a live secondmate is never re-touched on a later run"
505
+ }
506
+
507
+ test_sweep_skipped_under_detect_only() {
508
+ local w fb tmuxfb log out
509
+ w=$(new_world sweep-detect-only)
510
+ add_sm_home "$w" sm1 firstmate:fm-sm1
511
+ mkdir -p "$w/home/config"
512
+ printf 'codex\n' > "$w/home/config/crew-harness"
513
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
514
+ log="$w/calls.log"; : > "$log"
515
+
516
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" zsh "$log" FM_BOOTSTRAP_DETECT_ONLY=1)
517
+
518
+ assert_not_contains "$out" "CREW_HARNESS_OVERRIDE:" \
519
+ "detect-only should keep routine harness facts silent"
520
+ assert_not_contains "$out" "SECONDMATE_LIVENESS:" \
521
+ "the read-only detect-only path must never run the mutating liveness sweep"
522
+ [ ! -s "$log" ] || fail "detect-only must never touch any endpoint: $(cat "$log")"
523
+ pass "sweep: skipped entirely under FM_BOOTSTRAP_DETECT_ONLY=1, exactly like the other mutating sweeps"
524
+ }
525
+
526
+ test_sweep_noop_with_no_secondmate_meta() {
527
+ local w fb tmuxfb log out
528
+ w=$(new_world sweep-no-secondmates)
529
+ # No add_sm_home call: this state/ dir looks exactly like what a
530
+ # secondmate's OWN home always has (secondmates never spawn secondmates),
531
+ # proving the sweep's primary-only scoping falls out naturally.
532
+ fb=$(make_toolchain "$w"); tmuxfb=$(make_liveness_tmux "$w")
533
+ log="$w/calls.log"; : > "$log"
534
+
535
+ out=$(run_bootstrap "$tmuxfb:$fb" "$w/home" zsh "$log")
536
+
537
+ assert_not_contains "$out" "SECONDMATE_LIVENESS:" \
538
+ "with no kind=secondmate meta present, the sweep must print nothing"
539
+ [ ! -s "$log" ] || fail "with no secondmate meta, no endpoint should ever be touched: $(cat "$log")"
540
+ pass "sweep: a silent no-op with no kind=secondmate meta present (a secondmate home's own natural scoping)"
541
+ }
542
+
543
+ test_tmux_agent_state_classifies
544
+ test_tmux_agent_state_rejects_malformed_targets_before_probe
545
+ test_herdr_agent_state_preserves_husk_classifier
546
+ test_agent_state_dispatcher_and_compatibility
547
+ test_sweep_respawns_confirmed_dead_secondmate
548
+ test_sweep_leaves_alive_secondmate_untouched
549
+ test_sweep_respawns_authoritatively_missing_pi_secondmate
550
+ test_sweep_respawns_authoritatively_missing_pi_signed_secondmate
551
+ test_sweep_never_acts_on_ambiguous_existing_process
552
+ test_sweep_never_acts_on_transient_unreadability
553
+ test_sweep_reports_missing_endpoint_relaunch_failure
554
+ test_sweep_never_acts_on_unverified_harness_dead_reading
555
+ test_sweep_converges_no_retouch_once_alive
556
+ test_sweep_skipped_under_detect_only
557
+ test_sweep_noop_with_no_secondmate_meta
558
+
559
+ echo "# all fm-secondmate-liveness tests passed"