@iowarp/clio-coder 0.3.6 → 0.3.7

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 (258) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +16 -5
  3. package/dist/{acp-2BEHC4DL.js → acp-SK4MD6MM.js} +10 -10
  4. package/dist/{agents-LNNFTM53.js → agents-2FN2K6ME.js} +30 -25
  5. package/dist/assets/codewiki.json +1 -1
  6. package/dist/{auth-KXXFI2VS.js → auth-QIYZWM5I.js} +13 -13
  7. package/dist/{chunk-KHSFENX2.js → chunk-3HAPLH5M.js} +10 -10
  8. package/dist/{chunk-24I7BN55.js → chunk-465YSENW.js} +2 -2
  9. package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
  10. package/dist/{chunk-CYQKWTG3.js → chunk-4DWFMQDR.js} +4 -4
  11. package/dist/{chunk-E2ER4LJF.js → chunk-5C3AQNDW.js} +25 -1
  12. package/dist/{chunk-22NAGB7X.js → chunk-5C77SEEY.js} +5 -94
  13. package/dist/{chunk-43AOLP7E.js → chunk-5FR74PWO.js} +2 -1
  14. package/dist/{chunk-K7T3E2SR.js → chunk-5UJ6ECTS.js} +10 -9
  15. package/dist/{chunk-6US73PDB.js → chunk-6M7VS3J3.js} +5 -5
  16. package/dist/{chunk-CJUB2JJ2.js → chunk-6TUKSZVF.js} +5 -5
  17. package/dist/{chunk-5JGRAMKL.js → chunk-AB4XIIVB.js} +8 -6
  18. package/dist/{chunk-R46L2BIR.js → chunk-BMWK7ZIZ.js} +14 -20
  19. package/dist/{chunk-4BPJXDWC.js → chunk-C4JBQ5SR.js} +30 -14
  20. package/dist/{chunk-XXQNGV4M.js → chunk-CEYBNUGC.js} +243 -63
  21. package/dist/{chunk-VEZEGCGW.js → chunk-D4MDIG46.js} +20 -18
  22. package/dist/chunk-DJNLUABN.js +843 -0
  23. package/dist/{chunk-RY3LY4J5.js → chunk-DMD2AGVS.js} +5 -4
  24. package/dist/{chunk-KOHPCX4K.js → chunk-DOOEX22V.js} +2 -2
  25. package/dist/chunk-DQA7QLMD.js +123 -0
  26. package/dist/chunk-DR52UMZW.js +21 -0
  27. package/dist/{chunk-XF5N4U5A.js → chunk-EBEFWSGL.js} +6 -5
  28. package/dist/{chunk-EYPA3EGJ.js → chunk-EELBMBT6.js} +120 -13
  29. package/dist/{chunk-CKXWIANG.js → chunk-EOOQZZDE.js} +16 -14
  30. package/dist/{chunk-WR67VIZY.js → chunk-FOT2FX5J.js} +63 -5
  31. package/dist/{chunk-FYYLNIL5.js → chunk-GH5622CP.js} +2 -2
  32. package/dist/chunk-GWS3VEIW.js +195 -0
  33. package/dist/{chunk-LYF7OHWH.js → chunk-J7PIKKWC.js} +8 -463
  34. package/dist/{chunk-NILBFAPG.js → chunk-JNXPYBB4.js} +2 -2
  35. package/dist/{chunk-4VP4KH3K.js → chunk-JRIO5UD2.js} +4 -4
  36. package/dist/{chunk-6XXKFVSN.js → chunk-JTSEDYVQ.js} +7 -7
  37. package/dist/{chunk-QKMUKYO7.js → chunk-KCMKRQX4.js} +236 -84
  38. package/dist/chunk-KZ2H5X4G.js +1026 -0
  39. package/dist/{chunk-QNQHSOLF.js → chunk-LADCF22A.js} +12 -12
  40. package/dist/chunk-M4AKACEO.js +382 -0
  41. package/dist/{chunk-XYDYPRZI.js → chunk-MXI6J5JF.js} +7 -7
  42. package/dist/{chunk-G7MUEIGA.js → chunk-OB5HIGJY.js} +1 -1
  43. package/dist/{chunk-EKY57CSP.js → chunk-OBMAI2DP.js} +61 -767
  44. package/dist/chunk-PD3MESLB.js +242 -0
  45. package/dist/{chunk-ZRGEBJ4T.js → chunk-QCTRSGHQ.js} +21 -21
  46. package/dist/chunk-RVG5JXAL.js +41 -0
  47. package/dist/{chunk-RD5U66HV.js → chunk-SROCI7ZU.js} +7 -7
  48. package/dist/{chunk-MFFY33HR.js → chunk-THKY7CD7.js} +466 -205
  49. package/dist/{chunk-PCZJO5TI.js → chunk-UFQ3F4FW.js} +13 -178
  50. package/dist/{chunk-AD2SYQYC.js → chunk-UHXRNZ2J.js} +121 -3
  51. package/dist/chunk-UND3GU2L.js +103 -0
  52. package/dist/{chunk-QM3F2GKX.js → chunk-UUANF5CR.js} +2247 -2096
  53. package/dist/chunk-UVDSQ6LW.js +472 -0
  54. package/dist/{chunk-DJVECN66.js → chunk-VQNODYQ4.js} +14 -14
  55. package/dist/{chunk-3BPUFZDL.js → chunk-VREKEFLL.js} +3 -3
  56. package/dist/{chunk-PBTHKCPN.js → chunk-WJHBC77E.js} +6 -6
  57. package/dist/{chunk-XE2VEJHX.js → chunk-X2KV5FXT.js} +2 -2
  58. package/dist/{chunk-ZXF4XRKW.js → chunk-XEGB6BCN.js} +157 -7
  59. package/dist/{chunk-E25LMLRW.js → chunk-YD734TPH.js} +2 -2
  60. package/dist/{verifiers-NCBTHHN2.js → chunk-YTYFXUI3.js} +65 -322
  61. package/dist/{chunk-OH3TOQTB.js → chunk-ZGH7FGS5.js} +13 -7
  62. package/dist/cli/index.js +32 -30
  63. package/dist/{clio-M2KGYUFZ.js → clio-WBVQEBKO.js} +7 -7
  64. package/dist/{code-nav-GQNL7XA6.js → code-nav-FGGFIE7L.js} +3 -3
  65. package/dist/{components-5TTYYX6G.js → components-F7OEATSO.js} +4 -4
  66. package/dist/{config-XUUYQIWO.js → config-TRBL3RCF.js} +34 -29
  67. package/dist/{configure-IHJ7YOMV.js → configure-OLCVPHNM.js} +15 -15
  68. package/dist/{context-74JLXAWD.js → context-MJIJ6GOX.js} +11 -11
  69. package/dist/{context-ZQ7SIFJV.js → context-WFPKQSM6.js} +19 -3
  70. package/dist/{context-75MIWW3U.js → context-XEWE3MOJ.js} +31 -26
  71. package/dist/{context-clear-GYKWNUML.js → context-clear-KNOS2JPB.js} +31 -26
  72. package/dist/{context-working-set-UX5KEP4J.js → context-working-set-EUXAZI6N.js} +8 -8
  73. package/dist/{dispatch-runner-GIJBHNFL.js → dispatch-runner-B7MTOVKL.js} +313 -53
  74. package/dist/{docs-6FZSCG5B.js → docs-FLJTIDSE.js} +4 -4
  75. package/dist/{doctor-SVJ5BZCW.js → doctor-RN4YKO2X.js} +14 -14
  76. package/dist/{eval-CG6LLBLD.js → eval-RUBJVSNQ.js} +8 -7
  77. package/dist/{evidence-ZYFIEN42.js → evidence-JZNBUOQZ.js} +30 -25
  78. package/dist/{evolve-QGEXEMDW.js → evolve-FJVC4KKI.js} +30 -25
  79. package/dist/{extensions-ADGNCJJD.js → extensions-IQL36S7K.js} +4 -4
  80. package/dist/{fleet-S5R4ZOQY.js → fleet-BDKYJFCP.js} +214 -360
  81. package/dist/fleet-commands-ZFIWZSB3.js +70 -0
  82. package/dist/fleet-graph-Y6HPXIVF.js +125 -0
  83. package/dist/fleet-new-RDVJLHHH.js +48 -0
  84. package/dist/fleet-validate-BIYREGIK.js +79 -0
  85. package/dist/{init-5DRU55YR.js → init-LQUB5COQ.js} +44 -37
  86. package/dist/library-NJAHIGG4.js +217 -0
  87. package/dist/{memory-7YKKR6UC.js → memory-OG6HOYKM.js} +31 -26
  88. package/dist/{models-ZPOLRU2C.js → models-5ZG5XY7J.js} +21 -20
  89. package/dist/{monitor-US5F5YGZ.js → monitor-TJ7AMTGB.js} +49 -30
  90. package/dist/{orchestrator-E2AL4T5N.js → orchestrator-WZYB54DM.js} +3827 -581
  91. package/dist/{paths-E7KYAQWE.js → paths-XUC7GS6E.js} +4 -4
  92. package/dist/{reset-KZ652EK6.js → reset-PXQT45IY.js} +7 -7
  93. package/dist/{run-SRNBKDWD.js → run-FQ74YF62.js} +53 -45
  94. package/dist/{share-CGZE33UP.js → share-FW7SVCL3.js} +33 -9
  95. package/dist/{skills-S2X4DLY5.js → skills-7E7IRB3R.js} +24 -8
  96. package/dist/{skills-eval-W2GGIC4R.js → skills-eval-LI75W6OK.js} +34 -27
  97. package/dist/{targets-54SWINWB.js → targets-4CIFKCTW.js} +23 -22
  98. package/dist/{terminal-lease-SAIF2OGY.js → terminal-lease-WUZY7ZV5.js} +4 -4
  99. package/dist/{uninstall-BVLWXKBT.js → uninstall-7FV7IP4E.js} +4 -4
  100. package/dist/{upgrade-JKAR27XC.js → upgrade-K2HVIVMQ.js} +20 -19
  101. package/dist/{usage-MSAWCLX4.js → usage-GTZELZQX.js} +116 -49
  102. package/dist/verifiers-RLAHT27O.js +336 -0
  103. package/dist/{verify-X5HDROLA.js → verify-BX3BRKH5.js} +7 -6
  104. package/dist/{wiki-generate-GUSOQ6ZP.js → wiki-generate-ASIFASCN.js} +45 -37
  105. package/dist/worker/entry.js +38 -35
  106. package/docs/README.md +3 -2
  107. package/docs/acp.md +1 -1
  108. package/docs/alcf-provider.md +1 -1
  109. package/docs/architecture.md +2 -2
  110. package/docs/artifact-versions.md +10 -6
  111. package/docs/built-in-agents.md +26 -2
  112. package/docs/capacity-and-scheduling.md +1 -1
  113. package/docs/commands-and-modes.md +82 -2
  114. package/docs/configuration-and-targets.md +79 -2
  115. package/docs/context-engine.md +1 -1
  116. package/docs/development-pipeline.md +1 -1
  117. package/docs/dispatch-architecture-rationale.md +1 -1
  118. package/docs/documentation-coverage.md +3 -3
  119. package/docs/documentation-guide.md +3 -3
  120. package/docs/eval-runner.md +1 -1
  121. package/docs/evals-internal.md +1 -1
  122. package/docs/evidence-and-memory.md +5 -5
  123. package/docs/evolution.md +1 -1
  124. package/docs/exit-codes-and-output.md +4 -1
  125. package/docs/extensions-and-sharing.md +6 -2
  126. package/docs/fleet-demo-runbook.md +2 -2
  127. package/docs/fleet-dispatch.md +197 -10
  128. package/docs/git-commit-provenance.md +2 -2
  129. package/docs/glossary.md +1 -1
  130. package/docs/installation-and-lifecycle.md +2 -2
  131. package/docs/middleware-and-components.md +2 -1
  132. package/docs/model-catalog.md +1 -1
  133. package/docs/observability.md +55 -8
  134. package/docs/proactive-memory.md +1 -1
  135. package/docs/prompt-envelope-and-tools.md +1 -1
  136. package/docs/provider-adapter-cookbook.md +1 -1
  137. package/docs/release-cut-checklist.md +79 -64
  138. package/docs/resource-library.md +59 -0
  139. package/docs/safety-model.md +2 -2
  140. package/docs/scientific-validation.md +3 -3
  141. package/docs/session-lifecycle.md +37 -1
  142. package/docs/skills-marketplace.md +16 -3
  143. package/docs/tool-usage.md +14 -7
  144. package/docs/trace-store.md +1 -1
  145. package/docs/troubleshooting.md +1 -1
  146. package/docs/tui-design.md +1 -1
  147. package/docs/worker-dispatch-mechanics.md +3 -3
  148. package/package.json +1 -1
  149. package/src/cli/fleet-commands.ts +37 -0
  150. package/src/cli/fleet-graph.ts +102 -0
  151. package/src/cli/fleet-new.ts +36 -0
  152. package/src/cli/fleet-preflight.ts +121 -0
  153. package/src/cli/fleet-validate.ts +30 -0
  154. package/src/cli/fleet.ts +173 -335
  155. package/src/cli/index.ts +3 -1
  156. package/src/cli/library.ts +190 -0
  157. package/src/cli/share.ts +13 -1
  158. package/src/cli/usage.ts +111 -19
  159. package/src/core/bus-events.ts +4 -0
  160. package/src/core/commit-attribution.ts +4 -4
  161. package/src/core/config.ts +130 -0
  162. package/src/core/defaults.ts +81 -0
  163. package/src/domains/agents/builtins/architect.md +1 -0
  164. package/src/domains/agents/builtins/oracle.md +33 -0
  165. package/src/domains/agents/catalog.ts +13 -1
  166. package/src/domains/agents/fleet-contract.ts +278 -16
  167. package/src/domains/agents/index.ts +14 -0
  168. package/src/domains/agents/result-contract.ts +235 -1
  169. package/src/domains/config/classify.ts +4 -0
  170. package/src/domains/dispatch/active-route-planner.ts +14 -0
  171. package/src/domains/dispatch/backoff.ts +2 -1
  172. package/src/domains/dispatch/capability-match.ts +1 -0
  173. package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
  174. package/src/domains/dispatch/contract.ts +34 -0
  175. package/src/domains/dispatch/delegation-plan.ts +167 -0
  176. package/src/domains/dispatch/execution-plan.ts +76 -5
  177. package/src/domains/dispatch/execution-role.ts +3 -1
  178. package/src/domains/dispatch/execution-scheduler.ts +183 -67
  179. package/src/domains/dispatch/extension.ts +258 -9
  180. package/src/domains/dispatch/fleet-gate.ts +14 -0
  181. package/src/domains/dispatch/fleet-plan.ts +63 -3
  182. package/src/domains/dispatch/fleet-run.ts +737 -0
  183. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  184. package/src/domains/dispatch/host-verification.ts +178 -0
  185. package/src/domains/dispatch/index.ts +38 -0
  186. package/src/domains/dispatch/intent.ts +159 -0
  187. package/src/domains/dispatch/receipt-integrity.ts +8 -4
  188. package/src/domains/dispatch/state.ts +36 -3
  189. package/src/domains/dispatch/types.ts +51 -6
  190. package/src/domains/dispatch/validation.ts +66 -6
  191. package/src/domains/evidence/trust-status.ts +10 -1
  192. package/src/domains/middleware/index.ts +15 -0
  193. package/src/domains/middleware/watchdog.ts +281 -0
  194. package/src/domains/observability/contract.ts +3 -1
  195. package/src/domains/observability/cost.ts +12 -1
  196. package/src/domains/observability/extension.ts +2 -2
  197. package/src/domains/observability/index.ts +10 -0
  198. package/src/domains/observability/out-of-turn-usage.ts +223 -0
  199. package/src/domains/resources/index.ts +20 -0
  200. package/src/domains/resources/library.ts +326 -0
  201. package/src/domains/resources/skills/marketplace.ts +37 -12
  202. package/src/domains/session/handoff.ts +629 -0
  203. package/src/domains/share/archive.ts +67 -2
  204. package/src/entry/orchestrator.ts +37 -0
  205. package/src/interactive/bus-notices.ts +26 -0
  206. package/src/interactive/chat-loop.ts +235 -1
  207. package/src/interactive/chat-renderer.ts +22 -0
  208. package/src/interactive/cost-overlay.ts +31 -3
  209. package/src/interactive/council-dispatch.ts +30 -0
  210. package/src/interactive/council-grid.ts +213 -0
  211. package/src/interactive/council.ts +99 -0
  212. package/src/interactive/dispatch-board.ts +260 -16
  213. package/src/interactive/fleet-run-preview.ts +307 -0
  214. package/src/interactive/footer/notifications.ts +219 -0
  215. package/src/interactive/handoff-round.ts +56 -0
  216. package/src/interactive/interactive-application.ts +43 -1
  217. package/src/interactive/interactive-event-projection.ts +9 -1
  218. package/src/interactive/interactive-slash-runtime.ts +52 -2
  219. package/src/interactive/interactive-subscriptions.ts +14 -2
  220. package/src/interactive/oracle.ts +179 -0
  221. package/src/interactive/overlay-ask-user-lifecycle.ts +6 -0
  222. package/src/interactive/overlay-general-openers.ts +190 -1
  223. package/src/interactive/overlay-key-routing.ts +17 -1
  224. package/src/interactive/overlay-lifecycle.ts +41 -1
  225. package/src/interactive/overlay-permission-lifecycle.ts +10 -0
  226. package/src/interactive/overlay-resource-openers.ts +11 -3
  227. package/src/interactive/overlay-session-lifecycle.ts +234 -2
  228. package/src/interactive/overlays/fleet-run-approval.ts +208 -0
  229. package/src/interactive/overlays/handoff-review.ts +185 -0
  230. package/src/interactive/overlays/library-install-confirm.ts +151 -0
  231. package/src/interactive/overlays/list-overlay.ts +168 -2
  232. package/src/interactive/overlays/settings.ts +101 -4
  233. package/src/interactive/overlays/side-question.ts +139 -0
  234. package/src/interactive/overlays/skills-hub.ts +401 -15
  235. package/src/interactive/side-question.ts +171 -0
  236. package/src/interactive/slash-commands.ts +432 -5
  237. package/src/interactive/slash-spec.ts +19 -6
  238. package/src/interactive/theme/tokens.ts +30 -0
  239. package/src/interactive/turn-middleware.ts +15 -1
  240. package/src/interactive/watchdog-run.ts +75 -0
  241. package/src/interactive/worker-share.ts +56 -1
  242. package/src/interactive/worker-stream.ts +7 -0
  243. package/src/tools/bootstrap.ts +3 -0
  244. package/src/tools/compete-worktrees.ts +13 -79
  245. package/src/tools/dispatch-admission.ts +242 -8
  246. package/src/tools/dispatch-arguments.ts +57 -1
  247. package/src/tools/dispatch-plan.ts +136 -6
  248. package/src/tools/dispatch-runner.ts +319 -13
  249. package/src/tools/dispatch-types.ts +20 -1
  250. package/src/tools/dispatch.ts +72 -2
  251. package/src/tools/monitor.ts +16 -0
  252. package/src/tools/profiles.ts +18 -4
  253. package/src/tools/task-worktree.ts +238 -0
  254. package/src/tools/verify/authoring.ts +61 -1
  255. package/src/tools/verify/scripts.ts +62 -0
  256. package/src/tools/worker-evidence.ts +2 -1
  257. package/src/worker/spec-contract.ts +1 -0
  258. package/dist/chunk-HC4CLZ2Y.js +0 -68
