@synap-core/cli 1.12.2 → 1.13.1-next.20261102.ec3d166

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 (354) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -11
  3. package/dist/build-info.json +2 -3
  4. package/dist/commands/agents.d.ts +0 -1
  5. package/dist/commands/agents.js +13 -3
  6. package/dist/commands/agents.js.map +1 -1
  7. package/dist/commands/app.js +2 -1
  8. package/dist/commands/app.js.map +1 -1
  9. package/dist/commands/automation.js +46 -41
  10. package/dist/commands/automation.js.map +1 -1
  11. package/dist/commands/box.d.ts +42 -0
  12. package/dist/commands/box.js +89 -0
  13. package/dist/commands/box.js.map +1 -0
  14. package/dist/commands/bridge-setup.js +3 -1
  15. package/dist/commands/bridge-setup.js.map +1 -1
  16. package/dist/commands/capability.d.ts +87 -1
  17. package/dist/commands/capability.js +174 -64
  18. package/dist/commands/capability.js.map +1 -1
  19. package/dist/commands/close-questions.d.ts +27 -0
  20. package/dist/commands/close-questions.js +49 -0
  21. package/dist/commands/close-questions.js.map +1 -0
  22. package/dist/commands/close-questions.test.d.ts +1 -0
  23. package/dist/commands/close-questions.test.js +52 -0
  24. package/dist/commands/close-questions.test.js.map +1 -0
  25. package/dist/commands/connect.d.ts +1 -3
  26. package/dist/commands/connect.js +2 -2
  27. package/dist/commands/connect.js.map +1 -1
  28. package/dist/commands/context.js +72 -43
  29. package/dist/commands/context.js.map +1 -1
  30. package/dist/commands/data-extra.d.ts +13 -0
  31. package/dist/commands/data-extra.js +35 -6
  32. package/dist/commands/data-extra.js.map +1 -1
  33. package/dist/commands/data.js +2 -1
  34. package/dist/commands/data.js.map +1 -1
  35. package/dist/commands/doctor.d.ts +39 -0
  36. package/dist/commands/doctor.js +136 -14
  37. package/dist/commands/doctor.js.map +1 -1
  38. package/dist/commands/hooks.d.ts +19 -0
  39. package/dist/commands/hooks.js +70 -0
  40. package/dist/commands/hooks.js.map +1 -0
  41. package/dist/commands/import.d.ts +25 -0
  42. package/dist/commands/import.js +98 -12
  43. package/dist/commands/import.js.map +1 -1
  44. package/dist/commands/init.d.ts +14 -0
  45. package/dist/commands/init.js +63 -21
  46. package/dist/commands/init.js.map +1 -1
  47. package/dist/commands/keys-request.d.ts +48 -0
  48. package/dist/commands/keys-request.js +236 -0
  49. package/dist/commands/keys-request.js.map +1 -0
  50. package/dist/commands/keys-request.test.d.ts +1 -0
  51. package/dist/commands/keys-request.test.js +176 -0
  52. package/dist/commands/keys-request.test.js.map +1 -0
  53. package/dist/commands/knowledge.d.ts +6 -0
  54. package/dist/commands/knowledge.js +13 -3
  55. package/dist/commands/knowledge.js.map +1 -1
  56. package/dist/commands/lens.js +2 -1
  57. package/dist/commands/lens.js.map +1 -1
  58. package/dist/commands/market-authoring.js +1 -1
  59. package/dist/commands/market-authoring.js.map +1 -1
  60. package/dist/commands/market.d.ts +61 -4
  61. package/dist/commands/market.js +106 -48
  62. package/dist/commands/market.js.map +1 -1
  63. package/dist/commands/mcp.d.ts +1 -1
  64. package/dist/commands/mcp.js +14 -9
  65. package/dist/commands/mcp.js.map +1 -1
  66. package/dist/commands/observe.category.test.d.ts +1 -0
  67. package/dist/commands/observe.category.test.js +59 -0
  68. package/dist/commands/observe.category.test.js.map +1 -0
  69. package/dist/commands/observe.d.ts +3 -0
  70. package/dist/commands/observe.js +7 -5
  71. package/dist/commands/observe.js.map +1 -1
  72. package/dist/commands/observe.title.test.d.ts +1 -0
  73. package/dist/commands/observe.title.test.js +37 -0
  74. package/dist/commands/observe.title.test.js.map +1 -0
  75. package/dist/commands/playbook.js +9 -0
  76. package/dist/commands/playbook.js.map +1 -1
  77. package/dist/commands/pods.d.ts +6 -1
  78. package/dist/commands/pods.js +38 -17
  79. package/dist/commands/pods.js.map +1 -1
  80. package/dist/commands/proposals-actions.js +7 -1
  81. package/dist/commands/proposals-actions.js.map +1 -1
  82. package/dist/commands/proton-setup.js +3 -1
  83. package/dist/commands/proton-setup.js.map +1 -1
  84. package/dist/commands/providers.d.ts +22 -6
  85. package/dist/commands/providers.js +39 -32
  86. package/dist/commands/providers.js.map +1 -1
  87. package/dist/commands/raycast.d.ts +15 -0
  88. package/dist/commands/raycast.js +36 -10
  89. package/dist/commands/raycast.js.map +1 -1
  90. package/dist/commands/session-feed-wait.d.ts +48 -0
  91. package/dist/commands/session-feed-wait.js +261 -0
  92. package/dist/commands/session-feed-wait.js.map +1 -0
  93. package/dist/commands/session-post.d.ts +40 -0
  94. package/dist/commands/session-post.js +96 -0
  95. package/dist/commands/session-post.js.map +1 -0
  96. package/dist/commands/session-wait.d.ts +9 -4
  97. package/dist/commands/session-wait.js +20 -5
  98. package/dist/commands/session-wait.js.map +1 -1
  99. package/dist/commands/sessions.d.ts +2 -0
  100. package/dist/commands/sessions.js +23 -0
  101. package/dist/commands/sessions.js.map +1 -1
  102. package/dist/commands/skills-commands.d.ts +2 -0
  103. package/dist/commands/skills-commands.js +9 -1
  104. package/dist/commands/skills-commands.js.map +1 -1
  105. package/dist/commands/skills-commands.test.d.ts +1 -0
  106. package/dist/commands/skills-commands.test.js +57 -0
  107. package/dist/commands/skills-commands.test.js.map +1 -0
  108. package/dist/commands/status.js +13 -7
  109. package/dist/commands/status.js.map +1 -1
  110. package/dist/commands/statusline.backoff.test.js +13 -3
  111. package/dist/commands/statusline.backoff.test.js.map +1 -1
  112. package/dist/commands/statusline.d.ts +104 -9
  113. package/dist/commands/statusline.js +392 -148
  114. package/dist/commands/statusline.js.map +1 -1
  115. package/dist/commands/statusline.line2.test.d.ts +15 -0
  116. package/dist/commands/statusline.line2.test.js +226 -0
  117. package/dist/commands/statusline.line2.test.js.map +1 -0
  118. package/dist/commands/statusline.needs-you.test.d.ts +1 -0
  119. package/dist/commands/statusline.needs-you.test.js +17 -0
  120. package/dist/commands/statusline.needs-you.test.js.map +1 -0
  121. package/dist/commands/statusline.now.test.d.ts +10 -0
  122. package/dist/commands/statusline.now.test.js +250 -0
  123. package/dist/commands/statusline.now.test.js.map +1 -0
  124. package/dist/commands/tracks.d.ts +68 -6
  125. package/dist/commands/tracks.js +272 -16
  126. package/dist/commands/tracks.js.map +1 -1
  127. package/dist/commands/upload.js +12 -0
  128. package/dist/commands/upload.js.map +1 -1
  129. package/dist/commands/wait.d.ts +124 -0
  130. package/dist/commands/wait.js +384 -0
  131. package/dist/commands/wait.js.map +1 -0
  132. package/dist/commands/wait.test.d.ts +8 -0
  133. package/dist/commands/wait.test.js +308 -0
  134. package/dist/commands/wait.test.js.map +1 -0
  135. package/dist/commands/whoami.d.ts +7 -0
  136. package/dist/commands/whoami.js +17 -0
  137. package/dist/commands/whoami.js.map +1 -1
  138. package/dist/commands/worker-accounts.d.ts +149 -0
  139. package/dist/commands/worker-accounts.js +339 -0
  140. package/dist/commands/worker-accounts.js.map +1 -0
  141. package/dist/commands/worker-accounts.test.d.ts +1 -0
  142. package/dist/commands/worker-accounts.test.js +224 -0
  143. package/dist/commands/worker-accounts.test.js.map +1 -0
  144. package/dist/commands/worker-github-app.d.ts +63 -0
  145. package/dist/commands/worker-github-app.js +161 -0
  146. package/dist/commands/worker-github-app.js.map +1 -0
  147. package/dist/commands/worker-github-app.test.d.ts +1 -0
  148. package/dist/commands/worker-github-app.test.js +102 -0
  149. package/dist/commands/worker-github-app.test.js.map +1 -0
  150. package/dist/commands/worker-github-broker.d.ts +39 -0
  151. package/dist/commands/worker-github-broker.js +106 -0
  152. package/dist/commands/worker-github-broker.js.map +1 -0
  153. package/dist/commands/worker-github-broker.test.d.ts +1 -0
  154. package/dist/commands/worker-github-broker.test.js +90 -0
  155. package/dist/commands/worker-github-broker.test.js.map +1 -0
  156. package/dist/commands/worker-runs.test.d.ts +1 -0
  157. package/dist/commands/worker-runs.test.js +150 -0
  158. package/dist/commands/worker-runs.test.js.map +1 -0
  159. package/dist/commands/worker-worktrees.d.ts +34 -0
  160. package/dist/commands/worker-worktrees.js +87 -0
  161. package/dist/commands/worker-worktrees.js.map +1 -0
  162. package/dist/commands/worker.d.ts +406 -10
  163. package/dist/commands/worker.js +1180 -126
  164. package/dist/commands/worker.js.map +1 -1
  165. package/dist/commands/worker.test.js +588 -11
  166. package/dist/commands/worker.test.js.map +1 -1
  167. package/dist/index.js +220 -28
  168. package/dist/index.js.map +1 -1
  169. package/dist/lib/agent-door.d.ts +1 -3
  170. package/dist/lib/agent-door.js +10 -7
  171. package/dist/lib/agent-door.js.map +1 -1
  172. package/dist/lib/agents-config.d.ts +9 -0
  173. package/dist/lib/agents-config.js +20 -0
  174. package/dist/lib/agents-config.js.map +1 -1
  175. package/dist/lib/atomic-file.d.ts +20 -1
  176. package/dist/lib/atomic-file.js +100 -2
  177. package/dist/lib/atomic-file.js.map +1 -1
  178. package/dist/lib/auth.d.ts +28 -2
  179. package/dist/lib/auth.js +52 -12
  180. package/dist/lib/auth.js.map +1 -1
  181. package/dist/lib/box/egress.d.ts +82 -0
  182. package/dist/lib/box/egress.js +264 -0
  183. package/dist/lib/box/egress.js.map +1 -0
  184. package/dist/lib/box/evidence.d.ts +86 -0
  185. package/dist/lib/box/evidence.js +121 -0
  186. package/dist/lib/box/evidence.js.map +1 -0
  187. package/dist/lib/box/job-server.d.ts +72 -0
  188. package/dist/lib/box/job-server.js +250 -0
  189. package/dist/lib/box/job-server.js.map +1 -0
  190. package/dist/lib/box/provisioner.d.ts +83 -0
  191. package/dist/lib/box/provisioner.js +312 -0
  192. package/dist/lib/box/provisioner.js.map +1 -0
  193. package/dist/lib/box/proxmox.d.ts +112 -0
  194. package/dist/lib/box/proxmox.js +211 -0
  195. package/dist/lib/box/proxmox.js.map +1 -0
  196. package/dist/lib/box/wire.d.ts +98 -0
  197. package/dist/lib/box/wire.js +70 -0
  198. package/dist/lib/box/wire.js.map +1 -0
  199. package/dist/lib/bridge-invocation.test.d.ts +1 -0
  200. package/dist/lib/bridge-invocation.test.js +75 -0
  201. package/dist/lib/bridge-invocation.test.js.map +1 -0
  202. package/dist/lib/bridge-status.d.ts +144 -0
  203. package/dist/lib/bridge-status.js +227 -0
  204. package/dist/lib/bridge-status.js.map +1 -0
  205. package/dist/lib/bridge-status.test.d.ts +6 -0
  206. package/dist/lib/bridge-status.test.js +197 -0
  207. package/dist/lib/bridge-status.test.js.map +1 -0
  208. package/dist/lib/client-header.test.d.ts +1 -0
  209. package/dist/lib/client-header.test.js +103 -0
  210. package/dist/lib/client-header.test.js.map +1 -0
  211. package/dist/lib/conversation-headers.d.ts +89 -9
  212. package/dist/lib/conversation-headers.js +156 -3
  213. package/dist/lib/conversation-headers.js.map +1 -1
  214. package/dist/lib/conversation-headers.test.d.ts +1 -0
  215. package/dist/lib/conversation-headers.test.js +78 -0
  216. package/dist/lib/conversation-headers.test.js.map +1 -0
  217. package/dist/lib/credential-class.d.ts +40 -2
  218. package/dist/lib/credential-class.js +48 -6
  219. package/dist/lib/credential-class.js.map +1 -1
  220. package/dist/lib/device-connect.d.ts +45 -0
  221. package/dist/lib/device-connect.js +60 -0
  222. package/dist/lib/device-connect.js.map +1 -1
  223. package/dist/lib/exporter-coverage.d.ts +1 -1
  224. package/dist/lib/exporter-coverage.js +1 -1
  225. package/dist/lib/goal-words.d.ts +38 -0
  226. package/dist/lib/goal-words.js +115 -0
  227. package/dist/lib/goal-words.js.map +1 -0
  228. package/dist/lib/hub-client.d.ts +87 -8
  229. package/dist/lib/hub-client.js +205 -70
  230. package/dist/lib/hub-client.js.map +1 -1
  231. package/dist/lib/init-handoff.d.ts +8 -0
  232. package/dist/lib/init-handoff.js +9 -2
  233. package/dist/lib/init-handoff.js.map +1 -1
  234. package/dist/lib/key-locations.d.ts +3 -3
  235. package/dist/lib/key-locations.js +3 -39
  236. package/dist/lib/key-locations.js.map +1 -1
  237. package/dist/lib/key-source.d.ts +3 -1
  238. package/dist/lib/key-source.js +7 -4
  239. package/dist/lib/key-source.js.map +1 -1
  240. package/dist/lib/knowledge-title.d.ts +3 -2
  241. package/dist/lib/knowledge-title.js +3 -2
  242. package/dist/lib/knowledge-title.js.map +1 -1
  243. package/dist/lib/machine-instance.d.ts +7 -5
  244. package/dist/lib/machine-instance.js +7 -5
  245. package/dist/lib/machine-instance.js.map +1 -1
  246. package/dist/lib/mcp-bridge.d.ts +50 -0
  247. package/dist/lib/mcp-bridge.js +232 -11
  248. package/dist/lib/mcp-bridge.js.map +1 -1
  249. package/dist/lib/mcp-bridge.test.js +224 -4
  250. package/dist/lib/mcp-bridge.test.js.map +1 -1
  251. package/dist/lib/mcp-call.d.ts +5 -1
  252. package/dist/lib/mcp-call.js +7 -6
  253. package/dist/lib/mcp-call.js.map +1 -1
  254. package/dist/lib/mcp-connector-url.test.d.ts +1 -0
  255. package/dist/lib/mcp-connector-url.test.js +13 -0
  256. package/dist/lib/mcp-connector-url.test.js.map +1 -0
  257. package/dist/lib/mcp-snippets.d.ts +16 -0
  258. package/dist/lib/mcp-snippets.js +20 -2
  259. package/dist/lib/mcp-snippets.js.map +1 -1
  260. package/dist/lib/now-line.d.ts +66 -0
  261. package/dist/lib/now-line.js +193 -0
  262. package/dist/lib/now-line.js.map +1 -0
  263. package/dist/lib/now-line.test.d.ts +5 -0
  264. package/dist/lib/now-line.test.js +177 -0
  265. package/dist/lib/now-line.test.js.map +1 -0
  266. package/dist/lib/package-updates.d.ts +66 -0
  267. package/dist/lib/package-updates.js +76 -0
  268. package/dist/lib/package-updates.js.map +1 -0
  269. package/dist/lib/pod-moved.d.ts +70 -0
  270. package/dist/lib/pod-moved.js +146 -0
  271. package/dist/lib/pod-moved.js.map +1 -0
  272. package/dist/lib/pod-reach.d.ts +39 -0
  273. package/dist/lib/pod-reach.js +117 -0
  274. package/dist/lib/pod-reach.js.map +1 -0
  275. package/dist/lib/pod-reach.test.d.ts +1 -0
  276. package/dist/lib/pod-reach.test.js +67 -0
  277. package/dist/lib/pod-reach.test.js.map +1 -0
  278. package/dist/lib/pod.d.ts +8 -4
  279. package/dist/lib/pod.js +12 -10
  280. package/dist/lib/pod.js.map +1 -1
  281. package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
  282. package/dist/lib/register-claude-code-mcp.test.js +97 -0
  283. package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
  284. package/dist/lib/review-credential.js +3 -1
  285. package/dist/lib/review-credential.js.map +1 -1
  286. package/dist/lib/safe-open.d.ts +5 -3
  287. package/dist/lib/safe-open.js +9 -8
  288. package/dist/lib/safe-open.js.map +1 -1
  289. package/dist/lib/self-host.d.ts +17 -0
  290. package/dist/lib/self-host.js +24 -0
  291. package/dist/lib/self-host.js.map +1 -0
  292. package/dist/lib/session-feed.d.ts +185 -0
  293. package/dist/lib/session-feed.js +257 -0
  294. package/dist/lib/session-feed.js.map +1 -0
  295. package/dist/lib/targets.d.ts +52 -3
  296. package/dist/lib/targets.js +150 -209
  297. package/dist/lib/targets.js.map +1 -1
  298. package/dist/lib/term.d.ts +24 -0
  299. package/dist/lib/term.js +52 -0
  300. package/dist/lib/term.js.map +1 -0
  301. package/dist/lib/term.test.d.ts +1 -0
  302. package/dist/lib/term.test.js +29 -0
  303. package/dist/lib/term.test.js.map +1 -0
  304. package/dist/lib/transcript-index.d.ts +94 -0
  305. package/dist/lib/transcript-index.js +321 -0
  306. package/dist/lib/transcript-index.js.map +1 -0
  307. package/dist/lib/transcript-index.test.d.ts +10 -0
  308. package/dist/lib/transcript-index.test.js +200 -0
  309. package/dist/lib/transcript-index.test.js.map +1 -0
  310. package/dist/lib/wait-help.d.ts +11 -0
  311. package/dist/lib/wait-help.js +25 -0
  312. package/dist/lib/wait-help.js.map +1 -0
  313. package/dist/lib/wait-state.d.ts +57 -0
  314. package/dist/lib/wait-state.js +114 -0
  315. package/dist/lib/wait-state.js.map +1 -0
  316. package/dist/lib/wake-hook-settings.d.ts +57 -0
  317. package/dist/lib/wake-hook-settings.js +153 -0
  318. package/dist/lib/wake-hook-settings.js.map +1 -0
  319. package/dist/lib/wake-state.d.ts +65 -0
  320. package/dist/lib/wake-state.js +122 -0
  321. package/dist/lib/wake-state.js.map +1 -0
  322. package/package.json +5 -2
  323. package/skills/README.md +1 -1
  324. package/skills/agent-os/SKILL.md +8 -8
  325. package/skills/synap/SKILL.md +178 -88
  326. package/skills/synap/code-skills.md +84 -0
  327. package/skills/synap/concepts.md +38 -20
  328. package/skills/synap/creative-loop.md +1 -1
  329. package/skills/synap/document-embeds.md +17 -1
  330. package/skills/synap/focus-sessions.md +17 -8
  331. package/skills/synap/from-intent.md +33 -17
  332. package/skills/synap/governance-rules.md +3 -1
  333. package/skills/synap/lenses.md +4 -4
  334. package/skills/synap/linking.md +2 -2
  335. package/skills/synap/mental-model.md +1 -1
  336. package/skills/synap/operating-mode-rules.md +1 -1
  337. package/skills/synap/quick-reference.md +2 -1
  338. package/skills/synap/reflexes.md +8 -8
  339. package/skills/synap/viewframe-cells.md +1 -1
  340. package/skills/synap/work-model.md +24 -10
  341. package/skills/synap/workspace-design.md +5 -5
  342. package/skills/synap/writes.md +16 -9
  343. package/skills/synap/writing-titles.md +7 -0
  344. package/skills/synap-app/SKILL.md +148 -66
  345. package/skills/synap-app/creating-the-base-app.md +12 -7
  346. package/skills/synap-app/governance.md +27 -16
  347. package/skills/synap-app/install-commands.md +18 -9
  348. package/skills/synap-app/overview.md +16 -9
  349. package/skills/synap-app/using-the-sdk.md +75 -25
  350. package/skills/synap-market/SKILL.md +1 -1
  351. package/skills/synap-market/governance-and-catalog.md +1 -1
  352. package/skills/synap-schema/SKILL.md +24 -21
  353. package/skills/synap-schema/intent-vocabulary-ssot.md +24 -21
  354. package/templates/box/runner.py +206 -0
