@synap-core/cli 1.11.0 → 1.12.2

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 (452) hide show
  1. package/README.md +23 -198
  2. package/dist/build-info.json +6 -0
  3. package/dist/commands/agent-run.js +3 -2
  4. package/dist/commands/agent-run.js.map +1 -1
  5. package/dist/commands/agents.d.ts +33 -17
  6. package/dist/commands/agents.js +203 -237
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/app.d.ts +143 -0
  9. package/dist/commands/app.js +523 -0
  10. package/dist/commands/app.js.map +1 -0
  11. package/dist/commands/automate.d.ts +21 -0
  12. package/dist/commands/automate.js +42 -0
  13. package/dist/commands/automate.js.map +1 -0
  14. package/dist/commands/automation-schema.test.d.ts +16 -0
  15. package/dist/commands/automation-schema.test.js +77 -0
  16. package/dist/commands/automation-schema.test.js.map +1 -0
  17. package/dist/commands/automation.d.ts +12 -0
  18. package/dist/commands/automation.js +80 -35
  19. package/dist/commands/automation.js.map +1 -1
  20. package/dist/commands/bridge-setup.d.ts +14 -1
  21. package/dist/commands/bridge-setup.js +392 -128
  22. package/dist/commands/bridge-setup.js.map +1 -1
  23. package/dist/commands/cap-connections.d.ts +4 -4
  24. package/dist/commands/cap-connections.js +14 -14
  25. package/dist/commands/cap-connections.js.map +1 -1
  26. package/dist/commands/capability.d.ts +2 -0
  27. package/dist/commands/capability.js +218 -168
  28. package/dist/commands/capability.js.map +1 -1
  29. package/dist/commands/catalog.d.ts +275 -0
  30. package/dist/commands/catalog.js +481 -0
  31. package/dist/commands/catalog.js.map +1 -0
  32. package/dist/commands/cell.d.ts +155 -8
  33. package/dist/commands/cell.js +416 -40
  34. package/dist/commands/cell.js.map +1 -1
  35. package/dist/commands/centrality.js +1 -13
  36. package/dist/commands/centrality.js.map +1 -1
  37. package/dist/commands/connect.d.ts +38 -13
  38. package/dist/commands/connect.js +68 -167
  39. package/dist/commands/connect.js.map +1 -1
  40. package/dist/commands/connections.d.ts +3 -2
  41. package/dist/commands/connections.js +95 -25
  42. package/dist/commands/connections.js.map +1 -1
  43. package/dist/commands/context.js +7 -1
  44. package/dist/commands/context.js.map +1 -1
  45. package/dist/commands/data-extra.d.ts +34 -0
  46. package/dist/commands/data-extra.js +193 -23
  47. package/dist/commands/data-extra.js.map +1 -1
  48. package/dist/commands/data.d.ts +120 -2
  49. package/dist/commands/data.js +293 -20
  50. package/dist/commands/data.js.map +1 -1
  51. package/dist/commands/diagnose.d.ts +66 -4
  52. package/dist/commands/diagnose.js +285 -28
  53. package/dist/commands/diagnose.js.map +1 -1
  54. package/dist/commands/doc.d.ts +11 -4
  55. package/dist/commands/doc.js +39 -14
  56. package/dist/commands/doc.js.map +1 -1
  57. package/dist/commands/doctor.d.ts +112 -3
  58. package/dist/commands/doctor.js +657 -32
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/explain.js +5 -5
  61. package/dist/commands/explain.js.map +1 -1
  62. package/dist/commands/import.d.ts +368 -13
  63. package/dist/commands/import.js +1064 -54
  64. package/dist/commands/import.js.map +1 -1
  65. package/dist/commands/init.d.ts +20 -9
  66. package/dist/commands/init.js +433 -973
  67. package/dist/commands/init.js.map +1 -1
  68. package/dist/commands/keys.d.ts +1 -0
  69. package/dist/commands/keys.js +15 -2
  70. package/dist/commands/keys.js.map +1 -1
  71. package/dist/commands/knowledge.d.ts +22 -6
  72. package/dist/commands/knowledge.js +117 -55
  73. package/dist/commands/knowledge.js.map +1 -1
  74. package/dist/commands/lens.d.ts +37 -1
  75. package/dist/commands/lens.js +192 -71
  76. package/dist/commands/lens.js.map +1 -1
  77. package/dist/commands/market-authoring.d.ts +29 -2
  78. package/dist/commands/market-authoring.js +348 -7
  79. package/dist/commands/market-authoring.js.map +1 -1
  80. package/dist/commands/market-official.d.ts +58 -0
  81. package/dist/commands/market-official.js +84 -0
  82. package/dist/commands/market-official.js.map +1 -0
  83. package/dist/commands/market.d.ts +400 -16
  84. package/dist/commands/market.js +1802 -146
  85. package/dist/commands/market.js.map +1 -1
  86. package/dist/commands/mcp.d.ts +60 -25
  87. package/dist/commands/mcp.js +251 -64
  88. package/dist/commands/mcp.js.map +1 -1
  89. package/dist/commands/open.d.ts +39 -9
  90. package/dist/commands/open.js +80 -25
  91. package/dist/commands/open.js.map +1 -1
  92. package/dist/commands/playbook.d.ts +42 -0
  93. package/dist/commands/playbook.js +162 -0
  94. package/dist/commands/playbook.js.map +1 -0
  95. package/dist/commands/pod.js +1 -1
  96. package/dist/commands/pod.js.map +1 -1
  97. package/dist/commands/pods.d.ts +5 -0
  98. package/dist/commands/pods.js +97 -116
  99. package/dist/commands/pods.js.map +1 -1
  100. package/dist/commands/proposals-actions.d.ts +62 -0
  101. package/dist/commands/proposals-actions.js +143 -8
  102. package/dist/commands/proposals-actions.js.map +1 -1
  103. package/dist/commands/proposals-await.d.ts +68 -0
  104. package/dist/commands/proposals-await.js +248 -0
  105. package/dist/commands/proposals-await.js.map +1 -0
  106. package/dist/commands/proton-setup.d.ts +73 -0
  107. package/dist/commands/proton-setup.js +577 -0
  108. package/dist/commands/proton-setup.js.map +1 -0
  109. package/dist/commands/providers.d.ts +23 -0
  110. package/dist/commands/providers.js +126 -1
  111. package/dist/commands/providers.js.map +1 -1
  112. package/dist/commands/raycast.js +6 -2
  113. package/dist/commands/raycast.js.map +1 -1
  114. package/dist/commands/rule.d.ts +150 -0
  115. package/dist/commands/rule.js +447 -0
  116. package/dist/commands/rule.js.map +1 -0
  117. package/dist/commands/session-wait.d.ts +111 -0
  118. package/dist/commands/session-wait.js +209 -0
  119. package/dist/commands/session-wait.js.map +1 -0
  120. package/dist/commands/sessions.d.ts +52 -0
  121. package/dist/commands/sessions.js +478 -58
  122. package/dist/commands/sessions.js.map +1 -1
  123. package/dist/commands/skill-manage.d.ts +21 -0
  124. package/dist/commands/skill-manage.js +136 -19
  125. package/dist/commands/skill-manage.js.map +1 -1
  126. package/dist/commands/skills.js +16 -0
  127. package/dist/commands/skills.js.map +1 -1
  128. package/dist/commands/status.d.ts +1 -4
  129. package/dist/commands/status.js +5 -34
  130. package/dist/commands/status.js.map +1 -1
  131. package/dist/commands/statusline.backoff.test.d.ts +13 -0
  132. package/dist/commands/statusline.backoff.test.js +100 -0
  133. package/dist/commands/statusline.backoff.test.js.map +1 -0
  134. package/dist/commands/statusline.js +16 -9
  135. package/dist/commands/statusline.js.map +1 -1
  136. package/dist/commands/sync-status.d.ts +12 -0
  137. package/dist/commands/sync-status.js +125 -0
  138. package/dist/commands/sync-status.js.map +1 -0
  139. package/dist/commands/templates-retire.d.ts +34 -0
  140. package/dist/commands/templates-retire.js +192 -0
  141. package/dist/commands/templates-retire.js.map +1 -0
  142. package/dist/commands/tools.js +6 -21
  143. package/dist/commands/tools.js.map +1 -1
  144. package/dist/commands/tracks.d.ts +51 -0
  145. package/dist/commands/tracks.js +291 -0
  146. package/dist/commands/tracks.js.map +1 -0
  147. package/dist/commands/update.d.ts +3 -11
  148. package/dist/commands/update.js +5 -134
  149. package/dist/commands/update.js.map +1 -1
  150. package/dist/commands/upload.d.ts +41 -3
  151. package/dist/commands/upload.js +120 -18
  152. package/dist/commands/upload.js.map +1 -1
  153. package/dist/commands/vendor.d.ts +28 -0
  154. package/dist/commands/vendor.js +110 -0
  155. package/dist/commands/vendor.js.map +1 -0
  156. package/dist/commands/versions.js +6 -0
  157. package/dist/commands/versions.js.map +1 -1
  158. package/dist/commands/view.js +10 -5
  159. package/dist/commands/view.js.map +1 -1
  160. package/dist/commands/whoami.d.ts +23 -3
  161. package/dist/commands/whoami.js +169 -23
  162. package/dist/commands/whoami.js.map +1 -1
  163. package/dist/commands/worker.d.ts +122 -0
  164. package/dist/commands/worker.js +435 -0
  165. package/dist/commands/worker.js.map +1 -0
  166. package/dist/commands/worker.test.d.ts +1 -0
  167. package/dist/commands/worker.test.js +116 -0
  168. package/dist/commands/worker.test.js.map +1 -0
  169. package/dist/commands/workspace-ops.d.ts +35 -0
  170. package/dist/commands/workspace-ops.js +153 -0
  171. package/dist/commands/workspace-ops.js.map +1 -0
  172. package/dist/index.d.ts +6 -6
  173. package/dist/index.js +900 -180
  174. package/dist/index.js.map +1 -1
  175. package/dist/lib/agent-connections.d.ts +31 -0
  176. package/dist/lib/agent-connections.js +33 -0
  177. package/dist/lib/agent-connections.js.map +1 -0
  178. package/dist/lib/agent-detect.d.ts +27 -0
  179. package/dist/lib/agent-detect.js +71 -0
  180. package/dist/lib/agent-detect.js.map +1 -0
  181. package/dist/lib/agent-door.d.ts +138 -0
  182. package/dist/lib/agent-door.js +426 -0
  183. package/dist/lib/agent-door.js.map +1 -0
  184. package/dist/lib/agents-config.d.ts +2 -0
  185. package/dist/lib/agents-config.js +4 -9
  186. package/dist/lib/agents-config.js.map +1 -1
  187. package/dist/lib/approval-poll.d.ts +31 -2
  188. package/dist/lib/approval-poll.js +20 -7
  189. package/dist/lib/approval-poll.js.map +1 -1
  190. package/dist/lib/atomic-file.d.ts +48 -0
  191. package/dist/lib/atomic-file.js +129 -0
  192. package/dist/lib/atomic-file.js.map +1 -0
  193. package/dist/lib/auth.d.ts +14 -9
  194. package/dist/lib/auth.js +44 -61
  195. package/dist/lib/auth.js.map +1 -1
  196. package/dist/lib/batch-approval.d.ts +85 -0
  197. package/dist/lib/batch-approval.js +170 -0
  198. package/dist/lib/batch-approval.js.map +1 -0
  199. package/dist/lib/capture-lane.d.ts +6 -5
  200. package/dist/lib/capture-lane.js +6 -5
  201. package/dist/lib/capture-lane.js.map +1 -1
  202. package/dist/lib/capture-structure.d.ts +230 -11
  203. package/dist/lib/capture-structure.js +251 -13
  204. package/dist/lib/capture-structure.js.map +1 -1
  205. package/dist/lib/catalog-templates.d.ts +59 -0
  206. package/dist/lib/catalog-templates.js +126 -0
  207. package/dist/lib/catalog-templates.js.map +1 -0
  208. package/dist/lib/cli-build.d.ts +19 -0
  209. package/dist/lib/cli-build.js +37 -0
  210. package/dist/lib/cli-build.js.map +1 -0
  211. package/dist/lib/conversation-headers.d.ts +18 -0
  212. package/dist/lib/conversation-headers.js +32 -0
  213. package/dist/lib/conversation-headers.js.map +1 -0
  214. package/dist/lib/cp-packages.d.ts +167 -11
  215. package/dist/lib/cp-packages.js +253 -21
  216. package/dist/lib/cp-packages.js.map +1 -1
  217. package/dist/lib/credential-class.d.ts +117 -0
  218. package/dist/lib/credential-class.js +116 -0
  219. package/dist/lib/credential-class.js.map +1 -0
  220. package/dist/lib/describe-lens.d.ts +35 -0
  221. package/dist/lib/describe-lens.js +40 -0
  222. package/dist/lib/describe-lens.js.map +1 -1
  223. package/dist/lib/device-connect.d.ts +125 -0
  224. package/dist/lib/device-connect.js +256 -0
  225. package/dist/lib/device-connect.js.map +1 -0
  226. package/dist/lib/directory-lens.d.ts +99 -0
  227. package/dist/lib/directory-lens.js +187 -0
  228. package/dist/lib/directory-lens.js.map +1 -0
  229. package/dist/lib/exporter-coverage.d.ts +71 -0
  230. package/dist/lib/exporter-coverage.js +97 -0
  231. package/dist/lib/exporter-coverage.js.map +1 -0
  232. package/dist/lib/hub-client.d.ts +29 -8
  233. package/dist/lib/hub-client.js +328 -55
  234. package/dist/lib/hub-client.js.map +1 -1
  235. package/dist/lib/init-connect.d.ts +41 -0
  236. package/dist/lib/init-connect.js +75 -0
  237. package/dist/lib/init-connect.js.map +1 -0
  238. package/dist/lib/init-exit.d.ts +24 -0
  239. package/dist/lib/init-exit.js +41 -0
  240. package/dist/lib/init-exit.js.map +1 -0
  241. package/dist/lib/init-flow.d.ts +25 -0
  242. package/dist/lib/init-flow.js +40 -0
  243. package/dist/lib/init-flow.js.map +1 -0
  244. package/dist/lib/init-handoff.d.ts +16 -0
  245. package/dist/lib/init-handoff.js +19 -0
  246. package/dist/lib/init-handoff.js.map +1 -0
  247. package/dist/lib/init-output.d.ts +18 -0
  248. package/dist/lib/init-output.js +43 -0
  249. package/dist/lib/init-output.js.map +1 -0
  250. package/dist/lib/init-pod.d.ts +45 -0
  251. package/dist/lib/init-pod.js +36 -0
  252. package/dist/lib/init-pod.js.map +1 -0
  253. package/dist/lib/installed.d.ts +210 -11
  254. package/dist/lib/installed.js +234 -36
  255. package/dist/lib/installed.js.map +1 -1
  256. package/dist/lib/key-approval.d.ts +57 -0
  257. package/dist/lib/key-approval.js +117 -0
  258. package/dist/lib/key-approval.js.map +1 -0
  259. package/dist/lib/key-diagnosis.d.ts +56 -0
  260. package/dist/lib/key-diagnosis.js +227 -0
  261. package/dist/lib/key-diagnosis.js.map +1 -0
  262. package/dist/lib/key-doctor.d.ts +136 -0
  263. package/dist/lib/key-doctor.js +286 -0
  264. package/dist/lib/key-doctor.js.map +1 -0
  265. package/dist/lib/key-locations.d.ts +120 -0
  266. package/dist/lib/key-locations.js +326 -0
  267. package/dist/lib/key-locations.js.map +1 -0
  268. package/dist/lib/key-source.d.ts +66 -0
  269. package/dist/lib/key-source.js +106 -0
  270. package/dist/lib/key-source.js.map +1 -0
  271. package/dist/lib/key-state.d.ts +70 -0
  272. package/dist/lib/key-state.js +115 -0
  273. package/dist/lib/key-state.js.map +1 -0
  274. package/dist/lib/kind-package.d.ts +181 -0
  275. package/dist/lib/kind-package.js +679 -0
  276. package/dist/lib/kind-package.js.map +1 -0
  277. package/dist/lib/knowledge-title.d.ts +24 -0
  278. package/dist/lib/knowledge-title.js +46 -0
  279. package/dist/lib/knowledge-title.js.map +1 -0
  280. package/dist/lib/knowledge-title.test.d.ts +1 -0
  281. package/dist/lib/knowledge-title.test.js +34 -0
  282. package/dist/lib/knowledge-title.test.js.map +1 -0
  283. package/dist/lib/machine-instance.d.ts +64 -0
  284. package/dist/lib/machine-instance.js +142 -0
  285. package/dist/lib/machine-instance.js.map +1 -0
  286. package/dist/lib/mcp-bridge.d.ts +42 -0
  287. package/dist/lib/mcp-bridge.js +147 -0
  288. package/dist/lib/mcp-bridge.js.map +1 -0
  289. package/dist/lib/mcp-bridge.test.d.ts +1 -0
  290. package/dist/lib/mcp-bridge.test.js +90 -0
  291. package/dist/lib/mcp-bridge.test.js.map +1 -0
  292. package/dist/lib/mcp-call.d.ts +30 -0
  293. package/dist/lib/mcp-call.js +107 -0
  294. package/dist/lib/mcp-call.js.map +1 -0
  295. package/dist/lib/mcp-snippets.d.ts +53 -0
  296. package/dist/lib/mcp-snippets.js +82 -0
  297. package/dist/lib/mcp-snippets.js.map +1 -0
  298. package/dist/lib/next-steps.d.ts +8 -0
  299. package/dist/lib/next-steps.js +31 -1
  300. package/dist/lib/next-steps.js.map +1 -1
  301. package/dist/lib/package-wire.d.ts +179 -0
  302. package/dist/lib/package-wire.js +68 -0
  303. package/dist/lib/package-wire.js.map +1 -0
  304. package/dist/lib/pair-link.d.ts +38 -0
  305. package/dist/lib/pair-link.js +68 -0
  306. package/dist/lib/pair-link.js.map +1 -0
  307. package/dist/lib/pod-wide.d.ts +40 -0
  308. package/dist/lib/pod-wide.js +46 -0
  309. package/dist/lib/pod-wide.js.map +1 -0
  310. package/dist/lib/pod.d.ts +66 -112
  311. package/dist/lib/pod.js +134 -412
  312. package/dist/lib/pod.js.map +1 -1
  313. package/dist/lib/project-ref.d.ts +9 -3
  314. package/dist/lib/project-ref.js +10 -4
  315. package/dist/lib/project-ref.js.map +1 -1
  316. package/dist/lib/review-credential.d.ts +119 -0
  317. package/dist/lib/review-credential.js +147 -0
  318. package/dist/lib/review-credential.js.map +1 -0
  319. package/dist/lib/safe-open.d.ts +49 -0
  320. package/dist/lib/safe-open.js +119 -0
  321. package/dist/lib/safe-open.js.map +1 -0
  322. package/dist/lib/session-lens.d.ts +40 -1
  323. package/dist/lib/session-lens.js +54 -4
  324. package/dist/lib/session-lens.js.map +1 -1
  325. package/dist/lib/superwhisper-import.d.ts +8 -0
  326. package/dist/lib/superwhisper-import.js +14 -7
  327. package/dist/lib/superwhisper-import.js.map +1 -1
  328. package/dist/lib/superwhisper-title.test.d.ts +1 -0
  329. package/dist/lib/superwhisper-title.test.js +18 -0
  330. package/dist/lib/superwhisper-title.test.js.map +1 -0
  331. package/dist/lib/targets.d.ts +134 -10
  332. package/dist/lib/targets.js +962 -258
  333. package/dist/lib/targets.js.map +1 -1
  334. package/dist/lib/template-file.d.ts +4 -0
  335. package/dist/lib/template-file.js.map +1 -1
  336. package/dist/lib/template-lifecycle.d.ts +217 -0
  337. package/dist/lib/template-lifecycle.js +433 -0
  338. package/dist/lib/template-lifecycle.js.map +1 -0
  339. package/dist/lib/template-steps.d.ts +88 -0
  340. package/dist/lib/template-steps.js +118 -0
  341. package/dist/lib/template-steps.js.map +1 -0
  342. package/dist/lib/time-ago.d.ts +2 -0
  343. package/dist/lib/time-ago.js +15 -0
  344. package/dist/lib/time-ago.js.map +1 -0
  345. package/dist/utils/logger.js +5 -2
  346. package/dist/utils/logger.js.map +1 -1
  347. package/package.json +23 -17
  348. package/skills/README.md +12 -10
  349. package/skills/agent-os/SKILL.md +214 -99
  350. package/skills/manifest.json +1 -1
  351. package/skills/onboard/SKILL.md +55 -26
  352. package/skills/synap/README.md +5 -8
  353. package/skills/synap/SKILL.md +1086 -283
  354. package/skills/synap/_order.txt +7 -0
  355. package/skills/synap/_skill.yaml +1 -1
  356. package/skills/synap/automations.md +15 -0
  357. package/skills/synap/capture.md +5 -0
  358. package/skills/synap/cli-operations.md +24 -18
  359. package/skills/synap/concepts.md +28 -0
  360. package/skills/synap/content-os.md +10 -1
  361. package/skills/synap/creative-loop.md +15 -10
  362. package/skills/synap/crm.md +21 -52
  363. package/skills/synap/document-embeds.md +141 -47
  364. package/skills/synap/escalation-ladder.md +20 -10
  365. package/skills/synap/focus-sessions.md +47 -21
  366. package/skills/synap/from-intent.md +142 -0
  367. package/skills/synap/governance-rules.md +4 -4
  368. package/skills/synap/governance.md +10 -7
  369. package/skills/synap/hand-off.md +33 -0
  370. package/skills/synap/inline-patterns.md +15 -7
  371. package/skills/synap/lenses.md +33 -15
  372. package/skills/synap/linking.md +41 -40
  373. package/skills/synap/mcp-remote-servers.md +64 -0
  374. package/skills/synap/mental-model.md +17 -15
  375. package/skills/synap/operating-mode-rules.md +1 -1
  376. package/skills/synap/processes.md +118 -0
  377. package/skills/synap/quick-reference.md +5 -1
  378. package/skills/synap/reading.md +3 -1
  379. package/skills/synap/reflexes.md +12 -42
  380. package/skills/synap/viewframe-cells.md +38 -5
  381. package/skills/synap/work-flow.md +1 -1
  382. package/skills/synap/work-model.md +96 -0
  383. package/skills/synap/worked-examples.md +4 -5
  384. package/skills/synap/workspace-design.md +14 -10
  385. package/skills/synap/writes.md +97 -24
  386. package/skills/synap/writing-titles.md +63 -0
  387. package/skills/synap-app/SKILL.md +2 -2
  388. package/skills/synap-app/_skill.yaml +1 -1
  389. package/skills/synap-app/install-commands.md +1 -1
  390. package/skills/synap-design/SKILL.md +474 -0
  391. package/skills/synap-design/_order.txt +4 -0
  392. package/skills/synap-design/_skill.yaml +21 -0
  393. package/skills/synap-design/loop.md +134 -0
  394. package/skills/synap-design/overview.md +44 -0
  395. package/skills/synap-design/principles.md +130 -0
  396. package/skills/synap-design/system.md +133 -0
  397. package/skills/synap-market/SKILL.md +306 -16
  398. package/skills/synap-market/_skill.yaml +1 -1
  399. package/skills/synap-market/author-and-publish.md +145 -8
  400. package/skills/synap-market/governance-and-catalog.md +7 -0
  401. package/skills/synap-market/install.md +79 -1
  402. package/skills/synap-market/overview.md +74 -6
  403. package/skills/synap-schema/SKILL.md +172 -10
  404. package/skills/synap-schema/_order.txt +2 -0
  405. package/skills/synap-schema/_skill.yaml +4 -2
  406. package/skills/synap-schema/common-mistakes.md +4 -2
  407. package/skills/synap-schema/discover-profiles.md +1 -1
  408. package/skills/synap-schema/entity-scope.md +15 -3
  409. package/skills/synap-schema/extend-first.md +29 -0
  410. package/skills/synap-schema/extend-vs-create.md +1 -1
  411. package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
  412. package/skills/synap-schema/property-types.md +1 -1
  413. package/skills/synap-schema/relations.md +1 -1
  414. package/skills/synap-ui/SKILL.md +19 -12
  415. package/skills/synap-ui/_skill.yaml +1 -1
  416. package/skills/synap-ui/ai-companion.md +1 -1
  417. package/skills/synap-ui/arranging-bento.md +2 -0
  418. package/skills/synap-ui/bento-layouts.md +10 -10
  419. package/skills/synap-ui/bento-recipes.md +313 -543
  420. package/skills/synap-ui/four-builds.md +5 -0
  421. package/skills/synap-ui/view-types.md +2 -2
  422. package/skills/synap-ui/widget-catalog.md +22 -278
  423. package/templates/automations/bookmark-enrichment.automation.json +290 -13
  424. package/templates/automations/url-bookmark-capture.automation.json +73 -11
  425. package/templates/skills/authoring-playbooks/SKILL.md +6 -3
  426. package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
  427. package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
  428. package/dist/commands/infra.d.ts +0 -21
  429. package/dist/commands/infra.js +0 -262
  430. package/dist/commands/infra.js.map +0 -1
  431. package/dist/commands/template.d.ts +0 -42
  432. package/dist/commands/template.js +0 -191
  433. package/dist/commands/template.js.map +0 -1
  434. package/dist/lib/browser-auth.d.ts +0 -35
  435. package/dist/lib/browser-auth.js +0 -170
  436. package/dist/lib/browser-auth.js.map +0 -1
  437. package/dist/lib/openclaw.d.ts +0 -32
  438. package/dist/lib/openclaw.js +0 -164
  439. package/dist/lib/openclaw.js.map +0 -1
  440. package/dist/lib/seed.d.ts +0 -13
  441. package/dist/lib/seed.js +0 -135
  442. package/dist/lib/seed.js.map +0 -1
  443. package/node_modules/@synap/hub-rest-client/dist/index.cjs +0 -1261
  444. package/node_modules/@synap/hub-rest-client/dist/index.d.cts +0 -1647
  445. package/node_modules/@synap/hub-rest-client/dist/index.d.ts +0 -1647
  446. package/node_modules/@synap/hub-rest-client/dist/index.js +0 -1231
  447. package/node_modules/@synap/hub-rest-client/package.json +0 -45
  448. package/node_modules/@synap/hub-rest-client/src/client.ts +0 -1631
  449. package/node_modules/@synap/hub-rest-client/src/errors.ts +0 -30
  450. package/node_modules/@synap/hub-rest-client/src/index.ts +0 -153
  451. package/node_modules/@synap/hub-rest-client/src/setup.ts +0 -133
  452. package/node_modules/@synap/hub-rest-client/src/types.ts +0 -1299