package/src/cli/index.ts CHANGED
@@ -57,7 +57,7 @@ Usage:
57
57
  clio-coder uninstall remove all Clio Coder state; --remove-binary also unlinks the launcher
58
58
  clio-coder upgrade upgrade Clio Coder and run pending migrations
59
59
  clio-coder agents list discovered agent recipes
60
- clio-coder fleet list|run|status|drain|resume fleet contracts, status, and admission control
60
+ clio-coder fleet new|validate|graph|commands|run|status|drain|resume fleet authoring, execution, status, and admission control
61
61
  clio-coder evidence build, list, or inspect evidence artifacts
62
62
  clio-coder eval run, report, or compare local eval task files
63
63
  clio-coder memory list, propose, promote, approve, reject, or prune memory
@@ -65,6 +65,7 @@ Usage:
65
65
  clio-coder trace query or view the durable dispatch trace mirror
66
66
  clio-coder extensions install, list, enable, disable, or remove extension packages
67
67
  clio-coder skills list, inspect, validate, or install skills
68
+ clio-coder library list, search, add, or sync agents, prompts, fleets, and skills from catalogs
68
69
  clio-coder verifiers discover, author, validate, edit, or dry-run project checks
69
70
  clio-coder docs [topic] serve the HTML docs of a source checkout on 127.0.0.1 (--no-open to skip browser)