@@ -32,12 +32,14 @@ import { renderNextSteps, FLOW } from "../lib/next-steps.js";
32
32
  import { getStoredToken, isTokenLocallyExpired } from "../lib/auth.js";
33
33
  import prompts from "prompts";
34
34
  import { fetchPublicBrowseRows, fetchMyRows, fetchAvailableSlugs, fetchRetiredWorkspaceSlugs, fetchPackageDefinition, fetchPackageRecord, hydrateMineCategories, } from "../lib/cp-packages.js";
35
- import { fetchInstalledSlugs, fetchInstalledTemplates, fetchInstalledInventory, fetchInstalledInventoryStrict, installedRowsToTemplates, fetchWorkspaceAttachments, fetchWorkspaceAttachmentsStrict, verifyStampLanded, INSTALLED_KINDS } from "../lib/installed.js";
35
+ import { fetchInstalledSlugs, fetchInstalledTemplates, fetchInstalledInventory, installedRowsToTemplates, fetchWorkspaceAttachments, fetchWorkspaceAttachmentsStrict, verifyStampLanded, INSTALLED_KINDS } from "../lib/installed.js";
36
36
  import { isSuite } from "../lib/suite.js";
37
37
  import { TEMPLATE_STEP_LABELS, classifyTemplateStep, proposalsDoor, stepFromApplyState, templateStepGlyph, templateStepPhrase, } from "../lib/template-steps.js";
