@repo-os/repoos 0.5.50 → 0.5.52

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 (206) hide show
  1. package/README.md +16 -0
  2. package/dist/.build-info.json +2 -2
  3. package/dist/.build-stamp.json +1 -1
  4. package/dist/cli/index.js +7 -1
  5. package/dist/commands/certify.d.ts +10 -0
  6. package/dist/commands/certify.js +198 -0
  7. package/dist/commands/doctor.d.ts +17 -1
  8. package/dist/commands/doctor.js +121 -4
  9. package/dist/commands/service.js +2 -2
  10. package/dist/commands/tasks.d.ts +2 -2
  11. package/dist/commands/tasks.js +16 -5
  12. package/dist/core/agent-compatibility.d.ts +46 -0
  13. package/dist/core/agent-compatibility.js +329 -0
  14. package/dist/core/agent-compatibility.json +179 -0
  15. package/dist/core/agent-contract.d.ts +34 -0
  16. package/dist/core/agent-contract.js +895 -0
  17. package/dist/core/auth-store.d.ts +10 -0
  18. package/dist/core/auth-store.js +120 -0
  19. package/dist/core/canary.d.ts +1 -1
  20. package/dist/core/canary.js +1 -1
  21. package/dist/core/config.js +82 -2
  22. package/dist/core/detect-cache.d.ts +8 -0
  23. package/dist/core/detect-cache.js +30 -0
  24. package/dist/core/detect.d.ts +57 -6
  25. package/dist/core/detect.js +136 -28
  26. package/dist/core/doctor.d.ts +15 -0
  27. package/dist/core/doctor.js +79 -3
  28. package/dist/core/git.d.ts +7 -0
  29. package/dist/core/git.js +18 -8
  30. package/dist/core/hub-capabilities.d.ts +38 -0
  31. package/dist/core/hub-capabilities.js +66 -0
  32. package/dist/core/hub-task-search.d.ts +22 -0
  33. package/dist/core/hub-task-search.js +62 -0
  34. package/dist/core/repoos.d.ts +2 -0
  35. package/dist/core/repoos.js +2 -0
  36. package/dist/core/review-verdict.d.ts +5 -4
  37. package/dist/core/review-verdict.js +21 -8
  38. package/dist/core/review-verdict.test.js +6 -0
  39. package/dist/core/stories.d.ts +73 -0
  40. package/dist/core/stories.js +129 -0
  41. package/dist/core/story-definition-files.d.ts +49 -0
  42. package/dist/core/story-definition-files.js +252 -0
  43. package/dist/core/story-definitions.d.ts +3 -0
  44. package/dist/core/story-definitions.js +3 -0
  45. package/dist/core/story-display.d.ts +20 -0
  46. package/dist/core/story-display.js +55 -0
  47. package/dist/core/task.js +7 -0
  48. package/dist/core/types.d.ts +61 -2
  49. package/dist/server/agents.d.ts +5 -4
  50. package/dist/server/agents.js +47 -65
  51. package/dist/server/freeform.d.ts +2 -0
  52. package/dist/server/freeform.js +1 -0
  53. package/dist/server/integration-orchestrator.js +174 -139
  54. package/dist/server/live-index.d.ts +16 -1
  55. package/dist/server/live-index.js +20 -1
  56. package/dist/server/remote-validation.d.ts +47 -10
  57. package/dist/server/remote-validation.js +202 -11
  58. package/dist/server/review.d.ts +2 -2
  59. package/dist/server/review.js +23 -10
  60. package/dist/server/routes/agents.d.ts +18 -0
  61. package/dist/server/routes/agents.js +53 -10
  62. package/dist/server/routes/hub.d.ts +12 -0
  63. package/dist/server/routes/hub.js +234 -0
  64. package/dist/server/routes/index.d.ts +2 -0
  65. package/dist/server/routes/index.js +2 -0
  66. package/dist/server/routes/service.js +2 -2
  67. package/dist/server/routes/stories.d.ts +12 -0
  68. package/dist/server/routes/stories.js +66 -0
  69. package/dist/server/routes/tasks.js +2 -0
  70. package/dist/server/serve-reaper.d.ts +1 -1
  71. package/dist/server/serve-reaper.js +16 -2
  72. package/dist/server/server.d.ts +8 -0
  73. package/dist/server/server.js +158 -27
  74. package/dist/server/story-pm.d.ts +20 -0
  75. package/dist/server/story-pm.js +114 -0
  76. package/dist/server/test-run.d.ts +9 -0
  77. package/dist/server/test-run.js +33 -23
  78. package/dist/server/test-run.test.d.ts +1 -0
  79. package/dist/server/test-run.test.js +28 -0
  80. package/dist/server/watcher.d.ts +1 -0
  81. package/dist/server/watcher.js +21 -4
  82. package/dist/server/write.d.ts +2 -0
  83. package/dist/server/write.js +9 -0
  84. package/dist/ui/assets/AgentsView-UghV_I0u.js +1 -0
  85. package/dist/ui/assets/ChecksView-C0TtYC-4.css +1 -0
  86. package/dist/ui/assets/ChecksView-CE9_UWEH.js +0 -0
  87. package/dist/ui/assets/ContextView-C3cJribS.js +4 -0
  88. package/dist/ui/assets/DashboardView-DydNm09c.js +1 -0
  89. package/dist/ui/assets/{DashboardView-CRdYYcWz.css → DashboardView-ZvEsCIs4.css} +1 -1
  90. package/dist/ui/assets/DeploymentsView-DVMkUs04.js +1 -0
  91. package/dist/ui/assets/{DiffView-C3HYdj7S.js → DiffView-CCOUztfU.js} +2 -2
  92. package/dist/ui/assets/InputsView-CgH2DwWm.css +1 -0
  93. package/dist/ui/assets/InputsView-uzRKFx_8.js +1 -0
  94. package/dist/ui/assets/{LoginView-BjD2carP.js → LoginView-CV_1xAvv.js} +1 -1
  95. package/dist/ui/assets/ReleasesView-CMTPaJGR.js +3 -0
  96. package/dist/ui/assets/ReleasesView-DaX_TFoT.css +1 -0
  97. package/dist/ui/assets/SettingsView-3Y2d6VYS.js +4 -0
  98. package/dist/ui/assets/StoriesView-DGnU5Cy9.js +1 -0
  99. package/dist/ui/assets/StoriesView-DTqtvuk_.css +1 -0
  100. package/dist/ui/assets/TaskCard-hX9bZtBs.js +1 -0
  101. package/dist/ui/assets/WorkView-DpL4RTSC.js +2 -0
  102. package/dist/ui/assets/{abnfDiagram-VCTEODGH-BFGqju3J.js → abnfDiagram-VCTEODGH-CTfjwe9G.js} +1 -1
  103. package/dist/ui/assets/architecture-7GRP2DOG-iLDzG2hD.js +1 -0
  104. package/dist/ui/assets/{architectureDiagram-5GKGNRK7-CZhiMeBk.js → architectureDiagram-5GKGNRK7-CVfIBdXM.js} +1 -1
  105. package/dist/ui/assets/{blockDiagram-I7D4REHJ-B911Uy94.js → blockDiagram-I7D4REHJ-DHrovPE1.js} +1 -1
  106. package/dist/ui/assets/{c4Diagram-7LVT6UL2-CaAFewRn.js → c4Diagram-7LVT6UL2-D1_IKyVU.js} +1 -1
  107. package/dist/ui/assets/channel-C2SsuvKM.js +1 -0
  108. package/dist/ui/assets/{chunk-4HAMMTFA-DXh4eDR_.js → chunk-4HAMMTFA-BQK2Qs9d.js} +1 -1
  109. package/dist/ui/assets/{chunk-75Z2AOVW-Lw_aAEJj.js → chunk-75Z2AOVW-C560CV9I.js} +1 -1
  110. package/dist/ui/assets/{chunk-DU6HZSFF-xk3L0f7B.js → chunk-DU6HZSFF-BX9aRA1h.js} +1 -1
  111. package/dist/ui/assets/{chunk-F27PBJKO-Bpl_CvRh.js → chunk-F27PBJKO-MId0AvWB.js} +1 -1
  112. package/dist/ui/assets/{chunk-GMAD6QVW-BLy3zfAa.js → chunk-GMAD6QVW-B8uV52pK.js} +1 -1
  113. package/dist/ui/assets/{chunk-GVQU2GXP-I3QAn4hA.js → chunk-GVQU2GXP-BHRWhJBs.js} +1 -1
  114. package/dist/ui/assets/{chunk-IMKFNOWR-BkvAYHDv.js → chunk-IMKFNOWR-C2p26tmJ.js} +1 -1
  115. package/dist/ui/assets/{chunk-L3NEJ4N5-B3_3ZyvC.js → chunk-L3NEJ4N5-CiNIjzhG.js} +1 -1
  116. package/dist/ui/assets/{chunk-OSK3NFVY-CSPfQDZp.js → chunk-OSK3NFVY-DOZ8UOk-.js} +1 -1
  117. package/dist/ui/assets/{chunk-P2QGCYS3-DDuNAzPy.js → chunk-P2QGCYS3-CWkpd0sS.js} +1 -1
  118. package/dist/ui/assets/{chunk-POPQ4Y6H-CWqiokbE.js → chunk-POPQ4Y6H-C_jAEIPq.js} +1 -1
  119. package/dist/ui/assets/{chunk-PWAF6VOD-Bh7FA2-4.js → chunk-PWAF6VOD-DlV-Z1d6.js} +1 -1
  120. package/dist/ui/assets/{chunk-SHT3W25Y-COKMQSf1.js → chunk-SHT3W25Y-CDcQrQRH.js} +1 -1
  121. package/dist/ui/assets/{chunk-SVP7TREG-CvMd9Zj2.js → chunk-SVP7TREG-CXMcWUhi.js} +1 -1
  122. package/dist/ui/assets/{chunk-TICWLB2K-aL9gwVQB.js → chunk-TICWLB2K-C9NkrBRa.js} +1 -1
  123. package/dist/ui/assets/classDiagram-ZZMXUADV-DOc-KWik.js +1 -0
  124. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-DOc-KWik.js +1 -0
  125. package/dist/ui/assets/{cynefin-OW5HDTMX-zQf3P8pH.js → cynefin-OW5HDTMX-BOREGtlU.js} +1 -1
  126. package/dist/ui/assets/{cynefinDiagram-5FMLGOSQ-CfNzmRAi.js → cynefinDiagram-5FMLGOSQ-B4ry75uw.js} +1 -1
  127. package/dist/ui/assets/{dagre-GXQ25YYZ-CDheq0_R.js → dagre-GXQ25YYZ-DaFuaEbQ.js} +1 -1
  128. package/dist/ui/assets/{diagram-S7CK7UJ4-BrIlEImS.js → diagram-S7CK7UJ4-CWKov5PL.js} +1 -1
  129. package/dist/ui/assets/{diagram-UQ7AKVKN-DLOiVmxh.js → diagram-UQ7AKVKN-BIaDBoBe.js} +1 -1
  130. package/dist/ui/assets/{diagram-VSXAHHWV-CxppTre6.js → diagram-VSXAHHWV-BjTKaekf.js} +1 -1
  131. package/dist/ui/assets/{diagram-VX7I27RA-CBdgeQl6.js → diagram-VX7I27RA-Yx3scpQA.js} +1 -1
  132. package/dist/ui/assets/{diagram-Z3DM3KII-PpuVwayA.js → diagram-Z3DM3KII-Zj02SBoH.js} +1 -1
  133. package/dist/ui/assets/{ebnfDiagram-PWID7BFC-BLVfeyML.js → ebnfDiagram-PWID7BFC-0YAqIwpj.js} +1 -1
  134. package/dist/ui/assets/{erDiagram-RLTQ6QDP--wKoyFyZ.js → erDiagram-RLTQ6QDP-D1qzM_C2.js} +1 -1
  135. package/dist/ui/assets/eventmodeling-NTZA5JFV-DoMudewO.js +1 -0
  136. package/dist/ui/assets/flowDiagram-HODETNUW-COa-0qtC.js +1 -0
  137. package/dist/ui/assets/{ganttDiagram-EL5Y4UJY-DrTipQUC.js → ganttDiagram-EL5Y4UJY-BfFGqNAR.js} +1 -1
  138. package/dist/ui/assets/{gitGraph-4MIJSDKK-DAsPgCmr.js → gitGraph-4MIJSDKK-C8Hio8mK.js} +1 -1
  139. package/dist/ui/assets/{gitGraphDiagram-WWUBYQGX-BboA9zPg.js → gitGraphDiagram-WWUBYQGX-zDzdEhVR.js} +1 -1
  140. package/dist/ui/assets/index-CxZVHdeX.js +35 -0
  141. package/dist/ui/assets/index-DCiwKRGz.css +1 -0
  142. package/dist/ui/assets/{info-A6RAGUB7-DBoJACXH.js → info-A6RAGUB7-Co-frmaH.js} +1 -1
  143. package/dist/ui/assets/{infoDiagram-27XIBGKW-HmgR08Yy.js → infoDiagram-27XIBGKW-C8vJrt_c.js} +1 -1
  144. package/dist/ui/assets/{ishikawaDiagram-5VMMS53U-B4MzQwJc.js → ishikawaDiagram-5VMMS53U-BGO19EHJ.js} +1 -1
  145. package/dist/ui/assets/{journeyDiagram-3NMN7TZE-BvAMPv1w.js → journeyDiagram-3NMN7TZE-DduoU3Je.js} +1 -1
  146. package/dist/ui/assets/{kanban-definition-UXKFOSKX-B6y-zirR.js → kanban-definition-UXKFOSKX-D7pp8Jfx.js} +1 -1
  147. package/dist/ui/assets/{line-F8_u2Xou.js → line-un3qDwwl.js} +1 -1
  148. package/dist/ui/assets/{mermaid-parser.core-BsnCmkcV.js → mermaid-parser.core-BbfKCEpr.js} +3 -3
  149. package/dist/ui/assets/{mermaid.core-Xxe8xk1i.js → mermaid.core-BN7qhUmq.js} +4 -4
  150. package/dist/ui/assets/{mindmap-definition-YA3MSWOX-Bh1Ybhl5.js → mindmap-definition-YA3MSWOX-BYD5kmA5.js} +1 -1
  151. package/dist/ui/assets/{packet-AYTQ26CC-ZgwPjY4X.js → packet-AYTQ26CC-C4FJPnFC.js} +1 -1
  152. package/dist/ui/assets/{pegDiagram-XKGWAZYB-DrMCDNF5.js → pegDiagram-XKGWAZYB-DsBi7Fms.js} +1 -1
  153. package/dist/ui/assets/{pie-WAS4IAKB-DBrPfFPp.js → pie-WAS4IAKB-C79YZGPK.js} +1 -1
  154. package/dist/ui/assets/{pieDiagram-E7YTZNPT-bqsPJyZ5.js → pieDiagram-E7YTZNPT-BkOWAtjO.js} +1 -1
  155. package/dist/ui/assets/{quadrantDiagram-AXDQQJYC-x6IUxAPD.js → quadrantDiagram-AXDQQJYC-4cKZyntK.js} +1 -1
  156. package/dist/ui/assets/{radar-RG4KPBEZ-C4RwOnXH.js → radar-RG4KPBEZ-BRRdMOI4.js} +1 -1
  157. package/dist/ui/assets/{railroad-74A4TZTK-B5C8M-MW.js → railroad-74A4TZTK-Bbhl18lT.js} +1 -1
  158. package/dist/ui/assets/railroad-abnf-HS5TGJTU-DP10zylu.js +1 -0
  159. package/dist/ui/assets/railroad-ebnf-LZEXJU2U-CD0qyNXa.js +1 -0
  160. package/dist/ui/assets/railroad-peg-WCYAUIDC-B4QvCxtr.js +1 -0
  161. package/dist/ui/assets/{railroadDiagram-O6MQD6OU-Dzch68ki.js → railroadDiagram-O6MQD6OU-Bbg60dv2.js} +1 -1
  162. package/dist/ui/assets/{requirementDiagram-BXWQKSXE-C4GbHihu.js → requirementDiagram-BXWQKSXE-DoLwPzhb.js} +1 -1
  163. package/dist/ui/assets/{sankeyDiagram-P5KCCOFB-CU3I4C7t.js → sankeyDiagram-P5KCCOFB-BVBS_VZc.js} +1 -1
  164. package/dist/ui/assets/{sequenceDiagram-WJ2MYXX4-BsIlljR1.js → sequenceDiagram-WJ2MYXX4-BACpdW4n.js} +1 -1
  165. package/dist/ui/assets/{stateDiagram-D77RDMKH-3U3kk2zw.js → stateDiagram-D77RDMKH-DlGZE9N1.js} +1 -1
  166. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BAXOtgDm.js +1 -0
  167. package/dist/ui/assets/{swimlanes-42K2YHIH-B0nfmDPN.js → swimlanes-42K2YHIH-DLQ7Vteo.js} +1 -1
  168. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-BBsmj1pm.js +8 -0
  169. package/dist/ui/assets/{timeline-definition-24CTP7MA-QX2EZcsZ.js → timeline-definition-24CTP7MA-b99HY5j-.js} +1 -1
  170. package/dist/ui/assets/{treeView-Q6P3EWNA-ZEpxdDTl.js → treeView-Q6P3EWNA-BKXQAE6F.js} +1 -1
  171. package/dist/ui/assets/{treemap-WGGIJYW6-B91l9Icu.js → treemap-WGGIJYW6-CZj1ym9X.js} +1 -1
  172. package/dist/ui/assets/vendor-ui-Cke7Wpgg.js +3 -0
  173. package/dist/ui/assets/{vennDiagram-4TSXK5OY-3VORL03z.js → vennDiagram-4TSXK5OY-Syj4tlui.js} +1 -1
  174. package/dist/ui/assets/{wardley-WFR3VGLG-DGVR5lOB.js → wardley-WFR3VGLG-W_snBoVU.js} +1 -1
  175. package/dist/ui/assets/{wardleyDiagram-VM6X3IG4-DcSk5QFM.js → wardleyDiagram-VM6X3IG4-BnpA19Oz.js} +1 -1
  176. package/dist/ui/assets/{xychartDiagram-S5SC5T6Z-B0xjQS8L.js → xychartDiagram-S5SC5T6Z-g474RiA-.js} +1 -1
  177. package/dist/ui/index.html +3 -4
  178. package/dist/ui/sw.js +2 -2
  179. package/package.json +2 -2
  180. package/dist/ui/assets/AgentsView-kzYSn-dX.js +0 -1
  181. package/dist/ui/assets/ChecksView-BYIszmxn.js +0 -1
  182. package/dist/ui/assets/ChecksView-D79umAfM.css +0 -1
  183. package/dist/ui/assets/ContextView-CDHjupZ9.js +0 -4
  184. package/dist/ui/assets/DashboardView-CDIxxMbH.js +0 -1
  185. package/dist/ui/assets/DeploymentsView-jcE87eqc.js +0 -1
  186. package/dist/ui/assets/InputsView-B_NUIuXr.js +0 -1
  187. package/dist/ui/assets/InputsView-oTB_RUkL.css +0 -1
  188. package/dist/ui/assets/ReleasesView-C-2JFAqC.js +0 -3
  189. package/dist/ui/assets/ReleasesView-DMhF7OTi.css +0 -1
  190. package/dist/ui/assets/SettingsView-CaloQYvQ.js +0 -4
  191. package/dist/ui/assets/WorkView-CbqXqHFs.js +0 -2
  192. package/dist/ui/assets/architecture-7GRP2DOG-B4C2xWE4.js +0 -1
  193. package/dist/ui/assets/button-ywbZCzIW.js +0 -1
  194. package/dist/ui/assets/channel-DJ4Og_iH.js +0 -1
  195. package/dist/ui/assets/classDiagram-ZZMXUADV-5hxmdbcH.js +0 -1
  196. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-5hxmdbcH.js +0 -1
  197. package/dist/ui/assets/eventmodeling-NTZA5JFV-CrYsvllj.js +0 -1
  198. package/dist/ui/assets/flowDiagram-HODETNUW-C7Br4ITm.js +0 -1
  199. package/dist/ui/assets/index-BriWELa8.js +0 -27
  200. package/dist/ui/assets/index-RUa0QB2o.css +0 -1
  201. package/dist/ui/assets/railroad-abnf-HS5TGJTU-xuaYNYsa.js +0 -1
  202. package/dist/ui/assets/railroad-ebnf-LZEXJU2U-D-wtYSuE.js +0 -1
  203. package/dist/ui/assets/railroad-peg-WCYAUIDC-BEUNsbNC.js +0 -1
  204. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-1AQXnlXU.js +0 -1
  205. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-CBW88sps.js +0 -8
  206. package/dist/ui/assets/vendor-ui-C4DmZ9GE.js +0 -3