70
71
  clio-coder dev <command> harness instruments; run 'clio-coder dev' for the list
@@ -246,6 +247,7 @@ const COMMAND_HANDLERS = new Map<string, CommandHandler>([
246
247
  ["ext", extensionsCommand],
247
248
  ["fleet", async (subArgs) => (await import("./fleet.js")).runFleetCommand(subArgs)],
248
249
  ["skills", async (subArgs) => (await import("./skills.js")).runSkillsCommand(subArgs)],
250
+ ["library", async (subArgs) => (await import("./library.js")).runLibraryCommand(subArgs)],
249
251
  ["verifiers", async (subArgs) => (await import("./verifiers.js")).runVerifiersCommand(subArgs)],
250
252
  ["docs", async (subArgs) => (await import("./docs.js")).runDocsCommand(subArgs)],
251
253
  ["share", async (subArgs) => (await import("./share.js")).runShareCommand(subArgs)],
@@ -0,0 +1,190 @@
1
+ import {
2
+ classifyLibraryRequirements,
3
+ confirmLibraryRemote,
4
+ discoverLibrary,
5
+ installLibraryPlan,
6
+ type LibraryEntry,
7
+ type LibraryEntryKind,
8
+ libraryEntryRef,
9
+ libraryInstallPath,
10
+ planLibraryInstall,
11
+ syncLibrary,
12
+ } from "../domains/resources/index.js";
13
+ import { printError, printOk } from "./shared.js";
14
+
15
+ const KINDS = new Set<LibraryEntryKind>(["skill", "agent", "prompt", "fleet"]);
16
+ const HELP = `clio-coder library <command>
17
+
18
+ Commands:
19
+ clio-coder library list [--kind <kind>] [--json]
20
+ clio-coder library search <query> [--kind <kind>] [--json]
21
+ clio-coder library add <ref> [--from <catalog|path>] [--with-requirements] [--yes] [--json]
22
+ clio-coder library use <kind> <name>
23
+ clio-coder library sync
24
+ clio-coder library push
25
+ clio-coder library remote confirm <url>
26
+ `;
27
+
28
+ interface Parsed {
29
+ command?: string;
30
+ positional: string[];
31
+ kind?: LibraryEntryKind;
32
+ from?: string;
33
+ json: boolean;
34
+ yes: boolean;
35
+ withRequirements: boolean;
36
+ help: boolean;
37
+ }
38
+
39
+ function parse(argv: ReadonlyArray<string>): Parsed {
40
+ const out: Parsed = { positional: [], json: false, yes: false, withRequirements: false, help: false };
41
+ for (let i = 0; i < argv.length; i += 1) {
42
+ const arg = argv[i];
43
+ if (!arg) continue;
44
+ if (!out.command && !arg.startsWith("-")) {
45
+ out.command = arg;
46
+ continue;
47
+ }
48
+ if (arg === "--json") out.json = true;
49
+ else if (arg === "--yes") out.yes = true;
50
+ else if (arg === "--with-requirements") out.withRequirements = true;
51
+ else if (arg === "--help" || arg === "-h") out.help = true;
52
+ else if (arg === "--kind") {
53
+ const value = argv[++i];
54
+ if (!value || !KINDS.has(value as LibraryEntryKind))
55
+ throw new Error("--kind requires skill, agent, prompt, or fleet");
56
+ out.kind = value as LibraryEntryKind;
57
+ } else if (arg === "--from") {
58
+ const value = argv[++i];
59
+ if (!value) throw new Error("--from requires a value");
60
+ out.from = value;
61
+ } else if (arg.startsWith("-")) throw new Error(`unknown flag: ${arg}`);
62
+ else out.positional.push(arg);
63
+ }
64
+ return out;
65
+ }
66
+
67
+ function selectEntry(entries: ReadonlyArray<LibraryEntry>, ref: string): LibraryEntry {
68
+ const matches = ref.includes(":")
69
+ ? entries.filter((entry) => libraryEntryRef(entry) === ref)
70
+ : entries.filter((entry) => entry.name === ref);
71
+ if (matches.length === 0) throw new Error(`library entry not found: ${ref}`);
72
+ if (matches.length > 1)
73
+ throw new Error(`library entry is ambiguous; use a typed reference: ${matches.map(libraryEntryRef).join(", ")}`);
74
+ return matches[0] as LibraryEntry;
75
+ }
76
+
77
+ function filtered(entries: ReadonlyArray<LibraryEntry>, kind?: LibraryEntryKind): LibraryEntry[] {
78
+ return entries.filter((entry) => kind === undefined || entry.kind === kind);
79
+ }
80
+
81
+ export async function runLibraryCommand(argv: ReadonlyArray<string>): Promise<number> {
82
+ let parsed: Parsed;
83
+ try {
84
+ parsed = parse(argv);
85
+ } catch (error) {
86
+ printError(error instanceof Error ? error.message : String(error));
87
+ return 2;
88
+ }
89
+ if (!parsed.command || parsed.help) {
90
+ process.stdout.write(HELP);
91
+ return parsed.help ? 0 : 2;
92
+ }
93
+ try {
94
+ if (parsed.command === "list" || parsed.command === "search") {
95
+ const discovery = discoverLibrary();
96
+ const query = parsed.command === "search" ? parsed.positional.join(" ").trim().toLowerCase() : "";
97
+ if (parsed.command === "search" && !query) throw new Error("library search requires a query");
98
+ const entries = filtered(discovery.entries, parsed.kind).filter(
99
+ (entry) => !query || entry.name.toLowerCase().includes(query) || entry.description.toLowerCase().includes(query),
100
+ );
101
+ if (parsed.json)
102
+ process.stdout.write(`${JSON.stringify({ entries, diagnostics: discovery.diagnostics }, null, 2)}\n`);
103
+ else
104
+ for (const entry of entries) process.stdout.write(`${libraryEntryRef(entry).padEnd(28)} ${entry.description}\n`);
105
+ return 0;
106
+ }
107
+ if (parsed.command === "add") {
108
+ const ref = parsed.positional[0];
109
+ if (!ref || parsed.positional.length !== 1) throw new Error("library add requires one reference");
110
+ const catalog = parsed.from && parsed.from !== "catalog" ? parsed.from : undefined;
111
+ const discovery = discoverLibrary(catalog ? { catalog } : {});
112
+ let entry: LibraryEntry;
113
+ try {
114
+ entry = selectEntry(discovery.entries, ref);
115
+ } catch (error) {
116
+ const refusal = ref.includes(":")
117
+ ? discovery.refusals[ref]
118
+ : Object.entries(discovery.refusals).find(([key]) => key.endsWith(`:${ref}`))?.[1];
119
+ if (refusal) throw new Error(refusal);
120
+ throw error;
121
+ }
122
+ const requirements = classifyLibraryRequirements(entry, discovery.entries);
123
+ if (requirements.unsatisfied.length > 0 && !parsed.withRequirements) {
124
+ const refs = requirements.unsatisfied.map(libraryEntryRef);
125
+ if (parsed.json)
126
+ process.stdout.write(
127
+ `${JSON.stringify({ ok: false, entry: libraryEntryRef(entry), satisfiedRequirements: requirements.satisfied.map(libraryEntryRef), unresolvedRequirements: refs }, null, 2)}\n`,
128
+ );
129
+ else
130
+ process.stderr.write(
131
+ `satisfied requirements: ${requirements.satisfied.length > 0 ? requirements.satisfied.map(libraryEntryRef).join(", ") : "none"}\nunresolved requirements: ${refs.join(", ")}\npass --with-requirements to install them in dependency order\n`,
132
+ );
133
+ return 1;
134
+ }
135
+ const plans = [...(parsed.withRequirements ? requirements.unsatisfied : []), entry].map(planLibraryInstall);
136
+ if (parsed.json)
137
+ process.stdout.write(
138
+ `${JSON.stringify({ ok: true, confirmed: parsed.yes, satisfiedRequirements: requirements.satisfied.map(libraryEntryRef), writes: plans.map((plan) => ({ ref: libraryEntryRef(plan.entry), path: plan.path, sha256: plan.sha256 })) }, null, 2)}\n`,
139
+ );
140
+ else {
141
+ process.stdout.write("library add plan:\n");
142
+ process.stdout.write(
143
+ ` satisfied requirements: ${requirements.satisfied.length > 0 ? requirements.satisfied.map(libraryEntryRef).join(", ") : "none"}\n`,
144
+ );
145
+ for (const plan of plans)
146
+ process.stdout.write(` ${libraryEntryRef(plan.entry)} -> ${plan.path} sha256 ${plan.sha256}\n`);
147
+ }
148
+ if (!parsed.yes) return 0;
149
+ for (const plan of plans) installLibraryPlan(plan);
150
+ if (!parsed.json) printOk(`installed ${plans.length} library entry or entries`);
151
+ return 0;
152
+ }
153
+ if (parsed.command === "use") {
154
+ const kind = parsed.positional[0] as LibraryEntryKind | undefined;
155
+ const name = parsed.positional[1];
156
+ if (!kind || !KINDS.has(kind) || !name || parsed.positional.length !== 2)
157
+ throw new Error("library use requires a kind and name");
158
+ // A skill is loaded by the operator from the Skills Hub, never by a CLI
159
+ // verb, so the honest answer names where it lives and how to load it.
160
+ const output =
161
+ kind === "fleet"
162
+ ? `clio-coder fleet run ${name}`
163
+ : kind === "agent"
164
+ ? `/run ${name}`
165
+ : kind === "skill"
166
+ ? `${libraryInstallPath({ kind, name })}\nload it from /skill in the TUI, or ask the model to call context(scope="skills")`
167
+ : name;
168
+ process.stdout.write(`${output}\n`);
169
+ return 0;
170
+ }
171
+ if (parsed.command === "remote") {
172
+ if (parsed.positional[0] !== "confirm" || !parsed.positional[1] || parsed.positional.length !== 2)
173
+ throw new Error("library remote confirm requires a URL");
174
+ confirmLibraryRemote(parsed.positional[1]);
175
+ printOk("confirmed library remote");
176
+ return 0;
177
+ }
178
+ if (parsed.command === "sync" || parsed.command === "push") {
179
+ await syncLibrary(parsed.command);
180
+ printOk(`library ${parsed.command} complete`);
181
+ return 0;
182
+ }
183
+ throw new Error(`unknown library command: ${parsed.command}`);
184
+ } catch (error) {
185
+ const message = error instanceof Error ? error.message : String(error);
186
+ printError(message);
187
+ if (parsed.json) process.stdout.write(`${JSON.stringify({ ok: false, error: message }, null, 2)}\n`);
188
+ return 1;
189
+ }
190
+ }
package/src/cli/share.ts CHANGED
@@ -15,7 +15,7 @@ const HELP = `clio-coder share <command>
15
15
  Export and import portable Clio project/resource archives.
16
16
 
17
17
  Commands:
18
- clio-coder share export --out <path> [--project|--user|--both] [--context] [--prompts] [--skills] [--settings] [--extensions]
18
+ clio-coder share export --out <path> [--project|--user|--both] [--context] [--prompts] [--skills] [--agents] [--fleets] [--settings] [--extensions]
19
19
  clio-coder share import <path> [--dry-run] [--force] [--project|--user] [--json]
20
20
  clio-coder share inspect <path> [--json]
21
21
 
@@ -36,6 +36,8 @@ interface Parsed {
36
36
  includeContext?: boolean;
37
37
  includePrompts?: boolean;
38
38
  includeSkills?: boolean;
39
+ includeAgents?: boolean;
40
+ includeFleets?: boolean;
39
41
  includeSettings?: boolean;
40
42
  includeExtensions?: boolean;
41
43
  }
@@ -93,6 +95,12 @@ function parse(argv: ReadonlyArray<string>): Parsed | null {
93
95
  case "--skills":
94
96
  out.includeSkills = true;
95
97
  break;
98
+ case "--agents":
99
+ out.includeAgents = true;
100
+ break;
101
+ case "--fleets":
102
+ out.includeFleets = true;
103
+ break;
96
104
  case "--settings":
97
105
  out.includeSettings = true;
98
106
  break;
@@ -103,6 +111,8 @@ function parse(argv: ReadonlyArray<string>): Parsed | null {
103
111
  out.includeContext = true;
104
112
  out.includePrompts = true;
105
113
  out.includeSkills = true;
114
+ out.includeAgents = true;
115
+ out.includeFleets = true;
106
116
  out.includeSettings = true;
107
117
  out.includeExtensions = true;
108
118
  break;
@@ -152,6 +162,8 @@ function exportOptions(parsed: Parsed): ShareExportOptions {
152
162
  ...(parsed.includeContext !== undefined ? { includeContext: parsed.includeContext } : {}),
153
163
  ...(parsed.includePrompts !== undefined ? { includePrompts: parsed.includePrompts } : {}),
154
164
  ...(parsed.includeSkills !== undefined ? { includeSkills: parsed.includeSkills } : {}),
165
+ ...(parsed.includeAgents !== undefined ? { includeAgents: parsed.includeAgents } : {}),
166
+ ...(parsed.includeFleets !== undefined ? { includeFleets: parsed.includeFleets } : {}),
155
167
  ...(parsed.includeSettings !== undefined ? { includeSettings: parsed.includeSettings } : {}),
156
168
  ...(parsed.includeExtensions !== undefined ? { includeExtensions: parsed.includeExtensions } : {}),
157
169
  };
package/src/cli/usage.ts CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  import { clioDataDir, clioStateDir } from "../core/xdg.js";
10
10
  import { loadMemoryRecordsSync, type MemoryRecord } from "../domains/memory/index.js";
11
11
  import { readEvidenceIndex } from "../domains/observability/evidence-index.js";
12
+ import { type OutOfTurnUsageRow, readOutOfTurnUsageRows } from "../domains/observability/out-of-turn-usage.js";
12
13
  import { loadSkills } from "../domains/resources/index.js";
13
14
  import {
14
15
  type LedgerUsageCall,
@@ -23,9 +24,10 @@ import { formatColumns, printError } from "./shared.js";
23
24
  const HELP = `clio-coder usage report [--repo <path>] [--days <n>] [--json]
24
25
 
25
26
  Cross-session usage analyzer (experimental, read-only). Reads the local usage
26
- archive (receipts, session ledgers, audit rows, evidence index, memory store)
27
- and reports facts plus improvement opportunities, every line citing ids and
28
- counts. Nothing is written or stored; suggestions are printed only.
27
+ archive (receipts, session ledgers, the out-of-turn usage store, audit rows,
28
+ evidence index, memory store) and reports facts plus improvement opportunities,
29
+ every line citing ids and counts. Nothing is written or stored; suggestions are
30
+ printed only.
29
31
 
30
32
  Flags:
31
33
  --repo <path> restrict sessions (and runs via the run ledger) to one repo
@@ -98,6 +100,54 @@ function addResponseModelIdObservation(counts: ResponseModelIdObservationCounts,
98
100
  addResponseModelIdObservationCount(counts, call.responseModelIdObservation, call.apiCalls ?? 1);
99
101
  }
100
102
 
103
+ /**
104
+ * How the folded calls split between the session's own turns and the rounds
105
+ * that were billed beside it. A `/btw` side question and a `/handoff` round are
106
+ * real spend and belong in the token and cost totals, but neither is a turn:
107
+ * they never entered the session. `turns` therefore subtracts them from the
108
+ * folded row count, which is exactly what the `/cost` overlay does.
109
+ */
110
+ interface CallOrigins {
111
+ rows: number;
112
+ sideQuestions: number;
113
+ handoffs: number;
114
+ }
115
+
116
+ function emptyCallOrigins(): CallOrigins {
117
+ return { rows: 0, sideQuestions: 0, handoffs: 0 };
118
+ }
119
+
120
+ function turnsOf(origins: CallOrigins): number {
121
+ return origins.rows - origins.sideQuestions - origins.handoffs;
122
+ }
123
+
124
+ function hasLabelledCall(origins: CallOrigins): boolean {
125
+ return origins.sideQuestions > 0 || origins.handoffs > 0;
126
+ }
127
+
128
+ function addOutOfTurnRow(origins: CallOrigins, row: OutOfTurnUsageRow): void {
129
+ origins.rows += 1;
130
+ if (row.label === "side-question") origins.sideQuestions += 1;
131
+ else origins.handoffs += 1;
132
+ }
133
+
134
+ /** The out-of-turn store keeps its own usage shape; fold it as one completed call. */
135
+ function outOfTurnUsageCall(row: OutOfTurnUsageRow): LedgerUsageCall {
136
+ return {
137
+ providerId: row.target,
138
+ attributedModelId: row.attributedModelId,
139
+ requestedModelId: row.attributedModelId,
140
+ responseModelIdObservation: { state: "not-observed" },
141
+ input: row.usage.input,
142
+ output: row.usage.output,
143
+ cacheRead: row.usage.cacheRead,
144
+ cacheWrite: row.usage.cacheWrite,
145
+ reasoningTokens: row.usage.reasoning,
146
+ totalTokens: row.usage.totalTokens,
147
+ costUsd: row.usage.costUsd,
148
+ };
149
+ }
150
+
101
151
  function addUsageCall(totals: UsageTotals, call: LedgerUsageCall): void {
102
152
  totals.apiCalls += call.apiCalls ?? 1;
103
153
  totals.input += call.input;
@@ -250,6 +300,13 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
250
300
  (receipt) => repoRunIds === null || repoRunIds.has(receipt.runId),
251
301
  );
252
302
  const sessions = await readSessions(stateDir, windowStart, now, repoHash, diagnostics);
303
+ // Side questions and handoff rounds append nothing to the session ledger by
304
+ // design, so their spend lives in its own store and is folded in here.
305
+ const outOfTurn = readOutOfTurnUsageRows(stateDir);
306
+ for (const error of outOfTurn.errors) diagnostics.notes.push(error);
307
+ const outOfTurnRows = outOfTurn.rows.filter(
308
+ (row) => inWindow(row.timestamp, windowStart, now) && (repoHash === undefined || row.repoIdentity === repoHash),
309
+ );
253
310
  const auditRows = await readAuditRows(stateDir);
254
311
  diagnostics.malformedAuditRows = auditRows.errors.length;
255
312
  const auditInWindow = auditRows.rows.filter((row) => row.ts !== null && inWindow(row.ts, windowStart, now));
@@ -345,23 +402,36 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
345
402
  }
346
403
  >();
347
404
  const usageTotals = emptyUsageTotals();
405
+ const callOrigins = emptyCallOrigins();
406
+ const foldCall = (call: LedgerUsageCall): void => {
407
+ addUsageCall(usageTotals, call);
408
+ const key = `${call.providerId}::${call.attributedModelId}`;
409
+ const entry = usageByModel.get(key) ?? {
410
+ providerId: call.providerId,
411
+ attributedModelId: call.attributedModelId,
412
+ requestedModelIds: new Set<string>(),
413
+ responseModelIdObservationCounts: emptyResponseModelIdObservationCounts(),
414
+ totals: emptyUsageTotals(),
415
+ };
416
+ entry.requestedModelIds.add(call.requestedModelId);
417
+ addResponseModelIdObservation(entry.responseModelIdObservationCounts, call);
418
+ addUsageCall(entry.totals, call);
419
+ usageByModel.set(key, entry);
420
+ };
348
421
  for (const session of sessions) {
349
422
  for (const call of session.usageCalls) {
350
- addUsageCall(usageTotals, call);
351
- const key = `${call.providerId}::${call.attributedModelId}`;
352
- const entry = usageByModel.get(key) ?? {
353
- providerId: call.providerId,
354
- attributedModelId: call.attributedModelId,
355
- requestedModelIds: new Set<string>(),
356
- responseModelIdObservationCounts: emptyResponseModelIdObservationCounts(),
357
- totals: emptyUsageTotals(),
358
- };
359
- entry.requestedModelIds.add(call.requestedModelId);
360
- addResponseModelIdObservation(entry.responseModelIdObservationCounts, call);
361
- addUsageCall(entry.totals, call);
362
- usageByModel.set(key, entry);
423
+ foldCall(call);
424
+ callOrigins.rows += 1;
363
425
  }
364
426
  }
427
+ for (const row of outOfTurnRows) {
428
+ foldCall(outOfTurnUsageCall(row));
429
+ addOutOfTurnRow(callOrigins, row);
430
+ }
431
+ // Token and cost facts need one of their two inputs on disk. A machine whose
432
+ // session store is gone can still have recorded out-of-turn spend, and
433
+ // dropping those rows would report money that was spent as nothing at all.
434
+ const usageMeasurable = presence.sessionsPresent || outOfTurnRows.length > 0;
365
435
  const usageRows = [...usageByModel.values()].sort(
366
436
  (a, b) => b.totals.totalTokens - a.totals.totalTokens || a.providerId.localeCompare(b.providerId),
367
437
  );
@@ -443,8 +513,22 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
443
513
  if (presence.receiptsPresent) emit({ kind: "fact", fact: "dispatch-runs", value: receipts.length });
444
514
  else emit({ kind: "fact", fact: "receipt-store-missing", path: presence.receiptsPath });
445
515
  emit({ kind: "fact", fact: "audit-tool-calls", value: auditToolCalls.length, blocked: auditBlocked.length });
446
- if (presence.sessionsPresent) {
447
- emit({ kind: "fact", fact: "tokens", ...usageTotals });
516
+ if (usageMeasurable) {
517
+ // The origin split is emitted only when something out of turn was
518
+ // recorded, so a report over an archive with no `/btw` or `/handoff`
519
+ // round in it stays byte-identical to what it printed before.
520
+ emit({
521
+ kind: "fact",
522
+ fact: "tokens",
523
+ ...usageTotals,
524
+ ...(hasLabelledCall(callOrigins)
525
+ ? {
526
+ turns: turnsOf(callOrigins),
527
+ sideQuestions: callOrigins.sideQuestions,
528
+ handoffs: callOrigins.handoffs,
529
+ }
530
+ : {}),
531
+ });
448
532
  for (const row of usageRows) {
449
533
  emit({
450
534
  kind: "fact",
@@ -505,10 +589,18 @@ export async function runUsageCommand(argv: ReadonlyArray<string>): Promise<numb
505
589
  out(` receipt store missing at ${presence.receiptsPath}`);
506
590
  }
507
591
  out(` audited tool calls in window: ${auditToolCalls.length} (${auditBlocked.length} blocked/denied)`);
508
- if (presence.sessionsPresent) {
592
+ if (usageMeasurable) {
509
593
  out(
510
594
  ` tokens in window: ${usageTotals.totalTokens} over ${usageTotals.apiCalls} model calls (input ${usageTotals.input}, output ${usageTotals.output}, cache read ${usageTotals.cacheRead}, cache write ${usageTotals.cacheWrite}, reasoning ${usageTotals.reasoningTokens})`,
511
595
  );
596
+ if (hasLabelledCall(callOrigins)) {
597
+ // Only printed when a labelled call is in the window. Over an archive
598
+ // with none, these three lines would say nothing the line above does
599
+ // not already say, and their absence keeps the older output intact.
600
+ out(` turns in window: ${turnsOf(callOrigins)}`);
601
+ if (callOrigins.sideQuestions > 0) out(` side questions in window: ${callOrigins.sideQuestions}`);
602
+ if (callOrigins.handoffs > 0) out(` handoffs in window: ${callOrigins.handoffs}`);
603
+ }
512
604
  out(` provider-reported cost in window: $${usageTotals.costUsd.toFixed(4)}`);
513
605
  }
514
606
  if (usageRows.length > 0) {
@@ -487,6 +487,8 @@ export interface DispatchRunIdentity {
487
487
  node?: string | undefined;
488
488
  /** Review/compete gate role and cycle, for fleet board badges. */
489
489
  gate?: { role: string; cycle: number } | undefined;
490
+ /** Council group presentation data for the Fleet Runs board. */
491
+ council?: { group: string; label: string; color?: string; round: number } | undefined;
490
492
  /** Dead-node failover hops recorded on this run's chain so far. */
491
493
  rerouteCount?: number | undefined;
492
494
  /** Model context window in tokens, for the per-worker context meter. */
@@ -572,6 +574,8 @@ export interface DispatchTerminalStats {
572
574
  exitCode: number;
573
575
  /** Honest activity record aggregated from the run's tool telemetry; null when the receipt predates it. */
574
576
  toolActivity: ToolActivitySummary | null;
577
+ /** Host-run declared verification status when the request included checks. */
578
+ hostVerification?: "verified" | "rejected" | "skipped";
575
579
  }
576
580
 
577
581
  /** Published on {@link BusChannels.DispatchCompleted} when a run finalizes as succeeded. */
@@ -16,7 +16,7 @@ export const CLIO_COMMIT_TRAILERS = {
16
16
  } as const;
17
17
 
18
18
  export interface CommitReceiptEvidence {
19
- version: 15;
19
+ version: 19;
20
20
  algorithm: "sha256";
21
21
  digest: string;
22
22
  /** The receipt was checked against its run-ledger envelope. */
@@ -58,7 +58,7 @@ const KNOWN_CLIO_TRAILERS = new Set(
58
58
  );
59
59
 
60
60
  function isClioTrailer(key: string): boolean {
61
- return KNOWN_CLIO_TRAILERS.has(key) || key.startsWith("clio-evidence:receipt-v15/sha256:");
61
+ return KNOWN_CLIO_TRAILERS.has(key) || key.startsWith("clio-evidence:receipt-v19/sha256:");
62
62
  }
63
63
 
64
64
  /**
@@ -87,7 +87,7 @@ function trailerBlockStart(lines: ReadonlyArray<string>): number | null {
87
87
 
88
88
  function receiptTrailer(receipt: CommitReceiptEvidence | undefined): string | null {
89
89
  if (
90
- receipt?.version !== 15 ||
90
+ receipt?.version !== 19 ||
91
91
  receipt.algorithm !== "sha256" ||
92
92
  receipt.integrityValid !== true ||
93
93
  receipt.directlyRelevant !== true ||
@@ -95,7 +95,7 @@ function receiptTrailer(receipt: CommitReceiptEvidence | undefined): string | nu
95
95
  ) {
96
96
  return null;
97
97
  }
98
- return `Clio-Evidence: receipt-v15/sha256:${receipt.digest}`;
98
+ return `Clio-Evidence: receipt-v19/sha256:${receipt.digest}`;
99
99
  }
100
100
 
101
101
  /**