@openrig/cli 0.4.3 → 0.4.6

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 (634) hide show
  1. package/daemon/assets/guidance/openrig-start.md +6 -0
  2. package/daemon/assets/plugins/openrig-core/skills/mission-slice-sop/SKILL.md +47 -21
  3. package/daemon/assets/plugins/openrig-core/skills/openrig-cmux/SKILL.md +86 -0
  4. package/daemon/assets/plugins/openrig-core/skills/openrig-herdr/SKILL.md +158 -0
  5. package/daemon/assets/plugins/openrig-core/skills/openrig-user/SKILL.md +742 -94
  6. package/daemon/dist/adapters/codex-runtime-adapter.d.ts.map +1 -1
  7. package/daemon/dist/adapters/codex-runtime-adapter.js +12 -8
  8. package/daemon/dist/adapters/codex-runtime-adapter.js.map +1 -1
  9. package/daemon/dist/adapters/pi-resume.d.ts +32 -0
  10. package/daemon/dist/adapters/pi-resume.d.ts.map +1 -0
  11. package/daemon/dist/adapters/pi-resume.js +125 -0
  12. package/daemon/dist/adapters/pi-resume.js.map +1 -0
  13. package/daemon/dist/adapters/pi-runner-protocol.d.ts +88 -0
  14. package/daemon/dist/adapters/pi-runner-protocol.d.ts.map +1 -0
  15. package/daemon/dist/adapters/pi-runner-protocol.js +153 -0
  16. package/daemon/dist/adapters/pi-runner-protocol.js.map +1 -0
  17. package/daemon/dist/adapters/pi-runner.d.ts +99 -0
  18. package/daemon/dist/adapters/pi-runner.d.ts.map +1 -0
  19. package/daemon/dist/adapters/pi-runner.js +519 -0
  20. package/daemon/dist/adapters/pi-runner.js.map +1 -0
  21. package/daemon/dist/adapters/pi-runtime-adapter.d.ts +61 -0
  22. package/daemon/dist/adapters/pi-runtime-adapter.d.ts.map +1 -0
  23. package/daemon/dist/adapters/pi-runtime-adapter.js +356 -0
  24. package/daemon/dist/adapters/pi-runtime-adapter.js.map +1 -0
  25. package/daemon/dist/adapters/tmux.d.ts +22 -1
  26. package/daemon/dist/adapters/tmux.d.ts.map +1 -1
  27. package/daemon/dist/adapters/tmux.js +40 -1
  28. package/daemon/dist/adapters/tmux.js.map +1 -1
  29. package/daemon/dist/build-info.d.ts +12 -0
  30. package/daemon/dist/build-info.d.ts.map +1 -0
  31. package/daemon/dist/build-info.js +11 -0
  32. package/daemon/dist/build-info.js.map +1 -0
  33. package/daemon/dist/builtins/workflow-specs/branched-remediation.yaml +31 -0
  34. package/daemon/dist/builtins/workflow-specs/factory-rsi.yaml +152 -0
  35. package/daemon/dist/builtins/workflow-specs/gated-release.yaml +26 -0
  36. package/daemon/dist/builtins/workflow-specs/linear-build.yaml +21 -0
  37. package/daemon/dist/db/migrations/048_queue_item_evidence_ref.d.ts +18 -0
  38. package/daemon/dist/db/migrations/048_queue_item_evidence_ref.d.ts.map +1 -0
  39. package/daemon/dist/db/migrations/048_queue_item_evidence_ref.js +22 -0
  40. package/daemon/dist/db/migrations/048_queue_item_evidence_ref.js.map +1 -0
  41. package/daemon/dist/db/migrations/049_workflow_instance_version.d.ts +20 -0
  42. package/daemon/dist/db/migrations/049_workflow_instance_version.d.ts.map +1 -0
  43. package/daemon/dist/db/migrations/049_workflow_instance_version.js +24 -0
  44. package/daemon/dist/db/migrations/049_workflow_instance_version.js.map +1 -0
  45. package/daemon/dist/db/migrations/050_workflow_spec_json.d.ts +22 -0
  46. package/daemon/dist/db/migrations/050_workflow_spec_json.d.ts.map +1 -0
  47. package/daemon/dist/db/migrations/050_workflow_spec_json.js +26 -0
  48. package/daemon/dist/db/migrations/050_workflow_spec_json.js.map +1 -0
  49. package/daemon/dist/db/migrations/051_workflow_resume.d.ts +22 -0
  50. package/daemon/dist/db/migrations/051_workflow_resume.d.ts.map +1 -0
  51. package/daemon/dist/db/migrations/051_workflow_resume.js +27 -0
  52. package/daemon/dist/db/migrations/051_workflow_resume.js.map +1 -0
  53. package/daemon/dist/db/migrations/052_workflow_instance_bound_rig.d.ts +26 -0
  54. package/daemon/dist/db/migrations/052_workflow_instance_bound_rig.d.ts.map +1 -0
  55. package/daemon/dist/db/migrations/052_workflow_instance_bound_rig.js +30 -0
  56. package/daemon/dist/db/migrations/052_workflow_instance_bound_rig.js.map +1 -0
  57. package/daemon/dist/db/migrations/053_sessions_node_id_index.d.ts +48 -0
  58. package/daemon/dist/db/migrations/053_sessions_node_id_index.d.ts.map +1 -0
  59. package/daemon/dist/db/migrations/053_sessions_node_id_index.js +53 -0
  60. package/daemon/dist/db/migrations/053_sessions_node_id_index.js.map +1 -0
  61. package/daemon/dist/db/migrations/054_queue_transitions_archive.d.ts +34 -0
  62. package/daemon/dist/db/migrations/054_queue_transitions_archive.d.ts.map +1 -0
  63. package/daemon/dist/db/migrations/054_queue_transitions_archive.js +49 -0
  64. package/daemon/dist/db/migrations/054_queue_transitions_archive.js.map +1 -0
  65. package/daemon/dist/domain/claim-service.d.ts +11 -0
  66. package/daemon/dist/domain/claim-service.d.ts.map +1 -1
  67. package/daemon/dist/domain/claim-service.js +3 -1
  68. package/daemon/dist/domain/claim-service.js.map +1 -1
  69. package/daemon/dist/domain/discovery-types.d.ts +1 -1
  70. package/daemon/dist/domain/discovery-types.d.ts.map +1 -1
  71. package/daemon/dist/domain/feed/attention-aggregator.d.ts +31 -0
  72. package/daemon/dist/domain/feed/attention-aggregator.d.ts.map +1 -0
  73. package/daemon/dist/domain/feed/attention-aggregator.js +119 -0
  74. package/daemon/dist/domain/feed/attention-aggregator.js.map +1 -0
  75. package/daemon/dist/domain/files/file-write-service.d.ts +11 -2
  76. package/daemon/dist/domain/files/file-write-service.d.ts.map +1 -1
  77. package/daemon/dist/domain/files/file-write-service.js +77 -0
  78. package/daemon/dist/domain/files/file-write-service.js.map +1 -1
  79. package/daemon/dist/domain/hosts/fanout-contract.d.ts +33 -0
  80. package/daemon/dist/domain/hosts/fanout-contract.d.ts.map +1 -0
  81. package/daemon/dist/domain/hosts/fanout-contract.js +23 -0
  82. package/daemon/dist/domain/hosts/fanout-contract.js.map +1 -0
  83. package/daemon/dist/domain/hosts/hosts-registry-reader.d.ts +50 -0
  84. package/daemon/dist/domain/hosts/hosts-registry-reader.d.ts.map +1 -0
  85. package/daemon/dist/domain/hosts/hosts-registry-reader.js +184 -0
  86. package/daemon/dist/domain/hosts/hosts-registry-reader.js.map +1 -0
  87. package/daemon/dist/domain/hosts/hosts-registry-writer.d.ts +11 -0
  88. package/daemon/dist/domain/hosts/hosts-registry-writer.d.ts.map +1 -0
  89. package/daemon/dist/domain/hosts/hosts-registry-writer.js +54 -0
  90. package/daemon/dist/domain/hosts/hosts-registry-writer.js.map +1 -0
  91. package/daemon/dist/domain/hosts/read-through.d.ts +28 -0
  92. package/daemon/dist/domain/hosts/read-through.d.ts.map +1 -0
  93. package/daemon/dist/domain/hosts/read-through.js +139 -0
  94. package/daemon/dist/domain/hosts/read-through.js.map +1 -0
  95. package/daemon/dist/domain/hosts/remote-daemon-http.d.ts +56 -0
  96. package/daemon/dist/domain/hosts/remote-daemon-http.d.ts.map +1 -0
  97. package/daemon/dist/domain/hosts/remote-daemon-http.js +154 -0
  98. package/daemon/dist/domain/hosts/remote-daemon-http.js.map +1 -0
  99. package/daemon/dist/domain/human-route-enforcer.d.ts +71 -0
  100. package/daemon/dist/domain/human-route-enforcer.d.ts.map +1 -0
  101. package/daemon/dist/domain/human-route-enforcer.js +80 -0
  102. package/daemon/dist/domain/human-route-enforcer.js.map +1 -0
  103. package/daemon/dist/domain/mission-control/audit-browse.d.ts +8 -0
  104. package/daemon/dist/domain/mission-control/audit-browse.d.ts.map +1 -1
  105. package/daemon/dist/domain/mission-control/audit-browse.js +19 -0
  106. package/daemon/dist/domain/mission-control/audit-browse.js.map +1 -1
  107. package/daemon/dist/domain/mission-control/mission-control-action-log.d.ts +1 -1
  108. package/daemon/dist/domain/mission-control/mission-control-action-log.d.ts.map +1 -1
  109. package/daemon/dist/domain/mission-control/mission-control-action-log.js +4 -0
  110. package/daemon/dist/domain/mission-control/mission-control-action-log.js.map +1 -1
  111. package/daemon/dist/domain/mission-control/mission-control-fleet-cli-capability.js +1 -1
  112. package/daemon/dist/domain/mission-control/mission-control-fleet-cli-capability.js.map +1 -1
  113. package/daemon/dist/domain/mission-control/mission-control-read-layer.js +1 -1
  114. package/daemon/dist/domain/mission-control/mission-control-read-layer.js.map +1 -1
  115. package/daemon/dist/domain/mission-control/mission-control-write-contract.d.ts +28 -0
  116. package/daemon/dist/domain/mission-control/mission-control-write-contract.d.ts.map +1 -1
  117. package/daemon/dist/domain/mission-control/mission-control-write-contract.js +125 -0
  118. package/daemon/dist/domain/mission-control/mission-control-write-contract.js.map +1 -1
  119. package/daemon/dist/domain/node-inventory.d.ts +18 -0
  120. package/daemon/dist/domain/node-inventory.d.ts.map +1 -1
  121. package/daemon/dist/domain/node-inventory.js +206 -95
  122. package/daemon/dist/domain/node-inventory.js.map +1 -1
  123. package/daemon/dist/domain/node-launcher.d.ts +11 -0
  124. package/daemon/dist/domain/node-launcher.d.ts.map +1 -1
  125. package/daemon/dist/domain/node-launcher.js +10 -0
  126. package/daemon/dist/domain/node-launcher.js.map +1 -1
  127. package/daemon/dist/domain/policies/workflow-keepalive.d.ts +7 -0
  128. package/daemon/dist/domain/policies/workflow-keepalive.d.ts.map +1 -1
  129. package/daemon/dist/domain/policies/workflow-keepalive.js +93 -13
  130. package/daemon/dist/domain/policies/workflow-keepalive.js.map +1 -1
  131. package/daemon/dist/domain/ps-projection.d.ts +28 -1
  132. package/daemon/dist/domain/ps-projection.d.ts.map +1 -1
  133. package/daemon/dist/domain/ps-projection.js +76 -26
  134. package/daemon/dist/domain/ps-projection.js.map +1 -1
  135. package/daemon/dist/domain/queue-repository.d.ts +130 -1
  136. package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
  137. package/daemon/dist/domain/queue-repository.js +304 -11
  138. package/daemon/dist/domain/queue-repository.js.map +1 -1
  139. package/daemon/dist/domain/queue-retention.d.ts +130 -0
  140. package/daemon/dist/domain/queue-retention.d.ts.map +1 -0
  141. package/daemon/dist/domain/queue-retention.js +224 -0
  142. package/daemon/dist/domain/queue-retention.js.map +1 -0
  143. package/daemon/dist/domain/restore-orchestrator.d.ts +5 -0
  144. package/daemon/dist/domain/restore-orchestrator.d.ts.map +1 -1
  145. package/daemon/dist/domain/restore-orchestrator.js +29 -2
  146. package/daemon/dist/domain/restore-orchestrator.js.map +1 -1
  147. package/daemon/dist/domain/resume-token-capture.d.ts +13 -0
  148. package/daemon/dist/domain/resume-token-capture.d.ts.map +1 -1
  149. package/daemon/dist/domain/resume-token-capture.js +14 -1
  150. package/daemon/dist/domain/resume-token-capture.js.map +1 -1
  151. package/daemon/dist/domain/resume-token-validation.d.ts +1 -1
  152. package/daemon/dist/domain/resume-token-validation.d.ts.map +1 -1
  153. package/daemon/dist/domain/resume-token-validation.js +58 -10
  154. package/daemon/dist/domain/resume-token-validation.js.map +1 -1
  155. package/daemon/dist/domain/review/brief-spine.d.ts +19 -0
  156. package/daemon/dist/domain/review/brief-spine.d.ts.map +1 -0
  157. package/daemon/dist/domain/review/brief-spine.js +86 -0
  158. package/daemon/dist/domain/review/brief-spine.js.map +1 -0
  159. package/daemon/dist/domain/review/compose.d.ts +277 -0
  160. package/daemon/dist/domain/review/compose.d.ts.map +1 -0
  161. package/daemon/dist/domain/review/compose.js +862 -0
  162. package/daemon/dist/domain/review/compose.js.map +1 -0
  163. package/daemon/dist/domain/review/fleet-compose.d.ts +52 -0
  164. package/daemon/dist/domain/review/fleet-compose.d.ts.map +1 -0
  165. package/daemon/dist/domain/review/fleet-compose.js +294 -0
  166. package/daemon/dist/domain/review/fleet-compose.js.map +1 -0
  167. package/daemon/dist/domain/review/freeze.d.ts +31 -0
  168. package/daemon/dist/domain/review/freeze.d.ts.map +1 -0
  169. package/daemon/dist/domain/review/freeze.js +257 -0
  170. package/daemon/dist/domain/review/freeze.js.map +1 -0
  171. package/daemon/dist/domain/review/gather.d.ts +115 -0
  172. package/daemon/dist/domain/review/gather.d.ts.map +1 -0
  173. package/daemon/dist/domain/review/gather.js +812 -0
  174. package/daemon/dist/domain/review/gather.js.map +1 -0
  175. package/daemon/dist/domain/review/types.d.ts +361 -0
  176. package/daemon/dist/domain/review/types.d.ts.map +1 -0
  177. package/daemon/dist/domain/review/types.js +35 -0
  178. package/daemon/dist/domain/review/types.js.map +1 -0
  179. package/daemon/dist/domain/rig-expansion-service.d.ts.map +1 -1
  180. package/daemon/dist/domain/rig-expansion-service.js +3 -0
  181. package/daemon/dist/domain/rig-expansion-service.js.map +1 -1
  182. package/daemon/dist/domain/rig-repository.d.ts +7 -6
  183. package/daemon/dist/domain/rig-repository.d.ts.map +1 -1
  184. package/daemon/dist/domain/rig-repository.js +33 -11
  185. package/daemon/dist/domain/rig-repository.js.map +1 -1
  186. package/daemon/dist/domain/rigspec-codec.d.ts.map +1 -1
  187. package/daemon/dist/domain/rigspec-codec.js +3 -0
  188. package/daemon/dist/domain/rigspec-codec.js.map +1 -1
  189. package/daemon/dist/domain/rigspec-exporter.d.ts.map +1 -1
  190. package/daemon/dist/domain/rigspec-exporter.js +4 -0
  191. package/daemon/dist/domain/rigspec-exporter.js.map +1 -1
  192. package/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
  193. package/daemon/dist/domain/rigspec-instantiator.js +11 -0
  194. package/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
  195. package/daemon/dist/domain/rigspec-preflight.d.ts +6 -0
  196. package/daemon/dist/domain/rigspec-preflight.d.ts.map +1 -1
  197. package/daemon/dist/domain/rigspec-preflight.js +26 -1
  198. package/daemon/dist/domain/rigspec-preflight.js.map +1 -1
  199. package/daemon/dist/domain/rigspec-schema.d.ts.map +1 -1
  200. package/daemon/dist/domain/rigspec-schema.js +20 -1
  201. package/daemon/dist/domain/rigspec-schema.js.map +1 -1
  202. package/daemon/dist/domain/runtime-verifier.d.ts +7 -1
  203. package/daemon/dist/domain/runtime-verifier.d.ts.map +1 -1
  204. package/daemon/dist/domain/runtime-verifier.js +39 -1
  205. package/daemon/dist/domain/runtime-verifier.js.map +1 -1
  206. package/daemon/dist/domain/scope/scope-approve.d.ts +64 -0
  207. package/daemon/dist/domain/scope/scope-approve.d.ts.map +1 -0
  208. package/daemon/dist/domain/scope/scope-approve.js +153 -0
  209. package/daemon/dist/domain/scope/scope-approve.js.map +1 -0
  210. package/daemon/dist/domain/scope/scope-audit.d.ts +9 -1
  211. package/daemon/dist/domain/scope/scope-audit.d.ts.map +1 -1
  212. package/daemon/dist/domain/scope/scope-audit.js +173 -1
  213. package/daemon/dist/domain/scope/scope-audit.js.map +1 -1
  214. package/daemon/dist/domain/seat-handover-service.d.ts +9 -0
  215. package/daemon/dist/domain/seat-handover-service.d.ts.map +1 -1
  216. package/daemon/dist/domain/seat-handover-service.js +2 -0
  217. package/daemon/dist/domain/seat-handover-service.js.map +1 -1
  218. package/daemon/dist/domain/seat-identity-store.d.ts +7 -0
  219. package/daemon/dist/domain/seat-identity-store.d.ts.map +1 -1
  220. package/daemon/dist/domain/seat-identity-store.js +27 -0
  221. package/daemon/dist/domain/seat-identity-store.js.map +1 -1
  222. package/daemon/dist/domain/seat-status-service.d.ts.map +1 -1
  223. package/daemon/dist/domain/seat-status-service.js +6 -4
  224. package/daemon/dist/domain/seat-status-service.js.map +1 -1
  225. package/daemon/dist/domain/session-name.d.ts +22 -0
  226. package/daemon/dist/domain/session-name.d.ts.map +1 -1
  227. package/daemon/dist/domain/session-name.js +29 -0
  228. package/daemon/dist/domain/session-name.js.map +1 -1
  229. package/daemon/dist/domain/slices/slice-detail-projector.d.ts.map +1 -1
  230. package/daemon/dist/domain/slices/slice-detail-projector.js +4 -5
  231. package/daemon/dist/domain/slices/slice-detail-projector.js.map +1 -1
  232. package/daemon/dist/domain/spec-library-workflow-scanner.d.ts +18 -2
  233. package/daemon/dist/domain/spec-library-workflow-scanner.d.ts.map +1 -1
  234. package/daemon/dist/domain/spec-library-workflow-scanner.js +23 -1
  235. package/daemon/dist/domain/spec-library-workflow-scanner.js.map +1 -1
  236. package/daemon/dist/domain/startup-proof.d.ts +10 -6
  237. package/daemon/dist/domain/startup-proof.d.ts.map +1 -1
  238. package/daemon/dist/domain/startup-proof.js +35 -7
  239. package/daemon/dist/domain/startup-proof.js.map +1 -1
  240. package/daemon/dist/domain/successor-session-launcher.d.ts +16 -0
  241. package/daemon/dist/domain/successor-session-launcher.d.ts.map +1 -1
  242. package/daemon/dist/domain/successor-session-launcher.js +13 -0
  243. package/daemon/dist/domain/successor-session-launcher.js.map +1 -1
  244. package/daemon/dist/domain/terminal/cmux-provider-adapter.d.ts +27 -0
  245. package/daemon/dist/domain/terminal/cmux-provider-adapter.d.ts.map +1 -0
  246. package/daemon/dist/domain/terminal/cmux-provider-adapter.js +67 -0
  247. package/daemon/dist/domain/terminal/cmux-provider-adapter.js.map +1 -0
  248. package/daemon/dist/domain/terminal/herdr-adapter.d.ts +77 -0
  249. package/daemon/dist/domain/terminal/herdr-adapter.d.ts.map +1 -0
  250. package/daemon/dist/domain/terminal/herdr-adapter.js +266 -0
  251. package/daemon/dist/domain/terminal/herdr-adapter.js.map +1 -0
  252. package/daemon/dist/domain/terminal/herdr-transport.d.ts +50 -0
  253. package/daemon/dist/domain/terminal/herdr-transport.d.ts.map +1 -0
  254. package/daemon/dist/domain/terminal/herdr-transport.js +145 -0
  255. package/daemon/dist/domain/terminal/herdr-transport.js.map +1 -0
  256. package/daemon/dist/domain/terminal/terminal-provider.d.ts +88 -0
  257. package/daemon/dist/domain/terminal/terminal-provider.d.ts.map +1 -0
  258. package/daemon/dist/domain/terminal/terminal-provider.js +17 -0
  259. package/daemon/dist/domain/terminal/terminal-provider.js.map +1 -0
  260. package/daemon/dist/domain/terminal/terminal-service.d.ts +60 -0
  261. package/daemon/dist/domain/terminal/terminal-service.d.ts.map +1 -0
  262. package/daemon/dist/domain/terminal/terminal-service.js +174 -0
  263. package/daemon/dist/domain/terminal/terminal-service.js.map +1 -0
  264. package/daemon/dist/domain/terminal/terminal-views-store.d.ts +77 -0
  265. package/daemon/dist/domain/terminal/terminal-views-store.d.ts.map +1 -0
  266. package/daemon/dist/domain/terminal/terminal-views-store.js +146 -0
  267. package/daemon/dist/domain/terminal/terminal-views-store.js.map +1 -0
  268. package/daemon/dist/domain/terminal/view-composer.d.ts +42 -0
  269. package/daemon/dist/domain/terminal/view-composer.d.ts.map +1 -0
  270. package/daemon/dist/domain/terminal/view-composer.js +137 -0
  271. package/daemon/dist/domain/terminal/view-composer.js.map +1 -0
  272. package/daemon/dist/domain/tmux-option-defaults.d.ts +89 -0
  273. package/daemon/dist/domain/tmux-option-defaults.d.ts.map +1 -0
  274. package/daemon/dist/domain/tmux-option-defaults.js +132 -0
  275. package/daemon/dist/domain/tmux-option-defaults.js.map +1 -0
  276. package/daemon/dist/domain/topology/multi-rig-launcher.d.ts +49 -0
  277. package/daemon/dist/domain/topology/multi-rig-launcher.d.ts.map +1 -0
  278. package/daemon/dist/domain/topology/multi-rig-launcher.js +132 -0
  279. package/daemon/dist/domain/topology/multi-rig-launcher.js.map +1 -0
  280. package/daemon/dist/domain/topology/remote-up-leaf.d.ts +29 -0
  281. package/daemon/dist/domain/topology/remote-up-leaf.d.ts.map +1 -0
  282. package/daemon/dist/domain/topology/remote-up-leaf.js +60 -0
  283. package/daemon/dist/domain/topology/remote-up-leaf.js.map +1 -0
  284. package/daemon/dist/domain/topology/topology-manifest.d.ts +34 -0
  285. package/daemon/dist/domain/topology/topology-manifest.d.ts.map +1 -0
  286. package/daemon/dist/domain/topology/topology-manifest.js +195 -0
  287. package/daemon/dist/domain/topology/topology-manifest.js.map +1 -0
  288. package/daemon/dist/domain/types.d.ts +39 -1
  289. package/daemon/dist/domain/types.d.ts.map +1 -1
  290. package/daemon/dist/domain/types.js.map +1 -1
  291. package/daemon/dist/domain/up-command-router.d.ts +1 -1
  292. package/daemon/dist/domain/up-command-router.d.ts.map +1 -1
  293. package/daemon/dist/domain/up-command-router.js +34 -2
  294. package/daemon/dist/domain/up-command-router.js.map +1 -1
  295. package/daemon/dist/domain/user-settings/settings-store.d.ts +18 -1
  296. package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
  297. package/daemon/dist/domain/user-settings/settings-store.js +201 -0
  298. package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
  299. package/daemon/dist/domain/workflow/slice-workflow-projection.d.ts.map +1 -1
  300. package/daemon/dist/domain/workflow/slice-workflow-projection.js +6 -2
  301. package/daemon/dist/domain/workflow/slice-workflow-projection.js.map +1 -1
  302. package/daemon/dist/domain/workflow-boot-sweep.d.ts +28 -0
  303. package/daemon/dist/domain/workflow-boot-sweep.d.ts.map +1 -0
  304. package/daemon/dist/domain/workflow-boot-sweep.js +102 -0
  305. package/daemon/dist/domain/workflow-boot-sweep.js.map +1 -0
  306. package/daemon/dist/domain/workflow-deadline.d.ts +74 -0
  307. package/daemon/dist/domain/workflow-deadline.d.ts.map +1 -0
  308. package/daemon/dist/domain/workflow-deadline.js +165 -0
  309. package/daemon/dist/domain/workflow-deadline.js.map +1 -0
  310. package/daemon/dist/domain/workflow-exception-escalation.d.ts +33 -0
  311. package/daemon/dist/domain/workflow-exception-escalation.d.ts.map +1 -0
  312. package/daemon/dist/domain/workflow-exception-escalation.js +104 -0
  313. package/daemon/dist/domain/workflow-exception-escalation.js.map +1 -0
  314. package/daemon/dist/domain/workflow-exception-router.d.ts +33 -0
  315. package/daemon/dist/domain/workflow-exception-router.d.ts.map +1 -0
  316. package/daemon/dist/domain/workflow-exception-router.js +96 -0
  317. package/daemon/dist/domain/workflow-exception-router.js.map +1 -0
  318. package/daemon/dist/domain/workflow-exception.d.ts +90 -0
  319. package/daemon/dist/domain/workflow-exception.d.ts.map +1 -0
  320. package/daemon/dist/domain/workflow-exception.js +122 -0
  321. package/daemon/dist/domain/workflow-exception.js.map +1 -0
  322. package/daemon/dist/domain/workflow-frontier-guard.d.ts +24 -0
  323. package/daemon/dist/domain/workflow-frontier-guard.d.ts.map +1 -0
  324. package/daemon/dist/domain/workflow-frontier-guard.js +30 -0
  325. package/daemon/dist/domain/workflow-frontier-guard.js.map +1 -0
  326. package/daemon/dist/domain/workflow-instance-store.d.ts +28 -0
  327. package/daemon/dist/domain/workflow-instance-store.d.ts.map +1 -1
  328. package/daemon/dist/domain/workflow-instance-store.js +66 -10
  329. package/daemon/dist/domain/workflow-instance-store.js.map +1 -1
  330. package/daemon/dist/domain/workflow-keepalive-arming.d.ts +35 -0
  331. package/daemon/dist/domain/workflow-keepalive-arming.d.ts.map +1 -0
  332. package/daemon/dist/domain/workflow-keepalive-arming.js +87 -0
  333. package/daemon/dist/domain/workflow-keepalive-arming.js.map +1 -0
  334. package/daemon/dist/domain/workflow-projector.d.ts +117 -2
  335. package/daemon/dist/domain/workflow-projector.d.ts.map +1 -1
  336. package/daemon/dist/domain/workflow-projector.js +672 -41
  337. package/daemon/dist/domain/workflow-projector.js.map +1 -1
  338. package/daemon/dist/domain/workflow-role-context.d.ts +57 -0
  339. package/daemon/dist/domain/workflow-role-context.d.ts.map +1 -0
  340. package/daemon/dist/domain/workflow-role-context.js +120 -0
  341. package/daemon/dist/domain/workflow-role-context.js.map +1 -0
  342. package/daemon/dist/domain/workflow-role-resolver.d.ts +65 -0
  343. package/daemon/dist/domain/workflow-role-resolver.d.ts.map +1 -0
  344. package/daemon/dist/domain/workflow-role-resolver.js +108 -0
  345. package/daemon/dist/domain/workflow-role-resolver.js.map +1 -0
  346. package/daemon/dist/domain/workflow-runtime.d.ts +157 -1
  347. package/daemon/dist/domain/workflow-runtime.d.ts.map +1 -1
  348. package/daemon/dist/domain/workflow-runtime.js +718 -11
  349. package/daemon/dist/domain/workflow-runtime.js.map +1 -1
  350. package/daemon/dist/domain/workflow-spec-cache.d.ts +26 -1
  351. package/daemon/dist/domain/workflow-spec-cache.d.ts.map +1 -1
  352. package/daemon/dist/domain/workflow-spec-cache.js +327 -13
  353. package/daemon/dist/domain/workflow-spec-cache.js.map +1 -1
  354. package/daemon/dist/domain/workflow-types.d.ts +143 -8
  355. package/daemon/dist/domain/workflow-types.d.ts.map +1 -1
  356. package/daemon/dist/domain/workflow-types.js +14 -1
  357. package/daemon/dist/domain/workflow-types.js.map +1 -1
  358. package/daemon/dist/domain/workflow-validator.d.ts +11 -1
  359. package/daemon/dist/domain/workflow-validator.d.ts.map +1 -1
  360. package/daemon/dist/domain/workflow-validator.js +246 -1
  361. package/daemon/dist/domain/workflow-validator.js.map +1 -1
  362. package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
  363. package/daemon/dist/domain/workspace/default-workspace-scaffold.js +51 -6
  364. package/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
  365. package/daemon/dist/domain/workspace/workspace-doctor.d.ts +11 -0
  366. package/daemon/dist/domain/workspace/workspace-doctor.d.ts.map +1 -1
  367. package/daemon/dist/domain/workspace/workspace-doctor.js +82 -0
  368. package/daemon/dist/domain/workspace/workspace-doctor.js.map +1 -1
  369. package/daemon/dist/index.d.ts +17 -0
  370. package/daemon/dist/index.d.ts.map +1 -1
  371. package/daemon/dist/index.js +44 -0
  372. package/daemon/dist/index.js.map +1 -1
  373. package/daemon/dist/routes/activity.js +22 -0
  374. package/daemon/dist/routes/activity.js.map +1 -1
  375. package/daemon/dist/routes/config.d.ts.map +1 -1
  376. package/daemon/dist/routes/config.js +15 -6
  377. package/daemon/dist/routes/config.js.map +1 -1
  378. package/daemon/dist/routes/files.d.ts.map +1 -1
  379. package/daemon/dist/routes/files.js +45 -1
  380. package/daemon/dist/routes/files.js.map +1 -1
  381. package/daemon/dist/routes/hosts.d.ts +5 -0
  382. package/daemon/dist/routes/hosts.d.ts.map +1 -0
  383. package/daemon/dist/routes/hosts.js +346 -0
  384. package/daemon/dist/routes/hosts.js.map +1 -0
  385. package/daemon/dist/routes/mission-control.d.ts.map +1 -1
  386. package/daemon/dist/routes/mission-control.js +67 -2
  387. package/daemon/dist/routes/mission-control.js.map +1 -1
  388. package/daemon/dist/routes/queue.d.ts +10 -9
  389. package/daemon/dist/routes/queue.d.ts.map +1 -1
  390. package/daemon/dist/routes/queue.js +305 -10
  391. package/daemon/dist/routes/queue.js.map +1 -1
  392. package/daemon/dist/routes/review.d.ts +3 -0
  393. package/daemon/dist/routes/review.d.ts.map +1 -0
  394. package/daemon/dist/routes/review.js +195 -0
  395. package/daemon/dist/routes/review.js.map +1 -0
  396. package/daemon/dist/routes/scope-approve.d.ts +3 -0
  397. package/daemon/dist/routes/scope-approve.d.ts.map +1 -0
  398. package/daemon/dist/routes/scope-approve.js +55 -0
  399. package/daemon/dist/routes/scope-approve.js.map +1 -0
  400. package/daemon/dist/routes/scope-audit.d.ts.map +1 -1
  401. package/daemon/dist/routes/scope-audit.js +28 -1
  402. package/daemon/dist/routes/scope-audit.js.map +1 -1
  403. package/daemon/dist/routes/seat.js +13 -0
  404. package/daemon/dist/routes/seat.js.map +1 -1
  405. package/daemon/dist/routes/slices.d.ts.map +1 -1
  406. package/daemon/dist/routes/slices.js +49 -9
  407. package/daemon/dist/routes/slices.js.map +1 -1
  408. package/daemon/dist/routes/terminal-ws.d.ts.map +1 -1
  409. package/daemon/dist/routes/terminal-ws.js +58 -21
  410. package/daemon/dist/routes/terminal-ws.js.map +1 -1
  411. package/daemon/dist/routes/terminal.d.ts +11 -0
  412. package/daemon/dist/routes/terminal.d.ts.map +1 -0
  413. package/daemon/dist/routes/terminal.js +104 -0
  414. package/daemon/dist/routes/terminal.js.map +1 -0
  415. package/daemon/dist/routes/up.d.ts.map +1 -1
  416. package/daemon/dist/routes/up.js +84 -0
  417. package/daemon/dist/routes/up.js.map +1 -1
  418. package/daemon/dist/routes/workflow.d.ts.map +1 -1
  419. package/daemon/dist/routes/workflow.js +102 -10
  420. package/daemon/dist/routes/workflow.js.map +1 -1
  421. package/daemon/dist/routes/workspace.js +2 -2
  422. package/daemon/dist/server.d.ts +6 -0
  423. package/daemon/dist/server.d.ts.map +1 -1
  424. package/daemon/dist/server.js +36 -1
  425. package/daemon/dist/server.js.map +1 -1
  426. package/daemon/dist/startup.d.ts.map +1 -1
  427. package/daemon/dist/startup.js +238 -14
  428. package/daemon/dist/startup.js.map +1 -1
  429. package/daemon/docs/reference/agent-startup-guide.md +1 -1
  430. package/daemon/docs/reference/product-factory-vps-runbook.md +132 -0
  431. package/daemon/docs/reference/sdlc-conventions.md +187 -0
  432. package/daemon/specs/agents/conveyor/builder/agent.yaml +1 -1
  433. package/daemon/specs/agents/conveyor/builder/guidance/role.md +1 -0
  434. package/daemon/specs/agents/conveyor/lead/agent.yaml +1 -1
  435. package/daemon/specs/agents/conveyor/lead/guidance/role.md +1 -0
  436. package/daemon/specs/agents/conveyor/planner/agent.yaml +1 -1
  437. package/daemon/specs/agents/conveyor/planner/guidance/role.md +1 -0
  438. package/daemon/specs/agents/conveyor/reviewer/agent.yaml +1 -1
  439. package/daemon/specs/agents/conveyor/reviewer/guidance/role.md +1 -0
  440. package/daemon/specs/agents/design/product-designer/agent.yaml +1 -1
  441. package/daemon/specs/agents/design/product-designer/guidance/role.md +1 -0
  442. package/daemon/specs/agents/development/implementer/agent.yaml +1 -1
  443. package/daemon/specs/agents/development/implementer/guidance/role.md +1 -0
  444. package/daemon/specs/agents/development/qa/agent.yaml +1 -1
  445. package/daemon/specs/agents/development/qa/guidance/role.md +1 -0
  446. package/daemon/specs/agents/factory-rsi/dogfood/agent.yaml +29 -0
  447. package/daemon/specs/agents/factory-rsi/dogfood/guidance/role.md +37 -0
  448. package/daemon/specs/agents/factory-rsi/release-manager/agent.yaml +29 -0
  449. package/daemon/specs/agents/factory-rsi/release-manager/guidance/role.md +40 -0
  450. package/daemon/specs/agents/orchestration/orchestrator/agent.yaml +1 -1
  451. package/daemon/specs/agents/orchestration/orchestrator/guidance/role.md +1 -0
  452. package/daemon/specs/agents/product-management/pm/agent.yaml +1 -0
  453. package/daemon/specs/agents/product-management/pm/guidance/role.md +13 -0
  454. package/daemon/specs/agents/review/independent-reviewer/agent.yaml +1 -1
  455. package/daemon/specs/agents/review/independent-reviewer/guidance/role.md +1 -0
  456. package/daemon/specs/agents/shared/agent.yaml +2 -0
  457. package/daemon/specs/agents/shared/skills/core/mission-slice-sop/SKILL.md +113 -0
  458. package/daemon/specs/agents/shared/skills/core/openrig-cmux/SKILL.md +86 -0
  459. package/daemon/specs/agents/shared/skills/core/openrig-herdr/SKILL.md +158 -0
  460. package/daemon/specs/agents/shared/skills/core/openrig-operator/SKILL.md +4 -4
  461. package/daemon/specs/agents/shared/skills/core/openrig-user/SKILL.md +75 -29
  462. package/daemon/specs/agents/shared/skills/pods/orchestration-team/SKILL.md +2 -2
  463. package/daemon/specs/rigs/focused/pm-team/CULTURE.md +4 -0
  464. package/daemon/specs/rigs/launch/factory-rsi/CULTURE.md +47 -0
  465. package/daemon/specs/rigs/launch/factory-rsi/rig.yaml +115 -0
  466. package/daemon/specs/rigs/launch/kernel/agents/operator/agent/guidance/role.md +1 -1
  467. package/daemon/specs/rigs/launch/kernel/agents/operator/agent/startup/context.md +1 -1
  468. package/daemon/specs/rigs/preview/product-team/CULTURE.md +4 -0
  469. package/dist/build-info.d.ts +8 -0
  470. package/dist/build-info.d.ts.map +1 -0
  471. package/dist/build-info.js +11 -0
  472. package/dist/build-info.js.map +1 -0
  473. package/dist/commands/broadcast.d.ts +6 -1
  474. package/dist/commands/broadcast.d.ts.map +1 -1
  475. package/dist/commands/broadcast.js +101 -15
  476. package/dist/commands/broadcast.js.map +1 -1
  477. package/dist/commands/capture.d.ts.map +1 -1
  478. package/dist/commands/capture.js +99 -8
  479. package/dist/commands/capture.js.map +1 -1
  480. package/dist/commands/config-init-workspace.d.ts.map +1 -1
  481. package/dist/commands/config-init-workspace.js +20 -4
  482. package/dist/commands/config-init-workspace.js.map +1 -1
  483. package/dist/commands/config.d.ts.map +1 -1
  484. package/dist/commands/config.js +4 -0
  485. package/dist/commands/config.js.map +1 -1
  486. package/dist/commands/doctor.js +2 -2
  487. package/dist/commands/doctor.js.map +1 -1
  488. package/dist/commands/down.d.ts.map +1 -1
  489. package/dist/commands/down.js +5 -0
  490. package/dist/commands/down.js.map +1 -1
  491. package/dist/commands/expand.js +1 -1
  492. package/dist/commands/expand.js.map +1 -1
  493. package/dist/commands/file.d.ts +7 -0
  494. package/dist/commands/file.d.ts.map +1 -0
  495. package/dist/commands/file.js +77 -0
  496. package/dist/commands/file.js.map +1 -0
  497. package/dist/commands/host.d.ts +48 -0
  498. package/dist/commands/host.d.ts.map +1 -0
  499. package/dist/commands/host.js +772 -0
  500. package/dist/commands/host.js.map +1 -0
  501. package/dist/commands/launch.d.ts.map +1 -1
  502. package/dist/commands/launch.js +5 -0
  503. package/dist/commands/launch.js.map +1 -1
  504. package/dist/commands/proof.d.ts +54 -0
  505. package/dist/commands/proof.d.ts.map +1 -0
  506. package/dist/commands/proof.js +311 -0
  507. package/dist/commands/proof.js.map +1 -0
  508. package/dist/commands/ps.d.ts +41 -7
  509. package/dist/commands/ps.d.ts.map +1 -1
  510. package/dist/commands/ps.js +353 -135
  511. package/dist/commands/ps.js.map +1 -1
  512. package/dist/commands/queue.d.ts +36 -0
  513. package/dist/commands/queue.d.ts.map +1 -1
  514. package/dist/commands/queue.js +149 -7
  515. package/dist/commands/queue.js.map +1 -1
  516. package/dist/commands/restore-packet.d.ts.map +1 -1
  517. package/dist/commands/restore-packet.js +13 -2
  518. package/dist/commands/restore-packet.js.map +1 -1
  519. package/dist/commands/scope.d.ts.map +1 -1
  520. package/dist/commands/scope.js +140 -3
  521. package/dist/commands/scope.js.map +1 -1
  522. package/dist/commands/send.d.ts.map +1 -1
  523. package/dist/commands/send.js +127 -13
  524. package/dist/commands/send.js.map +1 -1
  525. package/dist/commands/terminal.d.ts +6 -0
  526. package/dist/commands/terminal.d.ts.map +1 -0
  527. package/dist/commands/terminal.js +116 -0
  528. package/dist/commands/terminal.js.map +1 -0
  529. package/dist/commands/transcript.d.ts +6 -1
  530. package/dist/commands/transcript.d.ts.map +1 -1
  531. package/dist/commands/transcript.js +113 -30
  532. package/dist/commands/transcript.js.map +1 -1
  533. package/dist/commands/up.d.ts +2 -0
  534. package/dist/commands/up.d.ts.map +1 -1
  535. package/dist/commands/up.js +78 -2
  536. package/dist/commands/up.js.map +1 -1
  537. package/dist/commands/whoami.d.ts.map +1 -1
  538. package/dist/commands/whoami.js +11 -0
  539. package/dist/commands/whoami.js.map +1 -1
  540. package/dist/commands/workflow-errors.d.ts +23 -0
  541. package/dist/commands/workflow-errors.d.ts.map +1 -0
  542. package/dist/commands/workflow-errors.js +100 -0
  543. package/dist/commands/workflow-errors.js.map +1 -0
  544. package/dist/commands/workflow-follow.d.ts +71 -0
  545. package/dist/commands/workflow-follow.d.ts.map +1 -0
  546. package/dist/commands/workflow-follow.js +259 -0
  547. package/dist/commands/workflow-follow.js.map +1 -0
  548. package/dist/commands/workflow-render.d.ts +114 -0
  549. package/dist/commands/workflow-render.d.ts.map +1 -0
  550. package/dist/commands/workflow-render.js +223 -0
  551. package/dist/commands/workflow-render.js.map +1 -0
  552. package/dist/commands/workflow.d.ts +1 -0
  553. package/dist/commands/workflow.d.ts.map +1 -1
  554. package/dist/commands/workflow.js +278 -14
  555. package/dist/commands/workflow.js.map +1 -1
  556. package/dist/commands/workspace.js +6 -6
  557. package/dist/commands/workspace.js.map +1 -1
  558. package/dist/config-store.d.ts +19 -1
  559. package/dist/config-store.d.ts.map +1 -1
  560. package/dist/config-store.js +171 -0
  561. package/dist/config-store.js.map +1 -1
  562. package/dist/cross-host-cli-helpers.d.ts +13 -0
  563. package/dist/cross-host-cli-helpers.d.ts.map +1 -1
  564. package/dist/cross-host-cli-helpers.js +27 -0
  565. package/dist/cross-host-cli-helpers.js.map +1 -1
  566. package/dist/cross-host-executor.d.ts +1 -0
  567. package/dist/cross-host-executor.d.ts.map +1 -1
  568. package/dist/cross-host-executor.js +4 -1
  569. package/dist/cross-host-executor.js.map +1 -1
  570. package/dist/cross-host-target.d.ts +49 -0
  571. package/dist/cross-host-target.d.ts.map +1 -0
  572. package/dist/cross-host-target.js +35 -0
  573. package/dist/cross-host-target.js.map +1 -0
  574. package/dist/daemon-lifecycle.d.ts.map +1 -1
  575. package/dist/daemon-lifecycle.js +4 -1
  576. package/dist/daemon-lifecycle.js.map +1 -1
  577. package/dist/host-registry.d.ts +17 -0
  578. package/dist/host-registry.d.ts.map +1 -1
  579. package/dist/host-registry.js +64 -2
  580. package/dist/host-registry.js.map +1 -1
  581. package/dist/host-selection.d.ts +13 -0
  582. package/dist/host-selection.d.ts.map +1 -0
  583. package/dist/host-selection.js +54 -0
  584. package/dist/host-selection.js.map +1 -0
  585. package/dist/index.d.ts +2 -0
  586. package/dist/index.d.ts.map +1 -1
  587. package/dist/index.js +9 -0
  588. package/dist/index.js.map +1 -1
  589. package/dist/lib/file-transfer.d.ts +89 -0
  590. package/dist/lib/file-transfer.d.ts.map +1 -0
  591. package/dist/lib/file-transfer.js +300 -0
  592. package/dist/lib/file-transfer.js.map +1 -0
  593. package/dist/lib/hosts/fanout-contract.d.ts +33 -0
  594. package/dist/lib/hosts/fanout-contract.d.ts.map +1 -0
  595. package/dist/lib/hosts/fanout-contract.js +23 -0
  596. package/dist/lib/hosts/fanout-contract.js.map +1 -0
  597. package/dist/lib/scope/scope-audit.d.ts +9 -1
  598. package/dist/lib/scope/scope-audit.d.ts.map +1 -1
  599. package/dist/lib/scope/scope-audit.js +173 -1
  600. package/dist/lib/scope/scope-audit.js.map +1 -1
  601. package/dist/lib/scope/templates.d.ts +1 -0
  602. package/dist/lib/scope/templates.d.ts.map +1 -1
  603. package/dist/lib/scope/templates.js +9 -0
  604. package/dist/lib/scope/templates.js.map +1 -1
  605. package/dist/lib/scope-templates/backlog-deprecation.md +16 -0
  606. package/dist/lib/scope-templates/backlog-tech-debt.md +16 -0
  607. package/dist/lib/scope-templates/bug-fix.md +16 -0
  608. package/dist/lib/scope-templates/implementation-prd.md +33 -0
  609. package/dist/lib/scope-templates/mission-placeholder.md +1 -1
  610. package/dist/lib/scope-templates/mission-progress.md +1 -1
  611. package/dist/lib/scope-templates/mission-release.md +1 -1
  612. package/dist/lib/scope-templates/placeholder.md +11 -7
  613. package/dist/lib/scope-templates/proof.md +5 -1
  614. package/dist/lib/scope-templates/release-feature.md +14 -6
  615. package/dist/lib/scope-templates/research.md +16 -0
  616. package/dist/lib/scope-templates/slice-progress.md +1 -1
  617. package/dist/remote-host-ops.d.ts +1 -0
  618. package/dist/remote-host-ops.d.ts.map +1 -1
  619. package/dist/remote-host-ops.js +11 -4
  620. package/dist/remote-host-ops.js.map +1 -1
  621. package/dist/session-name.d.ts +23 -0
  622. package/dist/session-name.d.ts.map +1 -0
  623. package/dist/session-name.js +61 -0
  624. package/dist/session-name.js.map +1 -0
  625. package/dist/version.d.ts +5 -0
  626. package/dist/version.d.ts.map +1 -1
  627. package/dist/version.js +11 -1
  628. package/dist/version.js.map +1 -1
  629. package/package.json +1 -1
  630. package/ui/dist/assets/index-CFqxa0zW.css +32 -0
  631. package/ui/dist/assets/index-zrFqS7gL.js +623 -0
  632. package/ui/dist/index.html +2 -2
  633. package/ui/dist/assets/index-DYZniQcc.js +0 -597
  634. package/ui/dist/assets/index-trcb4Yf_.css +0 -32
