@zerwiz/ymir 0.1.4 → 0.1.7

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 (865) 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/README.md +74 -0
  27. package/.agents/backend/backends/cmux.sh +649 -0
  28. package/.agents/backend/backends/herdr-eventwait.py +157 -0
  29. package/.agents/backend/backends/herdr-workspace-move.py +114 -0
  30. package/.agents/backend/backends/herdr.sh +3386 -0
  31. package/.agents/backend/backends/orca.sh +290 -0
  32. package/.agents/backend/backends/tmux.sh +357 -0
  33. package/.agents/backend/backends/zellij.sh +700 -0
  34. package/.agents/backend/fm-afk-launch.sh +654 -0
  35. package/.agents/backend/fm-afk-return.sh +241 -0
  36. package/.agents/backend/fm-afk-start.sh +172 -0
  37. package/.agents/backend/fm-arm-command-policy.mjs +960 -0
  38. package/.agents/backend/fm-arm-pretool-check.sh +200 -0
  39. package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
  40. package/.agents/backend/fm-backend.sh +981 -0
  41. package/.agents/backend/fm-backlog-handoff.sh +909 -0
  42. package/.agents/backend/fm-backlog-receive.sh +187 -0
  43. package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
  44. package/.agents/backend/fm-bearings-board.sh +204 -0
  45. package/.agents/backend/fm-bearings-snapshot.sh +546 -0
  46. package/.agents/backend/fm-bootstrap.sh +1568 -0
  47. package/.agents/backend/fm-branch-outcome.sh +203 -0
  48. package/.agents/backend/fm-branch-prompt.sh +101 -0
  49. package/.agents/backend/fm-brief.sh +452 -0
  50. package/.agents/backend/fm-busy-event.sh +234 -0
  51. package/.agents/backend/fm-busy-lib.sh +986 -0
  52. package/.agents/backend/fm-captain-hold.sh +1001 -0
  53. package/.agents/backend/fm-cd-command-policy.mjs +153 -0
  54. package/.agents/backend/fm-cd-pretool-check.sh +190 -0
  55. package/.agents/backend/fm-check-lib.sh +74 -0
  56. package/.agents/backend/fm-check-register.sh +42 -0
  57. package/.agents/backend/fm-check-unregister.sh +52 -0
  58. package/.agents/backend/fm-classify-lib.sh +1770 -0
  59. package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
  60. package/.agents/backend/fm-composer-lib.sh +1416 -0
  61. package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
  62. package/.agents/backend/fm-config-push.sh +254 -0
  63. package/.agents/backend/fm-control-lib.sh +251 -0
  64. package/.agents/backend/fm-control.sh +878 -0
  65. package/.agents/backend/fm-crew-state.sh +625 -0
  66. package/.agents/backend/fm-cursor-lib.sh +243 -0
  67. package/.agents/backend/fm-decision-hold.sh +232 -0
  68. package/.agents/backend/fm-doc-audience-check.sh +269 -0
  69. package/.agents/backend/fm-dod-lib.sh +67 -0
  70. package/.agents/backend/fm-ensure-agents-md.sh +253 -0
  71. package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
  72. package/.agents/backend/fm-extension.mjs +2577 -0
  73. package/.agents/backend/fm-extension.sh +16 -0
  74. package/.agents/backend/fm-ff-lib.sh +420 -0
  75. package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
  76. package/.agents/backend/fm-fleet-sync.sh +458 -0
  77. package/.agents/backend/fm-fleet-view.sh +96 -0
  78. package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
  79. package/.agents/backend/fm-guard.sh +242 -0
  80. package/.agents/backend/fm-harness.sh +195 -0
  81. package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
  82. package/.agents/backend/fm-herdr-lab.sh +346 -0
  83. package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
  84. package/.agents/backend/fm-home-seed.sh +984 -0
  85. package/.agents/backend/fm-home-summary-refresh.sh +255 -0
  86. package/.agents/backend/fm-hook-host-lib.sh +36 -0
  87. package/.agents/backend/fm-inactive-reconcile.sh +531 -0
  88. package/.agents/backend/fm-inbox.sh +399 -0
  89. package/.agents/backend/fm-install-actionlint.sh +84 -0
  90. package/.agents/backend/fm-install-herdr.sh +96 -0
  91. package/.agents/backend/fm-install-shellcheck.sh +84 -0
  92. package/.agents/backend/fm-install-treehouse.sh +95 -0
  93. package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
  94. package/.agents/backend/fm-lease-lib.sh +218 -0
  95. package/.agents/backend/fm-lease.sh +189 -0
  96. package/.agents/backend/fm-line-cap-lib.sh +51 -0
  97. package/.agents/backend/fm-lint-workflows.sh +137 -0
  98. package/.agents/backend/fm-lint.sh +591 -0
  99. package/.agents/backend/fm-lock-lib.sh +104 -0
  100. package/.agents/backend/fm-lock.sh +107 -0
  101. package/.agents/backend/fm-marker-lib.sh +12 -0
  102. package/.agents/backend/fm-merge-local.sh +74 -0
  103. package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
  104. package/.agents/backend/fm-nm-run-lib.sh +124 -0
  105. package/.agents/backend/fm-on.sh +125 -0
  106. package/.agents/backend/fm-operational-input.sh +253 -0
  107. package/.agents/backend/fm-peek.sh +46 -0
  108. package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
  109. package/.agents/backend/fm-pr-check.sh +135 -0
  110. package/.agents/backend/fm-pr-lib.sh +1016 -0
  111. package/.agents/backend/fm-pr-merge.sh +707 -0
  112. package/.agents/backend/fm-pr-poll.sh +110 -0
  113. package/.agents/backend/fm-primary-scope-lib.sh +33 -0
  114. package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
  115. package/.agents/backend/fm-procevent-lavish.sh +628 -0
  116. package/.agents/backend/fm-procevent-lib.sh +892 -0
  117. package/.agents/backend/fm-procevent-quota.sh +290 -0
  118. package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
  119. package/.agents/backend/fm-procevent-when.sh +504 -0
  120. package/.agents/backend/fm-procevent.sh +1466 -0
  121. package/.agents/backend/fm-project-mode.sh +92 -0
  122. package/.agents/backend/fm-project-origin-lib.sh +180 -0
  123. package/.agents/backend/fm-promote.sh +282 -0
  124. package/.agents/backend/fm-public-followup-emit.sh +260 -0
  125. package/.agents/backend/fm-public-followup-lib.sh +398 -0
  126. package/.agents/backend/fm-public-followup.sh +1330 -0
  127. package/.agents/backend/fm-push-transition-lib.sh +168 -0
  128. package/.agents/backend/fm-quota-axi-lib.sh +93 -0
  129. package/.agents/backend/fm-quota-choose.sh +384 -0
  130. package/.agents/backend/fm-remote-delta-read.sh +189 -0
  131. package/.agents/backend/fm-remote-doctor.sh +800 -0
  132. package/.agents/backend/fm-remote-entrypoint.sh +193 -0
  133. package/.agents/backend/fm-remote-file.sh +234 -0
  134. package/.agents/backend/fm-remote-home-provision.sh +259 -0
  135. package/.agents/backend/fm-remote-home-seed.sh +259 -0
  136. package/.agents/backend/fm-remote-inherit-push.sh +90 -0
  137. package/.agents/backend/fm-remote-inherit.sh +179 -0
  138. package/.agents/backend/fm-remote-job-lib.sh +1241 -0
  139. package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
  140. package/.agents/backend/fm-remote-job-worker.sh +1124 -0
  141. package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
  142. package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
  143. package/.agents/backend/fm-review-diff.sh +158 -0
  144. package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
  145. package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
  146. package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
  147. package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
  148. package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
  149. package/.agents/backend/fm-secondmate-report.sh +88 -0
  150. package/.agents/backend/fm-send.sh +1059 -0
  151. package/.agents/backend/fm-session-lock-lib.sh +176 -0
  152. package/.agents/backend/fm-session-start.sh +970 -0
  153. package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
  154. package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
  155. package/.agents/backend/fm-sessionstart-run.sh +145 -0
  156. package/.agents/backend/fm-spawn.sh +3153 -0
  157. package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
  158. package/.agents/backend/fm-startup-memory-budget.sh +94 -0
  159. package/.agents/backend/fm-startup-network.sh +642 -0
  160. package/.agents/backend/fm-stow-cascade.sh +251 -0
  161. package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
  162. package/.agents/backend/fm-supervise-daemon.sh +1732 -0
  163. package/.agents/backend/fm-supervision-instructions.sh +215 -0
  164. package/.agents/backend/fm-supervision-lib.sh +90 -0
  165. package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
  166. package/.agents/backend/fm-tangle-lib.sh +53 -0
  167. package/.agents/backend/fm-task-inbox-lib.sh +402 -0
  168. package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
  169. package/.agents/backend/fm-teardown.sh +2922 -0
  170. package/.agents/backend/fm-test-isolation-proof.sh +588 -0
  171. package/.agents/backend/fm-test-run.sh +2191 -0
  172. package/.agents/backend/fm-timeout-lib.sh +141 -0
  173. package/.agents/backend/fm-timing-lib.sh +179 -0
  174. package/.agents/backend/fm-tmux-lib.sh +291 -0
  175. package/.agents/backend/fm-tool-update-check.sh +898 -0
  176. package/.agents/backend/fm-trace-context-lib.sh +227 -0
  177. package/.agents/backend/fm-transition-lib.sh +103 -0
  178. package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
  179. package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
  180. package/.agents/backend/fm-turnend-guard.sh +432 -0
  181. package/.agents/backend/fm-update.sh +110 -0
  182. package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
  183. package/.agents/backend/fm-voice-client.py +1373 -0
  184. package/.agents/backend/fm-voice-relay.py +1256 -0
  185. package/.agents/backend/fm-wake-drain.sh +592 -0
  186. package/.agents/backend/fm-wake-grant.sh +127 -0
  187. package/.agents/backend/fm-wake-lib.sh +1849 -0
  188. package/.agents/backend/fm-watch-arm.sh +602 -0
  189. package/.agents/backend/fm-watch-checkpoint.sh +109 -0
  190. package/.agents/backend/fm-watch.sh +1962 -0
  191. package/.agents/backend/fm-x-dismiss.sh +116 -0
  192. package/.agents/backend/fm-x-followup.sh +286 -0
  193. package/.agents/backend/fm-x-lib.sh +1000 -0
  194. package/.agents/backend/fm-x-link.sh +234 -0
  195. package/.agents/backend/fm-x-poll.sh +185 -0
  196. package/.agents/backend/fm-x-reply.sh +385 -0
  197. package/.agents/backend/fm_voice_frame.py +166 -0
  198. package/.agents/backend/fm_voice_records.py +574 -0
  199. package/.agents/backend/model-bridge.py +360 -0
  200. package/.agents/backend/opencode-go-bridge.py +30 -0
  201. package/.agents/bus/README.md +12 -0
  202. package/.agents/bus/messages.json +1 -0
  203. package/.agents/config/agents.machine.example.yaml +16 -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 +11 -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/filebrowser/.filebrowser.json +6 -0
  211. package/.agents/filebrowser/README.md +11 -0
  212. package/.agents/gateway/README.md +12 -0
  213. package/.agents/github/README.md +15 -0
  214. package/.agents/github/webhooks/.gitkeep +0 -0
  215. package/.agents/github/workflows/.gitkeep +0 -0
  216. package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
  217. package/.agents/harness/opencode/plugins/package.json +4 -0
  218. package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
  219. package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
  220. package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
  221. package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
  222. package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
  223. package/.agents/memory/README.md +46 -0
  224. package/.agents/memory/runes_audit.md +5 -0
  225. package/.agents/migrations/0001-hodd-layout.sh +38 -0
  226. package/.agents/migrations/0002-a2a-mcp.sh +27 -0
  227. package/.agents/migrations/0003-private-data-separation.sh +121 -0
  228. package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
  229. package/.agents/migrations/0005-roots-out-of-tree.sh +158 -0
  230. package/.agents/sandbox/Dockerfile.utgard +19 -0
  231. package/.agents/sandbox/README.md +14 -0
  232. package/.agents/sandbox/utgard.config.json +14 -0
  233. package/.agents/skills/README.md +59 -0
  234. package/.agents/skills/bragi-marketing/README.md +3 -0
  235. package/.agents/skills/bragi-marketing/SKILL.md +82 -0
  236. package/.agents/skills/eindri-homes/README.md +3 -0
  237. package/.agents/skills/eindri-homes/SKILL.md +291 -0
  238. package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
  239. package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
  240. package/.agents/skills/frigg-consent/README.md +3 -0
  241. package/.agents/skills/frigg-consent/SKILL.md +56 -0
  242. package/.agents/skills/galdr-ymirsystem/README.md +3 -0
  243. package/.agents/skills/galdr-ymirsystem/SKILL.md +159 -0
  244. package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
  245. package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
  246. package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
  247. package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
  248. package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
  249. package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
  250. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +736 -0
  251. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
  252. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
  253. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
  254. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
  255. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
  256. package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +539 -0
  257. package/.agents/skills/galdr-ymirsystem/assets/installation.md +763 -0
  258. package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
  259. package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
  260. package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +163 -0
  261. package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +415 -0
  262. package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
  263. package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +133 -0
  264. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
  265. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
  266. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +101 -0
  267. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
  268. package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
  269. package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
  270. package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
  271. package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
  272. package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
  273. package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
  274. package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
  275. package/.agents/skills/galdr-ymirsystem/assets/smidja.md +180 -0
  276. package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
  277. package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
  278. package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
  279. package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +503 -0
  280. package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
  281. package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
  282. package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
  283. package/.agents/skills/gjallarhorn-relay/README.md +3 -0
  284. package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
  285. package/.agents/skills/groa-update/SKILL.md +90 -0
  286. package/.agents/skills/hamr-adapters/README.md +3 -0
  287. package/.agents/skills/hamr-adapters/SKILL.md +123 -0
  288. package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
  289. package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
  290. package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
  291. package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
  292. package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
  293. package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
  294. package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
  295. package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
  296. package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
  297. package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
  298. package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
  299. package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
  300. package/.agents/skills/herdr-panes/README.md +3 -0
  301. package/.agents/skills/herdr-panes/SKILL.md +92 -0
  302. package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
  303. package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
  304. package/.agents/skills/hnoss-design/DESIGN.md +19 -0
  305. package/.agents/skills/hnoss-design/README.md +3 -0
  306. package/.agents/skills/hnoss-design/SKILL.md +83 -0
  307. package/.agents/skills/hvild-afk/README.md +3 -0
  308. package/.agents/skills/hvild-afk/SKILL.md +241 -0
  309. package/.agents/skills/jord-projects/README.md +3 -0
  310. package/.agents/skills/jord-projects/SKILL.md +92 -0
  311. package/.agents/skills/lifecycle/SKILL.md +56 -0
  312. package/.agents/skills/lifecycle/smoke_test.sh +57 -0
  313. package/.agents/skills/lifecycle/start.sh +21 -0
  314. package/.agents/skills/lifecycle/status.sh +35 -0
  315. package/.agents/skills/lifecycle/stop.sh +16 -0
  316. package/.agents/skills/muninn-stow/README.md +3 -0
  317. package/.agents/skills/muninn-stow/SKILL.md +309 -0
  318. package/.agents/skills/no-mistakes/SKILL.md +379 -0
  319. package/.agents/skills/nornir-schedule/README.md +3 -0
  320. package/.agents/skills/nornir-schedule/SKILL.md +25 -0
  321. package/.agents/skills/nornir-schedule/assets/events.md +137 -0
  322. package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
  323. package/.agents/skills/nsr-compliance/README.md +3 -0
  324. package/.agents/skills/nsr-compliance/SKILL.md +29 -0
  325. package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
  326. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
  327. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
  328. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
  329. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
  330. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
  331. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
  332. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
  333. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
  334. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
  335. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
  336. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
  337. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
  338. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
  339. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
  340. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
  341. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
  342. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
  343. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
  344. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
  345. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
  346. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
  347. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
  348. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
  349. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
  350. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
  351. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
  352. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
  353. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
  354. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
  355. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
  356. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
  357. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
  358. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
  359. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
  360. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
  361. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
  362. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
  363. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
  364. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
  365. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
  366. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
  367. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
  368. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
  369. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
  370. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
  371. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
  372. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
  373. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
  374. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
  375. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
  376. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
  377. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
  378. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
  379. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
  380. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
  381. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
  382. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
  383. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
  384. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
  385. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
  386. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
  387. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
  388. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
  389. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
  390. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
  391. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
  392. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
  393. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
  394. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
  395. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
  396. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
  397. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
  398. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
  399. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
  400. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
  401. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
  402. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
  403. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
  404. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
  405. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
  406. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
  407. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
  408. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
  409. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
  410. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
  411. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
  412. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
  413. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
  414. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
  415. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
  416. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
  417. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
  418. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
  419. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
  420. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
  421. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
  422. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
  423. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
  424. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
  425. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
  426. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
  427. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
  428. package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
  429. package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
  430. package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
  431. package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
  432. package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
  433. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
  434. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
  435. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
  436. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
  437. package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
  438. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
  439. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
  440. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
  441. package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
  442. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
  443. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
  444. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
  445. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
  446. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
  447. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
  448. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
  449. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
  450. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
  451. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
  452. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
  453. package/.agents/skills/pr-ops/README.md +3 -0
  454. package/.agents/skills/pr-ops/SKILL.md +109 -0
  455. package/.agents/skills/ratatoskr-a2a/README.md +3 -0
  456. package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
  457. package/.agents/skills/rules-check-drift/SKILL.md +81 -0
  458. package/.agents/skills/saga-bearings/README.md +3 -0
  459. package/.agents/skills/saga-bearings/SKILL.md +26 -0
  460. package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
  461. package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
  462. package/.agents/skills/saga-bearings/assets/recap.md +56 -0
  463. package/.agents/skills/syn-recovery/README.md +3 -0
  464. package/.agents/skills/syn-recovery/SKILL.md +54 -0
  465. package/.agents/skills/tyr-check/README.md +3 -0
  466. package/.agents/skills/tyr-check/SKILL.md +218 -0
  467. package/.agents/skills/urdh-hold/README.md +3 -0
  468. package/.agents/skills/urdh-hold/SKILL.md +25 -0
  469. package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
  470. package/.agents/skills/urdh-hold/assets/hold.md +54 -0
  471. package/.agents/skills/vor-diagnostics/README.md +3 -0
  472. package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
  473. package/.agents/skills/ymir-host/README.md +3 -0
  474. package/.agents/skills/ymir-host/SKILL.md +35 -0
  475. package/.agents/skills/ymir-host/assets/desktop.md +36 -0
  476. package/.agents/skills/ymir-host/assets/install.md +69 -0
  477. package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
  478. package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
  479. package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
  480. package/.agents/skills/ymir-host/assets/update.md +64 -0
  481. package/.agents/tests/assets/board-render-harness.mjs +117 -0
  482. package/.agents/tests/cmux-test-safety.sh +51 -0
  483. package/.agents/tests/fixtures.sh +291 -0
  484. package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
  485. package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
  486. package/.agents/tests/fm-afk-launch.test.sh +961 -0
  487. package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
  488. package/.agents/tests/fm-afk-return.test.sh +283 -0
  489. package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
  490. package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
  491. package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
  492. package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
  493. package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
  494. package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
  495. package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
  496. package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
  497. package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
  498. package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
  499. package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
  500. package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
  501. package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
  502. package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
  503. package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
  504. package/.agents/tests/fm-backend-orca.test.sh +1357 -0
  505. package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
  506. package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
  507. package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
  508. package/.agents/tests/fm-backend.test.sh +1142 -0
  509. package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
  510. package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
  511. package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
  512. package/.agents/tests/fm-bearings-board.test.sh +414 -0
  513. package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
  514. package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
  515. package/.agents/tests/fm-bootstrap.test.sh +1178 -0
  516. package/.agents/tests/fm-branch-supervision.test.sh +552 -0
  517. package/.agents/tests/fm-brief.test.sh +785 -0
  518. package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
  519. package/.agents/tests/fm-busy-state.test.sh +465 -0
  520. package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
  521. package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
  522. package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
  523. package/.agents/tests/fm-check-unregister.test.sh +198 -0
  524. package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
  525. package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
  526. package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
  527. package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
  528. package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
  529. package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
  530. package/.agents/tests/fm-composer-ghost.test.sh +716 -0
  531. package/.agents/tests/fm-composer-lib.test.sh +666 -0
  532. package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
  533. package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
  534. package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
  535. package/.agents/tests/fm-control.test.sh +910 -0
  536. package/.agents/tests/fm-crew-state.test.sh +1610 -0
  537. package/.agents/tests/fm-cursor-harness.test.sh +404 -0
  538. package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
  539. package/.agents/tests/fm-cursor-primary.test.sh +708 -0
  540. package/.agents/tests/fm-daemon.test.sh +2740 -0
  541. package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
  542. package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
  543. package/.agents/tests/fm-extension-binding.test.sh +2187 -0
  544. package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
  545. package/.agents/tests/fm-fleet-sync.test.sh +721 -0
  546. package/.agents/tests/fm-gate-refuse.test.sh +356 -0
  547. package/.agents/tests/fm-gitignore-config.test.sh +89 -0
  548. package/.agents/tests/fm-gotmp.test.sh +230 -0
  549. package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
  550. package/.agents/tests/fm-grok-harness.test.sh +117 -0
  551. package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
  552. package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
  553. package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
  554. package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
  555. package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
  556. package/.agents/tests/fm-herdr-lab.test.sh +243 -0
  557. package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
  558. package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
  559. package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
  560. package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
  561. package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
  562. package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
  563. package/.agents/tests/fm-kimi-harness.test.sh +687 -0
  564. package/.agents/tests/fm-lint-workflows.test.sh +532 -0
  565. package/.agents/tests/fm-lint.test.sh +1023 -0
  566. package/.agents/tests/fm-muse-harness.test.sh +932 -0
  567. package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
  568. package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
  569. package/.agents/tests/fm-on.test.sh +507 -0
  570. package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
  571. package/.agents/tests/fm-operational-input.test.sh +160 -0
  572. package/.agents/tests/fm-peek-remote.test.sh +110 -0
  573. package/.agents/tests/fm-pending-reply.test.sh +1288 -0
  574. package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
  575. package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
  576. package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
  577. package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
  578. package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
  579. package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
  580. package/.agents/tests/fm-pr-merge.test.sh +2135 -0
  581. package/.agents/tests/fm-procevent-quota.test.sh +225 -0
  582. package/.agents/tests/fm-procevent-when.test.sh +406 -0
  583. package/.agents/tests/fm-procevent.test.sh +1745 -0
  584. package/.agents/tests/fm-project-origin.test.sh +110 -0
  585. package/.agents/tests/fm-public-followup.test.sh +2272 -0
  586. package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
  587. package/.agents/tests/fm-quota-choose.test.sh +626 -0
  588. package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
  589. package/.agents/tests/fm-remote-doctor.test.sh +625 -0
  590. package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
  591. package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
  592. package/.agents/tests/fm-remote-job.test.sh +768 -0
  593. package/.agents/tests/fm-remote-reply.test.sh +520 -0
  594. package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
  595. package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
  596. package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
  597. package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
  598. package/.agents/tests/fm-review-diff.test.sh +176 -0
  599. package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
  600. package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
  601. package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
  602. package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
  603. package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
  604. package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
  605. package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
  606. package/.agents/tests/fm-send-inbox.test.sh +352 -0
  607. package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
  608. package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
  609. package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
  610. package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
  611. package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
  612. package/.agents/tests/fm-send-settle.test.sh +147 -0
  613. package/.agents/tests/fm-send-strict.test.sh +241 -0
  614. package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
  615. package/.agents/tests/fm-session-start.test.sh +2515 -0
  616. package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
  617. package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
  618. package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
  619. package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
  620. package/.agents/tests/fm-spawn-batch.test.sh +148 -0
  621. package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
  622. package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
  623. package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
  624. package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
  625. package/.agents/tests/fm-startup-network.test.sh +712 -0
  626. package/.agents/tests/fm-stow-cascade.test.sh +370 -0
  627. package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
  628. package/.agents/tests/fm-supervision-events.test.sh +156 -0
  629. package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
  630. package/.agents/tests/fm-tangle-guard.test.sh +277 -0
  631. package/.agents/tests/fm-task-delivery.test.sh +420 -0
  632. package/.agents/tests/fm-task-inbox.test.sh +513 -0
  633. package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
  634. package/.agents/tests/fm-teardown.test.sh +2665 -0
  635. package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
  636. package/.agents/tests/fm-test-fixtures.test.sh +132 -0
  637. package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
  638. package/.agents/tests/fm-test-run.test.sh +1196 -0
  639. package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
  640. package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
  641. package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
  642. package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
  643. package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
  644. package/.agents/tests/fm-transition-lib.test.sh +54 -0
  645. package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
  646. package/.agents/tests/fm-update.test.sh +304 -0
  647. package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
  648. package/.agents/tests/fm-voice-relay.test.sh +4741 -0
  649. package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
  650. package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
  651. package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
  652. package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
  653. package/.agents/tests/fm-wake-queue.test.sh +1224 -0
  654. package/.agents/tests/fm-watch-arm.test.sh +821 -0
  655. package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
  656. package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
  657. package/.agents/tests/fm-watch-triage.test.sh +3889 -0
  658. package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
  659. package/.agents/tests/fm-x-mode.test.sh +3042 -0
  660. package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
  661. package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
  662. package/.agents/tests/herdr-test-safety.sh +42 -0
  663. package/.agents/tests/lib.sh +315 -0
  664. package/.agents/tests/remote-herdr-fixture.sh +125 -0
  665. package/.agents/tests/secondmate-helpers.sh +193 -0
  666. package/.agents/tests/smoke.test.sh +93 -0
  667. package/.agents/tests/wake-helpers.sh +338 -0
  668. package/.agents/tests/zellij-test-safety.sh +60 -0
  669. package/.agents/tools/README.md +10 -0
  670. package/.agents/tools/bin/tasks-cli +267 -0
  671. package/.agents/tools/tasks-cli.ts +216 -0
  672. package/AGENTS.md +498 -0
  673. package/CHANGELOG.md +1913 -0
  674. package/LICENSE +1 -1
  675. package/NOTICE +63 -0
  676. package/README.md +114 -60
  677. package/RULES/01-domains.md +51 -0
  678. package/RULES/02-agents.md +78 -0
  679. package/RULES/03-houses.md +61 -0
  680. package/RULES/04-hoard.md +97 -0
  681. package/RULES/05-platforms.md +67 -0
  682. package/RULES/06-append-only.md +108 -0
  683. package/RULES/07-config.md +101 -0
  684. package/RULES/08-delivery-gate.md +75 -0
  685. package/RULES/09-electron.md +58 -0
  686. package/RULES/README.md +22 -0
  687. package/bin/README.md +107 -0
  688. package/bin/a2a-mcp.sh +133 -0
  689. package/bin/a2a-serve.py +103 -0
  690. package/bin/a2a-serve.sh +8 -0
  691. package/bin/a2a-talk.sh +50 -0
  692. package/bin/a2abridge-ensure.sh +108 -0
  693. package/bin/agent-run.sh +43 -0
  694. package/bin/agents-config.sh +256 -0
  695. package/bin/apodex-smoke-test.sh +105 -0
  696. package/bin/bifrost-bridge.sh +131 -0
  697. package/bin/bifrost-ingress.sh +77 -0
  698. package/bin/bootstrap-macos.sh +112 -0
  699. package/bin/bootstrap-windows.ps1 +112 -0
  700. package/bin/branch-guard.sh +64 -0
  701. package/bin/brokk +73 -0
  702. package/bin/brokk-classify-lib.sh +1770 -0
  703. package/bin/brokk-lease-lib.sh +222 -0
  704. package/bin/brokk-lease.sh +193 -0
  705. package/bin/brokk-lint.sh +65 -0
  706. package/bin/brokk-send.sh +51 -0
  707. package/bin/brokk-update.sh +9 -0
  708. package/bin/brokk-wake-grant.sh +127 -0
  709. package/bin/brokk-wake-lib.sh +1849 -0
  710. package/bin/changelog-assemble.sh +154 -0
  711. package/bin/changelog-guard.sh +197 -0
  712. package/bin/crash-sense.sh +173 -0
  713. package/bin/design-check.sh +80 -0
  714. package/bin/design-icon.sh +153 -0
  715. package/bin/desktop-place.sh +224 -0
  716. package/bin/docs-guard.sh +39 -0
  717. package/bin/editor-place.sh +225 -0
  718. package/bin/eindri-acclaim.sh +47 -0
  719. package/bin/eindri-control.sh +28 -0
  720. package/bin/eindri-role.sh +83 -0
  721. package/bin/eindri-seat.sh +83 -0
  722. package/bin/eindri-seen.sh +54 -0
  723. package/bin/eindri-send.sh +15 -0
  724. package/bin/eindri-start.sh +98 -0
  725. package/bin/eindri-watch.sh +57 -0
  726. package/bin/einherjar-spawn.sh +576 -0
  727. package/bin/eir-doctor.sh +158 -0
  728. package/bin/erindi-brief.sh +271 -0
  729. package/bin/feature-inventory.sh +73 -0
  730. package/bin/fleet-apply.sh +81 -0
  731. package/bin/github-deploy.sh +94 -0
  732. package/bin/gjallarhorn-expose.sh +136 -0
  733. package/bin/gjallarhorn-notify.sh +71 -0
  734. package/bin/gjallarhorn-purge.sh +67 -0
  735. package/bin/gjallarhorn-tunnel.sh +85 -0
  736. package/bin/gleipnir-lock-lib.sh +284 -0
  737. package/bin/groa-update.sh +130 -0
  738. package/bin/hall-snapshot.sh +111 -0
  739. package/bin/hamr-harness.sh +246 -0
  740. package/bin/heimdall-ssh-keys.sh +374 -0
  741. package/bin/herdr-agents.py +44 -0
  742. package/bin/herdr-ensure.sh +104 -0
  743. package/bin/herdr-run.sh +452 -0
  744. package/bin/hermes-ensure.sh +88 -0
  745. package/bin/hlidskjalf-agents.sh +172 -0
  746. package/bin/hlidskjalf-usage.sh +196 -0
  747. package/bin/hoard-guard.sh +135 -0
  748. package/bin/hoard-lib.sh +105 -0
  749. package/bin/hodd.sh +102 -0
  750. package/bin/host-sense.sh +199 -0
  751. package/bin/huginn-research-worker.sh +121 -0
  752. package/bin/local-model-lock.sh +70 -0
  753. package/bin/mimir-bridge.py +259 -0
  754. package/bin/mimir-bridge.sh +100 -0
  755. package/bin/mimir-ingest.sh +131 -0
  756. package/bin/mimir-reflect.sh +27 -0
  757. package/bin/mimir.sh +113 -0
  758. package/bin/mjollnir-webhook.sh +72 -0
  759. package/bin/mjollnir.sh +104 -0
  760. package/bin/model-hardware.sh +96 -0
  761. package/bin/model-resolve.sh +160 -0
  762. package/bin/models-detect.sh +178 -0
  763. package/bin/nornir-cron-start.sh +162 -0
  764. package/bin/nornir-job-daily-briefing.sh +191 -0
  765. package/bin/nornir-job-git-sync.sh +152 -0
  766. package/bin/nornir-job-hall-snapshot.sh +28 -0
  767. package/bin/nornir-job-memory-housekeeping.sh +114 -0
  768. package/bin/nornir-job-nsr-compliance.sh +54 -0
  769. package/bin/nornir-job-observer.sh +166 -0
  770. package/bin/nornir-job-skillopt-sleep.sh +76 -0
  771. package/bin/npm-publish.sh +136 -0
  772. package/bin/omarchy-hook-install.sh +60 -0
  773. package/bin/omarchy-install.sh +161 -0
  774. package/bin/omarchy-plugins.sh +187 -0
  775. package/bin/omarchy-sense.sh +162 -0
  776. package/bin/perm-guard.sh +30 -0
  777. package/bin/pi-agent.sh +68 -0
  778. package/bin/pi-ensure.sh +77 -0
  779. package/bin/pi-local.sh +37 -0
  780. package/bin/pi-model-agnostic.sh +71 -0
  781. package/bin/pi-seat.sh +63 -0
  782. package/bin/prereq-ensure.sh +166 -0
  783. package/bin/private-guard.sh +58 -0
  784. package/bin/project-git.sh +69 -0
  785. package/bin/public-guard.sh +71 -0
  786. package/bin/ratatoskr.sh +49 -0
  787. package/bin/realm-lib.sh +32 -0
  788. package/bin/repo-scrub.sh +62 -0
  789. package/bin/rodd-operational-input.sh +250 -0
  790. package/bin/runes-append.sh +198 -0
  791. package/bin/saga-session-start.sh +172 -0
  792. package/bin/saga-sessionstart-run.sh +79 -0
  793. package/bin/saga-wake-drain.sh +41 -0
  794. package/bin/secret-guard.sh +63 -0
  795. package/bin/sessrumnir-ensure.sh +100 -0
  796. package/bin/sessrumnir-sync.sh +237 -0
  797. package/bin/sessrumnir.sh +104 -0
  798. package/bin/skillopt-setup.sh +76 -0
  799. package/bin/skuld-branch-outcome.sh +203 -0
  800. package/bin/skuld-branch-prompt.sh +101 -0
  801. package/bin/smidja-bootstrap.sh +94 -0
  802. package/bin/smidja-observe.sh +86 -0
  803. package/bin/syn-arm-pretool-check.sh +57 -0
  804. package/bin/syn-asset-pretool-check.sh +89 -0
  805. package/bin/syn-cd-pretool-check.sh +28 -0
  806. package/bin/syn-guard-pretool-check.sh +83 -0
  807. package/bin/syn-spawn-pretool-check.sh +58 -0
  808. package/bin/syn-turnend-guard.sh +36 -0
  809. package/bin/syn-watch-arm.sh +99 -0
  810. package/bin/tailscale-sync.sh +203 -0
  811. package/bin/telegram-bot.sh +82 -0
  812. package/bin/toolchain.sh +74 -0
  813. package/bin/ui-truth-check.sh +75 -0
  814. package/bin/utgard.sh +111 -0
  815. package/bin/valhalla.sh +115 -0
  816. package/bin/valknut-load.sh +298 -0
  817. package/bin/vor-crew-state.sh +124 -0
  818. package/bin/wedge-notify.sh +60 -0
  819. package/bin/workspace-provision.sh +80 -0
  820. package/bin/workspace-rag.sh +163 -0
  821. package/bin/wyrd-db.sh +47 -0
  822. package/bin/yggdrasil.sh +152 -0
  823. package/bin/ymir-edit.sh +145 -0
  824. package/bin/ymir-install.sh +806 -0
  825. package/bin/ymir-invite.sh +93 -0
  826. package/bin/ymir-isolation.sh +88 -0
  827. package/bin/ymir-migrate.sh +61 -0
  828. package/bin/ymir-plan.sh +356 -0
  829. package/bin/ymir-platform.sh +348 -0
  830. package/bin/ymir-say.sh +110 -0
  831. package/bin/ymir-setup-auth.sh +119 -0
  832. package/bin/ymir-validate.sh +193 -0
  833. package/bin/ymir.js +74 -16
  834. package/docs/Architecture.md +339 -0
  835. package/docs/design.md +351 -0
  836. package/docs/installations/README.md +63 -0
  837. package/docs/installations/ymir-home.md +93 -0
  838. package/docs/integration.md +105 -0
  839. package/docs/lore.md +1060 -0
  840. package/docs/research/agent-harnesses.md +290 -0
  841. package/docs/runbooks/README.md +19 -0
  842. package/docs/runbooks/a2a.md +91 -0
  843. package/docs/runbooks/agent-permissions.md +99 -0
  844. package/docs/runbooks/agents.md +57 -0
  845. package/docs/runbooks/models.md +69 -0
  846. package/docs/runbooks/realm-onboarding.md +60 -0
  847. package/docs/runbooks/secrets-and-hoard.md +60 -0
  848. package/docs/runbooks/updates-and-migrations.md +110 -0
  849. package/docs/runbooks/worktrees-isolation.md +72 -0
  850. package/docs/session-start.md +105 -0
  851. package/docs/skillopt-integration.md +321 -0
  852. package/docs/sync-system.md +66 -0
  853. package/docs/workspaces.md +104 -0
  854. package/docs/ymir-rut.md +260 -0
  855. package/package.json +54 -14
  856. package/packaging/build.sh +74 -0
  857. package/packaging/macos/Ymir Installer.command +43 -0
  858. package/packaging/windows/ymir-setup.nsi +74 -0
  859. package/scripts/README.md +22 -0
  860. package/scripts/electron.sh +269 -0
  861. package/scripts/lower.sh +34 -0
  862. package/scripts/raise.sh +42 -0
  863. package/scripts/start.sh +217 -0
  864. package/scripts/stop.sh +113 -0
  865. package/install.sh +0 -35
