@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
@@ -27,6 +27,8 @@ metadata:
27
27
 
28
28
  You extend a user's Synap pod schema: new entity profiles, new properties on existing profiles, overlay properties scoped to one workspace. The core rule: **reuse before extending.** Creating duplicate profiles fractures the graph.
29
29
 
30
+ ---
31
+
30
32
  ## Before you touch anything
31
33
 
32
34
  Always inventory first. Never assume the schema is empty.
@@ -42,6 +44,61 @@ GET /api/hub/property-defs?userId={userId}&workspaceId={workspaceId}&profileId={
42
44
 
43
45
  The `synap` skill's `scripts/orient.sh` already fetches profiles — reuse its output.
44
46
 
47
+ ---
48
+
49
+ ## Read before you write
50
+
51
+ Synap data is a typed graph — never write blind. Before creating or updating an
52
+ entity, work the loop the same way you'd read a file before editing it:
53
+
54
+ 1. **MAP** — know what types exist: `list_profiles` (the cheap map of entity
55
+ profiles), `list_views` for views.
56
+ 2. **SEARCH** — `search_unified({ query: <title>, collections: ["entities"] })`.
57
+ If a close match exists, LINK to it (relation or entity_id property) — do NOT
58
+ create a duplicate. Create only when there is genuinely no match.
59
+ 3. **READ THE SCHEMA** — before writing to a profile you haven't inspected this
60
+ session, call `get_profile({ slug })` for its real property defs (exact keys,
61
+ value types, enum options, link targets). For views, read the config
62
+ (`get_bento_schema`) before `create_view`.
63
+ 4. **WRITE INTO THE REAL FIELDS** — map each value to its correct typed property:
64
+ right `key`, valid `valueType` (dates as ISO, numbers as numbers), enum values
65
+ that satisfy the constraint, links via the property's `linksTo` target. Don't
66
+ invent property keys. A value with no matching property goes into
67
+ description/content, or propose a new one with `create_property_def` — never
68
+ drop it into a stray key.
69
+ 5. **CONNECT** — every new entity links to at least one other. Duplicates and
70
+ orphans are the two ways the graph degrades; avoid both.
71
+
72
+ ## Complete intent, governed outcome
73
+
74
+ `title` + `content` is only a minimum payload, not Synap's data model. Once
75
+ you have read the schema, send the complete intent that is known: `profileSlug`,
76
+ title, typed `properties`, short `description`, long-form `content`, an existing
77
+ `projectId`, links, and source/session provenance. Include role `facets` in the
78
+ same composite plan whenever they must be reviewed with the entity.
79
+
80
+ - **One entity with known fields and no creation-time role change** → use
81
+ `create_entity` / `POST /entities`.
82
+ - **Several entities, facets, or relations that belong in one review** → use the
83
+ composite graph/capture-plan door, never a loose sequence of creates.
84
+ - **Raw input whose structure is unknown** → use capture to produce a plan;
85
+ preserve an original file with `keepRaw` when supplied. Raw source is not the
86
+ same thing as an entity's edited content.
87
+
88
+ Workspace is an explicit lens: omit it to read the pod/base schema and let the
89
+ profile's placement rule apply. Pass a workspace only when the user or a
90
+ reviewed routing decision actually selected it; then its overlays are valid.
91
+ Never fill it from a configured/default workspace.
92
+
93
+ Read the write receipt before continuing. `pending` means a proposal exists and
94
+ no entity has materialized; `applied` means the reported operations completed;
95
+ `partial` means independent follow-up operations failed and must be repaired or
96
+ surfaced. Do not send a speculative second update merely because a write
97
+ completed — enrich only when you learned genuinely new information or the
98
+ receipt identifies a specific missing field.
99
+
100
+ ---
101
+
45
102
  ## Discover profiles — never assume
46
103
 
47
104
  **Always call `GET /api/hub/profiles?workspaceId={workspaceId}` first.** Profiles are dynamic — every pod and workspace has a different set depending on what was seeded and what the user created. Never assume a profile slug exists without verifying.
@@ -67,21 +124,41 @@ Custom workspace templates (devplane, content, etc.) add their own profiles enti
67
124
 
68
125
  Before creating a new profile: **does one of these already fit?** A podcast episode is arguably an `article`. A meeting is an `event`. A book to read is an `article` or `bookmark`. Err on the side of reuse + extension, not creation.
69
126
 
70
- ## When to extend an existing profile vs. create a new one
127
+ ---
128
+
129
+ ## When to extend an existing profile vs. create a new one vs. attach a facet
130
+
131
+ There are three moves, not two. Before extending or creating, ask whether the thing is really a **role** the entity plays rather than a new kind of entity at all — that's a facet, and it's the move people skip.
132
+
133
+ **Kind + Facets, the rule:** one entity = one kind (`profiles.profileKind = 'kind'`). Roles the entity plays — client, partner, investor, prospect — are role-profiles (`profileKind = 'role'`, `applicableKinds[]`) attached via `entity_facets`: additive, workspace-lensed, NOT entities. A facet cascades with its parent entity; only promote a role to a full kind if it accrues its own independent life.
134
+
135
+ **The litmus test:**
136
+
137
+ - Both sides of a connection are independently-alive kinds → it's a **relation** (e.g. person "works at" company — two entities, linked).
138
+ - One side is just wearing a hat with no independent lifecycle → it's a **facet** (e.g. "client" on a company — attach the role, don't create a new entity).
139
+ - The connection itself accrues its own multi-entity lifecycle (stages, money, deadlines, outcomes) → it gets **promoted to its own kind**. `deal` is the precedent: a buyer × seller × stage relationship-thing has its own life (pipeline stage, amount, close date) independent of either party, so it's kept as a primary kind, never a facet.
140
+
141
+ Attach when:
142
+
143
+ - The thing is a role/hat the entity is wearing (client, partner, investor, prospect, sponsor) — it has no properties or lifecycle independent of the parent entity
144
+ - AI-driven creation: resolve identity FIRST (strong signals — email, phone, url) before creating anything; if the entity already exists, `attach_facet` the new role onto it — never spin up a second entity for a hat
71
145
 
