@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,290 @@
1
+ #!/usr/bin/env bash
2
+ # bin/backends/orca.sh - the Orca terminal session-provider adapter.
3
+ #
4
+ # Orca owns both the task worktree and the terminal endpoint. Escape key support
5
+ # remains unsupported until Orca exposes a terminal-send primitive for it.
6
+ #
7
+ # Target string shape: the Orca terminal id accepted by `orca terminal ...`.
8
+
9
+ # Shared composer-content classifier (empty|pending|unknown, and the fleet-wide
10
+ # dead-shell-vs-agent-composer rule). Owned by bin/fm-composer-lib.sh, reused by
11
+ # every backend so the decision cannot drift.
12
+ # shellcheck source=bin/fm-composer-lib.sh
13
+ . "$(dirname -- "${BASH_SOURCE[0]}")/../fm-composer-lib.sh"
14
+
15
+ fm_backend_orca_tool_check() {
16
+ command -v orca >/dev/null 2>&1 || { echo "error: backend=orca selected but the 'orca' CLI is not installed" >&2; return 1; }
17
+ }
18
+
19
+ fm_backend_orca_runtime_check() {
20
+ fm_backend_orca_tool_check || return 1
21
+ local out
22
+ out=$(orca status --json 2>/dev/null) || {
23
+ echo "error: backend=orca selected but 'orca status --json' failed; start Orca and wait for the runtime to be ready" >&2
24
+ return 1
25
+ }
26
+ # shellcheck disable=SC2016 # Single quotes are deliberate: ${...} belongs to the Node snippet.
27
+ printf '%s' "$out" | node -e '
28
+ const fs = require("fs");
29
+ let data;
30
+ try {
31
+ data = JSON.parse(fs.readFileSync(0, "utf8"));
32
+ } catch (err) {
33
+ console.error("error: invalid Orca status JSON: " + err.message);
34
+ process.exit(1);
35
+ }
36
+ if (data.ok === false) {
37
+ const msg = data.error && (data.error.message || data.error.code);
38
+ console.error("error: Orca runtime is not ready" + (msg ? ": " + msg : ""));
39
+ process.exit(1);
40
+ }
41
+ const r = data.result || {};
42
+ const runtime = r.runtime || {};
43
+ const reachable = runtime.reachable ?? r.runtimeReachable;
44
+ const state = runtime.state || r.runtimeState || "";
45
+ if (reachable === true && state === "ready") process.exit(0);
46
+ console.error(`error: backend=orca requires a ready Orca runtime (reachable=${String(reachable)}, state=${state || "unknown"})`);
47
+ process.exit(1);
48
+ '
49
+ }
50
+
51
+ fm_backend_orca_json_get() { # <field> ; fields: worktree-id worktree-path terminal-handle worktree-terminal-handle repo-id
52
+ # Terminal handles are accepted only from verified terminal result shapes:
53
+ # result.terminal or a root terminal object with .handle. Undocumented
54
+ # result.id and result.worktree.terminal shapes are ignored until a real Orca
55
+ # smoke run proves them.
56
+ local field=$1
57
+ node -e '
58
+ const fs = require("fs");
59
+ const field = process.argv[1];
60
+ const data = JSON.parse(fs.readFileSync(0, "utf8"));
61
+ if (data.ok === false) {
62
+ const msg = data.error && (data.error.message || data.error.code);
63
+ if (msg) console.error(msg);
64
+ process.exit(2);
65
+ }
66
+ const r = data.result || {};
67
+ const wt = r.worktree || r.item || r;
68
+ const explicitTerm = r.terminal || null;
69
+ const repo = r.repo || r.repository || r;
70
+ function scalar(v) {
71
+ return (typeof v === "string" || typeof v === "number") ? String(v) : "";
72
+ }
73
+ function handle(obj) {
74
+ if (!obj) return "";
75
+ if (typeof obj === "string" || typeof obj === "number") return String(obj);
76
+ return scalar(obj.handle) || "";
77
+ }
78
+ let v = "";
79
+ if (field === "worktree-id") v = wt.id || wt.worktreeId || r.worktreeId || "";
80
+ if (field === "worktree-path") v = wt.path || (wt.git && wt.git.path) || r.path || "";
81
+ if (field === "terminal-handle") v = handle(explicitTerm || r) || "";
82
+ if (field === "worktree-terminal-handle") v = handle(explicitTerm) || "";
83
+ if (field === "repo-id") v = repo.id || repo.repoId || r.repoId || "";
84
+ if (!v) process.exit(1);
85
+ process.stdout.write(String(v));
86
+ ' "$field"
87
+ }
88
+
89
+ fm_backend_orca_json_ok() {
90
+ node -e '
91
+ const fs = require("fs");
92
+ const input = fs.readFileSync(0, "utf8").trim();
93
+ if (!input) process.exit(0);
94
+ let data;
95
+ try {
96
+ data = JSON.parse(input);
97
+ } catch (err) {
98
+ console.error("invalid Orca JSON: " + err.message);
99
+ process.exit(2);
100
+ }
101
+ if (data.ok === false) {
102
+ const msg = data.error && (data.error.message || data.error.code);
103
+ if (msg) console.error(msg);
104
+ process.exit(2);
105
+ }
106
+ '
107
+ }
108
+
109
+ fm_backend_orca_run_json() {
110
+ local out
111
+ out=$("$@") || return 1
112
+ printf '%s' "$out" | fm_backend_orca_json_ok
113
+ }
114
+
115
+ fm_backend_orca_repo_ensure() { # <project-path>
116
+ local project=$1 out repo_id
117
+ fm_backend_orca_tool_check || return 1
118
+ out=$(orca repo show --repo "path:$project" --json 2>/dev/null || true)
119
+ if repo_id=$(printf '%s' "$out" | fm_backend_orca_json_get repo-id 2>/dev/null); then
120
+ printf '%s' "$repo_id"
121
+ return 0
122
+ fi
123
+ out=$(orca repo add --path "$project" --json) || return 1
124
+ repo_id=$(printf '%s' "$out" | fm_backend_orca_json_get repo-id) || {
125
+ echo "error: orca repo add did not return a repo id for $project" >&2
126
+ return 1
127
+ }
128
+ printf '%s' "$repo_id"
129
+ }
130
+
131
+ fm_backend_orca_worktree_create() { # <project-path> <name>
132
+ local project=$1 name=$2 repo_id out wt_id wt_path terminal
133
+ repo_id=$(fm_backend_orca_repo_ensure "$project") || return 1
134
+ out=$(orca worktree create --repo "id:$repo_id" --name "$name" --no-parent --setup skip --json) || return 1
135
+ wt_id=$(printf '%s' "$out" | fm_backend_orca_json_get worktree-id) || {
136
+ echo "error: orca worktree create did not return a worktree id for $name" >&2
137
+ return 1
138
+ }
139
+ terminal=$(printf '%s' "$out" | fm_backend_orca_json_get worktree-terminal-handle 2>/dev/null || true)
140
+ wt_path=$(printf '%s' "$out" | fm_backend_orca_json_get worktree-path) || {
141
+ echo "error: orca worktree create did not return a path for $name" >&2
142
+ [ -z "$terminal" ] || fm_backend_orca_kill "$terminal" >/dev/null 2>&1 || true
143
+ if fm_backend_orca_remove_worktree "$wt_id" >/dev/null; then
144
+ return 1
145
+ fi
146
+ if [ -n "$terminal" ]; then
147
+ printf '%s\t\t%s' "$wt_id" "$terminal"
148
+ else
149
+ printf '%s\t' "$wt_id"
150
+ fi
151
+ return 2
152
+ }
153
+ printf '%s\t%s' "$wt_id" "$wt_path"
154
+ [ -z "$terminal" ] || printf '\t%s' "$terminal"
155
+ }
156
+
157
+ fm_backend_orca_terminal_create() { # <worktree-id> <title>
158
+ local worktree_id=$1 title=$2 out terminal
159
+ fm_backend_orca_tool_check || return 1
160
+ out=$(orca terminal create --worktree "id:$worktree_id" --title "$title" --json) || return 1
161
+ terminal=$(printf '%s' "$out" | fm_backend_orca_json_get terminal-handle) || {
162
+ echo "error: orca terminal create did not return a terminal handle for $title" >&2
163
+ return 1
164
+ }
165
+ printf '%s' "$terminal"
166
+ }
167
+
168
+ fm_backend_orca_send_text_line() { # <terminal-id> <text>
169
+ local terminal=$1 text=$2
170
+ fm_backend_orca_tool_check || return 1
171
+ fm_backend_orca_run_json orca terminal send --terminal "$terminal" --text "$text" --enter --json
172
+ }
173
+
174
+ fm_backend_orca_send_literal() { # <terminal-id> <text>
175
+ local terminal=$1 text=$2
176
+ fm_backend_orca_tool_check || return 1
177
+ fm_backend_orca_run_json orca terminal send --terminal "$terminal" --text "$text" --json
178
+ }
179
+
180
+ fm_backend_orca_remove_worktree() { # <worktree-id>
181
+ local worktree_id=${1:-}
182
+ [ -n "$worktree_id" ] || { echo "error: missing Orca worktree id; cannot remove worktree" >&2; return 1; }
183
+ fm_backend_orca_tool_check || return 1
184
+ fm_backend_orca_run_json orca worktree rm --worktree "id:$worktree_id" --force --json
185
+ }
186
+
187
+ fm_backend_orca_worktree_path() {
188
+ local worktree_id=${1:-} out path
189
+ [ -n "$worktree_id" ] || { echo "error: missing Orca worktree id; cannot resolve worktree path" >&2; return 1; }
190
+ fm_backend_orca_tool_check || return 1
191
+ out=$(orca worktree show --worktree "id:$worktree_id" --json) || return 1
192
+ path=$(printf '%s' "$out" | fm_backend_orca_json_get worktree-path) || {
193
+ echo "error: orca worktree show did not return a path for $worktree_id" >&2
194
+ return 1
195
+ }
196
+ printf '%s' "$path"
197
+ }
198
+
199
+ fm_backend_orca_capture() { # <terminal-id> <lines>
200
+ local terminal=$1 lines=${2:-40} out
201
+ fm_backend_orca_tool_check || return 1
202
+ out=$(orca terminal read --terminal "$terminal" --limit "$lines" --json) || return 1
203
+ fm_backend_orca_json_text "$out"
204
+ }
205
+
206
+ fm_backend_orca_json_text() { # <json>
207
+ printf '%s' "$1" | node -e '
208
+ const fs = require("fs");
209
+ const data = JSON.parse(fs.readFileSync(0, "utf8"));
210
+ if (data.ok === false) {
211
+ const msg = data.error && (data.error.message || data.error.code);
212
+ if (msg) console.error(msg);
213
+ process.exit(2);
214
+ }
215
+ const r = data.result || {};
216
+ if (r.terminal && Array.isArray(r.terminal.tail)) {
217
+ process.stdout.write(r.terminal.tail.join("\n"));
218
+ } else if (Array.isArray(r.tail)) {
219
+ process.stdout.write(r.tail.join("\n"));
220
+ } else {
221
+ process.stdout.write(r.text || r.output || r.content || r.preview || "");
222
+ }
223
+ '
224
+ }
225
+
226
+ # fm_backend_orca_composer_capture: the orca composer screen - one bounded
227
+ # tail read of the live terminal. Deliberately NOT the old 200-line
228
+ # backward-paged read: the composer is bottom-anchored, and paging back into
229
+ # scrollback is what let a stale startup banner (codex's bordered
230
+ # "permissions" box) compete with - and once outrank - the live composer.
231
+ fm_backend_orca_composer_capture() { # <terminal-id> [expected-label]
232
+ fm_backend_orca_capture "$1" "$FM_COMPOSER_CAPTURE_LINES"
233
+ }
234
+
235
+ # fm_backend_orca_composer_caps: static capability facts, not logic (see the
236
+ # capability model in bin/fm-composer-lib.sh). Orca's `terminal read` returns
237
+ # plain text; whether it can emit ANSI is unverified (orca is not installed
238
+ # on the verification machine), so styled stays 0 - the conservative
239
+ # degradation - until a live capture proves otherwise.
240
+ fm_backend_orca_composer_caps() {
241
+ printf 'styled=0\ncursor=0\nidentity=0\nrows=%s\n' "$FM_COMPOSER_CAPTURE_LINES"
242
+ }
243
+
244
+ # fm_backend_orca_composer_state: thin adapter - capture plus capabilities in,
245
+ # shared verdict out. Every shape (bordered boxes AND the borderless bare-glyph
246
+ # row this adapter never learned, which left every claude/codex/pi/muse steer
247
+ # unconfirmed) lives in bin/fm-composer-lib.sh.
248
+ fm_backend_orca_composer_state() { # <terminal-id> [expected-label] -> empty|pending|pending-unproven|unknown
249
+ local cap verdict
250
+ cap=$(fm_backend_orca_composer_capture "$1") || { printf 'unknown'; return 0; }
251
+ verdict=$(fm_composer_classify_screen "$(fm_backend_orca_composer_caps)" "$cap")
252
+ [ "$verdict" != need-identity ] || verdict=unknown
253
+ printf '%s' "$verdict"
254
+ }
255
+
256
+ fm_backend_orca_send_key() { # <terminal-id> <key>
257
+ local terminal=$1 key=$2
258
+ fm_backend_orca_tool_check || return 1
259
+ case "$key" in
260
+ C-c|ctrl+c|Ctrl-c|Ctrl-C)
261
+ fm_backend_orca_run_json orca terminal send --terminal "$terminal" --interrupt --json
262
+ ;;
263
+ Enter|enter)
264
+ fm_backend_orca_run_json orca terminal send --terminal "$terminal" --text "" --enter --json
265
+ ;;
266
+ *)
267
+ echo "error: unsupported Orca key '$key'" >&2
268
+ return 1
269
+ ;;
270
+ esac
271
+ }
272
+
273
+ # fm_backend_orca_send_text_submit: type <text> once, then drive the shared
274
+ # verify-and-retry-Enter loop (bin/fm-composer-lib.sh:
275
+ # fm_composer_submit_retry_core) against the shared composer verdict, so a
276
+ # slash-command popup placeholder fill gets the required second Enter without
277
+ # duplicating text.
278
+ fm_backend_orca_send_text_submit() { # <terminal-id> <text> <retries> <enter-sleep> <settle>
279
+ local terminal=$1 text=$2 retries=$3 sleep_s=$4 settle=$5
280
+ fm_backend_orca_tool_check || { printf 'send-failed'; return 0; }
281
+ fm_backend_orca_send_literal "$terminal" "$text" || { printf 'send-failed'; return 0; }
282
+ sleep "$settle"
283
+ fm_composer_submit_retry_core fm_backend_orca_send_key fm_backend_orca_composer_state \
284
+ "$terminal" "$retries" "$sleep_s"
285
+ }
286
+
287
+ fm_backend_orca_kill() { # <terminal-id>
288
+ fm_backend_orca_tool_check || return 0
289
+ orca terminal close --terminal "$1" --json >/dev/null 2>&1 || true
290
+ }
@@ -0,0 +1,357 @@
1
+ #!/usr/bin/env bash
2
+ # bin/backends/tmux.sh - the tmux session-provider adapter.
3
+ #
4
+ # Reference backend (AGENTS.md section 8; data/fm-backend-design-d7). P1 moves
5
+ # the tmux command sequences that fm-send.sh, fm-peek.sh, fm-watch.sh,
6
+ # fm-spawn.sh, and fm-teardown.sh already ran inline into named functions
7
+ # here, running the EXACT same commands in the EXACT same order, so the
8
+ # default (tmux, `backend=` absent) path stays byte-identical. Sourced only
9
+ # through bin/fm-backend.sh's fm_backend_source, never directly.
10
+ #
11
+ # Worktree acquisition (running `treehouse get` inside the pane, and polling
12
+ # its cwd) is unchanged by this extraction: P1 scopes only the session
13
+ # provider, not the worktree provider, so fm-spawn.sh still drives that part
14
+ # inline with these same send/current-path primitives.
15
+ #
16
+ # The verified composer/busy-detection and verify-and-retry-submit primitives
17
+ # already live in bin/fm-tmux-lib.sh, shared with the away-mode daemon
18
+ # (bin/fm-supervise-daemon.sh); this adapter sources that file and re-exports
19
+ # its submit core under the backend's naming convention rather than
20
+ # duplicating it, so the two consumers cannot drift apart.
21
+ # shellcheck source=bin/fm-tmux-lib.sh
22
+ . "$FM_BACKEND_LIB_DIR/fm-tmux-lib.sh"
23
+ # shellcheck source=bin/fm-session-lock-lib.sh
24
+ . "$FM_BACKEND_LIB_DIR/fm-session-lock-lib.sh"
25
+ # shellcheck source=bin/fm-cursor-lib.sh
26
+ . "$FM_BACKEND_LIB_DIR/fm-cursor-lib.sh"
27
+
28
+ # fm_backend_tmux_resolve_bare_selector: the live-window-listing fallback for a
29
+ # selector that is neither an explicit target nor a task selector routed
30
+ # through meta - an ad hoc window name with no recorded task. Mirrors the
31
+ # `tmux list-windows -a ... | grep` pipeline that used to live inline in
32
+ # fm-send.sh's and fm-peek.sh's own (until now duplicated) resolve().
33
+ fm_backend_tmux_resolve_bare_selector() { # <name>
34
+ local name=$1
35
+ tmux list-windows -a -F '#{session_name}:#{window_name}' | grep -m1 ":$name\$" \
36
+ || { echo "error: no window named $name" >&2; return 1; }
37
+ }
38
+
39
+ # fm_backend_tmux_capture: bounded plain-text pane capture. Mirrors
40
+ # fm-peek.sh's and fm-watch.sh's `tmux capture-pane -p -t "$T" -S -"$N"`.
41
+ fm_backend_tmux_capture() { # <target> <lines>
42
+ tmux capture-pane -p -t "$1" -S -"$2"
43
+ }
44
+
45
+ # fm_backend_tmux_send_key: one named key. Mirrors fm-send.sh's --key path:
46
+ # `tmux display-message -p -t "$T" '#{pane_id}' >/dev/null`, then
47
+ # `tmux send-keys -t "$T" "$2"`.
48
+ fm_backend_tmux_send_key() { # <target> <key>
49
+ tmux display-message -p -t "$1" '#{pane_id}' >/dev/null
50
+ tmux send-keys -t "$1" "$2"
51
+ }
52
+
53
+ # fm_backend_tmux_send_text_submit: type <text> into <target> once, then
54
+ # submit with Enter, retried (Enter only, never retyped) until the composer
55
+ # clears. Re-exports fm_tmux_submit_core (bin/fm-tmux-lib.sh) verbatim; see
56
+ # that file for the composer-verification contract and echoed verdicts.
57
+ fm_backend_tmux_send_text_submit() { # <target> <text> <retries> <enter-sleep> <settle>
58
+ fm_tmux_submit_core "$@"
59
+ }
60
+
61
+ # fm_backend_tmux_container_ensure: reuse the current tmux session when
62
+ # firstmate itself runs inside tmux, else ensure a dedicated detached
63
+ # "firstmate" session exists. Mirrors fm-spawn.sh's container-ensure block;
64
+ # prints the resolved session name.
65
+ fm_backend_tmux_container_ensure() {
66
+ if [ -n "${TMUX:-}" ]; then
67
+ tmux display-message -p '#S'
68
+ else
69
+ tmux has-session -t firstmate 2>/dev/null || tmux new-session -d -s firstmate
70
+ printf 'firstmate'
71
+ fi
72
+ }
73
+
74
+ # fm_backend_tmux_create_task: create the task's window in <proj-abs>,
75
+ # refusing an existing <window-name> in <session>. Mirrors fm-spawn.sh's
76
+ # duplicate-check-then-new-window sequence, including the exact error text
77
+ # (session:window, matching how fm-spawn.sh composed its own $T). Prints the
78
+ # created window's stable window id on stdout for the caller to target.
79
+ #
80
+ # Robustness (fm-spawn tmux window handling under a non-default captain config):
81
+ # - Capture a STABLE window id with -P -F '#{window_id}', and let tmux append
82
+ # at the next free index by targeting the session with a trailing colon
83
+ # ("$ses:"), so a non-default base-index (e.g. base-index 1) cannot collide.
84
+ # - PIN the window name by disabling automatic-rename and allow-rename on the
85
+ # new window: the captain's tmux may rename the window away from fm-<id> once
86
+ # treehouse cd's into the worktree, which would break name-based targeting.
87
+ # The returned window id lets callers target the window even if its name is ever
88
+ # lost, so worktree discovery cannot fall back to the active client's window.
89
+ fm_backend_tmux_create_task() { # <session> <window-name> <proj-abs> -> prints window id
90
+ local ses=$1 wname=$2 proj_abs=$3 wid
91
+ if tmux list-windows -t "$ses" -F '#{window_name}' | grep -qx "$wname"; then
92
+ echo "error: window $ses:$wname already exists" >&2
93
+ return 1
94
+ fi
95
+ wid=$(tmux new-window -dP -F '#{window_id}' -t "$ses:" -n "$wname" -c "$proj_abs") || return 1
96
+ tmux set-window-option -t "$wid" automatic-rename off 2>/dev/null || true
97
+ tmux set-window-option -t "$wid" allow-rename off 2>/dev/null || true
98
+ printf '%s\n' "$wid"
99
+ }
100
+
101
+ # fm_backend_tmux_current_path: the live pane's current working directory, or
102
+ # empty on any tmux error. Mirrors fm-spawn.sh's worktree-discovery poll:
103
+ # `tmux display-message -p -t "$T" '#{pane_current_path}'`.
104
+ fm_backend_tmux_current_path() { # <target>
105
+ tmux display-message -p -t "$1" '#{pane_current_path}' 2>/dev/null
106
+ }
107
+
108
+ # fm_backend_tmux_send_text_line: send one line of TEXT then Enter, with no
109
+ # composer verification - used for the fixed spawn-time commands
110
+ # (`treehouse get`, the GOTMPDIR export) that already ran this exact sequence
111
+ # inline in fm-spawn.sh. Mirrors `tmux send-keys -t "$T" "<text>" Enter`.
112
+ fm_backend_tmux_send_text_line() { # <target> <text>
113
+ tmux send-keys -t "$1" "$2" Enter
114
+ }
115
+
116
+ # fm_backend_tmux_send_literal: send TEXT as literal bytes with no
117
+ # submission - the caller sends Enter separately (fm-spawn.sh's launch-command
118
+ # send pauses between the literal send and Enter for the harness to settle).
119
+ # Mirrors `tmux send-keys -t "$T" -l "<text>"`.
120
+ fm_backend_tmux_send_literal() { # <target> <text>
121
+ tmux send-keys -t "$1" -l "$2"
122
+ }
123
+
124
+ # fm_backend_tmux_kill: remove one explicitly named task window, best-effort.
125
+ # Empty, omitted, and malformed targets return nonzero before invoking tmux so
126
+ # tmux can never interpret an empty target as the caller's current window.
127
+ fm_backend_tmux_kill() { # <target>
128
+ local target=${1:-} session window
129
+ case "$target" in
130
+ *:*)
131
+ session=${target%%:*}
132
+ window=${target#*:}
133
+ ;;
134
+ *) return 1 ;;
135
+ esac
136
+ case "$session:$window" in
137
+ :*|*:|*:*:*) return 1 ;;
138
+ esac
139
+ tmux kill-window -t "=$session:=$window" 2>/dev/null || true
140
+ }
141
+
142
+ # fm_backend_tmux_current_command: <target>'s live foreground process name -
143
+ # tmux's own `#{pane_current_command}`, already resolved from the pty's
144
+ # foreground process group (verified empirically with real tmux 3.6a: a
145
+ # harness invoked interactively stays the reported command even while it
146
+ # shells out to subcommands that do not take over the pty - e.g. `bash -c
147
+ # "sleep 30"` alone reports "sleep" because bash execs directly into it, but
148
+ # a persisting parent script running `sleep` as a child reports the PARENT's
149
+ # own name throughout; the value reverts to the shell's own name only once
150
+ # the foreground command actually exits). Empty on any tmux error.
151
+ fm_backend_tmux_current_command() { # <target>
152
+ tmux display-message -p -t "$1" '#{pane_current_command}' 2>/dev/null
153
+ }
154
+
155
+ # fm_backend_tmux_classify_process_name: the single owner of the process-name
156
+ # vocabulary shared by every liveness signal below - `agent` for a verified
157
+ # harness, `shell` for an idle login/interactive shell, `other` for anything
158
+ # else. Keeping one classifier means the two independent name sources can never
159
+ # drift into disagreeing about what a given name means.
160
+ fm_backend_tmux_classify_process_name() { # <path> [argv0] -> agent|shell|other
161
+ local path=$1 argv0=${2:-} base
162
+ base=${path##*/}
163
+ base=${base#-}
164
+ case "$base" in
165
+ # muse is anchored rather than globbed like its neighbours: its installed
166
+ # binary is muse-bin-<version> (the launcher execs it, so the version is the
167
+ # live process name and changes on every auto-update), and unlike `claude` or
168
+ # `codex` the substring `muse` is a common English fragment - a *muse* glob
169
+ # would classify musescore or amuse as a live agent pane. The install path
170
+ # cannot carry it either: ~/.local/bin/muse-bin-<version> has no `muse` path
171
+ # COMPONENT, so the fm_harness_path_name fallback below never fires for it.
172
+ muse|muse-bin-*) printf 'agent' ;;
173
+ *claude*|*codex*|*opencode*|*grok*|*kimi*|pi|pi-signed|pi-launcher|Pi) printf 'agent' ;;
174
+ zsh|bash|sh|dash|ash|ksh|mksh|tcsh|csh|fish) printf 'shell' ;;
175
+ *)
176
+ if fm_harness_path_name "$path" >/dev/null || fm_harness_path_name "$argv0" >/dev/null; then
177
+ printf 'agent'
178
+ # cursor-agent runs as a bundled node script, so tmux reports the pane
179
+ # command as a bare `node` that no name pattern above can own, and its
180
+ # other installed name is the far-too-generic `agent` (verified live on
181
+ # cursor-agent 2026.08.11-e8db854: #{pane_current_command} is `node` while
182
+ # `ps -o comm=` carries the cursor-agent install path). Identity therefore
183
+ # comes from the narrowed structural rule in bin/fm-cursor-lib.sh, which
184
+ # demands Cursor's own name or install tree in the path or argv[0]. An
185
+ # unrelated `node` or `agent` matches nothing here and stays `other`,
186
+ # which the callers above fold into `ambiguous` rather than `dead`, so a
187
+ # stranger's node pane is never reported as an agent-free pane.
188
+ elif fm_cursor_process_matches "${path:-$argv0}" '' "$argv0"; then
189
+ printf 'agent'
190
+ else
191
+ printf 'other'
192
+ fi
193
+ ;;
194
+ esac
195
+ }
196
+
197
+ # fm_backend_tmux_foreground_comms: the kernel-side names of every process in
198
+ # <target>'s pane tty foreground process group, one full value per line.
199
+ # Empty on any failure.
200
+ #
201
+ # This is the foreground-process-group half of the liveness probe, and it exists
202
+ # because `#{pane_current_command}` and `ps -o comm=` expose different name
203
+ # fields whose roles vary by platform. On macOS the tmux field can carry a
204
+ # harness-rewritten title (Claude Code 2.1.220 reports `2.1.220`) while `comm`
205
+ # retains executable identity; the portable Linux regression observes the
206
+ # reverse for its version-named executable. Reading both `comm` and argv[0]
207
+ # preserves an identifying install path without making either platform's field
208
+ # assignment load-bearing.
209
+ #
210
+ # Scoping to the foreground process group rather than to the pane's descendants
211
+ # is what keeps the probe honest in the other direction: a harness-named process
212
+ # left running in the background of an otherwise idle pane is deliberately NOT
213
+ # reported, so a genuinely agent-free pane still classifies `dead`. It also
214
+ # reports every member of a multi-process launcher (the Pi Launcher path runs a
215
+ # `pi-signed` wrapper and a `pi` engine in one group), so no launcher needs its
216
+ # own special case here.
217
+ #
218
+ # Like fm_backend_tmux_current_command this is a RAW pane read: tmux answers an
219
+ # absent target from the client's active window rather than failing, so callers
220
+ # must confirm exact window membership first, exactly as the classifier below
221
+ # does, or they will describe some other pane entirely.
222
+ fm_backend_tmux_foreground_comms() { # <target>
223
+ local target=$1 tty pid pgid tpgid comm
224
+ tty=$(tmux display-message -p -t "$target" '#{pane_tty}' 2>/dev/null) || return 0
225
+ [ -n "$tty" ] || return 0
226
+ LC_ALL=C ps -t "${tty#/dev/}" -o pid=,pgid=,tpgid=,comm= 2>/dev/null \
227
+ | while read -r pid pgid tpgid comm; do
228
+ [ -n "$comm" ] || continue
229
+ [ "$pgid" = "$tpgid" ] || continue
230
+ printf '%s\n' "$comm"
231
+ done
232
+ }
233
+
234
+ fm_backend_tmux_foreground_argv0s() { # <target>
235
+ local target=$1 tty pid pgid tpgid comm args argv0
236
+ tty=$(tmux display-message -p -t "$target" '#{pane_tty}' 2>/dev/null) || return 0
237
+ [ -n "$tty" ] || return 0
238
+ LC_ALL=C ps -t "${tty#/dev/}" -o pid=,pgid=,tpgid=,comm= 2>/dev/null \
239
+ | while read -r pid pgid tpgid comm; do
240
+ [ -n "$comm" ] || continue
241
+ [ "$pgid" = "$tpgid" ] || continue
242
+ args=$(LC_ALL=C ps -p "$pid" -o args= 2>/dev/null) || continue
243
+ args=${args#"${args%%[![:space:]]*}"}
244
+ argv0=${args%%[[:space:]]*}
245
+ [ -n "$argv0" ] && printf '%s\n' "$argv0"
246
+ done
247
+ }
248
+
249
+ # fm_backend_tmux_agent_state: recovery-grade harness-agent state for one
250
+ # recorded target. See bin/fm-backend.sh's fm_backend_agent_state for the
251
+ # shared state vocabulary and docs/tmux-backend.md "Agent liveness probe" for
252
+ # the empirical basis. Tmux silently falls back to the active window when a
253
+ # named target is absent, so the exact recorded window must appear in a
254
+ # successful session inventory before its foreground command can be trusted.
255
+ # An omitted window or a definitive missing-session/server response is
256
+ # `missing`; any other inventory or pane read failure is `unreadable`, so a
257
+ # transient tmux problem never licenses a duplicate.
258
+ #
259
+ # The verdict combines two independent name sources rather than trusting either
260
+ # alone. Either source naming a verified harness is enough for `alive`, because
261
+ # a false `dead` is the one outcome that can launch a duplicate agent onto a
262
+ # live worktree, while the foreground process group - when it is readable - is
263
+ # authoritative for the negative verdicts, since it is the only source that can
264
+ # distinguish a truly idle pane from a rewritten process title.
265
+ fm_backend_tmux_agent_state() { # <target>
266
+ local target=$1 comm session window windows inventory_status
267
+ local foreground argv0s name fg_seen=0 fg_shell=0 fg_other=0
268
+ case "$target" in
269
+ *:*:*|'':*|*:'') printf 'unreadable'; return 0 ;;
270
+ *:*) ;;
271
+ *) printf 'unreadable'; return 0 ;;
272
+ esac
273
+ session=${target%%:*}
274
+ window=${target#*:}
275
+ if windows=$(LC_ALL=C tmux list-windows -t "$session" -F '#{window_name}' 2>&1); then
276
+ inventory_status=0
277
+ else
278
+ inventory_status=$?
279
+ fi
280
+ if [ "$inventory_status" -ne 0 ]; then
281
+ case "$windows" in
282
+ *"can't find session:"*|*"no server running on "*|*"error connecting to "*" (No such file or directory)"|*"error connecting to "*" (Connection refused)")
283
+ printf 'missing'
284
+ ;;
285
+ *)
286
+ printf 'unreadable'
287
+ ;;
288
+ esac
289
+ return 0
290
+ fi
291
+ if ! printf '%s\n' "$windows" | grep -Fqx "$window"; then
292
+ printf 'missing'
293
+ return 0
294
+ fi
295
+
296
+ foreground=$(fm_backend_tmux_foreground_comms "$target")
297
+ while IFS= read -r name; do
298
+ [ -n "$name" ] || continue
299
+ fg_seen=1
300
+ case "$(fm_backend_tmux_classify_process_name "$name")" in
301
+ agent) printf 'alive'; return 0 ;;
302
+ shell) fg_shell=1 ;;
303
+ *) fg_other=1 ;;
304
+ esac
305
+ done <<EOF
306
+ $foreground
307
+ EOF
308
+
309
+ argv0s=$(fm_backend_tmux_foreground_argv0s "$target")
310
+ while IFS= read -r name; do
311
+ [ -n "$name" ] || continue
312
+ if [ "$(fm_backend_tmux_classify_process_name '' "$name")" = agent ]; then
313
+ printf 'alive'
314
+ return 0
315
+ fi
316
+ done <<EOF
317
+ $argv0s
318
+ EOF
319
+
320
+ comm=$(fm_backend_tmux_current_command "$target") || {
321
+ printf 'unreadable'
322
+ return 0
323
+ }
324
+ if [ "$(fm_backend_tmux_classify_process_name "$comm")" = agent ]; then
325
+ printf 'alive'
326
+ return 0
327
+ fi
328
+
329
+ # A readable foreground process group settles the negative verdicts: only a
330
+ # group that is nothing but shells is confidently agent-free.
331
+ if [ "$fg_seen" -eq 1 ]; then
332
+ if [ "$fg_other" -eq 0 ] && [ "$fg_shell" -eq 1 ]; then
333
+ printf 'dead'
334
+ else
335
+ printf 'ambiguous'
336
+ fi
337
+ return 0
338
+ fi
339
+
340
+ case "$comm" in
341
+ '') printf 'unreadable'; return 0 ;;
342
+ esac
343
+ case "$(fm_backend_tmux_classify_process_name "$comm")" in
344
+ shell) printf 'dead' ;;
345
+ *) printf 'ambiguous' ;;
346
+ esac
347
+ }
348
+
349
+ # Backward-compatible three-state view for callers that only need a yes/no
350
+ # agent verdict. The detailed state contract is owned by fm_backend_agent_state.
351
+ fm_backend_tmux_agent_alive() { # <target>
352
+ case "$(fm_backend_tmux_agent_state "$1")" in
353
+ alive) printf 'alive' ;;
354
+ dead|missing) printf 'dead' ;;
355
+ *) printf 'unknown' ;;
356
+ esac
357
+ }