@indigoai-us/hq-cli 5.314.0 → 5.316.0

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 (1193) hide show
  1. package/CHANGELOG.md +4320 -1
  2. package/README.md +113 -0
  3. package/assets/bot-workers/setup/context/USER-GUIDE.md +404 -0
  4. package/assets/bot-workers/setup/context/quick-reference.md +199 -0
  5. package/assets/bot-workers/setup/skills/agents-and-team.md +167 -0
  6. package/assets/bot-workers/setup/skills/explain-hq.md +35 -0
  7. package/assets/bot-workers/setup/skills/first-company.md +74 -0
  8. package/assets/bot-workers/setup/skills/joining-a-team.md +125 -0
  9. package/assets/bot-workers/setup/skills/pricing.md +92 -0
  10. package/assets/bot-workers/setup/skills/standing-help.md +81 -0
  11. package/assets/bot-workers/setup/skills/your-business.md +281 -0
  12. package/assets/bot-workers/setup/worker.yaml +791 -0
  13. package/assets/lanes-hooks/hq-lanes-drain.json +15 -0
  14. package/assets/lanes-hooks/hq-lanes-drain.mjs +275 -0
  15. package/assets/lanes-hooks/hq-lanes-drain.sh +21 -0
  16. package/assets/lanes-reconcile/hq-lanes-reconcile.service +11 -0
  17. package/assets/lanes-reconcile/hq-lanes-reconcile.timer +12 -0
  18. package/assets/scaffold/.claude/hooks/validate-policy-frontmatter.sh +485 -0
  19. package/assets/scaffold/core/scripts/audit-log.sh +384 -0
  20. package/assets/scaffold/core/scripts/checkpoint-stop-gate.sh +281 -43
  21. package/assets/scaffold/core/scripts/clean-worktree-reconcile-handoff.sh +171 -0
  22. package/assets/scaffold/core/scripts/detect-stale-review-base.sh +199 -0
  23. package/assets/scaffold/core/scripts/eval-trigger.sh +193 -0
  24. package/assets/scaffold/core/scripts/git-pack-extension-check.sh +164 -0
  25. package/assets/scaffold/core/scripts/handoff-finalize.sh +688 -0
  26. package/assets/scaffold/core/scripts/handoff-open-steps.sh +81 -0
  27. package/assets/scaffold/core/scripts/handoff-post.sh +252 -0
  28. package/assets/scaffold/core/scripts/hook-lib.sh +345 -50
  29. package/assets/scaffold/core/scripts/hq-delegate-bundle.sh +307 -0
  30. package/assets/scaffold/core/scripts/hq-delegate-grant.sh +252 -0
  31. package/assets/scaffold/core/scripts/hq-delegate-pickup.sh +99 -0
  32. package/assets/scaffold/core/scripts/hq-delegate-publish.sh +91 -0
  33. package/assets/scaffold/core/scripts/hq-delegate-repo.sh +158 -0
  34. package/assets/scaffold/core/scripts/hq-delegate-resolve.sh +145 -0
  35. package/assets/scaffold/core/scripts/hq-delegate-secrets.sh +129 -0
  36. package/assets/scaffold/core/scripts/hq-delegate-send.sh +259 -0
  37. package/assets/scaffold/core/scripts/hq-delegate-transfer.sh +175 -0
  38. package/assets/scaffold/core/scripts/hq-delegate-verify.sh +238 -0
  39. package/assets/scaffold/core/scripts/hq-dm-bind.sh +585 -0
  40. package/assets/scaffold/core/scripts/hq-job-notify.sh +389 -0
  41. package/assets/scaffold/core/scripts/hq-job-probe.sh +835 -0
  42. package/assets/scaffold/core/scripts/hq-job-remediate.sh +359 -0
  43. package/assets/scaffold/core/scripts/hq-job-run.sh +1025 -0
  44. package/assets/scaffold/core/scripts/hq-pin.sh +118 -0
  45. package/assets/scaffold/core/scripts/hq-session.sh +184 -23
  46. package/assets/scaffold/core/scripts/jobs-schedule-parse.sh +310 -0
  47. package/assets/scaffold/core/scripts/jobs-validate.sh +451 -0
  48. package/assets/scaffold/core/scripts/knowledge-prefs.sh +55 -0
  49. package/assets/scaffold/core/scripts/lib/portable.sh +211 -0
  50. package/assets/scaffold/core/scripts/lib/secret-patterns.sh +58 -0
  51. package/assets/scaffold/core/scripts/lib/session-id.sh +3 -2
  52. package/assets/scaffold/core/scripts/lib/session-scope-capability.sh +1 -1
  53. package/assets/scaffold/core/scripts/lib/work-mesh-enqueue.sh +2 -1
  54. package/assets/scaffold/core/scripts/lib/work-mesh-live-hook.sh +378 -0
  55. package/assets/scaffold/core/scripts/lib/work-mesh-live-rebind.sh +141 -0
  56. package/assets/scaffold/core/scripts/migrate-policy-triggers.sh +378 -0
  57. package/assets/scaffold/core/scripts/ontology-audience-grant.sh +81 -0
  58. package/assets/scaffold/core/scripts/ontology-brief.mjs +93 -0
  59. package/assets/scaffold/core/scripts/ontology-candidate.sh +100 -0
  60. package/assets/scaffold/core/scripts/ontology-garden.mjs +238 -0
  61. package/assets/scaffold/core/scripts/ontology-source-worklist.sh +79 -0
  62. package/assets/scaffold/core/scripts/outpost-jobs-reconcile.sh +834 -0
  63. package/assets/scaffold/core/scripts/policy-age-report.sh +156 -0
  64. package/assets/scaffold/core/scripts/policy-retire.sh +199 -0
  65. package/assets/scaffold/core/scripts/qmd-reindex-after-sync.sh +10 -87
  66. package/assets/scaffold/core/scripts/qmd-reindex-bg.sh +40 -0
  67. package/assets/scaffold/core/scripts/read-policy-frontmatter.sh +32 -0
  68. package/assets/scaffold/core/scripts/rebuild-company-knowledge-index.sh +36 -3
  69. package/assets/scaffold/core/scripts/rebuild-projects-index.sh +99 -12
  70. package/assets/scaffold/core/scripts/refresh-vault-access.sh +188 -0
  71. package/assets/scaffold/core/scripts/register-project.sh +262 -0
  72. package/assets/scaffold/core/scripts/repo-run-registry.sh +408 -0
  73. package/assets/scaffold/core/scripts/resolve-company.sh +199 -0
  74. package/assets/scaffold/core/scripts/resume-thread-lock.sh +285 -0
  75. package/assets/scaffold/core/scripts/share-suggestion-state.sh +541 -0
  76. package/assets/scaffold/core/scripts/source-yaml-validate.sh +36 -0
  77. package/assets/scaffold/core/scripts/token-usage-report.sh +81 -20
  78. package/assets/scaffold/core/scripts/verify-story-deliverables.sh +148 -0
  79. package/assets/scaffold/core/scripts/work-mesh-live-bind-trusted.sh +152 -0
  80. package/assets/scaffold/core/scripts/work-mesh-live-rebind.sh +59 -0
  81. package/assets/scaffold/core/scripts/worktree-gc.sh +362 -0
  82. package/contracts/preflight/v1/fixtures.json +87 -0
  83. package/contracts/preflight/v1/schema.json +58 -0
  84. package/dist/bin/hq-auth-refresh.d.ts +2 -0
  85. package/dist/bin/hq-auth-refresh.js +12 -6
  86. package/dist/command-catalog.generated.d.ts +10798 -0
  87. package/dist/command-catalog.generated.js +13915 -0
  88. package/dist/command-registration-plan.d.ts +474 -0
  89. package/dist/command-registration-plan.js +136 -0
  90. package/dist/commands/__fixtures__/access-vault.d.ts +2 -0
  91. package/dist/commands/__fixtures__/access-vault.js +1 -1
  92. package/dist/commands/_patterns.d.ts +16 -0
  93. package/dist/commands/_patterns.js +20 -3
  94. package/dist/commands/access.d.ts +2 -1
  95. package/dist/commands/access.js +58 -49
  96. package/dist/commands/agent-enroll.d.ts +146 -0
  97. package/dist/commands/agent-enroll.js +401 -0
  98. package/dist/commands/agent-inbox.d.ts +9 -0
  99. package/dist/commands/agent-inbox.js +102 -0
  100. package/dist/commands/agent-kit.d.ts +87 -0
  101. package/dist/commands/agent-kit.js +480 -0
  102. package/dist/commands/agent-mcp.d.ts +24 -0
  103. package/dist/commands/agent-mcp.js +127 -0
  104. package/dist/commands/agent-probe.d.ts +77 -0
  105. package/dist/commands/agent-probe.js +335 -0
  106. package/dist/commands/agent.d.ts +13 -0
  107. package/dist/commands/agent.js +40 -0
  108. package/dist/commands/agents.d.ts +106 -4
  109. package/dist/commands/agents.js +924 -45
  110. package/dist/commands/auth.d.ts +1 -0
  111. package/dist/commands/auth.js +189 -19
  112. package/dist/commands/billing-sponsor.d.ts +83 -0
  113. package/dist/commands/billing-sponsor.js +344 -0
  114. package/dist/commands/billing.d.ts +3 -0
  115. package/dist/commands/billing.js +6 -1
  116. package/dist/commands/bot-companies.d.ts +40 -0
  117. package/dist/commands/bot-companies.js +64 -0
  118. package/dist/commands/bot-continuity.d.ts +28 -0
  119. package/dist/commands/bot-continuity.js +68 -0
  120. package/dist/commands/bot-jobs.d.ts +131 -0
  121. package/dist/commands/bot-jobs.js +474 -0
  122. package/dist/commands/bot.d.ts +278 -0
  123. package/dist/commands/bot.js +1982 -0
  124. package/dist/commands/channels.js +56 -1
  125. package/dist/commands/cloud-demote.js +3 -2
  126. package/dist/commands/cloud-provision.d.ts +14 -0
  127. package/dist/commands/cloud-provision.js +232 -58
  128. package/dist/commands/cloud-retire.d.ts +51 -0
  129. package/dist/commands/cloud-retire.js +154 -0
  130. package/dist/commands/cloud.d.ts +49 -15
  131. package/dist/commands/cloud.js +357 -122
  132. package/dist/commands/company-rename-flag.d.ts +4 -0
  133. package/dist/commands/company-rename-flag.js +7 -0
  134. package/dist/commands/company-rename.d.ts +4 -0
  135. package/dist/commands/company-rename.js +90 -0
  136. package/dist/commands/company-transfer.d.ts +4 -28
  137. package/dist/commands/company-transfer.js +5 -49
  138. package/dist/commands/company.js +68 -3
  139. package/dist/commands/core-audit-log-native.d.ts +9 -0
  140. package/dist/commands/core-audit-log-native.js +257 -0
  141. package/dist/commands/core-checkpoint-gate-setting.d.ts +59 -0
  142. package/dist/commands/core-checkpoint-gate-setting.js +163 -0
  143. package/dist/commands/core-checkpoint-stop-gate-native.d.ts +34 -0
  144. package/dist/commands/core-checkpoint-stop-gate-native.js +725 -0
  145. package/dist/commands/core-checkpoint.d.ts +19 -9
  146. package/dist/commands/core-checkpoint.js +301 -37
  147. package/dist/commands/core-command-catalog.d.ts +34 -0
  148. package/dist/commands/core-command-catalog.js +62 -0
  149. package/dist/commands/core-company-index-scope-flag.d.ts +3 -0
  150. package/dist/commands/core-company-index-scope-flag.js +6 -0
  151. package/dist/commands/core-delegate-w1b.d.ts +10 -0
  152. package/dist/commands/core-delegate-w1b.js +1219 -0
  153. package/dist/commands/core-delegate.d.ts +46 -0
  154. package/dist/commands/core-delegate.js +1040 -0
  155. package/dist/commands/core-detect-stale-review-base-native.d.ts +23 -0
  156. package/dist/commands/core-detect-stale-review-base-native.js +178 -0
  157. package/dist/commands/core-dm-bind-native.d.ts +32 -0
  158. package/dist/commands/core-dm-bind-native.js +668 -0
  159. package/dist/commands/core-eval-trigger-native.d.ts +4 -0
  160. package/dist/commands/core-eval-trigger-native.js +12 -0
  161. package/dist/commands/core-git-pack-extension-check-native.d.ts +22 -0
  162. package/dist/commands/core-git-pack-extension-check-native.js +190 -0
  163. package/dist/commands/core-handoff-fast.d.ts +18 -0
  164. package/dist/commands/core-handoff-fast.js +104 -0
  165. package/dist/commands/core-handoff-open-steps.d.ts +21 -0
  166. package/dist/commands/core-handoff-open-steps.js +264 -0
  167. package/dist/commands/core-handoff.d.ts +24 -0
  168. package/dist/commands/core-handoff.js +1144 -0
  169. package/dist/commands/core-hook-state-helpers-native.d.ts +11 -0
  170. package/dist/commands/core-hook-state-helpers-native.js +74 -0
  171. package/dist/commands/core-hq-session-native.d.ts +39 -0
  172. package/dist/commands/core-hq-session-native.js +579 -0
  173. package/dist/commands/core-job-native-utils.d.ts +6 -0
  174. package/dist/commands/core-job-native-utils.js +80 -0
  175. package/dist/commands/core-job-native.d.ts +5 -0
  176. package/dist/commands/core-job-native.js +16 -0
  177. package/dist/commands/core-job-notify-native.d.ts +36 -0
  178. package/dist/commands/core-job-notify-native.js +359 -0
  179. package/dist/commands/core-job-probe-native.d.ts +45 -0
  180. package/dist/commands/core-job-probe-native.js +564 -0
  181. package/dist/commands/core-job-remediate-native.d.ts +26 -0
  182. package/dist/commands/core-job-remediate-native.js +374 -0
  183. package/dist/commands/core-job-remote-launcher.d.ts +7 -0
  184. package/dist/commands/core-job-remote-launcher.js +51 -0
  185. package/dist/commands/core-job-run-native.d.ts +47 -0
  186. package/dist/commands/core-job-run-native.js +1215 -0
  187. package/dist/commands/core-jobs-native.d.ts +25 -0
  188. package/dist/commands/core-jobs-native.js +1339 -0
  189. package/dist/commands/core-knowledge-prefs.d.ts +11 -0
  190. package/dist/commands/core-knowledge-prefs.js +137 -0
  191. package/dist/commands/core-migrate-policy-triggers-native.d.ts +21 -0
  192. package/dist/commands/core-migrate-policy-triggers-native.js +374 -0
  193. package/dist/commands/core-native-handoff-flag.d.ts +4 -0
  194. package/dist/commands/core-native-handoff-flag.js +7 -0
  195. package/dist/commands/core-native-hook-helper-commands.d.ts +4 -0
  196. package/dist/commands/core-native-hook-helper-commands.js +56 -0
  197. package/dist/commands/core-native-hook-helpers-flag.d.ts +4 -0
  198. package/dist/commands/core-native-hook-helpers-flag.js +7 -0
  199. package/dist/commands/core-native-jobs-flag.d.ts +4 -0
  200. package/dist/commands/core-native-jobs-flag.js +7 -0
  201. package/dist/commands/core-native-policy-flag.d.ts +9 -0
  202. package/dist/commands/core-native-policy-flag.js +12 -0
  203. package/dist/commands/core-native-session-flag.d.ts +4 -0
  204. package/dist/commands/core-native-session-flag.js +7 -0
  205. package/dist/commands/core-native-utilities-flag.d.ts +4 -0
  206. package/dist/commands/core-native-utilities-flag.js +7 -0
  207. package/dist/commands/core-native-utilities.d.ts +29 -0
  208. package/dist/commands/core-native-utilities.js +54 -0
  209. package/dist/commands/core-native-worker-skills-flag.d.ts +4 -0
  210. package/dist/commands/core-native-worker-skills-flag.js +7 -0
  211. package/dist/commands/core-ontology-native.d.ts +17 -0
  212. package/dist/commands/core-ontology-native.js +916 -0
  213. package/dist/commands/core-ontology.d.ts +66 -0
  214. package/dist/commands/core-ontology.js +430 -0
  215. package/dist/commands/core-pin-native.d.ts +14 -0
  216. package/dist/commands/core-pin-native.js +236 -0
  217. package/dist/commands/core-policy-frontmatter.d.ts +8 -0
  218. package/dist/commands/core-policy-frontmatter.js +52 -0
  219. package/dist/commands/core-policy.d.ts +14 -0
  220. package/dist/commands/core-policy.js +1018 -0
  221. package/dist/commands/core-refresh-vault-access-native.d.ts +20 -0
  222. package/dist/commands/core-refresh-vault-access-native.js +229 -0
  223. package/dist/commands/core-register-project-native.d.ts +30 -0
  224. package/dist/commands/core-register-project-native.js +347 -0
  225. package/dist/commands/core-repo-run-registry-native.d.ts +19 -0
  226. package/dist/commands/core-repo-run-registry-native.js +357 -0
  227. package/dist/commands/core-resolve-company-command.d.ts +4 -0
  228. package/dist/commands/core-resolve-company-command.js +42 -0
  229. package/dist/commands/core-resolve-company-native.d.ts +28 -0
  230. package/dist/commands/core-resolve-company-native.js +408 -0
  231. package/dist/commands/core-share-suggestion-state-native.d.ts +18 -0
  232. package/dist/commands/core-share-suggestion-state-native.js +445 -0
  233. package/dist/commands/core-work-mesh-bind-trusted-native.d.ts +32 -0
  234. package/dist/commands/core-work-mesh-bind-trusted-native.js +190 -0
  235. package/dist/commands/core-work-mesh-live-rebind-native.d.ts +18 -0
  236. package/dist/commands/core-work-mesh-live-rebind-native.js +262 -0
  237. package/dist/commands/core-worker-lint-native.d.ts +4 -0
  238. package/dist/commands/core-worker-lint-native.js +160 -0
  239. package/dist/commands/core-worker-share-native.d.ts +4 -0
  240. package/dist/commands/core-worker-share-native.js +260 -0
  241. package/dist/commands/core-worker-skills-command.d.ts +8 -0
  242. package/dist/commands/core-worker-skills-command.js +33 -0
  243. package/dist/commands/core-worker-skills-runtime.d.ts +33 -0
  244. package/dist/commands/core-worker-skills-runtime.js +86 -0
  245. package/dist/commands/core.d.ts +4 -0
  246. package/dist/commands/core.js +282 -80
  247. package/dist/commands/crm.js +52 -3
  248. package/dist/commands/daemon.d.ts +63 -0
  249. package/dist/commands/daemon.js +877 -0
  250. package/dist/commands/db-provision.js +4 -4
  251. package/dist/commands/db-sql.js +7 -21
  252. package/dist/commands/deploy-comments.d.ts +3 -0
  253. package/dist/commands/deploy-comments.js +162 -0
  254. package/dist/commands/dm.d.ts +119 -12
  255. package/dist/commands/dm.js +388 -38
  256. package/dist/commands/doctor.d.ts +12 -0
  257. package/dist/commands/doctor.js +158 -12
  258. package/dist/commands/feedback.d.ts +6 -0
  259. package/dist/commands/feedback.js +86 -37
  260. package/dist/commands/files-browse.d.ts +32 -12
  261. package/dist/commands/files-browse.js +176 -60
  262. package/dist/commands/files.d.ts +17 -0
  263. package/dist/commands/files.js +300 -47
  264. package/dist/commands/group-grants.js +3 -2
  265. package/dist/commands/groups.js +6 -5
  266. package/dist/commands/index-cmd.d.ts +19 -1
  267. package/dist/commands/index-cmd.js +74 -7
  268. package/dist/commands/integrations-api.d.ts +15 -10
  269. package/dist/commands/integrations-api.js +27 -22
  270. package/dist/commands/integrations-connect.d.ts +51 -13
  271. package/dist/commands/integrations-connect.js +86 -71
  272. package/dist/commands/integrations-core.d.ts +6 -6
  273. package/dist/commands/integrations-core.js +25 -11
  274. package/dist/commands/integrations-import.d.ts +1 -1
  275. package/dist/commands/integrations-import.js +43 -24
  276. package/dist/commands/integrations-manage.js +20 -13
  277. package/dist/commands/integrations.d.ts +8 -0
  278. package/dist/commands/integrations.js +94 -7
  279. package/dist/commands/lanes-accounts.d.ts +28 -0
  280. package/dist/commands/lanes-accounts.js +595 -0
  281. package/dist/commands/lanes-autopilot.d.ts +11 -0
  282. package/dist/commands/lanes-autopilot.js +336 -0
  283. package/dist/commands/lanes-checks.d.ts +51 -0
  284. package/dist/commands/lanes-checks.js +941 -0
  285. package/dist/commands/lanes-hold.d.ts +43 -0
  286. package/dist/commands/lanes-hold.js +655 -0
  287. package/dist/commands/lanes-keep-alive-audit.d.ts +10 -0
  288. package/dist/commands/lanes-keep-alive-audit.js +19 -0
  289. package/dist/commands/lanes-kpis.d.ts +11 -0
  290. package/dist/commands/lanes-kpis.js +34 -0
  291. package/dist/commands/lanes-message.d.ts +9 -0
  292. package/dist/commands/lanes-message.js +946 -0
  293. package/dist/commands/lanes-move.d.ts +12 -0
  294. package/dist/commands/lanes-move.js +397 -0
  295. package/dist/commands/lanes-questions.d.ts +36 -0
  296. package/dist/commands/lanes-questions.js +1005 -0
  297. package/dist/commands/lanes-report.d.ts +11 -0
  298. package/dist/commands/lanes-report.js +333 -0
  299. package/dist/commands/lanes-resume.d.ts +6 -0
  300. package/dist/commands/lanes-resume.js +564 -0
  301. package/dist/commands/lanes-review.d.ts +10 -0
  302. package/dist/commands/lanes-review.js +56 -0
  303. package/dist/commands/lanes-shared.d.ts +449 -0
  304. package/dist/commands/lanes-shared.js +170 -0
  305. package/dist/commands/lanes-stories.d.ts +15 -0
  306. package/dist/commands/lanes-stories.js +347 -0
  307. package/dist/commands/lanes-watch.d.ts +7 -0
  308. package/dist/commands/lanes-watch.js +216 -0
  309. package/dist/commands/lanes.d.ts +149 -0
  310. package/dist/commands/lanes.js +9013 -0
  311. package/dist/commands/login.js +49 -6
  312. package/dist/commands/mcp-registration.d.ts +32 -25
  313. package/dist/commands/mcp-registration.js +256 -23
  314. package/dist/commands/mcp-status.js +1 -0
  315. package/dist/commands/meetings.js +55 -34
  316. package/dist/commands/members.js +5 -1
  317. package/dist/commands/mesh.d.ts +11 -0
  318. package/dist/commands/mesh.js +1086 -76
  319. package/dist/commands/monitor.d.ts +58 -0
  320. package/dist/commands/monitor.js +980 -0
  321. package/dist/commands/onboard-bot-membership.d.ts +32 -0
  322. package/dist/commands/onboard-bot-membership.js +40 -0
  323. package/dist/commands/onboard-create-identity.d.ts +26 -0
  324. package/dist/commands/onboard-create-identity.js +23 -0
  325. package/dist/commands/onboard-identity-guard.d.ts +1 -1
  326. package/dist/commands/onboard.js +24 -5
  327. package/dist/commands/outpost-pruner.d.ts +3 -0
  328. package/dist/commands/outpost-pruner.js +125 -0
  329. package/dist/commands/pack-install.js +3 -1
  330. package/dist/commands/packs.js +11 -1
  331. package/dist/commands/people.d.ts +4 -0
  332. package/dist/commands/people.js +37 -3
  333. package/dist/commands/personal-connector-settings-flag.d.ts +4 -0
  334. package/dist/commands/personal-connector-settings-flag.js +7 -0
  335. package/dist/commands/personal-targeted-push-flag.d.ts +4 -0
  336. package/dist/commands/personal-targeted-push-flag.js +7 -0
  337. package/dist/commands/personal-targeted-push-paths.d.ts +3 -0
  338. package/dist/commands/personal-targeted-push-paths.js +67 -0
  339. package/dist/commands/publish.d.ts +8 -1
  340. package/dist/commands/publish.js +17 -4
  341. package/dist/commands/reindex.js +56 -6
  342. package/dist/commands/report.d.ts +19 -0
  343. package/dist/commands/report.js +537 -0
  344. package/dist/commands/rescue.d.ts +4 -0
  345. package/dist/commands/rescue.js +27 -17
  346. package/dist/commands/run-feature-telemetry.d.ts +3 -0
  347. package/dist/commands/run-feature-telemetry.js +6 -0
  348. package/dist/commands/run.js +18 -4
  349. package/dist/commands/safe-extract.d.ts +11 -2
  350. package/dist/commands/safe-extract.js +36 -8
  351. package/dist/commands/secrets.d.ts +20 -2
  352. package/dist/commands/secrets.js +175 -71
  353. package/dist/commands/skill.d.ts +35 -4
  354. package/dist/commands/skill.js +357 -18
  355. package/dist/commands/staff/reset-test-account.d.ts +110 -0
  356. package/dist/commands/staff/reset-test-account.js +268 -0
  357. package/dist/commands/staff/test-account.d.ts +51 -0
  358. package/dist/commands/staff/test-account.js +196 -0
  359. package/dist/commands/sync-mode.d.ts +11 -0
  360. package/dist/commands/sync-mode.js +30 -0
  361. package/dist/commands/sync-narrow.js +36 -5
  362. package/dist/commands/team-sync.js +71 -10
  363. package/dist/commands/update.js +6 -0
  364. package/dist/commands/vault-retention-flag.d.ts +3 -0
  365. package/dist/commands/vault-retention-flag.js +9 -0
  366. package/dist/commands/vault-retention.d.ts +11 -0
  367. package/dist/commands/vault-retention.js +69 -0
  368. package/dist/commands/version.d.ts +10 -0
  369. package/dist/commands/version.js +11 -0
  370. package/dist/commands/whoami.d.ts +22 -0
  371. package/dist/commands/whoami.js +137 -4
  372. package/dist/commands/workers.d.ts +2 -14
  373. package/dist/commands/workers.js +7 -10
  374. package/dist/fast-core.d.ts +7 -7
  375. package/dist/fast-core.js +91 -24
  376. package/dist/fast-scaffold.d.ts +86 -0
  377. package/dist/fast-scaffold.js +381 -0
  378. package/dist/index.d.ts +3 -4
  379. package/dist/index.js +59 -9
  380. package/dist/lanes-drain-hook.d.ts +14 -0
  381. package/dist/lanes-drain-hook.js +203 -0
  382. package/dist/lazy-commands.d.ts +20 -44
  383. package/dist/lazy-commands.js +60 -58
  384. package/dist/lib/agent-kit/adopt-identity.d.ts +27 -0
  385. package/dist/lib/agent-kit/adopt-identity.js +60 -0
  386. package/dist/lib/agent-kit/attachment-download.d.ts +24 -0
  387. package/dist/lib/agent-kit/attachment-download.js +47 -0
  388. package/dist/lib/agent-kit/creds.d.ts +106 -0
  389. package/dist/lib/agent-kit/creds.js +163 -0
  390. package/dist/lib/agent-kit/fallback.d.ts +78 -0
  391. package/dist/lib/agent-kit/fallback.js +210 -0
  392. package/dist/lib/agent-kit/inbox-state.d.ts +83 -0
  393. package/dist/lib/agent-kit/inbox-state.js +159 -0
  394. package/dist/lib/agent-kit/kit-config.d.ts +56 -0
  395. package/dist/lib/agent-kit/kit-config.js +65 -0
  396. package/dist/lib/agent-kit/log.d.ts +16 -0
  397. package/dist/lib/agent-kit/log.js +46 -0
  398. package/dist/lib/agent-kit/mcp/attachments.d.ts +126 -0
  399. package/dist/lib/agent-kit/mcp/attachments.js +222 -0
  400. package/dist/lib/agent-kit/mcp/jsonrpc.d.ts +75 -0
  401. package/dist/lib/agent-kit/mcp/jsonrpc.js +164 -0
  402. package/dist/lib/agent-kit/mcp/tools.d.ts +64 -0
  403. package/dist/lib/agent-kit/mcp/tools.js +397 -0
  404. package/dist/lib/agent-kit/paths.d.ts +65 -0
  405. package/dist/lib/agent-kit/paths.js +118 -0
  406. package/dist/lib/agent-kit/private-file.d.ts +29 -0
  407. package/dist/lib/agent-kit/private-file.js +91 -0
  408. package/dist/lib/agent-kit/run/heartbeat.d.ts +72 -0
  409. package/dist/lib/agent-kit/run/heartbeat.js +128 -0
  410. package/dist/lib/agent-kit/run/inbox.d.ts +76 -0
  411. package/dist/lib/agent-kit/run/inbox.js +205 -0
  412. package/dist/lib/agent-kit/run/supervisor.d.ts +35 -0
  413. package/dist/lib/agent-kit/run/supervisor.js +85 -0
  414. package/dist/lib/agent-kit/run/sync.d.ts +33 -0
  415. package/dist/lib/agent-kit/run/sync.js +58 -0
  416. package/dist/lib/agent-kit/services.d.ts +31 -0
  417. package/dist/lib/agent-kit/services.js +55 -0
  418. package/dist/lib/agent-kit/skills.d.ts +18 -0
  419. package/dist/lib/agent-kit/skills.js +151 -0
  420. package/dist/lib/agent-kit/wake.d.ts +83 -0
  421. package/dist/lib/agent-kit/wake.js +243 -0
  422. package/dist/lib/agents/model-catalog.d.ts +62 -0
  423. package/dist/lib/agents/model-catalog.js +275 -0
  424. package/dist/lib/auth-login-provider-state.d.ts +8 -0
  425. package/dist/lib/auth-login-provider-state.js +63 -0
  426. package/dist/lib/aws-sdk-node-warning-output.d.ts +12 -0
  427. package/dist/lib/aws-sdk-node-warning-output.js +22 -0
  428. package/dist/lib/billing/free-month.d.ts +18 -0
  429. package/dist/lib/billing/free-month.js +31 -0
  430. package/dist/lib/billing/plan-limit-refusals.d.ts +69 -0
  431. package/dist/lib/billing/plan-limit-refusals.js +187 -0
  432. package/dist/lib/billing/plan-limit-upgrade-url.d.ts +11 -0
  433. package/dist/lib/billing/plan-limit-upgrade-url.js +66 -0
  434. package/dist/lib/billing/plan-lock.d.ts +143 -0
  435. package/dist/lib/billing/plan-lock.js +439 -0
  436. package/dist/lib/bot/api.d.ts +349 -0
  437. package/dist/lib/bot/api.js +316 -0
  438. package/dist/lib/bot/attachments.d.ts +45 -0
  439. package/dist/lib/bot/attachments.js +89 -0
  440. package/dist/lib/bot/cli-update.d.ts +138 -0
  441. package/dist/lib/bot/cli-update.js +278 -0
  442. package/dist/lib/bot/company-bind.d.ts +27 -0
  443. package/dist/lib/bot/company-bind.js +62 -0
  444. package/dist/lib/bot/config.d.ts +153 -0
  445. package/dist/lib/bot/config.js +233 -0
  446. package/dist/lib/bot/continuity-download.d.ts +28 -0
  447. package/dist/lib/bot/continuity-download.js +75 -0
  448. package/dist/lib/bot/continuity-install.d.ts +14 -0
  449. package/dist/lib/bot/continuity-install.js +101 -0
  450. package/dist/lib/bot/continuity.d.ts +67 -0
  451. package/dist/lib/bot/continuity.js +301 -0
  452. package/dist/lib/bot/creds.d.ts +24 -0
  453. package/dist/lib/bot/creds.js +51 -0
  454. package/dist/lib/bot/daemon.d.ts +173 -0
  455. package/dist/lib/bot/daemon.js +552 -0
  456. package/dist/lib/bot/inbox-poll-backoff-flag.d.ts +24 -0
  457. package/dist/lib/bot/inbox-poll-backoff-flag.js +135 -0
  458. package/dist/lib/bot/inbox-state.d.ts +18 -0
  459. package/dist/lib/bot/inbox-state.js +51 -0
  460. package/dist/lib/bot/index.d.ts +23 -0
  461. package/dist/lib/bot/index.js +23 -0
  462. package/dist/lib/bot/inflight.d.ts +119 -0
  463. package/dist/lib/bot/inflight.js +83 -0
  464. package/dist/lib/bot/job-completions.d.ts +89 -0
  465. package/dist/lib/bot/job-completions.js +132 -0
  466. package/dist/lib/bot/job-quiet-flag.d.ts +4 -0
  467. package/dist/lib/bot/job-quiet-flag.js +14 -0
  468. package/dist/lib/bot/job-run.d.ts +114 -0
  469. package/dist/lib/bot/job-run.js +266 -0
  470. package/dist/lib/bot/local-config.d.ts +61 -0
  471. package/dist/lib/bot/local-config.js +145 -0
  472. package/dist/lib/bot/local-jobs.d.ts +89 -0
  473. package/dist/lib/bot/local-jobs.js +459 -0
  474. package/dist/lib/bot/local-name.d.ts +54 -0
  475. package/dist/lib/bot/local-name.js +114 -0
  476. package/dist/lib/bot/log.d.ts +13 -0
  477. package/dist/lib/bot/log.js +59 -0
  478. package/dist/lib/bot/owner-context.d.ts +79 -0
  479. package/dist/lib/bot/owner-context.js +175 -0
  480. package/dist/lib/bot/paths.d.ts +76 -0
  481. package/dist/lib/bot/paths.js +131 -0
  482. package/dist/lib/bot/progress.d.ts +132 -0
  483. package/dist/lib/bot/progress.js +289 -0
  484. package/dist/lib/bot/promote.d.ts +16 -0
  485. package/dist/lib/bot/promote.js +106 -0
  486. package/dist/lib/bot/promotion-hold.d.ts +24 -0
  487. package/dist/lib/bot/promotion-hold.js +103 -0
  488. package/dist/lib/bot/promotion-receipt.d.ts +9 -0
  489. package/dist/lib/bot/promotion-receipt.js +56 -0
  490. package/dist/lib/bot/promotion-upload.d.ts +16 -0
  491. package/dist/lib/bot/promotion-upload.js +80 -0
  492. package/dist/lib/bot/prompt.d.ts +136 -0
  493. package/dist/lib/bot/prompt.js +433 -0
  494. package/dist/lib/bot/room-policy.d.ts +63 -0
  495. package/dist/lib/bot/room-policy.js +91 -0
  496. package/dist/lib/bot/run.d.ts +219 -0
  497. package/dist/lib/bot/run.js +1881 -0
  498. package/dist/lib/bot/runnable.d.ts +51 -0
  499. package/dist/lib/bot/runnable.js +65 -0
  500. package/dist/lib/bot/runtime/claude.d.ts +50 -0
  501. package/dist/lib/bot/runtime/claude.js +170 -0
  502. package/dist/lib/bot/runtime/codex.d.ts +28 -0
  503. package/dist/lib/bot/runtime/codex.js +153 -0
  504. package/dist/lib/bot/runtime/grok-acp.d.ts +40 -0
  505. package/dist/lib/bot/runtime/grok-acp.js +265 -0
  506. package/dist/lib/bot/runtime/grok.d.ts +41 -0
  507. package/dist/lib/bot/runtime/grok.js +169 -0
  508. package/dist/lib/bot/runtime/index.d.ts +36 -0
  509. package/dist/lib/bot/runtime/index.js +417 -0
  510. package/dist/lib/bot/runtime/messages-stream.d.ts +56 -0
  511. package/dist/lib/bot/runtime/messages-stream.js +194 -0
  512. package/dist/lib/bot/runtime/sanitize.d.ts +18 -0
  513. package/dist/lib/bot/runtime/sanitize.js +28 -0
  514. package/dist/lib/bot/runtime/types.d.ts +159 -0
  515. package/dist/lib/bot/runtime/types.js +51 -0
  516. package/dist/lib/bot/runtime/windows.d.ts +10 -0
  517. package/dist/lib/bot/runtime/windows.js +53 -0
  518. package/dist/lib/bot/runtime-sign-in.d.ts +24 -0
  519. package/dist/lib/bot/runtime-sign-in.js +31 -0
  520. package/dist/lib/bot/scaffold.d.ts +38 -0
  521. package/dist/lib/bot/scaffold.js +94 -0
  522. package/dist/lib/bot/self-heal.d.ts +52 -0
  523. package/dist/lib/bot/self-heal.js +79 -0
  524. package/dist/lib/bot/self-process.d.ts +19 -0
  525. package/dist/lib/bot/self-process.js +35 -0
  526. package/dist/lib/bot/session.d.ts +19 -0
  527. package/dist/lib/bot/session.js +39 -0
  528. package/dist/lib/bot/setup-explain.d.ts +64 -0
  529. package/dist/lib/bot/setup-explain.js +141 -0
  530. package/dist/lib/bot/split.d.ts +32 -0
  531. package/dist/lib/bot/split.js +241 -0
  532. package/dist/lib/bot/status.d.ts +57 -0
  533. package/dist/lib/bot/status.js +66 -0
  534. package/dist/lib/bot/worker-source.d.ts +66 -0
  535. package/dist/lib/bot/worker-source.js +283 -0
  536. package/dist/lib/checkpoint-ontology/aliases.d.ts +17 -0
  537. package/dist/lib/checkpoint-ontology/aliases.js +44 -0
  538. package/dist/lib/checkpoint-ontology/apply.d.ts +110 -0
  539. package/dist/lib/checkpoint-ontology/apply.js +777 -0
  540. package/dist/lib/checkpoint-ontology/company-brief.d.ts +18 -0
  541. package/dist/lib/checkpoint-ontology/company-brief.js +337 -0
  542. package/dist/lib/checkpoint-ontology/company.d.ts +44 -0
  543. package/dist/lib/checkpoint-ontology/company.js +118 -0
  544. package/dist/lib/checkpoint-ontology/drop-aliases.d.ts +41 -0
  545. package/dist/lib/checkpoint-ontology/drop-aliases.js +76 -0
  546. package/dist/lib/checkpoint-ontology/entity-file.d.ts +109 -0
  547. package/dist/lib/checkpoint-ontology/entity-file.js +371 -0
  548. package/dist/lib/checkpoint-ontology/identity.d.ts +38 -0
  549. package/dist/lib/checkpoint-ontology/identity.js +95 -0
  550. package/dist/lib/checkpoint-ontology/merge-copies.d.ts +199 -0
  551. package/dist/lib/checkpoint-ontology/merge-copies.js +1086 -0
  552. package/dist/lib/checkpoint-ontology/multi-writer.d.ts +101 -0
  553. package/dist/lib/checkpoint-ontology/multi-writer.js +394 -0
  554. package/dist/lib/checkpoint-ontology/plan.d.ts +193 -0
  555. package/dist/lib/checkpoint-ontology/plan.js +504 -0
  556. package/dist/lib/checkpoint-ontology/queued-touches.d.ts +29 -0
  557. package/dist/lib/checkpoint-ontology/queued-touches.js +193 -0
  558. package/dist/lib/checkpoint-ontology/sync-client.d.ts +38 -0
  559. package/dist/lib/checkpoint-ontology/sync-client.js +84 -0
  560. package/dist/lib/checkpoint-ontology/tree.d.ts +55 -0
  561. package/dist/lib/checkpoint-ontology/tree.js +198 -0
  562. package/dist/lib/company-errors-sdk-warning-flag.d.ts +5 -0
  563. package/dist/lib/company-errors-sdk-warning-flag.js +8 -0
  564. package/dist/lib/company-skill-wrapper.d.ts +1 -0
  565. package/dist/lib/company-skill-wrapper.js +121 -29
  566. package/dist/lib/core-utils/codex-skill-bridge.d.ts +2 -1
  567. package/dist/lib/core-utils/common.d.ts +0 -1
  568. package/dist/lib/core-utils/common.js +0 -9
  569. package/dist/lib/core-utils/hook-timeout-debug-context-flag.d.ts +20 -0
  570. package/dist/lib/core-utils/hook-timeout-debug-context-flag.js +81 -0
  571. package/dist/lib/core-utils/jq-json-serializer.d.ts +5 -0
  572. package/dist/lib/core-utils/jq-json-serializer.js +10 -0
  573. package/dist/lib/core-utils/qmd-reindex-after-sync.d.ts +14 -1
  574. package/dist/lib/core-utils/qmd-reindex-after-sync.js +101 -17
  575. package/dist/lib/core-utils/secret-patterns.d.ts +43 -0
  576. package/dist/lib/core-utils/secret-patterns.js +34 -0
  577. package/dist/lib/core-utils/sentry-report.d.ts +114 -0
  578. package/dist/lib/core-utils/sentry-report.js +1055 -0
  579. package/dist/lib/core-utils/soft-timeout.js +1 -1
  580. package/dist/lib/core-utils/timeout-guard-native.d.ts +7 -0
  581. package/dist/lib/core-utils/timeout-guard-native.js +40 -0
  582. package/dist/lib/core-utils/timeout-guard.d.ts +3 -3
  583. package/dist/lib/core-utils/timeout-guard.js +28 -13
  584. package/dist/lib/core-utils/token-usage-report.js +17 -3
  585. package/dist/lib/core-utils/worktree-resume.d.ts +20 -0
  586. package/dist/lib/core-utils/worktree-resume.js +1198 -0
  587. package/dist/lib/daemon/catalog.d.ts +134 -0
  588. package/dist/lib/daemon/catalog.js +358 -0
  589. package/dist/lib/daemon/config.d.ts +35 -0
  590. package/dist/lib/daemon/config.js +108 -0
  591. package/dist/lib/daemon/flag.d.ts +25 -0
  592. package/dist/lib/daemon/flag.js +59 -0
  593. package/dist/lib/daemon/handoff.d.ts +56 -0
  594. package/dist/lib/daemon/handoff.js +161 -0
  595. package/dist/lib/daemon/hq-cloud.d.ts +79 -0
  596. package/dist/lib/daemon/hq-cloud.js +183 -0
  597. package/dist/lib/daemon/install.d.ts +85 -0
  598. package/dist/lib/daemon/install.js +320 -0
  599. package/dist/lib/daemon/legacy-sync-env.d.ts +10 -0
  600. package/dist/lib/daemon/legacy-sync-env.js +58 -0
  601. package/dist/lib/daemon/legacy.d.ts +45 -0
  602. package/dist/lib/daemon/legacy.js +133 -0
  603. package/dist/lib/daemon/lock.d.ts +47 -0
  604. package/dist/lib/daemon/lock.js +138 -0
  605. package/dist/lib/daemon/machine-type.d.ts +50 -0
  606. package/dist/lib/daemon/machine-type.js +159 -0
  607. package/dist/lib/daemon/migrate.d.ts +77 -0
  608. package/dist/lib/daemon/migrate.js +265 -0
  609. package/dist/lib/daemon/paths.d.ts +24 -0
  610. package/dist/lib/daemon/paths.js +43 -0
  611. package/dist/lib/daemon/protocol-tail.d.ts +33 -0
  612. package/dist/lib/daemon/protocol-tail.js +131 -0
  613. package/dist/lib/daemon/remote-control.d.ts +74 -0
  614. package/dist/lib/daemon/remote-control.js +153 -0
  615. package/dist/lib/daemon/requests.d.ts +28 -0
  616. package/dist/lib/daemon/requests.js +65 -0
  617. package/dist/lib/daemon/run.d.ts +79 -0
  618. package/dist/lib/daemon/run.js +755 -0
  619. package/dist/lib/daemon/succession.d.ts +118 -0
  620. package/dist/lib/daemon/succession.js +263 -0
  621. package/dist/lib/daemon/supervisor.d.ts +132 -0
  622. package/dist/lib/daemon/supervisor.js +836 -0
  623. package/dist/lib/daemon/sync-runner.d.ts +58 -0
  624. package/dist/lib/daemon/sync-runner.js +277 -0
  625. package/dist/lib/daemon/tools.d.ts +52 -0
  626. package/dist/lib/daemon/tools.js +95 -0
  627. package/dist/lib/daemon/updater.d.ts +57 -0
  628. package/dist/lib/daemon/updater.js +163 -0
  629. package/dist/lib/db/control-plane.js +6 -0
  630. package/dist/lib/db/local.d.ts +0 -5
  631. package/dist/lib/db/local.js +1 -1
  632. package/dist/lib/db/migrate.d.ts +0 -12
  633. package/dist/lib/db/migrate.js +5 -5
  634. package/dist/lib/db/remote-sql.d.ts +2 -2
  635. package/dist/lib/db/remote-sql.js +3 -3
  636. package/dist/lib/db/sql.d.ts +0 -10
  637. package/dist/lib/db/sql.js +4 -8
  638. package/dist/lib/deploy-api.d.ts +5 -0
  639. package/dist/lib/deploy-api.js +21 -0
  640. package/dist/lib/deploy-apps.d.ts +13 -0
  641. package/dist/lib/deploy-apps.js +29 -0
  642. package/dist/lib/doctor/__testing__/fake-hq-tree.d.ts +1 -1
  643. package/dist/lib/doctor/__testing__/fake-hq-tree.js +1 -1
  644. package/dist/lib/doctor/__testing__/run-doctor.d.ts +8 -0
  645. package/dist/lib/doctor/__testing__/run-doctor.js +52 -0
  646. package/dist/lib/doctor/checks/bots.d.ts +13 -0
  647. package/dist/lib/doctor/checks/bots.js +189 -0
  648. package/dist/lib/doctor/checks/claude-wiring.js +70 -1
  649. package/dist/lib/doctor/checks/codex-wiring.d.ts +0 -4
  650. package/dist/lib/doctor/checks/codex-wiring.js +3 -35
  651. package/dist/lib/doctor/checks/grok-wiring.js +1 -34
  652. package/dist/lib/doctor/checks/integrations.js +11 -0
  653. package/dist/lib/doctor/checks/runtime-health.d.ts +4 -17
  654. package/dist/lib/doctor/checks/runtime-health.js +20 -7
  655. package/dist/lib/doctor/checks/scaffold-cli-floor.d.ts +6 -0
  656. package/dist/lib/doctor/checks/scaffold-cli-floor.js +73 -0
  657. package/dist/lib/doctor/checks/sync-health.d.ts +21 -0
  658. package/dist/lib/doctor/checks/sync-health.js +72 -2
  659. package/dist/lib/doctor/checks/sync-runtime.d.ts +11 -0
  660. package/dist/lib/doctor/checks/sync-runtime.js +216 -0
  661. package/dist/lib/doctor/checks/work-context.js +20 -6
  662. package/dist/lib/doctor/client-health-flag-token.d.ts +15 -0
  663. package/dist/lib/doctor/client-health-flag-token.js +66 -0
  664. package/dist/lib/doctor/client-health-reason-codes-flag.d.ts +27 -0
  665. package/dist/lib/doctor/client-health-reason-codes-flag.js +106 -0
  666. package/dist/lib/doctor/compat.d.ts +0 -16
  667. package/dist/lib/doctor/compat.js +4 -3
  668. package/dist/lib/doctor/deep/effects.js +1 -3
  669. package/dist/lib/doctor/deep/executor.d.ts +4 -10
  670. package/dist/lib/doctor/deep/executor.js +1 -1
  671. package/dist/lib/doctor/deep/parity.d.ts +2 -29
  672. package/dist/lib/doctor/deep/parity.js +7 -7
  673. package/dist/lib/doctor/deep/sandbox.d.ts +7 -25
  674. package/dist/lib/doctor/deep/sandbox.js +5 -7
  675. package/dist/lib/doctor/fix/apply.d.ts +79 -8
  676. package/dist/lib/doctor/fix/apply.js +292 -80
  677. package/dist/lib/doctor/fix/json-output.d.ts +28 -0
  678. package/dist/lib/doctor/fix/json-output.js +33 -0
  679. package/dist/lib/doctor/fix/refresh-sync-outcome.d.ts +12 -0
  680. package/dist/lib/doctor/fix/refresh-sync-outcome.js +25 -0
  681. package/dist/lib/doctor/fix/remediation.d.ts +14 -6
  682. package/dist/lib/doctor/fix/remediation.js +49 -9
  683. package/dist/lib/doctor/fixtures/schema.js +1 -3
  684. package/dist/lib/doctor/json-output.d.ts +17 -1
  685. package/dist/lib/doctor/json-output.js +7 -2
  686. package/dist/lib/doctor/platform.d.ts +0 -26
  687. package/dist/lib/doctor/platform.js +5 -5
  688. package/dist/lib/doctor/registry.d.ts +14 -0
  689. package/dist/lib/doctor/registry.js +71 -0
  690. package/dist/lib/doctor/report.js +1 -1
  691. package/dist/lib/doctor/shared.d.ts +8 -0
  692. package/dist/lib/doctor/shared.js +38 -0
  693. package/dist/lib/doctor/stray-gate-entries.d.ts +35 -0
  694. package/dist/lib/doctor/stray-gate-entries.js +83 -0
  695. package/dist/lib/doctor/types.d.ts +5 -0
  696. package/dist/lib/doctor/types.js +20 -0
  697. package/dist/lib/first-sync-next-step.d.ts +34 -0
  698. package/dist/lib/first-sync-next-step.js +179 -0
  699. package/dist/lib/flag-registry-endpoint.d.ts +5 -0
  700. package/dist/lib/flag-registry-endpoint.js +9 -0
  701. package/dist/lib/flag-registry-worker-source.generated.d.ts +2 -0
  702. package/dist/lib/flag-registry-worker-source.generated.js +3 -0
  703. package/dist/lib/flag-registry-worker.js +12 -1
  704. package/dist/lib/flag-registry.d.ts +26 -6
  705. package/dist/lib/flag-registry.js +133 -16
  706. package/dist/lib/flag-snapshot-file.d.ts +20 -0
  707. package/dist/lib/flag-snapshot-file.js +91 -0
  708. package/dist/lib/heartbeat-identity.d.ts +30 -0
  709. package/dist/lib/heartbeat-identity.js +76 -0
  710. package/dist/lib/index-render/companies.d.ts +4 -1
  711. package/dist/lib/index-render/companies.js +66 -3
  712. package/dist/lib/index-render/company-knowledge.js +80 -17
  713. package/dist/lib/index-render/index.d.ts +1 -0
  714. package/dist/lib/index-render/index.js +2 -1
  715. package/dist/lib/index-render/projects.js +82 -5
  716. package/dist/lib/index-render/shared.d.ts +13 -1
  717. package/dist/lib/index-render/shared.js +41 -2
  718. package/dist/lib/lanes/account-home.d.ts +8 -0
  719. package/dist/lib/lanes/account-home.js +10 -0
  720. package/dist/lib/lanes/accounts.d.ts +117 -0
  721. package/dist/lib/lanes/accounts.js +366 -0
  722. package/dist/lib/lanes/admission-host.d.ts +22 -0
  723. package/dist/lib/lanes/admission-host.js +37 -0
  724. package/dist/lib/lanes/admission.d.ts +26 -0
  725. package/dist/lib/lanes/admission.js +210 -0
  726. package/dist/lib/lanes/approval-gate.d.ts +8 -0
  727. package/dist/lib/lanes/approval-gate.js +90 -0
  728. package/dist/lib/lanes/autopilot-metrics.d.ts +99 -0
  729. package/dist/lib/lanes/autopilot-metrics.js +301 -0
  730. package/dist/lib/lanes/autopilot-registry.d.ts +62 -0
  731. package/dist/lib/lanes/autopilot-registry.js +192 -0
  732. package/dist/lib/lanes/autopilot.d.ts +137 -0
  733. package/dist/lib/lanes/autopilot.js +1291 -0
  734. package/dist/lib/lanes/blocker-freshness.d.ts +31 -0
  735. package/dist/lib/lanes/blocker-freshness.js +168 -0
  736. package/dist/lib/lanes/checked-company-path.d.ts +3 -0
  737. package/dist/lib/lanes/checked-company-path.js +39 -0
  738. package/dist/lib/lanes/claude-balance.d.ts +97 -0
  739. package/dist/lib/lanes/claude-balance.js +319 -0
  740. package/dist/lib/lanes/compaction.d.ts +110 -0
  741. package/dist/lib/lanes/compaction.js +293 -0
  742. package/dist/lib/lanes/config.d.ts +94 -0
  743. package/dist/lib/lanes/config.js +606 -0
  744. package/dist/lib/lanes/constants.d.ts +3 -0
  745. package/dist/lib/lanes/constants.js +3 -0
  746. package/dist/lib/lanes/delivery-core.d.ts +15 -0
  747. package/dist/lib/lanes/delivery-core.js +21 -0
  748. package/dist/lib/lanes/delivery.d.ts +180 -0
  749. package/dist/lib/lanes/delivery.js +443 -0
  750. package/dist/lib/lanes/disk-guard.d.ts +65 -0
  751. package/dist/lib/lanes/disk-guard.js +172 -0
  752. package/dist/lib/lanes/dropbox.d.ts +129 -0
  753. package/dist/lib/lanes/dropbox.js +601 -0
  754. package/dist/lib/lanes/effort.d.ts +51 -0
  755. package/dist/lib/lanes/effort.js +113 -0
  756. package/dist/lib/lanes/envelope-repair-dispatch.d.ts +26 -0
  757. package/dist/lib/lanes/envelope-repair-dispatch.js +74 -0
  758. package/dist/lib/lanes/errors.d.ts +39 -0
  759. package/dist/lib/lanes/errors.js +72 -0
  760. package/dist/lib/lanes/flag-keys.d.ts +25 -0
  761. package/dist/lib/lanes/flag-keys.js +25 -0
  762. package/dist/lib/lanes/grants.d.ts +30 -0
  763. package/dist/lib/lanes/grants.js +171 -0
  764. package/dist/lib/lanes/hire-grant-dispatch.d.ts +29 -0
  765. package/dist/lib/lanes/hire-grant-dispatch.js +315 -0
  766. package/dist/lib/lanes/hooks-install.d.ts +82 -0
  767. package/dist/lib/lanes/hooks-install.js +555 -0
  768. package/dist/lib/lanes/host-capacity.d.ts +69 -0
  769. package/dist/lib/lanes/host-capacity.js +254 -0
  770. package/dist/lib/lanes/hq-root.d.ts +19 -0
  771. package/dist/lib/lanes/hq-root.js +28 -0
  772. package/dist/lib/lanes/index.d.ts +76 -0
  773. package/dist/lib/lanes/index.js +42 -0
  774. package/dist/lib/lanes/keep-alive-audit.d.ts +47 -0
  775. package/dist/lib/lanes/keep-alive-audit.js +370 -0
  776. package/dist/lib/lanes/keep-alive.d.ts +68 -0
  777. package/dist/lib/lanes/keep-alive.js +343 -0
  778. package/dist/lib/lanes/kr-freshness.d.ts +76 -0
  779. package/dist/lib/lanes/kr-freshness.js +413 -0
  780. package/dist/lib/lanes/lane-company.d.ts +10 -0
  781. package/dist/lib/lanes/lane-company.js +41 -0
  782. package/dist/lib/lanes/liveness.d.ts +108 -0
  783. package/dist/lib/lanes/liveness.js +396 -0
  784. package/dist/lib/lanes/machine-identity.d.ts +34 -0
  785. package/dist/lib/lanes/machine-identity.js +92 -0
  786. package/dist/lib/lanes/manager-status-gate.d.ts +17 -0
  787. package/dist/lib/lanes/manager-status-gate.js +133 -0
  788. package/dist/lib/lanes/merge-command.d.ts +15 -0
  789. package/dist/lib/lanes/merge-command.js +629 -0
  790. package/dist/lib/lanes/mesh-events.d.ts +127 -0
  791. package/dist/lib/lanes/mesh-events.js +564 -0
  792. package/dist/lib/lanes/message-replay.d.ts +21 -0
  793. package/dist/lib/lanes/message-replay.js +122 -0
  794. package/dist/lib/lanes/models.d.ts +86 -0
  795. package/dist/lib/lanes/models.js +234 -0
  796. package/dist/lib/lanes/monitor.d.ts +48 -0
  797. package/dist/lib/lanes/monitor.js +428 -0
  798. package/dist/lib/lanes/move-account.d.ts +56 -0
  799. package/dist/lib/lanes/move-account.js +193 -0
  800. package/dist/lib/lanes/orphans.d.ts +25 -0
  801. package/dist/lib/lanes/orphans.js +102 -0
  802. package/dist/lib/lanes/outpost-dispatch.d.ts +156 -0
  803. package/dist/lib/lanes/outpost-dispatch.js +293 -0
  804. package/dist/lib/lanes/outpost-hire-cache.d.ts +22 -0
  805. package/dist/lib/lanes/outpost-hire-cache.js +153 -0
  806. package/dist/lib/lanes/outpost-identity.d.ts +33 -0
  807. package/dist/lib/lanes/outpost-identity.js +59 -0
  808. package/dist/lib/lanes/outpost-profile-repin.d.ts +17 -0
  809. package/dist/lib/lanes/outpost-profile-repin.js +84 -0
  810. package/dist/lib/lanes/outpost-pruner-install.d.ts +37 -0
  811. package/dist/lib/lanes/outpost-pruner-install.js +238 -0
  812. package/dist/lib/lanes/outpost-registry-worker-approval.d.ts +18 -0
  813. package/dist/lib/lanes/outpost-registry-worker-approval.js +109 -0
  814. package/dist/lib/lanes/outpost-snapshot-memo.d.ts +6 -0
  815. package/dist/lib/lanes/outpost-snapshot-memo.js +14 -0
  816. package/dist/lib/lanes/outpost-worktree-pruner-flag.d.ts +19 -0
  817. package/dist/lib/lanes/outpost-worktree-pruner-flag.js +86 -0
  818. package/dist/lib/lanes/outpost-worktree-pruner.d.ts +62 -0
  819. package/dist/lib/lanes/outpost-worktree-pruner.js +1201 -0
  820. package/dist/lib/lanes/profile.d.ts +69 -0
  821. package/dist/lib/lanes/profile.js +552 -0
  822. package/dist/lib/lanes/provider-rejection.d.ts +86 -0
  823. package/dist/lib/lanes/provider-rejection.js +286 -0
  824. package/dist/lib/lanes/questions.d.ts +90 -0
  825. package/dist/lib/lanes/questions.js +384 -0
  826. package/dist/lib/lanes/quota.d.ts +134 -0
  827. package/dist/lib/lanes/quota.js +471 -0
  828. package/dist/lib/lanes/reconcile-install.d.ts +90 -0
  829. package/dist/lib/lanes/reconcile-install.js +257 -0
  830. package/dist/lib/lanes/reconcile.d.ts +161 -0
  831. package/dist/lib/lanes/reconcile.js +3343 -0
  832. package/dist/lib/lanes/registry-flag.d.ts +35 -0
  833. package/dist/lib/lanes/registry-flag.js +164 -0
  834. package/dist/lib/lanes/registry-persona.d.ts +20 -0
  835. package/dist/lib/lanes/registry-persona.js +329 -0
  836. package/dist/lib/lanes/registry.d.ts +122 -0
  837. package/dist/lib/lanes/registry.js +570 -0
  838. package/dist/lib/lanes/reviews.d.ts +38 -0
  839. package/dist/lib/lanes/reviews.js +395 -0
  840. package/dist/lib/lanes/runaway-tool-guard.d.ts +38 -0
  841. package/dist/lib/lanes/runaway-tool-guard.js +284 -0
  842. package/dist/lib/lanes/session-relink.d.ts +25 -0
  843. package/dist/lib/lanes/session-relink.js +216 -0
  844. package/dist/lib/lanes/spawn.d.ts +355 -0
  845. package/dist/lib/lanes/spawn.js +2668 -0
  846. package/dist/lib/lanes/ssm-command-context.d.ts +12 -0
  847. package/dist/lib/lanes/ssm-command-context.js +52 -0
  848. package/dist/lib/lanes/store.d.ts +91 -0
  849. package/dist/lib/lanes/store.js +1822 -0
  850. package/dist/lib/lanes/stories.d.ts +23 -0
  851. package/dist/lib/lanes/stories.js +92 -0
  852. package/dist/lib/lanes/story-ledger.d.ts +80 -0
  853. package/dist/lib/lanes/story-ledger.js +815 -0
  854. package/dist/lib/lanes/story-switch.d.ts +21 -0
  855. package/dist/lib/lanes/story-switch.js +75 -0
  856. package/dist/lib/lanes/text-scan.d.ts +11 -0
  857. package/dist/lib/lanes/text-scan.js +103 -0
  858. package/dist/lib/lanes/throttle.d.ts +116 -0
  859. package/dist/lib/lanes/throttle.js +437 -0
  860. package/dist/lib/lanes/timestamp.d.ts +3 -0
  861. package/dist/lib/lanes/timestamp.js +26 -0
  862. package/dist/lib/lanes/tracker-checks.d.ts +77 -0
  863. package/dist/lib/lanes/tracker-checks.js +134 -0
  864. package/dist/lib/lanes/tracker-report-state.d.ts +10 -0
  865. package/dist/lib/lanes/tracker-report-state.js +124 -0
  866. package/dist/lib/lanes/tracker-report.d.ts +203 -0
  867. package/dist/lib/lanes/tracker-report.js +522 -0
  868. package/dist/lib/lanes/tracker-store.d.ts +18 -0
  869. package/dist/lib/lanes/tracker-store.js +106 -0
  870. package/dist/lib/lanes/types.d.ts +1030 -0
  871. package/dist/lib/lanes/types.js +418 -0
  872. package/dist/lib/lanes/wait.d.ts +39 -0
  873. package/dist/lib/lanes/wait.js +159 -0
  874. package/dist/lib/lanes/watch.d.ts +39 -0
  875. package/dist/lib/lanes/watch.js +249 -0
  876. package/dist/lib/lanes/watcher-main.d.ts +11 -0
  877. package/dist/lib/lanes/watcher-main.js +108 -0
  878. package/dist/lib/lanes/watcher.d.ts +287 -0
  879. package/dist/lib/lanes/watcher.js +1972 -0
  880. package/dist/lib/mesh/api.d.ts +103 -10
  881. package/dist/lib/mesh/api.js +334 -64
  882. package/dist/lib/mesh/client.d.ts +3 -2
  883. package/dist/lib/mesh/client.js +26 -7
  884. package/dist/lib/mesh/denial-codes.d.ts +5 -0
  885. package/dist/lib/mesh/denial-codes.js +14 -0
  886. package/dist/lib/mesh/live/backfill-held.d.ts +67 -16
  887. package/dist/lib/mesh/live/backfill-held.js +415 -61
  888. package/dist/lib/mesh/live/backoff.d.ts +2 -2
  889. package/dist/lib/mesh/live/backoff.js +16 -3
  890. package/dist/lib/mesh/live/daemon/board-refresh.d.ts +7 -1
  891. package/dist/lib/mesh/live/daemon/board-refresh.js +78 -30
  892. package/dist/lib/mesh/live/daemon/config.d.ts +36 -0
  893. package/dist/lib/mesh/live/daemon/config.js +120 -0
  894. package/dist/lib/mesh/live/daemon/credentials.d.ts +64 -10
  895. package/dist/lib/mesh/live/daemon/credentials.js +270 -20
  896. package/dist/lib/mesh/live/daemon/doctor.d.ts +53 -0
  897. package/dist/lib/mesh/live/daemon/doctor.js +190 -6
  898. package/dist/lib/mesh/live/daemon/index.d.ts +13 -10
  899. package/dist/lib/mesh/live/daemon/index.js +7 -6
  900. package/dist/lib/mesh/live/daemon/install.d.ts +255 -1
  901. package/dist/lib/mesh/live/daemon/install.js +811 -13
  902. package/dist/lib/mesh/live/daemon/legacy-listen.d.ts +43 -0
  903. package/dist/lib/mesh/live/daemon/legacy-listen.js +89 -0
  904. package/dist/lib/mesh/live/daemon/live-cache.d.ts +26 -0
  905. package/dist/lib/mesh/live/daemon/live-cache.js +116 -0
  906. package/dist/lib/mesh/live/daemon/mqtt-events.d.ts +7 -0
  907. package/dist/lib/mesh/live/daemon/mqtt-events.js +2 -0
  908. package/dist/lib/mesh/live/daemon/mqtt-events.test-d.d.ts +2 -0
  909. package/dist/lib/mesh/live/daemon/mqtt-events.test-d.js +10 -0
  910. package/dist/lib/mesh/live/daemon/paths.d.ts +2 -0
  911. package/dist/lib/mesh/live/daemon/paths.js +2 -0
  912. package/dist/lib/mesh/live/daemon/presence.d.ts +24 -5
  913. package/dist/lib/mesh/live/daemon/presence.js +79 -10
  914. package/dist/lib/mesh/live/daemon/run.d.ts +48 -2
  915. package/dist/lib/mesh/live/daemon/run.js +485 -33
  916. package/dist/lib/mesh/live/daemon/state.d.ts +19 -2
  917. package/dist/lib/mesh/live/daemon/state.js +34 -2
  918. package/dist/lib/mesh/live/daemon/transcript-watch.d.ts +45 -9
  919. package/dist/lib/mesh/live/daemon/transcript-watch.js +227 -31
  920. package/dist/lib/mesh/live/daemon/version-drift.d.ts +5 -0
  921. package/dist/lib/mesh/live/daemon/version-drift.js +47 -0
  922. package/dist/lib/mesh/live/daemon/work-subscribe.d.ts +32 -0
  923. package/dist/lib/mesh/live/daemon/work-subscribe.js +262 -0
  924. package/dist/lib/mesh/live/emit-client.d.ts +8 -0
  925. package/dist/lib/mesh/live/emit-client.js +23 -8
  926. package/dist/lib/mesh/live/emit-evidence.d.ts +19 -0
  927. package/dist/lib/mesh/live/emit-evidence.js +20 -2
  928. package/dist/lib/mesh/live/emit.d.ts +9 -0
  929. package/dist/lib/mesh/live/emit.js +28 -2
  930. package/dist/lib/mesh/live/enqueue.d.ts +5 -0
  931. package/dist/lib/mesh/live/enqueue.js +19 -0
  932. package/dist/lib/mesh/live/flush.d.ts +17 -5
  933. package/dist/lib/mesh/live/flush.js +391 -38
  934. package/dist/lib/mesh/live/format-spool-line.d.ts +5 -2
  935. package/dist/lib/mesh/live/format-spool-line.js +10 -0
  936. package/dist/lib/mesh/live/paths.d.ts +2 -0
  937. package/dist/lib/mesh/live/paths.js +4 -0
  938. package/dist/lib/mesh/live/report-summary.d.ts +45 -0
  939. package/dist/lib/mesh/live/report-summary.js +234 -0
  940. package/dist/lib/mesh/live/session-event.schema.json +24 -1
  941. package/dist/lib/mesh/live/session-events-client.d.ts +2 -0
  942. package/dist/lib/mesh/live/session-events-client.js +26 -0
  943. package/dist/lib/mesh/live/session-seq.d.ts +4 -0
  944. package/dist/lib/mesh/live/session-seq.js +33 -0
  945. package/dist/lib/mesh/live/spool.d.ts +19 -0
  946. package/dist/lib/mesh/live/spool.js +269 -3
  947. package/dist/lib/mesh/live/validate-session-event.d.ts +1 -1
  948. package/dist/lib/mesh/live/validate-session-event.js +1 -1
  949. package/dist/lib/mesh/project-board.d.ts +65 -0
  950. package/dist/lib/mesh/project-board.js +181 -0
  951. package/dist/lib/mesh/story-status.d.ts +22 -0
  952. package/dist/lib/mesh/story-status.js +49 -0
  953. package/dist/lib/monitor.d.ts +149 -0
  954. package/dist/lib/monitor.js +519 -0
  955. package/dist/lib/node-binary.d.ts +50 -0
  956. package/dist/lib/node-binary.js +133 -0
  957. package/dist/lib/notify-recipient.d.ts +7 -0
  958. package/dist/lib/notify-recipient.js +11 -0
  959. package/dist/lib/onboarding/checkpoint.d.ts +13 -0
  960. package/dist/lib/onboarding/checkpoint.js +44 -0
  961. package/dist/lib/onboarding/cli/onboard.d.ts +53 -0
  962. package/dist/lib/onboarding/cli/onboard.js +135 -0
  963. package/dist/lib/onboarding/cli/prompts.d.ts +28 -0
  964. package/dist/lib/onboarding/cli/prompts.js +83 -0
  965. package/dist/lib/onboarding/errors.d.ts +34 -0
  966. package/dist/lib/onboarding/errors.js +59 -0
  967. package/dist/lib/onboarding/index.d.ts +13 -0
  968. package/dist/lib/onboarding/index.js +13 -0
  969. package/dist/lib/onboarding/orchestrator.d.ts +47 -0
  970. package/dist/lib/onboarding/orchestrator.js +569 -0
  971. package/dist/lib/onboarding/types.d.ts +79 -0
  972. package/dist/lib/onboarding/types.js +8 -0
  973. package/dist/lib/plan-limit-nag.d.ts +102 -6
  974. package/dist/lib/plan-limit-nag.js +348 -43
  975. package/dist/lib/policy-validator.d.ts +7 -0
  976. package/dist/lib/policy-validator.js +187 -0
  977. package/dist/lib/process-flag-company-context.d.ts +8 -0
  978. package/dist/lib/process-flag-company-context.js +67 -0
  979. package/dist/lib/report-publish.d.ts +175 -0
  980. package/dist/lib/report-publish.js +421 -0
  981. package/dist/lib/report-run.d.ts +62 -0
  982. package/dist/lib/report-run.js +123 -0
  983. package/dist/lib/report-snapshot.d.ts +12 -0
  984. package/dist/lib/report-snapshot.js +135 -0
  985. package/dist/lib/report-templates.d.ts +9 -0
  986. package/dist/lib/report-templates.js +21 -0
  987. package/dist/lib/scaffold-cli-floor.d.ts +8 -0
  988. package/dist/lib/scaffold-cli-floor.js +50 -0
  989. package/dist/lib/scan-packages/index.d.ts +2 -0
  990. package/dist/lib/scan-packages/index.js +168 -6
  991. package/dist/lib/search-index/background.d.ts +8 -1
  992. package/dist/lib/search-index/background.js +55 -200
  993. package/dist/lib/search-index/collection-path-repair-flag.d.ts +4 -0
  994. package/dist/lib/search-index/collection-path-repair-flag.js +7 -0
  995. package/dist/lib/search-index/embed-lock.d.ts +34 -0
  996. package/dist/lib/search-index/embed-lock.js +295 -0
  997. package/dist/lib/search-index/index.d.ts +12 -0
  998. package/dist/lib/search-index/index.js +153 -7
  999. package/dist/lib/search-index/load-gate.d.ts +57 -0
  1000. package/dist/lib/search-index/load-gate.js +270 -0
  1001. package/dist/lib/search-index/max-doc-bytes.d.ts +219 -0
  1002. package/dist/lib/search-index/max-doc-bytes.js +463 -0
  1003. package/dist/lib/search-index/qmd-exit-diagnostics.d.ts +5 -0
  1004. package/dist/lib/search-index/qmd-exit-diagnostics.js +40 -0
  1005. package/dist/lib/search-index/reindex-single-flight-flag.d.ts +5 -0
  1006. package/dist/lib/search-index/reindex-single-flight-flag.js +8 -0
  1007. package/dist/lib/service-manager/index.d.ts +42 -0
  1008. package/dist/lib/service-manager/index.js +105 -0
  1009. package/dist/lib/service-manager/launchd.d.ts +81 -0
  1010. package/dist/lib/service-manager/launchd.js +212 -0
  1011. package/dist/lib/service-manager/systemd.d.ts +19 -0
  1012. package/dist/lib/service-manager/systemd.js +72 -0
  1013. package/dist/lib/service-manager/types.d.ts +34 -0
  1014. package/dist/lib/service-manager/types.js +26 -0
  1015. package/dist/lib/test-utils/isolated-flag-company-context.d.ts +3 -0
  1016. package/dist/lib/test-utils/isolated-flag-company-context.js +18 -0
  1017. package/dist/lib/work-context/bind-best.d.ts +66 -0
  1018. package/dist/lib/work-context/bind-best.js +344 -0
  1019. package/dist/lib/work-context/bind-calling-session.d.ts +26 -0
  1020. package/dist/lib/work-context/bind-calling-session.js +63 -0
  1021. package/dist/lib/work-context/company-rebind.d.ts +23 -0
  1022. package/dist/lib/work-context/company-rebind.js +59 -0
  1023. package/dist/lib/work-context/company.d.ts +22 -20
  1024. package/dist/lib/work-context/company.js +124 -40
  1025. package/dist/lib/work-context/config.d.ts +58 -11
  1026. package/dist/lib/work-context/config.js +334 -83
  1027. package/dist/lib/work-context/contract.d.ts +13 -0
  1028. package/dist/lib/work-context/contract.schema.json +3 -1
  1029. package/dist/lib/work-context/default-company.d.ts +43 -0
  1030. package/dist/lib/work-context/default-company.js +83 -0
  1031. package/dist/lib/work-context/outbox-quarantine-status-flag.d.ts +4 -0
  1032. package/dist/lib/work-context/outbox-quarantine-status-flag.js +7 -0
  1033. package/dist/lib/work-context/outbox.d.ts +27 -5
  1034. package/dist/lib/work-context/outbox.js +135 -6
  1035. package/dist/lib/work-context/prd-sync.d.ts +56 -0
  1036. package/dist/lib/work-context/prd-sync.js +197 -0
  1037. package/dist/lib/work-context/preflight-contract.d.ts +28 -0
  1038. package/dist/lib/work-context/preflight-contract.js +85 -0
  1039. package/dist/lib/work-context/prompt-rebind.d.ts +25 -0
  1040. package/dist/lib/work-context/prompt-rebind.js +85 -0
  1041. package/dist/lib/work-context/reconcile.d.ts +15 -0
  1042. package/dist/lib/work-context/reconcile.js +405 -29
  1043. package/dist/lib/work-context/state.d.ts +93 -10
  1044. package/dist/lib/work-context/state.js +342 -29
  1045. package/dist/lib/work-context/windows-acl.d.ts +123 -0
  1046. package/dist/lib/work-context/windows-acl.js +425 -0
  1047. package/dist/lib/workers-registry/index.js +62 -8
  1048. package/dist/lib/workers-registry/read.d.ts +15 -0
  1049. package/dist/lib/workers-registry/read.js +17 -0
  1050. package/dist/main.d.ts +32 -0
  1051. package/dist/main.js +273 -73
  1052. package/dist/native-fast-route.d.ts +7 -0
  1053. package/dist/native-fast-route.js +45 -0
  1054. package/dist/node-network-compat-core.d.ts +12 -0
  1055. package/dist/node-network-compat-core.js +41 -0
  1056. package/dist/node-network-compat-fast.d.ts +7 -0
  1057. package/dist/node-network-compat-fast.js +23 -0
  1058. package/dist/node-network-compat.d.ts +2 -30
  1059. package/dist/node-network-compat.js +4 -51
  1060. package/dist/node-preflight.d.ts +7 -1
  1061. package/dist/node-preflight.js +5 -5
  1062. package/dist/register-all.d.ts +4 -29
  1063. package/dist/register-all.js +4 -233
  1064. package/dist/run/discover-schemas.d.ts +2 -1
  1065. package/dist/run/env-graph-guard.d.ts +2 -2
  1066. package/dist/run/env-graph-guard.js +5 -2
  1067. package/dist/run/hq-plugin.d.ts +4 -0
  1068. package/dist/run/hq-plugin.js +36 -8
  1069. package/dist/secrets-env-fast-path.d.ts +5 -0
  1070. package/dist/secrets-env-fast-path.js +16 -0
  1071. package/dist/secrets-env-fast-route.d.ts +18 -0
  1072. package/dist/secrets-env-fast-route.js +54 -0
  1073. package/dist/sentry-before-send.js +80 -0
  1074. package/dist/sentry.d.ts +16 -4
  1075. package/dist/sentry.js +179 -18
  1076. package/dist/startup-registration.d.ts +26 -2
  1077. package/dist/startup-registration.js +116 -15
  1078. package/dist/utils/checkpoint-stamp-write-error.d.ts +28 -0
  1079. package/dist/utils/checkpoint-stamp-write-error.js +99 -0
  1080. package/dist/utils/cli-network-lifecycle.d.ts +4 -0
  1081. package/dist/utils/cli-network-lifecycle.js +11 -0
  1082. package/dist/utils/cli-telemetry.d.ts +75 -1
  1083. package/dist/utils/cli-telemetry.js +433 -7
  1084. package/dist/utils/client-health.d.ts +0 -4
  1085. package/dist/utils/client-health.js +2 -2
  1086. package/dist/utils/cognito-refresh-sentry.d.ts +3 -0
  1087. package/dist/utils/cognito-refresh-sentry.js +49 -0
  1088. package/dist/utils/cognito-session.d.ts +71 -0
  1089. package/dist/utils/cognito-session.js +481 -27
  1090. package/dist/utils/console-origin.d.ts +9 -0
  1091. package/dist/utils/console-origin.js +28 -0
  1092. package/dist/utils/contribution-table.d.ts +1 -1
  1093. package/dist/utils/core-eval-trigger.d.ts +4 -0
  1094. package/dist/utils/core-eval-trigger.js +88 -0
  1095. package/dist/utils/environmental-error.d.ts +18 -0
  1096. package/dist/utils/environmental-error.js +240 -7
  1097. package/dist/utils/exclusive-lock.d.ts +32 -0
  1098. package/dist/utils/exclusive-lock.js +75 -0
  1099. package/dist/utils/expected-cli-error.d.ts +2 -0
  1100. package/dist/utils/expected-cli-error.js +4 -0
  1101. package/dist/utils/fast-stream-errors.d.ts +12 -0
  1102. package/dist/utils/fast-stream-errors.js +18 -0
  1103. package/dist/utils/feedback-diagnostics.d.ts +2 -1
  1104. package/dist/utils/feedback-log-bundle.d.ts +51 -26
  1105. package/dist/utils/feedback-log-bundle.js +211 -31
  1106. package/dist/utils/feedback-logs.d.ts +18 -47
  1107. package/dist/utils/feedback-logs.js +50 -21
  1108. package/dist/utils/feedback-screenshots.d.ts +0 -1
  1109. package/dist/utils/feedback-screenshots.js +1 -1
  1110. package/dist/utils/files-browse-acl.d.ts +5 -0
  1111. package/dist/utils/files-browse-acl.js +11 -0
  1112. package/dist/utils/hq-core-yaml.d.ts +10 -0
  1113. package/dist/utils/hq-core-yaml.js +40 -0
  1114. package/dist/utils/hq-root-resolver.d.ts +13 -0
  1115. package/dist/utils/hq-root-resolver.js +103 -0
  1116. package/dist/utils/hq-roots.d.ts +25 -2
  1117. package/dist/utils/hq-roots.js +67 -7
  1118. package/dist/utils/incomplete-install-error.d.ts +87 -19
  1119. package/dist/utils/incomplete-install-error.js +319 -68
  1120. package/dist/utils/install-tree-torn.d.ts +260 -24
  1121. package/dist/utils/install-tree-torn.js +998 -51
  1122. package/dist/utils/large-file-guard.d.ts +0 -10
  1123. package/dist/utils/large-file-guard.js +1 -1
  1124. package/dist/utils/local-files-overview.d.ts +4 -8
  1125. package/dist/utils/local-files-overview.js +48 -7
  1126. package/dist/utils/login-provider.d.ts +7 -0
  1127. package/dist/utils/login-provider.js +34 -0
  1128. package/dist/utils/pack-contributions.d.ts +2 -14
  1129. package/dist/utils/pack-contributions.js +7 -44
  1130. package/dist/utils/package-root-diagnostics.d.ts +1 -1
  1131. package/dist/utils/people.d.ts +7 -11
  1132. package/dist/utils/people.js +5 -20
  1133. package/dist/utils/plan-gate-error.d.ts +52 -10
  1134. package/dist/utils/plan-gate-error.js +364 -41
  1135. package/dist/utils/qmd-model-download-error.d.ts +0 -8
  1136. package/dist/utils/qmd-model-download-error.js +1 -1
  1137. package/dist/utils/qmd-query-document-error.d.ts +0 -6
  1138. package/dist/utils/qmd-query-document-error.js +1 -1
  1139. package/dist/utils/redact-error-text.d.ts +0 -2
  1140. package/dist/utils/redact-error-text.js +3 -2
  1141. package/dist/utils/redact-url.d.ts +14 -0
  1142. package/dist/utils/redact-url.js +218 -0
  1143. package/dist/utils/run-bundled-script.d.ts +6 -0
  1144. package/dist/utils/run-bundled-script.js +117 -4
  1145. package/dist/utils/sandbox-runner-client.d.ts +2 -1
  1146. package/dist/utils/scaffold-fast-import-guard.d.ts +2 -0
  1147. package/dist/utils/scaffold-fast-import-guard.js +40 -0
  1148. package/dist/utils/scaffold-packlist-guard.d.ts +7 -0
  1149. package/dist/utils/scaffold-packlist-guard.js +23 -0
  1150. package/dist/utils/scaffold-sibling-references.d.ts +22 -0
  1151. package/dist/utils/scaffold-sibling-references.js +156 -0
  1152. package/dist/utils/secret-load-availability.d.ts +8 -0
  1153. package/dist/utils/secret-load-availability.js +54 -0
  1154. package/dist/utils/secrets-cache.d.ts +7 -3
  1155. package/dist/utils/secrets-cache.js +162 -14
  1156. package/dist/utils/self-update.d.ts +34 -1
  1157. package/dist/utils/self-update.js +660 -42
  1158. package/dist/utils/sentry-fingerprint.d.ts +23 -1
  1159. package/dist/utils/sentry-fingerprint.js +223 -31
  1160. package/dist/utils/staged-install.d.ts +34 -0
  1161. package/dist/utils/staged-install.js +346 -0
  1162. package/dist/utils/staged-npm-install.d.ts +16 -0
  1163. package/dist/utils/staged-npm-install.js +264 -0
  1164. package/dist/utils/sync-log-sources.d.ts +15 -0
  1165. package/dist/utils/sync-log-sources.js +36 -0
  1166. package/dist/utils/table-width.d.ts +7 -0
  1167. package/dist/utils/table-width.js +15 -0
  1168. package/dist/utils/team-upgrade.d.ts +1 -1
  1169. package/dist/utils/team-upgrade.js +4 -3
  1170. package/dist/utils/update-command-supervisor.cjs +247 -0
  1171. package/dist/utils/upload-author.d.ts +15 -0
  1172. package/dist/utils/upload-author.js +39 -0
  1173. package/dist/utils/vault-api.d.ts +21 -1
  1174. package/dist/utils/vault-api.js +251 -84
  1175. package/dist/utils/version-check.d.ts +11 -1
  1176. package/dist/utils/version-check.js +32 -3
  1177. package/dist/utils/version-gate.d.ts +101 -17
  1178. package/dist/utils/version-gate.js +645 -70
  1179. package/dist/utils/version-report.d.ts +27 -0
  1180. package/dist/utils/version-report.js +105 -0
  1181. package/dist/utils/windows-spawn.d.ts +6 -0
  1182. package/dist/utils/windows-spawn.js +37 -0
  1183. package/dist/version-request.d.ts +14 -0
  1184. package/dist/version-request.js +36 -0
  1185. package/package.json +20 -8
  1186. package/scripts/mesh-daemon-if-stale.mjs +20 -0
  1187. package/templates/reports/blank.md +3 -0
  1188. package/templates/reports/daily-digest.md +11 -0
  1189. package/templates/runbooks/update-report.md +21 -0
  1190. package/dist/commands/scaffold-fast.d.ts +0 -41
  1191. package/dist/commands/scaffold-fast.js +0 -57
  1192. package/dist/lib/work-context/index.d.ts +0 -25
  1193. package/dist/lib/work-context/index.js +0 -21