72
146
  Extend when:
73
147
 
74
- - The thing fits an existing category (a "client" is a kind of `contact` — consider inheritance)
148
+ - The thing fits an existing category (a `client` **facet** is the role; if you instead need a distinct persisted sub-kind with its own fields, consider inheritance)
75
149
  - The user needs 1–3 extra fields on an existing type
76
150
  - The new fields are workspace-specific (use an overlay, see below)
77
151
 
78
152
  Create new when:
79
153
 
80
- - None of the system profiles fits
154
+ - None of the system profiles fits, and it's not a role of an existing entity
81
155
  - The thing has a clearly distinct set of properties (10+ fields)
82
156
  - The domain model genuinely calls for a new first-class type (recipe, workout, podcast episode, investment, plant, medication, vehicle, property listing…)
157
+ - It's a relationship-thing that accrues its own independent lifecycle (the `deal` precedent above)
83
158
 
84
- Prefer **inheritance** over new profiles when a system parent fits. `contact extends person` is the pattern — a new `client` profile can `parentProfileSlug: "contact"` and only add the fields that differ.
159
+ Prefer **inheritance** over new profiles when a system parent fits. `contact extends person` is the pattern — a new `client` profile can `parentProfileSlug: "contact"` and only add the fields that differ. But if `client` is really just a role a `company` or `person` plays (no independent properties of its own), it shouldn't be a profile at all — it's a facet, attached via `attach_facet`, never a second entity.
160
+
161
+ ---
85
162
 
86
163
  ## Creating a new profile
87
164
 
@@ -101,6 +178,8 @@ POST /api/hub/profiles
101
178
 
102
179
  Then add properties one by one (see below). You do NOT declare properties inline on the profile — they're separate rows.
103
180
 
181
+ ---
182
+
104
183
  ## Creating properties
105
184
 
