@notis_ai/cli 0.2.17 → 0.2.19

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 (395) hide show
  1. package/README.md +542 -146
  2. package/bin/check-runtime.js +15 -0
  3. package/bin/notis.js +2 -0
  4. package/config/notis_app_design_rules.json +320 -0
  5. package/config/portal-route-roots.json +45 -0
  6. package/dist/agent-hooks/notis-agent-hook.mjs +42323 -18258
  7. package/dist/base-skills/notis-cli/.notis-base-skill.json +1 -0
  8. package/dist/base-skills/notis-cli/SKILL.md +51 -280
  9. package/dist/base-skills/notis-cli/references/app-delivery.md +17 -0
  10. package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
  11. package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
  12. package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
  13. package/dist/base-skills/notis-cli/references/troubleshooting.md +67 -0
  14. package/dist/base-skills/notis-query/.notis-base-skill.json +1 -0
  15. package/dist/base-skills/notis-query/SKILL.md +35 -699
  16. package/dist/base-skills/notis-query/references/database-discovery.md +59 -0
  17. package/dist/base-skills/notis-query/references/documents.md +74 -0
  18. package/dist/base-skills/notis-query/references/query.md +76 -0
  19. package/dist/base-skills/notis-spaces/.notis-base-skill.json +1 -0
  20. package/dist/base-skills/notis-spaces/SKILL.md +218 -0
  21. package/dist/base-skills/notis-spaces/references/architecture.md +116 -0
  22. package/dist/base-skills/notis-spaces/references/context.md +81 -0
  23. package/dist/base-skills/notis-spaces/references/design.md +141 -0
  24. package/dist/base-skills/notis-spaces/references/fixtures.md +29 -0
  25. package/dist/base-skills/notis-spaces/references/memory.md +58 -0
  26. package/dist/base-skills/notis-spaces/references/reading.md +73 -0
  27. package/dist/base-skills/notis-spaces/references/release.md +120 -0
  28. package/dist/base-skills/notis-spaces/references/reports.md +77 -0
  29. package/dist/base-skills/notis-spaces/references/sdk.md +273 -0
  30. package/dist/base-skills/notis-spaces/references/store.md +118 -0
  31. package/dist/base-skills/notis-spaces/references/troubleshooting.md +28 -0
  32. package/dist/base-skills/notis-spaces/references/views.md +229 -0
  33. package/{template/packages → dist}/sdk/package.json +9 -10
  34. package/dist/sdk/src/agentContext.ts +36 -0
  35. package/dist/sdk/src/bundleModule.ts +175 -0
  36. package/dist/sdk/src/components/Dialog.tsx +103 -0
  37. package/dist/sdk/src/components/DocumentEditor.tsx +113 -0
  38. package/dist/sdk/src/components/DocumentPage.tsx +184 -0
  39. package/{template/packages → dist}/sdk/src/components/Markdown.tsx +9 -3
  40. package/{template/packages → dist}/sdk/src/components/MarkdownEditor.tsx +26 -5
  41. package/{template/packages → dist}/sdk/src/components/MultiSelectActionBar.tsx +95 -12
  42. package/{template/packages → dist}/sdk/src/components/MultiSelectCheckbox.tsx +4 -2
  43. package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
  44. package/{template/packages → dist}/sdk/src/components/NotisSelectionBoundary.tsx +9 -5
  45. package/dist/sdk/src/components/RecordComponents.tsx +111 -0
  46. package/dist/sdk/src/components/Skeleton.tsx +38 -0
  47. package/dist/sdk/src/config.ts +31 -0
  48. package/{template/packages → dist}/sdk/src/documents.ts +21 -6
  49. package/dist/sdk/src/hooks/useAction.ts +28 -0
  50. package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
  51. package/{template/packages → dist}/sdk/src/hooks/useBackend.ts +3 -2
  52. package/dist/sdk/src/hooks/useCloudComputer.ts +94 -0
  53. package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
  54. package/{template/packages → dist}/sdk/src/hooks/useCollectionInteractions.ts +157 -147
  55. package/dist/sdk/src/hooks/useDatabaseSchema.ts +50 -0
  56. package/{template/packages → dist}/sdk/src/hooks/useDatabaseSubscription.ts +2 -2
  57. package/dist/sdk/src/hooks/useDocument.ts +51 -0
  58. package/{template/packages → dist}/sdk/src/hooks/useDocuments.ts +25 -59
  59. package/{template/packages → dist}/sdk/src/hooks/useHandover.ts +7 -7
  60. package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
  61. package/dist/sdk/src/hooks/useMarqueeSelection.ts +194 -0
  62. package/{template/packages → dist}/sdk/src/hooks/useMultiSelect.ts +2 -8
  63. package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
  64. package/dist/sdk/src/hooks/useNativeDocuments.ts +143 -0
  65. package/{template/packages → dist}/sdk/src/hooks/useNotis.ts +6 -1
  66. package/dist/sdk/src/hooks/useNotisNavigation.ts +70 -0
  67. package/dist/sdk/src/hooks/useQuery.ts +81 -0
  68. package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
  69. package/dist/sdk/src/hooks/useTopBarSearch.ts +102 -0
  70. package/dist/sdk/src/hooks/useTopBarTitleLeaf.ts +75 -0
  71. package/{template/packages → dist}/sdk/src/hooks/useUpsertDocument.ts +1 -1
  72. package/dist/sdk/src/hooks/useViewParams.ts +195 -0
  73. package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
  74. package/{template/packages → dist}/sdk/src/index.ts +64 -1
  75. package/{template/packages → dist}/sdk/src/interactions/actions.ts +14 -1
  76. package/{template/packages → dist}/sdk/src/interactions/shortcuts.tsx +129 -23
  77. package/dist/sdk/src/interactions/visibility.ts +13 -0
  78. package/{template/packages → dist}/sdk/src/interactions.ts +5 -1
  79. package/dist/sdk/src/nativeData.ts +39 -0
  80. package/{template/packages → dist}/sdk/src/provider.tsx +9 -4
  81. package/dist/sdk/src/queryCache.ts +292 -0
  82. package/dist/sdk/src/queryErrors.ts +51 -0
  83. package/dist/sdk/src/runtime.ts +675 -0
  84. package/dist/sdk/src/runtimeModules.ts +33 -0
  85. package/dist/sdk/src/space.ts +442 -0
  86. package/dist/sdk/src/standardViewParams.ts +36 -0
  87. package/{template/packages → dist}/sdk/src/styles.css +81 -16
  88. package/dist/sdk/src/tailwind.ts +66 -0
  89. package/dist/sdk/src/ui/charts/RenderChartData.tsx +25 -0
  90. package/dist/sdk/src/ui/engine/core.ts +392 -0
  91. package/dist/sdk/src/ui/engine/dom.ts +183 -0
  92. package/dist/sdk/src/ui/engine/hooks.ts +195 -0
  93. package/dist/sdk/src/ui/engine/instance.ts +63 -0
  94. package/dist/sdk/src/ui/engine/keycapContext.ts +2 -0
  95. package/dist/sdk/src/ui/engine/registry.ts +262 -0
  96. package/dist/sdk/src/ui/engine/types.ts +62 -0
  97. package/dist/sdk/src/ui/icons.tsx +91 -0
  98. package/dist/sdk/src/ui/util.ts +83 -0
  99. package/dist/sdk/src/viewPeriod.ts +26 -0
  100. package/dist/sdk/src/vite.ts +92 -0
  101. package/dist/sdk/src/words/actions.ts +295 -0
  102. package/dist/sdk/src/words/clashes.ts +158 -0
  103. package/dist/sdk/src/words/format.ts +136 -0
  104. package/dist/sdk/src/words/index.ts +13 -0
  105. package/dist/sdk/src/words/keymap.ts +72 -0
  106. package/dist/sdk/src/words/keys.ts +297 -0
  107. package/dist/sdk/src/words/shell.ts +46 -0
  108. package/dist/sdk/src/words/types.ts +65 -0
  109. package/dist/skill-sync/index.js +832 -151
  110. package/dist/skill-sync/index.js.map +4 -4
  111. package/dist/skill-sync-worker.mjs +3941 -0
  112. package/dist/space-harness/host.js +1460 -0
  113. package/dist/space-sdk/dist/chunk-ZSN57ATH.js +5 -0
  114. package/dist/space-sdk/dist/index.js +15 -0
  115. package/dist/space-sdk/dist/ui.js +18 -0
  116. package/dist/space-sdk/package.json +33 -0
  117. package/dist/space-sdk/src/agentContext.d.ts +36 -0
  118. package/dist/space-sdk/src/components/Dialog.d.ts +20 -0
  119. package/dist/space-sdk/src/components/DocumentEditor.d.ts +46 -0
  120. package/dist/space-sdk/src/components/DocumentPage.d.ts +53 -0
  121. package/dist/space-sdk/src/components/Markdown.d.ts +18 -0
  122. package/dist/space-sdk/src/components/MarkdownEditor.d.ts +11 -0
  123. package/dist/space-sdk/src/components/MultiSelectActionBar.d.ts +31 -0
  124. package/dist/space-sdk/src/components/MultiSelectCheckbox.d.ts +14 -0
  125. package/dist/space-sdk/src/components/MultiSelectDragOverlay.d.ts +8 -0
  126. package/dist/space-sdk/src/components/NotisCommentBoundary.d.ts +36 -0
  127. package/dist/space-sdk/src/components/NotisSelectionBoundary.d.ts +16 -0
  128. package/dist/space-sdk/src/components/RecordComponents.d.ts +64 -0
  129. package/dist/space-sdk/src/components/ShortcutHints.d.ts +12 -0
  130. package/dist/space-sdk/src/components/Skeleton.d.ts +23 -0
  131. package/dist/space-sdk/src/config.ts +31 -0
  132. package/dist/space-sdk/src/documents.d.ts +59 -0
  133. package/dist/space-sdk/src/hooks/useAction.d.ts +8 -0
  134. package/dist/space-sdk/src/hooks/useActiveResource.d.ts +3 -0
  135. package/dist/space-sdk/src/hooks/useAgentContext.d.ts +7 -0
  136. package/dist/space-sdk/src/hooks/useBackend.d.ts +23 -0
  137. package/dist/space-sdk/src/hooks/useCloudComputer.d.ts +45 -0
  138. package/dist/space-sdk/src/hooks/useCloudComputerShell.d.ts +49 -0
  139. package/dist/space-sdk/src/hooks/useCollectionInteractions.d.ts +118 -0
  140. package/dist/space-sdk/src/hooks/useDatabaseSchema.d.ts +14 -0
  141. package/dist/space-sdk/src/hooks/useDatabaseSubscription.d.ts +26 -0
  142. package/dist/space-sdk/src/hooks/useDocument.d.ts +22 -0
  143. package/dist/space-sdk/src/hooks/useDocuments.d.ts +31 -0
  144. package/dist/space-sdk/src/hooks/useHandover.d.ts +43 -0
  145. package/dist/space-sdk/src/hooks/useLongPressSelection.d.ts +9 -0
  146. package/dist/space-sdk/src/hooks/useMarqueeSelection.d.ts +57 -0
  147. package/dist/space-sdk/src/hooks/useMultiSelect.d.ts +51 -0
  148. package/dist/space-sdk/src/hooks/useNativeDocumentBody.d.ts +24 -0
  149. package/dist/space-sdk/src/hooks/useNativeDocuments.d.ts +55 -0
  150. package/dist/space-sdk/src/hooks/useNotis.d.ts +25 -0
  151. package/dist/space-sdk/src/hooks/useNotisNavigation.d.ts +33 -0
  152. package/dist/space-sdk/src/hooks/useQuery.d.ts +22 -0
  153. package/dist/space-sdk/src/hooks/useTool.d.ts +20 -0
  154. package/dist/space-sdk/src/hooks/useToolQuery.d.ts +3 -0
  155. package/dist/space-sdk/src/hooks/useTools.d.ts +15 -0
  156. package/dist/space-sdk/src/hooks/useTopBarSearch.d.ts +48 -0
  157. package/dist/space-sdk/src/hooks/useTopBarTitleLeaf.d.ts +24 -0
  158. package/dist/space-sdk/src/hooks/useUpsertDocument.d.ts +27 -0
  159. package/dist/space-sdk/src/hooks/useViewParams.d.ts +76 -0
  160. package/dist/space-sdk/src/hooks/useViewerReads.d.ts +38 -0
  161. package/dist/space-sdk/src/index.d.ts +98 -0
  162. package/dist/space-sdk/src/interactions/actions.d.ts +33 -0
  163. package/dist/space-sdk/src/interactions/shortcuts.d.ts +42 -0
  164. package/dist/space-sdk/src/interactions/visibility.d.ts +2 -0
  165. package/dist/space-sdk/src/nativeData.d.ts +66 -0
  166. package/dist/space-sdk/src/provider.d.ts +17 -0
  167. package/dist/space-sdk/src/queryCache.d.ts +45 -0
  168. package/dist/space-sdk/src/queryErrors.ts +51 -0
  169. package/dist/space-sdk/src/runtime.d.ts +615 -0
  170. package/dist/space-sdk/src/runtimeModules.ts +33 -0
  171. package/dist/space-sdk/src/space.ts +442 -0
  172. package/dist/space-sdk/src/standardViewParams.d.ts +15 -0
  173. package/dist/space-sdk/src/tailwind-candidates.d.ts +3418 -0
  174. package/dist/space-sdk/src/tailwind.ts +66 -0
  175. package/dist/space-sdk/src/ui/actions/ActionToast.d.ts +15 -0
  176. package/dist/space-sdk/src/ui/actions/actionWords.d.ts +16 -0
  177. package/dist/space-sdk/src/ui/actions/index.d.ts +7 -0
  178. package/dist/space-sdk/src/ui/actions/useActions.d.ts +69 -0
  179. package/dist/space-sdk/src/ui/actions/useToast.d.ts +41 -0
  180. package/dist/space-sdk/src/ui/blocks/Tabs.d.ts +139 -0
  181. package/dist/space-sdk/src/ui/blocks/blocks.d.ts +217 -0
  182. package/dist/space-sdk/src/ui/blocks/index.d.ts +4 -0
  183. package/dist/space-sdk/src/ui/board/BoardView.d.ts +36 -0
  184. package/dist/space-sdk/src/ui/board/boardModel.d.ts +46 -0
  185. package/dist/space-sdk/src/ui/board/boardWords.d.ts +9 -0
  186. package/dist/space-sdk/src/ui/board/index.d.ts +5 -0
  187. package/dist/space-sdk/src/ui/calendar/CalendarView.d.ts +49 -0
  188. package/dist/space-sdk/src/ui/calendar/DayPicker.d.ts +23 -0
  189. package/dist/space-sdk/src/ui/calendar/calendarMath.d.ts +81 -0
  190. package/dist/space-sdk/src/ui/charts/Chart.d.ts +203 -0
  191. package/dist/space-sdk/src/ui/charts/ChartTable.d.ts +37 -0
  192. package/dist/space-sdk/src/ui/charts/RenderChartData.d.ts +16 -0
  193. package/dist/space-sdk/src/ui/charts/StatRow.d.ts +59 -0
  194. package/dist/space-sdk/src/ui/charts/chartData.d.ts +84 -0
  195. package/dist/space-sdk/src/ui/comments/CommentPane.d.ts +58 -0
  196. package/dist/space-sdk/src/ui/comments/commentModel.d.ts +157 -0
  197. package/dist/space-sdk/src/ui/comments/commentWords.d.ts +60 -0
  198. package/dist/space-sdk/src/ui/comments/index.d.ts +4 -0
  199. package/dist/space-sdk/src/ui/comments/useComments.d.ts +146 -0
  200. package/dist/space-sdk/src/ui/engine/HelpSheet.d.ts +12 -0
  201. package/dist/space-sdk/src/ui/engine/KeyboardEngine.d.ts +27 -0
  202. package/dist/space-sdk/src/ui/engine/core.d.ts +73 -0
  203. package/dist/space-sdk/src/ui/engine/hooks.d.ts +64 -0
  204. package/dist/space-sdk/src/ui/engine/index.d.ts +14 -0
  205. package/dist/space-sdk/src/ui/engine/instance.d.ts +21 -0
  206. package/dist/space-sdk/src/ui/engine/keycapContext.d.ts +2 -0
  207. package/dist/space-sdk/src/ui/engine/registry.d.ts +77 -0
  208. package/dist/space-sdk/src/ui/engine/step.d.ts +11 -0
  209. package/dist/space-sdk/src/ui/engine/types.d.ts +54 -0
  210. package/dist/space-sdk/src/ui/fields/fieldWords.d.ts +56 -0
  211. package/dist/space-sdk/src/ui/fields/fields.d.ts +162 -0
  212. package/dist/space-sdk/src/ui/fields/index.d.ts +5 -0
  213. package/dist/space-sdk/src/ui/fields/useFieldDraft.d.ts +22 -0
  214. package/dist/space-sdk/src/ui/gallery/AttachmentGallery.d.ts +53 -0
  215. package/dist/space-sdk/src/ui/gallery/ImageViewer.d.ts +27 -0
  216. package/dist/space-sdk/src/ui/gallery/galleryWords.d.ts +95 -0
  217. package/dist/space-sdk/src/ui/gallery/index.d.ts +5 -0
  218. package/dist/space-sdk/src/ui/icons.d.ts +13 -0
  219. package/dist/space-sdk/src/ui/index.d.ts +54 -0
  220. package/dist/space-sdk/src/ui/keycap/Keycap.d.ts +22 -0
  221. package/dist/space-sdk/src/ui/keycap/index.d.ts +2 -0
  222. package/dist/space-sdk/src/ui/layout/Panels.d.ts +50 -0
  223. package/dist/space-sdk/src/ui/layout/chatPanelEdge.d.ts +77 -0
  224. package/dist/space-sdk/src/ui/layout/index.d.ts +5 -0
  225. package/dist/space-sdk/src/ui/layout/panelMath.d.ts +91 -0
  226. package/dist/space-sdk/src/ui/list/ListReader.d.ts +380 -0
  227. package/dist/space-sdk/src/ui/list/Row.d.ts +145 -0
  228. package/dist/space-sdk/src/ui/list/SelectionBar.d.ts +65 -0
  229. package/dist/space-sdk/src/ui/list/index.d.ts +14 -0
  230. package/dist/space-sdk/src/ui/list/rowState.d.ts +22 -0
  231. package/dist/space-sdk/src/ui/list/useListKeys.d.ts +89 -0
  232. package/dist/space-sdk/src/ui/list/useReorder.d.ts +86 -0
  233. package/dist/space-sdk/src/ui/list/useSelection.d.ts +90 -0
  234. package/dist/space-sdk/src/ui/open/OpenAsMenu.d.ts +15 -0
  235. package/dist/space-sdk/src/ui/open/index.d.ts +6 -0
  236. package/dist/space-sdk/src/ui/open/openModeStore.d.ts +39 -0
  237. package/dist/space-sdk/src/ui/open/useOpenMode.d.ts +17 -0
  238. package/dist/space-sdk/src/ui/overlay/Menu.d.ts +88 -0
  239. package/dist/space-sdk/src/ui/overlay/Popover.d.ts +28 -0
  240. package/dist/space-sdk/src/ui/overlay/Tooltip.d.ts +19 -0
  241. package/dist/space-sdk/src/ui/overlay/index.d.ts +9 -0
  242. package/dist/space-sdk/src/ui/overlay/layerRoot.d.ts +24 -0
  243. package/dist/space-sdk/src/ui/overlay/position.d.ts +31 -0
  244. package/dist/space-sdk/src/ui/period/PeriodPicker.d.ts +30 -0
  245. package/dist/space-sdk/src/ui/period/dateFormat.d.ts +50 -0
  246. package/dist/space-sdk/src/ui/period/dateWords.d.ts +88 -0
  247. package/dist/space-sdk/src/ui/period/periods.d.ts +70 -0
  248. package/dist/space-sdk/src/ui/period/usePeriod.d.ts +23 -0
  249. package/dist/space-sdk/src/ui/present/index.d.ts +3 -0
  250. package/dist/space-sdk/src/ui/present/presentWords.d.ts +27 -0
  251. package/dist/space-sdk/src/ui/present/screens.d.ts +36 -0
  252. package/dist/space-sdk/src/ui/present/useAudienceScreen.d.ts +38 -0
  253. package/dist/space-sdk/src/ui/styles.d.ts +21 -0
  254. package/dist/space-sdk/src/ui/timeline/TimelineView.d.ts +44 -0
  255. package/dist/space-sdk/src/ui/timeline/timelineMath.d.ts +123 -0
  256. package/dist/space-sdk/src/viewPeriod.d.ts +8 -0
  257. package/dist/space-sdk/src/vite.ts +92 -0
  258. package/dist/space-sdk/src/words/actions.ts +295 -0
  259. package/dist/space-sdk/src/words/clashes.ts +158 -0
  260. package/dist/space-sdk/src/words/format.ts +136 -0
  261. package/dist/space-sdk/src/words/index.ts +13 -0
  262. package/dist/space-sdk/src/words/keymap.ts +72 -0
  263. package/dist/space-sdk/src/words/keys.ts +297 -0
  264. package/dist/space-sdk/src/words/shell.ts +46 -0
  265. package/dist/space-sdk/src/words/types.ts +65 -0
  266. package/dist/view-renderer/dist/host.css +1 -0
  267. package/dist/view-renderer/dist/host.js +2374 -0
  268. package/dist/view-renderer/dist/theme.css +73 -0
  269. package/dist/view-renderer/src/dom.js +212 -0
  270. package/dist/view-renderer/src/errors.js +8 -0
  271. package/dist/view-renderer/src/host.tsx +250 -0
  272. package/dist/view-renderer/src/index.js +4 -0
  273. package/dist/view-renderer/src/png.js +213 -0
  274. package/dist/view-renderer/src/pool.js +110 -0
  275. package/dist/view-renderer/src/remote-broker.js +59 -0
  276. package/dist/view-renderer/src/renderer.js +271 -0
  277. package/package.json +21 -11
  278. package/skills/notis-cli/AGENT_INSTRUCTIONS.md +63 -12
  279. package/skills/notis-onboarding/BRIEF.md +14 -9
  280. package/skills/notis-query/cli.md +1 -1
  281. package/skills/notis-spaces/cli.md +540 -0
  282. package/src/cli.js +8 -8
  283. package/src/command-specs/agents.js +121 -8
  284. package/src/command-specs/auth.js +3 -3
  285. package/src/command-specs/diagnostics.js +97 -20
  286. package/src/command-specs/documents.js +158 -0
  287. package/src/command-specs/files.js +29 -0
  288. package/src/command-specs/handover.js +331 -79
  289. package/src/command-specs/helpers.js +50 -40
  290. package/src/command-specs/index.js +14 -5
  291. package/src/command-specs/meta.js +38 -9
  292. package/src/command-specs/onboarding.js +1 -1
  293. package/src/command-specs/profile.js +42 -1
  294. package/src/command-specs/skills.js +314 -9
  295. package/src/command-specs/smoke.js +16 -4
  296. package/src/command-specs/spaces.js +783 -0
  297. package/src/command-specs/tools.js +118 -21
  298. package/src/command-specs/version-history.js +20 -0
  299. package/src/command-specs/views.js +69 -0
  300. package/src/runtime/agent-browser.js +178 -267
  301. package/src/runtime/agent-setup.js +172 -13
  302. package/src/runtime/app-boundary-validator.js +338 -2
  303. package/src/runtime/app-data-literals.js +82 -0
  304. package/src/runtime/app-platform.js +750 -1568
  305. package/src/runtime/auth-recovery.js +17 -0
  306. package/src/runtime/base-skills.d.ts +11 -0
  307. package/src/runtime/base-skills.js +100 -3
  308. package/src/runtime/computer-identity.d.ts +30 -0
  309. package/src/runtime/computer-identity.js +151 -0
  310. package/src/runtime/config-lock.js +135 -0
  311. package/src/runtime/confined-space-build.js +74 -0
  312. package/src/runtime/confined-space-verify.js +49 -0
  313. package/src/runtime/delegated-context.js +5 -21
  314. package/src/runtime/native-record-files.js +47 -0
  315. package/src/runtime/oauth.js +342 -31
  316. package/src/runtime/profiles.js +19 -112
  317. package/src/runtime/retired-sdk-files.js +24 -0
  318. package/src/runtime/retry.js +150 -0
  319. package/src/runtime/skill-sync/cloud-client.ts +33 -8
  320. package/src/runtime/skill-sync/index.ts +443 -106
  321. package/src/runtime/skill-sync/local-scanner.ts +248 -32
  322. package/src/runtime/skill-sync/native-identity.ts +102 -0
  323. package/src/runtime/skill-sync/native-plan.ts +70 -0
  324. package/src/runtime/skill-sync/symlink-manager.ts +66 -16
  325. package/src/runtime/skill-sync/sync-plan.ts +34 -2
  326. package/src/runtime/skill-sync/types.ts +54 -0
  327. package/src/runtime/skill-sync/write-cloud-skill.ts +4 -4
  328. package/src/runtime/skill-sync-service.js +109 -0
  329. package/src/runtime/source-root.js +32 -0
  330. package/src/runtime/space-collection-scaffold.js +107 -0
  331. package/src/runtime/space-database-structures.js +229 -0
  332. package/src/runtime/space-fixture-broker.js +68 -0
  333. package/src/runtime/space-lock.js +337 -0
  334. package/src/runtime/space-platform.js +133 -0
  335. package/src/runtime/space-source.js +290 -0
  336. package/src/runtime/space-test-server.js +354 -0
  337. package/src/runtime/space-verification.js +94 -0
  338. package/src/runtime/space-verify-browser-worker.js +51 -0
  339. package/src/runtime/space-view-manifest.js +368 -0
  340. package/src/runtime/sync-skills.d.ts +5 -1
  341. package/src/runtime/sync-skills.js +11 -2
  342. package/src/runtime/tool-confirmation.js +138 -0
  343. package/src/runtime/transport.js +118 -24
  344. package/src/runtime/upsell.js +219 -0
  345. package/src/runtime/view-render.js +49 -0
  346. package/src/skill-sync-worker-entry.js +2 -0
  347. package/src/skill-sync-worker.js +114 -0
  348. package/src/space-harness-host.ts +122 -0
  349. package/template/.harness/index.html.tmpl +9 -352
  350. package/template/app/globals.css +29 -3
  351. package/template/app/layout.tsx +2 -6
  352. package/template/components/ui/badge.tsx +7 -4
  353. package/template/components/ui/button.tsx +1 -1
  354. package/template/components/ui/native-select.tsx +24 -0
  355. package/template/notis.config.ts +4 -36
  356. package/template/package-lock.json +1800 -1867
  357. package/template/package.json +16 -14
  358. package/template/postcss.config.mjs +1 -1
  359. package/template/tailwind.config.ts +1 -6
  360. package/template/tsconfig.json +1 -0
  361. package/template/vite.config.ts +2 -2
  362. package/dist/base-skills/notis-apps/SKILL.md +0 -613
  363. package/skills/notis-apps/cli.md +0 -285
  364. package/src/command-specs/apps.js +0 -3000
  365. package/src/runtime/app-changelog.js +0 -79
  366. package/src/runtime/app-dev-consumers.js +0 -154
  367. package/src/runtime/app-dev-host-lock.js +0 -80
  368. package/src/runtime/app-dev-process-identity.js +0 -111
  369. package/src/runtime/app-dev-roots.js +0 -284
  370. package/src/runtime/app-dev-server.js +0 -1140
  371. package/src/runtime/app-dev-sessions.js +0 -185
  372. package/src/runtime/app-registry-scaffolds.js +0 -367
  373. package/src/runtime/assets/store-screenshot-dark.png +0 -0
  374. package/src/runtime/cli-mode.generated.js +0 -5
  375. package/src/runtime/cli-mode.js +0 -34
  376. package/src/runtime/store-screenshot.js +0 -143
  377. package/template/CHANGELOG.md +0 -5
  378. package/template/app/page.tsx +0 -60
  379. package/template/components/ui/card.tsx +0 -56
  380. package/template/packages/sdk/src/components/DocumentEditor.tsx +0 -103
  381. package/template/packages/sdk/src/config.ts +0 -259
  382. package/template/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  383. package/template/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  384. package/template/packages/sdk/src/hooks/useDocument.ts +0 -78
  385. package/template/packages/sdk/src/hooks/useNotisNavigation.ts +0 -52
  386. package/template/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  387. package/template/packages/sdk/src/runtime.ts +0 -439
  388. package/template/packages/sdk/src/vite.ts +0 -56
  389. package/template/packages/sdk/tsconfig.json +0 -15
  390. /package/{template/packages → dist}/sdk/src/components/MultiSelectDragOverlay.tsx +0 -0
  391. /package/{template/packages → dist}/sdk/src/components/ShortcutHints.tsx +0 -0
  392. /package/{template/packages → dist}/sdk/src/hooks/useActiveResource.ts +0 -0
  393. /package/{template/packages → dist}/sdk/src/hooks/useTool.ts +0 -0
  394. /package/{template/packages → dist}/sdk/src/hooks/useTools.ts +0 -0
  395. /package/{template/packages → dist}/sdk/src/ui.ts +0 -0
