@synap-core/cli 1.8.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/dist/commands/agent-chat.d.ts +47 -0
  2. package/dist/commands/agent-chat.js +250 -0
  3. package/dist/commands/agent-chat.js.map +1 -0
  4. package/dist/commands/agent-run.js +3 -4
  5. package/dist/commands/agent-run.js.map +1 -1
  6. package/dist/commands/agents.js +85 -46
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/automation.js +2 -1
  9. package/dist/commands/automation.js.map +1 -1
  10. package/dist/commands/bridge-setup.d.ts +66 -0
  11. package/dist/commands/bridge-setup.js +1112 -0
  12. package/dist/commands/bridge-setup.js.map +1 -0
  13. package/dist/commands/cap-connections.d.ts +28 -0
  14. package/dist/commands/cap-connections.js +224 -0
  15. package/dist/commands/cap-connections.js.map +1 -0
  16. package/dist/commands/capability.d.ts +89 -0
  17. package/dist/commands/capability.js +1594 -0
  18. package/dist/commands/capability.js.map +1 -0
  19. package/dist/commands/centrality.d.ts +20 -0
  20. package/dist/commands/centrality.js +95 -0
  21. package/dist/commands/centrality.js.map +1 -0
  22. package/dist/commands/connect.d.ts +2 -0
  23. package/dist/commands/connect.js +16 -35
  24. package/dist/commands/connect.js.map +1 -1
  25. package/dist/commands/context.js +6 -7
  26. package/dist/commands/context.js.map +1 -1
  27. package/dist/commands/data-extra.d.ts +1 -0
  28. package/dist/commands/data-extra.js +41 -14
  29. package/dist/commands/data-extra.js.map +1 -1
  30. package/dist/commands/data.d.ts +4 -4
  31. package/dist/commands/data.js +254 -187
  32. package/dist/commands/data.js.map +1 -1
  33. package/dist/commands/diagnose.d.ts +20 -0
  34. package/dist/commands/diagnose.js +186 -0
  35. package/dist/commands/diagnose.js.map +1 -0
  36. package/dist/commands/digest.d.ts +17 -0
  37. package/dist/commands/digest.js +122 -0
  38. package/dist/commands/digest.js.map +1 -0
  39. package/dist/commands/discover.d.ts +2 -0
  40. package/dist/commands/discover.js +25 -8
  41. package/dist/commands/discover.js.map +1 -1
  42. package/dist/commands/doc.d.ts +14 -0
  43. package/dist/commands/doc.js +61 -4
  44. package/dist/commands/doc.js.map +1 -1
  45. package/dist/commands/doctor.d.ts +21 -0
  46. package/dist/commands/doctor.js +189 -0
  47. package/dist/commands/doctor.js.map +1 -0
  48. package/dist/commands/events.js +5 -2
  49. package/dist/commands/events.js.map +1 -1
  50. package/dist/commands/explain.d.ts +1 -1
  51. package/dist/commands/explain.js +18 -15
  52. package/dist/commands/explain.js.map +1 -1
  53. package/dist/commands/facet.d.ts +29 -0
  54. package/dist/commands/facet.js +113 -0
  55. package/dist/commands/facet.js.map +1 -0
  56. package/dist/commands/graph.js +7 -4
  57. package/dist/commands/graph.js.map +1 -1
  58. package/dist/commands/import.d.ts +38 -0
  59. package/dist/commands/import.js +471 -0
  60. package/dist/commands/import.js.map +1 -0
  61. package/dist/commands/init.js +35 -16
  62. package/dist/commands/init.js.map +1 -1
  63. package/dist/commands/keys.js +3 -4
  64. package/dist/commands/keys.js.map +1 -1
  65. package/dist/commands/knowledge.d.ts +8 -0
  66. package/dist/commands/knowledge.js +308 -33
  67. package/dist/commands/knowledge.js.map +1 -1
  68. package/dist/commands/launch.d.ts +50 -0
  69. package/dist/commands/launch.js +790 -0
  70. package/dist/commands/launch.js.map +1 -0
  71. package/dist/commands/lens.d.ts +45 -0
  72. package/dist/commands/lens.js +386 -0
  73. package/dist/commands/lens.js.map +1 -0
  74. package/dist/commands/market-authoring.d.ts +45 -0
  75. package/dist/commands/market-authoring.js +225 -0
  76. package/dist/commands/market-authoring.js.map +1 -0
  77. package/dist/commands/market.d.ts +224 -0
  78. package/dist/commands/market.js +1643 -0
  79. package/dist/commands/market.js.map +1 -0
  80. package/dist/commands/mcp.d.ts +64 -0
  81. package/dist/commands/mcp.js +265 -0
  82. package/dist/commands/mcp.js.map +1 -0
  83. package/dist/commands/observe.js +14 -11
  84. package/dist/commands/observe.js.map +1 -1
  85. package/dist/commands/open.d.ts +21 -4
  86. package/dist/commands/open.js +45 -4
  87. package/dist/commands/open.js.map +1 -1
  88. package/dist/commands/pod.d.ts +100 -0
  89. package/dist/commands/pod.js +359 -0
  90. package/dist/commands/pod.js.map +1 -0
  91. package/dist/commands/pods.d.ts +15 -0
  92. package/dist/commands/pods.js +233 -17
  93. package/dist/commands/pods.js.map +1 -1
  94. package/dist/commands/proposals-actions.js +43 -3
  95. package/dist/commands/proposals-actions.js.map +1 -1
  96. package/dist/commands/purge.d.ts +23 -0
  97. package/dist/commands/purge.js +148 -0
  98. package/dist/commands/purge.js.map +1 -0
  99. package/dist/commands/raycast.d.ts +15 -0
  100. package/dist/commands/raycast.js +153 -0
  101. package/dist/commands/raycast.js.map +1 -0
  102. package/dist/commands/sessions.js +47 -22
  103. package/dist/commands/sessions.js.map +1 -1
  104. package/dist/commands/skill-manage.d.ts +21 -0
  105. package/dist/commands/skill-manage.js +195 -0
  106. package/dist/commands/skill-manage.js.map +1 -0
  107. package/dist/commands/skills-commands.js +2 -1
  108. package/dist/commands/skills-commands.js.map +1 -1
  109. package/dist/commands/skills.js +7 -4
  110. package/dist/commands/skills.js.map +1 -1
  111. package/dist/commands/status.d.ts +3 -1
  112. package/dist/commands/status.js +166 -14
  113. package/dist/commands/status.js.map +1 -1
  114. package/dist/commands/statusline.d.ts +24 -0
  115. package/dist/commands/statusline.js +450 -0
  116. package/dist/commands/statusline.js.map +1 -0
  117. package/dist/commands/subscribe.js +2 -2
  118. package/dist/commands/subscribe.js.map +1 -1
  119. package/dist/commands/template.d.ts +42 -0
  120. package/dist/commands/template.js +191 -0
  121. package/dist/commands/template.js.map +1 -0
  122. package/dist/commands/tools.d.ts +30 -0
  123. package/dist/commands/tools.js +315 -0
  124. package/dist/commands/tools.js.map +1 -0
  125. package/dist/commands/upload.d.ts +30 -0
  126. package/dist/commands/upload.js +155 -0
  127. package/dist/commands/upload.js.map +1 -0
  128. package/dist/commands/versions.d.ts +27 -0
  129. package/dist/commands/versions.js +277 -0
  130. package/dist/commands/versions.js.map +1 -0
  131. package/dist/commands/view.js +3 -2
  132. package/dist/commands/view.js.map +1 -1
  133. package/dist/commands/whoami.d.ts +21 -0
  134. package/dist/commands/whoami.js +129 -0
  135. package/dist/commands/whoami.js.map +1 -0
  136. package/dist/index.js +894 -60
  137. package/dist/index.js.map +1 -1
  138. package/dist/lib/approval-poll.d.ts +42 -0
  139. package/dist/lib/approval-poll.js +52 -0
  140. package/dist/lib/approval-poll.js.map +1 -0
  141. package/dist/lib/auth.d.ts +29 -6
  142. package/dist/lib/auth.js +105 -94
  143. package/dist/lib/auth.js.map +1 -1
  144. package/dist/lib/bundle-version.d.ts +11 -0
  145. package/dist/lib/bundle-version.js +33 -0
  146. package/dist/lib/bundle-version.js.map +1 -0
  147. package/dist/lib/capture-lane.d.ts +30 -12
  148. package/dist/lib/capture-lane.js +73 -14
  149. package/dist/lib/capture-lane.js.map +1 -1
  150. package/dist/lib/capture-structure.d.ts +123 -0
  151. package/dist/lib/capture-structure.js +57 -0
  152. package/dist/lib/capture-structure.js.map +1 -0
  153. package/dist/lib/cp-packages.d.ts +177 -0
  154. package/dist/lib/cp-packages.js +389 -0
  155. package/dist/lib/cp-packages.js.map +1 -0
  156. package/dist/lib/describe-lens.d.ts +46 -0
  157. package/dist/lib/describe-lens.js +33 -0
  158. package/dist/lib/describe-lens.js.map +1 -0
  159. package/dist/lib/hub-client.d.ts +91 -1
  160. package/dist/lib/hub-client.js +565 -22
  161. package/dist/lib/hub-client.js.map +1 -1
  162. package/dist/lib/id.d.ts +23 -0
  163. package/dist/lib/id.js +35 -0
  164. package/dist/lib/id.js.map +1 -0
  165. package/dist/lib/installed.d.ts +51 -0
  166. package/dist/lib/installed.js +70 -0
  167. package/dist/lib/installed.js.map +1 -0
  168. package/dist/lib/next-steps.d.ts +61 -0
  169. package/dist/lib/next-steps.js +146 -0
  170. package/dist/lib/next-steps.js.map +1 -0
  171. package/dist/lib/pod.d.ts +144 -22
  172. package/dist/lib/pod.js +302 -64
  173. package/dist/lib/pod.js.map +1 -1
  174. package/dist/lib/project-ref.d.ts +95 -0
  175. package/dist/lib/project-ref.js +144 -0
  176. package/dist/lib/project-ref.js.map +1 -0
  177. package/dist/lib/project.d.ts +35 -0
  178. package/dist/lib/project.js +39 -0
  179. package/dist/lib/project.js.map +1 -0
  180. package/dist/lib/session-lens.d.ts +33 -0
  181. package/dist/lib/session-lens.js +76 -0
  182. package/dist/lib/session-lens.js.map +1 -0
  183. package/dist/lib/skill-import.d.ts +40 -0
  184. package/dist/lib/skill-import.js +203 -0
  185. package/dist/lib/skill-import.js.map +1 -0
  186. package/dist/lib/skills-installer.d.ts +17 -6
  187. package/dist/lib/skills-installer.js +133 -19
  188. package/dist/lib/skills-installer.js.map +1 -1
  189. package/dist/lib/suite.d.ts +28 -0
  190. package/dist/lib/suite.js +29 -0
  191. package/dist/lib/suite.js.map +1 -0
  192. package/dist/lib/superwhisper-import.d.ts +40 -0
  193. package/dist/lib/superwhisper-import.js +389 -0
  194. package/dist/lib/superwhisper-import.js.map +1 -0
  195. package/dist/lib/targets.d.ts +49 -1
  196. package/dist/lib/targets.js +420 -288
  197. package/dist/lib/targets.js.map +1 -1
  198. package/dist/lib/template-file.d.ts +74 -0
  199. package/dist/lib/template-file.js +140 -0
  200. package/dist/lib/template-file.js.map +1 -0
  201. package/dist/lib/unwrapList.d.ts +1 -0
  202. package/dist/lib/unwrapList.js +20 -0
  203. package/dist/lib/unwrapList.js.map +1 -0
  204. package/dist/utils/logger.d.ts +2 -0
  205. package/dist/utils/logger.js +10 -2
  206. package/dist/utils/logger.js.map +1 -1
  207. package/node_modules/@synap/hub-rest-client/dist/index.cjs +414 -34
  208. package/node_modules/@synap/hub-rest-client/dist/index.d.cts +762 -22
  209. package/node_modules/@synap/hub-rest-client/dist/index.d.ts +762 -22
  210. package/node_modules/@synap/hub-rest-client/dist/index.js +414 -34
  211. package/node_modules/@synap/hub-rest-client/package.json +1 -1
  212. package/node_modules/@synap/hub-rest-client/src/client.ts +525 -37
  213. package/node_modules/@synap/hub-rest-client/src/index.ts +42 -0
  214. package/node_modules/@synap/hub-rest-client/src/setup.ts +57 -1
  215. package/node_modules/@synap/hub-rest-client/src/types.ts +697 -37
  216. package/package.json +11 -5
  217. package/skills/agent-os/SKILL.md +218 -0
  218. package/skills/manifest.json +5 -0
  219. package/skills/onboard/SKILL.md +193 -0
  220. package/skills/synap/SKILL.md +1284 -58
  221. package/skills/synap/_order.txt +37 -0
  222. package/skills/synap/_skill.yaml +24 -0
  223. package/skills/synap/authentication.md +10 -0
  224. package/skills/synap/automations.md +264 -0
  225. package/skills/synap/capabilities.md +107 -0
  226. package/skills/synap/capture.md +50 -142
  227. package/skills/synap/cli-operations.md +107 -0
  228. package/skills/synap/common-mistakes.md +13 -0
  229. package/skills/synap/content-os.md +83 -0
  230. package/skills/synap/creative-loop.md +43 -0
  231. package/skills/synap/crm.md +117 -0
  232. package/skills/synap/diagnostics.md +35 -0
  233. package/skills/synap/digesting-a-channel.md +63 -0
  234. package/skills/synap/document-embeds.md +123 -0
  235. package/skills/synap/escalation-ladder.md +71 -0
  236. package/skills/synap/focus-sessions.md +47 -0
  237. package/skills/synap/governance-rules.md +64 -0
  238. package/skills/synap/governance.md +6 -6
  239. package/skills/synap/graph-gardening.md +21 -0
  240. package/skills/synap/inline-patterns.md +38 -0
  241. package/skills/synap/lenses.md +38 -0
  242. package/skills/synap/linking-principle.md +39 -0
  243. package/skills/synap/linking.md +1 -0
  244. package/skills/synap/mental-model.md +45 -0
  245. package/skills/synap/more.md +7 -0
  246. package/skills/synap/multi-entity-capture.md +12 -0
  247. package/skills/synap/next-action.md +37 -0
  248. package/skills/synap/north-star.md +17 -0
  249. package/skills/synap/operating-mode-rules.md +45 -0
  250. package/skills/synap/operating-mode.md +9 -0
  251. package/skills/synap/quick-reference.md +67 -0
  252. package/skills/synap/reading.md +43 -0
  253. package/skills/synap/recap.md +21 -0
  254. package/skills/synap/reflexes.md +46 -0
  255. package/skills/synap/response-style.md +21 -0
  256. package/skills/synap/scope.md +13 -0
  257. package/skills/synap/showing.md +17 -0
  258. package/skills/synap/user-model.md +25 -0
  259. package/skills/synap/viewframe-cells.md +290 -0
  260. package/skills/synap/work-flow.md +113 -0
  261. package/skills/synap/worked-examples.md +74 -0
  262. package/skills/synap/workspace-design.md +45 -0
  263. package/skills/synap/workspace-edges.md +49 -0
  264. package/skills/synap/writes.md +213 -0
  265. package/skills/synap-app/SKILL.md +319 -0
  266. package/skills/synap-app/_order.txt +5 -0
  267. package/skills/synap-app/_skill.yaml +20 -0
  268. package/skills/synap-app/creating-the-base-app.md +64 -0
  269. package/skills/synap-app/governance.md +42 -0
  270. package/skills/synap-app/install-commands.md +55 -0
  271. package/skills/synap-app/overview.md +50 -0
  272. package/skills/synap-app/using-the-sdk.md +73 -0
  273. package/skills/synap-market/SKILL.md +335 -0
  274. package/skills/synap-market/_order.txt +5 -0
  275. package/skills/synap-market/_skill.yaml +24 -0
  276. package/skills/synap-market/author-and-publish.md +75 -0
  277. package/skills/synap-market/discover-and-fetch.md +59 -0
  278. package/skills/synap-market/governance-and-catalog.md +56 -0
  279. package/skills/synap-market/install.md +55 -0
  280. package/skills/synap-market/overview.md +51 -0
  281. package/skills/synap-schema/SKILL.md +97 -6
  282. package/skills/synap-schema/_order.txt +13 -0
  283. package/skills/synap-schema/_skill.yaml +22 -0
  284. package/skills/synap-schema/before-you-touch.md +14 -0
  285. package/skills/synap-schema/common-mistakes.md +9 -0
  286. package/skills/synap-schema/creating-profiles.md +17 -0
  287. package/skills/synap-schema/discover-profiles.md +24 -0
  288. package/skills/synap-schema/entity-scope.md +8 -0
  289. package/skills/synap-schema/extend-vs-create.md +31 -0
  290. package/skills/synap-schema/more.md +6 -0
  291. package/skills/synap-schema/overlay-properties.md +22 -0
  292. package/skills/synap-schema/profiles.md +3 -0
  293. package/skills/synap-schema/property-defs.md +29 -0
  294. package/skills/synap-schema/read-before-write.md +50 -0
  295. package/skills/synap-schema/relations.md +18 -0
  296. package/skills/synap-schema/worked-example.md +30 -0
  297. package/skills/synap-ui/SKILL.md +26 -2
  298. package/skills/synap-ui/_order.txt +13 -0
  299. package/skills/synap-ui/_skill.yaml +23 -0
  300. package/skills/synap-ui/ai-companion.md +27 -0
  301. package/skills/synap-ui/arranging-bento.md +8 -0
  302. package/skills/synap-ui/before-you-build.md +20 -0
  303. package/skills/synap-ui/bento-layouts.md +35 -0
  304. package/skills/synap-ui/common-mistakes.md +10 -0
  305. package/skills/synap-ui/creating-views.md +26 -0
  306. package/skills/synap-ui/four-builds.md +24 -0
  307. package/skills/synap-ui/more.md +7 -0
  308. package/skills/synap-ui/proposing-vs-extending.md +11 -0
  309. package/skills/synap-ui/view-list.md +24 -0
  310. package/skills/synap-ui/views.md +3 -0
  311. package/skills/synap-ui/worked-example.md +18 -0
  312. package/skills/synap-ui/workspaces.md +47 -0
  313. package/templates/automations/bookmark-enrichment.automation.json +44 -0
  314. package/templates/automations/mail-feed.automation.json +86 -0
  315. package/templates/automations/url-bookmark-capture.automation.json +70 -0
  316. package/templates/skills/README.md +21 -0
  317. package/templates/skills/authoring-automations/SKILL.md +95 -0
  318. package/templates/skills/authoring-automations/reference/node-matrix.md +49 -0
  319. package/templates/skills/authoring-capabilities/SKILL.md +93 -0
  320. package/templates/skills/authoring-capabilities/reference/template-anatomy.md +70 -0
  321. package/templates/skills/authoring-playbooks/SKILL.md +102 -0
  322. package/templates/skills/authoring-playbooks/reference/stages-contract.md +35 -0
  323. package/templates/skills/authoring-playbooks/reference/worked-example.md +64 -0
  324. package/templates/skills/bookmark-enrichment/SKILL.md +40 -0
  325. package/templates/skills/coordinating-agents/SKILL.md +32 -0
  326. package/templates/skills/coordinating-branches/SKILL.md +27 -0
  327. package/templates/skills/mapping-the-server/SKILL.md +54 -0
  328. package/templates/skills/reading-client-progress/SKILL.md +65 -0
  329. package/templates/skills/routing-to-channels/SKILL.md +54 -0
  330. package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
  331. package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
  332. package/templates/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
  333. package/templates/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
  334. package/templates/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
  335. package/templates/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
  336. package/templates/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
  337. package/templates/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
  338. package/templates/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
  339. package/templates/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
  340. package/templates/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
  341. package/templates/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
  342. package/templates/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
  343. package/templates/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
  344. package/templates/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
  345. package/templates/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
  346. package/templates/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
  347. package/templates/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
  348. package/templates/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
  349. package/templates/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
  350. package/templates/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
  351. package/templates/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
  352. package/templates/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
  353. package/templates/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
  354. package/templates/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
  355. package/templates/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
  356. package/templates/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
  357. package/templates/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
  358. package/dist/commands/connectors.d.ts +0 -31
  359. package/dist/commands/connectors.js +0 -276
  360. package/dist/commands/connectors.js.map +0 -1
  361. package/dist/commands/finish.d.ts +0 -25
  362. package/dist/commands/finish.js +0 -274
  363. package/dist/commands/finish.js.map +0 -1
  364. package/dist/commands/openclaw.d.ts +0 -40
  365. package/dist/commands/openclaw.js +0 -1148
  366. package/dist/commands/openclaw.js.map +0 -1
  367. package/dist/commands/security-audit.d.ts +0 -12
  368. package/dist/commands/security-audit.js +0 -100
  369. package/dist/commands/security-audit.js.map +0 -1
  370. package/dist/lib/hardening.d.ts +0 -18
  371. package/dist/lib/hardening.js +0 -214
  372. package/dist/lib/hardening.js.map +0 -1
