@zerwiz/ymir 0.1.4 โ†’ 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (850) hide show
  1. package/.agents/README.md +291 -0
  2. package/.agents/agents/bragi-marketer.md +111 -0
  3. package/.agents/agents/brokk.md +352 -0
  4. package/.agents/agents/forseti-reviewer.md +93 -0
  5. package/.agents/agents/frigg-consent.md +77 -0
  6. package/.agents/agents/groa-update.md +77 -0
  7. package/.agents/agents/hnoss-designer.md +69 -0
  8. package/.agents/agents/huginn-researcher.md +99 -0
  9. package/.agents/agents/jord-projects.md +78 -0
  10. package/.agents/agents/kvasir-scout.md +91 -0
  11. package/.agents/agents/mimir-planner.md +92 -0
  12. package/.agents/agents/muninn-stow.md +77 -0
  13. package/.agents/agents/saga-bearings.md +78 -0
  14. package/.agents/agents/sindri-developer.md +114 -0
  15. package/.agents/agents/snotra-documenter.md +105 -0
  16. package/.agents/agents/syn-recovery.md +78 -0
  17. package/.agents/agents/tyr-check.md +78 -0
  18. package/.agents/agents/urdh-hold.md +77 -0
  19. package/.agents/agents/volundr-smith.md +80 -0
  20. package/.agents/agents/vor-diagnostics.md +77 -0
  21. package/.agents/assets/agents/naming.md +50 -0
  22. package/.agents/assets/agents/registry.md +93 -0
  23. package/.agents/assets/agents/runtime.md +36 -0
  24. package/.agents/assets/agents/toon-tasks-cli.md +42 -0
  25. package/.agents/assets/templates/company_entity.template.md +37 -0
  26. package/.agents/backend/backends/cmux.sh +649 -0
  27. package/.agents/backend/backends/herdr-eventwait.py +157 -0
  28. package/.agents/backend/backends/herdr-workspace-move.py +114 -0
  29. package/.agents/backend/backends/herdr.sh +3386 -0
  30. package/.agents/backend/backends/orca.sh +290 -0
  31. package/.agents/backend/backends/tmux.sh +357 -0
  32. package/.agents/backend/backends/zellij.sh +700 -0
  33. package/.agents/backend/fm-afk-launch.sh +654 -0
  34. package/.agents/backend/fm-afk-return.sh +241 -0
  35. package/.agents/backend/fm-afk-start.sh +172 -0
  36. package/.agents/backend/fm-arm-command-policy.mjs +960 -0
  37. package/.agents/backend/fm-arm-pretool-check.sh +200 -0
  38. package/.agents/backend/fm-backend-hometag-lib.sh +52 -0
  39. package/.agents/backend/fm-backend.sh +981 -0
  40. package/.agents/backend/fm-backlog-handoff.sh +909 -0
  41. package/.agents/backend/fm-backlog-receive.sh +187 -0
  42. package/.agents/backend/fm-backlog-transition-lib.sh +779 -0
  43. package/.agents/backend/fm-bearings-board.sh +204 -0
  44. package/.agents/backend/fm-bearings-snapshot.sh +546 -0
  45. package/.agents/backend/fm-bootstrap.sh +1568 -0
  46. package/.agents/backend/fm-branch-outcome.sh +203 -0
  47. package/.agents/backend/fm-branch-prompt.sh +101 -0
  48. package/.agents/backend/fm-brief.sh +452 -0
  49. package/.agents/backend/fm-busy-event.sh +234 -0
  50. package/.agents/backend/fm-busy-lib.sh +986 -0
  51. package/.agents/backend/fm-captain-hold.sh +1001 -0
  52. package/.agents/backend/fm-cd-command-policy.mjs +153 -0
  53. package/.agents/backend/fm-cd-pretool-check.sh +190 -0
  54. package/.agents/backend/fm-check-lib.sh +74 -0
  55. package/.agents/backend/fm-check-register.sh +42 -0
  56. package/.agents/backend/fm-check-unregister.sh +52 -0
  57. package/.agents/backend/fm-classify-lib.sh +1770 -0
  58. package/.agents/backend/fm-claude-stop-autoarm.sh +334 -0
  59. package/.agents/backend/fm-composer-lib.sh +1416 -0
  60. package/.agents/backend/fm-config-inherit-lib.sh +1202 -0
  61. package/.agents/backend/fm-config-push.sh +254 -0
  62. package/.agents/backend/fm-control-lib.sh +251 -0
  63. package/.agents/backend/fm-control.sh +878 -0
  64. package/.agents/backend/fm-crew-state.sh +625 -0
  65. package/.agents/backend/fm-cursor-lib.sh +243 -0
  66. package/.agents/backend/fm-decision-hold.sh +232 -0
  67. package/.agents/backend/fm-doc-audience-check.sh +269 -0
  68. package/.agents/backend/fm-dod-lib.sh +67 -0
  69. package/.agents/backend/fm-ensure-agents-md.sh +253 -0
  70. package/.agents/backend/fm-extension-launch-barrier.mjs +129 -0
  71. package/.agents/backend/fm-extension.mjs +2577 -0
  72. package/.agents/backend/fm-extension.sh +16 -0
  73. package/.agents/backend/fm-ff-lib.sh +420 -0
  74. package/.agents/backend/fm-fleet-snapshot.sh +1463 -0
  75. package/.agents/backend/fm-fleet-sync.sh +458 -0
  76. package/.agents/backend/fm-fleet-view.sh +96 -0
  77. package/.agents/backend/fm-gate-refuse-lib.sh +102 -0
  78. package/.agents/backend/fm-guard.sh +242 -0
  79. package/.agents/backend/fm-harness.sh +195 -0
  80. package/.agents/backend/fm-herdr-ci-cleanup.sh +115 -0
  81. package/.agents/backend/fm-herdr-lab.sh +346 -0
  82. package/.agents/backend/fm-herdr-session-cleanup.sh +337 -0
  83. package/.agents/backend/fm-home-seed.sh +984 -0
  84. package/.agents/backend/fm-home-summary-refresh.sh +255 -0
  85. package/.agents/backend/fm-hook-host-lib.sh +36 -0
  86. package/.agents/backend/fm-inactive-reconcile.sh +531 -0
  87. package/.agents/backend/fm-inbox.sh +399 -0
  88. package/.agents/backend/fm-install-actionlint.sh +84 -0
  89. package/.agents/backend/fm-install-herdr.sh +96 -0
  90. package/.agents/backend/fm-install-shellcheck.sh +84 -0
  91. package/.agents/backend/fm-install-treehouse.sh +95 -0
  92. package/.agents/backend/fm-kimi-turnend-hook.sh +276 -0
  93. package/.agents/backend/fm-lease-lib.sh +218 -0
  94. package/.agents/backend/fm-lease.sh +189 -0
  95. package/.agents/backend/fm-line-cap-lib.sh +51 -0
  96. package/.agents/backend/fm-lint-workflows.sh +137 -0
  97. package/.agents/backend/fm-lint.sh +591 -0
  98. package/.agents/backend/fm-lock-lib.sh +104 -0
  99. package/.agents/backend/fm-lock.sh +107 -0
  100. package/.agents/backend/fm-marker-lib.sh +12 -0
  101. package/.agents/backend/fm-merge-local.sh +74 -0
  102. package/.agents/backend/fm-merge-outcome-lib.sh +138 -0
  103. package/.agents/backend/fm-nm-run-lib.sh +124 -0
  104. package/.agents/backend/fm-on.sh +125 -0
  105. package/.agents/backend/fm-operational-input.sh +253 -0
  106. package/.agents/backend/fm-peek.sh +46 -0
  107. package/.agents/backend/fm-pending-reply-lib.sh +1409 -0
  108. package/.agents/backend/fm-pr-check.sh +135 -0
  109. package/.agents/backend/fm-pr-lib.sh +1016 -0
  110. package/.agents/backend/fm-pr-merge.sh +707 -0
  111. package/.agents/backend/fm-pr-poll.sh +110 -0
  112. package/.agents/backend/fm-primary-scope-lib.sh +33 -0
  113. package/.agents/backend/fm-procevent-extension-capture.pl +259 -0
  114. package/.agents/backend/fm-procevent-lavish.sh +628 -0
  115. package/.agents/backend/fm-procevent-lib.sh +892 -0
  116. package/.agents/backend/fm-procevent-quota.sh +290 -0
  117. package/.agents/backend/fm-procevent-remote-reply.sh +577 -0
  118. package/.agents/backend/fm-procevent-when.sh +504 -0
  119. package/.agents/backend/fm-procevent.sh +1466 -0
  120. package/.agents/backend/fm-project-mode.sh +92 -0
  121. package/.agents/backend/fm-project-origin-lib.sh +180 -0
  122. package/.agents/backend/fm-promote.sh +282 -0
  123. package/.agents/backend/fm-public-followup-emit.sh +260 -0
  124. package/.agents/backend/fm-public-followup-lib.sh +398 -0
  125. package/.agents/backend/fm-public-followup.sh +1330 -0
  126. package/.agents/backend/fm-push-transition-lib.sh +168 -0
  127. package/.agents/backend/fm-quota-axi-lib.sh +93 -0
  128. package/.agents/backend/fm-quota-choose.sh +384 -0
  129. package/.agents/backend/fm-remote-delta-read.sh +189 -0
  130. package/.agents/backend/fm-remote-doctor.sh +800 -0
  131. package/.agents/backend/fm-remote-entrypoint.sh +193 -0
  132. package/.agents/backend/fm-remote-file.sh +234 -0
  133. package/.agents/backend/fm-remote-home-provision.sh +259 -0
  134. package/.agents/backend/fm-remote-home-seed.sh +259 -0
  135. package/.agents/backend/fm-remote-inherit-push.sh +90 -0
  136. package/.agents/backend/fm-remote-inherit.sh +179 -0
  137. package/.agents/backend/fm-remote-job-lib.sh +1241 -0
  138. package/.agents/backend/fm-remote-job-reap-orphans.sh +137 -0
  139. package/.agents/backend/fm-remote-job-worker.sh +1124 -0
  140. package/.agents/backend/fm-remote-readiness-lib.sh +44 -0
  141. package/.agents/backend/fm-remote-secondmate-control.sh +340 -0
  142. package/.agents/backend/fm-review-diff.sh +158 -0
  143. package/.agents/backend/fm-secondmate-charter-lib.sh +44 -0
  144. package/.agents/backend/fm-secondmate-nudge-lib.sh +68 -0
  145. package/.agents/backend/fm-secondmate-parent-lib.sh +70 -0
  146. package/.agents/backend/fm-secondmate-reconcile.sh +371 -0
  147. package/.agents/backend/fm-secondmate-registry-lib.sh +311 -0
  148. package/.agents/backend/fm-secondmate-report.sh +88 -0
  149. package/.agents/backend/fm-send.sh +1059 -0
  150. package/.agents/backend/fm-session-lock-lib.sh +176 -0
  151. package/.agents/backend/fm-session-start.sh +970 -0
  152. package/.agents/backend/fm-sessionstart-cursor.sh +40 -0
  153. package/.agents/backend/fm-sessionstart-nudge.sh +45 -0
  154. package/.agents/backend/fm-sessionstart-run.sh +145 -0
  155. package/.agents/backend/fm-spawn.sh +3153 -0
  156. package/.agents/backend/fm-startup-memory-budget-lib.sh +224 -0
  157. package/.agents/backend/fm-startup-memory-budget.sh +94 -0
  158. package/.agents/backend/fm-startup-network.sh +642 -0
  159. package/.agents/backend/fm-stow-cascade.sh +251 -0
  160. package/.agents/backend/fm-subagent-pretool-check.sh +207 -0
  161. package/.agents/backend/fm-supervise-daemon.sh +1732 -0
  162. package/.agents/backend/fm-supervision-instructions.sh +215 -0
  163. package/.agents/backend/fm-supervision-lib.sh +90 -0
  164. package/.agents/backend/fm-supervisor-target-lib.sh +78 -0
  165. package/.agents/backend/fm-tangle-lib.sh +53 -0
  166. package/.agents/backend/fm-task-inbox-lib.sh +402 -0
  167. package/.agents/backend/fm-tasks-axi-lib.sh +123 -0
  168. package/.agents/backend/fm-teardown.sh +2922 -0
  169. package/.agents/backend/fm-test-isolation-proof.sh +588 -0
  170. package/.agents/backend/fm-test-run.sh +2191 -0
  171. package/.agents/backend/fm-timeout-lib.sh +141 -0
  172. package/.agents/backend/fm-timing-lib.sh +179 -0
  173. package/.agents/backend/fm-tmux-lib.sh +291 -0
  174. package/.agents/backend/fm-tool-update-check.sh +898 -0
  175. package/.agents/backend/fm-trace-context-lib.sh +227 -0
  176. package/.agents/backend/fm-transition-lib.sh +103 -0
  177. package/.agents/backend/fm-turnend-guard-cursor.sh +391 -0
  178. package/.agents/backend/fm-turnend-guard-grok.sh +90 -0
  179. package/.agents/backend/fm-turnend-guard.sh +432 -0
  180. package/.agents/backend/fm-update.sh +110 -0
  181. package/.agents/backend/fm-vendor-auth-probe.sh +190 -0
  182. package/.agents/backend/fm-voice-client.py +1373 -0
  183. package/.agents/backend/fm-voice-relay.py +1256 -0
  184. package/.agents/backend/fm-wake-drain.sh +592 -0
  185. package/.agents/backend/fm-wake-grant.sh +127 -0
  186. package/.agents/backend/fm-wake-lib.sh +1849 -0
  187. package/.agents/backend/fm-watch-arm.sh +602 -0
  188. package/.agents/backend/fm-watch-checkpoint.sh +109 -0
  189. package/.agents/backend/fm-watch.sh +1962 -0
  190. package/.agents/backend/fm-x-dismiss.sh +116 -0
  191. package/.agents/backend/fm-x-followup.sh +286 -0
  192. package/.agents/backend/fm-x-lib.sh +1000 -0
  193. package/.agents/backend/fm-x-link.sh +234 -0
  194. package/.agents/backend/fm-x-poll.sh +185 -0
  195. package/.agents/backend/fm-x-reply.sh +385 -0
  196. package/.agents/backend/fm_voice_frame.py +166 -0
  197. package/.agents/backend/fm_voice_records.py +574 -0
  198. package/.agents/backend/model-bridge.py +290 -0
  199. package/.agents/backend/opencode-go-bridge.py +30 -0
  200. package/.agents/bus/README.md +12 -0
  201. package/.agents/bus/messages.json +1 -0
  202. package/.agents/config/agents.machine.example.yaml +16 -0
  203. package/.agents/config/agents.yaml +50 -0
  204. package/.agents/config/agents.yaml.example +72 -0
  205. package/.agents/config/crew-dispatch.json +22 -0
  206. package/.agents/config/cron.yaml +9 -0
  207. package/.agents/config/eindri-dispatch.json +67 -0
  208. package/.agents/config/eindri-harness +1 -0
  209. package/.agents/config/startup-memory-budget +1 -0
  210. package/.agents/config/tailscale-sync.yaml +27 -0
  211. package/.agents/filebrowser/.filebrowser.json +6 -0
  212. package/.agents/filebrowser/README.md +11 -0
  213. package/.agents/gateway/README.md +12 -0
  214. package/.agents/github/README.md +15 -0
  215. package/.agents/github/webhooks/.gitkeep +0 -0
  216. package/.agents/github/workflows/.gitkeep +0 -0
  217. package/.agents/harness/opencode/plugins/lib/rodd-operational-input.js +37 -0
  218. package/.agents/harness/opencode/plugins/package.json +4 -0
  219. package/.agents/harness/opencode/plugins/saga-sessionstart.js +77 -0
  220. package/.agents/harness/opencode/plugins/syn-cd-check.js +61 -0
  221. package/.agents/harness/opencode/plugins/syn-pretool-check.js +68 -0
  222. package/.agents/harness/opencode/plugins/syn-turnend-guard.js +105 -0
  223. package/.agents/harness/opencode/plugins/syn-watch-arm.js +521 -0
  224. package/.agents/memory/README.md +46 -0
  225. package/.agents/memory/kaia.engram +0 -0
  226. package/.agents/memory/kaia.engram-shm +0 -0
  227. package/.agents/memory/kaia.engram-wal +0 -0
  228. package/.agents/memory/runes_audit.md +5 -0
  229. package/.agents/memory/well/episodes.jsonl +367 -0
  230. package/.agents/memory/well/workspace.jsonl +27 -0
  231. package/.agents/migrations/0001-hodd-layout.sh +38 -0
  232. package/.agents/migrations/0002-a2a-mcp.sh +27 -0
  233. package/.agents/migrations/0003-private-data-separation.sh +111 -0
  234. package/.agents/migrations/0004-hoard-and-realms.sh +104 -0
  235. package/.agents/sandbox/Dockerfile.utgard +19 -0
  236. package/.agents/sandbox/README.md +14 -0
  237. package/.agents/sandbox/utgard.config.json +14 -0
  238. package/.agents/skills/README.md +59 -0
  239. package/.agents/skills/bragi-marketing/README.md +3 -0
  240. package/.agents/skills/bragi-marketing/SKILL.md +82 -0
  241. package/.agents/skills/eindri-homes/README.md +3 -0
  242. package/.agents/skills/eindri-homes/SKILL.md +291 -0
  243. package/.agents/skills/eindri-homes/assets/control-plane.md +122 -0
  244. package/.agents/skills/eindri-homes/assets/dispatch.md +80 -0
  245. package/.agents/skills/frigg-consent/README.md +3 -0
  246. package/.agents/skills/frigg-consent/SKILL.md +56 -0
  247. package/.agents/skills/galdr-ymirsystem/README.md +3 -0
  248. package/.agents/skills/galdr-ymirsystem/SKILL.md +158 -0
  249. package/.agents/skills/galdr-ymirsystem/assets/README.md +74 -0
  250. package/.agents/skills/galdr-ymirsystem/assets/brokk-distro-runtime.md +390 -0
  251. package/.agents/skills/galdr-ymirsystem/assets/build-method.md +113 -0
  252. package/.agents/skills/galdr-ymirsystem/assets/build-tool-categories.md +178 -0
  253. package/.agents/skills/galdr-ymirsystem/assets/eindri-orchestration.md +518 -0
  254. package/.agents/skills/galdr-ymirsystem/assets/eindri-profiles.md +136 -0
  255. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +673 -0
  256. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/claude-code.md +197 -0
  257. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/codex.md +191 -0
  258. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/cursor.md +193 -0
  259. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/opencode.md +262 -0
  260. package/.agents/skills/galdr-ymirsystem/assets/harness-integration/pi.md +295 -0
  261. package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +496 -0
  262. package/.agents/skills/galdr-ymirsystem/assets/installation.md +571 -0
  263. package/.agents/skills/galdr-ymirsystem/assets/local-models/HOST-DATA.example.md +72 -0
  264. package/.agents/skills/galdr-ymirsystem/assets/local-models.md +274 -0
  265. package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +161 -0
  266. package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +377 -0
  267. package/.agents/skills/galdr-ymirsystem/assets/norse-naming.md +325 -0
  268. package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +129 -0
  269. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/einherjar-spawn.schema.json +81 -0
  270. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/herdr-profile.toml +75 -0
  271. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +96 -0
  272. package/.agents/skills/galdr-ymirsystem/assets/pi-boot/supervision-tree.yml +163 -0
  273. package/.agents/skills/galdr-ymirsystem/assets/pi-boot-guide.md +58 -0
  274. package/.agents/skills/galdr-ymirsystem/assets/porting-upstream-to-norse.md +301 -0
  275. package/.agents/skills/galdr-ymirsystem/assets/principles.md +385 -0
  276. package/.agents/skills/galdr-ymirsystem/assets/reference-adoption.md +99 -0
  277. package/.agents/skills/galdr-ymirsystem/assets/registry.md +379 -0
  278. package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +463 -0
  279. package/.agents/skills/galdr-ymirsystem/assets/runtime-components.md +553 -0
  280. package/.agents/skills/galdr-ymirsystem/assets/smidja.md +175 -0
  281. package/.agents/skills/galdr-ymirsystem/schemas/toon-schemas.md +190 -0
  282. package/.agents/skills/galdr-ymirsystem/scripts/README.md +45 -0
  283. package/.agents/skills/galdr-ymirsystem/scripts/bench-one.sh +248 -0
  284. package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +360 -0
  285. package/.agents/skills/galdr-ymirsystem/scripts/gpu-sample.sh +43 -0
  286. package/.agents/skills/galdr-ymirsystem/scripts/stop-all.sh +34 -0
  287. package/.agents/skills/galdr-ymirsystem/scripts/toon-check.py +188 -0
  288. package/.agents/skills/gjallarhorn-relay/README.md +3 -0
  289. package/.agents/skills/gjallarhorn-relay/SKILL.md +283 -0
  290. package/.agents/skills/groa-update/SKILL.md +70 -0
  291. package/.agents/skills/hamr-adapters/README.md +3 -0
  292. package/.agents/skills/hamr-adapters/SKILL.md +123 -0
  293. package/.agents/skills/hamr-adapters/references/common/control-and-recovery.md +37 -0
  294. package/.agents/skills/hamr-adapters/references/common/dispatch.md +32 -0
  295. package/.agents/skills/hamr-adapters/references/common/model-and-effort.md +42 -0
  296. package/.agents/skills/hamr-adapters/references/common/primary-hooks.md +40 -0
  297. package/.agents/skills/hamr-adapters/references/harness/claude.md +55 -0
  298. package/.agents/skills/hamr-adapters/references/harness/codex.md +43 -0
  299. package/.agents/skills/hamr-adapters/references/harness/cursor.md +75 -0
  300. package/.agents/skills/hamr-adapters/references/harness/grok.md +69 -0
  301. package/.agents/skills/hamr-adapters/references/harness/kimi.md +51 -0
  302. package/.agents/skills/hamr-adapters/references/harness/muse.md +70 -0
  303. package/.agents/skills/hamr-adapters/references/harness/opencode.md +42 -0
  304. package/.agents/skills/hamr-adapters/references/harness/pi.md +56 -0
  305. package/.agents/skills/herdr-panes/README.md +3 -0
  306. package/.agents/skills/herdr-panes/SKILL.md +92 -0
  307. package/.agents/skills/herdr-panes/assets/herdr-backend.md +346 -0
  308. package/.agents/skills/herdr-panes/assets/tmux-backend.md +115 -0
  309. package/.agents/skills/hnoss-design/DESIGN.md +19 -0
  310. package/.agents/skills/hnoss-design/README.md +3 -0
  311. package/.agents/skills/hnoss-design/SKILL.md +83 -0
  312. package/.agents/skills/hvild-afk/README.md +3 -0
  313. package/.agents/skills/hvild-afk/SKILL.md +241 -0
  314. package/.agents/skills/jord-projects/README.md +3 -0
  315. package/.agents/skills/jord-projects/SKILL.md +92 -0
  316. package/.agents/skills/lifecycle/SKILL.md +56 -0
  317. package/.agents/skills/lifecycle/smoke_test.sh +52 -0
  318. package/.agents/skills/lifecycle/start.sh +21 -0
  319. package/.agents/skills/lifecycle/status.sh +35 -0
  320. package/.agents/skills/lifecycle/stop.sh +16 -0
  321. package/.agents/skills/muninn-stow/README.md +3 -0
  322. package/.agents/skills/muninn-stow/SKILL.md +309 -0
  323. package/.agents/skills/no-mistakes/SKILL.md +379 -0
  324. package/.agents/skills/nornir-schedule/README.md +3 -0
  325. package/.agents/skills/nornir-schedule/SKILL.md +25 -0
  326. package/.agents/skills/nornir-schedule/assets/events.md +137 -0
  327. package/.agents/skills/nornir-schedule/assets/quota.md +131 -0
  328. package/.agents/skills/nsr-compliance/README.md +3 -0
  329. package/.agents/skills/nsr-compliance/SKILL.md +29 -0
  330. package/.agents/skills/nsr-compliance/assets/nsr/README.md +40 -0
  331. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/README.md +15 -0
  332. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/git-workflow.md +18 -0
  333. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/security.md +22 -0
  334. package/.agents/skills/nsr-compliance/assets/nsr/assets/RULES/tech-stack.md +8 -0
  335. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/SKILL.md +71 -0
  336. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/config/core_four.yaml +16 -0
  337. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_danger.sh +102 -0
  338. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/check_wiring.sh +69 -0
  339. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/validate_code.sh +29 -0
  340. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/gates/verify_docs.py +66 -0
  341. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/generate.sh +109 -0
  342. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/result_envelope.json +14 -0
  343. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/envelopes/task_envelope.json +20 -0
  344. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/harness/runner.py +303 -0
  345. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/telemetry/logger.py +112 -0
  346. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/README.md +18 -0
  347. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/config/README.md +10 -0
  348. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/README.md +12 -0
  349. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_env.sh +23 -0
  350. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_paths.sh +20 -0
  351. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/gates/check_platform.sh +23 -0
  352. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/README.md +11 -0
  353. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/harness/envelopes/README.md +10 -0
  354. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/README.md +10 -0
  355. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/installer/install.sh +125 -0
  356. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/NSRcompliance/templates/compliance/telemetry/README.md +11 -0
  357. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/README.md +20 -0
  358. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/README.md +36 -0
  359. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/features/SKILL-template.md +14 -0
  360. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/README.md +25 -0
  361. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/SKILL.md +13 -0
  362. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/create_branch.sh +6 -0
  363. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/safe_commit.sh +9 -0
  364. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/git_ops/sync_upstream.sh +6 -0
  365. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/README.md +27 -0
  366. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/SKILL.md +15 -0
  367. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/smoke_test.sh +12 -0
  368. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/start.sh +19 -0
  369. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/status.sh +12 -0
  370. package/.agents/skills/nsr-compliance/assets/nsr/assets/agents_skills/lifecycle/stop.sh +15 -0
  371. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/README.md +18 -0
  372. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/README.md +10 -0
  373. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/config/core_four.yaml +13 -0
  374. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/README.md +12 -0
  375. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_danger.sh +102 -0
  376. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_env.sh +23 -0
  377. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_paths.sh +20 -0
  378. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_platform.sh +23 -0
  379. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/gates/check_wiring.sh +69 -0
  380. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/README.md +11 -0
  381. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/README.md +10 -0
  382. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/result_envelope.json +14 -0
  383. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/envelopes/task_envelope.json +20 -0
  384. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/harness/runner.py +303 -0
  385. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/README.md +10 -0
  386. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/installer/install.sh +125 -0
  387. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/README.md +11 -0
  388. package/.agents/skills/nsr-compliance/assets/nsr/assets/compliance/telemetry/logger.py +112 -0
  389. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/README.md +14 -0
  390. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/api.md +17 -0
  391. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/compliance-wiring.md +155 -0
  392. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/BEST_PRACTICES/frontend.md +15 -0
  393. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/README.md +11 -0
  394. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/README.md +23 -0
  395. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/README.md +16 -0
  396. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/clients/template-README.md +11 -0
  397. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/deploy.sh +49 -0
  398. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/README.md +12 -0
  399. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/development.env.example +17 -0
  400. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/production.env.example +17 -0
  401. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/envs/staging.env.example +17 -0
  402. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/README.md +11 -0
  403. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/CI_CD/deployment/tenants/template.env.example +8 -0
  404. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/README.md +26 -0
  405. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/agent.md +7 -0
  406. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/developers/dev-1.md +20 -0
  407. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/linux.md +9 -0
  408. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/macos.md +10 -0
  409. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/shared.md +19 -0
  410. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/DEVELOPER_SETUP/windows.md +14 -0
  411. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/README.md +25 -0
  412. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/_template.md +41 -0
  413. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/HOSTING/hosting-1.md +41 -0
  414. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/README.md +21 -0
  415. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/README.md +15 -0
  416. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/deployment.md +19 -0
  417. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/disaster-recovery.md +15 -0
  418. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/RUNBOOK/ops-tasks.md +14 -0
  419. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/features/README.md +16 -0
  420. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/project-skills.md +146 -0
  421. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/README.md +11 -0
  422. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/research/software-compliance-research.md +269 -0
  423. package/.agents/skills/nsr-compliance/assets/nsr/assets/docs/working-with-agents.md +260 -0
  424. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/AGENTS.md +38 -0
  425. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/ARCHITECTURE.md +36 -0
  426. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/BEST_PRACTICES.md +27 -0
  427. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/CI_CD.md +23 -0
  428. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/FEATURES.md +15 -0
  429. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/README.md +22 -0
  430. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/RULES.md +37 -0
  431. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/STRUCTURE.md +45 -0
  432. package/.agents/skills/nsr-compliance/assets/nsr/assets/root/TECH_STACK.md +28 -0
  433. package/.agents/skills/nsr-compliance/assets/nsr/scaffold-spec.md +63 -0
  434. package/.agents/skills/nsr-compliance/assets/nsr/scripts/scaffold.sh +103 -0
  435. package/.agents/skills/nsr-compliance/assets/nsr/scripts/validate.sh +52 -0
  436. package/.agents/skills/nsr-compliance/assets/nsrcompliance/SKILL.md +71 -0
  437. package/.agents/skills/nsr-compliance/assets/nsrcompliance/config/core_four.yaml +16 -0
  438. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_danger.sh +102 -0
  439. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/check_wiring.sh +69 -0
  440. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/validate_code.sh +29 -0
  441. package/.agents/skills/nsr-compliance/assets/nsrcompliance/gates/verify_docs.py +66 -0
  442. package/.agents/skills/nsr-compliance/assets/nsrcompliance/generate.sh +109 -0
  443. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/result_envelope.json +14 -0
  444. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/envelopes/task_envelope.json +20 -0
  445. package/.agents/skills/nsr-compliance/assets/nsrcompliance/harness/runner.py +303 -0
  446. package/.agents/skills/nsr-compliance/assets/nsrcompliance/telemetry/logger.py +112 -0
  447. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/README.md +18 -0
  448. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/config/README.md +10 -0
  449. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/README.md +12 -0
  450. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_env.sh +23 -0
  451. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_paths.sh +20 -0
  452. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/gates/check_platform.sh +23 -0
  453. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/README.md +11 -0
  454. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/harness/envelopes/README.md +10 -0
  455. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/README.md +10 -0
  456. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/installer/install.sh +125 -0
  457. package/.agents/skills/nsr-compliance/assets/nsrcompliance/templates/compliance/telemetry/README.md +11 -0
  458. package/.agents/skills/pr-ops/README.md +3 -0
  459. package/.agents/skills/pr-ops/SKILL.md +109 -0
  460. package/.agents/skills/ratatoskr-a2a/README.md +3 -0
  461. package/.agents/skills/ratatoskr-a2a/SKILL.md +148 -0
  462. package/.agents/skills/rules-check-drift/SKILL.md +81 -0
  463. package/.agents/skills/saga-bearings/README.md +3 -0
  464. package/.agents/skills/saga-bearings/SKILL.md +26 -0
  465. package/.agents/skills/saga-bearings/assets/bearings.md +161 -0
  466. package/.agents/skills/saga-bearings/assets/board-template.html +731 -0
  467. package/.agents/skills/saga-bearings/assets/recap.md +56 -0
  468. package/.agents/skills/syn-recovery/README.md +3 -0
  469. package/.agents/skills/syn-recovery/SKILL.md +54 -0
  470. package/.agents/skills/tyr-check/README.md +3 -0
  471. package/.agents/skills/tyr-check/SKILL.md +218 -0
  472. package/.agents/skills/urdh-hold/README.md +3 -0
  473. package/.agents/skills/urdh-hold/SKILL.md +25 -0
  474. package/.agents/skills/urdh-hold/assets/decisions.md +15 -0
  475. package/.agents/skills/urdh-hold/assets/hold.md +54 -0
  476. package/.agents/skills/vor-diagnostics/README.md +3 -0
  477. package/.agents/skills/vor-diagnostics/SKILL.md +68 -0
  478. package/.agents/skills/ymir-host/README.md +3 -0
  479. package/.agents/skills/ymir-host/SKILL.md +34 -0
  480. package/.agents/skills/ymir-host/assets/desktop.md +36 -0
  481. package/.agents/skills/ymir-host/assets/omarchy.md +297 -0
  482. package/.agents/skills/ymir-host/assets/runbooks.md +15 -0
  483. package/.agents/skills/ymir-host/assets/thjazi.md +220 -0
  484. package/.agents/skills/ymir-host/assets/update.md +64 -0
  485. package/.agents/tests/assets/board-render-harness.mjs +117 -0
  486. package/.agents/tests/cmux-test-safety.sh +51 -0
  487. package/.agents/tests/fixtures.sh +291 -0
  488. package/.agents/tests/fm-afk-inject-e2e.test.sh +428 -0
  489. package/.agents/tests/fm-afk-inject-herdr-e2e.test.sh +536 -0
  490. package/.agents/tests/fm-afk-launch.test.sh +961 -0
  491. package/.agents/tests/fm-afk-pi-herdr-return-e2e.test.sh +297 -0
  492. package/.agents/tests/fm-afk-return.test.sh +283 -0
  493. package/.agents/tests/fm-arm-pretool-check.test.sh +482 -0
  494. package/.agents/tests/fm-ask-user-authority.test.sh +42 -0
  495. package/.agents/tests/fm-backend-autodetect-smoke.test.sh +176 -0
  496. package/.agents/tests/fm-backend-cmux-smoke.test.sh +188 -0
  497. package/.agents/tests/fm-backend-cmux.test.sh +1166 -0
  498. package/.agents/tests/fm-backend-herdr-eventwait-smoke.test.sh +136 -0
  499. package/.agents/tests/fm-backend-herdr-eventwait.test.py +106 -0
  500. package/.agents/tests/fm-backend-herdr-focus-flash-e2e.test.sh +409 -0
  501. package/.agents/tests/fm-backend-herdr-launcher-workspace-e2e.test.sh +437 -0
  502. package/.agents/tests/fm-backend-herdr-presentation-e2e.test.sh +1424 -0
  503. package/.agents/tests/fm-backend-herdr-prune-safety-e2e.test.sh +180 -0
  504. package/.agents/tests/fm-backend-herdr-respawn-idem-e2e.test.sh +182 -0
  505. package/.agents/tests/fm-backend-herdr-smoke.test.sh +355 -0
  506. package/.agents/tests/fm-backend-herdr-workspace-per-home-e2e.test.sh +251 -0
  507. package/.agents/tests/fm-backend-herdr.test.sh +4606 -0
  508. package/.agents/tests/fm-backend-orca.test.sh +1357 -0
  509. package/.agents/tests/fm-backend-tmux-smoke.test.sh +173 -0
  510. package/.agents/tests/fm-backend-zellij-smoke.test.sh +205 -0
  511. package/.agents/tests/fm-backend-zellij.test.sh +1360 -0
  512. package/.agents/tests/fm-backend.test.sh +1142 -0
  513. package/.agents/tests/fm-backlog-atomicity.test.sh +2302 -0
  514. package/.agents/tests/fm-backlog-handoff.test.sh +1360 -0
  515. package/.agents/tests/fm-bearings-board-render.test.sh +135 -0
  516. package/.agents/tests/fm-bearings-board.test.sh +414 -0
  517. package/.agents/tests/fm-bearings-snapshot.test.sh +1990 -0
  518. package/.agents/tests/fm-bootstrap-network-parallel.test.sh +316 -0
  519. package/.agents/tests/fm-bootstrap.test.sh +1178 -0
  520. package/.agents/tests/fm-branch-supervision.test.sh +552 -0
  521. package/.agents/tests/fm-brief.test.sh +785 -0
  522. package/.agents/tests/fm-busy-adapter-wiring.test.sh +324 -0
  523. package/.agents/tests/fm-busy-state.test.sh +465 -0
  524. package/.agents/tests/fm-calm-pi-extension.test.sh +3979 -0
  525. package/.agents/tests/fm-captain-hold-lifecycle.test.sh +1187 -0
  526. package/.agents/tests/fm-cd-pretool-check.test.sh +400 -0
  527. package/.agents/tests/fm-check-unregister.test.sh +198 -0
  528. package/.agents/tests/fm-classify-corr-token.test.sh +543 -0
  529. package/.agents/tests/fm-classify-decision-key.test.sh +340 -0
  530. package/.agents/tests/fm-claude-stop-autoarm-live-e2e.test.sh +164 -0
  531. package/.agents/tests/fm-claude-stop-autoarm.test.sh +1190 -0
  532. package/.agents/tests/fm-cmux-claude-composer-live-e2e.test.sh +110 -0
  533. package/.agents/tests/fm-codex-continuity-live-e2e.test.sh +55 -0
  534. package/.agents/tests/fm-composer-ghost.test.sh +716 -0
  535. package/.agents/tests/fm-composer-lib.test.sh +666 -0
  536. package/.agents/tests/fm-composer-matrix-live-e2e.test.sh +220 -0
  537. package/.agents/tests/fm-control-herdr-smoke.test.sh +149 -0
  538. package/.agents/tests/fm-control-relaunch.test.sh +1530 -0
  539. package/.agents/tests/fm-control.test.sh +910 -0
  540. package/.agents/tests/fm-crew-state.test.sh +1610 -0
  541. package/.agents/tests/fm-cursor-harness.test.sh +404 -0
  542. package/.agents/tests/fm-cursor-primary-live-e2e.test.sh +217 -0
  543. package/.agents/tests/fm-cursor-primary.test.sh +708 -0
  544. package/.agents/tests/fm-daemon.test.sh +2740 -0
  545. package/.agents/tests/fm-documentation-audiences.test.sh +141 -0
  546. package/.agents/tests/fm-ensure-agents-md.test.sh +371 -0
  547. package/.agents/tests/fm-extension-binding.test.sh +2187 -0
  548. package/.agents/tests/fm-fleet-snapshot-view.test.sh +816 -0
  549. package/.agents/tests/fm-fleet-sync.test.sh +721 -0
  550. package/.agents/tests/fm-gate-refuse.test.sh +356 -0
  551. package/.agents/tests/fm-gitignore-config.test.sh +89 -0
  552. package/.agents/tests/fm-gotmp.test.sh +230 -0
  553. package/.agents/tests/fm-grok-continuity-live-e2e.test.sh +112 -0
  554. package/.agents/tests/fm-grok-harness.test.sh +117 -0
  555. package/.agents/tests/fm-grok-stop-live-e2e.test.sh +219 -0
  556. package/.agents/tests/fm-guard-stale-banner.test.sh +709 -0
  557. package/.agents/tests/fm-harness-adapter-instructions-live-e2e.test.sh +134 -0
  558. package/.agents/tests/fm-harness-adapter-references.test.sh +30 -0
  559. package/.agents/tests/fm-harness-liveness-drift-live-e2e.test.sh +151 -0
  560. package/.agents/tests/fm-herdr-lab.test.sh +243 -0
  561. package/.agents/tests/fm-herdr-session-cleanup-e2e.test.sh +146 -0
  562. package/.agents/tests/fm-herdr-session-cleanup.test.sh +329 -0
  563. package/.agents/tests/fm-herdr-submit-confirm-live-e2e.test.sh +125 -0
  564. package/.agents/tests/fm-herdr-version-floor-live-e2e.test.sh +144 -0
  565. package/.agents/tests/fm-home-summary-refresh.test.sh +971 -0
  566. package/.agents/tests/fm-inactive-reconcile.test.sh +485 -0
  567. package/.agents/tests/fm-kimi-harness.test.sh +687 -0
  568. package/.agents/tests/fm-lint-workflows.test.sh +532 -0
  569. package/.agents/tests/fm-lint.test.sh +1023 -0
  570. package/.agents/tests/fm-muse-harness.test.sh +932 -0
  571. package/.agents/tests/fm-muse-signals-live-e2e.test.sh +205 -0
  572. package/.agents/tests/fm-no-mistakes-required.test.sh +72 -0
  573. package/.agents/tests/fm-on.test.sh +507 -0
  574. package/.agents/tests/fm-opencode-primary-live-e2e.test.sh +357 -0
  575. package/.agents/tests/fm-operational-input.test.sh +160 -0
  576. package/.agents/tests/fm-peek-remote.test.sh +110 -0
  577. package/.agents/tests/fm-pending-reply.test.sh +1288 -0
  578. package/.agents/tests/fm-pi-branch-extension.test.sh +3182 -0
  579. package/.agents/tests/fm-pi-branch-live-e2e.test.sh +527 -0
  580. package/.agents/tests/fm-pi-primary-live-e2e.test.sh +345 -0
  581. package/.agents/tests/fm-pi-primary-types.test.sh +68 -0
  582. package/.agents/tests/fm-pi-watch-extension.test.sh +2843 -0
  583. package/.agents/tests/fm-pr-check-security.test.sh +2140 -0
  584. package/.agents/tests/fm-pr-merge.test.sh +2135 -0
  585. package/.agents/tests/fm-procevent-quota.test.sh +225 -0
  586. package/.agents/tests/fm-procevent-when.test.sh +406 -0
  587. package/.agents/tests/fm-procevent.test.sh +1745 -0
  588. package/.agents/tests/fm-project-origin.test.sh +110 -0
  589. package/.agents/tests/fm-public-followup.test.sh +2272 -0
  590. package/.agents/tests/fm-quota-array-dispatch-live-e2e.test.sh +526 -0
  591. package/.agents/tests/fm-quota-choose.test.sh +626 -0
  592. package/.agents/tests/fm-remote-backlog-handoff.test.sh +453 -0
  593. package/.agents/tests/fm-remote-doctor.test.sh +625 -0
  594. package/.agents/tests/fm-remote-entrypoint.test.sh +59 -0
  595. package/.agents/tests/fm-remote-job-orphan-reap.test.sh +205 -0
  596. package/.agents/tests/fm-remote-job.test.sh +768 -0
  597. package/.agents/tests/fm-remote-reply.test.sh +520 -0
  598. package/.agents/tests/fm-remote-secondmate-lifecycle-e2e.test.sh +1256 -0
  599. package/.agents/tests/fm-remote-secondmate-parent-binding.test.sh +326 -0
  600. package/.agents/tests/fm-remote-secondmate-trace-context.test.sh +310 -0
  601. package/.agents/tests/fm-remote-transport-lanes.test.sh +431 -0
  602. package/.agents/tests/fm-review-diff.test.sh +176 -0
  603. package/.agents/tests/fm-secondmate-harness.test.sh +2600 -0
  604. package/.agents/tests/fm-secondmate-lifecycle-e2e.test.sh +259 -0
  605. package/.agents/tests/fm-secondmate-liveness.test.sh +559 -0
  606. package/.agents/tests/fm-secondmate-reconcile.test.sh +732 -0
  607. package/.agents/tests/fm-secondmate-safety.test.sh +2972 -0
  608. package/.agents/tests/fm-secondmate-sync.test.sh +913 -0
  609. package/.agents/tests/fm-send-inbox-doorbell-live-e2e.test.sh +206 -0
  610. package/.agents/tests/fm-send-inbox.test.sh +352 -0
  611. package/.agents/tests/fm-send-popup-settle.test.sh +167 -0
  612. package/.agents/tests/fm-send-remote-delivery.test.sh +796 -0
  613. package/.agents/tests/fm-send-resolve-key.test.sh +551 -0
  614. package/.agents/tests/fm-send-secondmate-marker-herdr-e2e.test.sh +187 -0
  615. package/.agents/tests/fm-send-secondmate-marker.test.sh +278 -0
  616. package/.agents/tests/fm-send-settle.test.sh +147 -0
  617. package/.agents/tests/fm-send-strict.test.sh +241 -0
  618. package/.agents/tests/fm-session-lock-ancestry.test.sh +365 -0
  619. package/.agents/tests/fm-session-start.test.sh +2515 -0
  620. package/.agents/tests/fm-sessionstart-hook-live-e2e.test.sh +631 -0
  621. package/.agents/tests/fm-sessionstart-instruction-refresh-live-e2e.test.sh +230 -0
  622. package/.agents/tests/fm-sessionstart-nudge.test.sh +1039 -0
  623. package/.agents/tests/fm-shared-captain-inheritance.test.sh +404 -0
  624. package/.agents/tests/fm-spawn-batch.test.sh +148 -0
  625. package/.agents/tests/fm-spawn-dispatch-profile.test.sh +827 -0
  626. package/.agents/tests/fm-spawn-pool-base-freshen.test.sh +440 -0
  627. package/.agents/tests/fm-spawn-worktree-settle.test.sh +147 -0
  628. package/.agents/tests/fm-startup-memory-budget.test.sh +333 -0
  629. package/.agents/tests/fm-startup-network.test.sh +712 -0
  630. package/.agents/tests/fm-stow-cascade.test.sh +370 -0
  631. package/.agents/tests/fm-subagent-pretool-check.test.sh +291 -0
  632. package/.agents/tests/fm-supervision-events.test.sh +156 -0
  633. package/.agents/tests/fm-supervision-instructions.test.sh +189 -0
  634. package/.agents/tests/fm-tangle-guard.test.sh +277 -0
  635. package/.agents/tests/fm-task-delivery.test.sh +420 -0
  636. package/.agents/tests/fm-task-inbox.test.sh +513 -0
  637. package/.agents/tests/fm-teardown-endpoint-safety.test.sh +374 -0
  638. package/.agents/tests/fm-teardown.test.sh +2665 -0
  639. package/.agents/tests/fm-test-fixture-cleanup.test.sh +172 -0
  640. package/.agents/tests/fm-test-fixtures.test.sh +132 -0
  641. package/.agents/tests/fm-test-isolation-proof.test.sh +278 -0
  642. package/.agents/tests/fm-test-run.test.sh +1196 -0
  643. package/.agents/tests/fm-tmux-agent-liveness.test.sh +354 -0
  644. package/.agents/tests/fm-tmux-submit-busy.test.sh +340 -0
  645. package/.agents/tests/fm-tool-update-check.test.sh +1044 -0
  646. package/.agents/tests/fm-trace-context-lib.test.sh +253 -0
  647. package/.agents/tests/fm-trace-context-spawn.test.sh +581 -0
  648. package/.agents/tests/fm-transition-lib.test.sh +54 -0
  649. package/.agents/tests/fm-turnend-guard.test.sh +1822 -0
  650. package/.agents/tests/fm-update.test.sh +304 -0
  651. package/.agents/tests/fm-vendor-auth-probe.test.sh +395 -0
  652. package/.agents/tests/fm-voice-relay.test.sh +4741 -0
  653. package/.agents/tests/fm-wake-daemon-lifecycle-e2e.test.sh +171 -0
  654. package/.agents/tests/fm-wake-drain-open-decisions-cursor.test.sh +356 -0
  655. package/.agents/tests/fm-wake-drain-open-decisions.test.sh +226 -0
  656. package/.agents/tests/fm-wake-drain-unread-status.test.sh +379 -0
  657. package/.agents/tests/fm-wake-queue.test.sh +1224 -0
  658. package/.agents/tests/fm-watch-arm.test.sh +821 -0
  659. package/.agents/tests/fm-watch-checkpoint.test.sh +87 -0
  660. package/.agents/tests/fm-watch-recovery-loop.test.sh +223 -0
  661. package/.agents/tests/fm-watch-triage.test.sh +3889 -0
  662. package/.agents/tests/fm-watcher-lock.test.sh +1133 -0
  663. package/.agents/tests/fm-x-mode.test.sh +3042 -0
  664. package/.agents/tests/gleipnir-guard-pretool-check.test.sh +51 -0
  665. package/.agents/tests/gleipnir-machine-lock.test.sh +130 -0
  666. package/.agents/tests/herdr-test-safety.sh +42 -0
  667. package/.agents/tests/lib.sh +315 -0
  668. package/.agents/tests/remote-herdr-fixture.sh +125 -0
  669. package/.agents/tests/secondmate-helpers.sh +193 -0
  670. package/.agents/tests/smoke.test.sh +93 -0
  671. package/.agents/tests/wake-helpers.sh +338 -0
  672. package/.agents/tests/zellij-test-safety.sh +60 -0
  673. package/.agents/tools/README.md +10 -0
  674. package/.agents/tools/bin/tasks-cli +267 -0
  675. package/.agents/tools/tasks-cli.ts +216 -0
  676. package/AGENTS.md +454 -0
  677. package/CHANGELOG.md +881 -0
  678. package/LICENSE +1 -1
  679. package/NOTICE +63 -0
  680. package/README.md +113 -59
  681. package/RULES/01-domains.md +51 -0
  682. package/RULES/02-agents.md +78 -0
  683. package/RULES/03-houses.md +61 -0
  684. package/RULES/04-hoard.md +65 -0
  685. package/RULES/05-platforms.md +67 -0
  686. package/RULES/06-append-only.md +58 -0
  687. package/RULES/07-config.md +45 -0
  688. package/RULES/08-delivery-gate.md +75 -0
  689. package/RULES/README.md +20 -0
  690. package/bin/README.md +107 -0
  691. package/bin/a2a-mcp.sh +98 -0
  692. package/bin/a2a-serve.py +103 -0
  693. package/bin/a2a-serve.sh +8 -0
  694. package/bin/a2a-talk.sh +50 -0
  695. package/bin/a2abridge-ensure.sh +108 -0
  696. package/bin/agent-run.sh +43 -0
  697. package/bin/agents-config.sh +233 -0
  698. package/bin/apodex-smoke-test.sh +92 -0
  699. package/bin/bifrost-bridge.sh +112 -0
  700. package/bin/bifrost-ingress.sh +77 -0
  701. package/bin/bootstrap-macos.sh +107 -0
  702. package/bin/bootstrap-windows.ps1 +112 -0
  703. package/bin/branch-guard.sh +64 -0
  704. package/bin/brokk +73 -0
  705. package/bin/brokk-classify-lib.sh +1770 -0
  706. package/bin/brokk-lease-lib.sh +222 -0
  707. package/bin/brokk-lease.sh +193 -0
  708. package/bin/brokk-lint.sh +65 -0
  709. package/bin/brokk-send.sh +38 -0
  710. package/bin/brokk-update.sh +9 -0
  711. package/bin/brokk-wake-grant.sh +127 -0
  712. package/bin/brokk-wake-lib.sh +1849 -0
  713. package/bin/changelog-guard.sh +165 -0
  714. package/bin/crash-sense.sh +160 -0
  715. package/bin/desktop-place.sh +224 -0
  716. package/bin/docs-guard.sh +39 -0
  717. package/bin/editor-place.sh +207 -0
  718. package/bin/eindri-acclaim.sh +34 -0
  719. package/bin/eindri-control.sh +28 -0
  720. package/bin/eindri-role.sh +83 -0
  721. package/bin/eindri-seen.sh +41 -0
  722. package/bin/eindri-send.sh +15 -0
  723. package/bin/eindri-start.sh +85 -0
  724. package/bin/eindri-watch.sh +57 -0
  725. package/bin/einherjar-spawn.sh +576 -0
  726. package/bin/eir-doctor.sh +112 -0
  727. package/bin/erindi-brief.sh +271 -0
  728. package/bin/fleet-apply.sh +68 -0
  729. package/bin/github-deploy.sh +81 -0
  730. package/bin/gjallarhorn-expose.sh +102 -0
  731. package/bin/gjallarhorn-notify.sh +58 -0
  732. package/bin/gjallarhorn-purge.sh +54 -0
  733. package/bin/gjallarhorn-tunnel.sh +72 -0
  734. package/bin/gleipnir-lock-lib.sh +284 -0
  735. package/bin/groa-update.sh +122 -0
  736. package/bin/hall-snapshot.sh +92 -0
  737. package/bin/hamr-harness.sh +246 -0
  738. package/bin/heimdall-ssh-keys.sh +374 -0
  739. package/bin/herdr-agents.py +44 -0
  740. package/bin/herdr-ensure.sh +104 -0
  741. package/bin/herdr-run.sh +431 -0
  742. package/bin/hermes-ensure.sh +88 -0
  743. package/bin/hoard-lib.sh +25 -0
  744. package/bin/hodd.sh +78 -0
  745. package/bin/host-sense.sh +199 -0
  746. package/bin/huginn-research-worker.sh +108 -0
  747. package/bin/local-model-lock.sh +51 -0
  748. package/bin/mimir-bridge.py +226 -0
  749. package/bin/mimir-bridge.sh +87 -0
  750. package/bin/mimir-ingest.sh +131 -0
  751. package/bin/mimir.sh +113 -0
  752. package/bin/mjollnir-webhook.sh +59 -0
  753. package/bin/mjollnir.sh +85 -0
  754. package/bin/model-hardware.sh +82 -0
  755. package/bin/model-resolve.sh +147 -0
  756. package/bin/models-detect.sh +178 -0
  757. package/bin/nornir-cron-start.sh +162 -0
  758. package/bin/nornir-job-daily-briefing.sh +191 -0
  759. package/bin/nornir-job-git-sync.sh +152 -0
  760. package/bin/nornir-job-memory-housekeeping.sh +114 -0
  761. package/bin/nornir-job-observer.sh +166 -0
  762. package/bin/nornir-job-skillopt-sleep.sh +76 -0
  763. package/bin/omarchy-hook-install.sh +60 -0
  764. package/bin/omarchy-install.sh +148 -0
  765. package/bin/omarchy-plugins.sh +174 -0
  766. package/bin/omarchy-sense.sh +149 -0
  767. package/bin/perm-guard.sh +30 -0
  768. package/bin/pi-agent.sh +68 -0
  769. package/bin/pi-ensure.sh +77 -0
  770. package/bin/pi-local.sh +37 -0
  771. package/bin/pi-seat.sh +63 -0
  772. package/bin/prereq-ensure.sh +166 -0
  773. package/bin/private-guard.sh +38 -0
  774. package/bin/project-git.sh +55 -0
  775. package/bin/public-guard.sh +70 -0
  776. package/bin/ratatoskr.sh +49 -0
  777. package/bin/realm-lib.sh +32 -0
  778. package/bin/repo-scrub.sh +62 -0
  779. package/bin/rodd-operational-input.sh +250 -0
  780. package/bin/runes-append.sh +198 -0
  781. package/bin/saga-session-start.sh +172 -0
  782. package/bin/saga-sessionstart-run.sh +79 -0
  783. package/bin/saga-wake-drain.sh +41 -0
  784. package/bin/secret-guard.sh +63 -0
  785. package/bin/sessrumnir-ensure.sh +100 -0
  786. package/bin/sessrumnir-sync.sh +237 -0
  787. package/bin/sessrumnir.sh +91 -0
  788. package/bin/skillopt-setup.sh +76 -0
  789. package/bin/skuld-branch-outcome.sh +203 -0
  790. package/bin/skuld-branch-prompt.sh +101 -0
  791. package/bin/smidja-bootstrap.sh +90 -0
  792. package/bin/smidja-observe.sh +86 -0
  793. package/bin/syn-arm-pretool-check.sh +57 -0
  794. package/bin/syn-asset-pretool-check.sh +76 -0
  795. package/bin/syn-cd-pretool-check.sh +28 -0
  796. package/bin/syn-guard-pretool-check.sh +83 -0
  797. package/bin/syn-turnend-guard.sh +36 -0
  798. package/bin/syn-watch-arm.sh +99 -0
  799. package/bin/tailscale-sync.sh +190 -0
  800. package/bin/telegram-bot.sh +69 -0
  801. package/bin/toolchain.sh +74 -0
  802. package/bin/utgard.sh +111 -0
  803. package/bin/valhalla.sh +115 -0
  804. package/bin/valknut-load.sh +260 -0
  805. package/bin/vor-crew-state.sh +124 -0
  806. package/bin/wedge-notify.sh +47 -0
  807. package/bin/workspace-provision.sh +80 -0
  808. package/bin/workspace-rag.sh +150 -0
  809. package/bin/wyrd-db.sh +47 -0
  810. package/bin/yggdrasil.sh +152 -0
  811. package/bin/ymir-edit.sh +145 -0
  812. package/bin/ymir-install.sh +641 -0
  813. package/bin/ymir-invite.sh +93 -0
  814. package/bin/ymir-isolation.sh +88 -0
  815. package/bin/ymir-migrate.sh +61 -0
  816. package/bin/ymir-platform.sh +348 -0
  817. package/bin/ymir-say.sh +97 -0
  818. package/bin/ymir-setup-auth.sh +108 -0
  819. package/bin/ymir-validate.sh +173 -0
  820. package/bin/ymir.js +74 -16
  821. package/docs/Architecture.md +339 -0
  822. package/docs/design.md +351 -0
  823. package/docs/installations/README.md +63 -0
  824. package/docs/installations/ymir-home.md +93 -0
  825. package/docs/integration.md +105 -0
  826. package/docs/lore.md +1056 -0
  827. package/docs/research/agent-harnesses.md +290 -0
  828. package/docs/runbooks/README.md +19 -0
  829. package/docs/runbooks/a2a.md +91 -0
  830. package/docs/runbooks/agent-permissions.md +99 -0
  831. package/docs/runbooks/agents.md +57 -0
  832. package/docs/runbooks/models.md +69 -0
  833. package/docs/runbooks/realm-onboarding.md +60 -0
  834. package/docs/runbooks/secrets-and-hoard.md +60 -0
  835. package/docs/runbooks/updates-and-migrations.md +110 -0
  836. package/docs/runbooks/worktrees-isolation.md +72 -0
  837. package/docs/session-start.md +105 -0
  838. package/docs/skillopt-integration.md +321 -0
  839. package/docs/sync-system.md +66 -0
  840. package/docs/workspaces.md +104 -0
  841. package/docs/ymir-rut.md +260 -0
  842. package/package.json +44 -14
  843. package/packaging/build.sh +74 -0
  844. package/packaging/macos/Ymir Installer.command +43 -0
  845. package/packaging/windows/ymir-setup.nsi +74 -0
  846. package/scripts/README.md +22 -0
  847. package/scripts/electron.sh +210 -0
  848. package/scripts/start.sh +167 -0
  849. package/scripts/stop.sh +113 -0
  850. package/install.sh +0 -35