@@ -2,9 +2,17 @@
2
2
  * `notis handover` -- give the branch you are on to a Notis agent.
3
3
  *
4
4
  * The coding agent already sitting in the user's terminal is the caller here.
5
- * It pushes the branch, then hands the task to whichever agent the user picked:
6
- * the hosted Notis agent, or their own Codex/Claude Code running in the Notis
7
- * cloud sandbox or on their Mac.
5
+ * It pushes the branch, then starts a Notis thread for the task. The caller
6
+ * names who runs it and how, from the user's words, so the choice is never left
7
+ * to the Manager: `--route notis|codex|claude` becomes a plain sentence at the
8
+ * end of the task ("Use Codex for this task."), so it wins like it does in a
9
+ * chat message, and `--intelligence` and `--speed` become the thread's
10
+ * settings. `auto` hands a choice back to Notis, only when the user asked.
11
+ *
12
+ * The thread is started with `LOCAL_NOTIS_CONTROL_THREADS` create, the same
13
+ * operation voice, the hosted MCP and the agents use to start work. It shows up
14
+ * in the Manager like any other conversation, and its request receipt is what
15
+ * `handover status` reads back.
8
16
  *
9
17
  * The CLI deliberately does not create the cloud workspace itself. Doing so
10
18
  * would hard-code the Conductor app's database schema and script paths into the
