@zerwiz/ymir 0.1.3 → 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 -39
  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,970 @@
1
+ #!/usr/bin/env bash
2
+ # fm-session-start.sh - one command for the whole session start.
3
+ #
4
+ # Collapses AGENTS.md sections 3 (bootstrap) and 5 (recovery) into ONE script
5
+ # producing ONE ordered digest, so a session starts in one or two turns
6
+ # instead of the six-plus separate reads the old docs required: run
7
+ # fm-bootstrap.sh, then separately read data/projects.md, data/secondmates.md,
8
+ # data/captain.md, data/captain-shared.md, data/learnings.md, then run
9
+ # fm-lock.sh, fm-wake-drain.sh, then read data/backlog.md, every state/*.meta,
10
+ # and every state/*.status.
11
+ # Every one of those reads is UNCONDITIONAL at every session start, so they
12
+ # belong in a script, not in N agent turns.
13
+ #
14
+ # COMPOSITION, NOT DUPLICATION: this script calls fm-lock.sh, fm-bootstrap.sh,
15
+ # fm-wake-drain.sh, and fm-startup-network.sh as real subprocesses and prints
16
+ # their real output. It never re-implements their logic; all
17
+ # sequencing/formatting logic added here stays local to this file. Those four
18
+ # scripts remain fully working
19
+ # standalone with unchanged default behavior - other flows (fm-bootstrap.sh
20
+ # install <tools> after consent, /updatefirstmate, the afk daemon, existing
21
+ # tests) still call them directly. The one seam this script needed -
22
+ # bootstrap running its detect-only diagnostics without its six mutating
23
+ # sweeps - is an opt-in FM_BOOTSTRAP_DETECT_ONLY=1 flag on fm-bootstrap.sh
24
+ # itself (default unset/0 = unchanged behavior), not a fork.
25
+ #
26
+ # ORDERING, and why LOCK now runs before BOOTSTRAP (the old AGENTS.md order
27
+ # was bootstrap-then-lock):
28
+ #
29
+ # 1. lock - acquire the per-home session lock FIRST, before any
30
+ # mutating step runs.
31
+ # 2. bootstrap - home-local stale Herdr projection cleanup runs only
32
+ # when this session actually holds the lock. Detect-only
33
+ # diagnostics always run. Bootstrap's six MUTATING sweeps
34
+ # (same-home backlog reconciliation,
35
+ # secondmate convergence, secondmate liveness, pending remote
36
+ # handoff retry, X-mode artifact writes, fleet sync) also run only when
37
+ # locked; the four network sweeps run in the deferred
38
+ # stage rather than this synchronous bootstrap section.
39
+ # 3. inactive outcomes + wake-drain - runs the local bounded inactive-outcome
40
+ # reconciliation before presenting durable wakes and advancing
41
+ # recovery handling state, so both only run when locked.
42
+ # 4. supervision-instructions - the one emitted operating block for the
43
+ # detected primary harness.
44
+ # 5. read-once contract - the do-not-re-read contract covering every source
45
+ # represented by the two digests below.
46
+ # 6. fleet digest - a compact data/backlog.md identity/metadata listing,
47
+ # every state/*.meta, a bounded state/*.status tail,
48
+ # state/.afk, and a cheap per-task endpoint-liveness read:
49
+ # read-only, always runs.
50
+ # 7. network checks - the result of the deferred network stage started back at
51
+ # step 1, harvested WITHOUT waiting for it.
52
+ # 8. context digest - data/projects.md, data/secondmates.md, data/captain.md,
53
+ # data/captain-shared.md, data/learnings.md: read-only,
54
+ # always safe, always runs.
55
+ # 9. closing reminder - prints the context-specific watcher next step; this
56
+ # script points back to the emitted harness supervision
57
+ # block and deliberately never arms the watcher itself.
58
+ #
59
+ # Those nine names are also the runtime-bound stage list below, so a truncated
60
+ # startup can name exactly which of them never ran.
61
+ #
62
+ # NO NETWORK ON THE BLOCKING PATH. This digest runs on a session-open hook that
63
+ # blocks session initialization, so anything it waits for is time the captain
64
+ # waits before the first turn - and every external-network call it used to make
65
+ # was individually unbounded. One unreachable remote secondmate could burn the
66
+ # entire FM_SESSION_START_TIMEOUT and truncate the digest, so a slow network
67
+ # could cost the work queue itself.
68
+ # So no step between here and the last line below makes an external-network
69
+ # call. The five that did - `gh auth status`, secondmate liveness, secondmate
70
+ # convergence, pending remote handoff delivery, and the fleet-sync fetch - are
71
+ # started as one detached bounded worker right after the lock (step 1) and
72
+ # harvested at step 7 without ever blocking on it. bin/fm-startup-network.sh
73
+ # owns that stage and its safety argument; bin/fm-bootstrap.sh remains the owner
74
+ # of the sweeps themselves and still runs every one of them.
75
+ # The digest is therefore composed from local reads and local subprocesses only,
76
+ # and an unreachable host now delays a reported check rather than the startup.
77
+ # What this deliberately trades: on a slow network the digest prints "IN
78
+ # PROGRESS" and names exactly which checks are not yet confirmed, instead of
79
+ # waiting for them. It never reports an unconfirmed check as passed.
80
+ #
81
+ # ORDERING, and why FLEET STATE now runs before CONTEXT: this digest is
82
+ # delivered through a harness that truncates an oversized payload from the TAIL,
83
+ # and it has really been truncated in practice - a 70KB digest arrived as lines
84
+ # 1-435 of 578, cutting off eight lines before the live-task inventory. What a
85
+ # truncated tail drops must therefore be the CHEAPEST thing to lose. Curated
86
+ # memory is stable session to session, is already governed by a captain-set
87
+ # budget (config/startup-memory-budget), and is recoverable with one targeted
88
+ # read; live fleet identity - which tasks exist, their windows, worktrees,
89
+ # backends, and endpoint liveness - changes every session and is exactly what
90
+ # recovery depends on. So fleet state goes first and the memory files absorb the
91
+ # truncation. The read-once contract moves ahead of both for the same reason: a
92
+ # contract that only arrives after the payload it governs is the first thing a
93
+ # truncated digest loses, and it carries the truncation caveat that keeps it
94
+ # honest when a stage below it never ran.
95
+ # The LOCK/BOOTSTRAP/WAKE-QUEUE safety preamble keeps its order: it establishes
96
+ # mutation authority and this turn's work queue before anything else is read.
97
+ #
98
+ # On a Pi primary, the supervision-block step also checks whether Pi's two
99
+ # tracked primary extensions are loaded and prints a PI_WATCH_EXTENSION
100
+ # reminder line when one is missing.
101
+ #
102
+ # Why lock first: the old documented order (bootstrap, THEN lock) let a
103
+ # SECOND concurrent session run bootstrap's mutating sweeps - converging
104
+ # secondmate homes, retrying pending handoff outboxes, writing X-mode artifacts,
105
+ # and fetching or fast-forwarding every project clone - before ever discovering
106
+ # another session already holds the lock. Two sessions racing those sweeps is
107
+ # exactly the hazard the lock exists to prevent, so locking first closes the
108
+ # hole outright: only the session that actually wins the lock ever touches
109
+ # shared mutable state.
110
+ #
111
+ # The tradeoff this ordering accepts: a refused (read-only) session must not
112
+ # go dark. So on refusal, bootstrap still runs (in FM_BOOTSTRAP_DETECT_ONLY=1
113
+ # mode) for its local read-only detect lines - missing tools, the worktree-tangle
114
+ # check, the harness override, crew-dispatch validation, tasks-axi and quota-axi
115
+ # tool checks, and tasks-axi availability - none of which mutate shared state
116
+ # and all of which are safe to compute without verified lock ownership.
117
+ # It deliberately skips the network-only GitHub-auth probe because a read-only
118
+ # session has no dispatch, spawn, steer, or merge action for that verdict to gate.
119
+ # Only projection cleanup, the six bootstrap mutating sweeps, and wake-queue
120
+ # presentation are skipped.
121
+ # The context and fleet-state digests
122
+ # below are always read-only, so they run unconditionally in both modes.
123
+ #
124
+ # BACKLOG DIGEST: the startup listing is a RECOVERY input, not a reporting
125
+ # surface, so it carries what this turn can act on and nothing else.
126
+ # - `done` rows are never listed. Retained completion history belongs to the
127
+ # reporting surfaces (bin/fm-bearings-snapshot.sh, /ahoy), and at startup it
128
+ # is pure weight - 10 done rows cost 3.3KB in an observed main-home digest.
129
+ # - Every in-flight, held, and blocked row is listed IN FULL, with its
130
+ # hold_kind/hold_reason and blocked_by. Those are the rows AGENTS.md
131
+ # sections 7 and 10 make actionable at startup, so they are never bounded
132
+ # away.
133
+ # - Only the plain queued (dispatchable-now) listing is bounded, by
134
+ # FM_SESSION_START_QUEUED_LIMIT, default 20. Anything it omits is disclosed
135
+ # with an exact remainder count and the command that shows the rest, so a
136
+ # deep queue costs a counter rather than kilobytes.
137
+ # (This replaces FM_SESSION_START_BACKLOG_LIMIT, which bounded the whole
138
+ # listing indiscriminately and so could drop a held or blocked row.)
139
+ # When compatible tasks-axi is selected and available, the shared tasks-axi
140
+ # backend probe remains the compatibility owner and this script asks
141
+ # `tasks-axi list` for the compact identity fields plus blocked_by, hold_kind,
142
+ # and hold_reason, never body. The groups are the tool's own filters
143
+ # (`--state in_flight`, `--state held`, `--state queued --blocked`, and
144
+ # `tasks-axi ready`), so this script never reimplements task state; the groups
145
+ # can overlap, because an in-flight item that is also held appears under both.
146
+ # When manual mode is selected, or tasks-axi is unavailable or incompatible,
147
+ # this script prints only backlog section headings and item title lines, so
148
+ # title-line hold and blocked-by metadata remain visible while indented bodies
149
+ # stay out of the startup digest; the same never-bound-a-held-or-blocked-row
150
+ # rule applies, recognized there from the title line's own hold/blocked-by
151
+ # markers.
152
+ # Full bodies are targeted follow-up only: `tasks-axi show <id> --full` when
153
+ # compatible tasks-axi is available, or `data/backlog.md` when the file body is
154
+ # truly needed.
155
+ #
156
+ # STATUS TAILS: FM_SESSION_START_STATUS_TAIL bounds how many lines each task's
157
+ # tail prints, and bin/fm-line-cap-lib.sh bounds how long each of those lines
158
+ # may be. Both bounds are safe because the section prints every task's full
159
+ # status log path, and AGENTS.md section 8 treats a status line as a wake EVENT
160
+ # rather than current state - bin/fm-crew-state.sh owns current state.
161
+ #
162
+ # RUNTIME BOUND: the digest is now executed through a native session-open
163
+ # adapter (see bin/fm-sessionstart-run.sh), which blocks either hook-driven
164
+ # session initialization or Pi's first provider preflight while it runs, so an
165
+ # unbounded digest is no longer merely slow - it can strand a whole session or
166
+ # first turn behind one hung subprocess. Every remaining step is local, but
167
+ # local is not the same as bounded: tool version probes, the backlog listing,
168
+ # and the per-task endpoint reads are all unbounded subprocesses. So the whole
169
+ # digest still runs as ONE bounded child of this script
170
+ # (FM_SESSION_START_TIMEOUT, default 120s). The deferred network stage
171
+ # deliberately sits OUTSIDE that bound,
172
+ # in its own process group under its own aggregate deadline, so a truncated
173
+ # digest neither waits for it nor orphans it unbounded. The
174
+ # child writes the digest straight to this script's stdout, so everything it
175
+ # emitted before the bound was hit is already delivered; the parent then prints
176
+ # a loud STARTUP TRUNCATED banner naming the stage that did not finish and the
177
+ # sections that were therefore never emitted, and still exits 0. The child
178
+ # records its progress in FM_SESSION_START_STAGE_FILE, which is also the flag
179
+ # that tells a child it is the child - the parent never recurses.
180
+ # Hosts without timeout, gtimeout, or perl use the shared pure-Bash watchdog, so
181
+ # the digest never runs without the same hard bound and process-group cleanup.
182
+ #
183
+ # Usage: fm-session-start.sh [--reemit] [--source <source>]
184
+ # Prints the full ordered digest to stdout and always exits 0: this is a
185
+ # reporting command, not a gate. A lock refusal is reported as a loud
186
+ # banner inline, never a silent failure or a non-zero exit that would make
187
+ # an agent skip the rest of the digest.
188
+ #
189
+ # --reemit This process ALREADY took the helm at its own startup and has
190
+ # only lost its context (a /clear or a compaction). Skip the
191
+ # mutating sweeps that startup already reconciled - the stale Herdr
192
+ # projection cleanup and bootstrap's six mutating sweeps (fleet
193
+ # sync, same-home backlog reconciliation, secondmate convergence and
194
+ # liveness, pending remote handoff retry, X-mode
195
+ # artifact writes) - and
196
+ # re-emit the rest. Wake-queue presentation is NOT skipped: queued
197
+ # records are this turn's work queue, they arrived after startup,
198
+ # and a session that owns the lock is exactly the session that must
199
+ # handle and acknowledge them. Lock acquisition still runs, because
200
+ # ownership must be re-verified rather than assumed: fm-lock.sh already treats a lock
201
+ # this session's own harness holds as its own, so the re-emit
202
+ # proceeds, while a lock another live session took meanwhile still
203
+ # produces the ordinary read-only path.
204
+ #
205
+ # --source The native session-open source, supplied only by
206
+ # fm-sessionstart-run.sh. A genuine `startup` that owns the active
207
+ # session lock records AGENTS.md's SHA-256 baseline only after the
208
+ # digest completion record is published, keyed to that lock's
209
+ # harness pid. No resume, clear, reset, compact, or other rebuild
210
+ # creates or replaces it. Pi and pi-signed compaction are the only
211
+ # supported stale-cache rebuild pair: a missing baseline, a baseline
212
+ # for another harness pid, or a changed hash causes the complete
213
+ # current AGENTS.md to print before the bulky digest. The baseline
214
+ # remains immutable so every later drifted compaction refreshes
215
+ # again, while an equal baseline emits no instruction refresh.
216
+ set -u
217
+
218
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
219
+ FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
220
+ FM_HOME="${FM_HOME:-${FM_ROOT_OVERRIDE:-$FM_ROOT}}"
221
+ STATE="${FM_STATE_OVERRIDE:-$FM_HOME/state}"
222
+ DATA="${FM_DATA_OVERRIDE:-$FM_HOME/data}"
223
+ CONFIG="${FM_CONFIG_OVERRIDE:-$FM_HOME/config}"
224
+ COMPLETION_FILE="$STATE/.session-start-complete"
225
+ AGENTS_BASELINE_FILE="$STATE/.session-start-agents-baseline"
226
+
227
+ REEMIT=0
228
+ SESSION_SOURCE=
229
+ while [ "$#" -gt 0 ]; do
230
+ case "$1" in
231
+ --reemit)
232
+ REEMIT=1
233
+ shift
234
+ ;;
235
+ --source)
236
+ SESSION_SOURCE=${2:-}
237
+ if [ "$#" -ge 2 ]; then shift 2; else shift; fi
238
+ ;;
239
+ --source=*)
240
+ SESSION_SOURCE=${1#--source=}
241
+ shift
242
+ ;;
243
+ -h|--help)
244
+ sed -n '2,/^set -u$/p' "$SCRIPT_DIR/fm-session-start.sh" | sed 's/^# \{0,1\}//; $d'
245
+ exit 0
246
+ ;;
247
+ *)
248
+ printf 'fm-session-start: unknown argument: %s\n' "$1" >&2
249
+ printf 'usage: fm-session-start.sh [--reemit] [--source <source>]\n' >&2
250
+ exit 2
251
+ ;;
252
+ esac
253
+ done
254
+
255
+ # --- 0. runtime bound ---------------------------------------------------------
256
+ # The ordered stage list is the contract behind the truncation banner: the child
257
+ # names the stage it is entering, and the parent reports every stage at or after
258
+ # that one as never emitted. Keep it in the exact order the digest prints.
259
+ SESSION_START_STAGES='lock bootstrap wake-queue supervision-instructions read-once fleet-state network-checks context next-step'
260
+
261
+ stage() { # <stage-name>: breadcrumb for the parent's truncation banner
262
+ [ -n "${FM_SESSION_START_STAGE_FILE:-}" ] || return 0
263
+ printf '%s\n' "$1" > "$FM_SESSION_START_STAGE_FILE" 2>/dev/null || true
264
+ }
265
+
266
+ # shellcheck source=bin/fm-timeout-lib.sh
267
+ . "$SCRIPT_DIR/fm-timeout-lib.sh"
268
+ # shellcheck source=bin/fm-session-lock-lib.sh
269
+ . "$SCRIPT_DIR/fm-session-lock-lib.sh"
270
+
271
+ if [ -z "${FM_SESSION_START_STAGE_FILE:-}" ]; then
272
+ SESSION_START_BUDGET=${FM_SESSION_START_TIMEOUT:-120}
273
+ # A non-positive or non-numeric budget is not a budget (`timeout 0` disables
274
+ # the deadline outright), so an unusable value falls back to the default
275
+ # rather than silently removing the bound.
276
+ case "$SESSION_START_BUDGET" in ''|*[!0-9]*|0) SESSION_START_BUDGET=120 ;; esac
277
+ SESSION_START_STAGE_FILE=$(mktemp "${TMPDIR:-/tmp}/fm-session-start-stage.XXXXXX" 2>/dev/null) || SESSION_START_STAGE_FILE=
278
+ if [ -z "$SESSION_START_STAGE_FILE" ]; then
279
+ # Without a breadcrumb the bound still holds; only the banner's precision
280
+ # is lost, so the child still runs bounded.
281
+ SESSION_START_STAGE_FILE=/dev/null
282
+ fi
283
+ if [ "$REEMIT" -eq 1 ]; then
284
+ if [ -n "$SESSION_SOURCE" ]; then
285
+ fm_run_timed "$SESSION_START_BUDGET" \
286
+ env FM_SESSION_START_STAGE_FILE="$SESSION_START_STAGE_FILE" \
287
+ "$SCRIPT_DIR/fm-session-start.sh" --reemit --source "$SESSION_SOURCE"
288
+ else
289
+ fm_run_timed "$SESSION_START_BUDGET" \
290
+ env FM_SESSION_START_STAGE_FILE="$SESSION_START_STAGE_FILE" \
291
+ "$SCRIPT_DIR/fm-session-start.sh" --reemit
292
+ fi
293
+ elif [ -n "$SESSION_SOURCE" ]; then
294
+ fm_run_timed "$SESSION_START_BUDGET" \
295
+ env FM_SESSION_START_STAGE_FILE="$SESSION_START_STAGE_FILE" \
296
+ "$SCRIPT_DIR/fm-session-start.sh" --source "$SESSION_SOURCE"
297
+ else
298
+ fm_run_timed "$SESSION_START_BUDGET" \
299
+ env FM_SESSION_START_STAGE_FILE="$SESSION_START_STAGE_FILE" \
300
+ "$SCRIPT_DIR/fm-session-start.sh"
301
+ fi
302
+ SESSION_START_RC=$?
303
+ if [ "$SESSION_START_RC" -eq 124 ]; then
304
+ SESSION_START_LAST_STAGE=$(cat "$SESSION_START_STAGE_FILE" 2>/dev/null) || SESSION_START_LAST_STAGE=
305
+ [ -n "$SESSION_START_LAST_STAGE" ] || SESSION_START_LAST_STAGE=unknown
306
+ SESSION_START_PENDING=$(
307
+ printf '%s\n' "$SESSION_START_STAGES" | tr ' ' '\n' |
308
+ awk -v from="$SESSION_START_LAST_STAGE" '$0 == from {seen = 1} seen' | tr '\n' ' '
309
+ )
310
+ [ -n "${SESSION_START_PENDING# }" ] || SESSION_START_PENDING='(unknown - the digest may be incomplete anywhere)'
311
+ BAR='●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
312
+ printf '\n%s\n' "$BAR"
313
+ printf '● STARTUP TRUNCATED - SESSION START HIT ITS %ss RUNTIME BOUND\n' "$SESSION_START_BUDGET"
314
+ printf '● It stopped during the "%s" stage, so everything above is COMPLETE\n' "$SESSION_START_LAST_STAGE"
315
+ printf '● only up to that point.\n'
316
+ printf '● RECONCILE these stages before acting on anything they would have shown:\n'
317
+ printf '● %s\n' "${SESSION_START_PENDING% }"
318
+ printf '● Rerun bin/fm-session-start.sh now to finish taking the helm. If it truncates\n'
319
+ printf '● again, raise FM_SESSION_START_TIMEOUT and report the slow stage - a stage that\n'
320
+ printf '● cannot finish inside the bound is a fleet problem, not a reporting detail.\n'
321
+ printf '%s\n' "$BAR"
322
+ fi
323
+ rm -f "$SESSION_START_STAGE_FILE" 2>/dev/null || true
324
+ exit 0
325
+ fi
326
+
327
+ PRIMARY_HARNESS=$("$SCRIPT_DIR/fm-harness.sh" 2>/dev/null || printf unknown)
328
+
329
+ # shellcheck source=bin/fm-backend.sh
330
+ . "$SCRIPT_DIR/fm-backend.sh"
331
+ # shellcheck source=bin/fm-tasks-axi-lib.sh
332
+ . "$SCRIPT_DIR/fm-tasks-axi-lib.sh"
333
+ # shellcheck source=bin/fm-public-followup-lib.sh
334
+ . "$SCRIPT_DIR/fm-public-followup-lib.sh"
335
+ # shellcheck source=bin/fm-trace-context-lib.sh
336
+ . "$SCRIPT_DIR/fm-trace-context-lib.sh"
337
+ # shellcheck source=bin/fm-wake-lib.sh
338
+ . "$SCRIPT_DIR/fm-wake-lib.sh"
339
+ # shellcheck source=bin/fm-line-cap-lib.sh
340
+ . "$SCRIPT_DIR/fm-line-cap-lib.sh"
341
+
342
+ # One tasks-axi compatibility verdict per session start. The probe costs three
343
+ # tasks-axi subprocesses and this digest needs the same answer twice - here for
344
+ # the backlog listing and again inside the fm-bootstrap.sh child, which reports
345
+ # an incompatible build as MISSING. Computing it once and handing it to that
346
+ # child collapses six subprocesses to three. fm-tasks-axi-lib.sh owns both reuse
347
+ # layers and the one-hop consumption rule that keeps the verdict out of any
348
+ # agent's environment.
349
+ if fm_tasks_axi_compatible; then TASKS_AXI_COMPATIBLE=1; else TASKS_AXI_COMPATIBLE=0; fi
350
+
351
+ STATUS_TAIL=${FM_SESSION_START_STATUS_TAIL:-5}
352
+ case "$STATUS_TAIL" in ''|*[!0-9]*) STATUS_TAIL=5 ;; esac
353
+ QUEUED_LIMIT=${FM_SESSION_START_QUEUED_LIMIT:-20}
354
+ case "$QUEUED_LIMIT" in ''|*[!0-9]*|0) QUEUED_LIMIT=20 ;; esac
355
+ BACKLOG_FIELDS=blocked_by,hold_kind,hold_reason
356
+
357
+ RULE='================================================================================'
358
+ SUBRULE='--------------------------------------------------------------------------------'
359
+
360
+ section() { printf '\n%s\n%s\n%s\n' "$RULE" "$1" "$RULE"; }
361
+ subsection() { printf '\n%s\n%s\n' "$1" "$SUBRULE"; }
362
+
363
+ # print_file_or_absent <path> <label>: full contents under a labeled
364
+ # subsection, or an explicit ABSENT marker. Absence is semantically
365
+ # meaningful for every one of these files (captain.md absent = firstmate
366
+ # repo built-in defaults, projects.md absent = rebuild from clones, etc. -
367
+ # AGENTS.md section 3) and must never be confused with an empty-but-present
368
+ # file, so the two cases print differently.
369
+ print_file_or_absent() {
370
+ local path=$1 label=$2
371
+ subsection "$label"
372
+ if [ -f "$path" ]; then
373
+ if [ -s "$path" ]; then
374
+ cat "$path"
375
+ else
376
+ printf '(present, empty)\n'
377
+ fi
378
+ else
379
+ printf 'ABSENT\n'
380
+ fi
381
+ }
382
+
383
+ print_backlog_pointer() {
384
+ printf 'Full task bodies remain available on demand: tasks-axi show <id> --full when compatible tasks-axi is available, or data/backlog.md.\n'
385
+ }
386
+
387
+ # A queued title line whose own text already marks it held or blocked. The
388
+ # manual renderer has no task model, so this is the only signal it gets, and it
389
+ # is the one tasks-axi's markdown backend writes: "(hold: ...)", "(hold-kind:
390
+ # ...)", and "blocked-by: ...". Bracket expressions rather than backslashes,
391
+ # because awk's -v applies escape processing before the regex is ever compiled.
392
+ MANUAL_KEEP_RE='[(]hold|blocked-by:'
393
+
394
+ print_backlog_manual_compact() {
395
+ local path=$1 reason=$2
396
+ printf 'compact backlog listing (%s; done rows omitted; every in-flight, held, and blocked title line kept; other queued bounded to %s; indented task bodies omitted)\n' \
397
+ "$reason" "$QUEUED_LIMIT"
398
+ awk -v max="$QUEUED_LIMIT" -v keep_re="$MANUAL_KEEP_RE" '
399
+ function state_for_heading(line, heading) {
400
+ heading = line
401
+ sub(/^##[[:space:]]+/, "", heading)
402
+ sub(/[[:space:]]+$/, "", heading)
403
+ if (heading == "In flight") return "in_flight"
404
+ if (heading == "Queued") return "queued"
405
+ if (heading == "Done") return "done"
406
+ return ""
407
+ }
408
+ /^##[[:space:]]+/ {
409
+ state = state_for_heading($0)
410
+ # The Done heading is recognized so its items are skipped, never printed.
411
+ if (state != "" && state != "done") print $0
412
+ next
413
+ }
414
+ state == "in_flight" && /^[-*][[:space:]]+/ { in_flight++; print $0; next }
415
+ state == "done" && /^[-*][[:space:]]+/ { done_total++; next }
416
+ state == "queued" && /^[-*][[:space:]]+/ {
417
+ queued_total++
418
+ if ($0 ~ keep_re) { gated++; print $0; next }
419
+ if (plain_shown < max) { plain_shown++; print $0 }
420
+ next
421
+ }
422
+ END {
423
+ plain_total = queued_total - gated
424
+ if (in_flight + queued_total + done_total == 0) {
425
+ print "(no backlog item title lines found)"
426
+ } else {
427
+ printf "(shown %d in-flight, %d held or blocked queued, %d of %d other queued title line(s); %d done row(s) omitted)\n", \
428
+ in_flight, gated, plain_shown, plain_total, done_total
429
+ if (plain_total > plain_shown) {
430
+ printf "(%d more queued - raise FM_SESSION_START_QUEUED_LIMIT or read data/backlog.md for the rest)\n", plain_total - plain_shown
431
+ }
432
+ }
433
+ }
434
+ ' "$path"
435
+ }
436
+
437
+ # tasks-axi closes every listing with its own help block. This section composes
438
+ # four listings, so keeping them would repeat the same pointers four times, once
439
+ # per group, each carrying this home's full backlog path. The section prints one
440
+ # equivalent pointer of its own (print_backlog_pointer), so the per-group help
441
+ # blocks stop at their `help[` header instead.
442
+ strip_axi_help() {
443
+ awk '/^help\[/ { exit } { print }'
444
+ }
445
+
446
+ # Bound the dispatchable-now listing without rewriting the tool's own rendering:
447
+ # `tasks-axi ready` rows are the indented lines under its ready[N]{...} header,
448
+ # and every other line it prints (its count, its public-followup line) passes
449
+ # through untouched. Whatever is cut is disclosed exactly.
450
+ print_ready_queued_bounded() {
451
+ local ready=$1 path=$2
452
+ printf '%s\n' "$ready" | awk -v max="$QUEUED_LIMIT" -v path="$path" '
453
+ /^help\[/ { exit }
454
+ /^ready\[/ { rows = 1; print; next }
455
+ rows && /^[[:space:]]/ {
456
+ total++
457
+ if (shown < max) { print; shown++ }
458
+ next
459
+ }
460
+ { rows = 0; print }
461
+ END {
462
+ if (total > 0) {
463
+ printf "(shown %d of %d ready queued item(s))\n", shown, total
464
+ if (total > shown) {
465
+ printf "(%d more queued - tasks-axi ready --file %s)\n", total - shown, path
466
+ }
467
+ }
468
+ }
469
+ '
470
+ }
471
+
472
+ print_backlog_tasks_axi_compact() {
473
+ local path=$1 in_flight held blocked ready err
474
+ if ! in_flight=$(tasks-axi list --file "$path" --state in_flight --fields "$BACKLOG_FIELDS" 2>&1); then
475
+ err=$in_flight
476
+ elif ! held=$(tasks-axi list --file "$path" --state held --fields "$BACKLOG_FIELDS" 2>&1); then
477
+ err=$held
478
+ elif ! blocked=$(tasks-axi list --file "$path" --state queued --blocked --fields "$BACKLOG_FIELDS" 2>&1); then
479
+ err=$blocked
480
+ elif ! ready=$(tasks-axi ready --file "$path" 2>&1); then
481
+ err=$ready
482
+ else
483
+ printf 'compact backlog listing (tasks-axi; done rows omitted; every in-flight, held, and blocked row shown in full; ready queued bounded to %s; task bodies omitted)\n' \
484
+ "$QUEUED_LIMIT"
485
+ printf '\nin flight:\n'
486
+ printf '%s\n' "$in_flight" | strip_axi_help
487
+ printf '\nheld (captain- or time-gated; an in-flight item that is also held appears in both groups):\n'
488
+ printf '%s\n' "$held" | strip_axi_help
489
+ printf '\nblocked queued:\n'
490
+ printf '%s\n' "$blocked" | strip_axi_help
491
+ printf '\nready queued (dispatchable now):\n'
492
+ print_ready_queued_bounded "$ready" "$path"
493
+ return 0
494
+ fi
495
+ printf 'tasks-axi compact listing failed; falling back to title-line rendering.\n'
496
+ printf '%s\n' "$err"
497
+ print_backlog_manual_compact "$path" "fallback"
498
+ }
499
+
500
+ print_backlog_compact() {
501
+ local path=$1 label=$2
502
+ subsection "$label"
503
+ if [ -f "$path" ]; then
504
+ if [ -s "$path" ]; then
505
+ if fm_tasks_axi_backend_available "$CONFIG"; then
506
+ print_backlog_tasks_axi_compact "$path"
507
+ elif fm_backlog_backend_manual "$CONFIG"; then
508
+ print_backlog_manual_compact "$path" "manual backend"
509
+ else
510
+ print_backlog_manual_compact "$path" "tasks-axi unavailable or incompatible"
511
+ fi
512
+ print_backlog_pointer
513
+ else
514
+ printf '(present, empty)\n'
515
+ fi
516
+ else
517
+ printf 'ABSENT\n'
518
+ fi
519
+ }
520
+
521
+ print_status_tail() {
522
+ local status=$1 line
523
+ printf 'status tail (last %s line(s), each capped at %s characters, wake-EVENT history, not current state; full log: %s):\n' \
524
+ "$STATUS_TAIL" "$FM_LINE_CAP_DEFAULT" "$status"
525
+ # A crewmate writes its own status lines, so their length is unbounded: one
526
+ # observed line ran 865 characters. Cap each one the way the wake digest's
527
+ # OPEN DECISIONS section does; the lede carries the state word and the key,
528
+ # and the full log path above reaches the rest.
529
+ while IFS= read -r line || [ -n "$line" ]; do
530
+ fm_cap_line "$line"
531
+ done < <(tail -n "$STATUS_TAIL" "$status")
532
+ }
533
+
534
+ hash_file_sha256() {
535
+ local file=$1 digest
536
+ [ -f "$file" ] || return 1
537
+ if command -v shasum >/dev/null 2>&1; then
538
+ digest=$(shasum -a 256 "$file" 2>/dev/null | awk '
539
+ length($1) == 64 && $1 !~ /[^[:xdigit:]]/ { print "sha256:" $1; found=1; exit }
540
+ END { if (!found) exit 1 }
541
+ ') && [ -n "$digest" ] && { printf '%s\n' "$digest"; return 0; }
542
+ fi
543
+ if command -v sha256sum >/dev/null 2>&1; then
544
+ digest=$(sha256sum "$file" 2>/dev/null | awk '
545
+ length($1) == 64 && $1 !~ /[^[:xdigit:]]/ { print "sha256:" $1; found=1; exit }
546
+ END { if (!found) exit 1 }
547
+ ') && [ -n "$digest" ] && { printf '%s\n' "$digest"; return 0; }
548
+ fi
549
+ return 1
550
+ }
551
+
552
+ # The baseline describes instructions this true session started with, not the
553
+ # most recently emitted instructions. It is intentionally immutable for this
554
+ # lock owner: every later stale-context rebuild needs the current file again.
555
+ write_agents_baseline() { # <lock-pid> <agents-hash>
556
+ local lock_pid=$1 agents_hash=$2 tmp
557
+ [ -n "$lock_pid" ] && [ -n "$agents_hash" ] || return 1
558
+ tmp=$(mktemp "$STATE/.session-start-agents-baseline.XXXXXX" 2>/dev/null) || return 1
559
+ if printf '%s\n%s\n' "$lock_pid" "$agents_hash" > "$tmp" 2>/dev/null \
560
+ && mv -f "$tmp" "$AGENTS_BASELINE_FILE" 2>/dev/null; then
561
+ return 0
562
+ fi
563
+ rm -f "$tmp" 2>/dev/null || true
564
+ return 1
565
+ }
566
+
567
+ agents_baseline_drifted() { # <rebuilding-session-pid>
568
+ local lock_pid=$1 baseline_pid baseline_hash current_hash
569
+ [ -f "$AGENTS_BASELINE_FILE" ] && [ ! -L "$AGENTS_BASELINE_FILE" ] || return 0
570
+ baseline_pid=$(sed -n '1p' "$AGENTS_BASELINE_FILE" 2>/dev/null || true)
571
+ baseline_hash=$(sed -n '2p' "$AGENTS_BASELINE_FILE" 2>/dev/null || true)
572
+ current_hash=$(hash_file_sha256 "$FM_ROOT/AGENTS.md" 2>/dev/null || true)
573
+ [ -n "$current_hash" ] || return 0
574
+ [ "$baseline_pid" = "$lock_pid" ] && [ "$baseline_hash" = "$current_hash" ] && return 1
575
+ return 0
576
+ }
577
+
578
+ # Only run-tier source pairs with both a stale native instruction cache and a
579
+ # working Firstmate delivery path arrive here. Claude fresh-reads on reset, and
580
+ # Codex has no tracked interactive reset delivery path.
581
+ agents_refresh_required() { # <rebuilding-session-pid>
582
+ local lock_pid=$1
583
+ case "$PRIMARY_HARNESS:$SESSION_SOURCE" in
584
+ pi:compact|pi-signed:compact) ;;
585
+ *) return 1 ;;
586
+ esac
587
+ agents_baseline_drifted "$lock_pid"
588
+ }
589
+
590
+ print_agents_refresh_if_required() { # <rebuilding-session-pid>
591
+ local lock_pid=$1
592
+ agents_refresh_required "$lock_pid" || return 0
593
+ section "CURRENT AGENTS.md - INSTRUCTION REFRESH"
594
+ if [ -f "$FM_ROOT/AGENTS.md" ]; then
595
+ cat <<'EOF'
596
+ The complete on-disk AGENTS.md below supersedes the instruction copy this session
597
+ started with. Apply it as the current Firstmate instruction contract.
598
+
599
+ EOF
600
+ cat "$FM_ROOT/AGENTS.md"
601
+ else
602
+ printf 'The original AGENTS.md baseline no longer matches, but the current file is absent.\n'
603
+ fi
604
+ }
605
+
606
+ AGENTS_START_HASH=
607
+ if [ "$REEMIT" -eq 0 ] && [ "$SESSION_SOURCE" = startup ]; then
608
+ AGENTS_START_HASH=$(hash_file_sha256 "$FM_ROOT/AGENTS.md" 2>/dev/null || true)
609
+ fi
610
+
611
+ if [ "$REEMIT" -eq 1 ]; then
612
+ section "SESSION START (CONTEXT RE-EMIT) - $FM_HOME"
613
+ printf 'This session already took the helm at its own startup and has only lost its\n'
614
+ printf 'context. Lock ownership is re-verified and the durable records below are\n'
615
+ printf 'reprinted, but the sweeps startup already reconciled - project clone refresh,\n'
616
+ printf 'secondmate convergence and liveness, pending remote handoff\n'
617
+ printf 'retry, X-mode artifact writes, and stale Herdr child cleanup - are NOT repeated.\n'
618
+ printf 'Queued wakes ARE still drained: they arrived after startup and are this turn work.\n'
619
+ else
620
+ section "SESSION START - $FM_HOME"
621
+ fi
622
+ # --- 1. lock -----------------------------------------------------------
623
+ stage lock
624
+ subsection "LOCK"
625
+ LOCK_OUT=$("$SCRIPT_DIR/fm-lock.sh" 2>&1)
626
+ LOCK_RC=$?
627
+ printf '%s\n' "$LOCK_OUT"
628
+ READ_ONLY=0
629
+ if [ "$LOCK_RC" -ne 0 ]; then
630
+ READ_ONLY=1
631
+ BAR='●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
632
+ {
633
+ printf '%s\n' "$BAR"
634
+ printf '● READ-ONLY SESSION - FLEET LOCK OWNERSHIP WAS NOT VERIFIED\n'
635
+ printf '● %s\n' "$LOCK_OUT"
636
+ printf '● Skipping every mutating step: stale Herdr child cleanup,\n'
637
+ printf '● secondmate convergence, secondmate liveness, pending remote handoff retry,\n'
638
+ printf '● X-mode artifacts, fleet sync, and wake-queue drain. Detect-only bootstrap\n'
639
+ printf '● diagnostics and the rest of this read-only-safe digest still ran below.\n'
640
+ printf '● Operate read-only until this resolves - do not spawn, steer, merge, or\n'
641
+ printf '● otherwise mutate fleet state from this session.\n'
642
+ printf '%s\n' "$BAR"
643
+ }
644
+ fi
645
+ REBUILDING_SESSION_PID=$(fm_harness_ancestry_pid 2>/dev/null || true)
646
+ print_agents_refresh_if_required "$REBUILDING_SESSION_PID"
647
+
648
+ if [ "$READ_ONLY" -eq 0 ]; then
649
+ if [ "$REEMIT" -eq 0 ]; then
650
+ rm -f "$COMPLETION_FILE" 2>/dev/null || true
651
+ fi
652
+ fm_trace_context_session_start "$CONFIG" "$STATE/.trace-context-effective"
653
+ # A full locked start publishes this home's current structured summary.
654
+ # Publication is side-band and best-effort, so it can never change the
655
+ # session-start result. A context re-emit is not another session start.
656
+ if [ "$REEMIT" -eq 0 ]; then
657
+ "$SCRIPT_DIR/fm-home-summary-refresh.sh" --best-effort || true
658
+ fi
659
+ # Every network call this session start owes is launched HERE, detached and
660
+ # bounded, so it runs concurrently with the whole digest below instead of in
661
+ # front of it. Step 7 harvests whatever it has finished, without ever waiting.
662
+ # --reemit passes --locked 0 for the same reason it runs bootstrap detect-only:
663
+ # this process already ran the mutating sweeps at its own startup, so only the
664
+ # read-only GitHub-auth probe is owed. A read-only session starts nothing at
665
+ # all: it holds no mutation authority for the sweeps, and it must not spawn,
666
+ # steer, or merge anyway, so it has no action left for an auth verdict to gate.
667
+ NETWORK_STAGE_LOCKED=1
668
+ [ "$REEMIT" -eq 0 ] || NETWORK_STAGE_LOCKED=0
669
+ "$SCRIPT_DIR/fm-startup-network.sh" start \
670
+ --locked "$NETWORK_STAGE_LOCKED" --harvest-pid $$ >/dev/null 2>&1 || true
671
+ fi
672
+
673
+ # --- 2. bootstrap --------------------------------------------------------
674
+ # FM_BOOTSTRAP_NETWORK=skip on every path: bootstrap's own network half is what
675
+ # the deferred stage above is running right now, and running it twice would both
676
+ # re-block this digest and race the worker's sweeps against themselves.
677
+ stage bootstrap
678
+ subsection "BOOTSTRAP"
679
+ if [ "$READ_ONLY" -eq 1 ]; then
680
+ BOOT_OUT=$(FM_BOOTSTRAP_DETECT_ONLY=1 FM_BOOTSTRAP_NETWORK=skip \
681
+ FM_TASKS_AXI_COMPATIBLE="$TASKS_AXI_COMPATIBLE" "$SCRIPT_DIR/fm-bootstrap.sh" 2>&1)
682
+ elif [ "$REEMIT" -eq 1 ]; then
683
+ BOOT_OUT=$(FM_BOOTSTRAP_DETECT_ONLY=1 FM_BOOTSTRAP_LOCKED=1 FM_BOOTSTRAP_NETWORK=skip \
684
+ FM_TASKS_AXI_COMPATIBLE="$TASKS_AXI_COMPATIBLE" "$SCRIPT_DIR/fm-bootstrap.sh" 2>&1)
685
+ else
686
+ BOOT_OUT=$(
687
+ "$SCRIPT_DIR/fm-herdr-session-cleanup.sh" 2>&1 || true
688
+ FM_BOOTSTRAP_NETWORK=skip FM_TASKS_AXI_COMPATIBLE="$TASKS_AXI_COMPATIBLE" \
689
+ "$SCRIPT_DIR/fm-bootstrap.sh" 2>&1
690
+ )
691
+ fi
692
+ if [ -n "$BOOT_OUT" ]; then
693
+ printf '%s\n' "$BOOT_OUT"
694
+ else
695
+ printf '(silent - all good)\n'
696
+ fi
697
+
698
+ # --- 3. inactive outcomes + wake-drain -----------------------------------
699
+ # The existing locked session-start path runs the same local inactive-outcome
700
+ # reconciliation as the watcher poll before it presents the resulting durable
701
+ # wake, without adding a daemon or external-network call.
702
+ # Presented records are this turn's first work queue and remain durable until
703
+ # post-handling acknowledgement. The drain's separate OPEN DECISIONS section
704
+ # remains actionable even when that queue is empty (AGENTS.md sections 3 and 8).
705
+ # The drain also runs fm-guard.sh internally on the locked path, so the
706
+ # tangle/watcher-liveness alarms land right here too, ahead of the bulk digest
707
+ # below. The read-only path never touches the queue because it lacks mutation
708
+ # authority, and another session may be actively handling it. It still runs
709
+ # fm-guard.sh directly with non-mutating advisory text, so the same alarms
710
+ # surface without repair commands.
711
+ stage wake-queue
712
+ subsection "WAKE QUEUE"
713
+ if [ "$READ_ONLY" -eq 1 ]; then
714
+ QLEN=0
715
+ [ -s "$STATE/.wake-queue" ] && QLEN=$(grep -c . "$STATE/.wake-queue" 2>/dev/null || printf '0')
716
+ printf 'skipped (read-only session) - %s record(s) remain queued because this session lacks verified fleet-lock ownership.\n' "$QLEN"
717
+ GUARD_OUT=$(FM_GUARD_READ_ONLY=1 "$SCRIPT_DIR/fm-guard.sh" 2>&1)
718
+ [ -n "$GUARD_OUT" ] && printf '%s\n' "$GUARD_OUT"
719
+ else
720
+ INACTIVE_OUT=$(FM_HOME="$FM_HOME" FM_STATE_OVERRIDE="$STATE" \
721
+ "$SCRIPT_DIR/fm-inactive-reconcile.sh" scan --startup 2>&1) || INACTIVE_OUT=
722
+ if [ -n "$INACTIVE_OUT" ]; then
723
+ printf 'inactive outcome reconciliation: %s\n' "$INACTIVE_OUT"
724
+ fi
725
+ # Pi supervision-branch recovery, locked path only: clear leases whose
726
+ # supervising session died, and surface outcomes the branch stored durably
727
+ # that never reached main (docs/pi-supervision-branch.md). Gated to the
728
+ # pi/pi-signed primary so a non-Pi home runs neither step - homes on any
729
+ # other harness stay entirely untouched (captain-decided criterion).
730
+ if [ "$PRIMARY_HARNESS" = pi ] || [ "$PRIMARY_HARNESS" = pi-signed ]; then
731
+ FM_HOME="$FM_HOME" FM_STATE_OVERRIDE="$STATE" "$SCRIPT_DIR/fm-lease.sh" sweep 2>/dev/null || true
732
+ BRANCH_REPLAY_OUT=$(FM_HOME="$FM_HOME" FM_STATE_OVERRIDE="$STATE" \
733
+ "$SCRIPT_DIR/fm-branch-outcome.sh" startup-replay 2>&1) || BRANCH_REPLAY_OUT=
734
+ if [ -n "$BRANCH_REPLAY_OUT" ]; then
735
+ printf '%s\n' "$BRANCH_REPLAY_OUT"
736
+ fi
737
+ fi
738
+ DRAIN_OUT=$("$SCRIPT_DIR/fm-wake-drain.sh" 2>&1)
739
+ if [ -n "$DRAIN_OUT" ]; then
740
+ printf '%s\n' "$DRAIN_OUT"
741
+ else
742
+ printf '(no queued wakes)\n'
743
+ fi
744
+ fi
745
+
746
+ # --- 4. supervision operating instructions ----------------------------------
747
+ stage supervision-instructions
748
+ AFK_PRESENT=0
749
+ [ -e "$STATE/.afk" ] && AFK_PRESENT=1
750
+ X_MODE_PRESENT=0
751
+ [ -f "$CONFIG/x-mode.env" ] && X_MODE_PRESENT=1
752
+
753
+ if [ "$PRIMARY_HARNESS" = pi ] || [ "$PRIMARY_HARNESS" = pi-signed ]; then
754
+ PI_EXT="$FM_ROOT/.pi/extensions/fm-primary-pi-watch.ts"
755
+ PI_TURNEND_EXT="$FM_ROOT/.pi/extensions/fm-primary-turnend-guard.ts"
756
+ PI_WATCH_MARKER="$STATE/.pi-watch-extension-loaded"
757
+ PI_TURNEND_MARKER="$STATE/.pi-turnend-extension-loaded"
758
+ PI_LOCK="$STATE/.lock"
759
+ PI_RESTART_COMMAND=$PRIMARY_HARNESS
760
+ [ "$PRIMARY_HARNESS" != pi ] || PI_RESTART_COMMAND='plain pi'
761
+ PI_WATCH_VERSION=$(fm_pi_extension_version "$PI_EXT" || printf '')
762
+ PI_TURNEND_VERSION=$(fm_pi_extension_version "$PI_TURNEND_EXT" || printf '')
763
+ if ! fm_pi_extension_loaded "$PI_WATCH_MARKER" "$PI_WATCH_VERSION" "$PI_LOCK" \
764
+ || ! fm_pi_extension_loaded "$PI_TURNEND_MARKER" "$PI_TURNEND_VERSION" "$PI_LOCK"; then
765
+ printf 'PI_WATCH_EXTENSION: not loaded - approve Pi project trust once per clone, then restart %s so %s and %s auto-load for turn-end guard and background wake coverage; use -e %s -e %s only if project hooks are not trusted\n' "$PI_RESTART_COMMAND" "$PI_TURNEND_EXT" "$PI_EXT" "$PI_TURNEND_EXT" "$PI_EXT"
766
+ fi
767
+ fi
768
+ "$SCRIPT_DIR/fm-supervision-instructions.sh" \
769
+ --harness "$PRIMARY_HARNESS" \
770
+ --read-only "$READ_ONLY" \
771
+ --afk "$AFK_PRESENT" \
772
+ --x-mode "$X_MODE_PRESENT"
773
+
774
+ # --- 5. read-once contract -------------------------------------------------
775
+ # Ahead of the two digests it governs, not after them: a truncated tail is
776
+ # exactly what drops a closing reminder, and this contract is what stops the
777
+ # next turn from re-reading everything the digest just printed. Because it now
778
+ # arrives BEFORE its subject, it also names the one condition that voids it -
779
+ # a stage that never ran, which the truncation banner names by stage.
780
+ stage read-once
781
+ section "READ-ONCE CONTRACT"
782
+ cat <<'EOF'
783
+ Everything below is printed in full for this session start: every state/*.meta,
784
+ a compact data/backlog.md listing, a bounded tail of every state/*.status,
785
+ data/projects.md, data/secondmates.md, data/captain.md, data/captain-shared.md,
786
+ and data/learnings.md.
787
+ Do NOT re-read any of them after reading this digest, and do NOT bulk-read
788
+ data/backlog.md or state/*.status: re-reading everything defeats the entire
789
+ point of this command.
790
+
791
+ Go to a source directly only when:
792
+ - this digest flagged it ABSENT (then rebuild or create it per AGENTS.md),
793
+ - its contents looked unparseable or corrupt,
794
+ - an individual full status log is needed for older wake-event history, or a
795
+ status line was capped and its tail matters (each task's full log path is
796
+ printed with its tail),
797
+ - a full task body is needed (tasks-axi show <id> --full, or data/backlog.md),
798
+ - the backlog listing disclosed omitted queued items and this turn needs them,
799
+ - the NETWORK CHECKS section reported its checks still IN PROGRESS and this
800
+ turn needs their verdict (bin/fm-startup-network.sh report),
801
+ - or a STARTUP TRUNCATED banner named the stage that would have printed it, in
802
+ which case that stage's sources were never emitted and must be reconciled.
803
+ EOF
804
+
805
+ # --- 6. fleet-state digest ---------------------------------------------
806
+ # Before CONTEXT: see this file's ORDERING note. Live fleet identity is what a
807
+ # truncated tail must never take.
808
+ stage fleet-state
809
+ section "FLEET STATE"
810
+ print_backlog_compact "$DATA/backlog.md" "data/backlog.md"
811
+
812
+ subsection "Work under way (state/*.meta)"
813
+ META_FOUND=0
814
+ for meta in "$STATE"/*.meta; do
815
+ [ -f "$meta" ] || continue
816
+ META_FOUND=1
817
+ id=$(basename "$meta" .meta)
818
+ printf '\n--- %s ---\n' "$id"
819
+ cat "$meta"
820
+
821
+ window=$(fm_meta_get "$meta" window)
822
+ target=$(fm_backend_target_of_meta "$meta")
823
+ if [ -n "$window" ]; then
824
+ backend=$(fm_backend_of_meta "$meta")
825
+ if fm_backend_target_exists "$backend" "${target:-$window}" "fm-$id"; then
826
+ printf 'endpoint: alive (backend=%s window=%s)\n' "$backend" "$window"
827
+ else
828
+ printf 'endpoint: dead (backend=%s window=%s)\n' "$backend" "$window"
829
+ fi
830
+ else
831
+ printf 'endpoint: unknown (no window recorded)\n'
832
+ fi
833
+
834
+ status="$STATE/$id.status"
835
+ if [ -f "$status" ]; then
836
+ print_status_tail "$status"
837
+ else
838
+ printf 'status tail: (no status file yet: %s)\n' "$status"
839
+ fi
840
+ done
841
+ [ "$META_FOUND" -eq 1 ] || printf '(none)\n'
842
+
843
+ subsection "Orphan status logs (state/*.status without matching .meta)"
844
+ ORPHAN_STATUS_FOUND=0
845
+ for status in "$STATE"/*.status; do
846
+ [ -f "$status" ] || continue
847
+ id=$(basename "$status" .status)
848
+ [ -f "$STATE/$id.meta" ] && continue
849
+ ORPHAN_STATUS_FOUND=1
850
+ printf '\n--- %s ---\n' "$id"
851
+ print_status_tail "$status"
852
+ done
853
+ [ "$ORPHAN_STATUS_FOUND" -eq 1 ] || printf '(none)\n'
854
+
855
+ subsection "AFK"
856
+ if [ -e "$STATE/.afk" ]; then
857
+ printf 'present - away-mode supervision is active; the daemon owns the watcher.\n'
858
+ else
859
+ printf 'absent\n'
860
+ fi
861
+
862
+ # Public commitments made through the myfirstmate relay. A promise to reply in a
863
+ # public thread must survive compaction and restart, so it is surfaced from disk
864
+ # here rather than from conversation memory. fm-public-followup-lib.sh owns both
865
+ # gates: a home that never opted into the relay runs one [ -f ] test, prints no
866
+ # subsection, and never reaches fm-public-followup.sh.
867
+ if fm_pf_relay_active "$FM_HOME" \
868
+ && { fm_pf_has_registrations "$STATE" || fm_pf_has_events "$STATE"; }; then
869
+ PUBLIC_FOLLOWUP=$("$SCRIPT_DIR/fm-public-followup.sh" pending 2>/dev/null) || PUBLIC_FOLLOWUP=
870
+ if [ -n "$PUBLIC_FOLLOWUP" ]; then
871
+ subsection "Public commitments"
872
+ printf '%s\n' "$PUBLIC_FOLLOWUP"
873
+ printf '\nEach line is a public loop this home still holds: a reply still owed, or an open loop with nothing owed.\n'
874
+ printf 'Reconcile terminal results with %s/bin/fm-public-followup.sh consume, then deliver a ready one with\n' "$FM_ROOT"
875
+ printf '%s/bin/fm-public-followup.sh deliver <id>. Hand a delivered loop on with rechain, or close it with\n' "$FM_ROOT"
876
+ printf '%s/bin/fm-public-followup.sh retire <id> --reason "...". Load fmx-respond for the procedure.\n' "$FM_ROOT"
877
+ fi
878
+ fi
879
+
880
+ # --- 7. network checks ------------------------------------------------------
881
+ # Deliberately here and not later: these lines are actionable (a stuck clone, a
882
+ # secondmate that could not be relaunched, broken GitHub auth), and the section
883
+ # after this one is the curated memory a truncated tail is meant to take first.
884
+ # Deliberately here and not earlier: this is the last point in the digest, so the
885
+ # worker started at step 1 has had the whole composition above to finish in. It
886
+ # is a NON-BLOCKING read either way - whatever the worker has published by now is
887
+ # printed, and whatever it has not is named as not yet confirmed.
888
+ stage network-checks
889
+ section "NETWORK CHECKS"
890
+ if [ "$READ_ONLY" -eq 1 ]; then
891
+ printf 'skipped (read-only session) - GitHub authentication, project clone refresh,\n'
892
+ printf 'secondmate liveness and convergence, and pending handoff delivery were not run.\n'
893
+ printf 'They need the fleet lock, and this session must not spawn, steer, or merge, so it\n'
894
+ printf 'has no action they would gate. The session holding the lock runs them.\n'
895
+ else
896
+ "$SCRIPT_DIR/fm-startup-network.sh" harvest --pid $$ 2>&1 || true
897
+ fi
898
+
899
+ # --- 8. context digest -----------------------------------------------------
900
+ # Last of the bulk sections deliberately: curated memory is stable session to
901
+ # session, already governed by config/startup-memory-budget, and recoverable
902
+ # with one targeted read, so it is the cheapest thing for a truncated tail to
903
+ # take (see this file's ORDERING note).
904
+ stage context
905
+ section "CONTEXT"
906
+ print_file_or_absent "$DATA/projects.md" "data/projects.md"
907
+ print_file_or_absent "$DATA/secondmates.md" "data/secondmates.md"
908
+ print_file_or_absent "$DATA/captain.md" "data/captain.md"
909
+ print_file_or_absent "$DATA/captain-shared.md" "data/captain-shared.md (shared, main-authoritative, read-only in secondmate homes)"
910
+ print_file_or_absent "$DATA/learnings.md" "data/learnings.md"
911
+
912
+ # --- 9. closing reminder -----------------------------------------------
913
+ stage next-step
914
+ section "NEXT STEP"
915
+ if [ "$READ_ONLY" -eq 1 ]; then
916
+ cat <<'EOF'
917
+ This session did not acquire the fleet lock. Stay read-only: do not arm,
918
+ drain, spawn, steer, merge, or repair fleet state from here. Only a session
919
+ with verified fleet-lock ownership may perform mutable follow-up.
920
+
921
+ EOF
922
+ elif [ "$AFK_PRESENT" -eq 1 ]; then
923
+ cat <<'EOF'
924
+ Away mode is active. Follow the supervision operating instructions block above:
925
+ load /afk and ensure the daemon is running, because the daemon owns watcher
926
+ supervision.
927
+
928
+ EOF
929
+ elif [ -f "$CONFIG/x-mode.env" ]; then
930
+ cat <<EOF
931
+ Follow the supervision operating instructions block above for harness '$PRIMARY_HARNESS'.
932
+ X mode is active, so the emitted block's cadence instruction applies.
933
+ This script never starts supervision itself.
934
+
935
+ EOF
936
+ else
937
+ cat <<EOF
938
+ Follow the supervision operating instructions block above for harness '$PRIMARY_HARNESS'.
939
+ This script never starts supervision itself.
940
+
941
+ EOF
942
+ fi
943
+ cat <<'EOF'
944
+ The digest above is complete for this session start. The READ-ONCE CONTRACT
945
+ section near the top of it governs what may still be read from disk.
946
+ EOF
947
+
948
+ if [ "$READ_ONLY" -eq 0 ] && [ "$REEMIT" -eq 0 ]; then
949
+ COMPLETION_RECORDED=0
950
+ COMPLETION_PID=$(cat "$STATE/.lock" 2>/dev/null || true)
951
+ case "$COMPLETION_PID" in
952
+ ''|*[!0-9]*) COMPLETION_PID= ;;
953
+ esac
954
+ COMPLETION_TMP=$(mktemp "$STATE/.session-start-complete.XXXXXX" 2>/dev/null || true)
955
+ if [ -n "$COMPLETION_PID" ] && [ -n "$COMPLETION_TMP" ] \
956
+ && printf '%s\n' "$COMPLETION_PID" > "$COMPLETION_TMP" 2>/dev/null \
957
+ && mv -f "$COMPLETION_TMP" "$COMPLETION_FILE" 2>/dev/null; then
958
+ COMPLETION_RECORDED=1
959
+ else
960
+ [ -z "$COMPLETION_TMP" ] || rm -f "$COMPLETION_TMP" 2>/dev/null || true
961
+ printf '\nSESSION_START_COMPLETION: not recorded - the next clear or compact will run a full startup.\n'
962
+ fi
963
+ if [ "$SESSION_SOURCE" = startup ] && [ "$COMPLETION_RECORDED" -eq 1 ] && [ -n "$AGENTS_START_HASH" ]; then
964
+ if ! write_agents_baseline "$COMPLETION_PID" "$AGENTS_START_HASH"; then
965
+ printf '\nSESSION_START_AGENTS_BASELINE: not recorded - a later supported rebuild will re-emit AGENTS.md.\n'
966
+ fi
967
+ fi
968
+ fi
969
+
970
+ exit 0