@@ -0,0 +1,687 @@
1
+ #!/usr/bin/env bash
2
+ # Behavior tests for the verified Kimi Code CLI crewmate adapter.
3
+ set -u
4
+
5
+ # shellcheck source=tests/lib.sh
6
+ . "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
7
+
8
+ # bin/fm-harness.sh checks verified ENV markers before ancestry. A suite run
9
+ # from inside Cursor, Claude, Pi, or Grok inherits those markers, which outrank
10
+ # the fake ancestry the detection cases set up. Drop the ambient markers so the
11
+ # asserted verdict does not depend on which harness launched the suite.
12
+ unset CLAUDECODE PI_CODING_AGENT FM_PI_HARNESS GROK_AGENT CURSOR_AGENT CURSOR_INVOKED_AS
13
+
14
+ SPAWN="$ROOT/bin/fm-spawn.sh"
15
+ TEARDOWN="$ROOT/bin/fm-teardown.sh"
16
+ KIMI_HOOK="$ROOT/bin/fm-kimi-turnend-hook.sh"
17
+ TMP_ROOT=$(fm_test_tmproot fm-kimi-harness)
18
+ KIMI_RUNTIME_TASK_TMP=
19
+ PYTHON_BIN=$(command -v python3) || fail "test needs python3"
20
+ PYTHON_BIN_DIR=$(dirname "$PYTHON_BIN")
21
+ JQ_BIN=$(command -v jq) || fail "test needs jq"
22
+ BASE_PATH=${FM_TEST_BASE_PATH:-$PYTHON_BIN_DIR:/usr/bin:/bin:/usr/sbin:/sbin}
23
+
24
+ cleanup_kimi_harness() {
25
+ [ -z "$KIMI_RUNTIME_TASK_TMP" ] || rm -rf "$KIMI_RUNTIME_TASK_TMP"
26
+ rm -rf "$TMP_ROOT"
27
+ }
28
+ trap cleanup_kimi_harness EXIT
29
+
30
+ make_spawn_fakebin() {
31
+ local dir=$1 fakebin
32
+ fakebin=$(fm_fakebin "$dir")
33
+ cat > "$fakebin/tmux" <<'SH'
34
+ #!/usr/bin/env bash
35
+ set -u
36
+ printf '%s\n' "$*" >> "$FM_FAKE_TMUX_CALL_LOG"
37
+ state=$(cat "$FM_FAKE_KIMI_STATE" 2>/dev/null || true)
38
+ fake_screen() {
39
+ case "$state" in
40
+ ready)
41
+ printf 'Welcome to Kimi Code!\ncontext: 0%% (0/256k)\nโ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ\nโ”‚ > โ”‚\nโ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n'
42
+ ;;
43
+ pointer-typed)
44
+ printf 'context: 0%% (0/256k)\nโ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ\nโ”‚ > Read the brief and follow it โ”‚\nโ”‚ โ”‚\nโ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n'
45
+ ;;
46
+ delivered)
47
+ printf 'โœจ Read the brief at %s and follow it exactly.\ncontext: 1%% (2k/256k)\nโ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ\nโ”‚ > โ”‚\nโ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ\n' "$FM_FAKE_BRIEF_REAL"
48
+ ;;
49
+ *)
50
+ printf 'shell starting\n$ \n'
51
+ ;;
52
+ esac
53
+ }
54
+ fake_cursor_y() {
55
+ case "$state" in
56
+ pointer-typed) printf '3\n' ;;
57
+ ready|delivered) printf '3\n' ;;
58
+ *) printf '1\n' ;;
59
+ esac
60
+ }
61
+ case "$*" in
62
+ *"#{pane_current_path}"*) printf '%s\n' "$FM_FAKE_PANE_PATH"; exit 0 ;;
63
+ *"#{cursor_y}"*) fake_cursor_y; exit 0 ;;
64
+ esac
65
+ case "${1:-}" in
66
+ display-message) printf 'firstmate\n'; exit 0 ;;
67
+ list-windows) exit 0 ;;
68
+ has-session|new-session|new-window|kill-window) exit 0 ;;
69
+ send-keys)
70
+ prev=
71
+ literal=
72
+ for arg in "$@"; do
73
+ if [ "$prev" = -l ]; then literal=$arg; break; fi
74
+ prev=$arg
75
+ done
76
+ if [ -n "$literal" ]; then
77
+ case "$literal" in
78
+ *' --auto')
79
+ printf '%s\n' "$literal" >> "$FM_FAKE_LAUNCH_LOG"
80
+ printf 'launched\n' > "$FM_FAKE_KIMI_STATE"
81
+ ;;
82
+ *)
83
+ printf '%s\n' "$literal" >> "$FM_FAKE_POINTER_LOG"
84
+ printf 'pointer-typed\n' > "$FM_FAKE_KIMI_STATE"
85
+ ;;
86
+ esac
87
+ exit 0
88
+ fi
89
+ case " $* " in
90
+ *' Enter '*)
91
+ case "$state" in
92
+ launched)
93
+ if [ "${FM_FAKE_KIMI_READY:-yes}" = yes ]; then
94
+ printf 'ready\n' > "$FM_FAKE_KIMI_STATE"
95
+ fi
96
+ ;;
97
+ pointer-typed)
98
+ if [ "${FM_FAKE_KIMI_DELIVERY:-yes}" = yes ]; then
99
+ if [ "${FM_FAKE_KIMI_SWALLOW_FIRST:-no}" = yes ] \
100
+ && [ ! -f "$FM_FAKE_KIMI_SWALLOWED" ]; then
101
+ : > "$FM_FAKE_KIMI_SWALLOWED"
102
+ else
103
+ printf 'delivered\n' > "$FM_FAKE_KIMI_STATE"
104
+ fi
105
+ else
106
+ printf 'ready\n' > "$FM_FAKE_KIMI_STATE"
107
+ fi
108
+ ;;
109
+ esac
110
+ ;;
111
+ esac
112
+ exit 0
113
+ ;;
114
+ capture-pane)
115
+ start= end= prev=
116
+ for arg in "$@"; do
117
+ case "$prev" in
118
+ -S) start=$arg ;;
119
+ -E) end=$arg ;;
120
+ esac
121
+ case "$arg" in -S|-E) prev=$arg ;; *) prev= ;; esac
122
+ done
123
+ case "$start:$end" in
124
+ *[!0-9:]*|'':*|*:'') fake_screen ;;
125
+ *) fake_screen | awk -v start="$start" -v end="$end" \
126
+ 'NR - 1 >= start && NR - 1 <= end' ;;
127
+ esac
128
+ exit 0
129
+ ;;
130
+ esac
131
+ exit 0
132
+ SH
133
+ chmod +x "$fakebin/tmux"
134
+ fm_fake_exit0 "$fakebin" treehouse gh-axi gh
135
+ fm_fake_exit0 "$fakebin" kimi
136
+ ln -s "$JQ_BIN" "$fakebin/jq"
137
+ printf '%s\n' "$fakebin"
138
+ }
139
+
140
+ make_spawn_case() {
141
+ local name=$1 id=$2 case_dir home proj wt fakebin
142
+ case_dir="$TMP_ROOT/$name"
143
+ home="$case_dir/home"
144
+ proj="$case_dir/project"
145
+ wt="$case_dir/wt"
146
+ fakebin=$(make_spawn_fakebin "$case_dir/fake")
147
+ mkdir -p "$home/data/$id" "$home/projects" "$home/state" "$home/config" "$home/.kimi-code"
148
+ printf '# Kimi test config\ndefault_model = "test"\n' > "$home/.kimi-code/config.toml"
149
+ printf 'brief for kimi\n' > "$home/data/$id/brief.md"
150
+ printf 'kimi\n' > "$home/config/crew-harness"
151
+ fm_git_worktree "$proj" "$wt" "wt-$name"
152
+ touch "$home/state/.last-watcher-beat"
153
+ : > "$case_dir/launch.log"
154
+ : > "$case_dir/pointer.log"
155
+ : > "$case_dir/kimi.state"
156
+ : > "$case_dir/tmux-calls.log"
157
+ printf '%s\n' "$case_dir|$home|$proj|$wt|$fakebin"
158
+ }
159
+
160
+ run_spawn() {
161
+ local case_dir=$1 home=$2 proj=$3 wt=$4 fakebin=$5 id=$6
162
+ shift 6
163
+ HOME="$home" FM_ROOT_OVERRIDE='' FM_HOME="$home" \
164
+ FM_STATE_OVERRIDE="$home/state" FM_DATA_OVERRIDE="$home/data" \
165
+ FM_PROJECTS_OVERRIDE="$home/projects" FM_CONFIG_OVERRIDE="$home/config" \
166
+ FM_SPAWN_NO_GUARD=1 FM_FAKE_PANE_PATH="$wt" TMUX="fake,1,0" \
167
+ FM_FAKE_LAUNCH_LOG="$case_dir/launch.log" \
168
+ FM_FAKE_POINTER_LOG="$case_dir/pointer.log" \
169
+ FM_FAKE_KIMI_STATE="$case_dir/kimi.state" \
170
+ FM_FAKE_KIMI_SWALLOWED="$case_dir/kimi.swallowed" \
171
+ FM_FAKE_KIMI_SWALLOW_FIRST="${FM_FAKE_KIMI_SWALLOW_FIRST:-no}" \
172
+ FM_FAKE_TMUX_CALL_LOG="$case_dir/tmux-calls.log" \
173
+ FM_FAKE_BRIEF_REAL="$(cd "$home/data/$id" && pwd -P)/brief.md" \
174
+ FM_KIMI_READY_POLLS=2 FM_KIMI_DELIVERY_POLLS=2 FM_KIMI_POLL_INTERVAL=0 \
175
+ PATH="$fakebin:$BASE_PATH" \
176
+ "$SPAWN" "$id" "$proj" --harness kimi --mode no-mistakes --yolo off "$@" 2>&1
177
+ }
178
+
179
+ read_spawn_record() {
180
+ IFS='|' read -r CASE_DIR HOME_DIR PROJ_DIR WT_DIR FAKEBIN_DIR <<EOF
181
+ $1
182
+ EOF
183
+ }
184
+
185
+ test_kimi_launch_then_send_is_verified() {
186
+ local id rec out rc launch pointer brief_real meta task_tmp
187
+ id="kimi-success-z1-$$"
188
+ task_tmp="/tmp/fm-$id"
189
+ KIMI_RUNTIME_TASK_TMP=$task_tmp
190
+ rm -rf "$task_tmp"
191
+ rec=$(make_spawn_case success "$id")
192
+ read_spawn_record "$rec"
193
+ out=$(FM_FAKE_KIMI_SWALLOW_FIRST=yes run_spawn \
194
+ "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id" \
195
+ --model kimi-code/k3 --effort high)
196
+ rc=$?
197
+ expect_code 0 "$rc" "verified kimi launch-then-send should succeed"
198
+ assert_contains "$out" "spawned $id harness=kimi" "kimi spawn did not report success"
199
+
200
+ launch=$(cat "$CASE_DIR/launch.log")
201
+ [ "$launch" = "env -u CURSOR_AGENT -u CURSOR_INVOKED_AS '$FAKEBIN_DIR/kimi' --model 'kimi-code/k3' --auto" ] \
202
+ || fail "kimi launch did not use the absolute binary, model, and --auto only: $launch"
203
+ assert_not_contains "$launch" "--effort" "kimi launch emitted a nonexistent effort flag"
204
+ assert_not_contains "$launch" "turn-ended" "kimi launch embedded a turn-end path"
205
+ assert_not_contains "$launch" "__TURNEND__" "kimi launch retained a turn-end placeholder"
206
+
207
+ brief_real="$(cd "$HOME_DIR/data/$id" && pwd -P)/brief.md"
208
+ pointer=$(cat "$CASE_DIR/pointer.log")
209
+ [ "$pointer" = "Read the brief at $brief_real and follow it exactly." ] \
210
+ || fail "kimi pointer was not the exact absolute-path-only instruction: $pointer"
211
+ meta="$HOME_DIR/state/$id.meta"
212
+ assert_grep 'model=kimi-code/k3' "$meta" "kimi meta lost the requested model"
213
+ assert_grep 'effort=high' "$meta" "kimi meta did not retain the unsupported effort axis"
214
+ assert_grep "tasktmp=$task_tmp" "$meta" "kimi meta did not record its task temp root"
215
+ assert_present "$task_tmp/gotmp" "kimi spawn did not create its Go temp directory"
216
+ assert_grep "export GOTMPDIR=$task_tmp/gotmp" "$CASE_DIR/tmux-calls.log" \
217
+ "kimi spawn did not export its Go temp directory into the pane"
218
+ assert_grep 'BEGIN FIRSTMATE KIMI TURN-END HOOK' "$HOME_DIR/.kimi-code/config.toml" \
219
+ "kimi spawn did not install its guarded global hook region"
220
+ assert_grep 'token=' "$WT_DIR/.fm-kimi-turnend" "kimi spawn did not write its token pointer"
221
+ assert_present "$HOME_DIR/state/$id.kimi-turnend-token" "kimi spawn did not record its token"
222
+ pass "fm-spawn: kimi launches, delivers its brief, and registers a guarded turn-end token"
223
+ }
224
+
225
+ test_kimi_hook_install_is_surgical_idempotent_and_removable() {
226
+ local home config original once stripped count
227
+ home="$TMP_ROOT/config-surgery"
228
+ config="$home/.kimi-code/config.toml"
229
+ original="$home/original.toml"
230
+ once="$home/once.toml"
231
+ stripped="$home/stripped.toml"
232
+ mkdir -p "$home/.kimi-code"
233
+ cat > "$config" <<'EOF'
234
+ # Captain's leading comment stays exactly here.
235
+
236
+ [ui]
237
+ theme = "night" # inline comment
238
+ show_usage = true
239
+
240
+ # Foreign hook with intentionally unusual key ordering.
241
+ [[hooks]]
242
+ timeout=17
243
+ command = "printf foreign"
244
+ matcher=""
245
+ event = "Stop"
246
+
247
+ [providers.example]
248
+ model = "some/model"
249
+ # Final comment and blank line follow.
250
+
251
+ EOF
252
+ cp "$config" "$original"
253
+
254
+ HOME="$home" "$KIMI_HOOK" install || fail "Kimi hook install refused a realistic config"
255
+ cp "$config" "$once"
256
+ HOME="$home" "$KIMI_HOOK" install || fail "second Kimi hook install failed"
257
+ cmp -s "$once" "$config" || fail "second Kimi hook install changed config bytes"
258
+ count=$(grep -c '^# BEGIN FIRSTMATE KIMI TURN-END HOOK' "$config")
259
+ [ "$count" -eq 1 ] || fail "idempotent install left $count Firstmate regions"
260
+
261
+ HOME="$home" "$KIMI_HOOK" remove || fail "Kimi hook removal failed"
262
+ cp "$config" "$stripped"
263
+ cmp -s "$original" "$stripped" \
264
+ || fail "config with the Firstmate region excised was not byte-identical to the original"
265
+ assert_absent "$home/.kimi-code/fm-turn-end.sh" "removal left the Firstmate hook script"
266
+ assert_absent "$home/.kimi-code/fm-turn-end.d" "removal left the Firstmate registry"
267
+ pass "Kimi hook install is idempotent and removal restores every foreign config byte"
268
+ }
269
+
270
+ test_kimi_hook_remove_preserves_owned_newline_boundary() {
271
+ local appended config expected home original
272
+ home="$TMP_ROOT/config-owned-newline"
273
+ config="$home/.kimi-code/config.toml"
274
+ original="$home/original.toml"
275
+ expected="$home/expected.toml"
276
+ appended="$home/appended.toml"
277
+ mkdir -p "$home/.kimi-code"
278
+ printf 'default_model = "test"' > "$config"
279
+ cp "$config" "$original"
280
+
281
+ HOME="$home" "$KIMI_HOOK" install || fail "Kimi hook install refused config without a final newline"
282
+ HOME="$home" "$KIMI_HOOK" remove || fail "Kimi hook removal failed without appended config"
283
+ cmp -s "$original" "$config" \
284
+ || fail "pristine removal did not restore the absent final newline byte-identically"
285
+
286
+ HOME="$home" "$KIMI_HOOK" install || fail "second Kimi hook install refused config without a final newline"
287
+ printf '[captain]\nenabled = true\n' > "$appended"
288
+ cat "$appended" >> "$config"
289
+ HOME="$home" "$KIMI_HOOK" remove || fail "Kimi hook removal joined config appended after its region"
290
+ {
291
+ cat "$original"
292
+ printf '\n'
293
+ cat "$appended"
294
+ } > "$expected"
295
+ cmp -s "$expected" "$config" \
296
+ || fail "removal did not preserve appended captain config on its own line"
297
+ "$PYTHON_BIN" - "$config" <<'PY' || fail "config with appended captain TOML did not parse after removal"
298
+ import sys
299
+ import tomllib
300
+
301
+ with open(sys.argv[1], "rb") as stream:
302
+ tomllib.load(stream)
303
+ PY
304
+ pass "Kimi hook removal preserves owned newline boundaries and pristine bytes"
305
+ }
306
+
307
+ test_kimi_hook_fails_closed_on_missing_malformed_or_partial_config() {
308
+ local missing malformed partial out rc
309
+ missing="$TMP_ROOT/config-missing"
310
+ malformed="$TMP_ROOT/config-malformed"
311
+ partial="$TMP_ROOT/config-partial"
312
+ mkdir -p "$missing/.kimi-code" "$malformed/.kimi-code" "$partial/.kimi-code"
313
+
314
+ rc=0
315
+ out=$(HOME="$missing" "$KIMI_HOOK" install 2>&1) || rc=$?
316
+ [ "$rc" -ne 0 ] || fail "missing Kimi config was accepted"
317
+ assert_contains "$out" "Kimi config is missing" "missing config refusal lacked its concrete reason"
318
+ assert_absent "$missing/.kimi-code/fm-turn-end.sh" "missing config refusal wrote the hook script"
319
+
320
+ printf '[broken\n' > "$malformed/.kimi-code/config.toml"
321
+ cp "$malformed/.kimi-code/config.toml" "$malformed/before"
322
+ rc=0
323
+ out=$(HOME="$malformed" "$KIMI_HOOK" install 2>&1) || rc=$?
324
+ [ "$rc" -ne 0 ] || fail "malformed Kimi config was accepted"
325
+ assert_contains "$out" "malformed TOML" "malformed config refusal lacked its concrete reason"
326
+ cmp -s "$malformed/before" "$malformed/.kimi-code/config.toml" \
327
+ || fail "malformed config refusal changed config bytes"
328
+ assert_absent "$malformed/.kimi-code/fm-turn-end.sh" "malformed config refusal wrote the hook script"
329
+
330
+ printf '# BEGIN FIRSTMATE KIMI TURN-END HOOK\n' > "$partial/.kimi-code/config.toml"
331
+ cp "$partial/.kimi-code/config.toml" "$partial/before"
332
+ rc=0
333
+ out=$(HOME="$partial" "$KIMI_HOOK" install 2>&1) || rc=$?
334
+ [ "$rc" -ne 0 ] || fail "partial Firstmate marker was accepted"
335
+ assert_contains "$out" "partial, duplicated, or altered" "partial marker refusal lacked its concrete reason"
336
+ cmp -s "$partial/before" "$partial/.kimi-code/config.toml" \
337
+ || fail "partial marker refusal changed config bytes"
338
+ pass "Kimi hook install refuses missing, malformed, and surprising config without writing"
339
+ }
340
+
341
+ test_kimi_hook_install_refuses_without_jq() {
342
+ local home config before fakebin out rc
343
+ home="$TMP_ROOT/config-no-jq"
344
+ config="$home/.kimi-code/config.toml"
345
+ before="$home/config-before.toml"
346
+ fakebin=$(fm_fakebin "$home/no-jq")
347
+ mkdir -p "$home/.kimi-code"
348
+ printf '# Captain config\nmodel = "test"\n' > "$config"
349
+ cp "$config" "$before"
350
+ ln -s "$(command -v bash)" "$fakebin/bash"
351
+ ln -s "$(command -v python3)" "$fakebin/python3"
352
+
353
+ rc=0
354
+ out=$(HOME="$home" PATH="$fakebin" "$KIMI_HOOK" install 2>&1) || rc=$?
355
+ [ "$rc" -ne 0 ] || fail "Kimi hook install succeeded without jq"
356
+ assert_contains "$out" "jq is required" "missing-jq refusal did not name jq"
357
+ cmp -s "$before" "$config" || fail "missing-jq refusal changed config bytes"
358
+ assert_absent "$home/.kimi-code/fm-turn-end.sh" "missing-jq refusal wrote the hook script"
359
+ assert_absent "$home/.kimi-code/fm-turn-end.d" "missing-jq refusal wrote the registry"
360
+ pass "Kimi hook install refuses without jq before any config write"
361
+ }
362
+
363
+ test_kimi_hook_is_silent_and_requires_registered_workspace_token() {
364
+ local id rec out rc hook target token no_token snapshot_before snapshot_after fakebin
365
+ id=kimi-hook-auth-z6
366
+ rec=$(make_spawn_case hook-auth "$id")
367
+ read_spawn_record "$rec"
368
+ out=$(run_spawn "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id")
369
+ rc=$?
370
+ expect_code 0 "$rc" "Kimi spawn should succeed before hook authentication checks"
371
+ hook="$HOME_DIR/.kimi-code/fm-turn-end.sh"
372
+ target="$HOME_DIR/state/$id.turn-ended"
373
+ token=$(sed -n 's/^token=//p' "$WT_DIR/.fm-kimi-turnend")
374
+ assert_present "$HOME_DIR/.kimi-code/fm-turn-end.d/$token" "Kimi registry token is missing"
375
+
376
+ no_token="$CASE_DIR/no-token-workspace"
377
+ mkdir -p "$no_token"
378
+ snapshot_before=$(find "$no_token" -mindepth 1 -print)
379
+ out=$(printf '{"hook_event_name":"Stop","session_id":"ordinary","cwd":"%s","stop_hook_active":false}\n' "$no_token" \
380
+ | HOME="$HOME_DIR" bash "$hook" 2>&1)
381
+ rc=$?
382
+ expect_code 0 "$rc" "Kimi hook must never block a tokenless session"
383
+ [ -z "$out" ] || fail "Kimi hook printed into a tokenless session: $out"
384
+ snapshot_after=$(find "$no_token" -mindepth 1 -print)
385
+ [ "$snapshot_before" = "$snapshot_after" ] || fail "Kimi hook wrote inside a tokenless workspace"
386
+ assert_absent "$target" "tokenless Kimi hook invocation touched a task marker"
387
+
388
+ printf 'token=%s\n' "$token" > "$WT_DIR/.fm-kimi-turnend"
389
+ out=$(printf '{"hook_event_name":"Stop","session_id":"crew","cwd":"%s","stop_hook_active":false}\n' "$WT_DIR" \
390
+ | HOME="$HOME_DIR" bash "$hook" 2>&1)
391
+ rc=$?
392
+ expect_code 0 "$rc" "registered Kimi hook invocation did not exit zero"
393
+ [ -z "$out" ] || fail "registered Kimi hook invocation printed output: $out"
394
+ assert_present "$target" "registered Kimi hook invocation did not touch the turn-end marker"
395
+
396
+ rm "$target"
397
+ fakebin=$(fm_fakebin "$CASE_DIR/no-jq")
398
+ ln -s "$(command -v bash)" "$fakebin/bash"
399
+ out=$(printf '{"hook_event_name":"Stop","session_id":"crew","cwd":"%s","stop_hook_active":false}\n' "$WT_DIR" \
400
+ | HOME="$HOME_DIR" PATH="$fakebin" "$hook" 2>&1)
401
+ rc=$?
402
+ expect_code 0 "$rc" "Kimi hook without jq must still exit zero"
403
+ [ -z "$out" ] || fail "Kimi hook without jq printed output: $out"
404
+ assert_absent "$target" "Kimi hook without jq touched the turn-end marker"
405
+ pass "Kimi hook stays silent and inert without a Firstmate registry token"
406
+ }
407
+
408
+ test_kimi_spawn_refuses_unsafe_global_config_before_pane_creation() {
409
+ local id rec out rc
410
+ id=kimi-config-refuse-z7
411
+ rec=$(make_spawn_case config-refuse "$id")
412
+ read_spawn_record "$rec"
413
+ printf '[malformed\n' > "$HOME_DIR/.kimi-code/config.toml"
414
+ rc=0
415
+ out=$(run_spawn "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id") || rc=$?
416
+ [ "$rc" -ne 0 ] || fail "Kimi spawn accepted malformed global config"
417
+ assert_contains "$out" "malformed TOML" "Kimi spawn omitted the concrete config refusal"
418
+ if grep -Eq '(^| )new-(session|window)( |$)' "$CASE_DIR/tmux-calls.log"; then
419
+ fail "unsafe Kimi config refusal created a tmux container or pane"
420
+ fi
421
+ pass "fm-spawn: unsafe Kimi global config refuses before pane creation"
422
+ }
423
+
424
+ test_kimi_teardown_removes_pointer_and_registry_token() {
425
+ local id rec out rc token
426
+ id=kimi-teardown-z8
427
+ rec=$(make_spawn_case teardown "$id")
428
+ read_spawn_record "$rec"
429
+ out=$(run_spawn "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id")
430
+ rc=$?
431
+ expect_code 0 "$rc" "Kimi spawn should succeed before teardown"
432
+ token=$(sed -n 's/^token=//p' "$WT_DIR/.fm-kimi-turnend")
433
+
434
+ HOME="$HOME_DIR" FM_ROOT_OVERRIDE="$ROOT" FM_HOME="$HOME_DIR" \
435
+ FM_STATE_OVERRIDE="$HOME_DIR/state" FM_DATA_OVERRIDE="$HOME_DIR/data" \
436
+ FM_PROJECTS_OVERRIDE="$HOME_DIR/projects" FM_CONFIG_OVERRIDE="$HOME_DIR/config" \
437
+ FM_SPAWN_NO_GUARD=1 PATH="$FAKEBIN_DIR:$BASE_PATH" \
438
+ "$TEARDOWN" "$id" --force >/dev/null 2>&1 || fail "Kimi teardown failed"
439
+ assert_absent "$WT_DIR/.fm-kimi-turnend" "Kimi token pointer survived teardown"
440
+ assert_absent "$HOME_DIR/.kimi-code/fm-turn-end.d/$token" "Kimi registry token survived teardown"
441
+ assert_absent "$HOME_DIR/state/$id.kimi-turnend-token" "Kimi token state survived teardown"
442
+ pass "fm-teardown: Kimi task pointer and registry token are removed"
443
+ }
444
+
445
+ test_kimi_falls_back_to_expanded_home_binary() {
446
+ local id rec out rc launch fallback
447
+ id=kimi-fallback-z4
448
+ rec=$(make_spawn_case fallback "$id")
449
+ read_spawn_record "$rec"
450
+ rm "$FAKEBIN_DIR/kimi"
451
+ fallback="$HOME_DIR/.kimi-code/bin/kimi"
452
+ mkdir -p "$(dirname "$fallback")"
453
+ fm_fake_exit0 "$(dirname "$fallback")" kimi
454
+ out=$(run_spawn "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id")
455
+ rc=$?
456
+ expect_code 0 "$rc" "Kimi HOME fallback spawn should succeed"
457
+ launch=$(cat "$CASE_DIR/launch.log")
458
+ [ "$launch" = "env -u CURSOR_AGENT -u CURSOR_INVOKED_AS '$fallback' --auto" ] \
459
+ || fail "Kimi fallback did not expand HOME into an absolute executable: $launch"
460
+ pass "fm-spawn: Kimi fallback expands the active HOME"
461
+ }
462
+
463
+ test_kimi_missing_binary_refuses_before_pane_creation() {
464
+ local id rec out rc fallback
465
+ id=kimi-missing-z5
466
+ rec=$(make_spawn_case missing "$id")
467
+ read_spawn_record "$rec"
468
+ rm "$FAKEBIN_DIR/kimi"
469
+ fallback="$HOME_DIR/.kimi-code/bin/kimi"
470
+ rc=0
471
+ out=$(run_spawn "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id") || rc=$?
472
+ [ "$rc" -ne 0 ] || fail "missing Kimi executable should refuse the spawn"
473
+ assert_contains "$out" "searched PATH for 'kimi'" "missing Kimi diagnostic omitted PATH"
474
+ assert_contains "$out" "fallback '$fallback'" "missing Kimi diagnostic omitted expanded fallback"
475
+ if grep -Eq '(^| )new-(session|window)( |$)' "$CASE_DIR/tmux-calls.log"; then
476
+ fail "missing Kimi executable created a tmux container or pane"
477
+ fi
478
+ pass "fm-spawn: missing Kimi executable refuses before pane creation"
479
+ }
480
+
481
+ test_kimi_unconfirmed_delivery_fails_loudly() {
482
+ local id rec out rc
483
+ id=kimi-drop-z2
484
+ rec=$(make_spawn_case drop "$id")
485
+ read_spawn_record "$rec"
486
+ rc=0
487
+ out=$(FM_FAKE_KIMI_DELIVERY=no run_spawn \
488
+ "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id") || rc=$?
489
+ [ "$rc" -ne 0 ] || fail "an unconfirmed kimi delivery should fail"
490
+ assert_contains "$out" "kimi brief pointer delivery was not confirmed" \
491
+ "unconfirmed kimi delivery lacked a loud diagnostic"
492
+ assert_grep 'failed: kimi brief pointer delivery was not confirmed' "$HOME_DIR/state/$id.status" \
493
+ "unconfirmed kimi delivery did not leave a supervisor-visible failure"
494
+ pass "fm-spawn: kimi treats a silent pointer drop as a failed spawn"
495
+ }
496
+
497
+ test_kimi_readiness_gate_precedes_pointer() {
498
+ local id rec out rc
499
+ id=kimi-not-ready-z3
500
+ rec=$(make_spawn_case not-ready "$id")
501
+ read_spawn_record "$rec"
502
+ rc=0
503
+ out=$(FM_FAKE_KIMI_READY=no run_spawn \
504
+ "$CASE_DIR" "$HOME_DIR" "$PROJ_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$id") || rc=$?
505
+ [ "$rc" -ne 0 ] || fail "kimi spawn without a ready signal should fail"
506
+ assert_contains "$out" "kimi did not show a verified ready signal" \
507
+ "kimi readiness failure lacked a loud diagnostic"
508
+ [ ! -s "$CASE_DIR/pointer.log" ] || fail "kimi pointer was sent before readiness"
509
+ jq -e --arg id "$id" 'any(.endpoints[]; .id == $id)' \
510
+ "$HOME_DIR/state/home-summary.json" >/dev/null \
511
+ || fail "kimi readiness failure omitted its durable endpoint from the home summary"
512
+ pass "fm-spawn: kimi never sends the brief pointer before an observable ready signal"
513
+ }
514
+
515
+ test_kimi_detection_uses_ancestry_after_markers() {
516
+ local dir fakebin cfg out
517
+ dir="$TMP_ROOT/detection"
518
+ fakebin=$(fm_fakebin "$dir")
519
+ cfg="$dir/config"
520
+ mkdir -p "$cfg"
521
+ cat > "$fakebin/ps" <<'SH'
522
+ #!/usr/bin/env bash
523
+ set -u
524
+ field=
525
+ pid=
526
+ prev=
527
+ for arg in "$@"; do
528
+ [ "$prev" = -o ] && field=$arg
529
+ [ "$prev" = -p ] && pid=$arg
530
+ prev=$arg
531
+ done
532
+ case "$field:$pid" in
533
+ comm=:4242) printf '/opt/kimi/bin/kimi\n' ;;
534
+ comm=:*) printf '/bin/bash\n' ;;
535
+ ppid=:4242) printf '1\n' ;;
536
+ ppid=:*) printf '4242\n' ;;
537
+ args=:*) printf 'bash\n' ;;
538
+ esac
539
+ SH
540
+ chmod +x "$fakebin/ps"
541
+
542
+ out=$(env -u CLAUDECODE -u PI_CODING_AGENT -u FM_PI_HARNESS -u GROK_AGENT \
543
+ -u CURSOR_AGENT -u CURSOR_INVOKED_AS \
544
+ PATH="$fakebin:$BASE_PATH" FM_CONFIG_OVERRIDE="$cfg" "$ROOT/bin/fm-harness.sh")
545
+ [ "$out" = kimi ] || fail "kimi ancestry detection returned '$out'"
546
+ out=$(env -u CURSOR_AGENT -u CURSOR_INVOKED_AS \
547
+ CLAUDECODE=1 PATH="$fakebin:$BASE_PATH" FM_CONFIG_OVERRIDE="$cfg" "$ROOT/bin/fm-harness.sh")
548
+ [ "$out" = claude ] || fail "verified env-marker precedence changed, got '$out'"
549
+ pass "fm-harness: markerless kimi is detected by ancestry after env-marker precedence"
550
+ }
551
+
552
+ test_kimi_session_lock_identity() {
553
+ local home fakebin out
554
+ home="$TMP_ROOT/session-lock-home"
555
+ fakebin=$(fm_fakebin "$TMP_ROOT/session-lock-fake")
556
+ mkdir -p "$home/state"
557
+ cat > "$fakebin/ps" <<'SH'
558
+ #!/usr/bin/env bash
559
+ case "$*" in
560
+ *"comm="*) printf '%s\n' '/opt/kimi/bin/kimi'; exit 0 ;;
561
+ *"args="*) printf '%s\n' 'kimi'; exit 0 ;;
562
+ esac
563
+ exit 1
564
+ SH
565
+ chmod +x "$fakebin/ps"
566
+
567
+ FM_HOME="$home" PATH="$fakebin:$BASE_PATH" "$ROOT/bin/fm-lock.sh" \
568
+ || fail "fm-lock did not acquire from Kimi ancestry"
569
+ case "$(cat "$home/state/.lock")" in
570
+ ''|*[!0-9]*) fail "fm-lock did not record the Kimi harness ancestor" ;;
571
+ esac
572
+ printf '%s\n' "$$" > "$home/state/.lock"
573
+ out=$(FM_HOME="$home" PATH="$fakebin:$BASE_PATH" "$ROOT/bin/fm-lock.sh" status)
574
+ assert_contains "$out" "lock: held by live harness pid" \
575
+ "fm-lock did not recognize Kimi as a live holder"
576
+ pass "fm-lock recognizes Kimi ancestry and live lock holders"
577
+ }
578
+
579
+ test_kimi_busy_signature_is_scoped_to_spinner_lines() {
580
+ local capture
581
+ # shellcheck source=/dev/null
582
+ . "$ROOT/bin/fm-tmux-lib.sh"
583
+ unset FM_BUSY_REGEX
584
+ capture="$TMP_ROOT/busy-pane"
585
+ tmux() {
586
+ case "${1:-}" in
587
+ capture-pane) cat "$capture" ;;
588
+ *) return 0 ;;
589
+ esac
590
+ }
591
+ # These fixtures reproduce the observed spinner shape rather than byte-exact
592
+ # transcriptions. Leading whitespace is deliberately varied; separator whitespace
593
+ # follows the captured contract.
594
+ local phase
595
+ for phase in ๐ŸŒ‘ ๐ŸŒ’ ๐ŸŒ“ ๐ŸŒ” ๐ŸŒ• ๐ŸŒ– ๐ŸŒ— ๐ŸŒ˜; do
596
+ printf ' %s ยท Tip: Kimi is working\nโ”‚ > โ”‚\n' "$phase" > "$capture"
597
+ fm_pane_is_busy fake kimi || fail "Kimi spinner phase $phase was not recognized as busy"
598
+ done
599
+ printf 'ordinary response ending with ๐ŸŒ•\nโ”‚ > โ”‚\n' > "$capture"
600
+ if fm_pane_is_busy fake kimi; then
601
+ fail "a moon outside Kimi's spinner-line shape was misread as busy"
602
+ fi
603
+ printf '๐ŸŒ• Full moon details\nโ”‚ > โ”‚\n' > "$capture"
604
+ if fm_pane_is_busy fake kimi; then
605
+ fail "moon-led Kimi output without the middot separator was misread as busy"
606
+ fi
607
+ printf ' ๐ŸŒ— ยท Tip: /plugins: manage plugins ...\nโ”‚ > โ”‚\n' > "$capture"
608
+ if fm_pane_is_busy fake codex; then
609
+ fail "Kimi's real spinner signature leaked into another harness"
610
+ fi
611
+ printf 'tip: ctrl+c: cancel\nโ”‚ > โ”‚\n' > "$capture"
612
+ if fm_pane_is_busy fake kimi; then
613
+ fail "kimi's independently rotating idle tip was misread as busy"
614
+ fi
615
+ printf 'Ctrl+c:cancel\nโ”‚ > โ”‚\n' > "$capture"
616
+ if fm_pane_is_busy fake kimi; then
617
+ fail "Grok's exact busy token leaked into Kimi's harness-scoped matcher"
618
+ fi
619
+ printf 'auto K2.7 Coding thinking /some/path\nโ”‚ > โ”‚\n' > "$capture"
620
+ if fm_pane_is_busy fake kimi; then
621
+ fail "Kimi's idle thinking-effort status label was misread as busy"
622
+ fi
623
+ pass "busy detection: real Kimi moon-plus-middot captures require its harness while idle labels stay idle"
624
+ }
625
+
626
+ test_watcher_never_classifies_kimi_from_its_spinner() (
627
+ local state="$TMP_ROOT/watch-state" busy_capture=' ๐ŸŒ‘ ยท Tip: ask Kimi to schedule tasks, e.g. "remind me at 5pm"'
628
+ mkdir -p "$state"
629
+ printf 'window=fake\nharness=kimi\n' > "$state/kimi-watch.meta"
630
+ unset FM_BUSY_REGEX
631
+ FM_HOME="$TMP_ROOT/watch-home"
632
+ FM_STATE_OVERRIDE="$state"
633
+ export FM_HOME FM_STATE_OVERRIDE
634
+ # shellcheck source=/dev/null
635
+ . "$ROOT/bin/fm-watch.sh"
636
+ # shellcheck disable=SC2329 # Runtime override called by the sourced watcher.
637
+ fm_backend_busy_state() { printf 'unknown'; }
638
+ # Standalone Kimi has no verified semantic busy source, so it classifies
639
+ # unknown - and unknown is never working. Its moon-phase spinner is
640
+ # deliberately not a state source: the approved redesign forbids inventing a
641
+ # Kimi UI signature, and that glyph set is locale- and emoji-font-sensitive.
642
+ if window_is_busy fake "$busy_capture"; then
643
+ fail "fm-watch classified a Kimi task busy from its spinner instead of unknown"
644
+ fi
645
+ [ "$(fm_busy_classify tmux fake kimi kimi-watch "$state" "$busy_capture")" = "unknown kimi-unverified" ] \
646
+ || fail "a Kimi task must classify unknown kimi-unverified"
647
+ printf 'window=fake\nharness=codex\n' > "$state/kimi-watch.meta"
648
+ if window_is_busy fake "$busy_capture"; then
649
+ fail "fm-watch applied Kimi's spinner to a recorded Codex task"
650
+ fi
651
+ printf 'window=fake\nharness=grok\n' > "$state/kimi-watch.meta"
652
+ if window_is_busy fake "$busy_capture"; then
653
+ fail "Kimi's spinner classified a recorded Grok task through its isolated fallback"
654
+ fi
655
+ window_is_busy fake 'Ctrl+c:cancel' \
656
+ || fail "Grok's own verified token must still classify a recorded Grok task busy"
657
+ pass "fm-watch classifies Kimi as unknown rather than from its spinner, and Grok's fallback stays isolated"
658
+ )
659
+
660
+ test_kimi_bordered_prompt_needs_no_override() {
661
+ local out
662
+ # shellcheck source=/dev/null
663
+ . "$ROOT/bin/fm-composer-lib.sh"
664
+ out=$(fm_composer_classify_content 1 '>')
665
+ [ "$out" = empty ] || fail "kimi's bordered bare > composer should read empty, got '$out'"
666
+ out=$(fm_composer_classify_content 0 '>')
667
+ [ "$out" = unknown ] || fail "an unbordered dead-shell > must stay unknown, got '$out'"
668
+ pass "composer classifier: kimi's existing bordered > shape is already safe without an override"
669
+ }
670
+
671
+ test_kimi_hook_install_is_surgical_idempotent_and_removable
672
+ test_kimi_hook_remove_preserves_owned_newline_boundary
673
+ test_kimi_hook_fails_closed_on_missing_malformed_or_partial_config
674
+ test_kimi_hook_install_refuses_without_jq
675
+ test_kimi_launch_then_send_is_verified
676
+ test_kimi_hook_is_silent_and_requires_registered_workspace_token
677
+ test_kimi_spawn_refuses_unsafe_global_config_before_pane_creation
678
+ test_kimi_teardown_removes_pointer_and_registry_token
679
+ test_kimi_falls_back_to_expanded_home_binary
680
+ test_kimi_missing_binary_refuses_before_pane_creation
681
+ test_kimi_unconfirmed_delivery_fails_loudly
682
+ test_kimi_readiness_gate_precedes_pointer
683
+ test_kimi_detection_uses_ancestry_after_markers
684
+ test_kimi_session_lock_identity
685
+ test_kimi_busy_signature_is_scoped_to_spinner_lines
686
+ test_watcher_never_classifies_kimi_from_its_spinner
687
+ test_kimi_bordered_prompt_needs_no_override