106
185
  ```json
@@ -131,6 +210,8 @@ For linking properties, always use `entity_id` with `targetProfileSlug` in const
131
210
 
132
211
  This enables auto-sync (see `../synap/linking.md`) — the property becomes a typed link that shows up in graph traversals automatically.
133
212
 
213
+ ---
214
+
134
215
  ## Workspace overlay properties
135
216
 
136
217
  New concept (2026-04-10+). A single profile (say `task`) can have **different fields in different workspaces** without copying the profile. Set `overlay: true` on `POST /property-defs`:
@@ -154,6 +235,8 @@ Use cases:
154
235
 
155
236
  Overlays don't leak: workspace A can't see workspace B's overlay properties even though both share the profile. For the full scope model, read **`property-types.md`** §Overlay.
156
237
 
238
+ ---
239
+
157
240
  ## Entity scope (pod-wide vs. workspace-scoped)
158
241
 
159
242
  Profiles have an `entityScope` that determines where entities of that type live:
@@ -163,6 +246,8 @@ Profiles have an `entityScope` that determines where entities of that type live:
163
246
 
164
247
  Defaults to `workspace` if not set on the profile. The user can toggle this per profile in ProfileEditor Settings. If you're creating a profile for something clearly pod-wide (a person, a podcast the user follows, a book in their library), set `entityScope: "pod"` explicitly.
165
248
 
249
+ ---
250
+
166
251
  ## Custom relations
167
252
 
168
253
  If the user wants a typed edge that isn't in the convention list (see `../synap/linking.md`), you can define it:
@@ -182,6 +267,8 @@ POST /api/hub/relation-defs
182
267
 
183
268
  Defining a relation def is rarely worth it — `related_to` + a property usually suffices. Only create one when the relationship is semantic enough that UI should treat it specially (e.g., show "mentored by Jane" on a person's profile card).
184
269
 
270
+ ---
271
+
185
272
  ## Worked example — "I want to track podcasts I listen to"
186
273
 
187
274
  1. Inventory. `GET /profiles` → no `podcast` profile, no `podcast_episode`.
@@ -213,7 +300,9 @@ Defining a relation def is rarely worth it — `related_to` + a property usually
213
300
 
214
301
  7. Tell the user. "I added `podcast` and `podcast_episode` to your pod with linking between them. You can create your first episode now, or want me to also add a view for it?" (Hand off to the `synap-ui` skill if they say yes.)
215
302
 
216
- ## Common mistakes
303
+ ---
304
+
305
+ ## Common mistakes — schema extension
217
306
 
218
307
  1. **Creating a profile that already exists (e.g., `meeting` when `event` fits).** Always inventory first.
219
308
  2. **Declaring properties inline on the profile object.** Properties are separate rows; use `POST /property-defs`.
@@ -223,7 +312,9 @@ Defining a relation def is rarely worth it — `related_to` + a property usually
223
312
  6. **Creating an overlay when a base property is wanted.** Overlays only appear in one workspace. If the user wants the field everywhere, don't set `overlay: true`.
224
313
  7. **Creating a custom profile when extension would work.** `client extends contact` is cleaner than a parallel `client` profile.
225
314
 
226
- ## When you need more
315
+ ---
316
+
317
+ ## When you need more — schema extension
227
318
 
228
319
  - Full `valueType` reference + constraints + uiHints → **`property-types.md`**
229
320
  - Inheritance, overlay scope semantics, pod-wide caveats → **`property-types.md`** §Scope
@@ -0,0 +1,13 @@
1
+ profiles.md
2
+ before-you-touch.md
3
+ read-before-write.md
4
+ discover-profiles.md
5
+ extend-vs-create.md
6
+ creating-profiles.md
7
+ property-defs.md
8
+ overlay-properties.md
9
+ entity-scope.md
10
+ relations.md
11
+ worked-example.md
12
+ common-mistakes.md
13
+ more.md
@@ -0,0 +1,22 @@
1
+ name: synap-schema
2
+ description: >
3
+ Use this skill when the user needs to extend Synap's data model — defining a
4
+ new type of thing (entity profile) or adding/modifying fields (property defs)
5
+ on existing types. Triggers: "I need a new type for podcasts/recipes/workouts/
6
+ clients/books/plants/investments", "add a priority field to tasks", "create a
7
+ property for tracking budget", "I want to track Y and it's not in my current
8
+ schema", defining custom relations, setting up a profile for a specific domain
9
+ (real estate, music production, research, fitness, cooking). Also triggers on:
10
+ "do I already have a profile for X?", "what fields does <profile> have?",
11
+ extending an existing profile with workspace-specific overlay properties.
12
+ Do NOT use this skill for creating instances of existing types — the core
13
+ `synap` skill handles that. This skill changes the SCHEMA, not the data.
14
+ metadata:
15
+ openclaw:
16
+ requires:
17
+ env: [SYNAP_HUB_API_KEY, SYNAP_POD_URL]
18
+ primaryEnv: SYNAP_HUB_API_KEY
19
+ homepage: https://synap.live
20
+ capabilities: [schema, profiles, properties]
21
+ os: [macos, linux, windows]
22
+ userInvocable: false
@@ -0,0 +1,14 @@
1
+ ## Before you touch anything
2
+
3
+ Always inventory first. Never assume the schema is empty.
4
+
5
+ ```
6
+ GET /api/hub/profiles?userId={userId}&workspaceId={workspaceId}
7
+ → [{ slug, displayName, entityScope, parentProfileSlug,
8
+ properties: [{ slug, valueType, constraints, uiHints, targetProfileSlug? }] }]
9
+
10
+ GET /api/hub/property-defs?userId={userId}&workspaceId={workspaceId}&profileId={profileId}
11
+ → [{ slug, valueType, constraints, uiHints, workspaceId /* null=base, uuid=overlay */ }]
12
+ ```
13
+
14
+ The `synap` skill's `scripts/orient.sh` already fetches profiles — reuse its output.
@@ -0,0 +1,9 @@
1
+ ## Common mistakes — schema extension
2
+
3
+ 1. **Creating a profile that already exists (e.g., `meeting` when `event` fits).** Always inventory first.
4
+ 2. **Declaring properties inline on the profile object.** Properties are separate rows; use `POST /property-defs`.
5
+ 3. **Using `string` for what should be `entity_id`.** If the field refers to another entity (host of a podcast), use `entity_id` + `targetProfileSlug` — enables auto-sync and link UX.
6
+ 4. **Using `array` of strings for tags.** Tags are a built-in concept; reuse the `tags` property on `note`/`project` instead of creating a parallel field.
7
+ 5. **Forgetting `entityScope`.** Defaults to `workspace`. If the thing is pod-wide (people, books, podcasts), set it explicitly.
8
+ 6. **Creating an overlay when a base property is wanted.** Overlays only appear in one workspace. If the user wants the field everywhere, don't set `overlay: true`.
9
+ 7. **Creating a custom profile when extension would work.** `client extends contact` is cleaner than a parallel `client` profile.
@@ -0,0 +1,17 @@
1
+ ## Creating a new profile
2
+
3
+ ```json
4
+ POST /api/hub/profiles
5
+ {
6
+ "userId": "{userId}",
7
+ "workspaceId": "{workspaceId}",
8
+ "slug": "podcast_episode", // snake_case, unique
9
+ "displayName": "Podcast Episode",
10
+ "description": "An episode of a podcast the user listens to",
11
+ "parentProfileId": "<id of article or null>", // optional, enables inheritance
12
+ "defaultValues": { "status": "queued" },
13
+ "uiHints": { "icon": "mic", "color": "purple" }
14
+ }
15
+ ```
16
+
17
+ Then add properties one by one (see below). You do NOT declare properties inline on the profile — they're separate rows.
@@ -0,0 +1,24 @@
1
+ ## Discover profiles — never assume
2
+
3
+ **Always call `GET /api/hub/profiles?workspaceId={workspaceId}` first.** Profiles are dynamic — every pod and workspace has a different set depending on what was seeded and what the user created. Never assume a profile slug exists without verifying.
4
+
5
+ ```
6
+ GET /api/hub/profiles?workspaceId={workspaceId}
7
+ → [{ slug, displayName, entityScope, parentSlug,
8
+ properties: [{ slug, valueType, required, ... }] }]
9
+ ```
10
+
11
+ Read the response:
12
+
13
+ - `entityScope: "pod"` — visible across all workspaces
14
+ - `entityScope: "workspace"` — scoped to this workspace only (custom types, CRM profiles, template-seeded types)
15
+ - `parentSlug` — inheritance chain (e.g. `contact` extends `person`)
16
+
17
+ ### Commonly seeded profiles (verify before using)
18
+
19
+ Standard pods typically include: `note`, `task`, `project`, `event`, `person`, `contact`, `company`, `bookmark`, `website`, `article`, `capture`, `file`, `anchor`, `decision`, `question`, `research`
20
+
21
+ CRM workspaces additionally have: `deal`, `client` — but **only** when a CRM workspace was created.
22
+ Custom workspace templates (devplane, content, etc.) add their own profiles entirely.
23
+
24
+ Before creating a new profile: **does one of these already fit?** A podcast episode is arguably an `article`. A meeting is an `event`. A book to read is an `article` or `bookmark`. Err on the side of reuse + extension, not creation.
@@ -0,0 +1,8 @@
1
+ ## Entity scope (pod-wide vs. workspace-scoped)
2
+
3
+ Profiles have an `entityScope` that determines where entities of that type live:
4
+
5
+ - `entityScope: "pod"` — entities are pod-wide, visible in every workspace the user can access. Good for people, companies, notes, articles — things that cross contexts.
6
+ - `entityScope: "workspace"` — entities live in the workspace they were created in. Good for deals, files, workspace-specific artifacts.
7
+
8
+ Defaults to `workspace` if not set on the profile. The user can toggle this per profile in ProfileEditor Settings. If you're creating a profile for something clearly pod-wide (a person, a podcast the user follows, a book in their library), set `entityScope: "pod"` explicitly.
@@ -0,0 +1,31 @@
1
+ ## When to extend an existing profile vs. create a new one vs. attach a facet
2
+
3
+ There are three moves, not two. Before extending or creating, ask whether the thing is really a **role** the entity plays rather than a new kind of entity at all — that's a facet, and it's the move people skip.
4
+
5
+ **Kind + Facets, the rule:** one entity = one kind (`profiles.profileKind = 'kind'`). Roles the entity plays — client, partner, investor, prospect — are role-profiles (`profileKind = 'role'`, `applicableKinds[]`) attached via `entity_facets`: additive, workspace-lensed, NOT entities. A facet cascades with its parent entity; only promote a role to a full kind if it accrues its own independent life.
6
+
7
+ **The litmus test:**
8
+
9
+ - Both sides of a connection are independently-alive kinds → it's a **relation** (e.g. person "works at" company — two entities, linked).
10
+ - One side is just wearing a hat with no independent lifecycle → it's a **facet** (e.g. "client" on a company — attach the role, don't create a new entity).
11
+ - The connection itself accrues its own multi-entity lifecycle (stages, money, deadlines, outcomes) → it gets **promoted to its own kind**. `deal` is the precedent: a buyer × seller × stage relationship-thing has its own life (pipeline stage, amount, close date) independent of either party, so it's kept as a primary kind, never a facet.
12
+
13
+ Attach when:
14
+
15
+ - The thing is a role/hat the entity is wearing (client, partner, investor, prospect, sponsor) — it has no properties or lifecycle independent of the parent entity
16
+ - AI-driven creation: resolve identity FIRST (strong signals — email, phone, url) before creating anything; if the entity already exists, `attach_facet` the new role onto it — never spin up a second entity for a hat
17
+
18
+ Extend when:
19
+
20
+ - The thing fits an existing category (a `client` **facet** is the role; if you instead need a distinct persisted sub-kind with its own fields, consider inheritance)
21
+ - The user needs 1–3 extra fields on an existing type
22
+ - The new fields are workspace-specific (use an overlay, see below)
23
+
24
+ Create new when:
25
+
26
+ - None of the system profiles fits, and it's not a role of an existing entity
27
+ - The thing has a clearly distinct set of properties (10+ fields)
28
+ - The domain model genuinely calls for a new first-class type (recipe, workout, podcast episode, investment, plant, medication, vehicle, property listing…)
29
+ - It's a relationship-thing that accrues its own independent lifecycle (the `deal` precedent above)
30
+
31
+ Prefer **inheritance** over new profiles when a system parent fits. `contact extends person` is the pattern — a new `client` profile can `parentProfileSlug: "contact"` and only add the fields that differ. But if `client` is really just a role a `company` or `person` plays (no independent properties of its own), it shouldn't be a profile at all — it's a facet, attached via `attach_facet`, never a second entity.
@@ -0,0 +1,6 @@
1
+ ## When you need more — schema extension
2
+
3
+ - Full `valueType` reference + constraints + uiHints → **`property-types.md`**
4
+ - Inheritance, overlay scope semantics, pod-wide caveats → **`property-types.md`** §Scope
5
+ - Creating views over the new profile → install the **`synap-ui`** skill
6
+ - Creating instances of the new profile → use the core **`synap`** skill
@@ -0,0 +1,22 @@
1
+ ## Workspace overlay properties
2
+
3
+ New concept (2026-04-10+). A single profile (say `task`) can have **different fields in different workspaces** without copying the profile. Set `overlay: true` on `POST /property-defs`:
4
+
5
+ ```json
6
+ POST /api/hub/property-defs
7
+ {
8
+ "userId": "{userId}",
9
+ "workspaceId": "{workspaceId}",
10
+ "profileId": "{taskProfileId}",
11
+ "slug": "billableHours",
12
+ "valueType": "number",
13
+ "overlay": true // this property only appears in this workspace
14
+ }
15
+ ```
16
+
17
+ Use cases:
18
+
19
+ - "My consulting workspace needs `billableHours` on tasks; my personal workspace doesn't."
20
+ - "Our sales workspace wants a `dealSize` on contacts; engineering doesn't."
21
+
22
+ Overlays don't leak: workspace A can't see workspace B's overlay properties even though both share the profile. For the full scope model, read **`property-types.md`** §Overlay.
@@ -0,0 +1,3 @@
1
+ # Synap — schema extension
2
+
3
+ You extend a user's Synap pod schema: new entity profiles, new properties on existing profiles, overlay properties scoped to one workspace. The core rule: **reuse before extending.** Creating duplicate profiles fractures the graph.
@@ -0,0 +1,29 @@
1
+ ## Creating properties
2
+
3
+ ```json
4
+ POST /api/hub/property-defs
5
+ {
6
+ "userId": "{userId}",
7
+ "workspaceId": "{workspaceId}",
8
+ "profileId": "{profileId}", // the profile this property belongs to
9
+ "slug": "durationMinutes",
10
+ "valueType": "number",
11
+ "constraints": { "min": 0, "max": 600 },
12
+ "uiHints": { "format": "compact", "displayName": "Duration" }
13
+ }
14
+ ```
15
+
16
+ Value types: `string`, `number`, `boolean`, `date`, `entity_id`, `array`, `object`, `secret`. Full reference in **`property-types.md`**.
17
+
18
+ For linking properties, always use `entity_id` with `targetProfileSlug` in constraints:
19
+
20
+ ```json
21
+ {
22
+ "slug": "hostId",
23
+ "valueType": "entity_id",
24
+ "constraints": { "targetProfileSlug": "person" },
25
+ "uiHints": { "displayName": "Host" }
26
+ }
27
+ ```
28
+
29
+ This enables auto-sync (see `../synap/linking.md`) — the property becomes a typed link that shows up in graph traversals automatically.
@@ -0,0 +1,50 @@
1
+ ## Read before you write
2
+
3
+ Synap data is a typed graph — never write blind. Before creating or updating an
4
+ entity, work the loop the same way you'd read a file before editing it:
5
+
6
+ 1. **MAP** — know what types exist: `list_profiles` (the cheap map of entity
7
+ profiles), `list_views` for views.
8
+ 2. **SEARCH** — `search_unified({ query: <title>, collections: ["entities"] })`.
9
+ If a close match exists, LINK to it (relation or entity_id property) — do NOT
10
+ create a duplicate. Create only when there is genuinely no match.
11
+ 3. **READ THE SCHEMA** — before writing to a profile you haven't inspected this
12
+ session, call `get_profile({ slug })` for its real property defs (exact keys,
13
+ value types, enum options, link targets). For views, read the config
14
+ (`get_bento_schema`) before `create_view`.
15
+ 4. **WRITE INTO THE REAL FIELDS** — map each value to its correct typed property:
16
+ right `key`, valid `valueType` (dates as ISO, numbers as numbers), enum values
17
+ that satisfy the constraint, links via the property's `linksTo` target. Don't
18
+ invent property keys. A value with no matching property goes into
19
+ description/content, or propose a new one with `create_property_def` — never
20
+ drop it into a stray key.
21
+ 5. **CONNECT** — every new entity links to at least one other. Duplicates and
22
+ orphans are the two ways the graph degrades; avoid both.
23
+
24
+ ## Complete intent, governed outcome
25
+
26
+ `title` + `content` is only a minimum payload, not Synap's data model. Once
27
+ you have read the schema, send the complete intent that is known: `profileSlug`,
28
+ title, typed `properties`, short `description`, long-form `content`, an existing
29
+ `projectId`, links, and source/session provenance. Include role `facets` in the
30
+ same composite plan whenever they must be reviewed with the entity.
31
+
32
+ - **One entity with known fields and no creation-time role change** → use
33
+ `create_entity` / `POST /entities`.
34
+ - **Several entities, facets, or relations that belong in one review** → use the
35
+ composite graph/capture-plan door, never a loose sequence of creates.
36
+ - **Raw input whose structure is unknown** → use capture to produce a plan;
37
+ preserve an original file with `keepRaw` when supplied. Raw source is not the
38
+ same thing as an entity's edited content.
39
+
40
+ Workspace is an explicit lens: omit it to read the pod/base schema and let the
41
+ profile's placement rule apply. Pass a workspace only when the user or a
42
+ reviewed routing decision actually selected it; then its overlays are valid.
43
+ Never fill it from a configured/default workspace.
44
+
45
+ Read the write receipt before continuing. `pending` means a proposal exists and
46
+ no entity has materialized; `applied` means the reported operations completed;
47
+ `partial` means independent follow-up operations failed and must be repaired or
48
+ surfaced. Do not send a speculative second update merely because a write
49
+ completed — enrich only when you learned genuinely new information or the
50
+ receipt identifies a specific missing field.
@@ -0,0 +1,18 @@
1
+ ## Custom relations
2
+
3
+ If the user wants a typed edge that isn't in the convention list (see `../synap/linking.md`), you can define it:
4
+
5
+ ```json
6
+ POST /api/hub/relation-defs
7
+ {
8
+ "userId": "{userId}",
9
+ "workspaceId": "{workspaceId}",
10
+ "slug": "mentored_by",
11
+ "displayName": "Mentored by",
12
+ "sourceProfileSlug": "person",
13
+ "targetProfileSlug": "person",
14
+ "bidirectional": false
15
+ }
16
+ ```
17
+
18
+ Defining a relation def is rarely worth it — `related_to` + a property usually suffices. Only create one when the relationship is semantic enough that UI should treat it specially (e.g., show "mentored by Jane" on a person's profile card).
@@ -0,0 +1,30 @@
1
+ ## Worked example — "I want to track podcasts I listen to"
2
+
3
+ 1. Inventory. `GET /profiles` → no `podcast` profile, no `podcast_episode`.
4
+ 2. Decide scope. Podcasts/episodes are pod-wide (same podcast across workspaces).
5
+ 3. Create two profiles (podcast + episode) or one (episode only, with the show as a string property)? Decide based on the user's intent. If they want to group episodes by show → two profiles. If one-level is enough → one.
6
+ 4. For two profiles:
7
+
8
+ ```
9
+ POST /profiles { slug: "podcast", displayName: "Podcast", entityScope: "pod", uiHints: { icon: "radio" } }
10
+ POST /profiles { slug: "podcast_episode", displayName: "Podcast Episode", parentProfileId: <articleId>, entityScope: "pod" }
11
+ ```
12
+
13
+ 5. Add properties on `podcast`:
14
+
15
+ ```
16
+ POST /property-defs { slug: "host", valueType: "string" }
17
+ POST /property-defs { slug: "rssUrl", valueType: "string", uiHints: { inputType: "url" } }
18
+ POST /property-defs { slug: "category", valueType: "string" }
19
+ ```
20
+
21
+ 6. Add properties on `podcast_episode`:
22
+
23
+ ```
24
+ POST /property-defs { slug: "podcastId", valueType: "entity_id", constraints: { targetProfileSlug: "podcast" } }
25
+ POST /property-defs { slug: "durationMinutes", valueType: "number" }
26
+ POST /property-defs { slug: "listenedAt", valueType: "date" }
27
+ POST /property-defs { slug: "rating", valueType: "number", constraints: { min: 1, max: 5 } }
28
+ ```
29
+
30
+ 7. Tell the user. "I added `podcast` and `podcast_episode` to your pod with linking between them. You can create your first episode now, or want me to also add a view for it?" (Hand off to the `synap-ui` skill if they say yes.)
@@ -28,6 +28,8 @@ metadata:
28
28
 
29
29
  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.
30
30
 
31
+ ---
32
+
31
33
  ## Before you build anything
32
34
 
33
35
  Always inventory. Never hallucinate view types, widget kinds, or profiles.
@@ -49,6 +51,8 @@ GET /api/hub/views?userId={userId}&workspaceId={workspaceId}
49
51
 
50
52
  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).
51
53
 
54
+ ---
55
+
52
56
  ## Four things you can build
53
57
 
54
58
  1. **Views** — named queries + rendering config over entities of a given profile. Kanban of tasks, gallery of articles, calendar of events.
@@ -74,6 +78,8 @@ Widget definitions are the source of truth for which cells are installed and how
74
78
  - 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.
75
79
  - 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`).