@@ -15,6 +23,8 @@
15
23
  * on and getting it to origin.
16
24
  */
17
25
 
26
+ import { randomUUID } from 'node:crypto';
27
+
18
28
  import { CliError, EXIT_CODES, usageError } from '../runtime/errors.js';
19
29
  import {
20
30
  commitWorkingTree,
@@ -25,16 +35,40 @@ import {
25
35
  import { assertNotDelegated } from '../runtime/delegated-context.js';
26
36
  import { fetchToolSchema, nextIdempotencyKey, runToolCommand } from './helpers.js';
27
37
 
28
- const HAND_OVER_TOOL = 'LOCAL_NOTIS_HAND_OVER';
29
- const SEARCH_THREADS_TOOL = 'LOCAL_NOTIS_SEARCH_CODING_AGENT_THREADS';
38
+ const THREADS_TOOL = 'LOCAL_NOTIS_CONTROL_THREADS';
30
39
 
31
- const ROUTES = ['notis', 'auto', 'codex_cloud', 'claude_cloud', 'codex_local', 'claude_local'];
40
+ // What --route accepts and advertises. `auto` lets Notis pick the agent.
41
+ const ROUTES = ['notis', 'codex', 'claude', 'auto'];
42
+ // Values from before Notis picked the agent itself, the retired Mac runtimes
43
+ // among them. Still accepted, so scripts and agents that learned them keep
44
+ // working, but never shown in help, examples or errors. Each one now means the
45
+ // agent it names.
46
+ const LEGACY_ROUTES = new Map([
47
+ ['codex_cloud', 'codex'],
48
+ ['codex_local', 'codex'],
49
+ ['claude_cloud', 'claude'],
50
+ ['claude_local', 'claude'],
51
+ ]);
52
+ const ROUTE_LABELS = { notis: 'Notis', codex: 'Codex', claude: 'Claude' };
32
53
  const BRANCH_MODES = ['new', 'same'];
54
+ // The thread's settings. `auto` lets Notis pick the intelligence.
55
+ const INTELLIGENCE = ['low', 'medium', 'high', 'auto'];
56
+ const SPEEDS = ['normal', 'priority', 'flex'];
57
+ // Who runs the hand-over and how. All three are required, so the caller turns
58
+ // the user's words into a choice rather than leaving it to the Manager.
59
+ const CHOICES = [
60
+ ['route', '--route', ROUTES],
61
+ ['intelligence', '--intelligence', INTELLIGENCE],
62
+ ['speed', '--speed', SPEEDS],
63
+ ];
33
64
 
34
- // A cloud coding agent takes minutes to start, and the hand-over POST itself
35
- // queues a manager turn. 30s is the CLI default and is not enough headroom.
65
+ // A cloud coding agent takes minutes to start, and creating the thread admits
66
+ // its first turn. 30s is the CLI default and is not enough headroom.
36
67
  const HANDOVER_TIMEOUT_MS = 120_000;
37
68
 
69
+ const TITLE_LENGTH = 120;
70
+ const RECENT_THREADS = 20;
71
+
38
72
  /**
39
73
  * Preflight outcomes that mean "this account cannot hand over", as opposed to
40
74
  * "something went wrong on the way to asking". A tool denied by surface policy
@@ -44,6 +78,27 @@ const HANDOVER_TIMEOUT_MS = 120_000;
44
78
  */
45
79
  const HANDOVER_UNAVAILABLE_CODES = new Set(['usage_error', 'forbidden']);
46
80
 
81
+ /** A legacy route as the agent it now means; anything else unchanged. */
82
+ function normalizeRoute(route) {
83
+ return LEGACY_ROUTES.get(route) || route;
84
+ }
85
+
86
+ /** Who the hand-over went to, in words, for progress lines and the summary. */
87
+ function describeRoute(route) {
88
+ if (route === 'auto') return 'Notis, which picks the agent';
89
+ return ROUTE_LABELS[route] || route;
90
+ }
91
+
92
+ /**
93
+ * The task as the thread receives it. A named agent becomes a plain sentence at
94
+ * the end ("Use Codex for this task."), so the user's choice wins like it does
95
+ * in a chat message; `auto` adds nothing and Notis picks the agent.
96
+ */
97
+ function routedInstruction(instruction, route) {
98
+ const name = ROUTE_LABELS[route];
99
+ return name ? `${instruction}\n\nUse ${name} for this task.` : instruction;
100
+ }
101
+
47
102
  /**
48
103
  * Quote a value for the command line the receiving agent is told to run.
49
104
  *
@@ -106,6 +161,66 @@ function buildInstruction({ task, repository, branchMode, repoSlug }) {
106
161
  ].join('\n');
107
162
  }
108
163
 
164
+ /** The task's first line, short enough to read in the Manager's thread list. */
165
+ function threadTitle(task) {
166
+ const line = task.split('\n').find((part) => part.trim()) || task;
167
+ const title = line.replace(/\s+/g, ' ').trim();
168
+ return title.length > TITLE_LENGTH ? `${title.slice(0, TITLE_LENGTH - 3)}...` : title;
169
+ }
170
+
171
+ /** The intelligence and speed as the thread's settings. */
172
+ function threadSettings(intelligence, speed) {
173
+ return intelligence === 'auto' ? { auto: true, speed } : { mode: intelligence, speed };
174
+ }
175
+
176
+ /** The intelligence and speed, in words, for progress lines and the summary. */
177
+ function describeSettings(intelligence, speed) {
178
+ const level = intelligence === 'auto' ? 'Notis picks the intelligence' : `${intelligence} intelligence`;
179
+ return `${level}, ${speed} speed`;
180
+ }
181
+
182
+ /**
183
+ * The command that starts this hand-over again: with its key, the same
184
+ * request; without one, a new request.
185
+ */
186
+ function startCommand({ task, branchMode, route, intelligence, speed, repoSlug }, idempotencyKey = null) {
187
+ return [
188
+ ...(idempotencyKey ? ['notis --idempotency-key', shellSingleQuote(idempotencyKey)] : ['notis']),
189
+ 'handover start', shellSingleQuote(task),
190
+ '--route', route, '--intelligence', intelligence, '--speed', speed,
191
+ ...(branchMode === 'new' ? [] : ['--branch-mode', branchMode]),
192
+ ...(repoSlug ? ['--repo', shellSingleQuote(repoSlug)] : []),
193
+ ].join(' ');
194
+ }
195
+
196
+ /**
197
+ * How to settle a start whose outcome is unknown. Asking again with the same
198
+ * key settles it only when the answer was lost on the way (a timeout, a dropped
199
+ * connection) or the first attempt is still running. Any other uncertain answer
200
+ * is kept under the key and replayed as it is, so check whether the work
201
+ * started, and hand it over afresh only if it did not. A refusal gets neither:
202
+ * asking again cannot change it.
203
+ */
204
+ function recoveryHints(error, command, idempotencyKey, requestIds = []) {
205
+ const serverCode = error.details?.error?.code;
206
+ if (['network_timeout', 'network_error'].includes(error.code) || serverCode === 'idempotency_in_progress') {
207
+ return [{
208
+ command: startCommand(command, idempotencyKey),
209
+ reason: 'Ask again with the same key: it returns this hand-over\'s answer and never starts the work twice',
210
+ }];
211
+ }
212
+ if (['backend_error', 'handover_unconfirmed'].includes(error.code) || serverCode === 'idempotency_outcome_unknown') {
213
+ return [
214
+ {
215
+ command: requestIds[0] ? `notis handover status ${requestIds[0]}` : 'notis handover status',
216
+ reason: 'Check whether the hand-over started before anything else',
217
+ },
218
+ { command: startCommand(command), reason: 'Only if it did not start: hand it over again as a new request' },
219
+ ];
220
+ }
221
+ return [];
222
+ }
223
+
109
224
  async function handoverStartHandler(ctx) {
110
225
  // First statement on purpose. Everything below spends the user's credits and
111
226
  // starts real work; the check that this is a person's terminal comes first.
@@ -121,23 +236,45 @@ async function handoverStartHandler(ctx) {
121
236
  throw usageError(`--branch-mode must be one of: ${BRANCH_MODES.join(', ')}`, { branchMode });
122
237
  }
123
238
 
124
- const route = ctx.options.route || 'notis';
125
- if (!ROUTES.includes(route)) {
126
- throw usageError(`--route must be one of: ${ROUTES.join(', ')}`, { route });
239
+ const choice = {
240
+ route: ctx.options.route === undefined ? undefined : normalizeRoute(ctx.options.route),
241
+ intelligence: ctx.options.intelligence,
242
+ speed: ctx.options.speed,
243
+ };
244
+ for (const [name, flag, values] of CHOICES) {
245
+ if (choice[name] !== undefined && !values.includes(choice[name])) {
246
+ throw usageError(`${flag} must be one of: ${values.join(', ')}`, { [name]: ctx.options[name] });
247
+ }
248
+ }
249
+ // No defaults: a missing choice stops here, before git is touched, and the
250
+ // refusal names every one still to make.
251
+ const missing = CHOICES.filter(([name]) => choice[name] === undefined);
252
+ if (missing.length) {
253
+ throw usageError(
254
+ 'Choose who runs the hand-over and how from the user\'s words, then pass '
255
+ + `${missing.map(([, flag, values]) => `${flag} ${values.join('|')}`).join(', ')}.`,
256
+ { missing: missing.map(([, flag]) => flag) },
257
+ );
258
+ }
259
+ const { route, intelligence, speed } = choice;
260
+ // Codex and Claude have no flex speed, and with auto Notis may pick either,
261
+ // which would then inherit it.
262
+ if (speed === 'flex' && route !== 'notis') {
263
+ throw usageError('--speed flex runs on Notis only; use --route notis, or --speed normal.', { route, speed });
127
264
  }
128
265
 
129
266
  const repository = inspectRepository(ctx.options.cwd || process.cwd());
130
267
 
131
268
  // Ask whether the hand-over is even allowed before touching git. Everything
132
269
  // below this line is irreversible from the user's point of view -- a commit
133
- // and a push -- and during rollout the common answer is "not available",
134
- // which would otherwise leave a `wip:` commit on their remote for a hand-over
135
- // that never happened.
270
+ // and a push -- and a server that does not offer the tool here would
271
+ // otherwise leave a `wip:` commit on their remote for a hand-over that never
272
+ // happened.
136
273
  //
137
274
  // Only an explicit refusal blocks: a network or schema hiccup must not stop a
138
275
  // hand-over that would have worked.
139
276
  try {
140
- await fetchToolSchema(ctx.runtime, HAND_OVER_TOOL);
277
+ await fetchToolSchema(ctx.runtime, THREADS_TOOL);
141
278
  } catch (error) {
142
279
  if (error instanceof CliError && HANDOVER_UNAVAILABLE_CODES.has(error.code)) {
143
280
  throw new CliError({
@@ -216,33 +353,71 @@ async function handoverStartHandler(ctx) {
216
353
  throw error;
217
354
  }
218
355
 
219
- const instruction = buildInstruction({
220
- task,
221
- repository,
222
- branchMode,
223
- repoSlug: ctx.options.repo || null,
224
- });
356
+ const repoSlug = ctx.options.repo || null;
357
+ const instruction = buildInstruction({ task, repository, branchMode, repoSlug });
225
358
 
226
- ctx.output.emitProgress({ phase: 'handover', message: `Handing over to ${route}` });
227
- const result = await runToolCommand({
228
- runtime: {
229
- ...ctx.runtime,
230
- // Raise the floor, never pin: an explicit --timeout-ms must still win.
231
- timeoutMs: Math.max(ctx.runtime.timeoutMs || 0, HANDOVER_TIMEOUT_MS),
232
- },
233
- toolName: HAND_OVER_TOOL,
234
- arguments_: { instruction, agent_routing: route },
235
- mutating: true,
236
- idempotencyKey: nextIdempotencyKey(ctx.globalOptions),
359
+ // One key names this hand-over end to end: the HTTP retry key and, prefixed,
360
+ // the thread request. Resending it returns the thread the first attempt made.
361
+ const idempotencyKey = nextIdempotencyKey(ctx.globalOptions);
362
+ const requestKey = `handover:${idempotencyKey}`;
363
+ const command = { task, branchMode, route, intelligence, speed, repoSlug };
364
+
365
+ ctx.output.emitProgress({
366
+ phase: 'handover',
367
+ message: `Handing over to ${describeRoute(route)} (${describeSettings(intelligence, speed)})`,
237
368
  });
369
+ let result;
370
+ try {
371
+ result = await runToolCommand({
372
+ runtime: {
373
+ ...ctx.runtime,
374
+ // Raise the floor, never pin: an explicit --timeout-ms must still win.
375
+ timeoutMs: Math.max(ctx.runtime.timeoutMs || 0, HANDOVER_TIMEOUT_MS),
376
+ },
377
+ toolName: THREADS_TOOL,
378
+ arguments_: {
379
+ action: 'create',
380
+ request_id: requestKey,
381
+ instructions: routedInstruction(instruction, route),
382
+ title: threadTitle(task),
383
+ settings: threadSettings(intelligence, speed),
384
+ },
385
+ mutating: true,
386
+ idempotencyKey,
387
+ });
388
+ } catch (error) {
389
+ // A failed call may still have started the thread. Say how to find out
390
+ // without starting the work twice.
391
+ if (error instanceof CliError) {
392
+ error.details = { ...error.details, request_key: requestKey };
393
+ error.hints = [...(error.hints || []), ...recoveryHints(error, command, idempotencyKey)];
394
+ }
395
+ throw error;
396
+ }
238
397
 
239
398
  const payload = result?.payload ?? {};
240
399
  if (payload.status === 'error') {
241
400
  throw new CliError({
242
401
  code: payload.error_code || 'handover_failed',
243
- message: payload.message || 'Notis could not start the hand-over.',
402
+ message: payload.message || `Notis could not start the hand-over (${payload.error_code || 'error'}).`,
244
403
  exitCode: EXIT_CODES.backend,
245
- details: payload.details || {},
404
+ details: { request_key: requestKey, http_status: payload.http_status ?? null },
405
+ });
406
+ }
407
+ if (payload.status !== 'accepted') {
408
+ const requestIds = payload.request_ids || [];
409
+ throw new CliError({
410
+ code: 'handover_unconfirmed',
411
+ message:
412
+ 'Notis could not confirm that the hand-over started. It may be running already, '
413
+ + 'so check its status before handing it over again.',
414
+ exitCode: EXIT_CODES.backend,
415
+ details: {
416
+ request_key: requestKey,
417
+ request_ids: requestIds,
418
+ cause: payload.error_code || null,
419
+ },
420
+ hints: recoveryHints({ code: 'handover_unconfirmed' }, command, idempotencyKey, requestIds),
246
421
  });
247
422
  }
248
423
 
@@ -255,21 +430,29 @@ async function handoverStartHandler(ctx) {
255
430
  branch_mode: branchMode,
256
431
  head: repository.head,
257
432
  wip_commit: wipCommit,
258
- agent_routing: payload.agent_routing || route,
259
- interaction_id: payload.interaction_id || null,
433
+ agent_routing: route,
434
+ intelligence,
435
+ speed,
436
+ request_id: payload.request_id || null,
437
+ request_key: payload.request_key || requestKey,
438
+ row_id: payload.row_id || null,
260
439
  thread_id: payload.thread_id || null,
440
+ interaction_id: payload.interaction_id || null,
261
441
  };
262
442
 
263
443
  return ctx.output.emitSuccess({
264
444
  command: 'handover start',
265
445
  data,
266
446
  humanSummary:
267
- `Handed ${data.branch} over to ${data.agent_routing} ` +
268
- `(${branchMode === 'same' ? 'continuing the branch' : 'new branch from it'}).`,
447
+ `Handed ${data.branch} over to ${describeRoute(data.agent_routing)} `
448
+ + `(${describeSettings(intelligence, speed)}; `
449
+ + `${branchMode === 'same' ? 'continuing the branch' : 'new branch from it'}).`,
269
450
  hints: [
270
- { command: 'notis handover status', reason: 'See what the agent is doing' },
451
+ ...(data.request_id
452
+ ? [{ command: `notis handover status ${data.request_id}`, reason: 'Follow the hand-over and read its result' }]
453
+ : []),
271
454
  {
272
- command: `git fetch origin ${repository.branch}`,
455
+ command: `git fetch origin ${shellSingleQuote(repository.branch)}`,
273
456
  reason: 'Pull the agent\'s commits back down when it has pushed',
274
457
  },
275
458
  ],
@@ -277,32 +460,83 @@ async function handoverStartHandler(ctx) {
277
460
  });
278
461
  }
279
462
 
463
+ function eventText(event) {
464
+ const body = event?.body || {};
465
+ const message = body.message || {};
466
+ const text = message.text || message.body || message.content || body.text || '';
467
+ return typeof text === 'string' ? text : JSON.stringify(text);
468
+ }
469
+
280
470
  async function handoverStatusHandler(ctx) {
471
+ const requestId = (ctx.args.requestId || '').trim();
281
472
  const result = await runToolCommand({
282
473
  runtime: ctx.runtime,
283
- toolName: SEARCH_THREADS_TOOL,
284
- arguments_: {
285
- ...(ctx.options.provider ? { provider: ctx.options.provider } : {}),
286
- ...(ctx.options.refresh ? { refresh: true } : {}),
287
- },
474
+ toolName: THREADS_TOOL,
475
+ arguments_: requestId
476
+ ? { action: 'request', request_id: requestId }
477
+ : { action: 'list', filters: { activity: 'running' }, limit: RECENT_THREADS },
288
478
  mutating: false,
479
+ // The tool also writes, so the server asks every call for a key. A fresh
480
+ // one, never --idempotency-key: a reused key would replay a cached, stale
481
+ // read instead of asking again.
482
+ idempotencyKey: randomUUID(),
483
+ sendIdempotencyKeyWhenReading: true,
289
484
  });
290
485
 
291
486
  const payload = result?.payload ?? {};
292
- const threads = Array.isArray(payload.threads) ? payload.threads : [];
487
+ if (payload.status === 'error') {
488
+ throw new CliError({
489
+ code: payload.error_code || 'handover_status_failed',
490
+ message: payload.message || `Notis could not read the hand-over (${payload.error_code || 'error'}).`,
491
+ exitCode: EXIT_CODES.backend,
492
+ details: { request_id: requestId || null, http_status: payload.http_status ?? null },
493
+ });
494
+ }
293
495
 
496
+ if (!requestId) {
497
+ // The running filter applies to the most recent threads only, so say so
498
+ // rather than claiming nothing runs anywhere.
499
+ const threads = Array.isArray(payload.threads) ? payload.threads : [];
500
+ const summary = threads.length
501
+ ? `${threads.length} of your ${RECENT_THREADS} most recent threads running.`
502
+ : `None of your ${RECENT_THREADS} most recent threads is running.`;
503
+ return ctx.output.emitSuccess({
504
+ command: 'handover status',
505
+ data: { threads },
506
+ humanSummary: summary,
507
+ hints: [
508
+ { command: 'notis handover status <request-id>', reason: 'Read one hand-over\'s progress and result' },
509
+ ],
510
+ renderHuman: () => [
511
+ summary,
512
+ ...threads.map((thread) => ` ${thread.id} ${thread.title || '(untitled)'}`),
513
+ ].join('\n'),
514
+ meta: { mutating: false },
515
+ });
516
+ }
517
+
518
+ const events = Array.isArray(payload.events) ? payload.events : [];
519
+ const finished = events.find((event) => event?.terminal);
520
+ const summary = finished
521
+ ? `The hand-over finished (${finished.kind}).`
522
+ : `The hand-over is still running (${events.length} update(s) so far).`;
294
523
  return ctx.output.emitSuccess({
295
524
  command: 'handover status',
296
525
  data: payload,
297
- humanSummary: threads.length
298
- ? `${threads.length} coding-agent thread(s).`
299
- : 'No coding-agent threads yet. A hosted Notis hand-over shows up in the portal instead.',
300
- hints: [
301
- {
302
- command: 'notis tools exec LOCAL_NOTIS_OBSERVE_CODING_AGENT_THREAD --arguments \'{"external_session_id":"...","question":"..."}\'',
303
- reason: 'Ask a focused question about one thread',
304
- },
305
- ],
526
+ humanSummary: summary,
527
+ hints: payload.has_more
528
+ ? [{
529
+ command:
530
+ `notis tools exec ${THREADS_TOOL} --arguments '${JSON.stringify({
531
+ action: 'request', request_id: requestId, after: payload.next_cursor,
532
+ })}'`,
533
+ reason: 'Read the next page of updates',
534
+ }]
535
+ : [],
536
+ renderHuman: () => [
537
+ summary,
538
+ ...events.map((event) => `\n[${event.kind}] ${eventText(event)}`.trimEnd()),
539
+ ].join('\n'),
306
540
  meta: { mutating: false },
307
541
  });
308
542
  }
@@ -312,22 +546,36 @@ export const handoverCommandSpecs = [
312
546
  command_path: ['handover', 'start'],
313
547
  summary: 'Hand the current branch to a Notis agent and keep working.',
314
548
  when_to_use:
315
- 'Use this when you want Notis to continue work on the branch you are on -- long refactors, ' +
316
- 'test fixing, or anything that should keep running after you close the laptop. Pick the agent ' +
317
- 'with --route.',
549
+ 'Use this when you want Notis to continue work on the branch you are on -- long refactors, '
550
+ + 'test fixing, or anything that should keep running after you close the laptop. Choose the agent, '
551
+ + 'intelligence and speed yourself from the user\'s words, even loose ones ("get Claude on it", '
552
+ + '"this one is tricky", "no rush"), and pass all three; with no agent named, codex for code work. '
553
+ + 'Use auto only when the user asks Notis to pick.',
318
554
  args_schema: {
319
555
  arguments: [{ token: '<task>', description: 'What the agent should do, in plain language.' }],
320
556
  options: [
321
557
  {
322
- flags: '--branch-mode <mode>',
323
- key: 'branchMode',
558
+ flags: '--route <agent>',
324
559
  description:
325
- 'same = the agent commits onto your branch. new = the agent cuts a new branch from it (default).',
560
+ 'Required. Which agent runs it: notis, codex or claude, or auto only when the user asks Notis to pick.',
326
561
  },
327
562
  {
328
- flags: '--route <target>',
563
+ flags: '--intelligence <level>',
329
564
  description:
330
- 'Which agent runs it: notis (hosted, default), codex_cloud, claude_cloud, codex_local, claude_local, or auto.',
565
+ 'Required. low (quick, simple tasks), medium (most multi-step work and coding), high (hard '
566
+ + 'reasoning, investigations, complex code), or auto only when the user asks Notis to pick.',
567
+ },
568
+ {
569
+ flags: '--speed <speed>',
570
+ description:
571
+ 'Required. normal (the usual choice), priority (faster, costs more; for Codex or Claude only when '
572
+ + 'the user asks for their fast mode) or flex (cheaper and slower, Notis only).',
573
+ },
574
+ {
575
+ flags: '--branch-mode <mode>',
576
+ key: 'branchMode',
577
+ description:
578
+ 'same = the agent commits onto your branch. new = the agent cuts a new branch from it (default).',
331
579
  },
332
580
  { flags: '--repo <slug>', description: 'Configured repository slug on the cloud computer, when you know it.' },
333
581
  {
@@ -337,38 +585,42 @@ export const handoverCommandSpecs = [
337
585
  ],
338
586
  },
339
587
  examples: [
340
- 'notis handover start "fix the failing auth tests"',
341
- 'notis handover start "finish the migration" --branch-mode same --route codex_cloud',
342
- 'notis handover start "add integration tests" --route claude_cloud',
343
- 'notis handover start "review and clean up this branch" --route claude_local',
588
+ 'notis handover start "fix the failing auth tests" --route codex --intelligence medium --speed normal',
589
+ 'notis handover start "finish the migration" --branch-mode same --route codex --intelligence high --speed normal',
590
+ 'notis handover start "add integration tests" --route claude --intelligence medium --speed normal',
591
+ 'notis handover start "review and clean up this branch" --route notis --intelligence low --speed flex',
344
592
  ],
345
593
  output_schema:
346
- 'Returns the branch, the resolved routing target, and the interaction/thread ids of the started run.',
594
+ 'Returns the branch, the agent routing (notis, codex or claude, or auto when Notis picks), the '
595
+ + 'intelligence and speed the thread runs at, and the started thread: its request_id (for '
596
+ + '`handover status`), row and thread ids, and the interaction id of its first turn.',
347
597
  mutates: true,
348
598
  idempotent: false,
349
599
  require_auth: true,
350
- related_commands: ['notis handover status'],
351
- backend_call: { type: 'tool', name: HAND_OVER_TOOL },
600
+ related_commands: ['notis handover status <request-id>'],
601
+ backend_call: { type: 'tool', name: THREADS_TOOL },
352
602
  handler: handoverStartHandler,
353
603
  },
354
604
  {
355
605
  command_path: ['handover', 'status'],
356
- summary: 'Show the coding-agent threads Notis is running for you.',
357
- when_to_use: 'Use this after a hand-over to see whether the agent is still working.',
606
+ summary: 'Follow a hand-over, or list the work Notis is running for you.',
607
+ when_to_use:
608
+ 'Use this after a hand-over. Pass the request_id `handover start` returned to read its progress '
609
+ + 'and result; with no id it lists the threads still running.',
358
610
  args_schema: {
359
- arguments: [],
360
- options: [
361
- { flags: '--provider <provider>', description: 'Filter to codex or claude_code.' },
362
- { flags: '--refresh', description: 'Force a live refresh instead of cached state.' },
611
+ arguments: [
612
+ { token: '[request-id]', key: 'requestId', description: 'The request_id `handover start` returned.' },
363
613
  ],
614
+ options: [],
364
615
  },
365
- examples: ['notis handover status', 'notis handover status --provider codex --refresh'],
366
- output_schema: 'Returns the coding-agent thread list with status and metadata.',
616
+ examples: ['notis handover status', 'notis handover status 6f1c2e8a-4b7d-5c3e-9a1f-2d8b7e6c5a4f'],
617
+ output_schema:
618
+ 'With a request id: the request state, its result and its updates. Without: the running threads.',
367
619
  mutates: false,
368
620
  idempotent: true,
369
621
  require_auth: true,
370
622
  related_commands: ['notis handover start <task>'],
371
- backend_call: { type: 'tool', name: SEARCH_THREADS_TOOL },
623
+ backend_call: { type: 'tool', name: THREADS_TOOL },
372
624
  handler: handoverStatusHandler,
373
625
  },
374
626
  ];