@@ -1,4 +1,6 @@
1
1
  import { Command } from "commander";
2
+ import { resolveEffectiveHost } from "../host-selection.js";
3
+ import { sessionRigOf } from "../session-name.js";
2
4
  import { DaemonClient } from "../client.js";
3
5
  import { getDaemonStatus, getDaemonUrl } from "../daemon-lifecycle.js";
4
6
  import { realDeps } from "./daemon.js";
@@ -10,10 +12,8 @@ import { readOpenRigEnv } from "../openrig-compat.js";
10
12
  // with realistic agent counts. `--full` opts out. JSON output remains
11
13
  // unbounded by default for back-compat (Decision C hybrid).
12
14
  function extractRigName(sessionName) {
13
- const atIdx = sessionName.lastIndexOf("@");
14
- if (atIdx < 0 || atIdx === sessionName.length - 1)
15
- return undefined;
16
- return sessionName.slice(atIdx + 1);
15
+ // OPR.0.4.6.MH1 FR-8: the shared parse contract (greedy first-@ rig).
16
+ return sessionRigOf(sessionName);
17
17
  }
18
18
  const HUMAN_RIG_BUDGET = 50;
19
19
  const HUMAN_NODE_BUDGET = 100;
@@ -55,6 +55,7 @@ const NUMERIC_OPERATORS = [">=", "<=", ">", "<", "="];
55
55
  // rig-level only; `rigName` is the alias and exists at both levels (per the