@@ -0,0 +1,27 @@
1
+ ## AI Companion integration
2
+
3
+ When you create views or entities for the user inside the AI Companion, **always emit inline pattern chips** at the end of your reply so the user can jump directly to what you built.
4
+
5
+ ```
6
+ // After creating a kanban view with ID "abc123":
7
+ "Created your tasks pipeline → [[view:abc123|Active Tasks]] · [[open:side|view:abc123]]"
8
+
9
+ // After creating a workspace (home bento view ID "def456"):
10
+ "Workspace ready — [[open:main|view:def456|Home Dashboard]]"
11
+
12
+ // After creating an entity (e.g. a new project):
13
+ "Project created → [[entity:proj_789|Q3 Launch]]"
14
+ ```
15
+
16
+ ### Special cell keys (browser-native)
17
+
18
+ These cell keys are registered in the browser app but may not appear in `GET /api/hub/widget-definitions` (they are Electron-native, not server-seeded):
19
+
20
+ | Cell key | Where | Notes |
21
+ | --------------- | ------------------ | ------------------------------------------------------------ |
22
+ | `ai-companion` | Browser sidebar | The Companion chat panel itself — don't embed in bentos |
23
+ | `iframe-widget` | Bento blocks | Sandboxed iframe for custom embeds; requires `src` in config |
24
+ | `entity-detail` | Side panel / modal | Generic entity detail renderer — always available |
25
+ | `entity-list` | Bento / views | List of entities for a given profile |
26
+
27
+ **Rule:** If a cell key is not in `GET /api/hub/widget-definitions`, do NOT reference it in bento config unless it is one of the four browser-native keys above. Unknown keys will silently fail to render.
@@ -0,0 +1,8 @@
1
+ ## Arranging a bento after creation
2
+
3
+ ```json
4
+ POST /api/hub/views/{bentoViewId}/arrange
5
+ { "userId": "{userId}", "blocks": [ /* full new blocks array */ ] }
6
+ ```
7
+
8
+ `bento.arrange` is auto-approved by default. Safe to run without hesitation when the user rearranges or adds widgets.
@@ -0,0 +1,20 @@
1
+ ## Before you build anything
2
+
3
+ Always inventory. Never hallucinate view types, widget kinds, or profiles.
4
+
5
+ ```
6
+ GET /api/hub/manifest
7
+ → static capability map: view types, bento block kinds, inline patterns, browser-native cells
8
+ (call once per session — no DB queries, safe to cache)
9
+
10
+ GET /api/hub/profiles?userId={userId}&workspaceId={workspaceId}
11
+ → what data exists
12
+
13
+ GET /api/hub/widget-definitions?workspaceId={workspaceId}
14
+ → [{ kind, category, label, description, configSchema, supportedContexts }]
15
+
16
+ GET /api/hub/views?userId={userId}&workspaceId={workspaceId}
17
+ → [{ id, name, type, profileSlug, config }]
18
+ ```
19
+
20
+ Widget definitions are the source of truth for which cells are installed and how to configure them. **Never guess cell kinds.** If a cell doesn't appear in the registry, don't reference it (unless it's a browser-native cell from the manifest).
@@ -0,0 +1,35 @@
1
+ ## Bento layouts
2
+
3
+ A bento is a 12-column react-grid-layout. Blocks reference **cells** by kind.
4
+
5
+ ```json
6
+ POST /api/hub/views // a bento is just a view with type="bento"
7
+ {
8
+ "userId": "{userId}",
9
+ "workspaceId": "{workspaceId}",
10
+ "name": "Content Creation Home",
11
+ "type": "bento",
12
+ "config": {
13
+ "blocks": [
14
+ { "id": "b1", "kind": "view", "viewId": "<kanbanId>",
15
+ "layout": { "x": 0, "y": 0, "w": 8, "h": 4 } },
16
+ { "id": "b2", "kind": "entity", "entityId": "ent_current_project",
17
+ "layout": { "x": 8, "y": 0, "w": 4, "h": 4 } },
18
+ { "id": "b3", "kind": "widget", "widgetKind": "quick-access",
19
+ "layout": { "x": 0, "y": 4, "w": 6, "h": 2 },
20
+ "config": { "items": [ … ] } },
21
+ { "id": "b4", "kind": "widget", "widgetKind": "stat-card",
22
+ "layout": { "x": 6, "y": 4, "w": 6, "h": 2 },
23
+ "config": { "metric": "entities_created_this_week" } }
24
+ ]
25
+ }
26
+ }
27
+ ```
28
+
29
+ Block kinds:
30
+
31
+ - `view` — embeds a saved view by `viewId`
32
+ - `entity` — renders an entity card for a specific `entityId`
33
+ - `widget` — renders a registered cell by `widgetKind` with `config`
34
+
35
+ Full widget catalog in **`widget-catalog.md`**. Layout patterns in **`bento-recipes.md`**.
@@ -0,0 +1,10 @@
1
+ ## Common mistakes — UI generation
2
+
3
+ 1. **Creating a workspace without asking.** Always propose + confirm. Workspaces are too big to auto-commit.
4
+ 2. **Guessing widget kinds.** Always `GET /widget-definitions` first. A `kind` that isn't in the registry won't render.
5
+ 3. **Reinventing views.** Check existing views first — a kanban for tasks probably exists.
6
+ 4. **Creating a new profile when UI is the real need.** Don't create `client` profile for a "contacts who are clients" view — just create a filtered view on `contact`.
7
+ 5. **Putting unrelated data in one bento.** A bento tells a story ("my week", "this project", "content pipeline"). Kitchen-sink bentos overwhelm the user.
8
+ 6. **Ignoring color/icon.** Profiles and workspaces both take `uiHints.icon` and `uiHints.color` — set them. Untitled gray workspaces feel like a bug.
9
+ 7. **Hardcoding config for view types you haven't checked.** Each view type's `config` shape is different. Get an example from `/views` first.
10
+ 8. **Forgetting entityScope implications.** A view on a pod-scope profile (`note`) will show entities from every workspace the user can access — filter appropriately if you want workspace-local results.
@@ -0,0 +1,26 @@
1
+ ## Creating a view
2
+
3
+ ```json
4
+ POST /api/hub/views
5
+ {
6
+ "userId": "{userId}",
7
+ "workspaceId": "{workspaceId}",
8
+ "name": "Active Tasks by Project",
9
+ "type": "kanban",
10
+ "profileSlug": "task",
11
+ "config": {
12
+ "groupBy": { "property": "projectId" },
13
+ "columns": [
14
+ { "slug": "title" },
15
+ { "slug": "priority" },
16
+ { "slug": "dueDate" }
17
+ ],
18
+ "filters": [
19
+ { "property": "status", "op": "in", "value": ["todo", "in-progress"] }
20
+ ],
21
+ "sort": [{ "property": "priority", "direction": "desc" }]
22
+ }
23
+ }
24
+ ```
25
+
26
+ The `config` shape varies by view type — kanban needs `groupBy`, calendar needs a date property, gallery needs an image property. When in doubt, fetch an existing view of the same type first and mirror its structure.
@@ -0,0 +1,24 @@
1
+ ## Four things you can build
2
+
3
+ 1. **Views** — named queries + rendering config over entities of a given profile. Kanban of tasks, gallery of articles, calendar of events.
4
+ 2. **Bento dashboards** — 12-col grid compositions of cells (view-cards, entity-cards, widgets). The Home dashboard is a bento. Workspace landing pages are bentos.
5
+ 3. **Workspaces** — full lenses with profiles, views, a bento, and seed entities. The biggest building block.
6
+ 4. **New cell types** (Capability B) — AI can define entirely new rendering cells when no existing widget covers the need. Cells run in a sandboxed iframe. Pod-global cells (no `workspaceId`) are available immediately in all workspaces without a proposal step.
7
+
8
+ ```json
9
+ POST /api/hub/cells/define
10
+ {
11
+ "name": "Burndown Chart",
12
+ "rendererSource": "<!DOCTYPE html>…</html>",
13
+ "typeKey": "burndown-chart",
14
+ "description": "Sprint burndown over task completions",
15
+ "defaultSize": { "w": 8, "h": 6 },
16
+ "deps": {
17
+ "recharts": "2.12.0"
18
+ }
19
+ }
20
+ ```
21
+
22
+ - `deps` pins npm packages for the esm.sh import map. Keys are npm package names; values are version strings. Max 30 entries. React 19 is always available — never put it in `deps`.
23
+ - Always `GET /api/hub/widget-definitions` first — if a cell already covers the need, use it. New cell definitions are permanent; only create when genuinely novel.
24
+ - For the full in-frame query/mutate/shell-actions API see the `synap` skill's **ViewFrame Cells** section (or load `synap-ui:SKILL` via `GET /api/hub/skills/system?sections=synap-ui:SKILL`).
@@ -0,0 +1,7 @@
1
+ ## When you need more — UI generation
2
+
3
+ - Full per-view-type `config` shapes → **`view-types.md`**
4
+ - Complete widget/cell catalog + configSchemas → **`widget-catalog.md`**
5
+ - Ready-to-reuse bento layouts for common use cases → **`bento-recipes.md`**
6
+ - Creating the underlying data → use core **`synap`** skill
7
+ - Extending profiles with new fields before building views → use **`synap-schema`** skill
@@ -0,0 +1,11 @@
1
+ ## Proposing vs. extending
2
+
3
+ Before proposing a new workspace, ask: does one of the user's existing workspaces fit? A "Content" workspace and a "Writing" workspace are the same lens. Adding a view to the existing workspace is almost always better than creating a new one.
4
+
5
+ Create new when:
6
+
7
+ - The user explicitly asks for it ("new workspace for…")
8
+ - The data and access patterns are genuinely orthogonal to existing workspaces
9
+ - A different team/collaborator set makes sense
10
+
11
+ Otherwise: add a view, add a bento block, add properties — don't multiply workspaces.
@@ -0,0 +1,24 @@
1
+ ## View types (16 total, 12 implemented)
2
+
3
+ Pick one that matches the data's shape AND the user's intent:
4
+
5
+ | Type | Implemented | When it fits |
6
+ | ---------------- | ----------- | ---------------------------------------------------------- |
7
+ | `table` | yes | Dense data, many columns, sort/filter heavy |
8
+ | `list` | yes | Scan-friendly, compact rows (tasks, notes) |
9
+ | `grid` | yes | Card grid, medium density |
10
+ | `gallery` | yes | Image-forward cards (articles, bookmarks, products) |
11
+ | `kanban` | yes | Status pipelines (tasks by status, deals by stage) |
12
+ | `matrix` | yes | 2-axis grid (priority × urgency, effort × impact) |
13
+ | `masonry`/`feed` | yes | Pinterest-style, mixed-size cards; default for Library |
14
+ | `calendar` | yes | Date-indexed data (events, tasks by dueDate) |
15
+ | `flow` | yes | Node-edge diagrams (automations, mind maps) |
16
+ | `bento` | yes | Mixed composition (a dashboard-in-view) |
17
+ | `branch_tree` | yes | Hierarchical data (project → subtasks, threads → branches) |
18
+ | `whiteboard` | yes | Free-form canvas |
19
+ | `timeline` | no | (Defer) |
20
+ | `graph` | no | (Defer) |
21
+ | `gantt` | no | (Defer) |
22
+ | `mindmap` | no | (Defer) |
23
+
24
+ Decision: the data has statuses → `kanban`. Dates → `calendar`. Many columns → `table`. Mixed types → `masonry` or `bento`. Full reference in **`view-types.md`**.
@@ -0,0 +1,3 @@
1
+ # Synap — UI generation
2
+
3
+ You build the surfaces the user sees: views over their data, bento dashboards, full workspaces tuned for a domain. The core rule: **emergent complexity.** A workspace is a lens; a view is a lens; a bento is a composition of lenses. Everything renders through the cell system, nothing is hardcoded.
@@ -0,0 +1,18 @@
1
+ ## Worked example — "Make me a CRM"
2
+
3
+ 1. Inventory. User already has `person`, `contact`, `company`, `deal`, `event` profiles (all system).
4
+ 2. No new profiles needed. The CRM is a **lens**, not new data.
5
+ 3. Propose (before committing):
6
+ - Workspace name: "CRM"
7
+ - Views:
8
+ - `Deals Pipeline` — kanban on `deal`, groupBy `stage`
9
+ - `Contacts` — table on `contact`, columns: name, role, company, lastInteraction
10
+ - `Companies` — gallery on `company` (logo-forward)
11
+ - `Upcoming Meetings` — calendar on `event`, filter `relatedToContact`
12
+ - Bento:
13
+ - Top: `deals pipeline` view (8 cols × 4 rows)
14
+ - Side: `stat-card` — "Deals in pipeline: $X" (4 cols × 2 rows)
15
+ - Side: `stat-card` — "Meetings this week: N" (4 cols × 2 rows)
16
+ - Bottom: `recent-activity` widget (12 cols × 3 rows)
17
+ 4. Show to user. Confirm.
18
+ 5. Commit via `POST /workspaces`.
@@ -0,0 +1,47 @@
1
+ ## Creating or proposing a workspace
2
+
3
+ **Always ask before creating.** Workspaces are big objects with profiles, views, members, bento, and seed data. Commit only after user confirms.
4
+
5
+ The canonical flow:
6
+
7
+ 1. **Assemble a proposal** (no API call yet):
8
+
9
+ ```js
10
+ const proposal = {
11
+ name: "Content Creation",
12
+ description: "Draft, review, and publish articles",
13
+ icon: "pen-tool",
14
+ color: "purple",
15
+ profiles: [ // reuse system profiles by slug OR include custom ones
16
+ { slug: "article", reuse: true },
17
+ { slug: "draft", displayName: "Draft", parentSlug: "article",
18
+ properties: [
19
+ { slug: "status", valueType: "string", constraints: { enum: ["idea","writing","review","published"] }, uiHints: { displayAs: "status" } },
20
+ { slug: "wordCount", valueType: "number" },
21
+ { slug: "publishDate", valueType: "date" }
22
+ ]
23
+ }
24
+ ],
25
+ views: [
26
+ { name: "Pipeline", type: "kanban", profileSlug: "draft",
27
+ config: { groupBy: { property: "status" } } },
28
+ { name: "Published", type: "gallery", profileSlug: "article",
29
+ config: { filters: [{ property: "status", op: "eq", value: "published" }] } }
30
+ ],
31
+ bento: { blocks: [ … ] },
32
+ seedEntities: [] // optional
33
+ }
34
+ ```
35
+
36
+ 2. **Show it to the user**. Compact, readable. "Here's what I'd create — 2 profiles, 2 views, a bento. Ship it?"
37
+
38
+ 3. **On yes**, commit through `/api/hub/workspaces`:
39
+
40
+ ```json
41
+ POST /api/hub/workspaces
42
+ { "userId": "{userId}", "proposal": { /* the object above */ } }
43
+ ```
44
+
45
+ This goes through governance — `workspace.create` is **always** proposal-gated even for agents (see `../synap/governance.md`). Expect `status: "proposed"` and tell the user they'll see it in Proposals.
46
+
47
+ 4. **On no**, don't commit. Offer to adjust.
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "Bookmark Enrichment (auto)",
3
+ "triggerType": "event",
4
+ "status": "active",
5
+ "triggerConfig": {
6
+ "eventPattern": "entity.create.completed",
7
+ "filters": { "profileSlug": "bookmark" }
8
+ },
9
+ "flowDefinition": {
10
+ "nodes": [
11
+ {
12
+ "id": "trigger",
13
+ "type": "trigger",
14
+ "position": { "x": 0, "y": 0 },
15
+ "data": {
16
+ "triggerType": "event",
17
+ "label": "Bookmark created",
18
+ "config": {
19
+ "eventPattern": "entity.create.completed",
20
+ "filters": { "profileSlug": "bookmark" }
21
+ }
22
+ }
23
+ },
24
+ {
25
+ "id": "enrich",
26
+ "type": "skill",
27
+ "position": { "x": 0, "y": 120 },
28
+ "data": {
29
+ "label": "Bookmark Enrichment",
30
+ "skillName": "bookmark-enrichment",
31
+ "skillTitle": "Bookmark Enrichment",
32
+ "inputMapping": {
33
+ "entityId": "{{trigger.payload.subjectId}}"
34
+ }
35
+ }
36
+ }
37
+ ],
38
+ "edges": [{ "id": "e1", "source": "trigger", "target": "enrich" }]
39
+ },
40
+ "metadata": {
41
+ "source": "bridge-template",
42
+ "note": "The skill node carries `skillName`; the CLI seed command resolves it to the live `skillId` at install time (GET /skills by name)."
43
+ }
44
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "Mail feed → Discord (AI-triaged)",
3
+ "triggerType": "cron",
4
+ "status": "draft",
5
+ "triggerConfig": { "expression": "0 */2 * * *" },
6
+ "flowDefinition": {
7
+ "nodes": [
8
+ {
9
+ "id": "trigger",
10
+ "type": "trigger",
11
+ "position": { "x": 0, "y": 0 },
12
+ "data": {
13
+ "triggerType": "cron",
14
+ "label": "Every 2 hours",
15
+ "config": { "expression": "0 */2 * * *" }
16
+ }
17
+ },
18
+ {
19
+ "id": "fetch-mail",
20
+ "type": "capability",
21
+ "position": { "x": 0, "y": 120 },
22
+ "data": {
23
+ "label": "Search Gmail (source verb)",
24
+ "verbId": "gmail_search",
25
+ "inputMapping": { "query": "newer_than:2d", "maxResults": "25" },
26
+ "connectionSelector": { "connectionId": "" }
27
+ }
28
+ },
29
+ {
30
+ "id": "triage",
31
+ "type": "capability",
32
+ "position": { "x": 0, "y": 240 },
33
+ "data": {
34
+ "label": "AI triage (batch classifier verb)",
35
+ "verbId": "ai.triage",
36
+ "inputMapping": { "emails": "{{steps.fetch-mail.output.results}}" }
37
+ }
38
+ },
39
+ {
40
+ "id": "relevant-loop",
41
+ "type": "loop",
42
+ "position": { "x": 0, "y": 360 },
43
+ "data": {
44
+ "label": "For each relevant email",
45
+ "iteratorExpression": "steps.triage.output.results",
46
+ "itemVariable": "email"
47
+ }
48
+ },
49
+ {
50
+ "id": "post-to-feed",
51
+ "type": "output",
52
+ "position": { "x": 0, "y": 480 },
53
+ "data": {
54
+ "label": "Post to the Discord-bound feed channel",
55
+ "outputType": "channel_message",
56
+ "config": {
57
+ "channelId": "<discord-bound team feed channel id>",
58
+ "content": "**{{loop.item.subject}}** — _{{loop.item.category}}_\n{{loop.item.summary}}",
59
+ "channelType": "proactive",
60
+ "metadata": {
61
+ "proactiveType": "mail-feed",
62
+ "gmailId": "{{loop.item.id}}"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ ],
68
+ "edges": [
69
+ { "id": "e1", "source": "trigger", "target": "fetch-mail" },
70
+ { "id": "e2", "source": "fetch-mail", "target": "triage" },
71
+ { "id": "e3", "source": "triage", "target": "relevant-loop" },
72
+ { "id": "e4", "source": "relevant-loop", "target": "post-to-feed" }
73
+ ]
74
+ },
75
+ "metadata": {
76
+ "source": "feed-template",
77
+ "purpose": "CANONICAL example of the North Star: a FEED is an AUTOMATION that composes capability verbs. Cron → gmail_search (source verb) → AI triage (classifier verb) → loop → post relevant items to a Discord-bound feed channel. Replaces the bespoke run-mail-feed.ts worker with pure config.",
78
+ "prerequisites": [
79
+ "Wave 1 (SHIPPED): the `capability` node dispatches gmail_search (declarative) + any verb through executeCapability.",
80
+ "verb `ai.triage`: a batch email classifier verb must be seeded (today this is the mail_triage IS route; roadmap folds it into a verb). Until then, swap the triage node for a `command` node (IS task) or point verbId at the seeded classifier.",
81
+ "a connected Google account (nango-google) + set connectionSelector.connectionId to pin the mailbox.",
82
+ "a Discord-bound `branchPurpose:'team'` feed channel — put its id in the post node (or use channelType:'proactive' for the user's feed).",
83
+ "PER-ITEM filtering/AI inside the loop needs automation Wave 2 (loop body currently allows `output` only — this template does BATCH triage OUTSIDE the loop and posts via an `output.channel_message` node INSIDE the loop, which IS loop-allowed today)."
84
+ ]
85
+ }
86
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "URL → Bookmark (inbound messages)",
3
+ "triggerType": "event",
4
+ "status": "active",
5
+ "triggerConfig": {
6
+ "eventPattern": "external_message.received.*",
7
+ "filters": { "provider": "discord" }
8
+ },
9
+ "flowDefinition": {
10
+ "nodes": [
11
+ {
12
+ "id": "trigger",
13
+ "type": "trigger",
14
+ "position": { "x": 0, "y": 0 },
15
+ "data": {
16
+ "triggerType": "event",
17
+ "label": "Inbound message",
18
+ "config": {
19
+ "eventPattern": "external_message.received.*",
20
+ "filters": { "provider": "discord" }
21
+ }
22
+ }
23
+ },
24
+ {
25
+ "id": "extract",
26
+ "type": "transform",
27
+ "position": { "x": 0, "y": 120 },
28
+ "data": {
29
+ "label": "Extract URLs",
30
+ "expression": "{{trigger.payload.data.content}} | url_extract"
31
+ }
32
+ },
33
+ {
34
+ "id": "url-loop",
35
+ "type": "loop",
36
+ "position": { "x": 0, "y": 240 },
37
+ "data": {
38
+ "label": "For each URL",
39
+ "iteratorExpression": "steps.extract.output.result",
40
+ "itemVariable": "url"
41
+ }
42
+ },
43
+ {
44
+ "id": "create-bookmark",
45
+ "type": "output",
46
+ "position": { "x": 0, "y": 360 },
47
+ "data": {
48
+ "label": "Create bookmark",
49
+ "outputType": "entity_create",
50
+ "config": {
51
+ "profileSlug": "bookmark",
52
+ "title": "{{loop.item}}",
53
+ "dedupeBy": "url",
54
+ "properties": {
55
+ "url": "{{loop.item}}",
56
+ "sourceMessageId": "{{trigger.payload.data.messageId}}",
57
+ "sourceChannelId": "{{trigger.payload.data.threadId}}"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ ],
63
+ "edges": [
64
+ { "id": "e1", "source": "trigger", "target": "extract" },
65
+ { "id": "e2", "source": "extract", "target": "url-loop" },
66
+ { "id": "e3", "source": "url-loop", "target": "create-bookmark" }
67
+ ]
68
+ },
69
+ "metadata": { "source": "bridge-template" }
70
+ }
@@ -0,0 +1,21 @@
1
+ # CLI-bundled skills (`synap skill add bundled`)
2
+
3
+ This directory must NOT hold hand-authored copies of the backend **SSOT** skills.
4
+ The pod's baseline skills already reach every pod two other ways:
5
+
6
+ - **Auto-seeded** on pod boot by `ensureSystemSkills()` (backend `skills/` → `system/*` rows).
7
+ - Shipped as **Agent-Skills packages** by `scripts/sync-skills.sh` (→ `synap-cli/skills/`).
8
+
9
+ Duplicating them here is what drifted (e.g. an old CRM `digesting-a-channel`), so the
10
+ 15 SSOT-covered skills were retired from this bundle.
11
+
12
+ What remains here, and why:
13
+ - **CLI/agent-runtime skills** (`coordinating-*`, `authoring-*`) — genuine runtime
14
+ concerns with no SSOT counterpart. Hand-authored; this is their home.
15
+ - **Agency/domain skills** (`stellar-scf-grants-advisor` + its reference corpus,
16
+ `mapping-the-server`, `routing-to-channels`, `bookmark-enrichment`,
17
+ `reading-client-progress`) — these belong in the **CP capability templates** and
18
+ are applied via `/capabilities/apply` (see `bridge-setup` AGENCY plan). They stay
19
+ bundled here TEMPORARILY until CP gains reference-corpus support (`documents[]`/
20
+ `referenceDir`) so the stellar corpus survives the move. Do not add new SSOT-style
21
+ skills here.
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: authoring-automations
3
+ description: Authors a Synap Automation — the WHEN→THEN flow engine (triggers, nodes, data flow). Use whenever the user wants something to happen automatically: "every morning do X", "when a Y is created then Z", "poll this source and create entities", "fan out a list into records", "post to a channel when…", or asks to build/edit an automation flow. Also use when designing the trigger half of a playbook (the WHEN that fires a process).
4
+ ---
5
+
6
+ # Authoring Automations
7
+
8
+ A **Synap Automation** is a WHEN→THEN flow: a **trigger** fires, then a graph of **nodes** runs. It is how recurring work happens without a human in the loop. This skill encodes the VERIFIED capability matrix — the triggers, the nodes, the data-flow grammar, the canonical recipes, and the one firewall gotcha that will bite you.
9
+
10
+ Read `reference/node-matrix.md` for the exhaustive per-node field reference. Keep flows small: trigger → a couple of steps. Don't over-engineer the first version.
11
+
12
+ ## The template format
13
+
14
+ Automation templates live at `synap-backend/templates/automations/*.automation.json`:
15
+
16
+ ```jsonc
17
+ {
18
+ "name": "URL → Bookmark (inbound messages)",
19
+ "triggerType": "event",
20
+ "status": "active",
21
+ "triggerConfig": { "eventPattern": "external_message.received.*", "filters": { "provider": "discord" } },
22
+ "flowDefinition": {
23
+ "nodes": [ /* each: { id, type, position, data } */ ],
24
+ "edges": [ /* each: { id, source, target } */ ]
25
+ },
26
+ "metadata": { "source": "bridge-template" }
27
+ }
28
+ ```
29
+
30
+ The canonical `url-bookmark-capture` shape is: **message trigger → transform (`url_extract`) → loop → entity_create (with `dedupeBy`)**. That is the reference for any "extract items from input, create one entity each" flow.
31
+
32
+ ## Triggers (4)
33
+
34
+ | Trigger | Config | Fires when |
35
+ |---|---|---|
36
+ | `cron` | `{ expression: "0 9 * * *" }` | The pod-wide scheduler matches (it polls every minute, so minute granularity). |
37
+ | `event` | `{ eventPattern: "entities.*" \| "focus_session.stage_changed.*" \| …, filters }` | A matching domain event is emitted. |
38
+ | `webhook` | `{ webhookSubscriptionId }` | An inbound webhook hits the subscription. |
39
+ | `manual` | — | A user/agent runs it on demand. |
40
+
41
+ ## Nodes (14)
42
+
43
+ `trigger`, `command`, `condition`, `delay`, `output`, `loop`, `transform`, `fetch`, `query`, `switch`, `skill`, `capability`, `sub_automation`, `playbook_run`. Full fields in `reference/node-matrix.md`. The load-bearing ones:
44
+
45
+ - **command** — free-form AI step via the Intelligence Service. Powerful but UNTYPED — strongly prefer a `skill` for structured extraction. A `command` feeding a `loop` is a best-effort fallback only (ship `status: "draft"` + a reliability caveat; see below).
46
+ - **output** — the side-effect node. Subtypes: `entity_create` (`{ profileSlug, title, dedupeBy, properties }`; governed + empty/dup-guarded; **`dedupeBy` is a SINGLE key**), `entity_update`, `webhook` (POST to an arbitrary URL with vault headers), `notification`, `channel_message`.
47
+ - **loop** — iterate an array (cap 100). Its iterator is resolved **RAW** (not stringified) so it works on real arrays.
48
+ - **transform** — `uppercase` \| `lowercase` \| `json` \| `trim` \| `url_extract`.
49
+ - **fetch** — HTTP (30s timeout, vault headers, auto-JSON-parses the body).
50
+ - **skill** — run an IS skill (gated). The right tool for **structured extraction** (returns typed data).
51
+ - **capability** — run a capability verb → resolves to a skill (gated).
52
+ - **sub_automation** — call another automation (depth limit 5).
53
+ - **playbook_run** — start a playbook from a flow.
54
+
55
+ ## Data flow grammar
56
+
57
+ - `{{trigger.payload.x}}` — fields off the trigger event.
58
+ - `{{steps.<nodeId>.output.x}}` — output of a prior node by id.
59
+ - `{{loop.item}}` / `{{loop.index}}` — inside a loop body.
60
+
61
+ **Lossy stringify gotcha:** `resolveTemplate` STRINGIFIES values — fine for strings, **lossy for objects/arrays**. Two paths resolve RAW instead: the **loop iterator** (`iteratorExpression`) and **transform** input. So: build arrays/objects with those raw-path nodes; use `{{…}}` interpolation only where a string is wanted.
62
+
63
+ **Canonical fan-out:** a `skill` returns `{ items: [...] }` → `loop` over `steps.<skill>.output.items` → `entity_create` per `{{loop.item}}`. This is the backbone of every "source → many entities" automation.
64
+
65
+ ## The canonical "external source → calendar" recipe
66
+
67
+ ```
68
+ cron (0 7 * * *)
69
+ → fetch (GET the source URL)
70
+ → skill (structured extraction → returns { events: [...] })
71
+ → loop (iterator: steps.extract.output.events)
72
+ → entity_create (profileSlug: "event", dedupeBy: "externalId", properties from {{loop.item}})
73
+ ```
74
+
75
+ **Strongly prefer a skill for structured extraction.** A purpose-built `skill` (like `bookmark-enrichment`) returns typed, reliable structured data you can fan out — that is the path to reach for. A free-form `command` is NOT schema-typed; its IS task output shape is not guaranteed, so a `loop` over it is BEST-EFFORT and may resolve to `[]`. A `command → loop` is an explicit FALLBACK — use it only when no skill or JSON source exists, and when you do, ship the automation `status: "draft"` with a reliability caveat noting the output shape isn't guaranteed. Do not present command-based extraction as reliable.
76
+
77
+ ## THE FIREWALL GOTCHA (critical)
78
+
79
+ **`channel_message` does NOT relay to Discord.** It only inserts an internal `messages` row. To reach Discord from an automation you must use a **`webhook` node → Discord webhook URL**.
80
+
81
+ **BUT** that webhook path **bypasses the team-vs-client-comms firewall.** So:
82
+
83
+ - Posting to an internal **team** channel via webhook: acceptable.
84
+ - Posting to anything **client-linked** (a `client-comms` channel, mirrored to the client): **NEVER via an automation webhook.** It must go through the bridge's `proactive_post` / `route_to_channel` path, which enforces the firewall. An automation that webhooks into a client channel leaks bot activity to the client.
85
+
86
+ When in doubt, route client-facing posts through the bridge, never an automation.
87
+
88
+ ## Authoring checklist
89
+
90
+ 1. Pick the **trigger** (cron / event / webhook / manual) and its config.
91
+ 2. Sketch the smallest node chain that does the job.
92
+ 3. For structured extraction → strongly prefer a `skill`. A `command → loop` is a best-effort fallback only — ship it `status: "draft"` with a reliability caveat (output shape not guaranteed; the loop may resolve `[]`).
93
+ 4. Fan out with `skill → loop → entity_create` + a `dedupeBy` key (idempotency).
94
+ 5. Reaching Discord? `webhook` node — and if the target is client-linked, route through the bridge instead.
95
+ 6. Write it as `{ name, triggerType, status, triggerConfig, flowDefinition: { nodes, edges }, metadata }`.