@@ -60,18 +60,20 @@ Agents can perform these actions directly without a proposal:
60
60
  - `document.create`
61
61
  - `memory.store` (always auto-approved, never proposed)
62
62
  - `view.create`
63
- - `profile.create`, `profile.update`
64
- - `property_def.create`, `property_def.update`
65
63
  - `channel.create`
66
64
  - `bento.arrange`
67
- - `filesystem.write_workspace` (OpenClaw sandbox only)
65
+ - `filesystem.write_workspace` (agent sandbox only)
68
66
 
69
67
  **Proposal-gated** (always require approval when done by agents):
70
68
 
71
69
  - `entity.delete`, `entity.archive`, `entity.purge`
72
70
  - `view.update`, `view.delete`
73
- - `profile.delete`
74
- - `property_def.delete`
71
+ - `profile.create`, `profile.update`, `profile.delete` — META-MODEL. A kind/role
72
+ is pod-wide (`entityScope` defaults to `'pod'`), so it changes what the pod IS
73
+ in every workspace. Unlike `automation.create` (auto-approved but landing
74
+ INERT as a draft), profiles have no inert state, so they propose.
75
+ - `property_def.create`, `property_def.update`, `property_def.delete` — a base
76
+ property def (`workspace_id` NULL) extends a shared kind for every workspace.
75
77
  - `workspace.create`, `workspace.update`, `workspace.delete`
