@starlove/orbit 1.4.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/Dockerfile +10 -8
  2. package/README.md +146 -164
  3. package/dist/full/csp.txt +1 -0
  4. package/dist/full/fonts/JetBrains_Mono/JetBrainsMono-subset.woff2 +0 -0
  5. package/dist/full/fonts/JetBrains_Mono/README.txt +5 -0
  6. package/dist/full/fonts/Mona_Sans/MonaSans-subset.woff2 +0 -0
  7. package/{public/fonts/Open_Sans → dist/full/fonts/Mona_Sans}/OFL.txt +93 -93
  8. package/dist/full/fonts/Mona_Sans/README.txt +10 -0
  9. package/{public/fonts/JetBrains_Mono → dist/full/fonts/Newsreader}/OFL.txt +93 -93
  10. package/dist/full/fonts/Newsreader/README.txt +8 -0
  11. package/dist/full/fonts/Newsreader/newsreader.woff2 +0 -0
  12. package/dist/full/index.html +36 -653
  13. package/dist/full/js/app.BmuponPJ.js +32 -0
  14. package/dist/full/js/app.BmuponPJ.js.map +1 -0
  15. package/dist/full/js/chunk.1fJGQGbW.js +2 -0
  16. package/dist/full/js/chunk.1fJGQGbW.js.map +1 -0
  17. package/dist/full/js/chunk.5D7JO2zp.js +2 -0
  18. package/dist/full/js/chunk.5D7JO2zp.js.map +1 -0
  19. package/dist/full/js/chunk.BrNn_D79.js +2 -0
  20. package/dist/full/js/chunk.BrNn_D79.js.map +1 -0
  21. package/dist/full/js/chunk.CokJXIqM.js +2 -0
  22. package/dist/full/js/chunk.CokJXIqM.js.map +1 -0
  23. package/dist/full/js/chunk.D_Haqy6R.js +2 -0
  24. package/dist/full/js/chunk.D_Haqy6R.js.map +1 -0
  25. package/dist/full/js/chunk.RO0jsH6I.js +15 -0
  26. package/dist/full/js/chunk.RO0jsH6I.js.map +1 -0
  27. package/dist/full/js/chunk.dqWOEtBM.js +2 -0
  28. package/dist/full/js/chunk.dqWOEtBM.js.map +1 -0
  29. package/dist/full/js/warm.f260bbbc.js +15 -0
  30. package/dist/full/orbits-favicon.png +0 -0
  31. package/dist/full/orbits-logo-bg-wide.png +0 -0
  32. package/dist/full/orbits-logo-bg.png +0 -0
  33. package/dist/full/orbits-logo.png +0 -0
  34. package/dist/full/styles.2b154ffe.css +1 -0
  35. package/dist/full/vendor/starlove-ui/theme-init.js +66 -0
  36. package/dist/full/version.json +2 -2
  37. package/docs/AGENT_GUIDE.md +114 -0
  38. package/docs/UPDATING.md +249 -64
  39. package/lib/adapters/indexeddb/blobs.d.ts +3 -0
  40. package/lib/adapters/indexeddb/blobs.js +54 -0
  41. package/lib/adapters/indexeddb/database.d.ts +60 -0
  42. package/lib/adapters/indexeddb/database.js +126 -0
  43. package/lib/adapters/indexeddb/index.d.ts +5 -0
  44. package/lib/adapters/indexeddb/index.js +3 -0
  45. package/lib/adapters/indexeddb/locks.d.ts +14 -0
  46. package/lib/adapters/indexeddb/locks.js +40 -0
  47. package/lib/adapters/indexeddb/store.d.ts +40 -0
  48. package/lib/adapters/indexeddb/store.js +424 -0
  49. package/lib/adapters/indexeddb/tables.d.ts +43 -0
  50. package/lib/adapters/indexeddb/tables.js +127 -0
  51. package/lib/adapters/memory/blobs.d.ts +3 -0
  52. package/lib/adapters/memory/blobs.js +44 -0
  53. package/lib/adapters/memory/board.d.ts +41 -0
  54. package/lib/adapters/memory/board.js +521 -0
  55. package/lib/adapters/memory/index.d.ts +2 -0
  56. package/lib/adapters/memory/index.js +2 -0
  57. package/lib/adapters/memory/search.d.ts +6 -0
  58. package/lib/adapters/memory/search.js +30 -0
  59. package/lib/adapters/memory/store.d.ts +34 -0
  60. package/lib/adapters/memory/store.js +266 -0
  61. package/lib/adapters/sqlite/backups.d.ts +53 -0
  62. package/lib/adapters/sqlite/backups.js +232 -0
  63. package/lib/adapters/sqlite/blobs.d.ts +14 -0
  64. package/lib/adapters/sqlite/blobs.js +109 -0
  65. package/lib/adapters/sqlite/board.d.ts +77 -0
  66. package/lib/adapters/sqlite/board.js +328 -0
  67. package/lib/adapters/sqlite/database.d.ts +67 -0
  68. package/lib/adapters/sqlite/database.js +285 -0
  69. package/lib/adapters/sqlite/index.d.ts +3 -0
  70. package/lib/adapters/sqlite/index.js +2 -0
  71. package/lib/adapters/sqlite/lock.d.ts +11 -0
  72. package/lib/adapters/sqlite/lock.js +34 -0
  73. package/lib/adapters/sqlite/records.d.ts +54 -0
  74. package/lib/adapters/sqlite/records.js +546 -0
  75. package/lib/adapters/sqlite/schema.d.ts +54 -0
  76. package/lib/adapters/sqlite/schema.js +276 -0
  77. package/lib/adapters/sqlite/store.d.ts +39 -0
  78. package/lib/adapters/sqlite/store.js +385 -0
  79. package/lib/browser/in-page.d.ts +31 -0
  80. package/lib/browser/in-page.js +46 -0
  81. package/lib/browser/old-preview.d.ts +13 -0
  82. package/lib/browser/old-preview.js +80 -0
  83. package/lib/browser/preview-board.d.ts +8 -0
  84. package/lib/browser/preview-board.js +69 -0
  85. package/lib/cli/main.d.ts +7 -0
  86. package/lib/cli/main.js +343 -0
  87. package/lib/cli/orbit.d.ts +8 -0
  88. package/lib/cli/orbit.js +25 -0
  89. package/lib/client/http.d.ts +38 -0
  90. package/lib/client/http.js +334 -0
  91. package/lib/client/local.d.ts +26 -0
  92. package/lib/client/local.js +190 -0
  93. package/lib/client/object-url.d.ts +8 -0
  94. package/lib/client/object-url.js +21 -0
  95. package/lib/client/types.d.ts +268 -0
  96. package/lib/client/types.js +8 -0
  97. package/lib/commands/agent-tools.d.ts +31 -0
  98. package/lib/commands/agent-tools.js +100 -0
  99. package/lib/commands/index.d.ts +56 -0
  100. package/lib/commands/index.js +298 -0
  101. package/lib/commands/parse.d.ts +73 -0
  102. package/lib/commands/parse.js +231 -0
  103. package/lib/commands/present.d.ts +134 -0
  104. package/lib/commands/present.js +198 -0
  105. package/lib/commands/session.d.ts +85 -0
  106. package/lib/commands/session.js +138 -0
  107. package/lib/commands/verbs.d.ts +35 -0
  108. package/lib/commands/verbs.js +842 -0
  109. package/lib/core/actors.d.ts +18 -0
  110. package/lib/core/actors.js +45 -0
  111. package/lib/core/agent.d.ts +128 -0
  112. package/lib/core/agent.js +323 -0
  113. package/lib/core/boards.d.ts +113 -0
  114. package/lib/core/boards.js +288 -0
  115. package/lib/core/bootstrap.d.ts +47 -0
  116. package/lib/core/bootstrap.js +100 -0
  117. package/lib/core/bytes.d.ts +10 -0
  118. package/lib/core/bytes.js +52 -0
  119. package/lib/core/card-paths.d.ts +25 -0
  120. package/lib/core/card-paths.js +44 -0
  121. package/lib/core/context.d.ts +60 -0
  122. package/lib/core/context.js +42 -0
  123. package/lib/core/cross-board.d.ts +81 -0
  124. package/lib/core/cross-board.js +228 -0
  125. package/lib/core/describe.d.ts +21 -0
  126. package/lib/core/describe.js +81 -0
  127. package/lib/core/errors.d.ts +159 -0
  128. package/lib/core/errors.js +160 -0
  129. package/lib/core/files.d.ts +79 -0
  130. package/lib/core/files.js +262 -0
  131. package/lib/core/history.d.ts +20 -0
  132. package/lib/core/history.js +53 -0
  133. package/lib/core/image-types.d.ts +16 -0
  134. package/lib/core/image-types.js +36 -0
  135. package/lib/core/model.d.ts +263 -0
  136. package/lib/core/model.js +34 -0
  137. package/lib/core/nebula-link.d.ts +14 -0
  138. package/lib/core/nebula-link.js +39 -0
  139. package/lib/core/relations.d.ts +58 -0
  140. package/lib/core/relations.js +112 -0
  141. package/lib/core/search.d.ts +38 -0
  142. package/lib/core/search.js +92 -0
  143. package/lib/core/sessions.d.ts +44 -0
  144. package/lib/core/sessions.js +158 -0
  145. package/lib/core/snapshot-schema.d.ts +295 -0
  146. package/lib/core/snapshot-schema.js +82 -0
  147. package/lib/core/snapshots.d.ts +75 -0
  148. package/lib/core/snapshots.js +409 -0
  149. package/lib/core/states.d.ts +25 -0
  150. package/lib/core/states.js +126 -0
  151. package/lib/core/text.d.ts +40 -0
  152. package/lib/core/text.js +113 -0
  153. package/lib/core/tickets.d.ts +69 -0
  154. package/lib/core/tickets.js +311 -0
  155. package/lib/core/trello.d.ts +17 -0
  156. package/lib/core/trello.js +269 -0
  157. package/lib/core/verdicts.d.ts +28 -0
  158. package/lib/core/verdicts.js +92 -0
  159. package/lib/core/views.d.ts +95 -0
  160. package/lib/core/views.js +186 -0
  161. package/lib/http/app.d.ts +46 -0
  162. package/lib/http/app.js +491 -0
  163. package/lib/mcp-server.d.ts +10 -0
  164. package/lib/mcp-server.js +120 -0
  165. package/lib/node/assets.d.ts +7 -0
  166. package/lib/node/assets.js +68 -0
  167. package/lib/node/data-folder.d.ts +21 -0
  168. package/lib/node/data-folder.js +34 -0
  169. package/lib/node/env.d.ts +38 -0
  170. package/lib/node/env.js +49 -0
  171. package/lib/node/host-check.d.ts +24 -0
  172. package/lib/node/host-check.js +53 -0
  173. package/lib/node/host-services.d.ts +9 -0
  174. package/lib/node/host-services.js +150 -0
  175. package/lib/node/local.d.ts +22 -0
  176. package/lib/node/local.js +61 -0
  177. package/lib/node/migrate.d.ts +53 -0
  178. package/lib/node/migrate.js +635 -0
  179. package/lib/node/package.d.ts +7 -0
  180. package/lib/node/package.js +14 -0
  181. package/lib/node/repo-board.d.ts +49 -0
  182. package/lib/node/repo-board.js +245 -0
  183. package/lib/node/serve.d.ts +8 -0
  184. package/lib/node/serve.js +106 -0
  185. package/lib/orbit.d.ts +47 -0
  186. package/lib/orbit.js +44 -0
  187. package/lib/quiet-sqlite-warning.d.ts +1 -0
  188. package/lib/quiet-sqlite-warning.js +18 -0
  189. package/lib/store/blob-path.d.ts +6 -0
  190. package/lib/store/blob-path.js +12 -0
  191. package/lib/store/conformance.d.ts +52 -0
  192. package/lib/store/conformance.js +1449 -0
  193. package/lib/store/search-words.d.ts +10 -0
  194. package/lib/store/search-words.js +19 -0
  195. package/lib/store/types.d.ts +452 -0
  196. package/lib/store/types.js +34 -0
  197. package/llms.txt +63 -0
  198. package/package.json +109 -25
  199. package/src/cli/orbit.js +11 -658
  200. package/src/mcp-server.js +16 -876
  201. package/SKILL-ORBIT.md +0 -151
  202. package/build.mjs +0 -210
  203. package/dist/full/js/app.4e6fbe20.js +0 -952
  204. package/dist/full/js/app.4e6fbe20.js.map +0 -7
  205. package/dist/full/styles.4e60d824.css +0 -1
  206. package/docs/AGENT_PROTOCOL.md +0 -424
  207. package/docs/MCP_SETUP.md +0 -54
  208. package/docs/ORBIT_DISPATCH.md +0 -280
  209. package/docs/SS-Orbit-Dark.png +0 -0
  210. package/docs/SS-Orbit-Light.png +0 -0
  211. package/docs/mcp-client.example.json +0 -13
  212. package/docs/setup/orbit-init-wizard.md +0 -174
  213. package/public/apple-touch-icon.png +0 -0
  214. package/public/cursors/live_arrow.cur +0 -0
  215. package/public/cursors/live_link.cur +0 -0
  216. package/public/cursors/live_move.cur +0 -0
  217. package/public/cursors/live_select.cur +0 -0
  218. package/public/cursors/live_unavail.cur +0 -0
  219. package/public/favicon-32x32.png +0 -0
  220. package/public/fonts/Chakra_Petch/ChakraPetch-Bold.ttf +0 -0
  221. package/public/fonts/Chakra_Petch/ChakraPetch-BoldItalic.ttf +0 -0
  222. package/public/fonts/Chakra_Petch/ChakraPetch-Italic.ttf +0 -0
  223. package/public/fonts/Chakra_Petch/ChakraPetch-Light.ttf +0 -0
  224. package/public/fonts/Chakra_Petch/ChakraPetch-LightItalic.ttf +0 -0
  225. package/public/fonts/Chakra_Petch/ChakraPetch-Medium.ttf +0 -0
  226. package/public/fonts/Chakra_Petch/ChakraPetch-MediumItalic.ttf +0 -0
  227. package/public/fonts/Chakra_Petch/ChakraPetch-Regular.ttf +0 -0
  228. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBold.ttf +0 -0
  229. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBoldItalic.ttf +0 -0
  230. package/public/fonts/Chakra_Petch/OFL.txt +0 -93
  231. package/public/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf +0 -0
  232. package/public/fonts/Inter/Inter-VariableFont_opsz,wght.ttf +0 -0
  233. package/public/fonts/Inter/OFL.txt +0 -93
  234. package/public/fonts/Inter/README.txt +0 -118
  235. package/public/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  236. package/public/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf +0 -0
  237. package/public/fonts/JetBrains_Mono/README.txt +0 -79
  238. package/public/fonts/OpenRing-Regular.ttf +0 -0
  239. package/public/fonts/Open_Sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  240. package/public/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  241. package/public/fonts/Open_Sans/README.txt +0 -100
  242. package/public/fonts/Orbitron/OFL.txt +0 -93
  243. package/public/fonts/Orbitron/Orbitron-VariableFont_wght.ttf +0 -0
  244. package/public/fonts/Orbitron/README.txt +0 -68
  245. package/public/fonts/Rajdhani/OFL.txt +0 -93
  246. package/public/fonts/Rajdhani/Rajdhani-Bold.ttf +0 -0
  247. package/public/fonts/Rajdhani/Rajdhani-Light.ttf +0 -0
  248. package/public/fonts/Rajdhani/Rajdhani-Medium.ttf +0 -0
  249. package/public/fonts/Rajdhani/Rajdhani-Regular.ttf +0 -0
  250. package/public/fonts/Rajdhani/Rajdhani-SemiBold.ttf +0 -0
  251. package/public/fonts/runescape-uf.ttf +0 -0
  252. package/public/index.html +0 -769
  253. package/public/js/actor-labels.js +0 -65
  254. package/public/js/api.js +0 -39
  255. package/public/js/app.js +0 -45
  256. package/public/js/artifact-drawer.js +0 -79
  257. package/public/js/board-export.js +0 -161
  258. package/public/js/board-menu.js +0 -374
  259. package/public/js/card-actions.js +0 -545
  260. package/public/js/config.js +0 -20
  261. package/public/js/create-card.js +0 -190
  262. package/public/js/dom.js +0 -19
  263. package/public/js/drawer.js +0 -273
  264. package/public/js/font-preference.js +0 -230
  265. package/public/js/format.js +0 -433
  266. package/public/js/help-menu.js +0 -31
  267. package/public/js/icons.js +0 -16
  268. package/public/js/kanban.js +0 -694
  269. package/public/js/local-backend.js +0 -1015
  270. package/public/js/main.js +0 -161
  271. package/public/js/modal.js +0 -33
  272. package/public/js/motion-preference.js +0 -64
  273. package/public/js/panel.js +0 -58
  274. package/public/js/router.js +0 -134
  275. package/public/js/search.js +0 -56
  276. package/public/js/settings-tabs.js +0 -7
  277. package/public/js/settings.js +0 -1634
  278. package/public/js/sse.js +0 -159
  279. package/public/js/starscape.js +0 -332
  280. package/public/js/state.js +0 -129
  281. package/public/js/text-editing.js +0 -128
  282. package/public/js/theme-preference.js +0 -95
  283. package/public/js/ticket-detail.js +0 -1516
  284. package/public/js/ticket-typeahead.js +0 -49
  285. package/public/js/toast.js +0 -89
  286. package/public/js/topbar-notes.js +0 -155
  287. package/public/js/transport.js +0 -22
  288. package/public/js/typeahead.js +0 -206
  289. package/public/js/unread.js +0 -121
  290. package/public/js/update-check.js +0 -58
  291. package/public/js/url-routes.js +0 -94
  292. package/public/orbits-favicon.png +0 -0
  293. package/public/orbits-logo-bg-wide.png +0 -0
  294. package/public/orbits-logo-bg.png +0 -0
  295. package/public/orbits-logo.png +0 -0
  296. package/public/styles.css +0 -7709
  297. package/src/core/agent.js +0 -387
  298. package/src/core/agents-md.js +0 -109
  299. package/src/core/artifacts.js +0 -149
  300. package/src/core/attachments.js +0 -238
  301. package/src/core/auth.js +0 -85
  302. package/src/core/backups.js +0 -142
  303. package/src/core/board.js +0 -148
  304. package/src/core/boards.js +0 -409
  305. package/src/core/bootstrap.js +0 -170
  306. package/src/core/css-bundle.js +0 -30
  307. package/src/core/db.js +0 -315
  308. package/src/core/delete-board.js +0 -163
  309. package/src/core/dispatch.js +0 -1007
  310. package/src/core/events.js +0 -314
  311. package/src/core/http.js +0 -115
  312. package/src/core/migrate.js +0 -198
  313. package/src/core/paths.js +0 -55
  314. package/src/core/provision-repo-board.js +0 -119
  315. package/src/core/queries.js +0 -246
  316. package/src/core/registry.js +0 -211
  317. package/src/core/relations.js +0 -163
  318. package/src/core/review-verdicts.js +0 -138
  319. package/src/core/router.js +0 -556
  320. package/src/core/search.js +0 -183
  321. package/src/core/seed.js +0 -234
  322. package/src/core/snapshots.js +0 -692
  323. package/src/core/states.js +0 -167
  324. package/src/core/system-picker.js +0 -109
  325. package/src/core/tickets.js +0 -400
  326. package/src/core/util.js +0 -106
  327. package/src/core/version-check.js +0 -154
  328. package/src/mcp/orbit-client.js +0 -287
  329. package/src/server.js +0 -115
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The command language's answers: compact, line by line, cards as #n, lanes
3
+ * by name, no ids. Pure functions over plain models, so every transport (the
4
+ * CLI, MCP, HTTP) prints the same thing. These formats are a public contract,
5
+ * with size budgets.
6
+ *
7
+ * What people wrote can't pass for Orbit's own words: a title is quoted
8
+ * wherever more of the line follows it; names and labels are folded to one
9
+ * line; multi-line text sits indented under its heading, so every line that
10
+ * starts at the left edge is Orbit's.
11
+ */
12
+ import { laneText, oneLine } from "../core/describe.ts";
13
+ import type { Priority } from "../core/model.ts";
14
+ export { laneText, oneLine };
15
+ /** Orbit stores priority 0 to 4; people and agents see the app's words. */
16
+ export declare const PRIORITY_WORDS: Readonly<Record<number, string>>;
17
+ /** Who wrote something, for an agent: "a person" for someone in the app, else the agent's name, on one line. */
18
+ export declare function authorText(name: unknown): string;
19
+ /** The same, as a token for --json: "person" for someone in the app, else the agent's name. */
20
+ export declare function authorKey(name: unknown): string;
21
+ export declare function plural(count: number, one: string, many?: string): string;
22
+ export declare function priorityWord(priority: number): string;
23
+ /** "3h", "2d": how long ago, or "" under an hour (fresh is the default). */
24
+ export declare function age(iso: string | null | undefined, nowMs?: number): string;
25
+ /** A title inside a line: quoted, so nothing in it reads as the line's own markers. `max` counts the quoted form. */
26
+ export declare function quoted(title: unknown, max?: number): string;
27
+ export interface CardHolder {
28
+ name: string;
29
+ since: string;
30
+ }
31
+ /** A card as a view lists it. */
32
+ export interface CardLine {
33
+ n: number;
34
+ title: string;
35
+ type: string;
36
+ priority: Priority;
37
+ labels: string[];
38
+ parent: number | null;
39
+ sub: number;
40
+ /** Card numbers on this board; `slug#n` for a card on another board. */
41
+ blockedBy: (number | string)[];
42
+ holder: CardHolder | null;
43
+ comments: number;
44
+ }
45
+ /** `#3 bug high "Title" [labels] ^#1 (2 sub) blocked by #2 @crea 3h 1c` */
46
+ export declare function cardLine(card: CardLine, { nowMs }?: {
47
+ nowMs?: number;
48
+ }): string;
49
+ export interface ViewLane {
50
+ name: string;
51
+ role: string | null;
52
+ closed: boolean;
53
+ cards: (CardLine & {
54
+ id: string;
55
+ })[];
56
+ }
57
+ export interface ViewModel {
58
+ slug: string;
59
+ name: string;
60
+ open: number;
61
+ hasRules: boolean;
62
+ journalCount: number;
63
+ lanes: ViewLane[];
64
+ }
65
+ /** The board: open lanes list their cards (up to `cap` each); closed lanes (Done, Cancelled) show as counts unless `all`. */
66
+ export declare function renderView(model: ViewModel, options?: {
67
+ all?: boolean;
68
+ lane?: string | null;
69
+ cap?: number;
70
+ hint?: (line: string) => string;
71
+ nowMs?: number;
72
+ shell?: boolean;
73
+ }): string;
74
+ export interface CardBrief {
75
+ n: number;
76
+ title: string;
77
+ lane?: string | undefined;
78
+ /** Set for a card on another board than the one in view: its slug. */
79
+ board?: string | undefined;
80
+ }
81
+ /** A short reference to another card: `#2 "Trello import" (Todo)`. */
82
+ export declare function cardRef(card: CardBrief, { lane }?: {
83
+ lane?: boolean;
84
+ }): string;
85
+ /**
86
+ * Multi-line text, each line indented under its heading. Every way of
87
+ * breaking a line becomes a real line break (and so gets the indent), and
88
+ * other control characters are dropped.
89
+ */
90
+ export declare function block(text: unknown, indent?: string): string;
91
+ /** `Label: text` when the text is one line, else the label alone with the text indented under it. */
92
+ export declare function labelled(label: string, text: unknown): string;
93
+ export interface CommentLine {
94
+ author: string;
95
+ kind: string;
96
+ body: string;
97
+ at: string;
98
+ }
99
+ export declare function renderComments(comments: CommentLine[], { limit }?: {
100
+ limit?: number;
101
+ }): string;
102
+ export interface CardModel {
103
+ n: number;
104
+ title: string;
105
+ type: string;
106
+ priority: number;
107
+ lane: string;
108
+ archived: boolean;
109
+ labels: string[];
110
+ author: string;
111
+ holder: {
112
+ name: string;
113
+ id: string | null;
114
+ since: string;
115
+ } | null;
116
+ link: string;
117
+ parent: CardBrief | null;
118
+ children: CardBrief[];
119
+ blockedBy: CardBrief[];
120
+ blocks: CardBrief[];
121
+ related: CardBrief[];
122
+ description: string;
123
+ plan: string;
124
+ summary: string;
125
+ revisions: string;
126
+ nebula: string;
127
+ commentCount: number;
128
+ }
129
+ /** One card: title, a facts line (type · priority · lane · labels · author · link), its links, then its text. */
130
+ export declare function renderCard(card: CardModel, options?: {
131
+ comments?: CommentLine[] | null;
132
+ hint?: (line: string) => string;
133
+ nowMs?: number;
134
+ }): string;
@@ -0,0 +1,198 @@
1
+ /**
2
+ * The command language's answers: compact, line by line, cards as #n, lanes
3
+ * by name, no ids. Pure functions over plain models, so every transport (the
4
+ * CLI, MCP, HTTP) prints the same thing. These formats are a public contract,
5
+ * with size budgets.
6
+ *
7
+ * What people wrote can't pass for Orbit's own words: a title is quoted
8
+ * wherever more of the line follows it; names and labels are folded to one
9
+ * line; multi-line text sits indented under its heading, so every line that
10
+ * starts at the left edge is Orbit's.
11
+ */
12
+ import { laneText, oneLine } from "../core/describe.js";
13
+ import { asText } from "../core/text.js";
14
+ export { laneText, oneLine };
15
+ /** Orbit stores priority 0 to 4; people and agents see the app's words. */
16
+ export const PRIORITY_WORDS = Object.freeze({ 0: "maybe", 1: "low", 2: "med", 3: "high", 4: "urgent" });
17
+ /** The default priority goes unsaid in a view's card line (one card's facts always say it). */
18
+ const QUIET_PRIORITY = 2;
19
+ /** The names Orbit stores for a person in the app (it has no accounts), as the app's actor labels know them. */
20
+ const PERSON_NAMES = new Set(["local", "local-owner", "owner", "human"]);
21
+ /** Who wrote something, for an agent: "a person" for someone in the app, else the agent's name, on one line. */
22
+ export function authorText(name) {
23
+ const clean = oneLine(name, 40);
24
+ return PERSON_NAMES.has(clean.toLowerCase()) ? "a person" : clean;
25
+ }
26
+ /** The same, as a token for --json: "person" for someone in the app, else the agent's name. */
27
+ export function authorKey(name) {
28
+ const clean = oneLine(name, 40);
29
+ return PERSON_NAMES.has(clean.toLowerCase()) ? "person" : clean;
30
+ }
31
+ export function plural(count, one, many = `${one}s`) {
32
+ return `${count} ${count === 1 ? one : many}`;
33
+ }
34
+ export function priorityWord(priority) {
35
+ return PRIORITY_WORDS[priority] ?? PRIORITY_WORDS[QUIET_PRIORITY] ?? "med";
36
+ }
37
+ /** "3h", "2d": how long ago, or "" under an hour (fresh is the default). */
38
+ export function age(iso, nowMs = Date.now()) {
39
+ const then = Date.parse(iso ?? "");
40
+ if (!Number.isFinite(then))
41
+ return "";
42
+ const minutes = Math.floor((nowMs - then) / 60_000);
43
+ if (minutes < 60)
44
+ return "";
45
+ const hours = Math.floor(minutes / 60);
46
+ if (hours < 48)
47
+ return `${hours}h`;
48
+ return `${Math.floor(hours / 24)}d`;
49
+ }
50
+ /** A title inside a line: quoted, so nothing in it reads as the line's own markers. `max` counts the quoted form. */
51
+ export function quoted(title, max = 120) {
52
+ const full = oneLine(title, 100_000);
53
+ for (let cut = Math.min(full.length, max); cut > 1; cut -= 1) {
54
+ const text = cut < full.length ? `${full.slice(0, cut - 1).trimEnd()}…` : full;
55
+ const out = JSON.stringify(text);
56
+ if (out.length <= max + 2)
57
+ return out;
58
+ }
59
+ return JSON.stringify("…");
60
+ }
61
+ /** A label as one bare run: no brackets or commas to close the list early. */
62
+ function labelText(label) {
63
+ return oneLine(label, 40).replace(/[[\],]/g, "").trim();
64
+ }
65
+ /** `#3 bug high "Title" [labels] ^#1 (2 sub) blocked by #2 @crea 3h 1c` */
66
+ export function cardLine(card, { nowMs } = {}) {
67
+ const parts = [`#${card.n}`];
68
+ if (card.type === "bug" || card.type === "epic")
69
+ parts.push(card.type);
70
+ if (card.priority !== QUIET_PRIORITY)
71
+ parts.push(priorityWord(card.priority));
72
+ parts.push(quoted(card.title));
73
+ if (card.labels.length)
74
+ parts.push(`[${card.labels.map(labelText).join(",")}]`);
75
+ if (card.parent)
76
+ parts.push(`^#${card.parent}`);
77
+ if (card.sub)
78
+ parts.push(`(${card.sub} sub)`);
79
+ if (card.blockedBy.length)
80
+ parts.push(`blocked by ${card.blockedBy.map((n) => (typeof n === "number" ? `#${n}` : n)).join(",")}`);
81
+ if (card.holder) {
82
+ const since = age(card.holder.since, nowMs);
83
+ parts.push(`@${oneLine(card.holder.name, 40).replace(/\s+/g, "-")}${since ? ` ${since}` : ""}`);
84
+ }
85
+ if (card.comments)
86
+ parts.push(`${card.comments}c`);
87
+ return parts.join(" ");
88
+ }
89
+ /** The board: open lanes list their cards (up to `cap` each); closed lanes (Done, Cancelled) show as counts unless `all`. */
90
+ export function renderView(model, options = {}) {
91
+ const { all = false, lane = null, cap = 20, hint = (line) => line, nowMs, shell = false } = options;
92
+ const named = model.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") === model.slug ? "" : ` (${quoted(model.name, 60)})`;
93
+ const lines = [`Orbit board "${model.slug}"${named}: ${model.open} open. Cards are #n${shell ? " (in a shell: orbit card 12)" : ""}, med unless marked; lanes by name.`];
94
+ if (model.hasRules || model.journalCount) {
95
+ const what = [model.hasRules ? "board rules" : "", model.journalCount ? plural(model.journalCount, "entry", "entries") : ""].filter(Boolean).join(", ");
96
+ lines.push(`Read first: ${hint("journal")} (${what})`);
97
+ }
98
+ const hidden = [];
99
+ for (const column of model.lanes) {
100
+ if (lane && column.name !== lane)
101
+ continue;
102
+ if (column.closed && !all && !lane) {
103
+ hidden.push(`${laneText(column.name)} ${column.cards.length}`);
104
+ continue;
105
+ }
106
+ lines.push(`${laneText(column.name)} (${column.cards.length})`);
107
+ const limit = all || lane ? column.cards.length : cap;
108
+ for (const card of column.cards.slice(0, limit))
109
+ lines.push(` ${cardLine(card, { nowMs })}`);
110
+ if (column.cards.length > limit)
111
+ lines.push(` … ${column.cards.length - limit} more (${hint(`view --lane ${JSON.stringify(laneText(column.name))}`)})`);
112
+ }
113
+ if (hidden.length)
114
+ lines.push(`Hidden: ${hidden.join(", ")} (${hint("view --all")})`);
115
+ return lines.join("\n");
116
+ }
117
+ function stamp(iso) {
118
+ return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(iso) ? `${iso.slice(0, 10)} ${iso.slice(11, 16)}` : iso;
119
+ }
120
+ /** A short reference to another card: `#2 "Trello import" (Todo)`. */
121
+ export function cardRef(card, { lane = true } = {}) {
122
+ return `${card.board ?? ""}#${card.n} ${quoted(card.title, 80)}${lane && card.lane ? ` (${laneText(card.lane)})` : ""}`;
123
+ }
124
+ const COMMENT_VERBS = { checkpoint: "asked", completion: "finished" };
125
+ /**
126
+ * Multi-line text, each line indented under its heading. Every way of
127
+ * breaking a line becomes a real line break (and so gets the indent), and
128
+ * other control characters are dropped.
129
+ */
130
+ export function block(text, indent = " ") {
131
+ return asText(text ?? "")
132
+ .replace(/\r\n?|[\u0085\u2028\u2029\u000b\u000c]/g, "\n")
133
+ .replace(/[\u0000-\u0008\u000e-\u001f\u007f-\u009f]/g, "")
134
+ .trim()
135
+ .split("\n")
136
+ .map((line) => `${indent}${line}`.trimEnd())
137
+ .join("\n");
138
+ }
139
+ /** `Label: text` when the text is one line, else the label alone with the text indented under it. */
140
+ export function labelled(label, text) {
141
+ const body = block(text, "");
142
+ return body.includes("\n") ? `${label}\n${block(text)}` : `${label} ${body}`;
143
+ }
144
+ export function renderComments(comments, { limit = 20 } = {}) {
145
+ if (!comments.length)
146
+ return "No comments.";
147
+ const shown = comments.slice(-limit);
148
+ const lines = [];
149
+ if (comments.length > shown.length)
150
+ lines.push(`(${comments.length - shown.length} earlier comments not shown)`);
151
+ for (const comment of shown) {
152
+ const verb = COMMENT_VERBS[comment.kind] ? ` ${COMMENT_VERBS[comment.kind] ?? ""}` : "";
153
+ const body = block(comment.body).replace(/^ {2}/, "");
154
+ lines.push(`- ${authorText(comment.author)}${verb} (${stamp(comment.at)}): ${body}`);
155
+ }
156
+ return lines.join("\n");
157
+ }
158
+ /** One card: title, a facts line (type · priority · lane · labels · author · link), its links, then its text. */
159
+ export function renderCard(card, options = {}) {
160
+ const { comments = null, hint = (line) => line, nowMs } = options;
161
+ // One card always says its priority, med too: unsaid, it read as "no priority".
162
+ const facts = [card.type, priorityWord(card.priority)];
163
+ facts.push(card.archived ? `${laneText(card.lane)}, archived` : laneText(card.lane));
164
+ if (card.labels.length)
165
+ facts.push(`[${card.labels.map(labelText).join(", ")}]`);
166
+ if (card.author)
167
+ facts.push(`by ${authorText(card.author)}`);
168
+ if (card.holder) {
169
+ const since = age(card.holder.since, nowMs);
170
+ facts.push(`held by @${oneLine(card.holder.name, 40)}${since ? ` ${since}` : ""}`);
171
+ }
172
+ facts.push(card.link);
173
+ const lines = [`#${card.n} ${oneLine(card.title, 200)}`, facts.join(" · ")];
174
+ if (card.parent)
175
+ lines.push(`Parent: ${cardRef(card.parent, { lane: false })}`);
176
+ if (card.children.length)
177
+ lines.push(`Sub-cards: ${card.children.map((child) => cardRef(child)).join("; ")}`);
178
+ if (card.blockedBy.length)
179
+ lines.push(`Blocked by: ${card.blockedBy.map((other) => cardRef(other)).join("; ")}`);
180
+ if (card.blocks.length)
181
+ lines.push(`Blocks: ${card.blocks.map((other) => cardRef(other)).join("; ")}`);
182
+ if (card.related.length)
183
+ lines.push(`Related: ${card.related.map((other) => cardRef(other)).join("; ")}`);
184
+ // A stored link has no spaces or line breaks (src/core/nebula-link.ts); oneLine keeps it so.
185
+ if (card.nebula)
186
+ lines.push(`Nebula: ${oneLine(card.nebula, 2048)}`);
187
+ for (const [label, text] of [["Description:", card.description], ["Plan:", card.plan], ["Summary:", card.summary], ["Revisions:", card.revisions]]) {
188
+ if (!block(text, ""))
189
+ continue;
190
+ lines.push("", label, block(text));
191
+ }
192
+ lines.push("");
193
+ if (comments)
194
+ lines.push(renderComments(comments));
195
+ else
196
+ lines.push(`Comments: ${card.commentCount}${card.commentCount ? ` (${hint(`card #${card.n} --comments`)})` : ""}`);
197
+ return lines.join("\n");
198
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * One conversation with Orbit: who is asking, through what (a shell, MCP,
3
+ * HTTP), and the board it has chosen, like `cd`. A choice one caller makes
4
+ * never moves another caller's commands: an agent's choice stays in its
5
+ * session, and only a person's shell on the computer itself (`cli`, not
6
+ * `shared`) sets the computer's default board.
7
+ */
8
+ import type { Ctx } from "../core/context.ts";
9
+ import type { Actor, RegisteredBoard } from "../core/model.ts";
10
+ export type Transport = "cli" | "mcp" | "http";
11
+ /** A repo's orbit.json, as read: the board it names, or why it can't be used. */
12
+ export interface RepoChoice {
13
+ board: string | null;
14
+ problem?: "not_file" | "too_big" | "not_json" | "not_slug";
15
+ value?: unknown;
16
+ }
17
+ /**
18
+ * Where a repo's board comes from: a computer reads orbit.json where the
19
+ * command runs (and a shell there may write it); a remote client sends what
20
+ * it read. Only `read` is needed.
21
+ */
22
+ export interface RepoSource {
23
+ read(): RepoChoice;
24
+ /** How the caller's place is said: "this repo", "this folder". */
25
+ place?: string;
26
+ /** Writes or clears `board` in the file (`boards link`, `boards unlink`); only a shell on this computer has it. */
27
+ link?: (sub: "link" | "unlink", slug: string | null) => {
28
+ ok: boolean;
29
+ text: string;
30
+ data: unknown;
31
+ };
32
+ }
33
+ /** Why a repo's orbit.json can't name a board, in one line. */
34
+ export declare function repoProblemText(repo: RepoChoice): string;
35
+ /**
36
+ * A repo's board as a server gets it from a remote client (`repo_board`,
37
+ * `repo_board_problem`), checked again: the request is no more trusted than
38
+ * the file. Null when the client sent none.
39
+ */
40
+ export declare function repoBoardFromRequest(board: unknown, problem: unknown): RepoChoice | null;
41
+ export interface Session {
42
+ readonly c: Ctx;
43
+ readonly actor: Actor;
44
+ transport: Transport;
45
+ /** The board this session chose (`view <board>`, `ORBIT_BOARD`), as a slug. */
46
+ board: string | null;
47
+ /** True for a command over HTTP to an Orbit others use: it may choose a board for itself, never the default for everyone. */
48
+ readonly shared: boolean;
49
+ readonly repo: RepoSource | null;
50
+ }
51
+ export declare function createSession(c: Ctx, options?: {
52
+ transport?: Transport;
53
+ board?: string | null;
54
+ shared?: boolean;
55
+ repo?: RepoSource | null;
56
+ }): Session;
57
+ /** True in a shell: usages say `orbit card 12`, since a shell drops a word that starts with #. */
58
+ export declare const inShell: (session: Pick<Session, "transport">) => boolean;
59
+ /** How a command is written in this transport: `orbit view` in a shell, `view` elsewhere. */
60
+ export declare function hint(session: Pick<Session, "transport">, line: string): string;
61
+ /**
62
+ * The answer when there is no board: how to make one, and, while an older
63
+ * Orbit's boards wait on this computer, the migration first (with no path: an
64
+ * agent never sees one). A shell on this computer may run it; over MCP or a
65
+ * shared Orbit the agent asks its person, who runs it where Orbit runs.
66
+ */
67
+ export declare function noBoardsText(session: Pick<Session, "transport" | "c" | "shared">): string;
68
+ /** Only a shell on this computer sets its default board; agents over MCP or HTTP choose for themselves. */
69
+ export declare function setsComputerDefault(session: Session): boolean;
70
+ /** Where the caller runs, for "let ... name it". */
71
+ export declare function callerPlace(session: Session): string;
72
+ export declare const DEFAULT_BOARD = "default_board";
73
+ export declare function boardList(session: Session): Promise<string>;
74
+ export declare function boardRowFor(session: Session, ident: string): Promise<RegisteredBoard | null>;
75
+ /** The computer's default board (`boards use` in a shell), when it still exists. */
76
+ export declare function savedDefault(session: Session): Promise<RegisteredBoard | null>;
77
+ declare function repoChoice(session: Session): RepoChoice;
78
+ export { repoChoice };
79
+ /**
80
+ * The board a command uses: the one it names, else the session's, else the
81
+ * repo's orbit.json, else this computer's default, else the only one. A
82
+ * repo file that can't be used, or names a board this Orbit lacks, is
83
+ * refused: never a quiet fall-through to another board.
84
+ */
85
+ export declare function resolveBoard(session: Session, explicit?: string | null): Promise<RegisteredBoard>;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * One conversation with Orbit: who is asking, through what (a shell, MCP,
3
+ * HTTP), and the board it has chosen, like `cd`. A choice one caller makes
4
+ * never moves another caller's commands: an agent's choice stays in its
5
+ * session, and only a person's shell on the computer itself (`cli`, not
6
+ * `shared`) sets the computer's default board.
7
+ */
8
+ import { isSlug, slugify } from "../core/text.js";
9
+ import { fail, shellSafe } from "./parse.js";
10
+ import { oneLine } from "./present.js";
11
+ const ONE_LINE = '{"board": "<slug>"}';
12
+ /** Why a repo's orbit.json can't name a board, in one line. */
13
+ export function repoProblemText(repo) {
14
+ const tail = " Or name a board in the command.";
15
+ switch (repo.problem) {
16
+ case "too_big":
17
+ return `This repo's orbit.json is over 16 KB, so Orbit doesn't read it. It needs only ${ONE_LINE}.${tail}`;
18
+ case "not_json":
19
+ return `This repo's orbit.json isn't a JSON object, so Orbit doesn't read it. It needs only ${ONE_LINE}.${tail}`;
20
+ case "not_slug": {
21
+ const shown = typeof repo.value === "string" ? JSON.stringify(oneLine(repo.value, 60)) : oneLine(JSON.stringify(repo.value), 40);
22
+ const like = slugify(typeof repo.value === "string" ? repo.value : "") || "garden";
23
+ return `This repo's orbit.json names board ${shown}, which isn't a board slug (lowercase letters, digits and dashes, like ${like}).${tail}`;
24
+ }
25
+ case "not_file":
26
+ case undefined:
27
+ return `This repo's orbit.json isn't a plain file, so Orbit doesn't read it. Make it a file holding ${ONE_LINE}.${tail}`;
28
+ }
29
+ }
30
+ const PROBLEMS = ["not_file", "too_big", "not_json", "not_slug"];
31
+ /**
32
+ * A repo's board as a server gets it from a remote client (`repo_board`,
33
+ * `repo_board_problem`), checked again: the request is no more trusted than
34
+ * the file. Null when the client sent none.
35
+ */
36
+ export function repoBoardFromRequest(board, problem) {
37
+ if (PROBLEMS.includes(problem))
38
+ return { board: null, problem: problem, value: typeof board === "string" ? board : undefined };
39
+ if (board === undefined || board === null || board === "")
40
+ return null;
41
+ if (!isSlug(board))
42
+ return { board: null, problem: "not_slug", value: board };
43
+ return { board };
44
+ }
45
+ export function createSession(c, options = {}) {
46
+ return { c, actor: c.actor, transport: options.transport ?? "mcp", board: options.board ?? null, shared: Boolean(options.shared), repo: options.repo ?? null };
47
+ }
48
+ /** True in a shell: usages say `orbit card 12`, since a shell drops a word that starts with #. */
49
+ export const inShell = (session) => session.transport === "cli";
50
+ /** How a command is written in this transport: `orbit view` in a shell, `view` elsewhere. */
51
+ export function hint(session, line) {
52
+ return session.transport === "cli" ? `orbit ${shellSafe(line)}` : line;
53
+ }
54
+ /**
55
+ * The answer when there is no board: how to make one, and, while an older
56
+ * Orbit's boards wait on this computer, the migration first (with no path: an
57
+ * agent never sees one). A shell on this computer may run it; over MCP or a
58
+ * shared Orbit the agent asks its person, who runs it where Orbit runs.
59
+ */
60
+ export function noBoardsText(session) {
61
+ if (!session.c.deployment.older_data)
62
+ return `No boards yet. Create one: ${hint(session, "boards new <name>")}`;
63
+ const fresh = `\`${hint(session, "boards new <name>")}\``;
64
+ const run = session.transport === "cli" && !session.shared ? "run `orbit migrate`" : "ask your person to run `orbit migrate` in a terminal";
65
+ return `Boards from an older Orbit are waiting: ${run} to bring them here (it only reads the old files). Or start fresh: ${fresh}.`;
66
+ }
67
+ /** Only a shell on this computer sets its default board; agents over MCP or HTTP choose for themselves. */
68
+ export function setsComputerDefault(session) {
69
+ return session.transport === "cli" && !session.shared;
70
+ }
71
+ /** Where the caller runs, for "let ... name it". */
72
+ export function callerPlace(session) {
73
+ if (session.repo?.place)
74
+ return session.repo.place;
75
+ return session.transport === "cli" ? "this repo" : "the repo";
76
+ }
77
+ export const DEFAULT_BOARD = "default_board";
78
+ export async function boardList(session) {
79
+ return (await session.c.store.boards.list()).map((row) => row.slug).join(", ");
80
+ }
81
+ export async function boardRowFor(session, ident) {
82
+ return (await session.c.store.boards.bySlug(ident)) ?? (await session.c.store.boards.get(ident));
83
+ }
84
+ /** The computer's default board (`boards use` in a shell), when it still exists. */
85
+ export async function savedDefault(session) {
86
+ const slug = await session.c.store.settings.get(DEFAULT_BOARD);
87
+ return slug ? session.c.store.boards.bySlug(slug) : null;
88
+ }
89
+ function repoChoice(session) {
90
+ return session.repo?.read() ?? { board: null };
91
+ }
92
+ export { repoChoice };
93
+ /** This repo's orbit.json names a board this Orbit doesn't have. */
94
+ async function missingRepoBoard(session, slug) {
95
+ const all = await session.c.store.boards.list();
96
+ const named = `This repo's orbit.json names board ${oneLine(slug, 60)}, which this Orbit doesn't have.`;
97
+ const first = all[0];
98
+ if (!first)
99
+ return `${named} No boards here yet. Create one: ${hint(session, "boards new <name>")}`;
100
+ // The link names no board: the first one is rarely this repo's.
101
+ const way = session.transport === "cli" ? `Name one (orbit view ${first.slug}) or link one: orbit boards link <board>.` : `Name one (view ${first.slug}) or link one (boards link <board> says how).`;
102
+ return `${named} Boards here: ${await boardList(session)}. ${way}`;
103
+ }
104
+ /**
105
+ * The board a command uses: the one it names, else the session's, else the
106
+ * repo's orbit.json, else this computer's default, else the only one. A
107
+ * repo file that can't be used, or names a board this Orbit lacks, is
108
+ * refused: never a quiet fall-through to another board.
109
+ */
110
+ export async function resolveBoard(session, explicit) {
111
+ const named = explicit || session.board;
112
+ if (named) {
113
+ const row = await boardRowFor(session, named);
114
+ if (!row)
115
+ fail(`No board "${oneLine(named, 60)}". Boards: ${(await boardList(session)) || "none yet"}.`);
116
+ return row;
117
+ }
118
+ const repo = repoChoice(session);
119
+ if (repo.problem)
120
+ fail(repoProblemText(repo));
121
+ if (repo.board)
122
+ return (await session.c.store.boards.bySlug(repo.board)) ?? fail(await missingRepoBoard(session, repo.board));
123
+ const saved = await savedDefault(session);
124
+ if (saved)
125
+ return saved;
126
+ const all = await session.c.store.boards.list();
127
+ const [first] = all;
128
+ if (all.length === 1 && first)
129
+ return first;
130
+ if (!first)
131
+ fail(noBoardsText(session));
132
+ const list = await boardList(session);
133
+ // The link names no board: the first one is rarely this folder's.
134
+ if (session.transport !== "cli") {
135
+ fail(`Which board? ${list}. Name it (view ${first.slug} keeps it for this session, ${first.slug}#12, or --board ${first.slug}), or let ${callerPlace(session)} name it (boards link <board> says how).`);
136
+ }
137
+ fail(`Which board? ${list}. Name it (orbit view ${first.slug}, orbit card ${first.slug}#12, or --board ${first.slug}) or let ${callerPlace(session)} name it: orbit boards link <board>.`);
138
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * What each command does: reads the board through the port, changes it
3
+ * through the core's use cases (never by writing records itself), and says
4
+ * what happened in Orbit's words (./present.ts), with JSON data for --json.
5
+ */
6
+ import type { BoardCtx } from "../core/context.ts";
7
+ import type { Args } from "./parse.ts";
8
+ import type { Session } from "./session.ts";
9
+ /** What a command did: its text, its data, and the board it acted on (a write marks that board active). */
10
+ export interface Outcome {
11
+ text: string;
12
+ data: unknown;
13
+ board?: BoardCtx;
14
+ }
15
+ export declare const TEXT_TWICE_MESSAGE = "Text given twice: as -m/--text (or the text field) and as words on the line. Send it once: quote it, or put it all in text.";
16
+ export declare function cmdView(session: Session, args: Args): Promise<Outcome>;
17
+ export declare function cmdCard(session: Session, args: Args): Promise<Outcome>;
18
+ /** The overview's first lines for an agent: how to name itself (while it has no name) and the default work rules. */
19
+ export declare function agentLines(session: Pick<Session, "actor" | "transport">): string[];
20
+ export declare function cmdTake(session: Session, args: Args): Promise<Outcome>;
21
+ export declare function cmdMove(session: Session, args: Args): Promise<Outcome>;
22
+ export declare function cmdFinish(session: Session, args: Args): Promise<Outcome>;
23
+ export declare function cmdAsk(session: Session, args: Args): Promise<Outcome>;
24
+ export declare function cmdNote(session: Session, args: Args): Promise<Outcome>;
25
+ export declare function cmdNew(session: Session, args: Args): Promise<Outcome>;
26
+ export declare function cmdEdit(session: Session, args: Args): Promise<Outcome>;
27
+ export declare function cmdJournal(session: Session, args: Args): Promise<Outcome>;
28
+ export declare function cmdFind(session: Session, args: Args): Promise<Outcome>;
29
+ export declare function cmdChanges(session: Session, args: Args): Promise<Outcome>;
30
+ export declare const BOARDS_USAGE = "boards | boards new <name> [--slug s] | boards use <board> | boards link <board> | boards unlink";
31
+ export declare function cmdBoards(session: Session, args: Args): Promise<Outcome>;
32
+ export declare function cmdLink(session: Session, args: Args): Promise<Outcome>;
33
+ export declare function cmdUnlink(session: Session, args: Args): Promise<Outcome>;
34
+ export declare function cmdArchive(session: Session, args: Args): Promise<Outcome>;
35
+ export declare function cmdRestore(session: Session, args: Args): Promise<Outcome>;