package/README.md CHANGED
@@ -296,6 +296,22 @@ roles alongside the engineer agent. Freeform task creation sends a description
296
296
  through the PM agent for structured drafting. All agent capability is local —
297
297
  no API tokens leave your machine unless you configure them.
298
298
 
299
+ ## RepoOS Hub for macOS
300
+
301
+ A native Mac app (macOS 13+; sessions persist across relaunches on macOS 14+)
302
+ that keeps tabs on all your RepoOS servers from
303
+ one window: pin tasks across servers, see live attention counts in the sidebar
304
+ and Dock badge, and jump between servers and tasks with Cmd-K. Each server
305
+ loads in its own isolated WebKit session — sessions are never shared between
306
+ servers, and server pages get no bridge into your files or Keychain. Local
307
+ loopback servers need zero setup; remote servers use short-lived, revocable
308
+ capability tokens (created over HTTPS on the server, stored in the Keychain)
309
+ for their attention and search endpoints.
310
+
311
+ Download the latest [RepoOS Hub DMG](https://github.com/repo-os/repoos/releases/latest/download/RepoOSHub.dmg),
312
+ or browse [GitHub Releases](https://github.com/repo-os/repoos/releases). Setup,
313
+ pairing, and limitation details are in the [Hub guide](https://docs.repoos.org/macos-hub).
314
+
299
315
  ## Roadmap
300
316
 
301
317
  - **Stage 1 — parser + index + CLI** ✅
@@ -1,4 +1,4 @@
1
1
  {
2
- "hash": "f24758813ae7cee389c4a5256fd833c00e64a310a08a11ed6807f1e47cd49919",
3
- "version": "0.5.50"
2
+ "hash": "c59ba0faf030004be937d5bd9fb28afc6fdd9156857ae68454cba1c959f0f979",
3
+ "version": "0.5.52"
4
4
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "generatedAt": "2026-09-20T14:57:13.641Z"
2
+ "generatedAt": "2026-09-23T08:36:16.981Z"
3
3
  }
package/dist/cli/index.js CHANGED
@@ -15,6 +15,7 @@ import { cmdUpgrade } from "../commands/upgrade.js";
15
15
  import { cmdUninstall } from "../commands/uninstall.js";
16
16
  import { cmdStatus } from "../commands/status.js";
17
17
  import { cmdDoctor } from "../commands/doctor.js";
18
+ import { cmdCertify } from "../commands/certify.js";
18
19
  import { cmdSupport } from "../commands/support.js";
19
20
  import { cmdService } from "../commands/service.js";
20
21
  import { checkBuild } from "../core/build.js";
@@ -91,7 +92,8 @@ function help() {
91
92
  cmdRow("init [name]", "Scaffold work/, repoos.toml, AGENTS.md; outside a git repo runs a guided flow that can launch the web console"),
92
93
  cmdRow("list [status]", `Show the board (or one column: ${c.dim("inbox|ready|active|review|done")})`),
93
94
  cmdRow("status [--json]", "One-screen health snapshot: server, build freshness, board, worktrees, tunnel, git"),
94
- cmdRow("doctor [--json]", "Read-only readiness preflight: identity, config, layout, tools, check plan, server, secrets"),
95
+ cmdRow("doctor [--json] [--probe <cli>] [--binary <path>]", "Readiness preflight: identity, config, layout, tools, check plan, server, secrets (--probe runs a live contract check; --binary overrides PATH resolution)"),
96
+ cmdRow("certify <cli> [--yes] [--binary <path>]", "Run the adapter contract suite and write certification evidence into agent-compatibility.json (--binary probes a specific binary)"),
95
97
  cmdRow("support bundle", "Write a redacted, inspectable diagnostic bundle for failed setups"),
96
98
  cmdRow("show <id>", "Show a task's full spec"),
97
99
  cmdRow("mv <id> <status>", `Move a task to a new status — never merges code ${c.dim('flags: --note "...", --force-not-merged')}`),
@@ -163,6 +165,7 @@ function main() {
163
165
  "check",
164
166
  "status",
165
167
  "doctor",
168
+ "certify",
166
169
  "support",
167
170
  "help",
168
171
  "--help",
@@ -201,6 +204,9 @@ function main() {
201
204
  case "doctor":
202
205
  void cmdDoctor(rest);
203
206
  break;
207
+ case "certify":
208
+ void cmdCertify(rest);
209
+ break;
204
210
  case "support":
205
211
  void cmdSupport(rest);
206
212
  break;
@@ -0,0 +1,10 @@
1
+ export interface CertifyCliArgs {
2
+ cli: string | null;
3
+ yes: boolean;
4
+ json: boolean;
5
+ missingCli: boolean;
6
+ /** Explicit binary path — skips PATH resolution and probes this binary directly. */
7
+ binary: string | null;
8
+ }
9
+ export declare function parseCertifyArgs(argv: string[]): CertifyCliArgs;
10
+ export declare function cmdCertify(argv: string[]): Promise<void>;
@@ -0,0 +1,198 @@
1
+ /**
2
+ * `repoos certify <cli> [--yes] [--json]` — run the adapter contract suite and,
3
+ * when every seam passes, write the certification evidence back into
4
+ * `src/core/agent-compatibility.json` automatically.
5
+ *
6
+ * This is the maintainer-facing counterpart to `repoos doctor --probe`: doctor
7
+ * shows you the result; certify also commits it to the manifest so the next
8
+ * RepoOS release ships the updated compatibility status to all users.
9
+ *
10
+ * The command resolves the manifest path the same way `agent-compatibility.ts`
11
+ * does — src/core/ in a dev checkout, dist/core/ in a built install — and
12
+ * writes back to whichever file it loaded from.
13
+ */
14
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
15
+ import { fileURLToPath } from "node:url";
16
+ import { join } from "node:path";
17
+ import { runAdapterContract } from "../core/agent-contract.js";
18
+ import { parseAgentVersion } from "../core/agent-compatibility.js";
19
+ import { c } from "../cli/colors.js";
20
+ export function parseCertifyArgs(argv) {
21
+ const yes = argv.includes("--yes");
22
+ const json = argv.includes("--json");
23
+ const binaryIdx = argv.indexOf("--binary");
24
+ const binary = binaryIdx !== -1 ? (argv[binaryIdx + 1] ?? null) : null;
25
+ const positional = argv.filter((a, i) => !a.startsWith("--") && argv[i - 1] !== "--binary");
26
+ const cli = positional[0] ?? null;
27
+ return { cli, yes, json, missingCli: !cli, binary };
28
+ }
29
+ /** Locate the live manifest file on disk (src or dist). */
30
+ function findManifestPath() {
31
+ const manifestUrl = new URL("../core/agent-compatibility.json", import.meta.url);
32
+ const candidates = [];
33
+ if (manifestUrl.protocol === "file:") {
34
+ candidates.push(fileURLToPath(manifestUrl));
35
+ }
36
+ candidates.push(join(process.cwd(), "src/core/agent-compatibility.json"), join(process.cwd(), "dist/core/agent-compatibility.json"));
37
+ const root = process.env.REPOOS_ROOT;
38
+ if (root) {
39
+ candidates.push(join(root, "src/core/agent-compatibility.json"), join(root, "dist/core/agent-compatibility.json"));
40
+ }
41
+ for (const p of candidates) {
42
+ try {
43
+ if (existsSync(p))
44
+ return p;
45
+ }
46
+ catch {
47
+ /* skip */
48
+ }
49
+ }
50
+ return null;
51
+ }
52
+ function loadManifest(path) {
53
+ return JSON.parse(readFileSync(path, "utf8"));
54
+ }
55
+ function saveManifest(path, manifest) {
56
+ writeFileSync(path, JSON.stringify(manifest, null, 2) + "\n", "utf8");
57
+ }
58
+ export async function cmdCertify(argv) {
59
+ const { cli, yes, json: asJson, missingCli, binary } = parseCertifyArgs(argv);
60
+ if (missingCli || !cli) {
61
+ console.error(c.red(" repoos certify needs a harness id, e.g. `repoos certify opencode`."));
62
+ console.error(c.dim(" Use --binary <path> to probe a specific binary instead of PATH resolution."));
63
+ process.exitCode = 1;
64
+ return;
65
+ }
66
+ const WARNING = [
67
+ "",
68
+ c.yellow(c.bold("⚠ Live compatibility probe + manifest write")),
69
+ " This runs the adapter contract suite against the installed harness and,",
70
+ " if every seam passes, writes the certification evidence into",
71
+ " src/core/agent-compatibility.json. It may use your provider credentials",
72
+ " and spend tokens. It never reads task files or project content.",
73
+ "",
74
+ ].join("\n");
75
+ if (!yes) {
76
+ if (!process.stdin.isTTY) {
77
+ console.error(c.red(" repoos certify requires --yes when stdin is not a terminal."));
78
+ console.error(c.dim(" repoos certify " + cli + " --yes"));
79
+ process.exitCode = 1;
80
+ return;
81
+ }
82
+ const { createInterface } = await import("node:readline");
83
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
84
+ console.log(WARNING);
85
+ const answer = await new Promise((resolve) => {
86
+ rl.question(c.bold(` Run the ${cli} probe and write results to the manifest? [y/N] `), resolve);
87
+ });
88
+ rl.close();
89
+ if (!/^y(es)?$/i.test(answer.trim())) {
90
+ console.log(c.dim(" Cancelled."));
91
+ return;
92
+ }
93
+ }
94
+ else if (!asJson) {
95
+ console.log(WARNING);
96
+ }
97
+ // Run the probe.
98
+ const result = await runAdapterContract({
99
+ cli,
100
+ mode: "live",
101
+ ...(binary ? { bin: binary } : {}),
102
+ });
103
+ if (asJson) {
104
+ console.log(JSON.stringify(result, null, 2));
105
+ if (!result.passed)
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+ // Print probe output (same as doctor --probe).
110
+ console.log("");
111
+ console.log(" " +
112
+ c.bold(c.cyan("Adapter contract probe")) +
113
+ c.dim(" — " + result.cli) +
114
+ c.dim(" (" + result.binary + ")"));
115
+ for (const cap of result.capabilities) {
116
+ const icon = cap.ok ? c.green("✔") : c.red("✗");
117
+ console.log(" " + icon + " " + cap.label + c.dim(" (" + cap.id + ")"));
118
+ console.log(" " + c.dim(cap.detail));
119
+ }
120
+ const passCount = result.capabilities.filter((cap) => cap.ok).length;
121
+ const verdict = result.passed
122
+ ? c.green(`PASSED — ${result.capabilities.length}/${result.capabilities.length} seams`)
123
+ : c.red(`FAILED — ${passCount}/${result.capabilities.length} seams`);
124
+ console.log("");
125
+ console.log(" " + verdict + c.dim(` (${Math.round(result.durationMs / 1000)}s)`));
126
+ if (!result.passed) {
127
+ console.log("");
128
+ console.log(c.dim(" Manifest not updated — probe must pass all seams to certify."));
129
+ console.log("");
130
+ process.exitCode = 1;
131
+ return;
132
+ }
133
+ // Locate the manifest and update it.
134
+ const manifestPath = findManifestPath();
135
+ if (!manifestPath) {
136
+ console.error(c.red(" Cannot find agent-compatibility.json to write certification."));
137
+ console.error(c.dim(" Run from the repoos source checkout, or set REPOOS_ROOT."));
138
+ process.exitCode = 1;
139
+ return;
140
+ }
141
+ const manifest = loadManifest(manifestPath);
142
+ const versionStr = result.detectedVersion ? result.detectedVersion.join(".") : null;
143
+ const now = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
144
+ const source = `repoos certify ${cli} live probe — ${result.capabilities.length}/${result.capabilities.length} seams passed on ${result.startedAt} against binary ${result.binary}`;
145
+ let contract = manifest.contracts.find((c) => c.cli === cli);
146
+ if (!contract) {
147
+ // Bootstrap a minimal contract for a harness that has no entry yet.
148
+ const major = result.detectedVersion?.[0] ?? 0;
149
+ contract = {
150
+ cli,
151
+ name: cli,
152
+ supportedMajor: major,
153
+ supportedRange: `>=${major}.0.0 <${major + 1}.0.0`,
154
+ newestCertifiedVersion: versionStr,
155
+ knownIncompatibleRanges: [],
156
+ requiredCapabilities: result.capabilities.filter((c) => c.ok).map((c) => c.id),
157
+ verifiedAt: now,
158
+ verificationSource: source,
159
+ upgradeGuidance: `Install the current ${cli} release and re-run \`repoos certify ${cli}\`.`,
160
+ officialUrl: "",
161
+ };
162
+ manifest.contracts.push(contract);
163
+ console.log("");
164
+ console.log(" " + c.yellow("⚠ No existing contract — bootstrapped a new entry."));
165
+ console.log(c.dim(" Review src/core/agent-compatibility.json before committing:"));
166
+ console.log(c.dim(` officialUrl, upgradeGuidance, and supportedRange may need editing.`));
167
+ }
168
+ else {
169
+ // Update the three certification fields.
170
+ const prev = contract.newestCertifiedVersion;
171
+ const prevParsed = prev ? parseAgentVersion(prev) : null;
172
+ const thisParsed = result.detectedVersion;
173
+ // Only advance newestCertifiedVersion — never roll it back.
174
+ if (!prevParsed ||
175
+ !thisParsed ||
176
+ thisParsed[0] > prevParsed[0] ||
177
+ (thisParsed[0] === prevParsed[0] && thisParsed[1] > prevParsed[1]) ||
178
+ (thisParsed[0] === prevParsed[0] &&
179
+ thisParsed[1] === prevParsed[1] &&
180
+ thisParsed[2] >= prevParsed[2])) {
181
+ contract.newestCertifiedVersion = versionStr;
182
+ }
183
+ contract.verifiedAt = now;
184
+ contract.verificationSource = source;
185
+ }
186
+ saveManifest(manifestPath, manifest);
187
+ console.log("");
188
+ console.log(" " + c.green("✔ Manifest updated") + c.dim(" — " + manifestPath));
189
+ if (versionStr) {
190
+ console.log(c.dim(` newestCertifiedVersion: ${versionStr}`));
191
+ }
192
+ console.log(c.dim(` verifiedAt: ${now}`));
193
+ console.log("");
194
+ console.log(c.dim(" Next: review the diff, then commit:"));
195
+ console.log(c.dim(` git diff src/core/agent-compatibility.json`));
196
+ console.log(c.dim(` git add src/core/agent-compatibility.json && git commit -m "cert(${cli}): certify ${versionStr ?? "unknown"}"`));
197
+ console.log("");
198
+ }
@@ -1,4 +1,20 @@
1
1
  import { type DoctorReport } from "../core/doctor.js";
2
+ export interface DoctorCliArgs {
3
+ json: boolean;
4
+ yes: boolean;
5
+ /** Value passed to `--probe`, or null when the flag is absent. */
6
+ probe: string | null;
7
+ /** True when `--probe` was given without a value (or before another flag). */
8
+ probeMissingValue: boolean;
9
+ /** Explicit binary path for the probe — bypasses PATH resolution. */
10
+ binary: string | null;
11
+ }
12
+ /**
13
+ * Parse `repoos doctor`'s argument list. Kept pure and exported so the probe
14
+ * arming rules (`--probe` needs a value; `--probe --yes` is a usage error) are
15
+ * unit-tested rather than only exercised through a live run.
16
+ */
17
+ export declare function parseDoctorArgs(argv: string[]): DoctorCliArgs;
2
18
  export declare function renderDoctor(report: DoctorReport): void;
3
- /** `repoos doctor [--json]` */
19
+ /** `repoos doctor [--json] [--probe <cli>] [--yes]` */
4
20
  export declare function cmdDoctor(argv: string[]): Promise<void>;
@@ -1,16 +1,42 @@
1
1
  /**
2
- * `repoos doctor [--json]` — human and machine rendering of the readiness
3
- * preflight built in `src/core/doctor.ts`.
2
+ * `repoos doctor [--json] [--probe <cli>] [--yes]` — human and machine
3
+ * rendering of the readiness preflight built in `src/core/doctor.ts`.
4
4
  *
5
5
  * The command adds no diagnostic logic of its own: it runs the engine, prints
6
6
  * it, and sets the exit code (non-zero when any finding is a `fail`, so it is
7
7
  * usable in scripts). `--json` emits the same `DoctorReport` the UI and the
8
8
  * support bundle (#0453) consume.
9
+ *
10
+ * `--probe <cli>` runs the live adapter contract suite for that harness
11
+ * (`src/core/agent-contract.ts`) instead of the static report. It is opt-in
12
+ * and may use provider credentials/tokens, so it warns, asks for confirmation
13
+ * on a TTY (or requires `--yes` headless), runs in an isolated temp fixture,
14
+ * and cleans up.
9
15
  */
10
16
  import { readBuildMeta } from "../core/build.js";
17
+ import { runAdapterContract } from "../core/agent-contract.js";
11
18
  import { doctorRemediations, DOCTOR_CATEGORIES, runDoctor, } from "../core/doctor.js";
12
19
  import { c } from "../cli/colors.js";
13
20
  const ICON = { pass: "✔", warn: "⚠", fail: "✗" };
21
+ /**
22
+ * Parse `repoos doctor`'s argument list. Kept pure and exported so the probe
23
+ * arming rules (`--probe` needs a value; `--probe --yes` is a usage error) are
24
+ * unit-tested rather than only exercised through a live run.
25
+ */
26
+ export function parseDoctorArgs(argv) {
27
+ const json = argv.includes("--json");
28
+ const yes = argv.includes("--yes");
29
+ const binaryIdx = argv.indexOf("--binary");
30
+ const binary = binaryIdx !== -1 ? (argv[binaryIdx + 1] ?? null) : null;
31
+ const probeArg = argv.indexOf("--probe");
32
+ if (probeArg === -1)
33
+ return { json, yes, probe: null, probeMissingValue: false, binary };
34
+ const value = argv[probeArg + 1];
35
+ if (!value || value.startsWith("--")) {
36
+ return { json, yes, probe: null, probeMissingValue: true, binary };
37
+ }
38
+ return { json, yes, probe: value, probeMissingValue: false, binary };
39
+ }
14
40
  function severityColor(severity, text) {
15
41
  if (severity === "pass")
16
42
  return c.green(text);
@@ -57,9 +83,18 @@ export function renderDoctor(report) {
57
83
  }
58
84
  console.log("");
59
85
  }
60
- /** `repoos doctor [--json]` */
86
+ /** `repoos doctor [--json] [--probe <cli>] [--yes]` */
61
87
  export async function cmdDoctor(argv) {
62
- const asJson = argv.includes("--json");
88
+ const { json: asJson, yes, probe: probeCli, probeMissingValue, binary } = parseDoctorArgs(argv);
89
+ if (probeMissingValue) {
90
+ console.error(c.red(" repoos doctor --probe needs a harness id, e.g. `--probe opencode`."));
91
+ process.exitCode = 1;
92
+ return;
93
+ }
94
+ if (probeCli) {
95
+ await cmdProbe(probeCli, { asJson, yes, binary });
96
+ return;
97
+ }
63
98
  try {
64
99
  const report = await runDoctor({ version: readBuildMeta().version });
65
100
  if (asJson) {
@@ -76,3 +111,85 @@ export async function cmdDoctor(argv) {
76
111
  process.exitCode = 1;
77
112
  }
78
113
  }
114
+ /**
115
+ * Live adapter-contract probe (`repoos doctor --probe <cli>`). Opt-in: warns
116
+ * that provider credentials/tokens may be spent, confirms on a TTY (or demands
117
+ * `--yes` headless), runs every seam in an isolated temp fixture, and reports
118
+ * the honest result. A passed probe is the evidence a maintainer records in
119
+ * `src/core/agent-compatibility.json` (verifiedAt + verificationSource).
120
+ */
121
+ async function cmdProbe(cli, opts) {
122
+ const WARNING = [
123
+ "",
124
+ c.yellow(c.bold("⚠ Live compatibility probe")),
125
+ " This runs the installed harness in an isolated temporary directory,",
126
+ " exercising version, help, model listing, a headless one-shot, event",
127
+ " parsing, permission/auto mode, session continuation, and cancellation.",
128
+ " It may use your provider credentials and spend tokens: the one-shot,",
129
+ " resume, and cancellation seams each start a real harness run. It never",
130
+ " reads task files, prompts, or project content, and the temporary fixture",
131
+ " is removed when done.",
132
+ "",
133
+ ].join("\n");
134
+ if (!opts.yes) {
135
+ if (!process.stdin.isTTY) {
136
+ console.error(c.red(" repoos doctor --probe requires --yes when stdin is not a terminal."));
137
+ console.error(c.dim(" repoos doctor --probe " + cli + " --yes"));
138
+ process.exitCode = 1;
139
+ return;
140
+ }
141
+ const { createInterface } = await import("node:readline");
142
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
143
+ console.log(WARNING);
144
+ const answer = await new Promise((resolve) => {
145
+ rl.question(c.bold(` Run the live ${cli} compatibility probe? [y/N] `), resolve);
146
+ });
147
+ rl.close();
148
+ if (!/^y(es)?$/i.test(answer.trim())) {
149
+ console.log(c.dim(" Probe cancelled."));
150
+ return;
151
+ }
152
+ }
153
+ else if (!opts.asJson) {
154
+ console.log(WARNING);
155
+ }
156
+ try {
157
+ const result = await runAdapterContract({
158
+ cli,
159
+ mode: "live",
160
+ ...(opts.binary ? { bin: opts.binary } : {}),
161
+ });
162
+ if (opts.asJson) {
163
+ console.log(JSON.stringify(result, null, 2));
164
+ }
165
+ else {
166
+ console.log("");
167
+ console.log(" " +
168
+ c.bold(c.cyan("Adapter contract probe")) +
169
+ c.dim(" — " + result.cli) +
170
+ c.dim(" (" + result.binary + ")"));
171
+ for (const cap of result.capabilities) {
172
+ const icon = cap.ok ? c.green("✔") : c.red("✗");
173
+ console.log(" " + icon + " " + cap.label + c.dim(" (" + cap.id + ")"));
174
+ console.log(" " + c.dim(cap.detail));
175
+ }
176
+ const verdict = result.passed
177
+ ? c.green(`PASSED — ${result.capabilities.length}/${result.capabilities.length} seams`)
178
+ : c.red(`FAILED — ${result.capabilities.filter((cap) => cap.ok).length}/${result.capabilities.length} seams`);
179
+ console.log("");
180
+ console.log(" " + verdict + c.dim(` (${Math.round(result.durationMs / 1000)}s)`));
181
+ if (result.passed && result.evidence) {
182
+ console.log("");
183
+ console.log(" " + c.bold("Record evidence in the manifest"));
184
+ console.log(" " + c.dim(result.evidence));
185
+ }
186
+ console.log("");
187
+ }
188
+ if (!result.passed)
189
+ process.exitCode = 1;
190
+ }
191
+ catch (e) {
192
+ console.error(c.red(" repoos doctor --probe failed: ") + e.message);
193
+ process.exitCode = 1;
194
+ }
195
+ }
@@ -15,7 +15,7 @@
15
15
  * Commands operate on the current repo by default.
16
16
  */
17
17
  import { listServices, getServiceStatus, installService, removeService, startService, stopService, restartService, enableAutoStart, disableAutoStart, checkHealth, } from "../core/service-manager.js";
18
- import { boardRoot, deriveServePort, loadConfig } from "../core/config.js";
18
+ import { boardRoot, loadConfig, resolveServePort } from "../core/config.js";
19
19
  import { c } from "../cli/colors.js";
20
20
  function statusLabel(s) {
21
21
  if (s === "running")
@@ -78,7 +78,7 @@ export async function cmdService(argv) {
78
78
  case "install": {
79
79
  const { root } = boardRoot();
80
80
  const config = loadConfig(root);
81
- const port = deriveServePort(root);
81
+ const port = resolveServePort(root, config);
82
82
  const result = await installService(root, port, { autoStart: false });
83
83
  if (!result.ok) {
84
84
  console.error(c.red(" ✗ " + result.error));
@@ -50,8 +50,8 @@ export declare function cmdMv(id?: string, status?: string, note?: string, opts?
50
50
  */
51
51
  export declare function cmdNote(args: string[]): void;
52
52
  /**
53
- * `repoos update <id> [--title ...] [--area ...] [--priority ...] [--type ...]
54
- * [--body ... | --body -] [--branch ...] [--assigned-to ai|human]
53
+ * `repoos update <id> [--title ...] [--area ...] [--story ...] [--priority ...]
54
+ * [--type ...] [--body ... | --body -] [--branch ...] [--assigned-to ai|human]
55
55
  * [--needs-input true|false] [--questions "Question one\nQuestion two"]`
56
56
  *
57
57
  * Writes directly via patchTaskFile (same path the server's PATCH route uses),
@@ -248,6 +248,7 @@ export function cmdNote(args) {
248
248
  const UPDATE_FLAGS = {
249
249
  title: "title",
250
250
  area: "area",
251
+ story: "story",
251
252
  priority: "priority",
252
253
  type: "type",
253
254
  body: "body",
@@ -257,8 +258,8 @@ const UPDATE_FLAGS = {
257
258
  questions: "questions",
258
259
  };
259
260
  /**
260
- * `repoos update <id> [--title ...] [--area ...] [--priority ...] [--type ...]
261
- * [--body ... | --body -] [--branch ...] [--assigned-to ai|human]
261
+ * `repoos update <id> [--title ...] [--area ...] [--story ...] [--priority ...]
262
+ * [--type ...] [--body ... | --body -] [--branch ...] [--assigned-to ai|human]
262
263
  * [--needs-input true|false] [--questions "Question one\nQuestion two"]`
263
264
  *
264
265
  * Writes directly via patchTaskFile (same path the server's PATCH route uses),
@@ -268,7 +269,7 @@ const UPDATE_FLAGS = {
268
269
  */
269
270
  export function cmdUpdate(args) {
270
271
  const [id, ...rest] = args;
271
- const usage = ' Usage: repoos update <id> [--title "..."] [--area a] [--priority p] [--type t] [--body "..."|-] [--branch b] [--assigned-to ai|human] [--needs-input true|false] [--questions "Question one\\nQuestion two"] [--clear-questions]';
272
+ const usage = ' Usage: repoos update <id> [--title "..."] [--area a] [--story "Delivery slice"] [--priority p] [--type t] [--body "..."|-] [--branch b] [--assigned-to ai|human] [--needs-input true|false] [--questions "Question one\\nQuestion two"] [--clear-questions]';
272
273
  if (!id) {
273
274
  console.error(c.red(usage));
274
275
  process.exitCode = 1;
@@ -337,7 +338,16 @@ export function cmdUpdate(args) {
337
338
  process.exitCode = 1;
338
339
  }
339
340
  }
340
- const NEW_FLAGS = new Set(["ai", "type", "area", "priority", "body", "needs-input", "questions"]);
341
+ const NEW_FLAGS = new Set([
342
+ "ai",
343
+ "type",
344
+ "area",
345
+ "story",
346
+ "priority",
347
+ "body",
348
+ "needs-input",
349
+ "questions",
350
+ ]);
341
351
  function parseQuestions(raw) {
342
352
  try {
343
353
  const parsed = JSON.parse(raw);
@@ -355,7 +365,7 @@ function parseQuestions(raw) {
355
365
  }
356
366
  /** `repoos new <title> [--ai] [--needs-input true] [--questions "..."]` */
357
367
  export function cmdNew(args) {
358
- const usage = ' Usage: repoos new "Task title" [--ai] [--type bug] [--area web] [--priority p1] [--body "..."|-] [--needs-input true|false] [--questions "Question one\\nQuestion two"]';
368
+ const usage = ' Usage: repoos new "Task title" [--ai] [--type bug] [--area web] [--story "Delivery slice"] [--priority p1] [--body "..."|-] [--needs-input true|false] [--questions "Question one\\nQuestion two"]';
359
369
  const flags = {};
360
370
  const positional = [];
361
371
  for (let i = 0; i < args.length; i++) {
@@ -396,6 +406,7 @@ export function cmdNew(args) {
396
406
  title,
397
407
  type: flags.type || undefined,
398
408
  area: flags.area || undefined,
409
+ story: flags.story || undefined,
399
410
  priority: flags.priority || undefined,
400
411
  assignedTo: flags.ai ? "ai" : undefined,
401
412
  body: flags.body || undefined,
@@ -0,0 +1,46 @@
1
+ import type { DetectedAgent } from "./detect.js";
2
+ export type CompatibilityStatus = "verified" | "upgrade_recommended" | "newer_than_verified" | "unsupported" | "not_probed";
3
+ export interface AgentCompatibilityContract {
4
+ cli: string;
5
+ name: string;
6
+ supportedMajor: number;
7
+ supportedRange: string;
8
+ /**
9
+ * Newest release with recorded certification evidence, or `null` when the
10
+ * line is tracked but nothing has been certified yet. This pairs with
11
+ * `verifiedAt`/`verificationSource`: a non-null value without evidence, or
12
+ * evidence without a value, is a manifest inconsistency.
13
+ */
14
+ newestCertifiedVersion: string | null;
15
+ knownIncompatibleRanges: string[];
16
+ requiredCapabilities: string[];
17
+ verifiedAt: string | null;
18
+ verificationSource: string | null;
19
+ upgradeGuidance: string;
20
+ officialUrl: string;
21
+ }
22
+ export interface AgentCompatibility {
23
+ status: CompatibilityStatus;
24
+ label: string;
25
+ explanation: string;
26
+ installedVersion: string | null;
27
+ newestCertifiedVersion: string | null;
28
+ contract: AgentCompatibilityContract | null;
29
+ capabilities: string[];
30
+ }
31
+ export declare const AGENT_COMPATIBILITY_MANIFEST: {
32
+ schemaVersion: number;
33
+ contracts: AgentCompatibilityContract[];
34
+ };
35
+ export declare function parseAgentVersion(value: string | null): [number, number, number] | null;
36
+ /** True when `version` falls inside the semver `range` (e.g. `>=2.0.0 <3.0.0`, `^2.1`, `1.2.*`, `a || b`). */
37
+ export declare function versionSatisfiesRange(version: [number, number, number], range: string): boolean;
38
+ /**
39
+ * Classify one detected installation against a single contract. Exported so the
40
+ * full status ladder — including `verified` and the `newer_than_verified`
41
+ * rungs — can be tested against synthetic contracts without touching the live
42
+ * manifest.
43
+ */
44
+ export declare function compatibilityForContract(contract: AgentCompatibilityContract, agent: Pick<DetectedAgent, "version" | "drivable">): AgentCompatibility;
45
+ export declare function compatibilityForAgent(agent: Pick<DetectedAgent, "cli" | "version" | "drivable">): AgentCompatibility;
46
+ export declare function compatibilityForDetectedAgent(agent: DetectedAgent): AgentCompatibility;