@@ -0,0 +1,625 @@
1
+ #!/usr/bin/env bash
2
+ # fm-crew-state.sh - deterministic read of a crew's CURRENT state.
3
+ #
4
+ # Why this exists: state/<id>.status is an append-only, best-effort EVENT LOG.
5
+ # Crews append only wake-worthy transitions (done/needs-decision/blocked/paused/failed)
6
+ # and nothing when they silently resume, so `tail -1` of that log reports the
7
+ # last EVENT, not the current STATE. After firstmate resolves a needs-decision
8
+ # or blocked and the crew resumes (responds to the gate, the pipeline fixes, it
9
+ # re-validates), the log's last line stays stale. This helper never infers the
10
+ # current state from a tail of the log: it reads the authoritative source (a
11
+ # no-mistakes run-step attributed under bin/fm-nm-run-lib.sh's contract, else
12
+ # the pane busy-signature) and reconciles the possibly-stale log against it.
13
+ #
14
+ # The determinism lives entirely here - only run-step / pane / log reads plus
15
+ # fixed mapping logic, no heuristics and no LLM. Output is one stable, parseable,
16
+ # token-tight line firstmate can read every heartbeat:
17
+ #
18
+ # state: <working|parked|done|blocked|paused|failed|unknown> · source: <run-step|pane|status-log|remote-endpoint|none> · <detail>
19
+ #
20
+ # Logic, in order:
21
+ # 1. Resolve worktree + backend target + kind from state/<id>.meta. A meta
22
+ # recording remote_host= is a remote secondmate: its worktree and endpoint
23
+ # live on that host, so the local worktree and pane reads are skipped and
24
+ # the remote host is asked for the endpoint's recovery-grade state
25
+ # (fm-on.sh + fm-remote-secondmate-control.sh state). alive falls through
26
+ # to the routed status log; dead/missing report the remote verdict; an
27
+ # unreachable or unreadable remote reports unknown-remote, never a false
28
+ # gone/dead.
29
+ # 2. Attribute an active or terminal no-mistakes run under the branch, head,
30
+ # pipeline-custody, and newest-first rules owned by bin/fm-nm-run-lib.sh.
31
+ # The run-step is AUTHORITATIVE: running/fixing -> working, ci -> working,
32
+ # awaiting_approval/fix_review -> parked (with gate findings), terminal
33
+ # passed/checks-passed -> done, failed/cancelled -> failed. EXCEPT: while
34
+ # the active step is ci, `axi status` alone cannot tell "still waiting on
35
+ # checks" from "checks green, waiting on merge" (see nm_ci_checks_state) -
36
+ # a ci-step log-tail check overrides working -> done once checks read
37
+ # green, so a green PR is never silently read as still-validating.
38
+ # 3. Reconcile the status log: if its last line says needs-decision/blocked but
39
+ # the run-step shows the run moved on, the log is deterministically stale and
40
+ # is flagged superseded. A genuinely parked run plus a needs-decision log
41
+ # agree, and are reported as parked.
42
+ # 4. No run for this crew (pre-validation, or kind=scout): fall back to the
43
+ # recorded backend's pane busy state, then the status log's last line only
44
+ # when its verb maps to a recognized run-state. Decision-only events such as
45
+ # `resolved` never become current state or detail.
46
+ # 5. Missing meta or torn-down worktree: report unknown · none. If no run is
47
+ # attributed to this crew, a dead endpoint also reports unknown · none rather
48
+ # than trusting a stale status log.
49
+ #
50
+ # Read-only and side-effect free. Always exits 0 on a successful read regardless
51
+ # of state; exit 2 only on a usage error (no id).
52
+ set -u
53
+
54
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
55
+ FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
56
+ FM_HOME="${FM_HOME:-${FM_ROOT_OVERRIDE:-$FM_ROOT}}"
57
+ STATE="${FM_STATE_OVERRIDE:-$FM_HOME/state}"
58
+
59
+ # shellcheck source=bin/fm-tmux-lib.sh
60
+ . "$SCRIPT_DIR/fm-tmux-lib.sh"
61
+ # shellcheck source=bin/fm-backend.sh
62
+ . "$SCRIPT_DIR/fm-backend.sh"
63
+ # shellcheck source=bin/fm-classify-lib.sh
64
+ . "$SCRIPT_DIR/fm-classify-lib.sh"
65
+ # shellcheck source=bin/fm-busy-lib.sh
66
+ . "$SCRIPT_DIR/fm-busy-lib.sh"
67
+ # shellcheck source=bin/fm-nm-run-lib.sh
68
+ . "$SCRIPT_DIR/fm-nm-run-lib.sh"
69
+
70
+ ID=${1:-}
71
+ [ -n "$ID" ] || { echo "usage: fm-crew-state.sh <id>" >&2; exit 2; }
72
+
73
+ META="$STATE/$ID.meta"
74
+ LOG="$STATE/$ID.status"
75
+ NM_TIMEOUT=${FM_CREW_STATE_NM_TIMEOUT:-10}
76
+ case "$NM_TIMEOUT" in ''|*[!0-9]*) NM_TIMEOUT=10 ;; esac
77
+ # How many of the most recent `no-mistakes runs` rows the cross-branch fallback
78
+ # (nm_runs_status_for_branch, below) scans. Generous enough to still find a
79
+ # branch's own run on a busy multi-crew fleet without listing the entire
80
+ # history every call.
81
+ FM_CREW_STATE_RUNS_LIMIT=${FM_CREW_STATE_RUNS_LIMIT:-200}
82
+ case "$FM_CREW_STATE_RUNS_LIMIT" in ''|*[!0-9]*) FM_CREW_STATE_RUNS_LIMIT=200 ;; esac
83
+ SEP=' · '
84
+
85
+ # Emit the one canonical line and exit 0. Detail is optional.
86
+ emit() { # <state> <source> [detail]
87
+ local line="state: $1${SEP}source: $2"
88
+ [ -n "${3:-}" ] && line="$line${SEP}$3"
89
+ printf '%s\n' "$line"
90
+ exit 0
91
+ }
92
+
93
+ # --- meta resolution --------------------------------------------------------
94
+
95
+ [ -f "$META" ] || emit unknown none "no metadata for $ID"
96
+
97
+ meta_value() { # <key>
98
+ grep "^$1=" "$META" 2>/dev/null | tail -1 | cut -d= -f2- || true
99
+ }
100
+
101
+ WT=$(meta_value worktree)
102
+ KIND=$(meta_value kind)
103
+ HARNESS=$(meta_value harness)
104
+ REMOTE_HOST=$(meta_value remote_host)
105
+ [ -n "$KIND" ] || KIND=ship
106
+
107
+ # A torn-down (or never-created) worktree has no current state to read. A
108
+ # remote secondmate's recorded worktree is a path on ITS host, so the local
109
+ # probe proves nothing for it - the remote arm below reads the true source.
110
+ if [ -z "$REMOTE_HOST" ] && { [ -z "$WT" ] || [ ! -d "$WT" ]; }; then
111
+ emit unknown none "worktree gone (torn down?)"
112
+ fi
113
+
114
+ # --- status log ------------------------------------------------------------
115
+
116
+ # Last non-empty status line; fm-classify-lib.sh owns leading-verb normalization.
117
+ log_last_line() {
118
+ [ -f "$LOG" ] || return 1
119
+ grep -v '^[[:space:]]*$' "$LOG" 2>/dev/null | tail -1
120
+ }
121
+ # Map a status-log verb onto a canonical state for the fallback path. `paused` is
122
+ # the deliberate-external-wait verb (fm-classify-lib.sh's FM_CLASSIFY_PAUSED_VERB):
123
+ # a crew with no active run and an idle pane that declared a known external wait
124
+ # reports `paused` distinctly, so a supervisor reading this sees a declared pause
125
+ # and its reason rather than a wedge-suspect idle.
126
+ map_log_state() { # <line>
127
+ if status_is_paused "$1"; then
128
+ echo paused
129
+ return
130
+ fi
131
+ case "$(status_line_verb "$1")" in
132
+ working) echo working ;;
133
+ needs-decision) echo parked ;;
134
+ blocked) echo blocked ;;
135
+ done) echo "done" ;;
136
+ failed) echo failed ;;
137
+ *) echo unknown ;;
138
+ esac
139
+ }
140
+
141
+ LOG_LINE=$(log_last_line || true)
142
+ LOG_VERB=$(status_line_verb "$LOG_LINE")
143
+
144
+ # --- remote secondmate: the true source is the remote endpoint ---------------
145
+ # A remote mate's recorded worktree and backend target live on its own host, so
146
+ # the local worktree probe above and the local pane reads below would misreport
147
+ # a healthy remote mate as gone or dead. Ask the remote host for the endpoint's
148
+ # recovery-grade state over the same fm-on.sh transport fm-send uses, then read
149
+ # current activity from the routed status log exactly as for a local
150
+ # secondmate (an idle endpoint is healthy for a secondmate either way). An
151
+ # unreachable host or unreadable endpoint is reported as unknown-remote -
152
+ # explicitly NOT proof of death - so a transport blip never reads as a torn
153
+ # down or dead mate; only the remote host's own dead/missing verdict may say
154
+ # the endpoint is actually gone.
155
+ if [ -n "$REMOTE_HOST" ]; then
156
+ if ! REMOTE_STATE=$(FM_HOME="$FM_HOME" "$SCRIPT_DIR/fm-on.sh" "$ID" \
157
+ fm-remote-secondmate-control.sh state "$ID" < /dev/null 2>/dev/null); then
158
+ REMOTE_STATE=
159
+ fi
160
+ REMOTE_STATE=$(printf '%s\n' "$REMOTE_STATE" | tail -1)
161
+ case "$REMOTE_STATE" in
162
+ alive)
163
+ if [ -n "$LOG_VERB" ]; then
164
+ LOG_STATE=$(map_log_state "$LOG_LINE")
165
+ if [ "$LOG_STATE" != unknown ]; then
166
+ emit "$LOG_STATE" status-log "$(status_line_note "$LOG_LINE")${SEP}remote endpoint alive on $REMOTE_HOST"
167
+ fi
168
+ fi
169
+ emit unknown remote-endpoint "alive on $REMOTE_HOST (an idle secondmate is healthy)"
170
+ ;;
171
+ dead|missing)
172
+ emit unknown remote-endpoint "remote endpoint $REMOTE_STATE on $REMOTE_HOST"
173
+ ;;
174
+ '')
175
+ emit unknown remote-endpoint "unknown-remote: $REMOTE_HOST unreachable or endpoint unreadable (not proof of death)"
176
+ ;;
177
+ *)
178
+ emit unknown remote-endpoint "unknown-remote: endpoint state '$REMOTE_STATE' on $REMOTE_HOST (not proof of death)"
179
+ ;;
180
+ esac
181
+ fi
182
+
183
+ # pane_readable is consulted ONLY in the no-run fallback below. The run-step path
184
+ # stays authoritative regardless of pane liveness - judge by the run-step, not the
185
+ # shell - so a finished crew whose endpoint has closed still reports its run-step
186
+ # state (e.g. done) instead of being masked as unknown. Backend-aware
187
+ # (fm_backend_of_meta defaults absent backend= to tmux, the P1 contract): a
188
+ # herdr task is read through fm_backend_capture instead of a bare tmux probe.
189
+ TASK_BACKEND=$(fm_backend_of_meta "$META")
190
+ BACKEND_TARGET=$(fm_backend_target_of_meta "$META")
191
+ EXPECTED_LABEL="fm-$ID"
192
+ pane_readable() { # <target>
193
+ case "$TASK_BACKEND" in
194
+ tmux) tmux display-message -p -t "$1" '#{pane_id}' >/dev/null 2>&1 ;;
195
+ *) fm_backend_capture "$TASK_BACKEND" "$1" 1 "$EXPECTED_LABEL" >/dev/null 2>&1 ;;
196
+ esac
197
+ }
198
+ # crew_busy_verdict: the crew's semantic busy state from the one contract
199
+ # owner (bin/fm-busy-lib.sh), as "<busy|idle|unknown> <source>". A converted
200
+ # adapter answers from its own lifecycle record; Grok answers from its
201
+ # isolated rendered-tail fallback; a herdr crew's native `busy` is accepted
202
+ # when no record exists, but its native `idle` is NOT, because agent.get
203
+ # reports generation state (idle while a crew blocks on its own long-running
204
+ # foreground tool call) rather than turn state.
205
+ crew_busy_verdict() { # <target>
206
+ local tail40=''
207
+ case "$HARNESS" in
208
+ grok*) tail40=$(fm_backend_capture "$TASK_BACKEND" "$1" 40 "$EXPECTED_LABEL" 2>/dev/null) || tail40='' ;;
209
+ esac
210
+ fm_busy_classify "$TASK_BACKEND" "$1" "$HARNESS" "$ID" "$STATE" "$tail40"
211
+ }
212
+
213
+ # --- no-mistakes run lookup (authoritative when a run matches this branch) --
214
+ # trim, strip_quotes, the bounded nm_run call, nm_field's TOON parse, and the
215
+ # attribution helpers below are thin wrappers over the ONE owner in
216
+ # bin/fm-nm-run-lib.sh, shared with fm-teardown.sh's pre-teardown run abort.
217
+
218
+ trim() { fm_nm_trim "$@"; }
219
+ strip_quotes() { fm_nm_strip_quotes "$@"; }
220
+ nm_run() { # <args...>
221
+ fm_nm_run "$WT" "$NM_TIMEOUT" "$@"
222
+ }
223
+
224
+ # Scalar value of a TOON key in the captured run output ($RUN_OUT).
225
+ RUN_OUT=""
226
+ nm_field() { # <key>
227
+ fm_nm_field "$RUN_OUT" "$1"
228
+ }
229
+ # Finding count from a findings[N]{...} table header; empty when none.
230
+ nm_findings_count() {
231
+ printf '%s\n' "$RUN_OUT" | grep -oE 'findings\[[0-9]+\]' | head -1 | grep -oE '[0-9]+'
232
+ }
233
+ nm_gate_step_row() {
234
+ local row step rest status findings
235
+ row=$(printf '%s\n' "$RUN_OUT" | grep -E '^[[:space:]]*[^,]+,[[:space:]]*"?(awaiting_approval|fix_review)"?[[:space:]]*,' | head -1)
236
+ [ -n "$row" ] || return 0
237
+ row=$(trim "$row")
238
+ step=$(trim "${row%%,*}")
239
+ rest=${row#*,}
240
+ status=$(strip_quotes "$(trim "${rest%%,*}")")
241
+ rest=${rest#*,}
242
+ findings=$(trim "${rest%%,*}")
243
+ printf '%s|%s|%s' "$step" "$status" "$findings"
244
+ }
245
+ nm_gate_status() {
246
+ local s row
247
+ s=$(printf '%s\n' "$RUN_OUT" | grep -E '^[[:space:]]*(status|state):[[:space:]]*"?(awaiting_approval|fix_review)"?[[:space:]]*$' | head -1)
248
+ if [ -n "$s" ]; then
249
+ s=$(strip_quotes "$(trim "${s#*:}")")
250
+ printf '%s' "$s"
251
+ return
252
+ fi
253
+ row=$(nm_gate_step_row)
254
+ [ -n "$row" ] && { row=${row#*|}; printf '%s' "${row%%|*}"; }
255
+ }
256
+ nm_has_gate() {
257
+ printf '%s\n' "$RUN_OUT" | grep -Eq '^[[:space:]]*gate:[[:space:]]*'
258
+ }
259
+ nm_gate_line_name() {
260
+ local gate step
261
+ gate=$(strip_quotes "$(nm_field gate)")
262
+ [ -n "$gate" ] && { printf '%s' "$gate"; return; }
263
+ step=$(printf '%s\n' "$RUN_OUT" | sed -n '/^[[:space:]]*gate:[[:space:]]*$/,/^[^[:space:]][^:]*:/s/^[[:space:]]*step:[[:space:]]*\(.*\)/\1/p' | head -1)
264
+ step=$(strip_quotes "$step")
265
+ [ -n "$step" ] && printf '%s' "$step"
266
+ }
267
+ nm_gate_name() {
268
+ local gate row
269
+ gate=$(nm_gate_line_name)
270
+ [ -n "$gate" ] && { printf '%s' "$gate"; return; }
271
+ row=$(nm_gate_step_row)
272
+ [ -n "$row" ] && printf '%s' "${row%%|*}"
273
+ }
274
+ nm_gate_findings_count() {
275
+ local f row rest
276
+ f=$(nm_findings_count)
277
+ [ -n "$f" ] && { printf '%s' "$f"; return; }
278
+ row=$(nm_gate_step_row)
279
+ [ -n "$row" ] || return 0
280
+ rest=${row#*|}
281
+ rest=${rest#*|}
282
+ rest=${rest%%|*}
283
+ case "$rest" in ''|*[!0-9]*) return 0 ;; esac
284
+ printf '%s' "$rest"
285
+ }
286
+ log_reports_ci_ready() {
287
+ [ "$LOG_VERB" = "done" ] || return 1
288
+ case "$(status_line_note "$LOG_LINE")" in
289
+ *PR*"checks green"*|*"checks green"*PR*) return 0 ;;
290
+ *) return 1 ;;
291
+ esac
292
+ }
293
+
294
+ nm_ci_step_status() {
295
+ local row rest
296
+ row=$(printf '%s\n' "$RUN_OUT" | grep -E '^[[:space:]]*ci,[[:space:]]*"?(running|fixing)"?[[:space:]]*,' | head -1)
297
+ [ -n "$row" ] || return 0
298
+ row=$(trim "$row")
299
+ rest=${row#*,}
300
+ strip_quotes "$(trim "${rest%%,*}")"
301
+ }
302
+
303
+ nm_effective_ci_step_status() {
304
+ local step_status
305
+ if [ "${RUN_STATUS:-}" = fixing ]; then
306
+ printf 'fixing'
307
+ return 0
308
+ fi
309
+ step_status=$(nm_ci_step_status)
310
+ if [ -n "$step_status" ]; then
311
+ printf '%s' "$step_status"
312
+ return 0
313
+ fi
314
+ if [ "${RUN_STATUS:-}" = ci ]; then
315
+ printf 'running'
316
+ fi
317
+ }
318
+
319
+ # Root cause of the PR #252 incident (2026-07): for a repo where merge is left
320
+ # to the captain, no-mistakes' ci step (and therefore top-level status/outcome)
321
+ # stays "running" for the ENTIRE CI-monitor phase, including long after GitHub
322
+ # reports every check green - it only reaches outcome=passed once the PR is
323
+ # actually merged (or failed/cancelled if closed). `axi status`'s steps[] table
324
+ # never distinguishes "still waiting on checks" from "checks green, waiting on
325
+ # merge": both read as plain `ci,running,...`. The only place that transition is
326
+ # recorded is the ci step's own log text, e.g. "all CI checks passed - still
327
+ # monitoring until merged or closed" or "no CI checks reported - still
328
+ # monitoring until merged or closed" (verified against 360+ real run logs under
329
+ # ~/.no-mistakes/logs/*/ci.log on the installed v1.32.2 binary, including the
330
+ # actual PR #252 run). Reads the ci step's log tail via `axi logs` and scans it
331
+ # for the MOST RECENT recognized marker (the log is append-only/chronological,
332
+ # so the last match is current): green with nothing red after it means CI is
333
+ # green right now, still only waiting on merge/close.
334
+ nm_ci_checks_state() {
335
+ local run_id log_tail marker
336
+ run_id=$(strip_quotes "$(nm_field id)")
337
+ [ -n "$run_id" ] || { printf 'unknown'; return; }
338
+ log_tail=$(nm_run axi logs --step ci --run "$run_id") || true
339
+ [ -n "$log_tail" ] || { printf 'unknown'; return; }
340
+ marker=$(printf '%s\n' "$log_tail" \
341
+ | grep -E 'CI checks passed|no CI checks reported - still monitoring|no CI checks reported yet|checks failed|issues detected|CI checks running|base branch advanced.*re-arming CI monitor timeout' \
342
+ | tail -1)
343
+ case "$marker" in
344
+ *"checks passed"*|*"no CI checks reported - still monitoring"*) printf 'green' ;;
345
+ *"no CI checks reported yet"*|*"checks failed"*|*"issues detected"*|*"CI checks running"*|*"base branch advanced"*"re-arming CI monitor timeout"*) printf 'not-ready' ;;
346
+ *) printf 'unknown' ;;
347
+ esac
348
+ }
349
+ # Coarse fallback for cross-branch attribution. `no-mistakes axi status` (bare)
350
+ # reports the active-or-most-recent run for the CURRENT branch when one
351
+ # exists, else falls back to some other branch's run purely as informational
352
+ # display (verified empirically: querying a worktree with its own active run
353
+ # reliably returns that run, even under concurrent load from several other
354
+ # validating crews on the same underlying repo). A crew whose branch genuinely
355
+ # has no run yet therefore sees another branch's answer here.
356
+ #
357
+ # This fallback used to shell out to `no-mistakes axi` (bare, no subcommand)
358
+ # expecting a `runs[N]{id,branch,status,...}:` TOON table and re-query the
359
+ # matched id via `axi status --run <id>`. Verified against the real installed
360
+ # CLI (v1.32.2): the `axi` surface exposes only abort/logs/respond/run/status -
361
+ # there is no runs-listing subcommand under `axi` at all, so that table never
362
+ # appears and the lookup was silently dead code; whenever the bare `axi
363
+ # status` answer was not this crew's own branch, attribution always failed and
364
+ # the caller fell straight through to the pane/log fallback below. (The
365
+ # PRIMARY cause of the 2026-07 herdr false-surface incidents turned out to be
366
+ # a separate bug in bin/fm-watch.sh's stale_is_terminal precedence - see that
367
+ # file's history - but this cross-branch path was independently confirmed
368
+ # dead code and is worth having actually work.)
369
+ #
370
+ # The real run-listing command is the top-level `no-mistakes runs` (verified:
371
+ # `no-mistakes --help` lists it separately from `axi`). It is plain, human-
372
+ # oriented text - no run id, no JSON/TOON, newest-first, columns
373
+ # "<status> <branch> <short-sha> <date> [<pr-url>]" separated by runs of
374
+ # spaces (verified: no quoting, so splitting on the first two whitespace runs
375
+ # is exact) - but branch + coarse status is exactly what this predicate needs:
376
+ # is a run for THIS branch active right now. Echoes the first (most recent)
377
+ # matching row's status word (running/completed/cancelled/failed), or empty
378
+ # when the branch has no run within FM_CREW_STATE_RUNS_LIMIT rows.
379
+ nm_runs_status_for_branch() { # <branch>
380
+ local branch=$1 out row st rest br sha
381
+ out=$(nm_run runs --limit "$FM_CREW_STATE_RUNS_LIMIT")
382
+ [ -n "$out" ] || return 0
383
+ while IFS= read -r row; do
384
+ row=$(trim "$row")
385
+ [ -n "$row" ] || continue
386
+ st=${row%% *}
387
+ rest=${row#* }
388
+ rest=$(trim "$rest")
389
+ br=${rest%% *}
390
+ rest=${rest#* }
391
+ rest=$(trim "$rest")
392
+ sha=${rest%% *}
393
+ if [ "$br" = "$branch" ]; then
394
+ # Same code-identity rule as axi status: skip a same-branch row whose
395
+ # short-sha does not match this worktree (rewritten or advanced tip).
396
+ if ! nm_coarse_head_matches_worktree "$sha"; then
397
+ # An UNRESOLVABLE head is unknown attribution, not a proven
398
+ # mismatch. Stop instead of surfacing an older, superseded row;
399
+ # the caller's pane/log fallback can answer without misattribution.
400
+ fm_nm_head_resolvable "$WT" "$sha" || return 0
401
+ continue
402
+ fi
403
+ printf '%s' "$st"
404
+ return 0
405
+ fi
406
+ done <<< "$out"
407
+ return 0
408
+ }
409
+
410
+ # CREW_BRANCH is empty at detached HEAD (a just-spawned crew, or a scout's
411
+ # scratch worktree); with no branch there is no run to attribute to this crew.
412
+ CREW_BRANCH=$(git -C "$WT" symbolic-ref --quiet --short HEAD 2>/dev/null || true)
413
+
414
+ # 0 if the active axi-status run's head field matches this worktree's code
415
+ # identity. Branch match is a precondition (caller). Rule owned by
416
+ # fm_nm_head_matches_worktree in bin/fm-nm-run-lib.sh.
417
+ nm_run_head_matches_worktree() {
418
+ local run_head
419
+ run_head=$(strip_quotes "$(nm_field head)")
420
+ fm_nm_head_matches_worktree "$WT" "$run_head"
421
+ }
422
+
423
+ # Coarse runs-list rows are "<status> <branch> <short-sha> ...". 0 if the short
424
+ # sha for this branch row matches the worktree head under the same rules as
425
+ # nm_run_head_matches_worktree (equal, or local is ancestor of run tip).
426
+ nm_coarse_head_matches_worktree() { # <short-sha>
427
+ fm_nm_head_matches_worktree "$WT" "$1"
428
+ }
429
+
430
+ HAVE_RUN=0
431
+ # RUN_SOURCE distinguishes the two ways HAVE_RUN=1 can happen: "full" means
432
+ # $RUN_OUT is real `axi status` TOON with step/gate detail; "coarse" means only
433
+ # a bare status word came back from the runs-list fallback above, so the
434
+ # run-step block below skips the TOON field parsing entirely for this crew.
435
+ RUN_SOURCE=full
436
+ COARSE_STATUS=""
437
+ # Scouts and secondmates never drive a no-mistakes validation of their own
438
+ # worktree, so skip the lookup for them and read state from pane/log directly.
439
+ if [ "$KIND" = ship ] && [ -n "$CREW_BRANCH" ] && command -v no-mistakes >/dev/null 2>&1; then
440
+ RUN_OUT=$(nm_run axi status)
441
+ if [ -n "$RUN_OUT" ]; then
442
+ run_branch=$(strip_quotes "$(nm_field branch)")
443
+ # Head equality, or the pipeline-owned-active exemption: while the
444
+ # pipeline owns this branch, the daemon's own branch attribution is
445
+ # authoritative and the lane head need not be a git object here
446
+ # (fm_nm_run_is_pipeline_owned_active in bin/fm-nm-run-lib.sh).
447
+ if [ -n "$run_branch" ] && [ "$run_branch" = "$CREW_BRANCH" ] \
448
+ && { nm_run_head_matches_worktree || fm_nm_run_is_pipeline_owned_active "$RUN_OUT"; }; then
449
+ HAVE_RUN=1
450
+ else
451
+ # The active-or-most-recent run is for another branch, or its same-branch
452
+ # attribution failed (the CLI is alive and answered) - try the coarse
453
+ # fallback.
454
+ # Deliberately nested inside `[ -n "$RUN_OUT" ]`: an empty/timed-out
455
+ # primary call means the CLI itself did not respond, so retrying it
456
+ # immediately with a second bounded call would just double the wait
457
+ # for no better answer.
458
+ COARSE_STATUS=$(nm_runs_status_for_branch "$CREW_BRANCH")
459
+ if [ -n "$COARSE_STATUS" ]; then
460
+ HAVE_RUN=1
461
+ RUN_SOURCE=coarse
462
+ fi
463
+ fi
464
+ fi
465
+ fi
466
+
467
+ # --- run-step authoritative path -------------------------------------------
468
+
469
+ if [ "$HAVE_RUN" = 1 ]; then
470
+ RUN_STATE=working
471
+ RUN_DETAIL=""
472
+ CI_STEP_STATUS=""
473
+ CI_LOG_STATE=""
474
+ RUN_STATUS=""
475
+ if [ "$RUN_SOURCE" = coarse ]; then
476
+ # No step/gate detail is available from the plain runs list - only ever
477
+ # true/working, done, or failed. A crew genuinely parked at a gate still
478
+ # gets full detail once `axi status` reports its own branch again (e.g.
479
+ # once its own step is the most-recently-touched one), and its own
480
+ # needs-decision/blocked status-log append (a captain-relevant VERB) is
481
+ # surfaced by each supervisor's span classification (fm-classify-lib.sh's
482
+ # status_span_first_actionable) regardless of this coarse-vs-full
483
+ # distinction, so a real gate is never silently missed.
484
+ case "$COARSE_STATUS" in
485
+ running) RUN_STATE=working; RUN_DETAIL="validating (background run)" ;;
486
+ completed) RUN_STATE="done"; RUN_DETAIL="run completed" ;;
487
+ failed) RUN_STATE=failed; RUN_DETAIL="run failed" ;;
488
+ cancelled) RUN_STATE=failed; RUN_DETAIL="run cancelled" ;;
489
+ *) RUN_STATE=unknown; RUN_DETAIL="runs list status: $COARSE_STATUS" ;;
490
+ esac
491
+ else
492
+ status=$(strip_quotes "$(nm_field status)")
493
+ RUN_STATUS=$status
494
+ outcome=$(strip_quotes "$(nm_field outcome)")
495
+ awaiting=$(printf '%s\n' "$RUN_OUT" | grep -E '^[[:space:]]*awaiting_agent:' | head -1 || true)
496
+ gate_status=$(nm_gate_status)
497
+ has_gate=0
498
+ nm_has_gate && has_gate=1
499
+
500
+ if [ -n "$outcome" ]; then
501
+ case "$outcome" in
502
+ passed) RUN_STATE="done"; RUN_DETAIL="run passed: PR merged/closed" ;;
503
+ checks-passed) RUN_STATE="done"; RUN_DETAIL="checks green: PR ready for review" ;;
504
+ failed) RUN_STATE=failed; RUN_DETAIL="run failed" ;;
505
+ cancelled) RUN_STATE=failed; RUN_DETAIL="run cancelled" ;;
506
+ *) RUN_STATE=unknown; RUN_DETAIL="outcome: $outcome" ;;
507
+ esac
508
+ elif [ -n "$awaiting" ] || [ "$status" = awaiting_approval ] || [ "$status" = fix_review ] || [ -n "$gate_status" ] || [ "$has_gate" = 1 ]; then
509
+ if [ "$has_gate" = 1 ]; then
510
+ gate=$(nm_gate_line_name)
511
+ else
512
+ gate=$(nm_gate_name)
513
+ fi
514
+ [ -n "$gate" ] || gate=$status
515
+ [ -n "$gate" ] || gate=gate
516
+ RUN_STATE=parked
517
+ RUN_DETAIL="parked at $gate"
518
+ fcount=$(nm_gate_findings_count)
519
+ [ -n "$fcount" ] && RUN_DETAIL="$RUN_DETAIL: $fcount finding(s)"
520
+ if printf '%s\n' "$RUN_OUT" | grep -q 'ask-user'; then
521
+ RUN_DETAIL="$RUN_DETAIL (ask-user: authority decision)"
522
+ fi
523
+ else
524
+ case "$status" in
525
+ ci) RUN_STATE=working; RUN_DETAIL="ci running" ;;
526
+ running|fixing) RUN_STATE=working; RUN_DETAIL="validating ($status)" ;;
527
+ completed) RUN_STATE="done"; RUN_DETAIL="run completed" ;;
528
+ failed) RUN_STATE=failed; RUN_DETAIL="run failed" ;;
529
+ cancelled) RUN_STATE=failed; RUN_DETAIL="run cancelled" ;;
530
+ "") RUN_STATE=working; RUN_DETAIL="run active" ;;
531
+ *) RUN_STATE=working; RUN_DETAIL="run active ($status)" ;;
532
+ esac
533
+ if [ "$RUN_STATE" = working ]; then
534
+ CI_STEP_STATUS=$(nm_effective_ci_step_status)
535
+ case "$CI_STEP_STATUS" in
536
+ running)
537
+ CI_LOG_STATE=$(nm_ci_checks_state)
538
+ if [ "$CI_LOG_STATE" = green ]; then
539
+ RUN_STATE="done"
540
+ RUN_DETAIL="checks green: PR ready for review (still monitoring for merge/close)"
541
+ fi
542
+ ;;
543
+ fixing)
544
+ CI_LOG_STATE=not-ready
545
+ ;;
546
+ esac
547
+ fi
548
+ fi
549
+ fi
550
+
551
+ if [ "$RUN_STATE" = working ] && log_reports_ci_ready; then
552
+ if [ "$RUN_SOURCE" = coarse ]; then
553
+ emit "done" status-log "$(status_line_note "$LOG_LINE")${SEP}run still monitoring PR"
554
+ fi
555
+ [ -n "$CI_STEP_STATUS" ] || CI_STEP_STATUS=$(nm_effective_ci_step_status)
556
+ if [ "$RUN_STATUS" = fixing ]; then
557
+ CI_LOG_STATE=not-ready
558
+ elif [ "$CI_STEP_STATUS" = running ] && [ -z "$CI_LOG_STATE" ]; then
559
+ CI_LOG_STATE=$(nm_ci_checks_state)
560
+ elif [ "$CI_STEP_STATUS" = fixing ]; then
561
+ CI_LOG_STATE=not-ready
562
+ fi
563
+ if [ "$CI_LOG_STATE" != not-ready ]; then
564
+ emit "done" status-log "$(status_line_note "$LOG_LINE")${SEP}run still monitoring PR"
565
+ fi
566
+ fi
567
+
568
+ # Reconcile the status log. A needs-decision/blocked log line that the run-step
569
+ # has moved past (anything but a genuinely parked run) is deterministically
570
+ # stale: the gate resolved and the run resumed or finished.
571
+ case "$LOG_VERB" in
572
+ needs-decision|blocked)
573
+ if [ "$RUN_STATE" != parked ]; then
574
+ if [ "$RUN_STATE" = working ]; then
575
+ RUN_DETAIL="$RUN_DETAIL${SEP}status-log superseded by active run"
576
+ else
577
+ RUN_DETAIL="$RUN_DETAIL${SEP}status-log superseded (run $RUN_STATE)"
578
+ fi
579
+ fi
580
+ ;;
581
+ esac
582
+
583
+ emit "$RUN_STATE" run-step "$RUN_DETAIL"
584
+ fi
585
+
586
+ # --- fallback: no run attributed to this crew ------------------------------
587
+ # The run-step path above already handled any crew with a run, regardless of pane
588
+ # liveness, so a finished-but-pane-closed crew never reaches here. Down here there
589
+ # is no run to consult, so a dead/unreadable target means the crew is gone: report
590
+ # unknown rather than trusting a possibly-stale status log as the current state.
591
+ [ -n "$BACKEND_TARGET" ] || emit unknown none "no backend target recorded"
592
+ pane_readable "$BACKEND_TARGET" || emit unknown none "backend target gone: $BACKEND_TARGET"
593
+
594
+ # Secondmates idle on their own watcher (idle pane = healthy), so the busy
595
+ # state is not meaningful for them; read their state from the status log only.
596
+ # Only an exact busy verdict reports working here, and only an exact idle
597
+ # verdict permits the status-log fallback below. Missing, malformed, stale, or
598
+ # unverified semantic state remains unknown.
599
+ if [ "$KIND" != secondmate ]; then
600
+ BUSY_VERDICT=$(crew_busy_verdict "$BACKEND_TARGET")
601
+ case "${BUSY_VERDICT%% *}" in
602
+ busy) emit working pane "harness busy (${BUSY_VERDICT#* })" ;;
603
+ idle) ;;
604
+ *) emit unknown pane "harness state unavailable ($BUSY_VERDICT)" ;;
605
+ esac
606
+ fi
607
+
608
+ # Fall back to the status log's last line, but ONLY when its verb maps to a real
609
+ # run-state. A decision-closing event - resolved: (fm-classify-lib.sh's
610
+ # FM_CLASSIFY_RESOLVE_VERB), and any future decision-only sibling - is NOT a state:
611
+ # it exists solely to CLOSE a keyed decision in the durable fold, so a trailing
612
+ # resolved: must never become the current state or leak its resolution prose as the
613
+ # detail. Skipping it lets a just-resolved idle crew (typically a secondmate, which
614
+ # has no busy check above) fall through to the idle default instead of rendering
615
+ # `unknown` with the resolution note as `doing`. map_log_state is the single owner of
616
+ # the verb->state mapping (including the configurable paused verb), so reusing its
617
+ # `unknown` verdict as the "not a state" test needs no second verb list here.
618
+ if [ -n "$LOG_VERB" ]; then
619
+ LOG_STATE=$(map_log_state "$LOG_LINE")
620
+ if [ "$LOG_STATE" != unknown ]; then
621
+ emit "$LOG_STATE" status-log "$(status_line_note "$LOG_LINE")"
622
+ fi
623
+ fi
624
+
625
+ emit unknown none "no current-state source available"