56
56
  // closed `rig ps trust and scale-safety` slice at openrig 0a9fb43).
57
57
  const ALLOWED_RIG_FIELDS = new Set([
58
+ "attentionCount",
58
59
  "rigId",
59
60
  "name",
60
61
  "rigName",
@@ -196,6 +197,45 @@ function parseFields(input, allowed, level) {
196
197
  }
197
198
  return fields;
198
199
  }
200
+ function parsePsControls(opts) {
201
+ let effectiveFilter = opts.filter;
202
+ if (opts.active) {
203
+ if (effectiveFilter) {
204
+ return {
205
+ error: `--active and --filter cannot be combined. ` +
206
+ `--active is sugar for --filter agentActivity.state=running. ` +
207
+ `Pick one form, or compose by upgrading to --filter directly.`,
208
+ };
209
+ }
210
+ effectiveFilter = "agentActivity.state=running";
211
+ }
212
+ let parsedFilter = null;
213
+ if (effectiveFilter) {
214
+ const result = parseFilter(effectiveFilter);
215
+ if ("error" in result)
216
+ return result;
217
+ parsedFilter = result;
218
+ }
219
+ const limit = opts.limit !== undefined ? Number(opts.limit) : null;
220
+ if (limit !== null && (!Number.isInteger(limit) || limit < 0)) {
221
+ return { error: `--limit must be a non-negative integer; got '${opts.limit}'` };
222
+ }
223
+ let fields = null;
224
+ if (opts.fields !== undefined) {
225
+ const fieldsLevel = opts.nodes ? "nodes" : "rig";
226
+ const fieldsAllowed = fieldsLevel === "nodes" ? ALLOWED_NODE_FIELDS : ALLOWED_RIG_FIELDS;
227
+ const fieldsResult = parseFields(opts.fields, fieldsAllowed, fieldsLevel);
228
+ if ("error" in fieldsResult)
229
+ return fieldsResult;
230
+ fields = fieldsResult;
231
+ }
232
+ return {
233
+ parsedFilter,
234
+ limit,
235
+ fields,
236
+ useEnvelope: parsedFilter !== null || limit !== null || fields !== null || opts.summary === true,
237
+ };
238
+ }
199
239
  function applyRigFilter(entries, filter) {
200
240
  return entries.filter((e) => {
201
241
  if (filter.key === "status")
@@ -258,6 +298,65 @@ function applyNodeFilter(entries, filter) {
258
298
  // OPR.0.3.3.19 - build the /api/ps path, opting archived rigs back in when
259
299
  // --include-archived is set. Default (no flag) leaves the daemon's
260
300
  // archived-excluding default in force.
301
+ function fanOutNodesError() {
302
+ return [
303
+ "rig ps --all-hosts/--hosts --nodes: per-node fan-out requires the FULL explicit ladder.",
304
+ " rig ps --all-hosts --nodes -A (fleet nodes per host, projected rows)",
305
+ " rig ps --all-hosts --nodes -A --full (complete per-node records — the last rung)",
306
+ "One rig's seats on one host: rig ps --host <id> --nodes --rig <name>.",
307
+ ].join("\n");
308
+ }
309
+ /**
310
+ * OPR.0.4.4.21 FR-2/FR-3 — THE centralized disclosure-ladder validator.
311
+ * Runs BEFORE the local/HTTP-host/SSH/fan-out dispatch split so every path
312
+ * obeys one grammar (qa1 plan-review: remote mode bypassed the session-rig
313
+ * injection and fanned wide). Principle (arch-ratified): IMPLICIT SCOPE
314
+ * DEFAULTS DON'T CROSS HOST BOUNDARIES — the session-rig default has no
315
+ * stable referent on a remote host (a same-named rig there would silently
316
+ * misresolve), so remote per-node views are explicit-or-error.
317
+ * Returns the teaching error text, or null when the invocation is valid.
318
+ */
319
+ export function validatePsLadder(opts, callerRig) {
320
+ const isFanOut = !!(opts.allHosts || opts.hosts);
321
+ const isSingleRemote = !!opts.host;
322
+ // FR-3: -A/--all-rigs has exactly ONE meaning — the --nodes fleet widener.
323
+ if (opts.allRigs && !opts.nodes) {
324
+ return [
325
+ "rig ps -A: '-A/--all-rigs' now has exactly one meaning — the --nodes fleet widener.",
326
+ "The consolidated all-rigs view IS the default: just run 'rig ps'.",
327
+ "Fleet nodes: rig ps --nodes -A (add --full for complete per-node records).",
328
+ "Archived history: rig ps --include-archived.",
329
+ ].join("\n");
330
+ }
331
+ // FR-5: multi-host fan-out is rollup-only UNLESS the full explicit
332
+ // ladder is requested — `--nodes -A` per host (`--full` for complete
333
+ // records), exactly as the PRD writes it. Anything less explicit under
334
+ // --nodes errors; never silent rig-tier data under a --nodes flag.
335
+ if (opts.nodes && isFanOut && !opts.allRigs) {
336
+ return fanOutNodesError();
337
+ }
338
+ // FR-2: --nodes always names its scope — session default locally,
339
+ // explicit --rig / -A everywhere else. Never an implicit fan-out.
340
+ if (opts.nodes && !opts.rig && !opts.allRigs) {
341
+ if (isFanOut) {
342
+ return fanOutNodesError();
343
+ }
344
+ if (isSingleRemote) {
345
+ return [
346
+ `rig ps --host ${opts.host} --nodes: no target — the local session's rig is not a remote scope`,
347
+ "(implicit scope defaults don't cross host boundaries; a same-named remote rig would silently misresolve).",
348
+ `Name one: rig ps --host ${opts.host} --nodes --rig <name>, or that host's fleet explicitly: rig ps --host ${opts.host} --nodes -A.`,
349
+ ].join("\n");
350
+ }
351
+ if (!callerRig) {
352
+ return [
353
+ "rig ps --nodes: no target — outside a managed session there is no current rig to default to.",
354
+ "Name one: rig ps --nodes --rig <name>, or go fleet-wide explicitly: rig ps --nodes -A.",
355
+ ].join("\n");
356
+ }
357
+ }
358
+ return null;
359
+ }
261
360
  function psApiPath(opts) {
262
361
  return opts.includeArchived ? "/api/ps?includeArchived=true" : "/api/ps";
263
362
  }
@@ -269,6 +368,12 @@ function selectFields(entries, fields) {
269
368
  return out;
270
369
  });
271
370
  }
371
+ function selectFanOutFields(entries, fields) {
372
+ return entries.map((e) => {
373
+ const [selected] = selectFields([e], fields);
374
+ return { ...selected, hostId: e.hostId };
375
+ });
376
+ }
272
377
  function needsAttention(node) {
273
378
  return node.lifecycleState === "attention_required"
274
379
  || node.startupStatus === "attention_required"
@@ -373,22 +478,39 @@ function abbrevNodeLifecycle(state) {
373
478
  return "—";
374
479
  }
375
480
  /**
376
- * `rig ps` — list running rigs and optionally their nodes.
481
+ * `rig ps` — the consolidated fleet map + explicit disclosure ladder.
377
482
  *
378
- * L3-followup adds CLI-side shaping flags (`--limit`, `--fields`, `--summary`,
379
- * `--filter`, `--full`) for context-window-safe output on large hosts. Default
380
- * `rig ps` (human) truncates to ~50 rigs with an explicit footer naming totals
381
- * and the `--full` opt-out. Default `rig ps --json` keeps the bare-array shape
382
- * for back-compat; the truncation/envelope shape only applies when at least
383
- * one of `--limit`/`--summary`/`--fields`/`--filter` is specified.
483
+ * OPR.0.4.4.21: the default is ALL active rigs, one compact O(rigs) row each
484
+ * (the current-rig-only default is retired). The token-safety invariant: no
485
+ * invocation returns per-node detail across all rigs unless explicitly
486
+ * flagged (--nodes -A), and even then rows are projected unless --full.
487
+ * Default `rig ps --json` keeps the bare-array shape for back-compat; the
488
+ * truncation/envelope shape only applies when at least one of
489
+ * `--limit`/`--summary`/`--fields`/`--filter` is specified.
384
490
  */
385
491
  export function psCommand(depsOverride) {
386
492
  const cmd = new Command("ps")
387
493
  .description("List rigs and their status")
388
494
  .addHelpText("after", `
389
- Default: current-rig scope (derived from OPENRIG_SESSION_NAME's @<rig> suffix).
390
- Shows ALL states (stopped, recoverable, attention, idle non-running IS the
391
- actionable signal for topology/readiness). Use -A/--all-rigs for fleet breadth.
495
+ Default (OPR.0.4.4.21): ALL active rigs, ONE compact row each — O(rigs), never
496
+ a fleet node fan-out — plus the host rollup line ("N rigs · M seats · K need
497
+ attention"), the archived/stopped count line, and the drill-ladder footer.
498
+ STATED contract: default --json is a bare array of ALL non-archived rigs
499
+ INCLUDING stopped ones (existing keys preserved; additive attentionCount);
500
+ only the HUMAN table folds stopped rigs into the count line.
501
+
502
+ The disclosure ladder (each heavier view is an explicit step):
503
+ rig ps the consolidated map (this default)
504
+ rig ps --rig <name> one rig's detail
505
+ rig ps --nodes per-node, CURRENT rig (session default, local only)
506
+ rig ps --nodes --rig <name> per-node, named rig
507
+ rig ps --nodes -A fleet nodes, projected rows
508
+ rig ps --nodes -A --full complete per-node records (the only full fan-out)
509
+
510
+ -A/--all-rigs has exactly ONE meaning: the --nodes fleet widener. Bare -A
511
+ errors (all-rigs IS the default; archived history stays behind
512
+ --include-archived). The session-rig default never crosses host boundaries:
513
+ remote --nodes requires an explicit --rig or -A.
392
514
 
393
515
  Compact defaults: 'rig ps --nodes' shows a compact summary per node
394
516
  (rig, session, lifecycle, activity state, reason when attention, queue counts,
@@ -402,11 +524,10 @@ null even with --full; fetch the full recovery guidance + currentUsage from the
402
524
  single-node detail (/api/rigs/:rigId/nodes/:logicalId) or 'rig whoami'.
403
525
 
404
526
  Examples:
405
- rig ps Current rig summary (compact)
406
- rig ps -A All rigs (fleet breadth)
407
- rig ps --full Current rig, full detail
408
- rig ps --json Current rig, compact JSON
409
- rig ps -A --json All rigs, compact JSON
527
+ rig ps All active rigs, one row each + rollup
528
+ rig ps --rig <name> One rig's detail
529
+ rig ps --full All rigs, no table truncation
530
+ rig ps --json All non-archived rigs, bare JSON array
410
531
  rig ps --json --limit 20 Bounded JSON envelope
411
532
  rig ps --json --summary Aggregate-only JSON
412
533
  rig ps --json --fields rigName,status,lifecycleState
@@ -426,12 +547,16 @@ Examples:
426
547
  rig ps --nodes --running Same as --active
427
548
  rig ps --nodes --filter agentActivity.state=running
428
549
  Same as --active (the explicit form)
429
- rig ps --host vm-claude-test --nodes --json Remote host (no current-rig default)
550
+ rig ps --host vm-1 --nodes --rig <name> --json Remote host per-node (explicit target required)
551
+ rig ps --all-hosts Per-host O(rigs) rollups (AggregatedPayload JSON)
430
552
  rig ps --include-archived Include archived rigs (marked with *); hidden by default
431
553
 
432
- --rig <name> overrides the current-rig default. -A/--all-rigs disables it.
433
- --session <name> filters within the effective rig scope; use -A if the target
434
- session is in a different rig.
554
+ --rig <name> scopes to one rig. -A/--all-rigs is ONLY the --nodes fleet widener.
555
+ --session <name> filters within the effective rig scope; use --nodes -A if the
556
+ target session is in a different rig.
557
+ Multi-host fan-out (--all-hosts/--hosts) is rollup-only by default; the full
558
+ explicit ladder (--all-hosts --nodes -A, --full for complete records) fans out
559
+ per-node with hostId-stamped projected rows.
435
560
 
436
561
  --active/--running narrow to agentActivity.state=running. Cannot combine with --filter.
437
562
 
@@ -439,7 +564,8 @@ session is in a different rig.
439
564
  contextUsage.percent, contextUsage.state. Other keys are rejected.
440
565
 
441
566
  --fields accepts (rig-level): rigId, name, rigName, nodeCount, runningCount,
442
- activeCount, hasWorkCount, status, lifecycleState, uptime, latestSnapshot.
567
+ activeCount, hasWorkCount, attentionCount, status, lifecycleState, uptime,
568
+ latestSnapshot.
443
569
  --fields accepts (node-level, with --nodes): rigId, rigName, logicalId, podId,
444
570
  podNamespace, canonicalSessionName, nodeKind, runtime, sessionStatus,
445
571
  startupStatus, restoreOutcome, lifecycleState, tmuxAttachCommand,
@@ -473,20 +599,60 @@ Exit codes:
473
599
  .option("--all-hosts", "Fan out to all registered HTTP hosts (observation-only)")
474
600
  .option("--hosts <ids>", "Fan out to specific hosts (comma-separated)")
475
601
  .action(async (opts) => {
602
+ // OPR.0.4.6.MH1 FR-2: selected-host routing — explicit --host wins;
603
+ // else the persisted selection feeds the SHIPPED --host path; no
604
+ // selection = today exactly. Fan-out
605
+ // flags are their OWN explicit scope — never mixed with selection.
606
+ if (!opts.allHosts && !opts.hosts)
607
+ opts.host = resolveEffectiveHost(opts.host);
476
608
  if (opts.verbose)
477
609
  opts.full = true;
478
610
  if (opts.running)
479
611
  opts.active = true;
480
612
  const isRemote = !!(opts.host || opts.allHosts || opts.hosts);
481
- if (!opts.allRigs && !opts.rig && !isRemote) {
482
- const sessionName = readOpenRigEnv("OPENRIG_SESSION_NAME", "RIGGED_SESSION_NAME");
483
- const callerRig = sessionName ? extractRigName(sessionName) : undefined;
484
- if (callerRig)
485
- opts.rig = callerRig;
613
+ // OPR.0.4.4.21 FR-1: the rig tier is consolidated ALL-ACTIVE-RIGS by
614
+ // default (the current-rig-only default is RETIRED — it hid running
615
+ // rigs from the operator's field of view). The session-rig default
616
+ // now applies ONLY to the node tier (FR-2's scoped --nodes), and
617
+ // ONLY locally (the ladder validator enforces explicit-or-error on
618
+ // every remote path).
619
+ const sessionName = readOpenRigEnv("OPENRIG_SESSION_NAME", "RIGGED_SESSION_NAME");
620
+ const callerRig = sessionName ? extractRigName(sessionName) : undefined;
621
+ const ladderError = validatePsLadder(opts, callerRig);
622
+ if (ladderError) {
623
+ console.error(ladderError);
624
+ process.exitCode = 1;
625
+ return;
626
+ }
627
+ if (opts.nodes && !opts.allRigs && !opts.rig && !isRemote && callerRig) {
628
+ opts.rig = callerRig;
486
629
  }
487
630
  const deps = getDepsF();
631
+ // OPR.0.4.4.21 rev1-r2 fixback: the shared shaping controls
632
+ // (--active/--filter/--limit/--fields/--summary) parse + validate
633
+ // BEFORE any dispatch — local, single-host, or fan-out — so every
634
+ // path honors the same composition contract and rejections stay
635
+ // pre-HTTP on remote paths too.
636
+ // Parse shared composition controls once up front so local, single-host,
637
+ // and fan-out paths reject malformed --filter/--limit/--fields before
638
+ // any HTTP call and apply the same shaping semantics.
639
+ const controls = parsePsControls(opts);
640
+ if ("error" in controls) {
641
+ console.error(controls.error);
642
+ process.exitCode = 1;
643
+ return;
644
+ }
645
+ const { parsedFilter, limit, fields, useEnvelope } = controls;
488
646
  if (opts.allHosts || opts.hosts) {
489
- await runFanOutPs(opts, deps);
647
+ // AggregatedPayload is the closed fan-out contract (items + hosts).
648
+ // Do not add an ad-hoc summary member here; teach the per-host form.
649
+ if (opts.summary) {
650
+ console.error("rig ps --all-hosts/--hosts --summary: summary does not compose with the merged fan-out payload.\n" +
651
+ "Summarize one host: rig ps --host <id> --summary; or drop --summary for the merged AggregatedPayload.");
652
+ process.exitCode = 1;
653
+ return;
654
+ }
655
+ await runFanOutPs(opts, deps, { parsedFilter, limit, fields });
490
656
  return;
491
657
  }
492
658
  if (opts.host) {
@@ -499,73 +665,31 @@ Exit codes:
499
665
  process.exitCode = 1;
500
666
  return;
501
667
  }
502
- // Parse filter once up front so unknown keys/malformed filters surface
503
- // as exit-1 errors before any HTTP call.
504
- //
505
- // PL-019 item 1: --active is sugar for --filter agentActivity.state=running.
506
- // Combining --active with --filter is rejected (composition is
507
- // ambiguous — pick one explicit form). Parity is verified end-to-end
508
- // by the focused test: `--active` and the explicit filter must yield
509
- // identical output on the same fixture.
510
- let effectiveFilter = opts.filter;
511
- if (opts.active) {
512
- if (effectiveFilter) {
513
- console.error(`--active and --filter cannot be combined. ` +
514
- `--active is sugar for --filter agentActivity.state=running. ` +
515
- `Pick one form, or compose by upgrading to --filter directly.`);
516
- process.exitCode = 1;
517
- return;
518
- }
519
- effectiveFilter = "agentActivity.state=running";
520
- }
521
- let parsedFilter = null;
522
- if (effectiveFilter) {
523
- const result = parseFilter(effectiveFilter);
524
- if ("error" in result) {
525
- console.error(result.error);
526
- process.exitCode = 1;
527
- return;
528
- }
529
- parsedFilter = result;
530
- }
531
- const limit = opts.limit !== undefined ? Number(opts.limit) : null;
532
- if (limit !== null && (!Number.isInteger(limit) || limit < 0)) {
533
- console.error(`--limit must be a non-negative integer; got '${opts.limit}'`);
534
- process.exitCode = 1;
535
- return;
536
- }
537
- // C9a: validate --fields against the per-level allow-list before any HTTP
538
- // call, mirroring the --filter validation above. Level is determined by
539
- // --nodes; both branches downstream use the same `fields` variable, so
540
- // one up-front validation covers both paths.
541
- let fields = null;
542
- if (opts.fields !== undefined) {
543
- const fieldsLevel = opts.nodes ? "nodes" : "rig";
544
- const fieldsAllowed = fieldsLevel === "nodes" ? ALLOWED_NODE_FIELDS : ALLOWED_RIG_FIELDS;
545
- const fieldsResult = parseFields(opts.fields, fieldsAllowed, fieldsLevel);
546
- if ("error" in fieldsResult) {
547
- console.error(fieldsResult.error);
548
- process.exitCode = 1;
549
- return;
550
- }
551
- fields = fieldsResult;
552
- }
553
- const useEnvelope = parsedFilter !== null || limit !== null || fields !== null || opts.summary === true;
554
668
  const client = deps.clientFactory(getDaemonUrl(status));
555
669
  if (opts.nodes) {
556
670
  await handleNodes(client, opts, parsedFilter, limit, fields, useEnvelope);
557
671
  return;
558
672
  }
559
- const res = await client.get(psApiPath(opts));
673
+ // OPR.0.4.4.21 FR-1: ONE O(rigs) fetch including archived so the
674
+ // count line can be computed; visibility is split client-side below
675
+ // (JSON keeps today's default of excluding archived — parity).
676
+ const res = await client.get("/api/ps?includeArchived=true");
560
677
  if (res.status >= 400) {
561
678
  console.error(`Failed to fetch rig list from daemon (HTTP ${res.status}). Check daemon status with: rig status`);
562
679
  process.exitCode = 2;
563
680
  return;
564
681
  }
565
682
  const all = res.data;
683
+ // OPR.0.4.4.21 — archived visibility parity: the daemon call above
684
+ // always includes archived (for the count line); without
685
+ // --include-archived they are dropped from BOTH renders here, exactly
686
+ // as the daemon default used to do. archivedCount feeds the FR-1
687
+ // count line only.
688
+ const archivedCount = all.filter((e) => e.isArchived === true).length;
689
+ const visible = opts.includeArchived ? all : all.filter((e) => e.isArchived !== true);
566
690
  const rigScoped = opts.rig
567
- ? all.filter((e) => (e.rigName ?? e.name) === opts.rig)
568
- : all;
691
+ ? visible.filter((e) => (e.rigName ?? e.name) === opts.rig)
692
+ : visible;
569
693
  // Apply CLI-side filter (Amendment A: prefer CLI shaping).
570
694
  const filtered = parsedFilter ? applyRigFilter(rigScoped, parsedFilter) : rigScoped;
571
695
  // Summary mode short-circuits per-entry output.
@@ -608,15 +732,32 @@ Exit codes:
608
732
  if (parsedFilter) {
609
733
  console.log(`No rigs match --filter ${parsedFilter.key}=${parsedFilter.value}`);
610
734
  }
735
+ else if (archivedCount > 0 && !opts.includeArchived) {
736
+ // Proven-empty with the history pointer, never a bare "No rigs"
737
+ // while archived history exists.
738
+ console.log(`No active rigs · ${archivedCount} archived (rig ps --include-archived)`);
739
+ }
611
740
  else {
612
741
  console.log("No rigs");
613
742
  }
614
743
  return;
615
744
  }
745
+ // OPR.0.4.4.21 FR-1 (human table ONLY — JSON keeps ALL non-archived
746
+ // entries including stopped; this scope split is a STATED contract
747
+ // sentence in the help text): on the BARE default (no filter, no
748
+ // --rig, no --include-archived) stopped rigs fold into the count
749
+ // line — history is what the default drops, not field of view.
750
+ const bareDefault = !parsedFilter && !opts.rig && !opts.includeArchived;
751
+ const tableRows = bareDefault ? limited.filter((e) => e.status !== "stopped") : limited;
752
+ const stoppedCount = bareDefault ? limited.length - tableRows.length : 0;
753
+ // FR-1 display element 1: the host rollup line.
754
+ const rollupSeats = tableRows.reduce((n, e) => n + e.nodeCount, 0);
755
+ const rollupAttention = tableRows.reduce((n, e) => n + (e.attentionCount ?? 0), 0);
756
+ console.log(`${tableRows.length} rig${tableRows.length === 1 ? "" : "s"} · ${rollupSeats} seat${rollupSeats === 1 ? "" : "s"} · ${rollupAttention} need${rollupAttention === 1 ? "s" : ""} attention`);
616
757
  // Human output: apply default truncation budget unless --full.
617
- const humanList = (opts.full || limit !== null) ? limited : limited.slice(0, HUMAN_RIG_BUDGET);
618
- const humanTruncated = !opts.full && limit === null && filtered.length > HUMAN_RIG_BUDGET;
619
- const header = padRigRow("RIG", "NODES", "RUNNING", "ACTIVE", "WORK", "STATUS", "LIFECYCLE", "UPTIME", "SNAPSHOT");
758
+ const humanList = (opts.full || limit !== null) ? tableRows : tableRows.slice(0, HUMAN_RIG_BUDGET);
759
+ const humanTruncated = !opts.full && limit === null && tableRows.length > HUMAN_RIG_BUDGET;
760
+ const header = padRigRow("RIG", "NODES", "RUNNING", "ACTIVE", "WORK", "ATTN", "STATUS", "LIFECYCLE", "UPTIME", "SNAPSHOT");
620
761
  console.log(header);
621
762
  let anyArchivedShown = false;
622
763
  for (const e of humanList) {
@@ -627,11 +768,27 @@ Exit codes:
627
768
  anyArchivedShown = true;
628
769
  console.log(padRigRow(e.isArchived ? `${e.rigName ?? e.name} *` : (e.rigName ?? e.name), String(e.nodeCount), String(e.runningCount),
629
770
  // Slice 15 — "—" when daemon predates the field; honest absence.
630
- e.activeCount !== undefined ? String(e.activeCount) : "—", e.hasWorkCount !== undefined ? String(e.hasWorkCount) : "—", e.status, abbrevRigLifecycle(e.lifecycleState), e.uptime ?? "—", e.latestSnapshot ?? "—"));
771
+ e.activeCount !== undefined ? String(e.activeCount) : "—", e.hasWorkCount !== undefined ? String(e.hasWorkCount) : "—",
772
+ // OPR.0.4.4.21 — the founder's field-of-view anchor: where is
773
+ // something that might concern me. "—" = daemon predates the field.
774
+ e.attentionCount !== undefined ? (e.attentionCount > 0 ? `▲${e.attentionCount}` : "0") : "—", e.status, abbrevRigLifecycle(e.lifecycleState), e.uptime ?? "—", e.latestSnapshot ?? "—"));
631
775
  }
632
776
  if (anyArchivedShown) {
633
777
  console.log("* = archived (hidden from the default view; shown via --include-archived). Reverse with: rig unarchive <rig>");
634
778
  }
779
+ // FR-1 display element 2: history as ONE count line, never rows.
780
+ if (stoppedCount > 0 || (!opts.includeArchived && archivedCount > 0)) {
781
+ const parts = [];
782
+ if (stoppedCount > 0)
783
+ parts.push(`${stoppedCount} stopped (rig ps --filter status=stopped)`);
784
+ if (!opts.includeArchived && archivedCount > 0)
785
+ parts.push(`${archivedCount} archived (rig ps --include-archived)`);
786
+ console.log(`not shown: ${parts.join(" · ")}`);
787
+ }
788
+ // FR-1 display element 3: the affordance footer — the drill ladder.
789
+ if (bareDefault) {
790
+ console.log("drill: rig ps --rig <name> (one rig) · rig ps --nodes --rig <name> (its seats) · --full (everything)");
791
+ }
635
792
  if (humanTruncated) {
636
793
  const remaining = filtered.length - HUMAN_RIG_BUDGET;
637
794
  console.log(`... and ${remaining} more rig${remaining === 1 ? "" : "s"} (truncated at ${HUMAN_RIG_BUDGET}).`);
@@ -666,7 +823,12 @@ async function handleNodes(client, opts, parsedFilter, limit, fields, useEnvelop
666
823
  console.error(`Warning: failed to fetch nodes for rig "${rig.rigName ?? rig.name}" (HTTP ${nodesRes.status}). List rigs with: rig ps`);
667
824
  continue;
668
825
  }
669
- allNodes.push(...nodesRes.data);
826
+ const parentRigName = rig.rigName ?? rig.name;
827
+ allNodes.push(...nodesRes.data.map((n) => ({
828
+ ...n,
829
+ rigId: n.rigId ?? rig.rigId,
830
+ rigName: n.rigName ?? parentRigName,
831
+ })));
670
832
  }
671
833
  let narrowed = allNodes;
672
834
  if (opts.rig)
@@ -769,7 +931,7 @@ function truncate(s, max) {
769
931
  function fitCell(value, width) {
770
932
  return truncate(value, width).padEnd(width);
771
933
  }
772
- function padRigRow(rig, nodes, running, active, work, status, lifecycle, uptime, snapshot) {
934
+ function padRigRow(rig, nodes, running, active, work, attn, status, lifecycle, uptime, snapshot) {
773
935
  return [
774
936
  fitCell(rig, 24),
775
937
  fitCell(nodes, 7),
@@ -780,6 +942,8 @@ function padRigRow(rig, nodes, running, active, work, status, lifecycle, uptime,
780
942
  // operators see which dimension differs at a glance.
781
943
  fitCell(active, 8),
782
944
  fitCell(work, 6),
945
+ // OPR.0.4.4.21 — ATTN: seats needing attention (the field-of-view anchor).
946
+ fitCell(attn, 6),
783
947
  fitCell(status, 10),
784
948
  fitCell(lifecycle, 11),
785
949
  fitCell(uptime, 11),
@@ -878,7 +1042,10 @@ async function runCrossHostPs(hostId, opts, deps) {
878
1042
  // OPR.0.4.0.34: forward the breadth flag so `--host h -A` keeps all-rigs
879
1043
  // breadth across the hop (the current-rig default is local-only and never
880
1044
  // applied to a remote call, but an explicit -A must still reach the remote).
881
- if (opts.allRigs)
1045
+ // OPR.0.4.4.21 FR-3: -A is legal only alongside --nodes (the validator
1046
+ // already rejected the bare form before any dispatch; this guard keeps
1047
+ // the reconstructed remote argv obeying the same grammar).
1048
+ if (opts.allRigs && opts.nodes)
882
1049
  argv.push("--all-rigs");
883
1050
  if (opts.limit !== undefined)
884
1051
  argv.push("--limit", opts.limit);
@@ -932,46 +1099,15 @@ async function runHttpPs(host, opts, deps) {
932
1099
  process.exitCode = 1;
933
1100
  return;
934
1101
  }
935
- let effectiveFilter = opts.filter;
936
- if (opts.active) {
937
- if (effectiveFilter) {
938
- console.error("--active and --filter cannot be combined.");
939
- process.exitCode = 1;
940
- return;
941
- }
942
- effectiveFilter = "agentActivity.state=running";
943
- }
944
- let parsedFilter = null;
945
- if (effectiveFilter) {
946
- const result = parseFilter(effectiveFilter);
947
- if ("error" in result) {
948
- console.error(result.error);
949
- process.exitCode = 1;
950
- return;
951
- }
952
- parsedFilter = result;
953
- }
954
- const limit = opts.limit !== undefined ? Number(opts.limit) : null;
955
- if (limit !== null && (!Number.isInteger(limit) || limit < 0)) {
956
- console.error(`--limit must be a non-negative integer; got '${opts.limit}'`);
1102
+ const controls = parsePsControls(opts);
1103
+ if ("error" in controls) {
1104
+ console.error(controls.error);
957
1105
  process.exitCode = 1;
958
1106
  return;
959
1107
  }
960
- let fields = null;
961
- if (opts.fields !== undefined) {
962
- const fieldsLevel = opts.nodes ? "nodes" : "rig";
963
- const fieldsAllowed = fieldsLevel === "nodes" ? ALLOWED_NODE_FIELDS : ALLOWED_RIG_FIELDS;
964
- const fieldsResult = parseFields(opts.fields, fieldsAllowed, fieldsLevel);
965
- if ("error" in fieldsResult) {
966
- console.error(fieldsResult.error);
967
- process.exitCode = 1;
968
- return;
969
- }
970
- fields = fieldsResult;
971
- }
1108
+ const { parsedFilter, limit, fields, useEnvelope } = controls;
972
1109
  const client = deps.clientFactory(host.url);
973
1110
  const headers = buildRemoteHeaders(bearerResult.token);
974
- const useEnvelope = parsedFilter !== null || limit !== null || fields !== null || opts.summary === true;
975
1111
  try {
976
1112
  if (opts.nodes) {
977
1113
  await handleNodes(client, opts, parsedFilter, limit, fields, useEnvelope, headers);
@@ -1020,7 +1156,22 @@ async function runHttpPs(host, opts, deps) {
1020
1156
  process.exitCode = 1;
1021
1157
  }
1022
1158
  }
1023
- async function runFanOutPs(opts, deps) {
1159
+ /** OPR.0.4.4.21 FR-5 adapter to the intra-P4 shared contract
1160
+ * (fanout-contract.ts, slice 15 first-lander at 0ecd329b; the closed
1161
+ * status enum is THE contract, failedStep rides as additive detail). */
1162
+ function toPerHostStatus(r) {
1163
+ const status = r.ok ? "ok"
1164
+ : r.failedStep === "unsupported-transport" ? "unsupported-transport"
1165
+ : r.failedStep === "permission-gate" ? "auth-failed"
1166
+ : "unreachable";
1167
+ const out = { hostId: r.host, status };
1168
+ if (r.error)
1169
+ out.error = r.error;
1170
+ if (!r.ok && r.failedStep !== "unsupported-transport")
1171
+ out.failedStep = r.failedStep;
1172
+ return out;
1173
+ }
1174
+ async function runFanOutPs(opts, deps, shaping) {
1024
1175
  const loader = deps.hostRegistryLoader ?? loadHostRegistry;
1025
1176
  const registry = loader();
1026
1177
  if (!registry.ok) {
@@ -1040,14 +1191,20 @@ async function runFanOutPs(opts, deps) {
1040
1191
  }
1041
1192
  }
1042
1193
  else {
1043
- targetIds = allHosts.filter((h) => h.transport === "http").map((h) => h.id);
1194
+ // OPR.0.4.4.21 fixback (qa1 F1): target EVERY declared host non-HTTP
1195
+ // hosts must appear in hosts[] as unsupported-transport (R15-2), never
1196
+ // be silently absent. The per-host leg classifies transport.
1197
+ targetIds = allHosts.map((h) => h.id);
1044
1198
  }
1045
1199
  const results = await Promise.all(targetIds.map(async (id) => {
1046
1200
  const host = allHosts.find((h) => h.id === id);
1047
1201
  if (!host)
1048
1202
  return { host: id, ok: false, failedStep: "remote-daemon-unreachable", error: `unknown host ${id}` };
1049
1203
  if (host.transport !== "http") {
1050
- return { host: id, ok: false, failedStep: "remote-command-failed", error: `host ${id} uses transport ${host.transport}; HTTP fan-out requires transport: http` };
1204
+ // R15-2 (shared contract): an SSH-declared host is a STRUCTURED
1205
+ // unsupported-transport status — never prose-only, never silently
1206
+ // thinner output.
1207
+ return { host: id, ok: false, failedStep: "unsupported-transport", error: `host ${id} uses transport ${host.transport}; HTTP fan-out requires transport: http` };
1051
1208
  }
1052
1209
  const httpHost = host;
1053
1210
  const bearerResult = resolveRemoteBearer(httpHost);
@@ -1055,16 +1212,35 @@ async function runFanOutPs(opts, deps) {
1055
1212
  return { host: id, ok: false, failedStep: bearerResult.failedStep, error: bearerResult.error };
1056
1213
  }
1057
1214
  const client = deps.clientFactory(httpHost.url);
1215
+ const headers = buildRemoteHeaders(bearerResult.token);
1058
1216
  try {
1059
1217
  const psQuery = opts.includeArchived ? "?includeArchived=true" : "";
1060
- const res = await client.get(`/api/ps${psQuery}`, {
1061
- headers: buildRemoteHeaders(bearerResult.token),
1062
- });
1218
+ const res = await client.get(`/api/ps${psQuery}`, { headers });
1063
1219
  const failedStep = classifyHttpFailedStep(res.status);
1064
1220
  if (failedStep !== "none") {
1065
1221
  return { host: id, ok: false, failedStep, error: `HTTP ${res.status}` };
1066
1222
  }
1067
- return { host: id, ok: true, failedStep: "none", data: res.data };
1223
+ if (!opts.nodes) {
1224
+ return { host: id, ok: true, failedStep: "none", data: res.data };
1225
+ }
1226
+ // OPR.0.4.4.21 FR-5 — the full explicit ladder (--nodes -A, --full
1227
+ // for complete records): per-host node fan-out, projected unless
1228
+ // --full (the invariant's last rung; validated as -A-only upstream).
1229
+ const rigs = Array.isArray(res.data) ? res.data : [];
1230
+ const nodes = [];
1231
+ for (const rig of rigs) {
1232
+ const nodesRes = await client.get(`/api/rigs/${encodeURIComponent(rig.rigId)}/nodes`, { headers });
1233
+ if (nodesRes.status >= 400) {
1234
+ return { host: id, ok: false, failedStep: classifyHttpFailedStep(nodesRes.status), error: `HTTP ${nodesRes.status} fetching nodes for rig ${rig.rigName ?? rig.name}` };
1235
+ }
1236
+ const parentRigName = rig.rigName ?? rig.name;
1237
+ nodes.push(...nodesRes.data.map((n) => ({
1238
+ ...n,
1239
+ rigId: n.rigId ?? rig.rigId,
1240
+ rigName: n.rigName ?? parentRigName,
1241
+ })));
1242
+ }
1243
+ return { host: id, ok: true, failedStep: "none", data: nodes };
1068
1244
  }
1069
1245
  catch (err) {
1070
1246
  return { host: id, ok: false, failedStep: classifyHttpError(err), error: err.message };
@@ -1072,7 +1248,49 @@ async function runFanOutPs(opts, deps) {
1072
1248
  }));
1073
1249
  const hasFailure = results.some((r) => !r.ok);
1074
1250
  if (opts.json) {
1075
- console.log(JSON.stringify({ hosts: results }));
1251
+ // OPR.0.4.4.21 FR-5 — the intra-P4 shared payload (ONE contract with
1252
+ // slice 15): items = each host's rows stamped with their origin hostId
1253
+ // (flat-mergeable; origin never positional), hosts = the per-host
1254
+ // structured status array. EVERY targeted host appears in hosts[] —
1255
+ // ok or not (no silent thinning).
1256
+ const rawItems = results.flatMap((r) => r.ok && Array.isArray(r.data)
1257
+ ? r.data.map((row) => ({ ...row, hostId: r.host }))
1258
+ : []);
1259
+ const hostStatuses = results.map(toPerHostStatus);
1260
+ let narrowed = rawItems;
1261
+ if (opts.rig)
1262
+ narrowed = narrowed.filter((e) => (e.rigName ?? e.name) === opts.rig);
1263
+ if (opts.nodes && opts.session)
1264
+ narrowed = narrowed.filter((n) => n.canonicalSessionName === opts.session);
1265
+ const filtered = shaping.parsedFilter
1266
+ ? opts.nodes
1267
+ ? applyNodeFilter(narrowed, shaping.parsedFilter)
1268
+ : applyRigFilter(narrowed, shaping.parsedFilter)
1269
+ : narrowed;
1270
+ let items;
1271
+ if (opts.summary) {
1272
+ items = [
1273
+ opts.nodes
1274
+ ? summarizeNodes(filtered)
1275
+ : summarizeRigs(filtered),
1276
+ ];
1277
+ }
1278
+ else {
1279
+ const limited = shaping.limit !== null ? filtered.slice(0, shaping.limit) : filtered;
1280
+ items = shaping.fields
1281
+ ? selectFanOutFields(limited, shaping.fields)
1282
+ : opts.nodes && !opts.full
1283
+ ? compactNodeProjection(limited).map((row, i) => ({
1284
+ ...row,
1285
+ hostId: limited[i]?.hostId,
1286
+ }))
1287
+ : limited;
1288
+ }
1289
+ const payload = {
1290
+ items,
1291
+ hosts: hostStatuses,
1292
+ };
1293
+ console.log(JSON.stringify(payload));
1076
1294
  }
1077
1295
  else {
1078
1296
  for (const r of results) {