@@ -0,0 +1,1291 @@
1
+ import { createHash } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { laneRunsOnHost } from "./admission.js";
5
+ import { isControllerAliasOutpostId } from "./admission-host.js";
6
+ import { LEAD_REGISTRY_REL, validateOutpostLeadRegistry } from "./autopilot-registry.js";
7
+ import { appendDropboxMessage } from "./dropbox.js";
8
+ import { LanesError } from "./errors.js";
9
+ import { LANE_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG, LANE_AUTOPILOT_NUDGE_DEDUPE_FLAG, LEAD_AUTOPILOT_KPI_STALENESS_BATCH_FLAG, LEAD_AUTOPILOT_KPI_STALENESS_FLAG, LEAD_AUTOPILOT_HEADLINE_STALENESS_FLAG, LEAD_AUTOPILOT_PER_LEAD_ERRORS_FLAG as PER_LEAD_ERRORS_FLAG, } from "./flag-keys.js";
10
+ import { resolveLaneCompany } from "./lane-company.js";
11
+ import { readLanesRegistryFlag } from "./registry-flag.js";
12
+ import { readAllLanes } from "./store.js";
13
+ export const LEAD_AUTOPILOT_FLAG = "lanes.lead-autopilot";
14
+ export const LEAD_AUTOPILOT_DEFAULT_ENABLED = false;
15
+ export const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG = LANE_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG;
16
+ export const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DEFAULT_ENABLED = false;
17
+ export const LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DELAY_MS = 60 * 60_000;
18
+ export const LEAD_AUTOPILOT_NUDGE_DEDUPE_FLAG = LANE_AUTOPILOT_NUDGE_DEDUPE_FLAG;
19
+ export const LEAD_AUTOPILOT_NUDGE_DEDUPE_DEFAULT_ENABLED = false;
20
+ export const LEAD_AUTOPILOT_NUDGE_REDELIVERY_DELAY_MS = 30 * 60_000;
21
+ export const LEAD_AUTOPILOT_NUDGE_STATE_RETENTION_MS = 24 * 60 * 60_000;
22
+ const LEAD_AUTOPILOT_DELIVERED_ID_RETENTION_MS = 7 * 24 * 60 * 60_000;
23
+ export const LEAD_AUTOPILOT_REVIEW_DELAY_MS = 15 * 60_000;
24
+ export const LEAD_AUTOPILOT_FILL_DELAY_MS = 15 * 60_000;
25
+ export const LEAD_AUTOPILOT_PROMPT_LOOP = "personal/knowledge/team-lead-operating-loop.md";
26
+ export const LEAD_AUTOPILOT_KPI_STALE_AFTER_MINUTES = 55;
27
+ export const LEAD_AUTOPILOT_HEADLINE_STALE_AFTER_MINUTES = 55;
28
+ export const LEAD_AUTOPILOT_PER_LEAD_ERRORS_FLAG = PER_LEAD_ERRORS_FLAG;
29
+ export const LEAD_AUTOPILOT_PER_LEAD_ERRORS_DEFAULT_ENABLED = false;
30
+ const LIVE_STATES = new Set(["running", "queued", "awaiting_input", "blocked"]);
31
+ const OPEN_STORY_STATES = new Set(["todo", "queued", "in_progress", "review", "blocked"]);
32
+ function isOpenProjectStory(story) {
33
+ return story.passes !== true && OPEN_STORY_STATES.has(story.status);
34
+ }
35
+ function isRecord(value) {
36
+ return value !== null && typeof value === "object" && !Array.isArray(value);
37
+ }
38
+ function readJsonFile(filePath, code) {
39
+ let text;
40
+ try {
41
+ const stat = fs.lstatSync(filePath);
42
+ if (!stat.isFile() || stat.isSymbolicLink())
43
+ throw new Error("expected a regular file");
44
+ text = fs.readFileSync(filePath, "utf8");
45
+ }
46
+ catch (error) {
47
+ throw new LanesError(code, `Cannot read ${filePath}: ${error instanceof Error ? error.message : String(error)}`, { path: filePath });
48
+ }
49
+ try {
50
+ return JSON.parse(text);
51
+ }
52
+ catch (error) {
53
+ throw new LanesError(code, `Cannot parse ${filePath}: ${error instanceof Error ? error.message : String(error)}`, { path: filePath });
54
+ }
55
+ }
56
+ function parseRegistry(hqRoot, outpostId, now) {
57
+ const file = path.join(hqRoot, LEAD_REGISTRY_REL);
58
+ let stat;
59
+ try {
60
+ stat = fs.lstatSync(file);
61
+ }
62
+ catch (error) {
63
+ if (error.code === "ENOENT") {
64
+ // An Outpost without a delivered registry reports it; it does not fail reconcile.
65
+ // The primary delivers nothing when it has no registry or every company is flagged off.
66
+ if (outpostId !== null && !isControllerAliasOutpostId(outpostId, { kind: "outpost", id: outpostId }))
67
+ return null;
68
+ return [];
69
+ }
70
+ throw new LanesError("lead_autopilot_registry_invalid", `Cannot inspect ${file}: ${error instanceof Error ? error.message : String(error)}`, { path: file });
71
+ }
72
+ if (!stat.isFile() || stat.isSymbolicLink()) {
73
+ throw new LanesError("lead_autopilot_registry_invalid", `Invalid lead registry ${file}: expected a regular file`, { path: file });
74
+ }
75
+ const raw = readJsonFile(file, "lead_autopilot_registry_invalid");
76
+ if (outpostId !== null && !isControllerAliasOutpostId(outpostId, { kind: "outpost", id: outpostId }))
77
+ return validateOutpostLeadRegistry({ registry: raw, outpostId, now }).juniors;
78
+ if (isRecord(raw) && raw.juniors === undefined && Array.isArray(raw.retired))
79
+ return [];
80
+ if (!isRecord(raw) || !Array.isArray(raw.juniors)) {
81
+ throw new LanesError("lead_autopilot_registry_invalid", `Invalid lead registry ${file}: juniors must be an array`, { path: file });
82
+ }
83
+ const rows = [];
84
+ for (const [index, value] of raw.juniors.entries()) {
85
+ if (!isRecord(value) || ["team", "lane", "host", "status", "prd"].some((key) => typeof value[key] !== "string" || !value[key].trim())) {
86
+ throw new LanesError("lead_autopilot_registry_invalid", `Invalid lead registry ${file}: juniors[${index}] must name team, lane, host, status, and prd`, { path: file, index });
87
+ }
88
+ rows.push(value);
89
+ }
90
+ return rows;
91
+ }
92
+ function registeredFilePath(hqRoot, relativePath, errorCode) {
93
+ const root = path.resolve(hqRoot);
94
+ const file = path.resolve(root, relativePath);
95
+ if (file === root || !file.startsWith(`${root}${path.sep}`)) {
96
+ throw new LanesError(errorCode, `Registered path escapes HQ root: ${relativePath}`, { path: relativePath });
97
+ }
98
+ try {
99
+ const realRoot = fs.realpathSync(root);
100
+ const realFile = fs.realpathSync(file);
101
+ if (realFile === realRoot || !realFile.startsWith(`${realRoot}${path.sep}`)) {
102
+ throw new LanesError(errorCode, `Registered path resolves outside HQ root: ${relativePath}`, { path: relativePath });
103
+ }
104
+ }
105
+ catch (error) {
106
+ if (error instanceof LanesError)
107
+ throw error;
108
+ throw new LanesError(errorCode, `Cannot resolve registered path ${relativePath}: ${error instanceof Error ? error.message : String(error)}`, { path: relativePath });
109
+ }
110
+ return file;
111
+ }
112
+ function projectStories(hqRoot, relativePath, companySlug, projectId) {
113
+ if (companySlug !== undefined) {
114
+ const expected = path.join("companies", companySlug, "projects", projectId, "prd.json");
115
+ if (path.normalize(relativePath) !== expected) {
116
+ throw new LanesError("lead_autopilot_tenant_mismatch", `Project registry path does not match lead ${companySlug}/${projectId}`, { path: relativePath, company: companySlug, project_id: projectId });
117
+ }
118
+ }
119
+ const file = registeredFilePath(hqRoot, relativePath, "lead_autopilot_project_path_invalid");
120
+ const raw = readJsonFile(file, "lead_autopilot_project_invalid");
121
+ const rows = isRecord(raw) ? raw.userStories ?? raw.stories : undefined;
122
+ if (!Array.isArray(rows)) {
123
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: userStories or stories must be an array`, { path: file });
124
+ }
125
+ return rows.map((story, index) => {
126
+ const rawStatus = isRecord(story) ? story.status ?? story.state : undefined;
127
+ const status = isRecord(story) && story.passes === true ? "done" : rawStatus;
128
+ if (!isRecord(story) || typeof story.id !== "string" || typeof status !== "string") {
129
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: stories[${index}] needs string id and status/state`, { path: file, index });
130
+ }
131
+ const sourceRef = isRecord(story.source) ? story.source.ref : undefined;
132
+ const rawBrief = story.brief_path ?? story.brief_file ?? sourceRef;
133
+ if (story.lanes !== undefined && (!Array.isArray(story.lanes) || story.lanes.some((lane) => typeof lane === "string" ? !lane.trim() : !isRecord(lane) || typeof lane.lane_id !== "string" || !lane.lane_id.trim()))) {
134
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: stories[${index}] lanes must contain lane IDs or lane_id objects`, { path: file, index });
135
+ }
136
+ if (story.updated_at !== undefined && (typeof story.updated_at !== "string" || !Number.isFinite(Date.parse(story.updated_at)))) {
137
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: stories[${index}] updated_at must be a valid timestamp`, { path: file, index });
138
+ }
139
+ if (story.lane !== undefined && story.lane !== null && typeof story.lane !== "string") {
140
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: stories[${index}] lane must be a string`, { path: file, index });
141
+ }
142
+ if (story.external_blocker !== undefined && (typeof story.external_blocker !== "string" || !story.external_blocker.trim())) {
143
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: stories[${index}] external_blocker must be a non-empty string`, { path: file, index });
144
+ }
145
+ if (rawBrief !== undefined && (typeof rawBrief !== "string" || !rawBrief.trim())) {
146
+ throw new LanesError("lead_autopilot_project_invalid", `Invalid project ${file}: stories[${index}] brief path must be a non-empty string`, { path: file, index });
147
+ }
148
+ if (typeof rawBrief === "string" && companySlug !== undefined) {
149
+ const normalizedBrief = path.normalize(rawBrief);
150
+ if (normalizedBrief.startsWith(`companies${path.sep}`) && !normalizedBrief.startsWith(path.join("companies", companySlug) + path.sep)) {
151
+ throw new LanesError("lead_autopilot_tenant_mismatch", `Story brief path does not match lead ${companySlug}/${projectId}`, { path: rawBrief, company: companySlug, project_id: projectId });
152
+ }
153
+ }
154
+ let briefPath;
155
+ if (typeof rawBrief === "string") {
156
+ briefPath = registeredFilePath(hqRoot, rawBrief, "lead_autopilot_story_brief_path_invalid");
157
+ try {
158
+ const briefStat = fs.lstatSync(briefPath);
159
+ if (!briefStat.isFile() || briefStat.isSymbolicLink())
160
+ throw new Error("expected a regular file");
161
+ }
162
+ catch (error) {
163
+ throw new LanesError("lead_autopilot_story_brief_invalid", `Cannot read story brief ${rawBrief}: ${error instanceof Error ? error.message : String(error)}`, { path: rawBrief, story_id: story.id });
164
+ }
165
+ }
166
+ return {
167
+ id: story.id,
168
+ status,
169
+ ...(story.passes === true ? { passes: true } : {}),
170
+ ...(briefPath ? { briefPath } : {}),
171
+ ...storyLaneIds(story),
172
+ ...(typeof story.updated_at === "string" ? { updatedAt: story.updated_at } : {}),
173
+ ...(typeof story.external_blocker === "string" ? { externalBlocker: story.external_blocker } : {}),
174
+ deadlineFields: story,
175
+ };
176
+ });
177
+ }
178
+ const DEADLINE_FIELDS = ["deadline", "due_at", "unblock_by", "unblock_at", "eta"];
179
+ const CLOSED_COMMITMENT_STATES = new Set(["done", "resolved", "closed", "cancelled", "canceled", "dropped", "complete", "completed"]);
180
+ const COMMITMENT_SECTIONS = ["open_blockers", "waiting", "open_decisions", "decisions", "slot_requests", "blockers"];
181
+ function hasDeadlineField(value) {
182
+ return DEADLINE_FIELDS.some((field) => value[field] !== undefined && value[field] !== null && value[field] !== "");
183
+ }
184
+ function commitmentDue(value, context) {
185
+ const dates = [];
186
+ const errors = [];
187
+ for (const field of DEADLINE_FIELDS) {
188
+ const raw = value[field];
189
+ if (raw === undefined || raw === null || raw === "")
190
+ continue;
191
+ if (typeof raw !== "string" || !/^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d{1,9})?)?(?:Z|[+-]\d\d:\d\d)$/.test(raw) || !Number.isFinite(Date.parse(raw))) {
192
+ // `eta` is also used as free-text planning context in manager and story
193
+ // records. It is a deadline only when it is already a valid ISO instant.
194
+ if (field === "eta")
195
+ continue;
196
+ errors.push({ field, reason: `${context}.${field} must be a valid date-time` });
197
+ continue;
198
+ }
199
+ dates.push({ field, iso: new Date(Date.parse(raw)).toISOString() });
200
+ }
201
+ if (errors.length > 0)
202
+ return { due: null, errors };
203
+ if (dates.length === 0)
204
+ return { due: null, errors };
205
+ if (new Set(dates.map((date) => date.iso)).size > 1) {
206
+ return { due: null, errors: [{ field: "deadline_fields", reason: `${context} has conflicting deadline fields` }] };
207
+ }
208
+ return { due: dates[0].iso, errors };
209
+ }
210
+ function isResolvedCommitment(value, status) {
211
+ return value.passes === true || value.resolved === true || value.open === false ||
212
+ value.resolved_at !== undefined && value.resolved_at !== null ||
213
+ value.completed_at !== undefined && value.completed_at !== null ||
214
+ (typeof status === "string" && CLOSED_COMMITMENT_STATES.has(status.toLowerCase()));
215
+ }
216
+ function optionalLabel(value, fields, fallback) {
217
+ for (const field of fields) {
218
+ const candidate = value[field];
219
+ if (typeof candidate === "string" && candidate.trim())
220
+ return candidate.trim();
221
+ }
222
+ return fallback;
223
+ }
224
+ function deadlineCommitments(status, stories, leadLane) {
225
+ const commitments = [];
226
+ const errors = [];
227
+ for (const section of COMMITMENT_SECTIONS) {
228
+ const rows = status[section];
229
+ if (rows === undefined)
230
+ continue;
231
+ if (!Array.isArray(rows)) {
232
+ errors.push({ lead_lane: leadLane, item_ref: `manager:${section}`, field: section, reason: `Manager status ${section} must be an array` });
233
+ continue;
234
+ }
235
+ rows.forEach((row, index) => {
236
+ if (!isRecord(row) || !hasDeadlineField(row))
237
+ return;
238
+ const itemRef = `manager:${section}[${index}]`;
239
+ const dueResult = commitmentDue(row, `Manager status ${section}[${index}]`);
240
+ errors.push(...dueResult.errors.map((error) => ({ lead_lane: leadLane, item_ref: itemRef, ...error })));
241
+ if (dueResult.errors.length > 0 || !dueResult.due)
242
+ return;
243
+ const id = row.id;
244
+ if (typeof id !== "string" || !id.trim()) {
245
+ errors.push({ lead_lane: leadLane, item_ref: itemRef, field: "id", reason: `Manager status ${section}[${index}] with a deadline needs a non-empty id` });
246
+ return;
247
+ }
248
+ const owner = optionalLabel(row, ["owner", "unblock_owner", "waiting_on", "assigned_to"], "unassigned");
249
+ const state = typeof row.status === "string" ? row.status : typeof row.state === "string" ? row.state : undefined;
250
+ commitments.push({
251
+ key: `manager:${section}:${id}`,
252
+ item: id,
253
+ owner,
254
+ due: dueResult.due,
255
+ description: optionalLabel(row, ["what", "question", "request", "title", "line"], id),
256
+ resolved: isResolvedCommitment(row, state),
257
+ });
258
+ });
259
+ }
260
+ for (const story of stories) {
261
+ const raw = story.deadlineFields;
262
+ if (!raw || !hasDeadlineField(raw))
263
+ continue;
264
+ const dueResult = commitmentDue(raw, `Project story ${story.id}`);
265
+ errors.push(...dueResult.errors.map((error) => ({ lead_lane: leadLane, item_ref: `story:${story.id}`, ...error })));
266
+ if (dueResult.errors.length > 0 || !dueResult.due)
267
+ continue;
268
+ const state = typeof raw.status === "string" ? raw.status : typeof raw.state === "string" ? raw.state : story.status;
269
+ commitments.push({
270
+ key: `story:${story.id}`,
271
+ item: story.id,
272
+ owner: optionalLabel(raw, ["owner", "assigned_to"], "lead"),
273
+ due: dueResult.due,
274
+ description: optionalLabel(raw, ["title", "name", "what"], story.id),
275
+ resolved: isResolvedCommitment(raw, state),
276
+ });
277
+ }
278
+ return { commitments: commitments.sort((a, b) => a.key.localeCompare(b.key)), errors };
279
+ }
280
+ function readStatus(hqRoot, relativePath, companySlug) {
281
+ if (path.isAbsolute(relativePath)) {
282
+ throw new LanesError("lead_autopilot_status_path_invalid", `Registered status path must be relative to the HQ root: ${relativePath}`, { path: relativePath });
283
+ }
284
+ const root = path.resolve(hqRoot);
285
+ const file = registeredFilePath(root, relativePath, "lead_autopilot_status_path_invalid");
286
+ const assertCompanyBoundary = (candidate) => {
287
+ const relative = path.relative(root, candidate).split(path.sep);
288
+ if (relative[0] === "companies" && relative[1] !== companySlug) {
289
+ throw new LanesError("lead_autopilot_tenant_mismatch", `Manager status path does not match lead company ${companySlug}`, { path: relativePath, company: companySlug });
290
+ }
291
+ };
292
+ assertCompanyBoundary(path.resolve(root, relativePath));
293
+ assertCompanyBoundary(fs.realpathSync(file));
294
+ const status = readJsonFile(file, "lead_autopilot_status_invalid");
295
+ if (!isRecord(status))
296
+ throw new LanesError("lead_autopilot_status_invalid", `Invalid manager status ${file}: expected an object`, { path: file });
297
+ return status;
298
+ }
299
+ function parseOkrReports(status) {
300
+ const raw = status.okr_reports;
301
+ if (raw === undefined)
302
+ return [];
303
+ if (!Array.isArray(raw)) {
304
+ throw new LanesError("lead_autopilot_okr_reports_invalid", "Manager status okr_reports must be an array");
305
+ }
306
+ return raw.map((value, index) => {
307
+ if (!isRecord(value) || typeof value.at !== "string" || !Number.isFinite(Date.parse(value.at)) || !Array.isArray(value.kpis) || !Array.isArray(value.okrs)) {
308
+ throw new LanesError("lead_autopilot_okr_reports_invalid", `Manager status okr_reports[${index}] must include at, kpis, and okrs`);
309
+ }
310
+ const parseLines = (rows, kind) => rows.map((row, lineIndex) => {
311
+ if (!isRecord(row) || typeof row.id !== "string" || !row.id.trim()) {
312
+ throw new LanesError("lead_autopilot_okr_reports_invalid", `Manager status okr_reports[${index}].${kind.toLowerCase()}s[${lineIndex}] needs an id`);
313
+ }
314
+ const text = typeof row.line === "string" ? row.line : typeof row.name === "string" ? row.name : typeof row.objective === "string" ? row.objective : "";
315
+ if (!text.trim()) {
316
+ throw new LanesError("lead_autopilot_okr_reports_invalid", `Manager status okr_reports[${index}].${kind.toLowerCase()}s[${lineIndex}] needs a line, name, or objective`);
317
+ }
318
+ if ((row.value !== undefined && (typeof row.value !== "number" || !Number.isFinite(row.value))) ||
319
+ (row.moved !== undefined && (typeof row.moved !== "number" || !Number.isFinite(row.moved)))) {
320
+ throw new LanesError("lead_autopilot_okr_reports_invalid", `Manager status okr_reports[${index}].${kind.toLowerCase()}s[${lineIndex}] has invalid numeric progress`);
321
+ }
322
+ return { id: row.id, line: text, ...(typeof row.value === "number" ? { value: row.value } : {}), ...(typeof row.moved === "number" ? { moved: row.moved } : {}) };
323
+ });
324
+ return { at: value.at, kpis: parseLines(value.kpis, "KPI"), okrs: parseLines(value.okrs, "OKR") };
325
+ }).sort((a, b) => a.at.localeCompare(b.at));
326
+ }
327
+ // A story's current `lane` counts alongside its `lanes` history, so `lanes: []` with `lane: X` is assigned to X.
328
+ function storyLaneIds(story) {
329
+ const history = Array.isArray(story.lanes)
330
+ ? story.lanes.map((lane) => typeof lane === "string" ? lane : lane.lane_id)
331
+ : undefined;
332
+ const current = typeof story.lane === "string" && story.lane.trim() ? story.lane : undefined;
333
+ if (history)
334
+ return { laneIds: current && !history.includes(current) ? [...history, current] : history };
335
+ if (current)
336
+ return { laneIds: [current] };
337
+ return story.lane === "" ? { laneIds: [] } : {};
338
+ }
339
+ function statusBlockers(status) {
340
+ const raw = status.blockers;
341
+ if (raw === undefined)
342
+ return [];
343
+ if (!Array.isArray(raw))
344
+ throw new LanesError("lead_autopilot_status_invalid", "Manager status blockers must be an array");
345
+ return raw.map((value, index) => {
346
+ if (!isRecord(value) || typeof value.id !== "string" || !value.id.trim()) {
347
+ throw new LanesError("lead_autopilot_status_invalid", `Manager status blockers[${index}] needs a non-empty id`);
348
+ }
349
+ return value;
350
+ });
351
+ }
352
+ function managerKpiFreshness(status, now) {
353
+ const rawKpis = status.kpis;
354
+ if (rawKpis === undefined)
355
+ return [];
356
+ if (!Array.isArray(rawKpis)) {
357
+ return [{
358
+ name: "kpis",
359
+ measuredAt: null,
360
+ ageMinutes: null,
361
+ stale: false,
362
+ staleAfterMinutes: LEAD_AUTOPILOT_KPI_STALE_AFTER_MINUTES,
363
+ fingerprint: "",
364
+ error: "invalid_kpi",
365
+ }];
366
+ }
367
+ return rawKpis.map((value, index) => {
368
+ const invalid = () => {
369
+ let name = `KPI ${index + 1}`;
370
+ if (isRecord(value)) {
371
+ const rawName = typeof value.name === "string" ? value.name : value.id;
372
+ if (typeof rawName === "string" && rawName.trim())
373
+ name = rawName.trim();
374
+ }
375
+ return {
376
+ name,
377
+ measuredAt: null,
378
+ ageMinutes: null,
379
+ stale: false,
380
+ staleAfterMinutes: LEAD_AUTOPILOT_KPI_STALE_AFTER_MINUTES,
381
+ fingerprint: "",
382
+ ...(isRecord(value) && typeof value.status === "string" ? { status: value.status } : {}),
383
+ error: "invalid_kpi",
384
+ };
385
+ };
386
+ if (!isRecord(value)) {
387
+ return invalid();
388
+ }
389
+ const rawName = typeof value.name === "string" ? value.name : value.id;
390
+ if (typeof rawName !== "string" || !rawName.trim()) {
391
+ return invalid();
392
+ }
393
+ const staleAfterMinutes = value.stale_after_minutes === undefined
394
+ ? LEAD_AUTOPILOT_KPI_STALE_AFTER_MINUTES
395
+ : value.stale_after_minutes;
396
+ if (typeof staleAfterMinutes !== "number" || !Number.isSafeInteger(staleAfterMinutes) || staleAfterMinutes < 1 || staleAfterMinutes > 525_600) {
397
+ return invalid();
398
+ }
399
+ const measuredAt = typeof value.measured_at === "string" && Number.isFinite(Date.parse(value.measured_at))
400
+ ? new Date(Date.parse(value.measured_at)).toISOString()
401
+ : null;
402
+ const elapsedMs = measuredAt === null ? null : Math.max(0, now.getTime() - Date.parse(measuredAt));
403
+ const ageMinutes = elapsedMs === null ? null : Math.floor(elapsedMs / 60_000);
404
+ const terminalStatus = typeof value.status === "string" && ["superseded", "retired", "dropped"].includes(value.status.toLowerCase());
405
+ const stale = !terminalStatus && (elapsedMs === null || elapsedMs > staleAfterMinutes * 60_000);
406
+ const fingerprint = `stale-kpi:${createHash("sha256").update(JSON.stringify([rawName.trim(), measuredAt, value.value ?? null])).digest("hex")}`;
407
+ return {
408
+ name: rawName.trim(),
409
+ measuredAt,
410
+ ageMinutes,
411
+ stale,
412
+ staleAfterMinutes,
413
+ fingerprint,
414
+ ...(typeof value.status === "string" ? { status: value.status } : {}),
415
+ };
416
+ });
417
+ }
418
+ function managerHeadlineFreshness(status, now) {
419
+ let field;
420
+ let rawTimestamp;
421
+ if (typeof status.headline_at === "string" && status.headline_at.trim()) {
422
+ field = "headline_at";
423
+ rawTimestamp = status.headline_at;
424
+ }
425
+ else if (status.headline_at === undefined || status.headline_at === null) {
426
+ if (typeof status.now !== "string")
427
+ return undefined;
428
+ const prefix = status.now.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2}))/)?.[1];
429
+ if (!prefix)
430
+ return undefined;
431
+ field = "now";
432
+ rawTimestamp = prefix;
433
+ }
434
+ else {
435
+ return undefined;
436
+ }
437
+ const timestamp = Date.parse(rawTimestamp);
438
+ if (!Number.isFinite(timestamp))
439
+ return undefined;
440
+ const ageMinutes = Math.floor(Math.max(0, now.getTime() - timestamp) / 60_000);
441
+ if (now.getTime() - timestamp <= LEAD_AUTOPILOT_HEADLINE_STALE_AFTER_MINUTES * 60_000)
442
+ return undefined;
443
+ return { field, measuredAt: new Date(timestamp).toISOString(), ageMinutes };
444
+ }
445
+ function leastMoved(lines, priorLines = []) {
446
+ const priorById = new Map(priorLines.map((line) => [line.id, line]));
447
+ return [...lines].sort((a, b) => {
448
+ const moved = (line) => line.moved !== undefined ? Math.abs(line.moved) :
449
+ line.value !== undefined && priorById.get(line.id)?.value !== undefined ? Math.abs(line.value - priorById.get(line.id).value) : 0;
450
+ return moved(a) - moved(b) || a.id.localeCompare(b.id);
451
+ })[0];
452
+ }
453
+ export function planLeadAutopilotWakes(input) {
454
+ const { lead, children, stories, now } = input;
455
+ if (input.keepAliveResumed)
456
+ return [];
457
+ const status = input.managerStatus ?? {};
458
+ const reports = parseOkrReports(status);
459
+ const blockers = statusBlockers(status);
460
+ const byStory = new Map(stories.map((story) => [story.id, story]));
461
+ const wakes = [];
462
+ if (input.headlineStalenessEnabled && !(lead.story_status === "done" && lead.story_complete === true)) {
463
+ const headline = managerHeadlineFreshness(status, now);
464
+ if (headline) {
465
+ const fingerprint = `stale-headline:${createHash("sha256").update(JSON.stringify([headline.field, headline.measuredAt])).digest("hex")}`;
466
+ wakes.push({
467
+ condition: "stale_headline",
468
+ lead_lane: lead.lane_id,
469
+ story_id: "headline-staleness",
470
+ fingerprint,
471
+ prompt: `The dashboard ${headline.field} field is ${headline.ageMinutes} minutes old. Rewrite headline, headline_at, and now in manager-status.json so the team status is current. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.`,
472
+ });
473
+ }
474
+ }
475
+ if (input.kpiStalenessEnabled) {
476
+ const staleKpis = managerKpiFreshness(status, now).filter((kpi) => kpi.stale);
477
+ if (input.kpiStalenessBatchEnabled && staleKpis.length > 0) {
478
+ const byOldest = [...staleKpis].sort((a, b) => (b.ageMinutes ?? Number.MAX_SAFE_INTEGER) - (a.ageMinutes ?? Number.MAX_SAFE_INTEGER) ||
479
+ a.name.localeCompare(b.name));
480
+ const identity = staleKpis
481
+ .map(({ name, measuredAt }) => [name, measuredAt])
482
+ .sort(([nameA, measuredAtA], [nameB, measuredAtB]) => nameA.localeCompare(nameB) || String(measuredAtA).localeCompare(String(measuredAtB)));
483
+ const fingerprint = `stale-kpi-batch:${createHash("sha256").update(JSON.stringify(identity)).digest("hex")}`;
484
+ const details = byOldest.map((kpi) => `- ${kpi.name}: age ${kpi.ageMinutes === null ? "unknown" : kpi.ageMinutes} minutes (stale after ${kpi.staleAfterMinutes} minutes)`).join("\n");
485
+ wakes.push({
486
+ condition: "stale_kpi",
487
+ lead_lane: lead.lane_id,
488
+ story_id: "kpi-staleness",
489
+ kpi_id: "batch",
490
+ fingerprint,
491
+ prompt: `Re-measure these stale KPIs, oldest first:\n${details}\nUpdate measured_at in manager-status.json. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.`,
492
+ });
493
+ }
494
+ else {
495
+ for (const kpi of staleKpis) {
496
+ const age = kpi.ageMinutes === null
497
+ ? "its measurement age is unknown"
498
+ : `its latest measurement is ${kpi.ageMinutes} minutes old`;
499
+ wakes.push({
500
+ condition: "stale_kpi",
501
+ lead_lane: lead.lane_id,
502
+ story_id: "kpi-staleness",
503
+ kpi_id: kpi.name,
504
+ fingerprint: kpi.fingerprint,
505
+ prompt: `Re-measure KPI ${kpi.name}: ${age} (stale after ${kpi.staleAfterMinutes} minutes). Update measured_at in manager-status.json. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.`,
506
+ });
507
+ }
508
+ }
509
+ }
510
+ const finishedReviews = children.flatMap((child) => {
511
+ if (!["done", "blocked", "failed", "interrupted"].includes(child.state))
512
+ return [];
513
+ const story = byStory.get(child.story_id);
514
+ if (!story || !isOpenProjectStory(story))
515
+ return [];
516
+ const finishedAt = child.ended_at ?? child.updated_at;
517
+ const finishedMs = Date.parse(finishedAt);
518
+ if (!Number.isFinite(finishedMs) || now.getTime() - finishedMs < LEAD_AUTOPILOT_REVIEW_DELAY_MS)
519
+ return [];
520
+ return [{ laneId: child.lane_id, story, finishedAt }];
521
+ });
522
+ const knownChildIds = new Set(children.map((child) => child.lane_id));
523
+ const missingReviews = stories.flatMap((story) => {
524
+ if (!isOpenProjectStory(story) || !story.updatedAt || !story.laneIds)
525
+ return [];
526
+ const finishedMs = Date.parse(story.updatedAt);
527
+ if (!Number.isFinite(finishedMs) || now.getTime() - finishedMs < LEAD_AUTOPILOT_REVIEW_DELAY_MS)
528
+ return [];
529
+ // The lead's own lane is never a finished worker of itself.
530
+ return story.laneIds.filter((laneId) => laneId !== lead.lane_id && !knownChildIds.has(laneId))
531
+ .map((laneId) => ({ laneId, story, finishedAt: story.updatedAt }));
532
+ });
533
+ const overdueReviews = [...finishedReviews, ...missingReviews].sort((a, b) => a.laneId.localeCompare(b.laneId));
534
+ if (overdueReviews.length > 0) {
535
+ const fingerprint = `review:${overdueReviews.map(({ laneId, story, finishedAt }) => `${laneId}:${story.id}:${story.status}:${finishedAt}`).join(",")}`;
536
+ const reviewList = overdueReviews.map(({ laneId, story }) => `lane ${laneId} (story ${story.id}, status ${story.status})`).join("; ");
537
+ wakes.push({
538
+ condition: "review_finished_worker",
539
+ lead_lane: lead.lane_id,
540
+ story_id: overdueReviews.map(({ story }) => story.id).join(","),
541
+ ...(overdueReviews.length === 1 ? { worker_lane: overdueReviews[0].laneId } : {}),
542
+ fingerprint,
543
+ prompt: `Review finished worker ${overdueReviews.length === 1 ? "lane" : "lanes"}: ${reviewList}. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.`,
544
+ });
545
+ }
546
+ const liveChildren = children.filter((child) => LIVE_STATES.has(child.state));
547
+ const liveCount = liveChildren.length;
548
+ const assigned = new Set(liveChildren.flatMap((child) => [child.story_id, ...(child.stories ?? []).map((story) => story.story_id)]));
549
+ const readyStory = stories.find((story) => story.status === "todo" && !story.passes && !assigned.has(story.id));
550
+ if (readyStory && liveCount < (lead.hire_grant ?? 0)) {
551
+ const fingerprint = `fill:${readyStory.id}:${liveCount}:${lead.hire_grant ?? 0}`;
552
+ wakes.push({
553
+ condition: "fill_grant",
554
+ lead_lane: lead.lane_id,
555
+ story_id: readyStory.id,
556
+ fingerprint,
557
+ prompt: `Start a worker for ready story ${readyStory.id}. You have ${liveCount} live workers against a grant of ${lead.hire_grant ?? 0}. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.`,
558
+ });
559
+ }
560
+ const hasFreeSlots = liveCount < (lead.hire_grant ?? 0);
561
+ if (hasFreeSlots && !readyStory) {
562
+ const latest = reports.at(-1);
563
+ const previous = reports.at(-2);
564
+ const kpiLine = latest ? leastMoved(latest.kpis, previous?.kpis) : undefined;
565
+ const okrLine = latest ? leastMoved(latest.okrs, previous?.okrs) : undefined;
566
+ const kpiText = kpiLine?.line ?? "no KPI line in the latest OKR report";
567
+ const okrText = okrLine?.line ?? "no OKR line in the latest OKR report";
568
+ const fingerprint = `plan:${latest?.at ?? "no-report"}:${kpiLine?.id ?? "no-kpi"}:${okrLine?.id ?? "no-okr"}:${stories.map((story) => `${story.id}:${story.status}`).sort().join(",")}`;
569
+ wakes.push({ condition: "plan_free_slots", lead_lane: lead.lane_id, story_id: "planning", fingerprint,
570
+ prompt: `You have ${liveCount} live workers against a grant of ${lead.hire_grant ?? 0} and no ready stories. Plan work against the least-moved KPI line: ${kpiText}; and OKR line: ${okrText}. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.` });
571
+ }
572
+ if (reports.length >= 2) {
573
+ const latest = reports.at(-1);
574
+ const prior = new Map(reports.at(-2).kpis.filter((line) => line.value !== undefined).map((line) => [line.id, line]));
575
+ const flat = latest.kpis.filter((line) => line.value !== undefined && prior.get(line.id)?.value === line.value);
576
+ if (flat.length > 0) {
577
+ const line = flat.map((item) => `${item.line} (${item.value})`).join("; ");
578
+ const fingerprint = `flat-kpi:${latest.at}:${flat.map((item) => `${item.id}:${item.value}`).join(",")}`;
579
+ wakes.push({ condition: "flat_kpi", lead_lane: lead.lane_id, story_id: flat.map((item) => item.id).join(","), fingerprint,
580
+ prompt: `KPI line(s) remained flat across the two latest OKR reports: ${line}. Re-plan the affected line(s). Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.` });
581
+ }
582
+ }
583
+ const staleBlockers = blockers.filter((blocker) => {
584
+ const blockerStatus = blocker.status ?? blocker.state;
585
+ const resolved = blockerStatus === "resolved" || blocker.resolved_at !== undefined && blocker.resolved_at !== null;
586
+ const owner = typeof blocker.unblock_owner === "string" ? blocker.unblock_owner : blocker.owner;
587
+ const due = blocker.unblock_by ?? blocker.unblock_at ?? blocker.due_at;
588
+ const ownerMissing = typeof owner !== "string" || !owner.trim();
589
+ const dueMissing = typeof due !== "string" || !Number.isFinite(Date.parse(due));
590
+ return resolved || ownerMissing || dueMissing;
591
+ });
592
+ if (staleBlockers.length > 0) {
593
+ const labels = staleBlockers.map((blocker) => `${String(blocker.id)}${typeof blocker.what === "string" ? ` (${blocker.what})` : ""}`).join("; ");
594
+ const fingerprint = `blockers:${staleBlockers.map((blocker) => `${String(blocker.id)}:${String(blocker.status ?? blocker.state ?? "")}:${String(blocker.resolved_at ?? "")}:${String(blocker.unblock_owner ?? blocker.owner ?? "")}:${String(blocker.unblock_by ?? blocker.unblock_at ?? blocker.due_at ?? "")}`).join(",")}`;
595
+ wakes.push({ condition: "blocker_record_needs_update", lead_lane: lead.lane_id, story_id: staleBlockers.map((blocker) => String(blocker.id)).join(","), fingerprint,
596
+ prompt: `Fix blocker records still listed as resolved or missing an unblock owner/time: ${labels}. Move resolved blockers out of blockers, and give every open blocker an owner and time. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.` });
597
+ }
598
+ if (stories.length > 0 && stories.every((story) => story.passes === true || story.status === "done" || story.status === "dropped" ||
599
+ ((story.status === "parked" || story.status === "blocked") && Boolean(story.externalBlocker)))) {
600
+ const fingerprint = `project-close:${stories.map((story) => `${story.id}:${story.status}:${story.externalBlocker ?? ""}`).sort().join(",")}`;
601
+ wakes.push({ condition: "project_ready_to_close", lead_lane: lead.lane_id, story_id: stories.map((story) => story.id).join(","), fingerprint,
602
+ prompt: `Every story is done, dropped, or parked on a named external blocker. Write the final report and mark the project complete. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.` });
603
+ }
604
+ const staleLedger = stories.flatMap((story) => {
605
+ if (story.status !== "in_progress" || !story.updatedAt || !story.laneIds)
606
+ return [];
607
+ const updated = Date.parse(story.updatedAt);
608
+ if (!Number.isFinite(updated) || now.getTime() - updated <= 30 * 60_000)
609
+ return [];
610
+ return story.laneIds.flatMap((laneId) => {
611
+ const worker = children.find((child) => child.lane_id === laneId && child.state === "running" &&
612
+ (child.story_id === story.id || (child.stories ?? []).some((carried) => carried.story_id === story.id)));
613
+ return worker ? [{ story, worker }] : [];
614
+ });
615
+ }).sort((a, b) => a.story.id.localeCompare(b.story.id) || a.worker.lane_id.localeCompare(b.worker.lane_id));
616
+ if (staleLedger.length > 0) {
617
+ const labels = staleLedger.map(({ story, worker }) => `${story.id} (lane ${worker.lane_id}, ledger updated ${story.updatedAt})`).join("; ");
618
+ const fingerprint = `stale-ledger:${staleLedger.map(({ story, worker }) => `${story.id}:${worker.lane_id}:${story.updatedAt}`).join(",")}`;
619
+ wakes.push({ condition: "stale_worker_ledger", lead_lane: lead.lane_id, story_id: staleLedger.map(({ story }) => story.id).join(","), worker_lane: staleLedger.length === 1 ? staleLedger[0].worker.lane_id : undefined, fingerprint,
620
+ prompt: `A running worker has made no ledger update in over 30 minutes: ${labels}. Check the worker and update the story ledger. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.` });
621
+ }
622
+ const withoutLiveLane = stories.flatMap((story) => {
623
+ if (story.status !== "in_progress")
624
+ return [];
625
+ const laneIds = story.laneIds ?? [];
626
+ // A story assigned to the lead itself is worked by the lead, which is the lane being woken.
627
+ if (laneIds.includes(lead.lane_id))
628
+ return [];
629
+ const live = laneIds.filter((laneId) => children.some((child) => child.lane_id === laneId && LIVE_STATES.has(child.state)));
630
+ if (live.length > 0)
631
+ return [];
632
+ const detail = laneIds.length === 0 ? "empty lane assignment" : `no live lane among ${laneIds.join(", ")}`;
633
+ return [{ story, laneIds, detail }];
634
+ }).sort((a, b) => a.story.id.localeCompare(b.story.id));
635
+ if (withoutLiveLane.length > 0) {
636
+ const labels = withoutLiveLane.map(({ story, detail }) => `${story.id} (${detail})`).join("; ");
637
+ const fingerprint = `missing-worker:${withoutLiveLane.map(({ story, detail }) => `${story.id}:${story.updatedAt ?? ""}:${detail}`).join(",")}`;
638
+ wakes.push({ condition: "story_without_live_lane", lead_lane: lead.lane_id, story_id: withoutLiveLane.map(({ story }) => story.id).join(","), fingerprint,
639
+ prompt: `In-progress story has no live worker lane: ${labels}. Relaunch a worker or set the story to waiting/blocked with its wake. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.` });
640
+ }
641
+ return wakes;
642
+ }
643
+ function readState(file) {
644
+ if (!fs.existsSync(file))
645
+ return { schema_version: "hq-lanes-autopilot-state.v1", sent: {}, deadline_misses: {} };
646
+ const value = readJsonFile(file, "lead_autopilot_state_invalid");
647
+ if (!isRecord(value) || value.schema_version !== "hq-lanes-autopilot-state.v1" || !isRecord(value.sent) ||
648
+ (value.delivered_ids !== undefined && !isRecord(value.delivered_ids)) ||
649
+ (value.deadline_misses !== undefined && !isRecord(value.deadline_misses)) ||
650
+ (value.per_lead_error_notices !== undefined && (!isRecord(value.per_lead_error_notices) || Object.values(value.per_lead_error_notices).some((id) => typeof id !== "string")))) {
651
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid autopilot state ${file}`, { path: file });
652
+ }
653
+ for (const [key, row] of Object.entries(value.sent)) {
654
+ if (!isRecord(row) || typeof row.fingerprint !== "string" || typeof row.at !== "string" ||
655
+ (row.status_updated_at !== undefined && typeof row.status_updated_at !== "string") ||
656
+ (row.acted !== undefined && typeof row.acted !== "boolean") ||
657
+ (row.auto_started !== undefined && typeof row.auto_started !== "boolean") ||
658
+ (row.worker_lane !== undefined && typeof row.worker_lane !== "string") ||
659
+ (row.wake_count !== undefined && (!Number.isSafeInteger(row.wake_count) || row.wake_count < 1)) ||
660
+ (row.last_wake_at !== undefined && typeof row.last_wake_at !== "string") ||
661
+ (row.escalated_at !== undefined && typeof row.escalated_at !== "string") ||
662
+ (row.inactive_since !== undefined && (typeof row.inactive_since !== "string" || !Number.isFinite(Date.parse(row.inactive_since))))) {
663
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid autopilot state entry ${key}`, { path: file, key });
664
+ }
665
+ }
666
+ for (const [key, row] of Object.entries(value.deadline_misses ?? {})) {
667
+ if (!isRecord(row) || typeof row.item !== "string" || typeof row.owner !== "string" ||
668
+ typeof row.due_at !== "string" || !Number.isFinite(Date.parse(row.due_at)) ||
669
+ !Number.isSafeInteger(row.miss_count) || row.miss_count < 1 ||
670
+ typeof row.first_missed_at !== "string" || !Number.isFinite(Date.parse(row.first_missed_at)) ||
671
+ typeof row.currently_missed !== "boolean" ||
672
+ (row.escalated_at !== undefined && (typeof row.escalated_at !== "string" || !Number.isFinite(Date.parse(row.escalated_at))))) {
673
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid missed-deadline state entry ${key}`, { path: file, key });
674
+ }
675
+ }
676
+ for (const [messageId, deliveredAt] of Object.entries(value.delivered_ids ?? {})) {
677
+ if (!messageId.trim() || typeof deliveredAt !== "string" || !Number.isFinite(Date.parse(deliveredAt))) {
678
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid delivered message id ${messageId}`, { path: file, message_id: messageId });
679
+ }
680
+ }
681
+ return {
682
+ ...value,
683
+ per_lead_error_notices: (value.per_lead_error_notices ?? {}),
684
+ };
685
+ }
686
+ function appendAutopilotMessage(input) {
687
+ if (input.dedupeEnabled && input.state.delivered_ids?.[input.message.message_id])
688
+ return false;
689
+ appendDropboxMessage(input.hqRoot, input.leadLane, input.message);
690
+ if (input.dedupeEnabled) {
691
+ input.state.delivered_ids ??= {};
692
+ input.state.delivered_ids[input.message.message_id] = input.message.at;
693
+ }
694
+ return true;
695
+ }
696
+ function removeDeliveredIdsForFingerprint(state, fingerprint) {
697
+ const prefix = `lead-autopilot:${fingerprint}`;
698
+ let removed = false;
699
+ for (const messageId of Object.keys(state.delivered_ids ?? {})) {
700
+ if (messageId.startsWith(prefix)) {
701
+ delete state.delivered_ids[messageId];
702
+ removed = true;
703
+ }
704
+ }
705
+ return removed;
706
+ }
707
+ function pruneDeliveredIds(state, now) {
708
+ let pruned = false;
709
+ for (const [messageId, deliveredAt] of Object.entries(state.delivered_ids ?? {})) {
710
+ if (now.getTime() - Date.parse(deliveredAt) > LEAD_AUTOPILOT_DELIVERED_ID_RETENTION_MS) {
711
+ delete state.delivered_ids[messageId];
712
+ pruned = true;
713
+ }
714
+ }
715
+ return pruned;
716
+ }
717
+ function writeState(file, state) {
718
+ fs.mkdirSync(path.dirname(file), { recursive: true });
719
+ const temp = `${file}.${process.pid}.tmp`;
720
+ fs.writeFileSync(temp, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
721
+ fs.renameSync(temp, file);
722
+ }
723
+ function recordOperatorEscalation(hqRoot, record) {
724
+ const file = path.join(hqRoot, "workspace", "lane-briefs", "ops-board-state.json");
725
+ let state = {};
726
+ if (fs.existsSync(file)) {
727
+ const value = readJsonFile(file, "lead_autopilot_escalation_record_invalid");
728
+ if (!isRecord(value))
729
+ throw new LanesError("lead_autopilot_escalation_record_invalid", `Invalid operator board state ${file}`);
730
+ state = value;
731
+ }
732
+ const current = state.autopilot_escalations;
733
+ if (current !== undefined && (!Array.isArray(current) || current.some((item) => !isRecord(item)))) {
734
+ throw new LanesError("lead_autopilot_escalation_record_invalid", `Invalid autopilot escalations in ${file}`);
735
+ }
736
+ const rows = (current ?? []);
737
+ if (rows.some((item) => item.lead_lane === record.lead_lane && item.fingerprint === record.fingerprint))
738
+ return;
739
+ const next = { ...state, autopilot_escalations: [...rows, record] };
740
+ fs.mkdirSync(path.dirname(file), { recursive: true });
741
+ const temp = `${file}.${process.pid}.tmp`;
742
+ fs.writeFileSync(temp, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600 });
743
+ fs.renameSync(temp, file);
744
+ }
745
+ async function runLeadAutopilotPassUnlocked(input) {
746
+ const { hqRoot, host, now } = input;
747
+ const effectiveOutpostId = input.outpostId !== null && isControllerAliasOutpostId(input.outpostId, { kind: "outpost", id: input.outpostId }) ? null : input.outpostId;
748
+ const result = { ok: true, host, evaluated: 0, sent: [], started: [], escalated: [], skipped: [] };
749
+ const registered = parseRegistry(hqRoot, input.outpostId, now);
750
+ if (registered === null)
751
+ result.registry = "missing";
752
+ const leads = registered ?? [];
753
+ const lanes = readAllLanes(hqRoot);
754
+ const byId = new Map(lanes.map((lane) => [lane.lane_id, lane]));
755
+ const stateFile = path.join(hqRoot, "workspace", "lane-briefs", "autopilot-state.json");
756
+ const state = readState(stateFile);
757
+ for (const registered of leads) {
758
+ const lead = byId.get(registered.lane) ?? lanes.find((candidate) => candidate.lane_id.startsWith(`${registered.lane}_`));
759
+ if (!lead) {
760
+ result.skipped.push({ lead_lane: registered.lane, reason: "lead_lane_missing" });
761
+ continue;
762
+ }
763
+ const company = resolveLaneCompany(hqRoot, lead).company;
764
+ if (!company) {
765
+ result.skipped.push({ lead_lane: lead.lane_id, reason: "lead_company_unresolved" });
766
+ continue;
767
+ }
768
+ const registeredLocalHost = registered.host === "local" || registered.host === input.hostname;
769
+ const hostMatchesRegistry = registeredLocalHost
770
+ ? lead.host.kind === "local"
771
+ : lead.host.kind === "outpost" && lead.host.id === registered.host && input.outpostId === registered.host;
772
+ if (!hostMatchesRegistry ||
773
+ !laneRunsOnHost(lead, { hostname: input.hostname, outpostId: effectiveOutpostId })) {
774
+ result.skipped.push({ lead_lane: lead.lane_id, reason: "lead_host_mismatch" });
775
+ continue;
776
+ }
777
+ let stateChanged = false;
778
+ let perLeadErrorsEnabled = false;
779
+ let currentInputPath = registered.status;
780
+ try {
781
+ const readFlag = input.readFlag ?? readLanesRegistryFlag;
782
+ const enabled = await readFlag(LEAD_AUTOPILOT_FLAG, { company });
783
+ if (!enabled) {
784
+ result.skipped.push({ lead_lane: lead.lane_id, reason: "flag_off" });
785
+ continue;
786
+ }
787
+ perLeadErrorsEnabled = await readFlag(PER_LEAD_ERRORS_FLAG, { company });
788
+ currentInputPath = registered.status;
789
+ const status = readStatus(hqRoot, registered.status, company.slug);
790
+ const kpiStalenessEnabled = await (input.readFlag ?? readLanesRegistryFlag)(LEAD_AUTOPILOT_KPI_STALENESS_FLAG, { company });
791
+ const kpiStalenessBatchEnabled = kpiStalenessEnabled && await (input.readFlag ?? readLanesRegistryFlag)(LEAD_AUTOPILOT_KPI_STALENESS_BATCH_FLAG, { company });
792
+ const headlineStalenessEnabled = await (input.readFlag ?? readLanesRegistryFlag)(LEAD_AUTOPILOT_HEADLINE_STALENESS_FLAG, { company });
793
+ if (kpiStalenessEnabled) {
794
+ result.kpi_status ??= [];
795
+ result.kpi_status.push(...managerKpiFreshness(status, now).map((kpi) => ({
796
+ lead_lane: lead.lane_id,
797
+ team: registered.team,
798
+ kpi: kpi.name,
799
+ age_minutes: kpi.ageMinutes,
800
+ stale: kpi.stale,
801
+ stale_after_minutes: kpi.staleAfterMinutes,
802
+ ...(kpi.status === undefined ? {} : { status: kpi.status }),
803
+ ...(kpi.error === undefined ? {} : { error: kpi.error }),
804
+ })));
805
+ }
806
+ const statusUpdatedAt = typeof status.updated_at === "string" && Number.isFinite(Date.parse(status.updated_at))
807
+ ? new Date(Date.parse(status.updated_at)).toISOString()
808
+ : undefined;
809
+ currentInputPath = registered.prd;
810
+ const stories = projectStories(hqRoot, registered.prd, company.slug, lead.project_id);
811
+ const children = lanes.filter((lane) => lane.senior.kind === "lane" && lane.senior.id === lead.lane_id);
812
+ const deadlineEscalationEnabled = await (input.readDeadlineFlag ?? readFlag)(LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_FLAG, { company });
813
+ const nudgeDedupeEnabled = await (input.readNudgeDedupeFlag ?? readFlag)(LEAD_AUTOPILOT_NUDGE_DEDUPE_FLAG, { company });
814
+ if (nudgeDedupeEnabled && pruneDeliveredIds(state, now))
815
+ stateChanged = true;
816
+ currentInputPath = registered.status;
817
+ let planned = planLeadAutopilotWakes({
818
+ lead,
819
+ children,
820
+ stories,
821
+ now,
822
+ managerStatus: status,
823
+ kpiStalenessEnabled,
824
+ kpiStalenessBatchEnabled,
825
+ headlineStalenessEnabled,
826
+ keepAliveResumed: input.keepAliveResumedLeads?.has(lead.lane_id) === true,
827
+ });
828
+ if (kpiStalenessBatchEnabled) {
829
+ const batch = planned.find((wake) => wake.condition === "stale_kpi" && wake.kpi_id === "batch");
830
+ const headline = planned.find((wake) => wake.condition === "stale_headline");
831
+ if (batch && headline) {
832
+ const priorHeadline = state.sent[`${lead.lane_id}:stale_headline`];
833
+ if (priorHeadline?.fingerprint !== headline.fingerprint) {
834
+ batch.prompt += `\n\n${headline.prompt}`;
835
+ batch.headline_fingerprint = headline.fingerprint;
836
+ }
837
+ planned = planned.filter((wake) => wake !== headline);
838
+ }
839
+ }
840
+ const stateKey = (wake) => `${lead.lane_id}:${wake.condition}${wake.condition === "stale_kpi" ? `:${wake.kpi_id}` : ""}`;
841
+ const activeKeys = new Set(planned.flatMap((wake) => [
842
+ stateKey(wake),
843
+ ...(wake.headline_fingerprint ? [`${lead.lane_id}:stale_headline`] : []),
844
+ ]));
845
+ const suppressedKeys = new Set();
846
+ for (const key of Object.keys(state.sent)) {
847
+ if (!key.startsWith(`${lead.lane_id}:`))
848
+ continue;
849
+ const entry = state.sent[key];
850
+ const isActive = activeKeys.has(key);
851
+ if (!nudgeDedupeEnabled) {
852
+ if (!isActive) {
853
+ delete state.sent[key];
854
+ stateChanged = true;
855
+ }
856
+ continue;
857
+ }
858
+ if (!isActive && entry.inactive_since === undefined) {
859
+ state.sent[key] = { ...entry, inactive_since: now.toISOString() };
860
+ stateChanged = true;
861
+ continue;
862
+ }
863
+ if (isActive && entry.inactive_since !== undefined) {
864
+ const inactiveAt = Date.parse(entry.inactive_since);
865
+ if (now.getTime() - inactiveAt < LEAD_AUTOPILOT_NUDGE_STATE_RETENTION_MS) {
866
+ suppressedKeys.add(key);
867
+ }
868
+ else {
869
+ delete state.sent[key];
870
+ if (removeDeliveredIdsForFingerprint(state, entry.fingerprint))
871
+ stateChanged = true;
872
+ stateChanged = true;
873
+ }
874
+ }
875
+ else if (!isActive) {
876
+ const inactiveSince = entry.inactive_since ?? now.toISOString();
877
+ if (now.getTime() - Date.parse(inactiveSince) >= LEAD_AUTOPILOT_NUDGE_STATE_RETENTION_MS) {
878
+ delete state.sent[key];
879
+ if (removeDeliveredIdsForFingerprint(state, entry.fingerprint))
880
+ stateChanged = true;
881
+ stateChanged = true;
882
+ }
883
+ else if (entry.inactive_since === undefined) {
884
+ state.sent[key] = { ...entry, inactive_since: inactiveSince };
885
+ stateChanged = true;
886
+ }
887
+ }
888
+ }
889
+ for (const wake of planned) {
890
+ const key = stateKey(wake);
891
+ if (suppressedKeys.has(key))
892
+ continue;
893
+ const prior = state.sent[key];
894
+ if (nudgeDedupeEnabled && prior && prior.fingerprint !== wake.fingerprint && !prior.acted) {
895
+ const leadActedSincePrior = statusUpdatedAt !== undefined && prior.status_updated_at !== undefined &&
896
+ Date.parse(statusUpdatedAt) > Date.parse(prior.status_updated_at);
897
+ if (!leadActedSincePrior) {
898
+ const lastWakeAt = Date.parse(prior.last_wake_at ?? prior.at);
899
+ if (!Number.isFinite(lastWakeAt)) {
900
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid wake time for ${lead.lane_id}`, { lead_lane: lead.lane_id, story_id: wake.story_id });
901
+ }
902
+ if (now.getTime() - lastWakeAt < LEAD_AUTOPILOT_NUDGE_REDELIVERY_DELAY_MS)
903
+ continue;
904
+ }
905
+ }
906
+ if (prior?.fingerprint === wake.fingerprint) {
907
+ if (input.dryRun)
908
+ continue;
909
+ let current = prior;
910
+ const lastWakeAt = Date.parse(prior.last_wake_at ?? prior.at);
911
+ if (!Number.isFinite(lastWakeAt)) {
912
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid wake time for ${lead.lane_id}`, { lead_lane: lead.lane_id, story_id: wake.story_id });
913
+ }
914
+ if (statusUpdatedAt === undefined || prior.status_updated_at === undefined) {
915
+ throw new LanesError("lead_autopilot_status_activity_unverifiable", `Cannot verify whether lead ${lead.lane_id} acted after its autopilot wake`, { lead_lane: lead.lane_id, story_id: wake.story_id });
916
+ }
917
+ if (!prior.acted && Date.parse(statusUpdatedAt) > Date.parse(prior.status_updated_at)) {
918
+ current = { ...prior, acted: true };
919
+ state.sent[key] = current;
920
+ stateChanged = true;
921
+ }
922
+ if (wake.condition === "fill_grant" && input.startWorker && !current.acted && !current.auto_started) {
923
+ const firstWakeAt = Date.parse(current.at);
924
+ if (!Number.isFinite(firstWakeAt)) {
925
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid fill-grant wake time for ${lead.lane_id}`, { lead_lane: lead.lane_id, story_id: wake.story_id });
926
+ }
927
+ if (now.getTime() - firstWakeAt >= LEAD_AUTOPILOT_FILL_DELAY_MS) {
928
+ const story = stories.find((candidate) => candidate.id === wake.story_id && candidate.status === "todo");
929
+ if (!story?.briefPath) {
930
+ throw new LanesError("lead_autopilot_story_brief_missing", `Cannot auto-start story ${wake.story_id}: its project record has no valid brief path`, { lead_lane: lead.lane_id, story_id: wake.story_id, project_id: lead.project_id });
931
+ }
932
+ if (lead.state !== "running" && lead.state !== "queued") {
933
+ current = { ...current, acted: true };
934
+ state.sent[key] = current;
935
+ stateChanged = true;
936
+ result.skipped.push({ lead_lane: lead.lane_id, reason: "auto_start_lead_not_active" });
937
+ }
938
+ else {
939
+ const started = await input.startWorker({ lead, story });
940
+ current = { ...current, auto_started: true, worker_lane: started.lane_id };
941
+ state.sent[key] = current;
942
+ stateChanged = true;
943
+ result.started.push({ lead_lane: lead.lane_id, story_id: story.id, worker_lane: started.lane_id });
944
+ }
945
+ }
946
+ }
947
+ // Stale KPIs get one notice per measurement fingerprint, not the
948
+ // repeated wake/escalation cadence used by other conditions.
949
+ if (wake.condition === "stale_kpi")
950
+ continue;
951
+ if (wake.condition === "stale_headline")
952
+ continue;
953
+ const redeliveryDelay = nudgeDedupeEnabled ? LEAD_AUTOPILOT_NUDGE_REDELIVERY_DELAY_MS : LEAD_AUTOPILOT_FILL_DELAY_MS;
954
+ if (!current.acted && !current.auto_started && current.escalated_at === undefined && now.getTime() - lastWakeAt >= redeliveryDelay) {
955
+ const wakeCount = current.wake_count ?? 1;
956
+ if (wakeCount < 2) {
957
+ const delivered = appendAutopilotMessage({ hqRoot, leadLane: lead.lane_id, state, dedupeEnabled: nudgeDedupeEnabled, message: {
958
+ at: now.toISOString(),
959
+ message_id: `lead-autopilot:${wake.fingerprint}:wake-2`,
960
+ kind: "system_notice",
961
+ text: wake.prompt,
962
+ } });
963
+ current = { ...current, wake_count: 2, last_wake_at: now.toISOString() };
964
+ state.sent[key] = current;
965
+ stateChanged = true;
966
+ if (delivered)
967
+ result.sent.push(wake);
968
+ }
969
+ else {
970
+ const escalation = { team: registered.team, lead_lane: lead.lane_id, condition: wake.condition, story_id: wake.story_id, at: now.toISOString(), fingerprint: wake.fingerprint };
971
+ recordOperatorEscalation(hqRoot, escalation);
972
+ current = { ...current, escalated_at: now.toISOString() };
973
+ state.sent[key] = current;
974
+ stateChanged = true;
975
+ result.escalated.push(escalation);
976
+ }
977
+ }
978
+ continue;
979
+ }
980
+ if (!input.dryRun) {
981
+ const delivered = appendAutopilotMessage({ hqRoot, leadLane: lead.lane_id, state, dedupeEnabled: nudgeDedupeEnabled, message: {
982
+ at: now.toISOString(),
983
+ message_id: `lead-autopilot:${wake.fingerprint}`,
984
+ kind: "system_notice",
985
+ text: wake.prompt,
986
+ } });
987
+ state.sent[key] = {
988
+ fingerprint: wake.fingerprint,
989
+ at: now.toISOString(),
990
+ ...(statusUpdatedAt ? { status_updated_at: statusUpdatedAt } : {}),
991
+ wake_count: 1,
992
+ last_wake_at: now.toISOString(),
993
+ };
994
+ if (wake.headline_fingerprint) {
995
+ state.sent[`${lead.lane_id}:stale_headline`] = {
996
+ fingerprint: wake.headline_fingerprint,
997
+ at: now.toISOString(),
998
+ ...(statusUpdatedAt ? { status_updated_at: statusUpdatedAt } : {}),
999
+ wake_count: 1,
1000
+ last_wake_at: now.toISOString(),
1001
+ };
1002
+ }
1003
+ stateChanged = true;
1004
+ if (!delivered)
1005
+ continue;
1006
+ }
1007
+ result.sent.push(wake);
1008
+ }
1009
+ // Planned wakes have already been delivered. Persist their dedupe state
1010
+ // before deadline parsing/recording so an unexpected deadline failure
1011
+ // cannot make those wakes repeat on the next pass.
1012
+ if (!input.dryRun && stateChanged) {
1013
+ writeState(stateFile, state);
1014
+ stateChanged = false;
1015
+ }
1016
+ if (deadlineEscalationEnabled) {
1017
+ result.missed_deadlines ??= [];
1018
+ const parsedCommitments = deadlineCommitments(status, stories, lead.lane_id);
1019
+ if (parsedCommitments.errors.length > 0) {
1020
+ result.deadline_errors ??= [];
1021
+ result.deadline_errors.push(...parsedCommitments.errors);
1022
+ }
1023
+ const commitments = parsedCommitments.commitments;
1024
+ const currentCommitmentKeys = new Set(commitments.map((item) => `${lead.lane_id}:${item.key}`));
1025
+ const deadlineState = state.deadline_misses ?? (state.deadline_misses = {});
1026
+ for (const key of Object.keys(deadlineState)) {
1027
+ if (key.startsWith(`${lead.lane_id}:`) && !currentCommitmentKeys.has(key)) {
1028
+ delete deadlineState[key];
1029
+ stateChanged = true;
1030
+ }
1031
+ }
1032
+ const escalationDelay = input.missedDeadlineEscalationDelayMs ?? LEAD_AUTOPILOT_MISSED_DEADLINE_ESCALATION_DELAY_MS;
1033
+ if (!Number.isFinite(escalationDelay) || escalationDelay < 0) {
1034
+ throw new LanesError("lead_autopilot_deadline_config_invalid", "Missed-deadline escalation delay must be a non-negative number");
1035
+ }
1036
+ for (const commitment of commitments) {
1037
+ const key = `${lead.lane_id}:${commitment.key}`;
1038
+ const prior = deadlineState[key];
1039
+ if (commitment.resolved) {
1040
+ if (prior) {
1041
+ delete deadlineState[key];
1042
+ stateChanged = true;
1043
+ }
1044
+ continue;
1045
+ }
1046
+ const isMissed = now.getTime() > Date.parse(commitment.due);
1047
+ if (!isMissed) {
1048
+ if (prior && (prior.due_at !== commitment.due || prior.owner !== commitment.owner || prior.currently_missed)) {
1049
+ deadlineState[key] = { ...prior, due_at: commitment.due, owner: commitment.owner, currently_missed: false };
1050
+ stateChanged = true;
1051
+ }
1052
+ continue;
1053
+ }
1054
+ if (!prior || prior.miss_count === 0) {
1055
+ const firstMiss = {
1056
+ item: commitment.item,
1057
+ owner: commitment.owner,
1058
+ due_at: commitment.due,
1059
+ miss_count: 1,
1060
+ first_missed_at: now.toISOString(),
1061
+ currently_missed: true,
1062
+ };
1063
+ if (!input.dryRun) {
1064
+ const fingerprint = `missed-deadline:${commitment.key}:${commitment.owner}:${commitment.due}`;
1065
+ const wake = {
1066
+ condition: "missed_deadline",
1067
+ lead_lane: lead.lane_id,
1068
+ story_id: commitment.item,
1069
+ fingerprint,
1070
+ prompt: `Deadline missed for ${commitment.item} (${commitment.description}), owner ${commitment.owner}, due ${commitment.due}. Deliver it or re-date with a reason. Follow ${LEAD_AUTOPILOT_PROMPT_LOOP}.`,
1071
+ };
1072
+ const delivered = appendAutopilotMessage({ hqRoot, leadLane: lead.lane_id, state, dedupeEnabled: nudgeDedupeEnabled, message: {
1073
+ at: now.toISOString(),
1074
+ message_id: `lead-autopilot:${fingerprint}`,
1075
+ kind: "system_notice",
1076
+ text: wake.prompt,
1077
+ } });
1078
+ stateChanged = true;
1079
+ if (delivered)
1080
+ result.sent.push(wake);
1081
+ deadlineState[key] = firstMiss;
1082
+ }
1083
+ else {
1084
+ deadlineState[key] = firstMiss;
1085
+ }
1086
+ }
1087
+ else {
1088
+ const dueChanged = prior.due_at !== commitment.due || prior.owner !== commitment.owner;
1089
+ const reMissed = !prior.currently_missed;
1090
+ const firstMissAt = Date.parse(prior.first_missed_at);
1091
+ if (!Number.isFinite(firstMissAt)) {
1092
+ throw new LanesError("lead_autopilot_state_invalid", `Invalid first missed-deadline time for ${commitment.item}`, { lead_lane: lead.lane_id, item: commitment.item });
1093
+ }
1094
+ const stillLateAgain = now.getTime() - firstMissAt >= escalationDelay;
1095
+ const secondMiss = !prior.escalated_at && (dueChanged || reMissed || stillLateAgain);
1096
+ const next = {
1097
+ ...prior,
1098
+ item: commitment.item,
1099
+ owner: commitment.owner,
1100
+ due_at: commitment.due,
1101
+ miss_count: secondMiss ? prior.miss_count + 1 : prior.miss_count,
1102
+ currently_missed: true,
1103
+ ...(secondMiss ? { escalated_at: now.toISOString() } : {}),
1104
+ };
1105
+ if (secondMiss) {
1106
+ const fingerprint = `missed-deadline:${commitment.key}:${commitment.owner}:${commitment.due}:miss-${next.miss_count}`;
1107
+ const escalation = {
1108
+ team: registered.team,
1109
+ lead_lane: lead.lane_id,
1110
+ condition: "missed_deadline",
1111
+ story_id: commitment.item,
1112
+ at: now.toISOString(),
1113
+ fingerprint,
1114
+ owner: commitment.owner,
1115
+ due: commitment.due,
1116
+ miss_count: next.miss_count,
1117
+ };
1118
+ if (!input.dryRun)
1119
+ recordOperatorEscalation(hqRoot, escalation);
1120
+ if (!input.dryRun)
1121
+ stateChanged = true;
1122
+ result.escalated.push(escalation);
1123
+ }
1124
+ if (!input.dryRun && JSON.stringify(prior) !== JSON.stringify(next))
1125
+ stateChanged = true;
1126
+ deadlineState[key] = next;
1127
+ }
1128
+ const current = deadlineState[key] ?? prior;
1129
+ result.missed_deadlines.push({ lead_lane: lead.lane_id, item: commitment.item, owner: commitment.owner, due: commitment.due, miss_count: current?.miss_count ?? 1 });
1130
+ }
1131
+ }
1132
+ if (!input.dryRun && stateChanged)
1133
+ writeState(stateFile, state);
1134
+ result.evaluated += 1;
1135
+ }
1136
+ catch (error) {
1137
+ if (!input.dryRun && stateChanged)
1138
+ writeState(stateFile, state);
1139
+ if (perLeadErrorsEnabled && error instanceof LanesError && LEAD_AUTOPILOT_PER_LEAD_ERROR_CODES.has(error.error)) {
1140
+ const errorPath = typeof error.details.path === "string" ? error.details.path : currentInputPath;
1141
+ const messageId = `lead-autopilot-error:${error.error}:${createHash("sha256").update(`${error.error}\0${errorPath}`).digest("hex")}`;
1142
+ result.skipped.push({ lane_id: lead.lane_id, error: error.error, path: errorPath, message: error.message });
1143
+ const noticeKey = `${lead.lane_id}:${error.error}:${errorPath}`;
1144
+ if (!input.dryRun && state.per_lead_error_notices?.[noticeKey] !== messageId) {
1145
+ appendDropboxMessage(hqRoot, lead.lane_id, {
1146
+ at: now.toISOString(),
1147
+ message_id: messageId,
1148
+ kind: "system_notice",
1149
+ text: `Lead autopilot skipped this lead because ${error.error}: ${error.message}. Fix the registry row for lane ${registered.lane} (team ${registered.team}) in ${LEAD_REGISTRY_REL} (registered path: ${errorPath}).`,
1150
+ });
1151
+ state.per_lead_error_notices ??= {};
1152
+ state.per_lead_error_notices[noticeKey] = messageId;
1153
+ writeState(stateFile, state);
1154
+ }
1155
+ continue;
1156
+ }
1157
+ if (!(error instanceof LanesError) || LEAD_AUTOPILOT_PASS_FATAL_ERRORS.has(error.error))
1158
+ throw error;
1159
+ result.skipped.push({ lead_lane: lead.lane_id, reason: error.error });
1160
+ }
1161
+ }
1162
+ return result;
1163
+ }
1164
+ // Tenant-boundary and path-safety failures stop the whole pass; other per-lead
1165
+ // data errors skip only that lead.
1166
+ const LEAD_AUTOPILOT_PASS_FATAL_ERRORS = new Set([
1167
+ "lead_autopilot_tenant_mismatch",
1168
+ "lead_autopilot_status_path_invalid",
1169
+ "lead_autopilot_escalation_record_invalid",
1170
+ ]);
1171
+ const LEAD_AUTOPILOT_PER_LEAD_ERROR_CODES = new Set([
1172
+ "lead_autopilot_tenant_mismatch",
1173
+ "lead_autopilot_project_path_invalid",
1174
+ "lead_autopilot_project_invalid",
1175
+ "lead_autopilot_story_brief_path_invalid",
1176
+ "lead_autopilot_story_brief_invalid",
1177
+ "lead_autopilot_status_path_invalid",
1178
+ "lead_autopilot_status_invalid",
1179
+ ]);
1180
+ const LEAD_AUTOPILOT_STALE_LOCK_MAX_AGE_MS = 60 * 60_000;
1181
+ function processStartIdentity(pid) {
1182
+ try {
1183
+ const stat = fs.readFileSync(`/proc/${pid}/stat`, "utf8");
1184
+ const fields = stat.slice(stat.lastIndexOf(")") + 2).trim().split(/\s+/);
1185
+ return fields[19] ?? null;
1186
+ }
1187
+ catch {
1188
+ return null;
1189
+ }
1190
+ }
1191
+ function reclaimStaleLock(lockPath) {
1192
+ let before;
1193
+ let text;
1194
+ let after;
1195
+ try {
1196
+ before = fs.lstatSync(lockPath);
1197
+ text = fs.readFileSync(lockPath, "utf8");
1198
+ after = fs.lstatSync(lockPath);
1199
+ }
1200
+ catch (error) {
1201
+ if (error.code === "ENOENT")
1202
+ return true;
1203
+ return false;
1204
+ }
1205
+ if (!before.isFile() || before.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino)
1206
+ return false;
1207
+ const [pidText, createdAt, recordedStartIdentity] = text.split("\n");
1208
+ const pid = Number(pidText);
1209
+ if (!Number.isSafeInteger(pid) || pid < 1)
1210
+ return false;
1211
+ let dead = false;
1212
+ try {
1213
+ process.kill(pid, 0);
1214
+ const currentStartIdentity = processStartIdentity(pid);
1215
+ if (recordedStartIdentity && currentStartIdentity) {
1216
+ if (recordedStartIdentity !== currentStartIdentity)
1217
+ dead = true;
1218
+ else
1219
+ return false;
1220
+ }
1221
+ else {
1222
+ const createdMs = Date.parse(createdAt ?? "");
1223
+ if (!Number.isFinite(createdMs) || Date.now() - createdMs < LEAD_AUTOPILOT_STALE_LOCK_MAX_AGE_MS)
1224
+ return false;
1225
+ dead = true;
1226
+ }
1227
+ }
1228
+ catch (error) {
1229
+ if (error.code !== "ESRCH")
1230
+ return false;
1231
+ dead = true;
1232
+ }
1233
+ if (!dead)
1234
+ return false;
1235
+ try {
1236
+ const current = fs.lstatSync(lockPath);
1237
+ if (current.dev !== before.dev || current.ino !== before.ino)
1238
+ return false;
1239
+ fs.unlinkSync(lockPath);
1240
+ return true;
1241
+ }
1242
+ catch (error) {
1243
+ if (error.code === "ENOENT")
1244
+ return true;
1245
+ return false;
1246
+ }
1247
+ }
1248
+ export async function runLeadAutopilotPass(input) {
1249
+ if (input.dryRun)
1250
+ return runLeadAutopilotPassUnlocked(input);
1251
+ const lockPath = path.join(input.hqRoot, "workspace", "lane-briefs", "autopilot.lock");
1252
+ fs.mkdirSync(path.dirname(lockPath), { recursive: true });
1253
+ let lockFd;
1254
+ for (let attempt = 0; attempt < 2; attempt += 1) {
1255
+ try {
1256
+ lockFd = fs.openSync(lockPath, "wx", 0o600);
1257
+ fs.writeFileSync(lockFd, `${process.pid}\n${input.now.toISOString()}\n${processStartIdentity(process.pid) ?? ""}\n`, "utf8");
1258
+ break;
1259
+ }
1260
+ catch (error) {
1261
+ if (error.code === "EEXIST" && attempt === 0 && reclaimStaleLock(lockPath))
1262
+ continue;
1263
+ if (error.code === "EEXIST") {
1264
+ throw new LanesError("lead_autopilot_lock_busy", `Another autopilot pass owns ${lockPath}`, { path: lockPath });
1265
+ }
1266
+ throw new LanesError("lead_autopilot_lock_failed", `Cannot lock autopilot state: ${error instanceof Error ? error.message : String(error)}`, { path: lockPath });
1267
+ }
1268
+ }
1269
+ if (lockFd === undefined)
1270
+ throw new LanesError("lead_autopilot_lock_busy", `Another autopilot pass owns ${lockPath}`, { path: lockPath });
1271
+ try {
1272
+ return await runLeadAutopilotPassUnlocked(input);
1273
+ }
1274
+ finally {
1275
+ try {
1276
+ fs.closeSync(lockFd);
1277
+ }
1278
+ catch (error) {
1279
+ process.stderr.write(`hq lanes autopilot: lock close failed: ${error instanceof Error ? error.message : String(error)}\n`);
1280
+ }
1281
+ try {
1282
+ fs.unlinkSync(lockPath);
1283
+ }
1284
+ catch (error) {
1285
+ if (error.code !== "ENOENT") {
1286
+ process.stderr.write(`hq lanes autopilot: lock removal failed: ${error instanceof Error ? error.message : String(error)}\n`);
1287
+ }
1288
+ }
1289
+ }
1290
+ }
1291
+ //# sourceMappingURL=autopilot.js.map