76
78
 
77
79
  ## Destructive action override
@@ -108,7 +110,7 @@ You do not poll or wait. The user's experience is asynchronous.
108
110
 
109
111
  An agent user is a pod-wide user with `agentMetadata.writesRequireProposal` set. Created by `POST /api/hub/setup/agent`. Each agent user has:
110
112
 
111
- - `agentType`: a free-form string (`"claude-code"`, `"openclaw"`, `"raycast"`, `"custom"`)
113
+ - `agentType`: a free-form string (`"claude-code"`, `"codex"`, `"raycast"`, `"custom"`)
112
114
  - `agentMetadata`: arbitrary JSON for config
113
115
  - Hub API keys scoped to `hub-protocol.read` + `hub-protocol.write` + `mcp.*`
114
116
 
@@ -184,7 +186,8 @@ GET /api/hub/workspaces/{workspaceId}/governance
184
186
  effective: {
185
187
  autoApproveFor: [ // the actual whitelist at this workspace
186
188
  "entity.create", "entity.update", "relation.create", "document.create",
187
- "view.create", "profile.create", "property_def.create", "memory.*", …
189
+ "view.create", "memory.*", … // NOT profile.create / property_def.create —
190
+ // meta-model writes propose (see "Proposal-gated" above)
188
191
  ],
189
192
  governanceMode: "default" | "agent-owned",
190
193
  proposalApprovalPolicy: "owner_and_admins" | "any_editor" | "admins_only",
@@ -0,0 +1,33 @@
1
+ ## Hand work to an agent on the person's computer
2
+
3
+ The person says "start this on my devbox", "have my Mac's Claude Code do it", "give this session to Codex". You find the agent, hand it the work through a session, follow the session's room, and report back. You never run their machine yourself: an agent they connected there (`synap worker`, Claude Code, Codex) picks the work up.
4
+
5
+ **1. Find it — `synap_list_agents`.** One read: `computers[]` (the person's own) and `agents[]`, each with `computer`, `canTakeYourWork` (else `whyNot`), `live`, `paused`, `lastSeenAt`, and `handOff`: what YOUR hand-off would do right now (`direct`, `asks_you`, `blocked` + `handOffReason`). Ready agents come first.
6
+
7
+ - **Match the person's words against computer names first** ("my devbox" → the computer named `devbox`, any case), **then agent names and types** ("Codex", "claude-code"). Take the agents on that computer that can take the work.
8
+ - **Two or more fit → ask the person** which one, by name ("Claude Code on devbox, or Codex on devbox?"). Never pick for them.
9
+ - **None fits → say so.** "I see no agent on a computer called devbox" plus what you do see. Never hand it to a different machine silently.
10
+ - **`paused: true` → say it is paused** and that a person must resume it (Settings › Agents). Do not hand it off.
11
+ - **`live: false` → say when it was last seen** (`lastSeenAt`) and that it picks the work up the next time it checks in. Hand off only if the person still wants it.
12
+ - **`canTakeYourWork: false`** — `whyNot` says why: `not_owned` (another person's agent: it would never see this work), `wrong_reach` (the pod's own agent: it answers in rooms, it never picks work up), `paused`.
13
+
14
+ **2. Hand it — through a session.** The session's roster is how work reaches an agent.
15
+
16
+ - New work: `synap_start_session` with a `title`, a one-sentence `goal`, 2–5 `criteria` the person can check, and `agentIds: [agentUserId]`.
17
+ - Work in flight ("this session"): `synap_update_session` with `addAgentId: agentUserId`.
18
+ - Read the reply. `handOffs[].status` (start) or `handOff.status` (update): `granted` = on the roster now; `proposed` = waiting for the person's approval; `denied` = say the `reason` as given.
19
+ - **`asks_you` / `proposed`: the person approves the hand-off first.** Tell them plainly: "approve the hand-off on your phone", with the `reviewUrl` from the reply. It is success, do not retry. Then wait: `synap_get_session` until the agent is on its roster (or `synap_wait_for_answer` if you also asked them something), and go on to step 3.
20
+ - **`blocked` / `denied`: say why, in the reason's words.** Never retry it as is. One case the list cannot predict: your own proposal limit ("Agent proposal limit reached") — the reply carries a link to raise it; pass that to the person.
21
+
22
+ **3. Follow the room.** Everything the agent says lands in the session's room (`session.channelId`). Read it with `synap_get_thread_context { threadId: channelId }`; read the session's outcomes with `synap_get_session`. A `synap worker` on that computer follows this protocol:
23
+
24
+ - It checks for handed sessions about every 30 seconds and starts ONE run of Claude Code per session, in its working folder.
25
+ - It **claims** the session in the room in one line: picked up, and what it will do first.
26
+ - It works on a branch (`devbox/<session>-<slug>`, in a git worktree). It never pushes to main and never deploys.
27
+ - It **asks** with a room message starting `QUESTION:`. Kind `update` = you, the orchestrating AI, can answer; kind `question` = a decision only the person can make (the person is notified). It waits up to 30 minutes, reading the room every minute, and takes the FIRST reply posted after its question. No reply: it states its assumption and continues, or stops and says what is blocked.
28
+ - It **reports** in the room (what changed, branch, commit, files) and records deliverables against the session's outcomes. It does not close the session; the owner does.
29
+ - **Any room message posted after its run ended, by anyone but the agent, wakes it again** in the same conversation (up to 20 times). That is how an answer reaches it after it stopped. So post in the room only what you want it to act on.
30
+
31
+ Answer a `QUESTION:` of kind `update` yourself with `synap_post_message` to the room. Leave kind `question` to the person, or ask them and relay their answer.
32
+
33
+ **4. Report back.** Tell the person, in a few lines: which agent on which computer took it, whether it is on the roster or waiting for their approval, what the agent reported (result, branch, commit), and anything it asked that only they can answer. Point them at the session to review and close it.
@@ -8,6 +8,7 @@ When the user is interacting with Synap's AI Companion (the in-browser chat pane
8
8
  | ---------------------------- | --------------------------- | --------------------------------- |
9
9
  | `[[entity:UUID\|Name]]` | Purple entity chip | Opens entity detail in side panel |
10
10
  | `[[view:UUID\|Name]]` | Blue view chip | Opens view |
11
+ | `[[view:UUID]]` | View chip, named for you | Same; the label is optional |
11
12
  | `[[open:side\|view:UUID]]` | Amber "Open in side" button | Opens view in side panel |
12
13
  | `[[open:main\|view:UUID]]` | Amber "Open" button | Opens view in main panel |
13
14
  | `[[open:side\|entity:UUID]]` | Amber "Open in side" button | Opens entity in side panel |
@@ -16,10 +17,11 @@ When the user is interacting with Synap's AI Companion (the in-browser chat pane
16
17
 
17
18
  ### Rules
18
19
 
20
+ - **The label is optional.** `[[kind:UUID]]` is valid: in a document the chip shows the object's current name; in chat, where nothing looks it up, it reads as its kind ("View"). So in a chat reply, write the name you know: `[[view:UUID|Active Tasks]]`. A chip never shows the raw id.
19
21
  - **Always use real IDs.** Never hallucinate UUIDs. Only emit patterns for entities/views you just created or retrieved via Hub Protocol.
20
22
  - **Emit after creation.** When you create a view or entity, immediately reference it: `"Created your pipeline → [[view:abc123|Active Tasks]]"`
21
23
  - **Prefer side panel.** Use `[[open:side|view:UUID]]` so the user keeps their current context.
22
- - **Only in Companion replies.** These patterns are silently ignored in non-companion channels, documents, and memory. Do not use them there.
24
+ - **Companion replies and documents.** In a document, `[[entity:…|…]]` / `[[view:…|…]]` render as chips and the editor keeps them (`document-embeds.md`); the `[[open:…]]` / `[[run:…]]` commands are chat-only. Other channels and memory ignore them.
23
25
  - **Combine with prose.** Don't lead with a chip — embed it naturally: `"Here are your open deals → [[view:xyz|Deals Pipeline]] · [[open:side|view:xyz]]"`
24
26
 
25
27
  ### Proposals
@@ -28,11 +30,17 @@ There is no `[[open:…|proposal:…]]` chip — `open`'s `resourceType` only ac
28
30
  `entity`, `view`, `doc`, `cell`, `channel`. A proposal is not one of those, so
29
31
  never invent that form.
30
32
 
31
- When a write returns `status: "proposed"`, the response also carries a
32
- `reviewUrl` (a full Synap Studio URL). Surface it as a plain markdown link, and
33
- add one sentence explaining why the write was proposed instead of auto-applied:
33
+ When a write returns `status: "proposed"` (or any per-op outcome carrying a
34
+ `reviewUrl` — `writeReceipt.reviewUrl`, `perm.reviewUrl`, a capability run's
35
+ `kind: "proposed"`), the response also carries that `reviewUrl` (a real,
36
+ resolvable `${PUBLIC_URL}/open/<id>` link — never invented). **Surfacing it is
37
+ MANDATORY, not optional:** every reply that reports a proposed write MUST
38
+ include the link as a plain markdown link, plus one sentence explaining why it
39
+ was proposed instead of auto-applied:
34
40
 
35
- > Queued the task deletion for your review — destructive actions always need approval: [Review proposal](https://pod.example.com/proposals/prp_abc)
41
+ > Queued the task deletion for your review — destructive actions always need approval: [Review proposal](https://pod.example.com/open/prp_abc)
36
42
 
37
- `"proposed"` is normal, not an error — don't apologize for it or wait for the
38
- user to approve before continuing the conversation.
43
+ A reply that only says "I've proposed that for review" with no link is
44
+ incomplete — the user has no way to act on it. `"proposed"` is normal, not an
45
+ error — don't apologize for it or wait for the user to approve before
46
+ continuing the conversation.
@@ -2,18 +2,35 @@
2
2
 
3
3
  You don't work "inside a workspace" the way you'd work inside a folder. You operate **across the whole pod**, and you **focus** through up to three composable lenses. **Lenses narrow; they never silo.** Omitting them is legal and common — that's pod-wide.
4
4
 
5
- | Lens | What it is | How to set (this session) |
6
- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
7
- | **Project** | a **company or initiative** — the thing that ties the work together (Synap, a client, a launch). The lens you usually _organize by_. | `synap project use <id>` / `clear` |
8
- | **Workspace** | an **operational domain** — where data lives (Foundation, CRM, Marketing, Finance, Builder). How the work is separated; the default home for writes. | `synap use <name-or-id>` |
9
- | **Session** | the **work room** for the current goal (holds goal, deliverables, progress) | `synap session start --goal "…"` / `attach <id>` |
5
+ Tool names below are stems; your door may prefix them.
10
6
 
11
- **How they compose — this is the whole model:**
7
+ What each word means (workspace, project, track, step, work): `concepts` — the one glossary. This file is only about scoping.
12
8
 
13
- - A **project spans workspaces**: one company/initiative has a Foundation, a CRM, a Marketing, a Finance… each a different operational lens on the _same_ project.
14
- - A **workspace spans projects**: the Marketing workspace can hold work for several clients/projects at once.
15
- - **Membership is per-entity, filed on write.** An entity belongs to a project because it was created/filed **under the project lens** — not because its workspace is "in" the project (there is no workspace→project link). So **set the project lens before writing** work that belongs to an initiative, and it composes into that project from any workspace.
16
- - Compose either way, or both. That's why they're lenses, not folders: **workspaces exist so that development, finance, marketing, and operations don't pile into one undifferentiated place** — they're the separation that makes the work legible.
9
+ | Lens | Scopes | Set it (MCP / CLI) |
10
+ | ------------- | ---------------------------------------------------------- | ------------------------------------------------------------------ |
11
+ | **Workspace** | a domain; a thing lives in exactly ONE; default write home | `set_workspace_focus` / `synap use <name-or-id>` |
12
+ | **Project** | a commitment across workspaces; a thing can be in several | `set_project_focus` or `projectId` / `synap project use <id>` |
13
+ | **Session** | the work room for the current goal; pass its id on writes | `start_session` / `synap session start --goal "…"` / `attach <id>` |
14
+
15
+ **The project rule (one rule, every door):** a project is set ONLY when the user names it — declare it with `set_project_focus`, or pass `projectId` on the write. Filing into a project shares entities and documents with its members (a session is shared only through its room, never by filing), so never infer one from content, and never let a session decide it: a write without a `sessionId` is grouped into YOUR session — the one you started, else one opened for you, never another client's — and that door-picked session never sets the project. When nobody named a project, leave it unset. Guessing a workspace is merely untidy; guessing a project is not.
16
+
17
+ **One space per domain — the lens rule (every door):** A space is a domain, installed once (Content, Brand, CRM…). A project is a filter across spaces. To make something “for project X”: file it into X inside the domain's space (`file_into_project`), and link X to the space (`project_use_workspace`). Never create a space named after a project, a brand or a client. A second space from a template whose domain already has a live space is refused for an agent (`status: "exists"` + the space to use); a person may still create one, with the same note.
18
+
19
+ **Reads:** pod-wide by default; find by name, id or role, and pass `workspaceId` / `projectId` only to narrow a list.
20
+
21
+ **Writes:** name the kind (profile slug) and, when known, the roles as facets. Omit `workspaceId` unless you are deliberately pinning a domain — the server places the write from installed profile metadata. Never invent a workspace name. Focus sticks for the session; an explicit `workspaceId` / `projectId` on one call overrides it for that call.
22
+
23
+ **Empty domains:** a workspace holding 0 entities is a scaffold — prefer an active one unless the user names it (`orient` lists active domains; `detail:'full'` shows every one).
24
+
25
+ **Where the kinds are:** `orient` names the kinds in use, most-used first; the profile-listing tool lists every kind and role. A kind's property schema (fields, enums, required): over MCP, `get_entity` on any existing entity of that kind returns it as `effectiveProperties`; over HTTP, `GET /api/hub/discover?profileSlugs=<slug>`; CLI `synap discover`. A write that breaks the schema is rejected with the valid fields quoted.
26
+
27
+ **The space brief — what a space is FOR, and what it KNOWS.** PIN a space and the pod hands you its **brief**: `purpose` + `persona` (what it is for), `keyKinds` (the kinds it holds), `rules`, `playbooks`, `anchors`, and — the one that changes how you work — **`skills`**: the agent know-how the space ACTIVATES, each `{ slug, mode, when? }`. Reach it by passing a `workspaceId` to `orient` (an unpinned orient carries NO brief — it is space-scoped), or by `set_workspace_focus`; its reply carries the same brief. **Read the mode:** `mode: 'always'` is in effect for every task in this space — `load_skill` its slug before you work; `mode: 'on-demand'` means load it when the task matches its `when`. A space's skills are the pod telling you _this domain has a way of doing things_ — honour them rather than improvising. Pin the space the moment you are about to work in one.
28
+
29
+ **How they compose** (definitions: `concepts`):
30
+
31
+ - A **project spans workspaces** and a **workspace spans projects**.
32
+ - **Membership is per-entity, filed on write.** An entity belongs to a project because it was written **under that project lens** (`belongs_to_project`) — that is the data ACL/filing edge. Separately, provisioning with a `projectId` also stamps **`project --uses--> workspace`**: an INDEX of domains the engagement runs through. That index is **not** an ACL and does **not** replace entity filing — set the project lens before writing work so entities compose into the project from any workspace.
33
+ - A lasting goal inside a project is a **track**, never a child project or a workspace; a bounded piece of work is a **session** (`trackId` when it belongs to a track). There are no nested projects.
17
34
 
18
35
  - **The connection is pod-wide by design.** Your MCP/CLI link is _not_ welded to a workspace — reads default pod-wide, writes default to a sensible workspace. Pass a lens to narrow a single call; the lens is a focus, not a fence.
19
36
  - **These are per-Claude-session.** Two concurrent Claude sessions can sit on different projects/workspaces/sessions without colliding. `synap use` here rebinds **this** session only.
@@ -24,15 +41,16 @@ You don't work "inside a workspace" the way you'd work inside a folder. You oper
24
41
  **Before the FIRST write of a new unit of work**, check your lens and orient if you're unsure:
25
42
 
26
43
  1. `synap lens` — am I scoped where this work belongs?
27
- 2. If unsure what exists → `synap orient` — it returns a **light lens map**: the projects and the workspaces (names + ids), so you see the shape without a data dump. Never guess IDs. Drill into a workspace's profiles or a project's contents only when you actually need them.
44
+ 2. If unsure what exists → `synap orient` — it returns the **briefing**: pending review, open sessions, the kinds in use, then the projects and workspaces (names + ids), without a data dump. Never guess IDs. Drill into a workspace's profiles or a project's contents only when you actually need them.
28
45
  3. **Connect or create:** if the right project / workspace / session doesn't exist yet, create it. A **session is the normal per-task move**. Creating a **workspace (a new operational domain) is a deliberate, expected move as the work grows** — not something to avoid. A **project, though, is a COMMITMENT WITH GRAVITY**: search existing projects first (`synap orient`) and prefer **linking into an existing one** via `belongs_to_project`. Only create a new project for a real initiative that ties work together — never for a task, plan, repo, or theme (those are entities), and **never for the pod owner's own company** (the company _is_ the pod, not a project inside it). An agent-created project must cite **≥5 existing entities** as evidence or the backend rejects it, and near-duplicate names are rejected with the existing candidates.
29
46
 
30
47
  **Don't re-orient mid-flow.** Once you've oriented and you're in a run of related writes, keep going — re-check only when you **start a new piece of work** or switch domains. The reflex guards the _start_ of work, not every call.
31
48
 
32
- ### Notice a missing domain — and offer it
49
+ ### Notice a missing method or domain — and offer it
33
50
 
34
- Because workspaces are how a company separates its operations, a project is sometimes **missing an operational domain it clearly needs**. If the conversation is squarely about an area — sales, content, finance, hiring, ops — and the active project has **no workspace for it**, say so **once, at the end, in one line**, and offer to set it up:
51
+ A project sometimes clearly needs something it lacks. Tell the two apart first:
35
52
 
36
- > _"This project doesn't have a Marketing workspace yet — want me to spin one up and capture the essentials?"_
53
+ - **A lasting goal is missing** (the talk keeps returning to a goal — growing the newsletter, landing clients… — and `list_tracks` shows no track for it) → offer a **track**: _"This project has no track for the newsletter yet — want me to start one?"_ Then `start_track` with a `name` and `direction`; no method needed.
54
+ - **A domain is missing** (new kinds of things must be recorded that no workspace owns — e.g. you are logging deals and there is no CRM) → offer a **workspace**, provisioned with the project lens active (see the `agent-os` skill). Never a workspace to stand for a method.
37
55
 
38
- If they say yes, provision that **one** domain and run its onboarding interview **with the project lens active** (so its entities file into the project) (see the `agent-os` skill — it handles both the whole-company setup and adding a single domain to an existing project). **Offer, don't auto-build.** One nudge per response, and only when the gap is real — never a checklist of everything the project "could" have. **If the user has already declined a domain (this session or before), drop it — don't re-offer.**
56
+ Say it **once, at the end, in one line**. **Offer, don't auto-build.** One nudge per response, only when the gap is real — never a checklist of everything the project "could" have. **If the user has already declined it (this session or before), drop it — don't re-offer.**
@@ -8,17 +8,14 @@ When a profile property has `valueType: "entity_id"`, setting it on entity creat
8
8
 
9
9
  Known system-profile auto-syncs:
10
10
 
11
- | Profile | Property | Target profile | Auto-relation type |
12
- | -------- | ----------- | -------------- | -------------------- |
13
- | task | `projectId` | project | `belongs_to_project` |
14
- | task | `assignee` | person | `assigned_to` |
15
- | contact | `companyId` | company | `works_at` |
16
- | deal | `contactId` | contact | `deal_for` |
17
- | deal | `companyId` | company | `deal_with` |
18
- | document | `entityId` | (any) | `attached_to` |
19
- | anchor | `channelId` | (channel) | `anchored_in` |
20
-
21
- Custom profiles: if you created a property with `valueType: "entity_id"`, the auto-sync kicks in, but the relation type defaults to `related_to` unless the profile defines a `relationDefinition`. When precision matters, create the relation explicitly (Way 2) with a specific `type`.
11
+ | Profile | Property | Target profile | Auto-relation type |
12
+ | ------- | ----------- | -------------- | -------------------- |
13
+ | task | `projectId` | project | `belongs_to_project` |
14
+ | task | `assignee` | person | `assigned_to` |
15
+ | contact | `companyId` | company | `works_at` |
16
+ | deal | `contactId` | contact | `deal_for` |
17
+
18
+ Custom profiles: an `entity_id` property does NOT create an edge on its own. Auto-sync writes a relation only when the property def is mapped to a relation def (its `relationDefId`), and the edge then takes THAT def's slug. An unmapped `entity_id` property stores the id and creates no relation at all — there is no default or fallback type. When you need the edge, create it explicitly (Way 2) with an existing relation-def slug; `synap_list_profiles` returns them under `relationTypes`.
22
19
 
23
20
  **Do not trust this table to stay current.** Always verify with `GET /api/hub/profiles` — the returned profile includes `properties[].valueType` and `properties[].targetProfileSlug`. Any property with `valueType: "entity_id"` is an auto-sync candidate.
24
21
 
@@ -68,37 +65,40 @@ POST /api/hub/relations
68
65
  }
69
66
  ```
70
67
 
71
- ## Conventional relation types
72
-
73
- String-typed, case-insensitive by convention. Use these first before inventing new ones — workspace UI often renders known types specially.
74
-
75
- | Type | Direction | When |
76
- | -------------- | --------------- | ------------------------------------------------- |
77
- | `related_to` | bidirectional | Generic association, no stronger label fits |
78
- | `parent_of` | source → target | Hierarchy (project parent of sub-project) |
79
- | `child_of` | source → target | Hierarchy (inverse of parent_of) |
80
- | `belongs_to` | source → target | Membership |
81
- | `authored_by` | source → target | Note/document authored by a person |
82
- | `depends_on` | source → target | Task blocked by another task, project needs input |
83
- | `references` | source → target | Task references a document, note cites an article |
84
- | `mentions` | source → target | Entity mentioned within another entity |
85
- | `works_with` | bidirectional | People who collaborate |
86
- | `part_of` | source → target | Component relationship |
87
- | `from_meeting` | source → target | Any entity extracted from a meeting/event |
88
- | `anchored_in` | source → target | Anchor (pinned chat message) in a channel |
89
-
90
- If none fits, invent a snake_case verb. Keep it short and symmetric with existing verbs. Don't create `related-to-this-specific-thing` — prefer a generic `related_to` plus a more specific property or document.
68
+ ## Relation types — use the pod's, never invent one
69
+
70
+ A relation's `type` must be the slug of a relation definition the pod has. `synap_list_profiles` returns them under `relationTypes` (custom ones a workspace added included) — read it before linking. The defaults every pod ships:
71
+
72
+ | Type | Direction | When |
73
+ | ------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
74
+ | `relates_to` | bidirectional | Generic association, when no stronger type fits |
75
+ | `references` | source → target | A task references a document, a note cites an article |
76
+ | `mentions` | source → target | One entity is mentioned within another's content |
77
+ | `links_to` | source → target | A hyperlink or explicit pointer |
78
+ | `parent_of` | source → target | Entity hierarchy (a kind instance of another). Not nested projects — those do not exist. A method in a project is a track; a unit of work is a session. |
79
+ | `belongs_to_project` | source → target | An entity filed into a project (prefer the `projectId` property — Way 1) |
80
+ | `assigned_to` | source → target | A task/project assigned to a person |
81
+ | `created_by` | source → target | A note/document authored or created by a person |
82
+ | `blocks` / `depends_on` | source → target | A DEPENDENCY: the source blocks / waits on the target. Dependencies are becoming ONE `blocked_by` edge across kinds (session · entity · track); these two slugs are its entity-side names |
83
+ | `tagged_with` | source → target | Categorization by a tag entity |
84
+ | `attended_by` | source → target | An event's participant |
85
+ | `works_at` · `works_on` · `affiliated_with` | source → target | A person and an organization / a project they contribute to / an affiliation |
86
+ | `knows` · `met_at` · `discussed_with` | person → target | People who know each other / where they met / who they talked with |
87
+ | `deal_for` | source → target | A sales deal for a contact |
88
+ | `has_skill` | source → target | A person's skill |
89
+
90
+ **No fitting type? Do not invent one.** A slug that is not a relation definition is refused or lands as a link nobody can read. Use `relates_to` plus a more specific property or document, or — if the relationship recurs and deserves a name — propose a new relation definition (it is a schema change, reviewed like one).
91
91
 
92
92
  ## Decision table
93
93
 
94
- | Situation | Use |
95
- | ------------------------------------------------------ | -------------------------------------- |
96
- | Profile has matching `valueType: "entity_id"` property | Way 1 — set the property |
97
- | Linking two already-existing entities | Way 2 — create a relation |
98
- | Custom connection, no matching property | Way 2 |
99
- | Unsure whether a property exists | `GET /profiles` first |
100
- | Linking a document to its parent entity | Use `entityId` on the document (Way 1) |
101
- | Multi-party link (entity A ↔ entity B ↔ entity C) | Two relations, both Way 2 |
94
+ | Situation | Use |
95
+ | ------------------------------------------------------ | ------------------------- |
96
+ | Profile has matching `valueType: "entity_id"` property | Way 1 — set the property |
97
+ | Linking two already-existing entities | Way 2 — create a relation |
98
+ | Custom connection, no matching property | Way 2 |
99
+ | Unsure whether a property exists | `GET /profiles` first |
100
+ | Linking a document to the entity it is about | Way 2 — `references` |
101
+ | Multi-party link (entity A ↔ entity B ↔ entity C) | Two relations, both Way 2 |
102
102
 
103
103
  ## Reading the graph
104
104
 
@@ -125,5 +125,6 @@ GET /api/hub/graph/traverse?entityId={id}&maxDepth=2
125
125
  - **Spinning up a new project instead of linking into an existing one.** A project is a **commitment with gravity**, not a folder for a task, plan, repo, or theme (those are entities). Before `create_project`, search existing projects and file the entity into one via `belongs_to_project` (Way 1 `projectId`, or Way 2 relation). Near-duplicate project names are rejected server-side with the existing candidates, and an agent-created project also requires **≥5 existing entities** as evidence.
126
126
  - **Creating an orphan, then forgetting to link it.** Every `POST /entities` should include properties that link, OR be immediately followed by a `POST /relations`. Never close the operation with a disconnected node.
127
127
  - **Double-linking.** If you set `properties.projectId` AND also `POST /relations` with type `belongs_to_project`, the auto-sync already did it. Don't duplicate.
128
- - **Using `related_to` when a specific verb fits.** `related_to` is the fallback. `authored_by`, `depends_on`, `references` carry more meaning to both the user and downstream views.
128
+ - **Using `relates_to` when a specific type fits.** `relates_to` is the fallback. `created_by`, `depends_on`, `references` carry more meaning to both the user and downstream views.
129
+ - **Inventing a relation type.** `child_of`, `belongs_to`, `authored_by`, `part_of`, `works_with` are NOT relation types here — use `parent_of` (from the parent), `belongs_to_project`, `created_by`, `parent_of` / `relates_to`, `knows`. Check `relationTypes` first.
129
130
  - **Inverting direction.** Source is "the thing doing the action or owning the relationship." `task depends_on task` means the source is blocked by the target. Check twice.
@@ -0,0 +1,64 @@
1
+ # Remote MCP servers — how a pod registers, approves and governs them
2
+
3
+ Load this before you suggest connecting an external MCP server to a pod, or when a server's tools do not
4
+ show up. Every claim here is read from the code: the `mcp_servers` table
5
+ (`packages/database/src/schema/mcp-servers.ts`), the settings door (`routers/mcp-servers.ts`), the
6
+ capability installer (`services/capabilities/create-from-definition.ts`) and the IS adapter.
7
+
8
+ ### The row
9
+
10
+ One row per server in `mcp_servers`, scoped to a space (`workspaceId`) or pod-wide (null). `slug` is
11
+ lowercase `a-z0-9-`, unique per space; the IS names each tool `mcp_<slug>_<tool>`, so a space's server
12
+ overrides a pod-wide one with the same slug.
13
+
14
+ | Field | Meaning |
15
+ | ------------ | ------------------------------------------------------------------------------------------ |
16
+ | `transport` | `http` (needs `url`) or `stdio` (needs `command` + `args`, runs on the IS host) |
17
+ | `auth` | http only: `{ credentialRef: "vault://<id>", header: "Authorization", prefix: "Bearer " }` |
18
+ | `toolPolicy` | `{ default: "governed" or "inline", inline: ["tool_a", …] }`; absent = governed |
19
+ | `approved` | false by default; the supply-chain gate |
20
+ | `enabled` | the owner's on/off switch |
21
+
22
+ ### Secrets never sit on the row
23
+
24
+ `auth.credentialRef` points at a vault secret. The pod resolves it server-side on every call (never
25
+ cached), sends it to the IS as a header, and the agent never sees it. If it cannot be resolved for the
26
+ acting user or agent, the server is skipped and its tools simply do not appear: check the vault grant
27
+ before you blame the server.
28
+
29
+ ### Governed by default
30
+
31
+ - A **governed** tool is never called directly: the IS routes it through the pod (`mcp://<slug>`),
32
+ where the capability gate runs it or files a proposal. For an agent, `proposed` is success.
33
+ - An **inline** tool is called directly by the IS. Declare `default: "inline"` only for a server that
34
+ exposes nothing but reads; for a mixed server, list its read tools in `inline`.
35
+ - No policy at all means governed. This is deliberate and fail-closed.
36
+
37
+ ### Approval, and when it resets
38
+
39
+ - Tools reach an agent only when the server is **approved AND enabled** (and, in a channel that keeps
40
+ its own MCP list, only the servers that channel opted into). The list is cached for 30 seconds.
41
+ - In the space settings, tab MCP Servers: a space **owner or admin** adds, edits or deletes a server; only the space
42
+ **owner** approves it; a pod-wide server needs a pod admin to add or edit.
43
+ - Editing `url`, `command`, `args`, `env` or `transport` in the settings **resets approval** (compared by
44
+ value, so a rename or an enabled toggle does not). Re-approve after re-pointing a server.
45
+ - A capability (catalog or `market.install`) may declare `mcpServers[]` with `auth` and `toolPolicy`;
46
+ this is the only door that sets those two today (the settings form does not). Its install is the trust
47
+ decision: it may ship `approved: true`. Re-applying it converges url, auth and policy to the
48
+ template and only ever promotes approval, never revokes it.
49
+
50
+ ### As an agent
51
+
52
+ You have no tool that registers a server. Propose it: a capability that declares the server (installed
53
+ through `market.install`, which files a proposal), or ask the person to add it in the space settings (MCP Servers). Never
54
+ ask for the secret in chat; it goes in the vault.
55
+
56
+ ### Network: who must reach the URL
57
+
58
+ The **IS** opens the connection, not your machine. A `url` must be reachable from where the pod's IS runs.
59
+
60
+ **An unauthenticated dev MCP is never registered on a public URL.** Storybook's `/mcp`
61
+ (`http://localhost:6006/mcp`) and similar dev servers have no auth: reach them only over a private
62
+ network or a tunnel the IS is on (an SSH tunnel to a dev pod), keep them bound to loopback otherwise,
63
+ and prefer a static artifact (Storybook's `/manifests/components.json`) for agents on a remote pod. If
64
+ a server would need to be public to be reached, it needs `auth` first.
@@ -6,15 +6,15 @@ Synap is a typed knowledge graph. **Reading is one verb (`synap ask`) — it rou
6
6
 
7
7
  Ask yourself: _who does this knowledge serve?_ **There is no private AI scratchpad** — structuring knowledge into a real lane IS your job. Never write a `note` (that's the human's raw inbox); always `capture` into a lane.
8
8
 
9
- **Known fields → typed create.** If you already know the profileSlug and the values, use `synap create entity` / `synap_create_entity` (or typed `capture --type` for a knowledge entry). Reach for free-text `capture "…"` only for an unstructured blob you haven't parsed — it runs an AI pipeline that can degrade to one flat `note`. 'Always capture into a lane' means _don't leave it unstructured_, not _always use the free-text pipeline_.
9
+ **Known fields → typed create.** If you already know the profileSlug and values, use `synap create entity` / `synap_create_entity`. Reach for free-text `capture "…"` only for an unstructured blob you haven't parsed — it runs an AI pipeline that can degrade to one flat `note`. 'Always capture into a lane' means _don't leave it unstructured_, not _always use the free-text pipeline_.
10
10
 
11
- | If it… | Lane | Where it goes | Governance |
12
- | ------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
13
- | **is about the CURRENT WORK** — domain know-how for the project/task you're on (incl. a domain-specific gotcha/lesson/decision) | **Work** _(default)_ | a `knowledge` entity in the **active workspace** (`synap capture --type …`) | proposal-gated (it's the user's real data; the workspace IS the domain — Builder ≠ marketing) |
14
- | **is GLOBAL truth** — a best-practice / runbook / how-to that holds across ALL projects | **Global** | pod-wide procedural `knowledge_keys` (`synap capture --global --type … [--key ns:slug]`) | reviewed for shared truth |
15
- | **is about the USER** — how they work/talk/decide, their preferences, their life | **User** | pod-wide `user_observation` (`synap observe write` / `record_observation` tool) | inferences are **proposed** (you review); explicit "I always X" auto-saves — never model the user silently |
11
+ | If it… | Lane | Where it goes | Governance |
12
+ | --------------------------------------------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
13
+ | **is about the CURRENT WORK** — a reusable conclusion or caveat in the project/task you're on | **Work** _(default)_ | a `knowledge` entity through server-derived Work placement (pin with `--workspace` only when you know the domain) | proposal-gated (it's the user's real data; the workspace IS the domain — Builder ≠ marketing) |
14
+ | **is GLOBAL truth** — a best-practice / runbook / how-to that holds across ALL projects | **Global** | pod-wide procedural `knowledge_keys` (`synap capture --global --type … [--key ns:slug]`) | reviewed for shared truth |
15
+ | **is about the USER** — how they work/talk/decide, their preferences, their life | **User** | pod-wide `user_observation` (`synap observe write` / `record_observation` tool) | inferences are **proposed** (you review); explicit "I always X" auto-saves — never model the user silently |
16
16
 
17
- > **Why this matters:** writing to the wrong lane degrades the graph. A gotcha you learned about the **current project** is **Work** (the active workspace — its domain). A best-practice that holds **everywhere** is **Global** (`--global`, pod-wide). A fact about **how the user works** is **User** (pod-wide, inferences proposed). `synap capture` echoes which lane + governance it used; check it.
17
+ > **Why this matters:** writing to the wrong lane degrades the graph. A caution you learned about the **current project** is **Work** (let the server route it, or pin the known domain explicitly). A best-practice that holds **everywhere** is **Global** (`--global`, pod-wide). A fact about **how the user works** is **User** (pod-wide, inferences proposed). `synap capture` echoes which lane + governance it used; check it.
18
18
 
19
19
  > **Read the write outcome — it guides your next move (it never blocks you).** Every write (`capture`, `observe`, `create entity`, `create relation`, `note`) reports one of two outcomes (and `--json` carries `"outcome"`):
20
20
  >
@@ -23,6 +23,8 @@ Ask yourself: _who does this knowledge serve?_ **There is no private AI scratchp
23
23
 
24
24
  > **Substrate names (tables under the hood):** _semantic_ = `entities` (the `knowledge` profile, workspace-scoped = domain separation), _episodic_ = `knowledge_facts`, _procedural_ = `knowledge_keys` (pod-wide runbooks). `ask` queries across them so you never pick on read.
25
25
 
26
+ **Facets (roles)** are hats on **any kind** (`applicableKinds`), not only person/company. “This item is an X” is `attach_facet`, not a new kind, until X has its own life. Widen the role when `kind_mismatch`. See `from-intent` + `extend-first`. What role, workspace, project, track and template mean: `concepts` (the one glossary).
27
+
26
28
  ### Data layers — the graph itself
27
29
 
28
30
  | Layer | What it is | When to use |
@@ -35,11 +37,11 @@ Ask yourself: _who does this knowledge serve?_ **There is no private AI scratchp
35
37
 
36
38
  ### Key profiles for AI use
37
39
 
38
- | Profile slug | Scope | Who writes | Purpose |
39
- | ------------------ | --------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
- | `note` | pod | **human only** | The human's raw "dump now, structure later" inbox. **The AI never writes a note** — structuring into a lane is its job; use `capture` instead. |
41
- | `knowledge` | workspace | AI | Validated gotchas/lessons/decisions — the **Work lane** (default `synap capture --type`; ek_type/ek_claim/ek_why). DOMAIN = the workspace (a Builder gotcha ≠ a marketing one). Cross-project runbooks go to `knowledge_keys` via `--global`. |
42
- | `user_observation` | pod | AI only | Durable user model — habits, communication style, preferences |
43
- | `decision` | pod | human + AI | Architectural decisions with rationale |
44
- | `research` | pod | AI | Investigation with sources + conclusion |
45
- | `question` | pod | human + AI | Open inquiry, closed when a decision answers it |
40
+ | Profile slug | Scope | Who writes | Purpose |
41
+ | ------------------ | --------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
42
+ | `note` | pod | **human only** | The human's raw "dump now, structure later" inbox. **The AI never writes a note** — structuring into a lane is its job; use `capture` instead. |
43
+ | `knowledge` | workspace | AI | Reusable **Insights** and **Cautions** — one required `knowledgeForm`; an optional `ek_claim` is only a compact summary and long form belongs in the linked Markdown document. Decisions and sources remain linked first-class entities. DOMAIN = the workspace. Cross-project runbooks go to `knowledge_keys` via `--global`. |
44
+ | `user_observation` | pod | AI only | Durable user model — habits, communication style, preferences |
45
+ | `decision` | pod | human + AI | Architectural decisions with rationale |
46
+ | `research` | pod | AI | Investigation with sources + conclusion |
47
+ | `question` | pod | human + AI | Open inquiry, closed when a decision answers it |
@@ -1,6 +1,6 @@
1
1
  ## Synap-first operating mode
2
2
 
3
- > **MCP clients** (Claude Desktop, Raycast, OpenClaw with MCP): use `synap_*` tool names — they wrap auth and governance automatically. **REST / HTTP clients**: use the endpoints below.
3
+ > **MCP clients** (Claude Desktop, Raycast, any agent with MCP): use `synap_*` tool names — they wrap auth and governance automatically. **REST / HTTP clients**: use the endpoints below.
4
4
 
5
5
  These five rules override default assistant behavior when connected to a Synap pod:
6
6
 
@@ -0,0 +1,118 @@
1
+ # Processes — a playbook that follows a kind's lifecycle
2
+
3
+ <!-- brief:start -->
4
+
5
+ A process = `synap_create_playbook` with `subjectProfileSlug`; it FOLLOWS the
6
+ lifecycle the kind or role declares (omit `statusProperty`, or name that same
7
+ property). Each stage's `subjectStatus` is an EXISTING option of it (read it
8
+ with `synap_list_profiles` first — never invent one); `gate: {kind: 'human'}` at
9
+ every commitment, `onFail: {toStage}` for rework; typed `expectedOutputs`
10
+ (`kind`, `label`, `relationToSubject`); workers = `activators` (`on`, `size`,
11
+ default `mode: 'propose'`). What you create is POD-LOCAL, never an official
12
+ template.
13
+
14
+ <!-- brief:end -->
15
+
16
+ ## Writing a process (a playbook that follows a kind's lifecycle)
17
+
18
+ The status belongs to the **kind or role**, never to a playbook. Its profile declares the lifecycle ONCE, in its
19
+ template:
20
+
21
+ ```yaml
22
+ lifecycle:
23
+ property: post-status
24
+ options:
25
+ - { key: Idea, category: open }
26
+ - { key: Published, category: done }
27
+ - { key: Archived, category: lost, humanOnly: true }
28
+ ```
29
+
30
+ Every option has one category (`open · active · paused · done · lost`); rules read the category, names stay free.
31
+ `humanOnly` marks an option no agent sets; an agent's move into `done` or `lost` proposes. Every move goes through
32
+ the one status door (`moveStatus`; an agent sends `update_entity` with `expectedStatus`).
33
+
34
+ A playbook that works that lifecycle is a **process**: it FOLLOWS it. Its stages name options of it, its workers
35
+ start on it, and a person decides at the moments that commit the business. It never keeps a second status field.
36
+ The reference is Content OS "Produce Content" (`synap-app/packages/workspace-templates/src/content-os.yaml`).
37
+
38
+ **Official vs pod-local.** An official template or capability lives ONLY in the catalog
39
+ (`synap-app/packages/workspace-templates/`, by kind) and is published with
40
+ `synap catalog publish --official` (CI on main). A playbook, kind or automation an agent creates on a pod
41
+ (`synap_create_playbook`, `synap_define_kind`, …) is **pod-local**: it never reaches the catalog. To make it
42
+ official, write it into the catalog file and publish.
43
+
44
+ | Field | Where | Rule |
45
+ | ------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
46
+ | `subjectProfile.profileSlug` | playbook | The kind or role the process works. |
47
+ | `subjectProfile.statusProperty` | playbook | Omit it: the pod follows the profile's declared lifecycle. If you name it, name that same property. A status worker on a role with no declared lifecycle is refused. |
48
+ | `stages[].subjectStatus` | stage | Entering the stage moves the subject to this option, through the door. Must be an **existing option** of the lifecycle — never invent one. |
49
+ | `stages[].gate` | stage | `{kind: human}` at every commitment: send to a client, sign, pay, publish, won/lost, anything irreversible. `{kind: check}` only where the stage's own criteria can be verified. A gated stage writes its status only when the gate passes. A check gate judges the stage being LEFT, so never use it to guard an irreversible status. |
50
+ | `stages[].onFail` | stage | `{toStage: <key>}` — where a rejected gate sends the run (rework loop). |
51
+ | `stages[].criteria` | stage | 2–5 binary statements; `check.kind` evidence (cheapest) · capability · judge · human. |
52
+ | `expectedOutputs[]` | stage or playbook | What the step must produce: `kind` + `label` + `relationToSubject` (an existing relation slug, or `none`). The UI shows what was produced from this. |
53
+ | `activators[]` (workers) | playbook | `on`: `created` · `enters_status` (+ `status`) · `count` (+ `status`, `min` ≥ 2) · `schedule` (+ `cron`, UTC) · `manual`. `size`: `per_thing` (default) · `per_moment` (count and schedule always are). `mode`: `propose` (default) · `run` only when cheap and safe. `maxPendingApprovals` (default 20) throttles. Compiled to a governed rule the owner can pause; it fires once per thing per transition. |
54
+ | `humanOnlyStatuses` | playbook | Legacy: the options no stage owns. Mark a person-only option `humanOnly` on the lifecycle instead; while `statusProperty` is set, `synap catalog validate` still checks that stages and this list cover every option. |
55
+ | `goalTemplate` | playbook | Placeholders are `{paramName}`. Never `@{arg:…}` (read-only legacy). |
56
+ | `params` | playbook | The subject is a `type: entity` param. A required param left unanswered becomes a question owed by the person, not an empty string. |
57
+
58
+ Human moments use an `ask` on an owed slot: `confirm` / `choose` (one `recommended`) / `form` / `act` / `provide`
59
+ (connection, file or secret through the vault). Never ask for a secret in a form.
60
+
61
+ Validation: `synap catalog validate` (process contract, goal grammar, lifecycle coverage ratchet — the count of
62
+ lifecycle kinds with no process may only go down).
63
+
64
+ ## Declaring it over MCP
65
+
66
+ `synap_create_playbook` takes the contract as-is. Before calling it, read the
67
+ subject kind (`synap_list_profiles`) and copy the options of its lifecycle
68
+ property exactly. Over MCP you cannot declare or change a lifecycle; it comes
69
+ with the kind's template.
70
+
71
+ ```json
72
+ {
73
+ "name": "Draft a post",
74
+ "goalTemplate": "Draft {post}",
75
+ "params": [{ "name": "post", "type": "entity", "required": true }],
76
+ "subjectProfileSlug": "post",
77
+ "activators": [
78
+ {
79
+ "on": "enters_status",
80
+ "status": "Briefed",
81
+ "size": "per_thing",
82
+ "mode": "propose"
83
+ }
84
+ ],
85
+ "stages": [
86
+ {
87
+ "key": "draft",
88
+ "name": "Draft",
89
+ "category": "started",
90
+ "subjectStatus": "In Draft",
91
+ "expectedOutputs": [
92
+ {
93
+ "kind": "document",
94
+ "label": "Draft",
95
+ "relationToSubject": "made_for"
96
+ }
97
+ ]
98
+ },
99
+ {
100
+ "key": "review",
101
+ "name": "Review",
102
+ "category": "started",
103
+ "subjectStatus": "Review",
104
+ "gate": { "kind": "human" },
105
+ "onFail": { "toStage": "draft" }
106
+ }
107
+ ]
108
+ }
109
+ ```
110
+
111
+ These are the Content OS post options; use the ones the kind really has. A
112
+ batch worker looks like `{ "on": "schedule", "cron": "0 8 * * 1", "status":
113
+ "Idea", "mode": "propose" }` (one session over every post in Idea, weekly) or
114
+ `{ "on": "count", "status": "Review", "min": 5, "mode": "propose" }`.
115
+ An agent call lands as a proposal (`status: "proposed"` is success). The
116
+ playbook lives on this pod only; to make it an official template, a developer
117
+ writes it into the catalog and publishes it with
118
+ `synap catalog publish --official`.