38
38
  import { capabilityAdd } from "./capability.js";
39
39
  import { bundledTemplatesVersion } from "../lib/bundle-version.js";
40
40
  import { HubNetworkError } from "../lib/hub-client.js";
41
+ import { checksFromStandings, fetchPackageStandings, StandingsUnavailableError, } from "../lib/package-updates.js";
42
+ import { podAdminOrigin } from "../lib/safe-open.js";
41
43
  import { parseDataChanges, dataChangesFromRefusal, consentNeedsPerson, dataChangeRefusalMessage, printDataChanges, parseAcceptList, decideConsent, consentRerunCommand, consentRefusalLines, lifecycleNotice, overlayNotice, overlayNeedsAttention, } from "../lib/template-lifecycle.js";
42
44
  // Same longer budget launch uses — an apply writes profiles/views/entities.
43
45
  const APPLY_TIMEOUT_MS = 120_000;
@@ -167,8 +169,8 @@ const KIND_HEADINGS = {
167
169
  // (`GET /installed`) calls the same thing `automation`. Both tokens reach
168
170
  // `kindHeading()` — `market --list` speaks CP, `market installed` speaks pod —
169
171
  // so both are mapped, to the ONE plural the registry says.
170
- workflow: "Rules",
171
- automation: "Rules",
172
+ workflow: "Automations",
173
+ automation: "Automations",
172
174
  view: "Views",
173
175
  cell: "Cards",
174
176
  workspace: "Spaces",
@@ -1260,6 +1262,14 @@ function stampVersion(pkg, slug, version) {
1260
1262
  const meta = pkg._meta ?? {};
1261
1263
  return { ...pkg, _meta: { ...meta, slug, ...(version ? { version } : {}) } };
1262
1264
  }
1265
+ /**
1266
+ * The slugs with an update that `synap market update <slug>` can apply (a
1267
+ * kind with a CLI updater). Next-step suggestions use it, so they never offer
1268
+ * a command that would only refuse.
1269
+ */
1270
+ export function cliUpdatableSlugs(checks) {
1271
+ return checks.filter((c) => c.updateAvailable && updateDoorFor(c.kind) !== null).map((c) => c.slug);
1272
+ }
1263
1273
  export function updateDoorFor(kind) {
1264
1274
  switch (kind ?? "workspace") {
1265
1275
  case "workspace":
@@ -1341,7 +1351,7 @@ export function dedupeBySlug(checks) {
1341
1351
  * pod's idempotent-create path, which reconciles when the pod build supports
1342
1352
  * it (see the `applyOnePackage` caveat below for what "created" means here).
1343
1353
  */
1344
- async function applyOnePackage(entry, cat, cfg, opts, applyTimeoutMs = APPLY_TIMEOUT_MS, extra = {}) {
1354
+ export async function applyOnePackage(entry, cat, cfg, opts, applyTimeoutMs = APPLY_TIMEOUT_MS, extra = {}) {
1345
1355
  if (cat.lockedSlugs.has(entry.slug)) {
1346
1356
  const tier = cat.tierBySlug.get(entry.slug)?.requiredTier;
1347
1357
  if (!opts.json)
@@ -1366,14 +1376,28 @@ async function applyOnePackage(entry, cat, cfg, opts, applyTimeoutMs = APPLY_TIM
1366
1376
  try {
1367
1377
  const res = (await hubPost("/packages/apply", pkg, cfg, applyTimeoutMs));
1368
1378
  s?.stop();
1379
+ // A key that may not apply a workspace package on its own (a computer
1380
+ // key's grant leaves out `workspace.update`) files the update for the
1381
+ // person's approval: 202 `{status:"proposed", proposalId, reviewUrl}`.
1382
+ // Waiting, never failed — it applies when the person approves it.
1369
1383
  if (writeGovernance(res) === "proposed") {
1370
1384
  const proposalId = res.proposalId ? String(res.proposalId) : undefined;
1385
+ const reviewUrl = approvalLink(cfg.podUrl, proposalId, res.reviewUrl);
1371
1386
  if (!opts.json) {
1372
- log.info(`${entry.name} — update proposed (under review, not live yet).`);
1373
- if (proposalId)
1374
- log.hint(`Review and approve: synap open proposal ${proposalId}`);
1387
+ log.info(`${entry.name} — update filed for your approval (not applied yet).`);
1388
+ if (reviewUrl)
1389
+ log.hint(`Approve it: ${reviewUrl}`);
1390
+ else if (proposalId)
1391
+ log.hint(`Approve it: synap open proposal ${proposalId}`);
1375
1392
  }
1376
- return { slug: entry.slug, outcome: "proposed", status: "proposed", warnings: [] };
1393
+ return {
1394
+ slug: entry.slug,
1395
+ outcome: "proposed",
1396
+ status: "proposed",
1397
+ warnings: [],
1398
+ ...(proposalId ? { proposalId } : {}),
1399
+ ...(reviewUrl ? { reviewUrl } : {}),
1400
+ };
1377
1401
  }
1378
1402
  const ws = res.workspace;
1379
1403
  const dependencies = res.dependencies;
@@ -1431,7 +1455,7 @@ async function applyOnePackage(entry, cat, cfg, opts, applyTimeoutMs = APPLY_TIM
1431
1455
  if (refusal)
1432
1456
  log.warn(refusal);
1433
1457
  else
1434
- renderHubError(e);
1458
+ renderHubError(e, { personDoor: marketUpdatesDoor(cfg.podUrl) });
1435
1459
  }
1436
1460
  return {
1437
1461
  slug: entry.slug,
@@ -1442,6 +1466,29 @@ async function applyOnePackage(entry, cat, cfg, opts, applyTimeoutMs = APPLY_TIM
1442
1466
  };
1443
1467
  }
1444
1468
  }
1469
+ /**
1470
+ * Where the person approves a filed update: pod admin's proposal page, the
1471
+ * approval door (`/proposal/<id>`), when the pod-admin origin derives from the
1472
+ * pod's; else the link the pod sent (`reviewUrl`); else nothing.
1473
+ */
1474
+ export function approvalLink(podUrl, proposalId, reviewUrl) {
1475
+ const admin = podAdminOrigin(podUrl);
1476
+ if (admin && proposalId)
1477
+ return `${admin}/proposal/${encodeURIComponent(proposalId)}`;
1478
+ return typeof reviewUrl === "string" && reviewUrl.length > 0 ? reviewUrl : undefined;
1479
+ }
1480
+ /**
1481
+ * Where the person applies a package update a limited key may not apply
1482
+ * (a computer key's grant leaves out `workspace.update`, by design: applying a
1483
+ * workspace package is the person's act). Pod admin's Marketplace, Updates
1484
+ * tab, named by URL when the pod-admin origin derives from the pod's.
1485
+ */
1486
+ export function marketUpdatesDoor(podUrl) {
1487
+ const admin = podAdminOrigin(podUrl);
1488
+ return admin
1489
+ ? `Apply it yourself from pod admin → Marketplace → Updates: ${admin}/marketplace/updates`
1490
+ : "Apply it yourself from pod admin → Marketplace → Updates.";
1491
+ }
1445
1492
  /**
1446
1493
  * Ask the pod's write-free preview door (`POST /packages/preflight`, the same
1447
1494
  * body `/packages/apply` takes) which data changes an update would run.
@@ -1509,26 +1556,28 @@ async function reconcileOutcome(c, report, opts) {
1509
1556
  }
1510
1557
  export async function marketUpdate(slugsArg, opts) {
1511
1558
  const applyTimeoutMs = parseApplyTimeoutMs(opts.timeout);
1512
- // STRICT fetch: distinguish "pod unreachable" (transient — don't claim the
1513
- // pod is empty, that reads as data loss) from "genuinely nothing installed".
1514
1559
  const cat = await buildMarketCatalog();
1515
- let installedTemplates;
1516
- // Whether the pod answered from the ONE read door (`GET /installed`, all six
1517
- // kinds) or is old enough that only workspace packages were visible. An old
1518
- // pod is not an empty pod — say which, rather than letting a narrower list
1519
- // read as the whole truth.
1520
- let degraded = false;
1560
+ // THE POD'S ANSWER, never the CLI's: which installed package has an update
1561
+ // is derived once on the pod, for every kind, with one rule (Hub
1562
+ // `GET /package-updates` → `installed[]`), and pod admin's Updates tab reads
1563
+ // the same list. A pod that cannot answer is said out loud, never replaced
1564
+ // by a verdict computed here (that fork is how the CLI said "content
1565
+ // changed" while pod admin said nothing, 2 Nov 2026).
1566
+ let standings;
1521
1567
  try {
1522
- const inv = await fetchInstalledInventoryStrict();
1523
- installedTemplates = installedRowsToTemplates(inv.rows);
1524
- degraded = inv.degraded;
1568
+ standings = await fetchPackageStandings(await resolveHubConfig(opts));
1525
1569
  }
1526
1570
  catch (e) {
1527
1571
  // Unreachable ≠ success — a script checking `$?` (or `&&`-chaining) must see
1528
1572
  // failure, not exit 0, even though the JSON payload also carries the reason.
1529
1573
  process.exitCode = 1;
1574
+ const unavailable = e instanceof StandingsUnavailableError ? e.reason : null;
1530
1575
  if (opts.json) {
1531
- console.log(JSON.stringify({ checks: [], loggedIn: cat.loggedIn, error: "pod-unreachable" }, null, 2));
1576
+ console.log(JSON.stringify({ checks: [], loggedIn: cat.loggedIn, error: unavailable ?? "pod-unreachable" }, null, 2));
1577
+ return;
1578
+ }
1579
+ if (e instanceof StandingsUnavailableError) {
1580
+ log.error(e.message);
1532
1581
  return;
1533
1582
  }
1534
1583
  log.error("Couldn't reach your pod to read what's installed — not saying it's empty.");
@@ -1536,26 +1585,21 @@ export async function marketUpdate(slugsArg, opts) {
1536
1585
  log.hint("Check the pod is up / you're on the right --pod, then retry.");
1537
1586
  return;
1538
1587
  }
1539
- const degradedNote = degraded
1540
- ? "This pod does not serve GET /api/hub/installed — only workspace packages were checked. Capability / view / skill / automation / card installs were NOT (upgrade the pod to include them)."
1541
- : undefined;
1542
- if (installedTemplates.length === 0) {
1588
+ // Kept in the JSON for readers of the older shape: the pod's list covers
1589
+ // every kind, so it is never the workspace-only view of an old pod.
1590
+ const degraded = false;
1591
+ if (standings.length === 0) {
1543
1592
  if (opts.json) {
1544
- console.log(JSON.stringify({ checks: [], loggedIn: cat.loggedIn, degraded, ...(degradedNote ? { degradedNote } : {}) }, null, 2));
1593
+ console.log(JSON.stringify({ checks: [], loggedIn: cat.loggedIn, degraded }, null, 2));
1545
1594
  return;
1546
1595
  }
1547
1596
  log.warn("No installed packages found on this pod.");
1548
- if (degradedNote)
1549
- log.dim(degradedNote);
1550
1597
  log.hint("Install one: synap market install <slug>");
1551
1598
  return;
1552
1599
  }
1553
- // ONE ROW PER SLUG. `GET /installed` reports one row per installed OBJECT —
1554
- // a views pack that installed four views is four rows — and an update is
1555
- // applied per PACKAGE, not per object. Without this the preview listed
1556
- // `task-views-pack` four times and the "N up to date" tally counted it four
1557
- // times. `market installed` has always deduped the same way.
1558
- let checks = dedupeBySlug(computeUpdates(installedTemplates, cat));
1600
+ // One check per slug: the pod answers per package (slug + kind); a slug
1601
+ // installed as two kinds is updated per kind by its own door, but listed once.
1602
+ let checks = dedupeBySlug(checksFromStandings(standings));
1559
1603
  const entryBySlug = new Map(cat.entries.map((e) => [e.slug, e]));
1560
1604
  const explicitSlugs = !!slugsArg && slugsArg.length > 0;
1561
1605
  let unknownSlugs = [];
@@ -1679,8 +1723,6 @@ export async function marketUpdate(slugsArg, opts) {
1679
1723
  if (noVersionInfo.length > 0) {
1680
1724
  log.dim(`${noVersionInfo.length} installed without a version stamp — can't check ${noVersionInfo.length === 1 ? "it" : "them"} for updates.`);
1681
1725
  }
1682
- if (degradedNote)
1683
- log.dim(degradedNote);
1684
1726
  }
1685
1727
  // What the JSON carries for the new facts: per slug, the pod's data changes
1686
1728
  // (`null` = this pod sent none: an older pod) and the template lifecycle.
@@ -1722,7 +1764,10 @@ export async function marketUpdate(slugsArg, opts) {
1722
1764
  return;
1723
1765
  }
1724
1766
  if (!shouldApply) {
1725
- const steps = FLOW.afterMarketUpdateCheck(withUpdates.map((c) => c.slug));
1767
+ // Next steps offer only what this command can run: a capability update
1768
+ // (no CLI updater) is the person's act in pod admin, named once below.
1769
+ const steps = FLOW.afterMarketUpdateCheck(cliUpdatableSlugs(withUpdates));
1770
+ const personApplies = withUpdates.filter((c) => updateDoorFor(c.kind) === null).map((c) => c.slug);
1726
1771
  if (opts.json) {
1727
1772
  console.log(JSON.stringify({
1728
1773
  checks,
@@ -1730,6 +1775,9 @@ export async function marketUpdate(slugsArg, opts) {
1730
1775
  unknownSlugs,
1731
1776
  applied: [],
1732
1777
  nextSteps: steps,
1778
+ ...(personApplies.length > 0
1779
+ ? { appliedInPodAdmin: { slugs: personApplies, where: marketUpdatesDoor(cfg.podUrl) } }
1780
+ : {}),
1733
1781
  dataChanges: dataChangesJson,
1734
1782
  templateLifecycle: lifecycleJson,
1735
1783
  }, null, 2));
@@ -1739,6 +1787,9 @@ export async function marketUpdate(slugsArg, opts) {
1739
1787
  if ([...previews.values()].some((pv) => (pv.changes?.length ?? 0) > 0)) {
1740
1788
  log.hint("Updates with data changes ask before they run. To agree up front: --accept-data-changes <opKey,…> (or --yes for all listed)");
1741
1789
  }
1790
+ if (personApplies.length > 0) {
1791
+ log.hint(`${personApplies.join(", ")}: not updated by this command. ${marketUpdatesDoor(cfg.podUrl)}`);
1792
+ }
1742
1793
  renderNextSteps(steps);
1743
1794
  return;
1744
1795
  }
@@ -1750,8 +1801,13 @@ export async function marketUpdate(slugsArg, opts) {
1750
1801
  for (const c of withUpdates) {
1751
1802
  const door = updateDoorFor(c.kind);
1752
1803
  if (door === null) {
1753
- if (!opts.json)
1754
- log.warn(`${c.slug} is a ${c.kind} — the pod has no per-package update for this kind, so it was not updated. Nothing was written.`);
1804
+ if (!opts.json) {
1805
+ // A capability update is a person's act on pod admin (the pod refuses
1806
+ // an agent key there); any other kind here has no updater at all.
1807
+ log.warn(c.kind === "capability"
1808
+ ? `${c.slug} is a capability — it was not updated here. Nothing was written. ${marketUpdatesDoor(cfg.podUrl)}`
1809
+ : `${c.slug} is a ${c.kind} — the pod has no per-package update for this kind, so it was not updated. Nothing was written.`);
1810
+ }
1755
1811
  results.push({ slug: c.slug, outcome: "no-updater", status: "no-updater", warnings: [] });
1756
1812
  continue;
1757
1813
  }
@@ -1834,9 +1890,11 @@ export async function marketUpdate(slugsArg, opts) {
1834
1890
  * already-current, the `*-with-failures` and `"stamp-contradiction"` statuses
1835
1891
  * get their OWN bucket — a partial capability-seed failure or a stamp that
1836
1892
  * silently didn't take is never folded into a clean "updated" count.
1837
- * `"timed-out"` is broken out from the generic `"failed"` bucket; everything
1838
- * else (locked/proposed/fetch-failed/not-in-catalog/no-workspace/unknown)
1839
- * rolls into "failed".
1893
+ * `"timed-out"` is broken out from the generic `"failed"` bucket;
1894
+ * `"proposed"`/`"awaiting-approval"` count as waiting for the person's
1895
+ * approval (never failed); everything else
1896
+ * (locked/fetch-failed/not-in-catalog/no-workspace/unknown) rolls into
1897
+ * "failed".
1840
1898
  */
1841
1899
  export function summarizeApplyResults(results) {
1842
1900
  let updated = 0;
@@ -1886,7 +1944,7 @@ export function summarizeApplyResults(results) {
1886
1944
  }
1887
1945
  const parts = [`${updated} updated`, `${unchanged} already current`];
1888
1946
  if (proposed > 0)
1889
- parts.push(`${proposed} proposed (awaiting review)`);
1947
+ parts.push(`${proposed} waiting for your approval`);
1890
1948
  // The vocabulary's `unfinished` ("Not finished"): one state, one name on
1891
1949
  // every surface — never "completed with failures" (review2 UX §1 #2).
1892
1950
  if (withFailures > 0)
@@ -1899,7 +1957,7 @@ export function summarizeApplyResults(results) {
1899
1957
  parts.push(`${needsConsent} waiting for your agreement to data changes`);
1900
1958
  const clean = withFailures === 0 && failed === 0 && timedOut === 0 && needsConsent === 0;
1901
1959
  // Proposed isn't a failure (never ⚠) but isn't live yet (not a bare ✓) —
1902
- // a distinct "→ awaiting review" marker keeps the summary honest.
1960
+ // a distinct "→ waiting for your approval" marker keeps the summary honest.
1903
1961
  const marker = !clean ? "⚠" : proposed > 0 ? "→" : "✓";
1904
1962
  const color = !clean ? chalk.yellow : proposed > 0 ? chalk.cyan : chalk.green;
1905
1963
  return {
@@ -2389,7 +2447,7 @@ export async function marketInstalled(opts) {
2389
2447
  const entryBySlug = new Map(cat.entries.map((e) => [e.slug, e]));
2390
2448
  if (opts.layers) {
2391
2449
  const graph = await buildInstallationGraph(installedTemplates, cat, checks);
2392
- const steps = FLOW.afterMarketInstalledCheck(rows.filter((c) => c.updateAvailable).map((c) => c.slug));
2450
+ const steps = FLOW.afterMarketInstalledCheck(cliUpdatableSlugs(rows));
2393
2451
  if (opts.json) {
2394
2452
  console.log(JSON.stringify({
2395
2453
  nodes: [...graph.nodes.values()],
@@ -2416,7 +2474,7 @@ export async function marketInstalled(opts) {
2416
2474
  }
2417
2475
  if (opts.tree) {
2418
2476
  const { packages, leafRows } = await buildCompositionTrees(rows, cat, installedTemplates, workspaceCountBySlug);
2419
- const steps = FLOW.afterMarketInstalledCheck(rows.filter((c) => c.updateAvailable).map((c) => c.slug));
2477
+ const steps = FLOW.afterMarketInstalledCheck(cliUpdatableSlugs(rows));
2420
2478
  if (opts.json) {
2421
2479
  console.log(JSON.stringify({
2422
2480
  packages,
@@ -2476,7 +2534,7 @@ export async function marketInstalled(opts) {
2476
2534
  return;
2477
2535
  }
2478
2536
  if (opts.json) {
2479
- const steps = FLOW.afterMarketInstalledCheck(rows.filter((c) => c.updateAvailable).map((c) => c.slug));
2537
+ const steps = FLOW.afterMarketInstalledCheck(cliUpdatableSlugs(rows));
2480
2538
  console.log(JSON.stringify({
2481
2539
  rows: rows.map((c) => {
2482
2540
  const entry = entryBySlug.get(c.slug);
@@ -2594,7 +2652,7 @@ export async function marketInstalled(opts) {
2594
2652
  log.dim(degradedNote);
2595
2653
  if (!cat.loggedIn)
2596
2654
  log.dim("Not logged in — private template updates aren't visible. Run: synap login");
2597
- renderNextSteps(FLOW.afterMarketInstalledCheck(rows.filter((c) => c.updateAvailable).map((c) => c.slug)));
2655
+ renderNextSteps(FLOW.afterMarketInstalledCheck(cliUpdatableSlugs(rows)));
2598
2656
  }
2599
2657
  /** Classify one workspace's attachment, reusing `computeUpdates`' drift verdict for the stamped case. */
2600
2658
  function classifyAttachment(ws, check) {