@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,800 @@
1
+ #!/usr/bin/env bash
2
+ # Check, and optionally repair, one remote account's second-mate readiness.
3
+ #
4
+ # Usage:
5
+ # bin/fm-on.sh <secondmate-id|ssh-alias> fm-remote-doctor.sh [--fix]
6
+ #
7
+ # Run it through fm-on.sh so the fixed entrypoint invokes this readiness owner
8
+ # over its plain SSH bootstrap. The command reports the same filesystem-composed
9
+ # PATH used by worker jobs while retaining authority to inspect and repair the
10
+ # worker itself.
11
+ #
12
+ # A remote second mate always runs on the Herdr backend in the dedicated
13
+ # fm-remote session. Its account therefore needs the Firstmate-owned Aqua Herdr
14
+ # agent plus the sibling dev.firstmate.remote-job worker that runs normal fm-on
15
+ # commands through the Aqua or Linux job-worker path. Doctor remains invokable
16
+ # over the plain-SSH bootstrap path to inspect and repair that worker. SSH cannot
17
+ # create an Aqua session, so a host with no GUI login is a human gap rather than
18
+ # something --fix attempts to bypass.
19
+ #
20
+ # Line protocol, one fact per line, stable for script consumers:
21
+ # mode=check|fix
22
+ # path=<the child PATH this command inherited>
23
+ # entrypoint=yes|no
24
+ # platform=darwin|linux|<uname -s>|unknown
25
+ # required <tool>=<path>|MISSING
26
+ # optional <tool>=<path>|absent
27
+ # fix <check>=applied: <what changed> (--fix only)
28
+ # fix <check>=failed: <why the repair did not land> (--fix only)
29
+ # check <check>=ok: <evidence>
30
+ # check <check>=skip: <why this host is exempt>
31
+ # check <check>=fixable: <gap --fix can close>
32
+ # check <check>=human: <gap only a person at that machine can close>
33
+ # action: <check>: <the exact step to take>
34
+ # Every check line is authoritative for the moment it printed: under --fix it is
35
+ # the state after the repair attempt, so a human gap is never presented as
36
+ # fixed. Any remaining fixable or human gap, and any missing required tool,
37
+ # exits non-zero.
38
+ #
39
+ # --fix is idempotent and closes only automatable gaps: it writes and reloads
40
+ # both Firstmate-owned Aqua agents, starts the Linux workers where no Aqua agent
41
+ # applies, recreates the entrypoint symlink, and may add an owned ~/.local/bin
42
+ # wrapper for a required tool it can discover under nvm, asdf, or mise. It never
43
+ # installs packages, creates a login session, writes an auto-login password,
44
+ # changes FileVault, stores an account password, or replaces a non-Firstmate
45
+ # wrapper; those remain reported gaps.
46
+ set -eu
47
+
48
+ # Resolve this script's directory with builtins only: a host missing a required
49
+ # tool must still reach the report that names it, not die on a bare PATH.
50
+ SCRIPT_SELF=${BASH_SOURCE[0]}
51
+ SCRIPT_DIR=${SCRIPT_SELF%/*}
52
+ [ "$SCRIPT_DIR" != "$SCRIPT_SELF" ] || SCRIPT_DIR=.
53
+ SCRIPT_DIR=$(CDPATH='' cd -- "$SCRIPT_DIR" && pwd -P)
54
+ FM_ROOT="${FM_ROOT_OVERRIDE:-$(CDPATH='' cd "$SCRIPT_DIR/.." && pwd -P)}"
55
+ # shellcheck source=bin/fm-remote-job-lib.sh
56
+ . "$SCRIPT_DIR/fm-remote-job-lib.sh"
57
+ # shellcheck source=bin/fm-tasks-axi-lib.sh
58
+ . "$SCRIPT_DIR/fm-tasks-axi-lib.sh"
59
+ REQUIRED_TOOLS=(git jq herdr tasks-axi treehouse)
60
+ HARNESS_TOOLS=(claude codex opencode pi pi-signed grok kimi)
61
+ OPTIONAL_TOOLS=(tmux no-mistakes gh)
62
+ LAUNCH_AGENT_LABEL=dev.firstmate.herdr.fm-remote
63
+ # The dedicated remote-secondmate session. The user's interactive Herdr work
64
+ # remains in the separate default session, which this readiness check never
65
+ # requires or changes.
66
+ HERDR_SESSION_NAME=fm-remote
67
+ LAUNCH_AGENT_DIR="${HOME:-}/Library/LaunchAgents"
68
+ LAUNCH_AGENT_PLIST="$LAUNCH_AGENT_DIR/$LAUNCH_AGENT_LABEL.plist"
69
+ LAUNCH_AGENT_LOG_DIR="${HOME:-}/Library/Logs"
70
+ LAUNCH_AGENT_LOG="$LAUNCH_AGENT_LOG_DIR/$LAUNCH_AGENT_LABEL.log"
71
+ ENTRYPOINT_LINK="${HOME:-}/.local/bin/fm-remote-entrypoint.sh"
72
+
73
+ usage() { sed -n '2,5p' "$0" | sed 's/^# \{0,1\}//'; exit 2; }
74
+
75
+ MODE=check
76
+ case "${1:-}" in
77
+ '') ;;
78
+ --fix) MODE=fix; shift ;;
79
+ --worker-tool-probe)
80
+ [ "${FM_REMOTE_JOB_ACTIVE:-}" = 1 ] || { printf 'error: worker tool probe requires the remote job worker\n' >&2; exit 64; }
81
+ MODE='worker-tool-probe'
82
+ shift
83
+ ;;
84
+ *) usage ;;
85
+ esac
86
+ [ "$#" -eq 0 ] || usage
87
+
88
+ PLATFORM=$(fm_remote_job_platform)
89
+ UID_NUM=$(id -u 2>/dev/null) || UID_NUM=
90
+
91
+ CHECK_NAMES=()
92
+ CHECK_VALUES=()
93
+ CHECK_ACTIONS=()
94
+
95
+ record() { # <name> <value> [operator-action]
96
+ CHECK_NAMES+=("$1")
97
+ CHECK_VALUES+=("$2")
98
+ CHECK_ACTIONS+=("${3:-}")
99
+ }
100
+
101
+ check_value() { # <name>; prints the recorded value, empty when unrecorded
102
+ local i=0
103
+ while [ "$i" -lt "${#CHECK_NAMES[@]}" ]; do
104
+ if [ "${CHECK_NAMES[$i]}" = "$1" ]; then
105
+ printf '%s' "${CHECK_VALUES[$i]}"
106
+ return 0
107
+ fi
108
+ i=$((i + 1))
109
+ done
110
+ return 1
111
+ }
112
+
113
+ check_is_ok() { # <name>
114
+ case "$(check_value "$1" 2>/dev/null || true)" in ok:*) return 0 ;; esac
115
+ return 1
116
+ }
117
+
118
+ set_check() { # <name> <value> [operator-action]
119
+ local i=0
120
+ while [ "$i" -lt "${#CHECK_NAMES[@]}" ]; do
121
+ if [ "${CHECK_NAMES[$i]}" = "$1" ]; then
122
+ CHECK_VALUES[i]=$2
123
+ CHECK_ACTIONS[i]=${3:-}
124
+ return 0
125
+ fi
126
+ i=$((i + 1))
127
+ done
128
+ record "$@"
129
+ }
130
+
131
+ herdr_cli_available() {
132
+ local herdr_bin jq_bin
133
+ herdr_bin=$(command -v herdr 2>/dev/null || true)
134
+ jq_bin=$(command -v jq 2>/dev/null || true)
135
+ [ -n "$herdr_bin" ] && [ -x "$herdr_bin" ] && [ -n "$jq_bin" ] && [ -x "$jq_bin" ]
136
+ }
137
+
138
+ # The herdr adapter is the single owner of session-scoped herdr invocation and
139
+ # of starting a server, so read and start through it rather than restating
140
+ # either here. Sourced only when both tools resolve, so a bare host still
141
+ # reports its gaps instead of failing to load.
142
+ herdr_adapter_load() {
143
+ [ -z "${FM_REMOTE_DOCTOR_HERDR_LOADED:-}" ] || return 0
144
+ herdr_cli_available || return 1
145
+ [ -f "$SCRIPT_DIR/fm-backend.sh" ] && [ -f "$SCRIPT_DIR/backends/herdr.sh" ] || return 1
146
+ # shellcheck source=bin/fm-backend.sh
147
+ . "$SCRIPT_DIR/fm-backend.sh" || return 1
148
+ fm_backend_source herdr || return 1
149
+ FM_REMOTE_DOCTOR_HERDR_LOADED=1
150
+ }
151
+
152
+ herdr_server_running() {
153
+ local running
154
+ herdr_adapter_load || return 1
155
+ running=$(fm_backend_herdr_cli "$HERDR_SESSION_NAME" status --json 2>/dev/null \
156
+ | jq -r '.server.running // false' 2>/dev/null) || return 1
157
+ [ "$running" = true ]
158
+ }
159
+
160
+ launch_agent_is_aqua() {
161
+ local stripped
162
+ [ -f "$LAUNCH_AGENT_PLIST" ] && [ ! -L "$LAUNCH_AGENT_PLIST" ] || return 1
163
+ stripped=$(tr -d ' \t\r\n' < "$LAUNCH_AGENT_PLIST" 2>/dev/null) || return 1
164
+ case "$stripped" in
165
+ *'<key>LimitLoadToSessionType</key><string>Aqua</string>'*) return 0 ;;
166
+ esac
167
+ return 1
168
+ }
169
+
170
+ render_launch_agent() { # <resolved-herdr-path>
171
+ local herdr_bin=$1
172
+ cat <<XML
173
+ <?xml version="1.0" encoding="UTF-8"?>
174
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
175
+ <plist version="1.0">
176
+ <dict>
177
+ <key>Label</key>
178
+ <string>$LAUNCH_AGENT_LABEL</string>
179
+ <key>ProgramArguments</key>
180
+ <array>
181
+ <string>$herdr_bin</string>
182
+ <string>server</string>
183
+ <string>--session</string>
184
+ <string>$HERDR_SESSION_NAME</string>
185
+ </array>
186
+ <key>LimitLoadToSessionType</key>
187
+ <string>Aqua</string>
188
+ <key>RunAtLoad</key>
189
+ <true/>
190
+ <key>KeepAlive</key>
191
+ <true/>
192
+ <key>StandardOutPath</key>
193
+ <string>$LAUNCH_AGENT_LOG</string>
194
+ <key>StandardErrorPath</key>
195
+ <string>$LAUNCH_AGENT_LOG</string>
196
+ </dict>
197
+ </plist>
198
+ XML
199
+ }
200
+
201
+ launch_agent_contract_matches() {
202
+ local herdr_bin actual expected
203
+ [ -f "$LAUNCH_AGENT_PLIST" ] && [ ! -L "$LAUNCH_AGENT_PLIST" ] || return 1
204
+ herdr_bin=$(command -v herdr 2>/dev/null) || return 1
205
+ actual=$(tr -d ' \t\r\n' < "$LAUNCH_AGENT_PLIST" 2>/dev/null) || return 1
206
+ expected=$(render_launch_agent "$herdr_bin" | tr -d ' \t\r\n') || return 1
207
+ [ "$actual" = "$expected" ]
208
+ }
209
+
210
+ launch_agent_loaded_contract_matches() {
211
+ local loaded herdr_bin herdr_compact plist_compact log_compact args
212
+ herdr_bin=$(command -v herdr 2>/dev/null) || return 1
213
+ loaded=$(launchctl print "gui/$UID_NUM/$LAUNCH_AGENT_LABEL" 2>/dev/null) || return 1
214
+ loaded=$(printf '%s' "$loaded" | tr -d ' \t\r\n') || return 1
215
+ herdr_compact=$(printf '%s' "$herdr_bin" | tr -d ' \t\r\n') || return 1
216
+ plist_compact=$(printf '%s' "$LAUNCH_AGENT_PLIST" | tr -d ' \t\r\n') || return 1
217
+ log_compact=$(printf '%s' "$LAUNCH_AGENT_LOG" | tr -d ' \t\r\n') || return 1
218
+ args="arguments={$herdr_compact"'server--session'"$HERDR_SESSION_NAME}"
219
+ [[ "$loaded" == *"path=$plist_compact"* ]] || return 1
220
+ [[ "$loaded" == *"program=$herdr_compact"* ]] || return 1
221
+ [[ "$loaded" == *"$args"* ]] || return 1
222
+ [[ "$loaded" == *"stdoutpath=$log_compact"* ]] || return 1
223
+ [[ "$loaded" == *"stderrpath=$log_compact"* ]] || return 1
224
+ [[ "$loaded" == *'properties=keepalive|runatload'* ]] || return 1
225
+ }
226
+
227
+ # --- remote job and tool checks ---------------------------------------------
228
+
229
+ remote_job_existing_state() {
230
+ local root
231
+ root=${FM_REMOTE_JOB_STATE_ROOT:-${HOME:-}/.firstmate/remote-job}
232
+ root=$(fm_remote_job_canonical_existing_dir "$root") || return 1
233
+ fm_remote_job_canonical_existing_dir "$root/jobs" >/dev/null || return 1
234
+ # shellcheck disable=SC2034 # The sourceable worker helpers consume the validated state root.
235
+ FM_REMOTE_JOB_STATE=$root
236
+ }
237
+
238
+ remote_job_probe_ok() {
239
+ local ready mtime now
240
+ [ "${FM_REMOTE_JOB_ACTIVE:-}" = 1 ] && return 0
241
+ remote_job_existing_state || return 1
242
+ ready="$FM_REMOTE_JOB_STATE/worker.ready"
243
+ [ -f "$ready" ] && [ ! -L "$ready" ] || return 1
244
+ mtime=$(fm_remote_job_path_mtime "$ready" 2>/dev/null || true)
245
+ case "$mtime" in ''|*[!0-9]*) return 1 ;; esac
246
+ now=$(date +%s)
247
+ [ $((now - mtime)) -le 10 ]
248
+ }
249
+
250
+ remote_job_identity_ok() {
251
+ [ "${FM_REMOTE_JOB_ACTIVE:-}" = 1 ] && return 0
252
+ remote_job_probe_ok || return 1
253
+ fm_remote_job_worker_identity_matches "$FM_ROOT" "${HOME:-}"
254
+ }
255
+
256
+ check_remote_job_worker() {
257
+ local worker
258
+ worker="$FM_ROOT/bin/fm-remote-job-worker.sh"
259
+ if [ ! -f "$worker" ] || [ -L "$worker" ] || [ ! -x "$worker" ]; then
260
+ record remote-job-worker "human: the configured Firstmate code root has no safe remote job worker" \
261
+ "update the remote Firstmate checkout, then rerun this command with --fix"
262
+ record remote-job-worker-loaded "skip: no worker executable is available"
263
+ record remote-job-probe "skip: no worker executable is available"
264
+ return 0
265
+ fi
266
+ if [ "$PLATFORM" = darwin ]; then
267
+ fm_remote_job_launchagent_paths "${HOME:-}"
268
+ if fm_remote_job_launchagent_contract_matches "$FM_ROOT" "${HOME:-}"; then
269
+ record remote-job-worker "ok: $FM_REMOTE_JOB_LAUNCH_AGENT_PLIST matches the Firstmate-owned Aqua worker contract"
270
+ else
271
+ record remote-job-worker "fixable: $FM_REMOTE_JOB_LAUNCH_AGENT_PLIST does not match the Firstmate-owned Aqua worker contract" \
272
+ "rerun this command with --fix to write dev.firstmate.remote-job"
273
+ fi
274
+ if [ -z "$UID_NUM" ] || ! command -v launchctl >/dev/null 2>&1; then
275
+ record remote-job-worker-loaded "human: the remote job worker cannot be inspected without launchctl and an account uid" \
276
+ "restore launchctl and a readable account uid, then rerun this command"
277
+ elif fm_remote_job_launchagent_loaded "$FM_ROOT" "${HOME:-}" "$UID_NUM"; then
278
+ record remote-job-worker-loaded "ok: $FM_REMOTE_JOB_LABEL is loaded in gui/$UID_NUM"
279
+ elif check_is_ok gui-session; then
280
+ record remote-job-worker-loaded "fixable: $FM_REMOTE_JOB_LABEL is not loaded in gui/$UID_NUM" \
281
+ "rerun this command with --fix to bootstrap the worker"
282
+ else
283
+ record remote-job-worker-loaded "human: $FM_REMOTE_JOB_LABEL cannot be loaded because gui/$UID_NUM has no login session" \
284
+ "close the login-session gap first; SSH cannot create an Aqua session"
285
+ fi
286
+ else
287
+ local pid
288
+ pid=$(cat "${FM_REMOTE_JOB_STATE_ROOT:-${HOME:-}/.firstmate/remote-job}/worker.pid" 2>/dev/null || true)
289
+ if [ "${FM_REMOTE_JOB_ACTIVE:-}" = 1 ] ||
290
+ { remote_job_existing_state && case "$pid" in ''|*[!0-9]*) false ;; *) kill -0 "$pid" 2>/dev/null ;; esac; }; then
291
+ record remote-job-worker "ok: the Linux remote job worker is running"
292
+ record remote-job-worker-loaded "skip: Aqua launch agents do not apply on $PLATFORM"
293
+ else
294
+ record remote-job-worker "fixable: the Linux remote job worker is not running" \
295
+ "rerun this command with --fix to start it"
296
+ record remote-job-worker-loaded "skip: Aqua launch agents do not apply on $PLATFORM"
297
+ fi
298
+ fi
299
+ if ! remote_job_probe_ok; then
300
+ record remote-job-probe "fixable: the remote job worker has not reported a fresh probe" \
301
+ "rerun this command with --fix to restart the worker, then rerun through fm-on.sh"
302
+ elif ! remote_job_identity_ok; then
303
+ set_check remote-job-worker "fixable: the running remote job worker does not match the current Firstmate code" \
304
+ "rerun this command with --fix to reload the current worker"
305
+ record remote-job-probe "fixable: the remote job worker identity is stale, so its runtime cannot be probed" \
306
+ "rerun this command with --fix to reload the current worker"
307
+ else
308
+ record remote-job-probe "ok: the remote job worker published a fresh heartbeat"
309
+ fi
310
+ }
311
+
312
+ report_required_tools() {
313
+ local tool resolved harness
314
+ MISSING=()
315
+ for tool in "${REQUIRED_TOOLS[@]}"; do
316
+ resolved=$(command -v "$tool" 2>/dev/null || true)
317
+ if [ -n "$resolved" ] && [ -x "$resolved" ]; then
318
+ if [ "$tool" = tasks-axi ] && ! fm_tasks_axi_compatible; then
319
+ printf 'required tasks-axi=MISSING (incompatible)\n'
320
+ MISSING+=(tasks-axi)
321
+ else
322
+ printf 'required %s=%s\n' "$tool" "$resolved"
323
+ fi
324
+ else
325
+ printf 'required %s=MISSING\n' "$tool"
326
+ MISSING+=("$tool")
327
+ fi
328
+ done
329
+ for harness in "${HARNESS_TOOLS[@]}"; do
330
+ resolved=$(command -v "$harness" 2>/dev/null || true)
331
+ if [ -n "$resolved" ] && [ -x "$resolved" ]; then
332
+ printf 'required harness=%s:%s\n' "$harness" "$resolved"
333
+ return 0
334
+ fi
335
+ done
336
+ printf 'required harness=MISSING\n'
337
+ MISSING+=(harness)
338
+ }
339
+
340
+ report_required_tools_from_worker() {
341
+ local job_id probe_stdout probe_stderr probe_exit line fact name value
342
+ local expected=6 count=0 valid=1 seen=' '
343
+ if ! job_id=$(fm_remote_job_stage "${HOME:-}" "$FM_ROOT" "${FM_HOME:-}" \
344
+ fm-remote-doctor.sh --worker-tool-probe </dev/null); then
345
+ set_check remote-job-probe "fixable: the remote job worker could not accept the required-tool probe" \
346
+ "rerun this command with --fix to restart the worker"
347
+ report_required_tools
348
+ return 0
349
+ fi
350
+ if ! fm_remote_job_wait "${HOME:-}" "$job_id"; then
351
+ fm_remote_job_reap "${HOME:-}" "$job_id" 2>/dev/null || true
352
+ set_check remote-job-probe "fixable: the remote job worker did not complete the required-tool probe" \
353
+ "rerun this command with --fix to restart the worker"
354
+ report_required_tools
355
+ return 0
356
+ fi
357
+ probe_stdout=$FM_REMOTE_JOB_STDOUT
358
+ probe_stderr=$FM_REMOTE_JOB_STDERR
359
+ probe_exit=$FM_REMOTE_JOB_EXIT
360
+ MISSING=()
361
+ while IFS= read -r line; do
362
+ case "$line" in required\ *=*) ;; *) valid=0; continue ;; esac
363
+ fact=${line#required }
364
+ name=${fact%%=*}
365
+ value=${fact#*=}
366
+ case "$name" in git|jq|herdr|tasks-axi|treehouse|harness) ;; *) valid=0; continue ;; esac
367
+ case "$seen" in *" $name "*) valid=0; continue ;; esac
368
+ seen="$seen$name "
369
+ count=$((count + 1))
370
+ case "$value" in MISSING*) MISSING+=("$name") ;; '') valid=0 ;; esac
371
+ done < "$probe_stdout"
372
+ [ "$count" -eq "$expected" ] || valid=0
373
+ [ ! -s "$probe_stderr" ] || valid=0
374
+ case "$probe_exit:${#MISSING[@]}" in 0:0|1:[1-9]*) ;; *) valid=0 ;; esac
375
+ if [ "$valid" -eq 1 ]; then
376
+ cat "$probe_stdout"
377
+ set_check remote-job-probe "ok: the remote job worker completed the required-tool probe"
378
+ else
379
+ set_check remote-job-probe "fixable: the remote job worker returned an invalid required-tool probe result" \
380
+ "rerun this command with --fix to restart the worker"
381
+ report_required_tools
382
+ fi
383
+ fm_remote_job_reap "${HOME:-}" "$job_id" 2>/dev/null || true
384
+ }
385
+
386
+ wrapper_is_firstmate_owned() { # <path>
387
+ local path=$1 first second
388
+ [ -f "$path" ] && [ ! -L "$path" ] || return 1
389
+ IFS= read -r first < "$path" || return 1
390
+ IFS= read -r second < <(tail -n +2 "$path") || return 1
391
+ [ "$first" = '#!/usr/bin/env bash' ] && [ "$second" = '# Firstmate remote tool wrapper v1' ]
392
+ }
393
+
394
+ repair_tool_wrapper() { # <tool>
395
+ local tool=$1 target wrapper tmp
396
+ local resolved
397
+ resolved=$(command -v "$tool" 2>/dev/null || true)
398
+ [ -n "$resolved" ] && [ -x "$resolved" ] && return 0
399
+ target=$(fm_remote_job_manager_tool "${HOME:-}" "$tool" 2>/dev/null || true)
400
+ [ -n "$target" ] || return 1
401
+ wrapper="${HOME:-}/.local/bin/$tool"
402
+ if [ -e "$wrapper" ] || [ -L "$wrapper" ]; then
403
+ if ! wrapper_is_firstmate_owned "$wrapper"; then
404
+ fix_report "required-$tool" failed "$wrapper exists and is not Firstmate-owned"
405
+ return 1
406
+ fi
407
+ else
408
+ if ! mkdir -p "${HOME:-}/.local/bin" 2>/dev/null || [ -L "${HOME:-}/.local/bin" ]; then
409
+ fix_report "required-$tool" failed "cannot create ${HOME:-}/.local/bin"
410
+ return 1
411
+ fi
412
+ fi
413
+ tmp="${HOME:-}/.local/bin/.$tool.tmp.$$"
414
+ {
415
+ printf '%s\n' '#!/usr/bin/env bash'
416
+ printf '%s\n' '# Firstmate remote tool wrapper v1'
417
+ printf 'exec %q "$@"\n' "$target"
418
+ } > "$tmp" || { rm -f -- "$tmp"; fix_report "required-$tool" failed "cannot write $wrapper"; return 1; }
419
+ if ! chmod 0700 "$tmp" || ! mv -f -- "$tmp" "$wrapper"; then
420
+ rm -f -- "$tmp"
421
+ fix_report "required-$tool" failed "cannot publish $wrapper"
422
+ return 1
423
+ fi
424
+ fix_report "required-$tool" applied "linked the discoverable version-manager tool at $wrapper"
425
+ }
426
+
427
+ repair_required_wrappers() {
428
+ local tool resolved
429
+ for tool in "${REQUIRED_TOOLS[@]}"; do
430
+ repair_tool_wrapper "$tool" || true
431
+ done
432
+ for tool in "${HARNESS_TOOLS[@]}"; do
433
+ resolved=$(command -v "$tool" 2>/dev/null || true)
434
+ [ -z "$resolved" ] || [ ! -x "$resolved" ] || return 0
435
+ done
436
+ for tool in "${HARNESS_TOOLS[@]}"; do
437
+ fm_remote_job_manager_tool "${HOME:-}" "$tool" >/dev/null 2>&1 || continue
438
+ repair_tool_wrapper "$tool" && return 0
439
+ done
440
+ }
441
+
442
+ fix_remote_job_worker() {
443
+ if fm_remote_job_ensure_worker "$FM_ROOT" "${HOME:-}"; then
444
+ [ "$FM_REMOTE_JOB_REPAIRED" -eq 0 ] || fix_report remote-job-worker applied "installed or reloaded $FM_REMOTE_JOB_LABEL"
445
+ return 0
446
+ fi
447
+ fix_report remote-job-worker failed "${FM_REMOTE_JOB_ERROR:-the remote job worker could not start}"
448
+ return 1
449
+ }
450
+
451
+ # --- checks -----------------------------------------------------------------
452
+
453
+ check_herdr() {
454
+ local resolved
455
+ if resolved=$(command -v herdr 2>/dev/null) && [ -x "$resolved" ]; then
456
+ record herdr "ok: $resolved"
457
+ return 0
458
+ fi
459
+ record herdr "human: the herdr CLI does not resolve on the remote runtime PATH" \
460
+ "install herdr from https://herdr.dev on that account, or add a ~/.local/bin wrapper for it; a remote second mate always runs on the Herdr backend"
461
+ }
462
+
463
+ check_gui_session() {
464
+ if [ "$PLATFORM" != darwin ]; then
465
+ record gui-session "skip: no Aqua login session applies on $PLATFORM"
466
+ return 0
467
+ fi
468
+ if [ -z "$UID_NUM" ]; then
469
+ record gui-session "human: the account uid could not be read, so its login session cannot be inspected" \
470
+ "run 'id -u' on that account and report the failure; Firstmate cannot address gui/<uid> without it"
471
+ return 0
472
+ fi
473
+ if ! command -v launchctl >/dev/null 2>&1; then
474
+ record gui-session "human: launchctl does not resolve, so the login session cannot be inspected" \
475
+ "restore /bin/launchctl on that macOS account; without it no launch agent can be inspected or loaded"
476
+ return 0
477
+ fi
478
+ if launchctl print "gui/$UID_NUM" >/dev/null 2>&1; then
479
+ record gui-session "ok: gui/$UID_NUM"
480
+ return 0
481
+ fi
482
+ record gui-session "human: no Aqua login session exists for uid $UID_NUM" \
483
+ "log that account in once at the console, and enable automatic login in System Settings > Users & Groups if the machine runs headless; SSH cannot create a GUI session, and Firstmate never writes an auto-login password or changes FileVault"
484
+ }
485
+
486
+ check_launch_agent() {
487
+ if [ "$PLATFORM" != darwin ]; then
488
+ record launchagent "skip: launch agents apply only on darwin"
489
+ record launchagent-scope "skip: launch agents apply only on darwin"
490
+ record launchagent-loaded "skip: launch agents apply only on darwin"
491
+ return 0
492
+ fi
493
+ if [ -f "$LAUNCH_AGENT_PLIST" ] && [ ! -L "$LAUNCH_AGENT_PLIST" ]; then
494
+ if launch_agent_contract_matches; then
495
+ record launchagent "ok: $LAUNCH_AGENT_PLIST matches the Firstmate-owned contract"
496
+ else
497
+ record launchagent "fixable: $LAUNCH_AGENT_PLIST does not match the current Firstmate-owned contract" \
498
+ "rerun this command with --fix to rewrite its label, program arguments, session scope, restart policy, and log paths"
499
+ fi
500
+ if launch_agent_is_aqua; then
501
+ record launchagent-scope "ok: LimitLoadToSessionType=Aqua"
502
+ else
503
+ record launchagent-scope "fixable: $LAUNCH_AGENT_PLIST is not scoped to the Aqua login session" \
504
+ "rerun this command with --fix to rewrite it with LimitLoadToSessionType=Aqua"
505
+ fi
506
+ else
507
+ record launchagent "fixable: no Firstmate herdr launch agent at $LAUNCH_AGENT_PLIST" \
508
+ "rerun this command with --fix to install it"
509
+ record launchagent-scope "skip: no launch agent is installed yet"
510
+ fi
511
+ check_launch_agent_loaded
512
+ }
513
+
514
+ check_launch_agent_loaded() {
515
+ if [ -z "$UID_NUM" ] || ! command -v launchctl >/dev/null 2>&1; then
516
+ record launchagent-loaded "human: the launch agent domain gui/<uid> cannot be inspected on this account" \
517
+ "restore launchctl and a readable account uid, then rerun this command"
518
+ return 0
519
+ fi
520
+ if launchctl print "gui/$UID_NUM/$LAUNCH_AGENT_LABEL" >/dev/null 2>&1; then
521
+ if launch_agent_loaded_contract_matches; then
522
+ record launchagent-loaded "ok: gui/$UID_NUM/$LAUNCH_AGENT_LABEL matches the effective contract"
523
+ else
524
+ record launchagent-loaded "fixable: gui/$UID_NUM/$LAUNCH_AGENT_LABEL does not match the effective Firstmate-owned contract" \
525
+ "rerun this command with --fix to replace the loaded job with the current launch-agent contract"
526
+ fi
527
+ return 0
528
+ fi
529
+ if check_is_ok gui-session; then
530
+ record launchagent-loaded "fixable: $LAUNCH_AGENT_LABEL is not loaded into gui/$UID_NUM" \
531
+ "rerun this command with --fix to bootstrap and start it"
532
+ return 0
533
+ fi
534
+ record launchagent-loaded "human: $LAUNCH_AGENT_LABEL cannot be loaded because gui/$UID_NUM has no login session" \
535
+ "close the login-session gap first; a launch agent can only be bootstrapped into an existing GUI session"
536
+ }
537
+
538
+ check_herdr_server() {
539
+ if ! herdr_cli_available; then
540
+ record herdr-server "human: herdr server status cannot be read without both herdr and jq on the runtime PATH" \
541
+ "install the missing tool reported above, then rerun this command"
542
+ return 0
543
+ fi
544
+ if herdr_server_running; then
545
+ record herdr-server "ok: session $HERDR_SESSION_NAME is running"
546
+ return 0
547
+ fi
548
+ if [ "$PLATFORM" = darwin ] && ! check_is_ok gui-session; then
549
+ record herdr-server "human: the herdr server for session $HERDR_SESSION_NAME is not running and there is no GUI login session to start it in" \
550
+ "close the login-session gap first; a server started over SSH would not belong to an Aqua session"
551
+ return 0
552
+ fi
553
+ record herdr-server "fixable: the herdr server for session $HERDR_SESSION_NAME is not running" \
554
+ "rerun this command with --fix to start it"
555
+ }
556
+
557
+ check_entrypoint_link() {
558
+ local want
559
+ if [ -z "${FM_ROOT_OVERRIDE:-}" ]; then
560
+ record entrypoint-link "skip: this run did not come through the fixed remote entrypoint"
561
+ return 0
562
+ fi
563
+ want="$FM_ROOT_OVERRIDE/bin/fm-remote-entrypoint.sh"
564
+ if [ -L "$ENTRYPOINT_LINK" ] && [ "$(readlink "$ENTRYPOINT_LINK")" = "$want" ]; then
565
+ record entrypoint-link "ok: $ENTRYPOINT_LINK"
566
+ return 0
567
+ fi
568
+ if [ -e "$ENTRYPOINT_LINK" ] || [ -L "$ENTRYPOINT_LINK" ]; then
569
+ record entrypoint-link "human: $ENTRYPOINT_LINK exists but is not the symlink to $want" \
570
+ "inspect that path yourself and replace it with 'ln -sfn $want $ENTRYPOINT_LINK' if it is stale; Firstmate never overwrites a file it did not create there"
571
+ return 0
572
+ fi
573
+ record entrypoint-link "fixable: no entrypoint symlink at $ENTRYPOINT_LINK" \
574
+ "rerun this command with --fix to create it"
575
+ }
576
+
577
+ run_checks() {
578
+ CHECK_NAMES=()
579
+ CHECK_VALUES=()
580
+ CHECK_ACTIONS=()
581
+ check_herdr
582
+ check_gui_session
583
+ check_remote_job_worker
584
+ check_launch_agent
585
+ check_herdr_server
586
+ check_entrypoint_link
587
+ }
588
+
589
+ # --- repairs ----------------------------------------------------------------
590
+
591
+ fix_report() { # <check> applied|failed <text>
592
+ printf 'fix %s=%s: %s\n' "$1" "$2" "$3"
593
+ }
594
+
595
+ write_launch_agent() {
596
+ local herdr_bin tmp
597
+ if ! herdr_bin=$(command -v herdr 2>/dev/null); then
598
+ fix_report launchagent failed "herdr does not resolve, so no launch agent was written"
599
+ return 1
600
+ fi
601
+ case "$herdr_bin" in
602
+ *'&'*|*'<'*|*'>'*|*'"'*|*"'"*)
603
+ fix_report launchagent failed "the resolved herdr path contains characters that cannot be embedded in a property list: $herdr_bin"
604
+ return 1
605
+ ;;
606
+ esac
607
+ if ! mkdir -p "$LAUNCH_AGENT_DIR" 2>/dev/null; then
608
+ fix_report launchagent failed "cannot create $LAUNCH_AGENT_DIR"
609
+ return 1
610
+ fi
611
+ mkdir -p "$LAUNCH_AGENT_LOG_DIR" 2>/dev/null || true
612
+ tmp="$LAUNCH_AGENT_DIR/.$LAUNCH_AGENT_LABEL.plist.tmp.$$"
613
+ render_launch_agent "$herdr_bin" > "$tmp"
614
+ chmod 0644 "$tmp" 2>/dev/null || true
615
+ if ! mv -f -- "$tmp" "$LAUNCH_AGENT_PLIST" 2>/dev/null; then
616
+ rm -f -- "$tmp"
617
+ fix_report launchagent failed "cannot publish $LAUNCH_AGENT_PLIST"
618
+ return 1
619
+ fi
620
+ fix_report launchagent applied "wrote the Aqua-scoped $LAUNCH_AGENT_LABEL launch agent running $herdr_bin server"
621
+ }
622
+
623
+ # Reload rather than plain bootstrap so a rewritten plist replaces a stale
624
+ # in-memory copy, and kickstart so the server is running now rather than at the
625
+ # next login. Both are safe to repeat.
626
+ reload_launch_agent() { # <check-to-report-under>
627
+ local report=$1 out
628
+ [ -f "$LAUNCH_AGENT_PLIST" ] || {
629
+ fix_report "$report" failed "there is no launch agent to load at $LAUNCH_AGENT_PLIST"
630
+ return 1
631
+ }
632
+ if [ -z "$UID_NUM" ] || ! command -v launchctl >/dev/null 2>&1; then
633
+ fix_report "$report" failed "launchctl or the account uid is unavailable"
634
+ return 1
635
+ fi
636
+ launchctl bootout "gui/$UID_NUM/$LAUNCH_AGENT_LABEL" >/dev/null 2>&1 || true
637
+ if ! out=$(launchctl bootstrap "gui/$UID_NUM" "$LAUNCH_AGENT_PLIST" 2>&1); then
638
+ fix_report "$report" failed "launchctl bootstrap gui/$UID_NUM refused: ${out:-no diagnostic}"
639
+ return 1
640
+ fi
641
+ if ! out=$(launchctl kickstart -k "gui/$UID_NUM/$LAUNCH_AGENT_LABEL" 2>&1); then
642
+ fix_report "$report" failed "launchctl kickstart gui/$UID_NUM/$LAUNCH_AGENT_LABEL refused: ${out:-no diagnostic}"
643
+ return 1
644
+ fi
645
+ if ! wait_for_herdr_server; then
646
+ fix_report "$report" failed "the herdr server for session $HERDR_SESSION_NAME did not report running within 10s"
647
+ return 1
648
+ fi
649
+ fix_report "$report" applied "bootstrapped and started $LAUNCH_AGENT_LABEL in gui/$UID_NUM"
650
+ }
651
+
652
+ wait_for_herdr_server() {
653
+ local i=0
654
+ while [ "$i" -lt 20 ]; do
655
+ herdr_server_running && return 0
656
+ i=$((i + 1))
657
+ sleep 0.5
658
+ done
659
+ return 1
660
+ }
661
+
662
+ start_herdr_server() {
663
+ if ! herdr_adapter_load; then
664
+ fix_report herdr-server failed "herdr and jq must both resolve before the server can be started"
665
+ return 1
666
+ fi
667
+ if fm_backend_herdr_server_ensure "$HERDR_SESSION_NAME" >/dev/null 2>&1; then
668
+ fix_report herdr-server applied "started the herdr server for session $HERDR_SESSION_NAME"
669
+ return 0
670
+ fi
671
+ fix_report herdr-server failed "the herdr server for session $HERDR_SESSION_NAME did not come up"
672
+ return 1
673
+ }
674
+
675
+ link_entrypoint() {
676
+ local want="${FM_ROOT_OVERRIDE:-}/bin/fm-remote-entrypoint.sh"
677
+ if ! mkdir -p "$(dirname "$ENTRYPOINT_LINK")" 2>/dev/null; then
678
+ fix_report entrypoint-link failed "cannot create $(dirname "$ENTRYPOINT_LINK")"
679
+ return 1
680
+ fi
681
+ if ! ln -s "$want" "$ENTRYPOINT_LINK" 2>/dev/null; then
682
+ fix_report entrypoint-link failed "cannot create the symlink at $ENTRYPOINT_LINK"
683
+ return 1
684
+ fi
685
+ fix_report entrypoint-link applied "linked $ENTRYPOINT_LINK to $want"
686
+ }
687
+
688
+ apply_fixes() {
689
+ local i name value launch_agent_written=0 launch_agent_reloaded=0 remote_job_fixed=0
690
+ repair_required_wrappers
691
+ i=0
692
+ while [ "$i" -lt "${#CHECK_NAMES[@]}" ]; do
693
+ name=${CHECK_NAMES[$i]}
694
+ value=${CHECK_VALUES[$i]}
695
+ i=$((i + 1))
696
+ case "$value" in fixable:*) ;; *) continue ;; esac
697
+ case "$name" in
698
+ remote-job-worker|remote-job-worker-loaded|remote-job-probe)
699
+ [ "$remote_job_fixed" -eq 0 ] || continue
700
+ remote_job_fixed=1
701
+ fix_remote_job_worker || true
702
+ ;;
703
+ launchagent|launchagent-scope)
704
+ [ "$launch_agent_written" -eq 0 ] || continue
705
+ launch_agent_written=1
706
+ write_launch_agent || continue
707
+ # A freshly written plist runs nothing until it is (re)loaded, and only
708
+ # an existing GUI session can hold it.
709
+ check_is_ok gui-session || continue
710
+ launch_agent_reloaded=1
711
+ reload_launch_agent launchagent-loaded || true
712
+ ;;
713
+ launchagent-loaded)
714
+ [ "$launch_agent_reloaded" -eq 0 ] || continue
715
+ launch_agent_reloaded=1
716
+ reload_launch_agent launchagent-loaded || true
717
+ ;;
718
+ herdr-server)
719
+ # On darwin the launch agent owns the server, so restart it through
720
+ # launchd rather than starting a stray one outside the Aqua session. A
721
+ # reload earlier in this same pass has already done that.
722
+ if [ "$PLATFORM" = darwin ] && [ -f "$LAUNCH_AGENT_PLIST" ] && check_is_ok gui-session; then
723
+ [ "$launch_agent_reloaded" -eq 0 ] || continue
724
+ launch_agent_reloaded=1
725
+ reload_launch_agent herdr-server || true
726
+ continue
727
+ fi
728
+ start_herdr_server || true
729
+ ;;
730
+ entrypoint-link) link_entrypoint || true ;;
731
+ esac
732
+ done
733
+ }
734
+
735
+ # --- report -----------------------------------------------------------------
736
+
737
+ if [ "$MODE" = worker-tool-probe ]; then
738
+ report_required_tools
739
+ [ "${#MISSING[@]}" -eq 0 ]
740
+ exit
741
+ fi
742
+
743
+ printf 'mode=%s\n' "$MODE"
744
+ printf 'path=%s\n' "${PATH:-}"
745
+ if [ -n "${FM_ROOT_OVERRIDE:-}" ] && [ "${PATH%%:*}" = "$FM_ROOT_OVERRIDE/bin" ]; then
746
+ printf 'entrypoint=yes\n'
747
+ else
748
+ printf 'entrypoint=no\n'
749
+ printf 'note: not launched through the fixed remote entrypoint; the reported PATH is this caller environment.\n' >&2
750
+ fi
751
+ printf 'platform=%s\n' "$PLATFORM"
752
+
753
+ run_checks
754
+ if [ "$MODE" = fix ]; then
755
+ apply_fixes
756
+ # Re-derive every check from the host itself, so what prints below is the
757
+ # state after repair rather than the intent of a repair.
758
+ run_checks
759
+ fi
760
+
761
+ if [ "${FM_REMOTE_JOB_ACTIVE:-}" = 1 ] || ! remote_job_identity_ok; then
762
+ report_required_tools
763
+ else
764
+ report_required_tools_from_worker
765
+ fi
766
+ for tool in "${OPTIONAL_TOOLS[@]}"; do
767
+ if resolved=$(command -v "$tool" 2>/dev/null); then
768
+ printf 'optional %s=%s\n' "$tool" "$resolved"
769
+ else
770
+ printf 'optional %s=absent\n' "$tool"
771
+ fi
772
+ done
773
+
774
+ GAPS=()
775
+ i=0
776
+ while [ "$i" -lt "${#CHECK_NAMES[@]}" ]; do
777
+ printf 'check %s=%s\n' "${CHECK_NAMES[$i]}" "${CHECK_VALUES[$i]}"
778
+ case "${CHECK_VALUES[$i]}" in
779
+ fixable:*|human:*) GAPS+=("$i") ;;
780
+ esac
781
+ i=$((i + 1))
782
+ done
783
+ for i in ${GAPS[@]+"${GAPS[@]}"}; do
784
+ [ -z "${CHECK_ACTIONS[$i]}" ] || printf 'action: %s: %s\n' "${CHECK_NAMES[$i]}" "${CHECK_ACTIONS[$i]}"
785
+ done
786
+
787
+ if [ "${#MISSING[@]}" -gt 0 ]; then
788
+ printf 'error: required tools do not resolve on the remote runtime PATH: %s\n' "${MISSING[*]}" >&2
789
+ printf 'fix: install each one where it resolves on the path reported above, or put a wrapper script for it in %s/.local/bin, which is always on that PATH.\n' "${HOME:-~}" >&2
790
+ printf 'fix: tools in an unselected nvm version or outside the discovered asdf or mise paths need an absolute wrapper; see docs/remote-secondmates.md for the wrapper recipe.\n' >&2
791
+ fi
792
+ if [ "${#MISSING[@]}" -gt 0 ] || [ "${#GAPS[@]}" -gt 0 ]; then
793
+ NAMES=
794
+ for i in ${GAPS[@]+"${GAPS[@]}"}; do
795
+ NAMES="${NAMES:+$NAMES }${CHECK_NAMES[$i]}"
796
+ done
797
+ printf 'error: this host is not ready for a remote second mate%s\n' "${NAMES:+; unresolved: $NAMES}" >&2
798
+ exit 1
799
+ fi
800
+ printf 'ok: remote second-mate readiness confirmed on this host\n'