76
80
 
81
+ ---
82
+
77
83
  ## View types (16 total, 12 implemented)
78
84
 
79
85
  Pick one that matches the data's shape AND the user's intent:
@@ -99,6 +105,8 @@ Pick one that matches the data's shape AND the user's intent:
99
105
 
100
106
  Decision: the data has statuses → `kanban`. Dates → `calendar`. Many columns → `table`. Mixed types → `masonry` or `bento`. Full reference in **`view-types.md`**.
101
107
 
108
+ ---
109
+
102
110
  ## Creating a view
103
111
 
104
112
  ```json
@@ -126,6 +134,8 @@ POST /api/hub/views
126
134
 
127
135
  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.
128
136
 
137
+ ---
138
+
129
139
  ## Bento layouts
130
140
 
131
141
  A bento is a 12-column react-grid-layout. Blocks reference **cells** by kind.
@@ -162,6 +172,8 @@ Block kinds:
162
172
 
163
173
  Full widget catalog in **`widget-catalog.md`**. Layout patterns in **`bento-recipes.md`**.
164
174
 
175
+ ---
176
+
165
177
  ## Creating or proposing a workspace
166
178
 
167
179
  **Always ask before creating.** Workspaces are big objects with profiles, views, members, bento, and seed data. Commit only after user confirms.
@@ -210,6 +222,8 @@ The canonical flow:
210
222
 
211
223
  4. **On no**, don't commit. Offer to adjust.
212
224
 
225
+ ---
226
+
213
227
  ## Proposing vs. extending
214
228
 
215
229
  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.
@@ -222,6 +236,8 @@ Create new when:
222
236
 
223
237
  Otherwise: add a view, add a bento block, add properties — don't multiply workspaces.
224
238
 
239
+ ---
240
+
225
241
  ## Worked example — "Make me a CRM"
226
242
 
227
243
  1. Inventory. User already has `person`, `contact`, `company`, `deal`, `event` profiles (all system).
@@ -241,6 +257,8 @@ Otherwise: add a view, add a bento block, add properties — don't multiply work
241
257
  4. Show to user. Confirm.
242
258
  5. Commit via `POST /workspaces`.
243
259
 
260
+ ---
261
+
244
262
  ## Arranging a bento after creation
245
263
 
246
264
  ```json
@@ -250,7 +268,9 @@ POST /api/hub/views/{bentoViewId}/arrange
250
268
 
251
269
  `bento.arrange` is auto-approved by default. Safe to run without hesitation when the user rearranges or adds widgets.
252
270
 
253
- ## Common mistakes
271
+ ---
272
+
273
+ ## Common mistakes — UI generation
254
274
 
255
275
  1. **Creating a workspace without asking.** Always propose + confirm. Workspaces are too big to auto-commit.
256
276
  2. **Guessing widget kinds.** Always `GET /widget-definitions` first. A `kind` that isn't in the registry won't render.
@@ -261,6 +281,8 @@ POST /api/hub/views/{bentoViewId}/arrange
261
281
  7. **Hardcoding config for view types you haven't checked.** Each view type's `config` shape is different. Get an example from `/views` first.
262
282
  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.
263
283
 
284
+ ---
285
+
264
286
  ## AI Companion integration
265
287
 
266
288
  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.
@@ -289,7 +311,9 @@ These cell keys are registered in the browser app but may not appear in `GET /ap
289
311
 
290
312
  **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.
291
313
 
292
- ## When you need more
314
+ ---
315
+
316
+ ## When you need more — UI generation
293
317
 
294
318
  - Full per-view-type `config` shapes → **`view-types.md`**
295
319
  - Complete widget/cell catalog + configSchemas → **`widget-catalog.md`**
@@ -0,0 +1,13 @@
1
+ views.md
2
+ before-you-build.md
3
+ four-builds.md
4
+ view-list.md
5
+ creating-views.md
6
+ bento-layouts.md
7
+ workspaces.md
8
+ proposing-vs-extending.md
9
+ worked-example.md
10
+ arranging-bento.md
11
+ common-mistakes.md
12
+ ai-companion.md
13
+ more.md
@@ -0,0 +1,23 @@
1
+ name: synap-ui
2
+ description: >
3
+ Use this skill when the user wants to BUILD interface in Synap — creating views,
4
+ dashboards, bento layouts, or whole workspaces over their data. Triggers:
5
+ "build me a dashboard for tracking X", "create a kanban for my projects",
6
+ "make a CRM workspace", "I want a feed view of my articles", "design a home
7
+ dashboard", "show my reading list as a gallery", "turn this into a
8
+ timeline/calendar/matrix", "generate a workspace for content creation /
9
+ sales / research / project management / fitness tracking", "arrange widgets
10
+ on my bento", "create a command / automation trigger". This skill PRESENTS
11
+ data — the underlying entities must already exist (use core `synap`) and
12
+ schema extensions happen via `synap-schema`. Always propose workspace creation
13
+ to the user before committing — workspaces are lenses on data, not silos,
14
+ and the user decides when a new lens is warranted.
15
+ metadata:
16
+ openclaw:
17
+ requires:
18
+ env: [SYNAP_HUB_API_KEY, SYNAP_POD_URL]
19
+ primaryEnv: SYNAP_HUB_API_KEY
20
+ homepage: https://synap.live
21
+ capabilities: [views, bento, workspaces, widgets]
22
+ os: [macos, linux, windows]
23
+ userInvocable: false