@synap-core/workspace-templates 0.12.0 → 0.23.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 (245) hide show
  1. package/README.md +483 -0
  2. package/automations/bookmark-enrichment.automation.json +321 -0
  3. package/automations/github-pr-events.automation.json +505 -0
  4. package/automations/mail-feed.automation.json +86 -0
  5. package/automations/ship-a-change-checks-green.automation.json +106 -0
  6. package/automations/ship-a-change-checks-red.automation.json +106 -0
  7. package/automations/ship-a-change-deployed.automation.json +56 -0
  8. package/automations/ship-a-change-pr-merged.automation.json +110 -0
  9. package/automations/ship-a-change-pr-opened.automation.json +104 -0
  10. package/automations/url-bookmark-capture.automation.json +132 -0
  11. package/capabilities/agency-skills.capability.json +157 -0
  12. package/capabilities/apify.capability.json +265 -0
  13. package/capabilities/apollo.capability.json +120 -0
  14. package/capabilities/arch-backend.capability.json +97 -0
  15. package/capabilities/arch-client-intelligence.capability.json +401 -0
  16. package/capabilities/backblaze-b2.capability.json +205 -0
  17. package/capabilities/cal-com.capability.json +266 -0
  18. package/capabilities/canva.capability.json +274 -0
  19. package/capabilities/claude-code-routines.capability.json +172 -0
  20. package/capabilities/claude-managed-agents.capability.json +215 -0
  21. package/capabilities/client-comms-report.capability.json +246 -0
  22. package/capabilities/content-idea-to-production.capability.json +29 -0
  23. package/capabilities/datagouv.capability.json +315 -0
  24. package/capabilities/discord-bot.capability.json +157 -0
  25. package/capabilities/dropbox.capability.json +281 -0
  26. package/capabilities/exa.capability.json +109 -0
  27. package/capabilities/fal-ai.capability.json +83 -0
  28. package/capabilities/fal-media-lab.capability.json +158 -0
  29. package/capabilities/fireflies.capability.json +191 -0
  30. package/capabilities/freellmapi.capability.json +114 -0
  31. package/capabilities/generic-apikey.capability.json +92 -0
  32. package/capabilities/github-merge.capability.json +99 -0
  33. package/capabilities/github-read.capability.json +325 -0
  34. package/capabilities/governance-tighten-recommender.capability.json +81 -0
  35. package/capabilities/jev.capability.json +226 -0
  36. package/capabilities/lead-conversion-enrollment.capability.json +246 -0
  37. package/capabilities/mail-feed.capability.json +277 -0
  38. package/capabilities/mailgun.capability.json +52 -0
  39. package/capabilities/nango-google.capability.json +639 -0
  40. package/capabilities/notion.capability.json +417 -0
  41. package/capabilities/omniroute.capability.json +137 -0
  42. package/capabilities/posthog-analytics.capability.json +258 -0
  43. package/capabilities/postiz.capability.json +467 -0
  44. package/capabilities/proactive-digest.capability.json +190 -0
  45. package/capabilities/proton.capability.json +288 -0
  46. package/capabilities/replicate-rvm.capability.json +97 -0
  47. package/capabilities/research-methods.capability.json +57 -0
  48. package/capabilities/shopify.capability.json +395 -0
  49. package/capabilities/slack.capability.json +369 -0
  50. package/capabilities/stripe.capability.json +420 -0
  51. package/capabilities/telegram-bridge.capability.json +56 -0
  52. package/capabilities/treg.capability.json +102 -0
  53. package/capabilities/unipile-linkedin.capability.json +471 -0
  54. package/capabilities/vercel.capability.json +424 -0
  55. package/dist/define-CPS0n8BV.d.ts +1331 -0
  56. package/dist/index.d.ts +174 -900
  57. package/dist/index.js +26148 -23931
  58. package/dist/index.js.map +1 -1
  59. package/dist/wire.d.ts +222 -0
  60. package/dist/wire.js +77 -0
  61. package/dist/wire.js.map +1 -0
  62. package/package.json +27 -4
  63. package/packs/bookmark-views-pack.json +33 -0
  64. package/packs/crm-pack.json +76 -0
  65. package/packs/customer-profile.json +28 -0
  66. package/packs/deep-research.playbook.json +30 -0
  67. package/packs/event-views-pack.json +33 -0
  68. package/packs/habit-profile.json +27 -0
  69. package/packs/hr-pack.json +54 -0
  70. package/packs/invoice-profile.json +28 -0
  71. package/packs/knowledge-base-pack.json +56 -0
  72. package/packs/meeting-profile.json +29 -0
  73. package/packs/product-profile.json +30 -0
  74. package/packs/project-management-pack.json +49 -0
  75. package/packs/recipe-profile.json +29 -0
  76. package/packs/task-views-pack.json +39 -0
  77. package/retired.yaml +136 -0
  78. package/skills/app-factory-build-slice/SKILL.md +70 -0
  79. package/skills/app-factory-build-slice.catalog.json +17 -0
  80. package/skills/app-factory-design-canvas/SKILL.md +96 -0
  81. package/skills/app-factory-design-canvas.catalog.json +17 -0
  82. package/skills/app-factory-design-review/SKILL.md +99 -0
  83. package/skills/app-factory-design-review.catalog.json +18 -0
  84. package/skills/app-factory-research/SKILL.md +123 -0
  85. package/skills/app-factory-research.catalog.json +17 -0
  86. package/skills/bookmark-enrichment/SKILL.md +40 -0
  87. package/skills/carousel-format/carousel-format.skill.json +18 -0
  88. package/skills/collage-broll/collage-broll.skill.json +20 -0
  89. package/skills/content-taste/content-taste.skill.json +18 -0
  90. package/skills/creative-director/creative-director.skill.json +18 -0
  91. package/skills/design-critique/SKILL.md +135 -0
  92. package/skills/design-critique.catalog.json +12 -0
  93. package/skills/designing-with-real-components/SKILL.md +140 -0
  94. package/skills/designing-with-real-components.catalog.json +12 -0
  95. package/skills/edit-loop/edit-loop.skill.json +25 -0
  96. package/skills/facecam-edit/facecam-edit.skill.json +24 -0
  97. package/skills/mapping-the-server/SKILL.md +54 -0
  98. package/skills/math-explainer-manimgx/math-explainer-manimgx.skill.json +20 -0
  99. package/skills/motion-quality-gates/motion-quality-gates.skill.json +20 -0
  100. package/skills/open-design-edit/open-design-edit.skill.json +24 -0
  101. package/skills/reading-client-progress/SKILL.md +65 -0
  102. package/skills/routing-to-channels/SKILL.md +54 -0
  103. package/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
  104. package/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
  105. package/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
  106. package/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
  107. package/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
  108. package/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
  109. package/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
  110. package/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
  111. package/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
  112. package/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
  113. package/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
  114. package/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
  115. package/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
  116. package/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
  117. package/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
  118. package/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
  119. package/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
  120. package/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
  121. package/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
  122. package/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
  123. package/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
  124. package/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
  125. package/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
  126. package/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
  127. package/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
  128. package/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
  129. package/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
  130. package/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
  131. package/skills/video-direction/video-direction.skill.json +20 -0
  132. package/skills/video-style-vocabulary/video-style-vocabulary.skill.json +20 -0
  133. package/skills/video-toolbox/video-toolbox.skill.json +20 -0
  134. package/src/__fixtures__/lifecycle-presets.flat-before.json +205 -0
  135. package/src/agency-os.yaml +122 -0
  136. package/src/agent-os-skill-slugs.test.ts +65 -0
  137. package/src/apify-social-reader.test.ts +317 -0
  138. package/src/base.yaml +85 -39
  139. package/src/blockchain-ecosystem.yaml +1 -0
  140. package/src/brand-library.yaml +525 -14
  141. package/src/builder-dev-fold.template.test.ts +113 -0
  142. package/src/builder.yaml +779 -91
  143. package/src/business-model-catalog-description.test.ts +47 -0
  144. package/src/business-model-grp.template.test.ts +214 -0
  145. package/src/business-model.yaml +296 -49
  146. package/src/catalog-safety.test.ts +198 -0
  147. package/src/catalog.template-items.test.ts +75 -0
  148. package/src/catalog.ts +66 -2
  149. package/src/concept-guard.test.ts +28 -8
  150. package/src/concept-guard.ts +2 -2
  151. package/src/content-creation.template.test.ts +52 -0
  152. package/src/content-creation.yaml +192 -0
  153. package/src/content-os.edit-loop.template.test.ts +210 -0
  154. package/src/content-os.publish-due-posts.template.test.ts +261 -0
  155. package/src/content-os.template.test.ts +322 -0
  156. package/src/content-os.video-takes.template.test.ts +338 -0
  157. package/src/content-os.work-a-take.template.test.ts +125 -0
  158. package/src/content-os.yaml +1830 -39
  159. package/src/content-studio-retired.template.test.ts +82 -0
  160. package/src/corpus-flow-validity.test.ts +4 -5
  161. package/src/crm-absorbs-outreach.template.test.ts +117 -0
  162. package/src/crm-build-plan.template.test.ts +128 -0
  163. package/src/crm-lists.template.test.ts +96 -0
  164. package/src/crm-messages-cadence.template.test.ts +164 -0
  165. package/src/crm-one-send-door.template.test.ts +65 -0
  166. package/src/crm.yaml +1456 -181
  167. package/src/decisions-wave.template.test.ts +186 -0
  168. package/src/define.ts +130 -17
  169. package/src/design-to-implementation.template.test.ts +94 -0
  170. package/src/domain-template-type.test.ts +75 -0
  171. package/src/ecosystem.yaml +27 -66
  172. package/src/enterprise-os.yaml +10 -134
  173. package/src/facecam-edit.audio-studio.test.ts +188 -0
  174. package/src/fal-generate-image.test.ts +200 -0
  175. package/src/fal-media-lab-pod-files.test.ts +180 -0
  176. package/src/finance.yaml +254 -1
  177. package/src/foundation.yaml +78 -38
  178. package/src/frame-host-modules.d.mts +6 -0
  179. package/src/frame-host-modules.mjs +58 -0
  180. package/src/generate.mjs +9 -3
  181. package/src/github-merge.test.ts +210 -0
  182. package/src/grants.yaml +46 -17
  183. package/src/hr.yaml +39 -6
  184. package/src/index.ts +36 -1
  185. package/src/intent.test.ts +161 -0
  186. package/src/internal-runbook.yaml +19 -1
  187. package/src/jev.test.ts +356 -0
  188. package/src/legal.yaml +33 -1
  189. package/src/life-os.yaml +51 -240
  190. package/src/lifecycle-coverage.test.ts +124 -0
  191. package/src/lifecycle-declarations.test.ts +252 -0
  192. package/src/lifecycle-presets.test.ts +468 -0
  193. package/src/lifecycle-presets.ts +494 -0
  194. package/src/lifecycle-stuck.test.ts +46 -0
  195. package/src/lifecycle-waits.parity.test.ts +319 -0
  196. package/src/marketing.yaml +108 -4
  197. package/src/meetings-knowledge.yaml +18 -0
  198. package/src/networking.yaml +23 -2
  199. package/src/operations.yaml +304 -4
  200. package/src/pipeline-views.template.test.ts +88 -0
  201. package/src/playbook-goal-placeholders.test.ts +57 -0
  202. package/src/postiz-contract.test.ts +134 -0
  203. package/src/presentation-declarations.test.ts +174 -0
  204. package/src/process-contract.validate.test.ts +352 -0
  205. package/src/project-management.yaml +39 -740
  206. package/src/publish-body.d.mts +29 -0
  207. package/src/publish-body.mjs +74 -0
  208. package/src/publish-body.test.ts +74 -0
  209. package/src/publish-official-lib.test.ts +176 -0
  210. package/src/replicate-rvm.test.ts +504 -0
  211. package/src/research-base.yaml +119 -20
  212. package/src/research-decision.yaml +60 -3
  213. package/src/reserved-profile-slugs.test.ts +83 -0
  214. package/src/retired-goal-kinds.test.ts +58 -0
  215. package/src/role-reference-and-step-domain.test.ts +192 -0
  216. package/src/seed-obligation.test.ts +1 -6
  217. package/src/send-message-maps.test.ts +227 -0
  218. package/src/shared-role-ssot.test.ts +40 -2
  219. package/src/ship-a-change.template.test.ts +177 -0
  220. package/src/skills.test.ts +170 -0
  221. package/src/social.yaml +85 -27
  222. package/src/space-packages.freshness.test.ts +97 -0
  223. package/src/space-packages.generated.ts +40 -0
  224. package/src/space-packages.test.ts +125 -0
  225. package/src/space-packages.ts +73 -0
  226. package/src/start.test.ts +188 -0
  227. package/src/task-intents.test.ts +293 -0
  228. package/src/templates.ts +20851 -21496
  229. package/src/types.ts +443 -60
  230. package/src/unipile-publish-post.test.ts +162 -0
  231. package/src/validate-flow.drift.test.ts +2 -3
  232. package/src/validate-flow.ts +22 -2
  233. package/src/validate-onboarding.test.ts +59 -0
  234. package/src/validate.test.ts +71 -4
  235. package/src/validate.ts +1335 -7
  236. package/src/wire-core.ts +231 -0
  237. package/src/wire.test.ts +159 -0
  238. package/src/wire.ts +107 -0
  239. package/src/agent-fleet.yaml +0 -1645
  240. package/src/business-developer.template.test.ts +0 -351
  241. package/src/business-developer.yaml +0 -860
  242. package/src/content-studio.yaml +0 -361
  243. package/src/dev-dashboard.yaml +0 -990
  244. package/src/outreach-comms.yaml +0 -486
  245. package/src/the-arch.yaml +0 -201
@@ -0,0 +1,315 @@
1
+ {
2
+ "apiVersion": "synap/v1",
3
+ "kind": "capability",
4
+ "meta": {
5
+ "slug": "datagouv",
6
+ "name": "data.gouv.fr — French Open Data",
7
+ "description": "Search, preview and save datasets from data.gouv.fr, France's official open-data platform: companies (SIRENE), property sales (DVF), addresses, public procurement and more. Read-only. No API key needed.",
8
+ "tags": [
9
+ "capability",
10
+ "france",
11
+ "opendata",
12
+ "mcp",
13
+ "opt-in"
14
+ ],
15
+ "isPublic": true,
16
+ "syncByDefault": false
17
+ },
18
+ "spec": {
19
+ "key": "datagouv",
20
+ "name": "data.gouv.fr — French Open Data",
21
+ "description": "Official French open-data platform (data.gouv.fr) as a first-class Synap capability. Registers the public DINUM MCP server (https://mcp.data.gouv.fr/mcp — no API key, read-only) so agents get live tools, plus curated verbs for search/preview/capture and a teaching skill that maps the full MCP + REST surface so an AI can crystallize useful MCP workflows into new callable caps, automations, and skills. Coverage: ~75k datasets, ~1k dataservices (APIs catalogued on the platform), orgs (INSEE, DGFiP, collectivités…), Tabular row preview (CSV≤100MB / XLSX≤12.5MB). High-value domains: SIRENE (companies), DVF (real-estate transactions), BAN (addresses), cadastre, IRVE (EV chargers), population, marchés publics. Licence Ouverte / Etalab for most data. PRECONDITION: none for the hosted MCP. Optional: self-host URL via mcpUrl param. Install is opt-in (not default-synced to every pod).",
22
+ "params": [
23
+ {
24
+ "name": "mcpUrl",
25
+ "label": "MCP server URL",
26
+ "type": "text",
27
+ "required": false,
28
+ "default": "https://mcp.data.gouv.fr/mcp",
29
+ "description": "Streamable-HTTP MCP endpoint. Default is the official public instance (no auth). Override only if you self-host datagouv-mcp."
30
+ }
31
+ ],
32
+ "vault": [],
33
+ "mcpServers": [
34
+ {
35
+ "slug": "datagouv",
36
+ "name": "data.gouv.fr",
37
+ "description": "Official French open-data MCP (DINUM). Search datasets, list resources, query tabular rows, discover third-party APIs (dataservices).",
38
+ "transport": "http",
39
+ "url": "{{mcpUrl}}",
40
+ "enabled": true,
41
+ "toolPolicy": {
42
+ "default": "inline"
43
+ },
44
+ "metadata": {
45
+ "provider": "datagouv",
46
+ "docs": "https://github.com/datagouv/datagouv-mcp",
47
+ "license": "MIT",
48
+ "auth": "none"
49
+ }
50
+ }
51
+ ],
52
+ "tools": [
53
+ {
54
+ "name": "datagouv_mcp",
55
+ "kind": "mcp",
56
+ "description": "Gateway to the data.gouv.fr MCP server. callProvider('datagouv_mcp', 'POST', '<mcp_tool_name>', args) runs any registered MCP tool (search_datasets, get_dataset_info, list_dataset_resources, get_resource_info, query_resource_data, search_organizations, search_dataservices, get_dataservice_info, get_dataservice_openapi_spec, get_metrics). Path = MCP tool name; body = tool arguments. No vault secret — credentialRef is the mcp:// server slug.",
57
+ "credentialRef": "mcp://datagouv",
58
+ "executor": "is-agent",
59
+ "config": {
60
+ "serverSlug": "datagouv"
61
+ },
62
+ "metadata": {
63
+ "provider": "datagouv",
64
+ "mcpTools": [
65
+ "search_datasets",
66
+ "search_organizations",
67
+ "get_dataset_info",
68
+ "list_dataset_resources",
69
+ "get_resource_info",
70
+ "query_resource_data",
71
+ "search_dataservices",
72
+ "get_dataservice_info",
73
+ "get_dataservice_openapi_spec",
74
+ "get_metrics"
75
+ ]
76
+ }
77
+ }
78
+ ],
79
+ "skills": [
80
+ {
81
+ "name": "datagouv-open-data-advisor",
82
+ "kind": "instruction",
83
+ "scope": "pod",
84
+ "description": "Expert playbook for French open data via data.gouv.fr. Load when the user asks about French public data, SIRENE/companies, DVF/real estate, BAN/addresses, IRVE, INSEE stats, marchés publics, or when crystallizing an MCP workflow into a reusable capability/automation. Contains the full MCP tool map, REST API map, high-value dataset guide, entity mapping rules, and the MCP→cap crystallization protocol.",
85
+ "code": "# data.gouv.fr Open Data Advisor\n\nYou are the French open-data specialist for this Synap pod. You help discover, preview, and **structure** public data from [data.gouv.fr](https://www.data.gouv.fr) — and you turn useful ad-hoc MCP workflows into durable, callable capabilities.\n\n## Mental model (three layers)\n\n1. **Live MCP tools** — injected from the `datagouv` MCP server (and/or via `callProvider('datagouv_mcp', …)` / curated verbs below). Best for exploration and one-shot answers.\n2. **Curated capability verbs** — first-class skills (`datagouv_search_datasets`, `datagouv_query_resource`, …). Best for automations and other agents that need stable contracts.\n3. **Crystallized caps** — new skills/automations YOU propose after a workflow proves useful. This is the product loop: *MCP explore → useful workflow → real cap*.\n\nNever invent dataset IDs. Always search first, then drill into resources.\n\n## MCP tool map (path = tool name for `datagouv_mcp`)\n\n| Tool | Args | Use |\n|---|---|---|\n| `search_datasets` | `query` (req), `page?`, `page_size?` (max 100) | Find datasets by keywords |\n| `search_organizations` | `query?`, `page?`, `page_size?`, `sort?`, `badge?` (`public-service`\\|`certified`\\|`local-authority`\\|…) | Find publishers |\n| `get_dataset_info` | `dataset_id` | Full metadata, license, tags, org |\n| `list_dataset_resources` | `dataset_id` | Files (format, size, URL) |\n| `get_resource_info` | `resource_id` | MIME, Tabular availability, download URL |\n| `query_resource_data` | `resource_id`, `page?`, `page_size?` (max 200) | Preview CSV/XLS rows via Tabular API |\n| `search_dataservices` | `query`, `page?`, `page_size?` | Find live third-party APIs catalogued on the platform |\n| `get_dataservice_info` | `dataservice_id` | Base API URL, OpenAPI URL, license |\n| `get_dataservice_openapi_spec` | `dataservice_id` | Endpoint summary |\n| `get_metrics` | `dataset_id?` and/or `resource_id?`, `limit?` | Visits / downloads (prod only) |\n\n**Recommended MCP workflow:** `search_datasets` → `list_dataset_resources` → `query_resource_data` (page_size 20) to learn schema → for small sets paginate; for large sets use the raw file URL from `get_resource_info` (do not try to pull multi-GB dumps through MCP).\n\n**Tabular limits:** CSV ≤ 100 MB, XLSX ≤ 12.5 MB.\n\n**Dataservices note:** MCP *discovers* APIs (Adresse, Sirene live, etc.) and returns OpenAPI — it does **not** call those third-party APIs for you. After OpenAPI, either call them out-of-band or crystallize a new `kind:\"api\"` tool + verbs.\n\n## REST API (data.gouv catalog — no key for reads)\n\nBase: `https://www.data.gouv.fr/api/1`\n\n| Path | Notes |\n|---|---|\n| `GET /datasets/?q=` | Search (same catalog as MCP) |\n| `GET /datasets/{id}/` | Dataset detail |\n| `GET /datasets/{id}/resources/` | Resources |\n| `GET /organizations/?q=` | Orgs |\n| `GET /dataservices/?q=` | Third-party APIs |\n| Tabular | Via MCP `query_resource_data` or resource-specific tabular endpoints |\n\n`X-API-KEY` is only required for **writes** (publishing). This capability is read-only consumption.\n\n## High-value datasets (start here)\n\n| Need | Search terms / known anchors |\n|---|---|\n| French companies (SIREN/SIRET, NAF, siège) | `Base Sirene`, `SIRENE` (INSEE) |\n| Real-estate sale prices | `Demandes de valeurs foncières`, `DVF`, `DVF+` |\n| Official addresses + coords | `Base Adresse Nationale`, `BAN` |\n| Cadastre / parcels | `cadastre`, plan cadastral |\n| EV charging stations | `IRVE` |\n| Population / admin geo | INSEE population, COG, communes |\n| Public procurement | `marchés publics`, BOAMP-linked dumps |\n\nLicence is usually **Licence Ouverte / Etalab** — free reuse including commercial, with attribution. Always record `provider: 'data.gouv.fr'`, `dataset_id`, `resource_id`, `retrieved_at` on any entity you create.\n\n## Mapping into the pod (do not invent kinds)\n\n| Open data | Prefer entity / property |\n|---|---|\n| Company (SIREN) | `company` — attach role facets (client/partner/…) as needed; never create a second entity for a hat |\n| Address / place | existing place/geo fields or a note with structured properties |\n| Dataset discovery | `research` or `bookmark` with provenance URL |\n| Fact / lesson | `knowledge` / capture with claim + source |\n\nIdentity-first: match on SIREN/SIRET/email/url before creating a company.\n\n## Crystallization protocol (MCP → real capability)\n\nWhen a multi-step MCP workflow is **repeatable and valuable**, promote it — do not leave it as chat-only knowledge.\n\n### When to crystallize\n- Used ≥2 times with stable inputs/outputs\n- Would be useful to another agent or a cron/automation\n- Clear success criteria (e.g. \"lookup company by SIREN → propose company entity\")\n\n### What to produce (proposal-gated)\n1. **A skill verb** (`kind: code` or `declarative`) with:\n - stable `name` (snake_case, prefixed `datagouv_` or domain-specific)\n - `requires: [\"datagouv_mcp\"]` (or a new `kind:api` tool if calling a third-party dataservice)\n - typed `parameters` (`string?` for optional)\n - short description (agent-facing contract)\n2. Optionally an **automation** (cron/event) that calls that verb\n3. Optionally a **playbook stage grant** if it belongs to a session template\n\n### How to propose\n- Prefer the pod's capability/skill proposal paths (`propose` tools / capability apply definition) over free-text-only advice.\n- Capture a short `knowledge` lesson: *workflow*, *inputs*, *outputs*, *gotchas* (Tabular size, ID types, license).\n- If the workflow needs a **third-party API** (BAN geocode, live Sirene): use `search_dataservices` + OpenAPI, then propose a NEW capability tool `kind:\"api\"` with its own baseUrl — do not pretend MCP will call it.\n\n### Do NOT crystallize\n- One-off research answers\n- Full bulk dumps (SIRENE national file, multi-year DVF) — those need ETL/jobs, not MCP page loops\n- Restricted admin APIs (API Entreprise / Particulier — Datapass) without habilitation\n\n## Curated verbs already installed\n\n| Verb | Purpose |\n|---|---|\n| `datagouv_search_datasets` | Keyword search |\n| `datagouv_get_dataset` | Dataset metadata by id |\n| `datagouv_list_resources` | Files for a dataset |\n| `datagouv_query_resource` | Tabular row preview |\n| `datagouv_search_dataservices` | Discover live APIs |\n| `datagouv_get_dataservice` | One API's metadata + OpenAPI summary path |\n| `datagouv_capture_dataset` | Propose a research/bookmark entity with provenance |\n\nUse these first; invent new verbs only when the contract is different.\n\n## Safety & quality\n- Read-only: never claim you can publish to data.gouv without a user API key + write capability.\n- Cite dataset title + URL when answering humans.\n- Prefer French queries for French catalog relevance (`immobilier Paris`, `entreprises SIRENE`).\n- If MCP is down, say so; do not fabricate rows.\n"
86
+ },
87
+ {
88
+ "name": "datagouv_search_datasets",
89
+ "intent": "search_external",
90
+ "kind": "code",
91
+ "scope": "pod",
92
+ "description": "Search data.gouv.fr datasets by keywords (French open data catalog). Read-only. Args: { query: string, page?: number (default 1), page_size?: number (default 20, max 100) }. Returns search hits with title, id, organization, tags, resource count.",
93
+ "requires": [
94
+ "datagouv_mcp"
95
+ ],
96
+ "executionMode": "sync",
97
+ "timeoutSeconds": 45,
98
+ "parameters": {
99
+ "query": "string",
100
+ "page": "number?",
101
+ "page_size": "number?"
102
+ },
103
+ "code": "const query = String(args?.query ?? '').trim();\nif (!query) throw new Error('datagouv_search_datasets: query is required');\nconst page = Number.isFinite(Number(args?.page)) ? Math.max(1, Math.trunc(Number(args.page))) : 1;\nconst ps = Number.isFinite(Number(args?.page_size)) ? Math.trunc(Number(args.page_size)) : 20;\nconst page_size = Math.max(1, Math.min(100, ps));\nconst res = await callProvider('datagouv_mcp', 'POST', 'search_datasets', { query, page, page_size });\nif (res?.success === false) throw new Error(String(res?.error || 'datagouv MCP search_datasets failed'));\nconst payload = res?.body !== undefined ? res.body : res;\nreturn { query, page, page_size, result: payload };"
104
+ },
105
+ {
106
+ "name": "datagouv_get_dataset",
107
+ "intent": "fetch_record",
108
+ "kind": "code",
109
+ "scope": "pod",
110
+ "description": "Get detailed metadata for one data.gouv.fr dataset (title, description, organization, tags, license, dates). Read-only. Args: { dataset_id: string }.",
111
+ "requires": [
112
+ "datagouv_mcp"
113
+ ],
114
+ "executionMode": "sync",
115
+ "timeoutSeconds": 45,
116
+ "parameters": {
117
+ "dataset_id": "string"
118
+ },
119
+ "code": "const dataset_id = String(args?.dataset_id ?? '').trim();\nif (!dataset_id) throw new Error('datagouv_get_dataset: dataset_id is required');\nconst res = await callProvider('datagouv_mcp', 'POST', 'get_dataset_info', { dataset_id });\nif (res?.success === false) throw new Error(String(res?.error || 'datagouv MCP get_dataset_info failed'));\nconst payload = res?.body !== undefined ? res.body : res;\nreturn { dataset_id, result: payload };"
120
+ },
121
+ {
122
+ "name": "datagouv_list_resources",
123
+ "intent": "list_records",
124
+ "kind": "code",
125
+ "scope": "pod",
126
+ "description": "List files (resources) in a data.gouv.fr dataset — format, size, type, URL. Read-only. Args: { dataset_id: string }.",
127
+ "requires": [
128
+ "datagouv_mcp"
129
+ ],
130
+ "executionMode": "sync",
131
+ "timeoutSeconds": 45,
132
+ "parameters": {
133
+ "dataset_id": "string"
134
+ },
135
+ "code": "const dataset_id = String(args?.dataset_id ?? '').trim();\nif (!dataset_id) throw new Error('datagouv_list_resources: dataset_id is required');\nconst res = await callProvider('datagouv_mcp', 'POST', 'list_dataset_resources', { dataset_id });\nif (res?.success === false) throw new Error(String(res?.error || 'datagouv MCP list_dataset_resources failed'));\nconst payload = res?.body !== undefined ? res.body : res;\nreturn { dataset_id, result: payload };"
136
+ },
137
+ {
138
+ "name": "datagouv_query_resource",
139
+ "intent": "list_records",
140
+ "kind": "code",
141
+ "scope": "pod",
142
+ "description": "Preview rows from a CSV/XLS resource via data.gouv Tabular API. Use after list_resources to learn schema. Not for multi-GB dumps (CSV≤100MB, XLSX≤12.5MB). Read-only. Args: { resource_id: string, page?: number (default 1), page_size?: number (default 20, max 200) }.",
143
+ "requires": [
144
+ "datagouv_mcp"
145
+ ],
146
+ "executionMode": "sync",
147
+ "timeoutSeconds": 60,
148
+ "parameters": {
149
+ "resource_id": "string",
150
+ "page": "number?",
151
+ "page_size": "number?"
152
+ },
153
+ "code": "const resource_id = String(args?.resource_id ?? '').trim();\nif (!resource_id) throw new Error('datagouv_query_resource: resource_id is required');\nconst page = Number.isFinite(Number(args?.page)) ? Math.max(1, Math.trunc(Number(args.page))) : 1;\nconst ps = Number.isFinite(Number(args?.page_size)) ? Math.trunc(Number(args.page_size)) : 20;\nconst page_size = Math.max(1, Math.min(200, ps));\nconst res = await callProvider('datagouv_mcp', 'POST', 'query_resource_data', { resource_id, page, page_size });\nif (res?.success === false) throw new Error(String(res?.error || 'datagouv MCP query_resource_data failed'));\nconst payload = res?.body !== undefined ? res.body : res;\nreturn { resource_id, page, page_size, result: payload };"
154
+ },
155
+ {
156
+ "name": "datagouv_search_dataservices",
157
+ "intent": "search_external",
158
+ "kind": "code",
159
+ "scope": "pod",
160
+ "description": "Search third-party APIs catalogued on data.gouv.fr (Adresse, Sirene, local APIs…). Returns metadata + base API URL; does NOT call the third-party API. Read-only. Args: { query: string, page?: number, page_size?: number }.",
161
+ "requires": [
162
+ "datagouv_mcp"
163
+ ],
164
+ "executionMode": "sync",
165
+ "timeoutSeconds": 45,
166
+ "parameters": {
167
+ "query": "string",
168
+ "page": "number?",
169
+ "page_size": "number?"
170
+ },
171
+ "code": "const query = String(args?.query ?? '').trim();\nif (!query) throw new Error('datagouv_search_dataservices: query is required');\nconst page = Number.isFinite(Number(args?.page)) ? Math.max(1, Math.trunc(Number(args.page))) : 1;\nconst ps = Number.isFinite(Number(args?.page_size)) ? Math.trunc(Number(args.page_size)) : 20;\nconst page_size = Math.max(1, Math.min(100, ps));\nconst res = await callProvider('datagouv_mcp', 'POST', 'search_dataservices', { query, page, page_size });\nif (res?.success === false) throw new Error(String(res?.error || 'datagouv MCP search_dataservices failed'));\nconst payload = res?.body !== undefined ? res.body : res;\nreturn { query, page, page_size, result: payload };"
172
+ },
173
+ {
174
+ "name": "datagouv_get_dataservice",
175
+ "intent": "fetch_record",
176
+ "kind": "code",
177
+ "scope": "pod",
178
+ "description": "Get one dataservice's metadata and OpenAPI summary (endpoints/params). Use before crystallizing a dedicated API capability for a third-party service. Read-only. Args: { dataservice_id: string }.",
179
+ "requires": [
180
+ "datagouv_mcp"
181
+ ],
182
+ "executionMode": "sync",
183
+ "timeoutSeconds": 60,
184
+ "parameters": {
185
+ "dataservice_id": "string"
186
+ },
187
+ "code": "const dataservice_id = String(args?.dataservice_id ?? '').trim();\nif (!dataservice_id) throw new Error('datagouv_get_dataservice: dataservice_id is required');\nconst infoRes = await callProvider('datagouv_mcp', 'POST', 'get_dataservice_info', { dataservice_id });\nif (infoRes?.success === false) throw new Error(String(infoRes?.error || 'datagouv MCP get_dataservice_info failed'));\nconst info = infoRes?.body !== undefined ? infoRes.body : infoRes;\nlet openapi = null;\ntry {\n const specRes = await callProvider('datagouv_mcp', 'POST', 'get_dataservice_openapi_spec', { dataservice_id });\n if (specRes?.success !== false) openapi = specRes?.body !== undefined ? specRes.body : specRes;\n} catch (_) { openapi = null; }\nreturn { dataservice_id, info, openapi };"
188
+ },
189
+ {
190
+ "name": "datagouv_capture_dataset",
191
+ "intent": "capture_into_pod",
192
+ "kind": "code",
193
+ "scope": "pod",
194
+ "description": "Fetches dataset metadata from data.gouv.fr and proposes a research entity with provenance (title, dataset_id, organization, license, URL, retrieved_at). Proposal-gated write. Args: { dataset_id: string, notes?: string }.",
195
+ "requires": [
196
+ "datagouv_mcp"
197
+ ],
198
+ "executionMode": "async",
199
+ "timeoutSeconds": 60,
200
+ "parameters": {
201
+ "dataset_id": "string",
202
+ "notes": "string?"
203
+ },
204
+ "code": "const dataset_id = String(args?.dataset_id ?? '').trim();\nif (!dataset_id) throw new Error('datagouv_capture_dataset: dataset_id is required');\nconst notes = typeof args?.notes === 'string' ? args.notes.trim() : '';\nconst res = await callProvider('datagouv_mcp', 'POST', 'get_dataset_info', { dataset_id });\nif (res?.success === false) throw new Error(String(res?.error || 'datagouv MCP get_dataset_info failed'));\nconst raw = res?.body !== undefined ? res.body : res;\n// MCP content may be text/JSON-wrapped — prefer object fields when present.\nconst info = (raw && typeof raw === 'object' && !Array.isArray(raw)) ? raw : { raw };\nconst title = String(info.title || info.name || `data.gouv dataset ${dataset_id}`);\nconst pageUrl = String(info.page || info.url || `https://www.data.gouv.fr/datasets/${dataset_id}/`);\nconst organization = info.organization?.name || info.organization || null;\nconst license = info.license || info.license_id || null;\nconst proposed = await propose.entity({\n profileSlug: 'research',\n title: title,\n properties: {\n provenance: 'connector', provider: 'data.gouv.fr',\n dataset_id: dataset_id,\n organization: organization,\n license: license,\n url: pageUrl,\n retrieved_at: new Date().toISOString(),\n notes: notes || null,\n tags: Array.isArray(info.tags) ? info.tags : null\n },\n reasoning: `Captured data.gouv.fr dataset ${dataset_id} for research with full provenance.`\n});\nreturn { success: true, dataset_id, title, pageUrl, proposed };"
205
+ }
206
+ ],
207
+ "provides": [
208
+ "search_external",
209
+ "fetch_record",
210
+ "list_records",
211
+ "capture_into_pod"
212
+ ],
213
+ "playbooks": [
214
+ {
215
+ "name": "French Open Data Research",
216
+ "description": "Guided session to find, preview, and capture French public datasets for a research question — then crystallize any repeatable lookup into a capability verb.",
217
+ "goalTemplate": "Answer the open-data research question using data.gouv.fr: discover datasets, preview resources, capture provenance, and propose a crystallized verb if the workflow is reusable.",
218
+ "params": [
219
+ {
220
+ "name": "question",
221
+ "label": "Research question",
222
+ "type": "text",
223
+ "required": true,
224
+ "description": "What French public data question are we answering? e.g. 'median apartment prices Lyon 6' or 'SIRENE lookup pattern for CRM'."
225
+ }
226
+ ],
227
+ "channelSpec": {
228
+ "type": "THREAD",
229
+ "aiReactionMode": "only_mentioned"
230
+ },
231
+ "executor": "is-agent",
232
+ "status": "draft",
233
+ "stages": [
234
+ {
235
+ "key": "discover",
236
+ "name": "Discover",
237
+ "category": "started",
238
+ "description": "Search datasets and organizations relevant to the question. Use datagouv_search_datasets and the open-data advisor skill.",
239
+ "goal": "Shortlist 1–3 datasets with clear titles, orgs, and why they fit.",
240
+ "grants": [
241
+ {
242
+ "kind": "skill",
243
+ "id": "datagouv-open-data-advisor"
244
+ },
245
+ {
246
+ "kind": "skill",
247
+ "id": "datagouv_search_datasets"
248
+ }
249
+ ],
250
+ "suggestedTasks": [
251
+ "Search catalog in French and English keywords",
252
+ "Note dataset_ids and licenses"
253
+ ]
254
+ },
255
+ {
256
+ "key": "preview",
257
+ "name": "Preview",
258
+ "category": "started",
259
+ "description": "List resources and query a small Tabular sample to learn schema.",
260
+ "goal": "Document resource_ids, columns, and row sample limits.",
261
+ "grants": [
262
+ {
263
+ "kind": "skill",
264
+ "id": "datagouv_list_resources"
265
+ },
266
+ {
267
+ "kind": "skill",
268
+ "id": "datagouv_query_resource"
269
+ },
270
+ {
271
+ "kind": "skill",
272
+ "id": "datagouv_get_dataset"
273
+ }
274
+ ]
275
+ },
276
+ {
277
+ "key": "capture",
278
+ "name": "Capture",
279
+ "category": "started",
280
+ "description": "Write research entities with provenance; answer the question from samples (not bulk dumps).",
281
+ "goal": "Captured research notes + human-readable answer with citations.",
282
+ "grants": [
283
+ {
284
+ "kind": "skill",
285
+ "id": "datagouv_capture_dataset"
286
+ }
287
+ ]
288
+ },
289
+ {
290
+ "key": "crystallize",
291
+ "name": "Crystallize",
292
+ "category": "started",
293
+ "description": "If the workflow is repeatable, propose a new capability verb (and optional automation) following the advisor crystallization protocol.",
294
+ "goal": "Either a proposed skill definition or an explicit 'not worth crystallizing' decision with reason.",
295
+ "grants": [
296
+ {
297
+ "kind": "skill",
298
+ "id": "datagouv-open-data-advisor"
299
+ },
300
+ {
301
+ "kind": "skill",
302
+ "id": "datagouv_search_dataservices"
303
+ },
304
+ {
305
+ "kind": "skill",
306
+ "id": "datagouv_get_dataservice"
307
+ }
308
+ ]
309
+ }
310
+ ]
311
+ }
312
+ ]
313
+ },
314
+ "dependencies": []
315
+ }
@@ -0,0 +1,157 @@
1
+ {
2
+ "apiVersion": "synap/v1",
3
+ "kind": "capability",
4
+ "meta": {
5
+ "slug": "discord-bot",
6
+ "name": "Discord Bot",
7
+ "description": "Connects your Discord bot to Synap: links channels to CRM records, brings messages into your workspace and posts agent updates back. Includes Client Onboarding and Lead Outreach playbooks. Needs a Discord bot token.",
8
+ "tags": [
9
+ "capability"
10
+ ],
11
+ "isPublic": true,
12
+ "syncByDefault": true
13
+ },
14
+ "spec": {
15
+ "_generated": "from telegram-discord-bridge/src/synapCapabilities.js — do not hand-edit; run `pnpm sync:discord-cap` in synap-control-plane-api",
16
+ "key": "discord-bot",
17
+ "name": "Discord Bot",
18
+ "description": "The bot is the agent's Discord presence — links channels to CRM entities, ingests messages into the productivity pipeline, and posts agent feedback. It owns the Discord bot token as a vault credential.",
19
+ "metadata": {
20
+ "mode": "standing"
21
+ },
22
+ "vault": [
23
+ {
24
+ "ref": "discord-bot-token",
25
+ "name": "Discord Bot Token",
26
+ "value": "{{botToken}}",
27
+ "type": "api_key",
28
+ "service": "discord",
29
+ "description": "Bot token used to authenticate the Discord gateway + outbound sends."
30
+ }
31
+ ],
32
+ "tools": [
33
+ {
34
+ "name": "discord",
35
+ "kind": "external",
36
+ "description": "Discord channel source + outbound bot.",
37
+ "credentialRef": "discord-bot-token",
38
+ "metadata": {
39
+ "discord": {
40
+ "categoryMap": {},
41
+ "categoryRules": {},
42
+ "reactCapture": false,
43
+ "feedbackRouting": "team",
44
+ "feedbackChannel": "",
45
+ "teamForum": "",
46
+ "captureChannel": "",
47
+ "captureFlows": [],
48
+ "mailFeed": {
49
+ "enabled": false,
50
+ "channelId": "",
51
+ "gmailQuery": "",
52
+ "senderAllow": [],
53
+ "senderDeny": [],
54
+ "mutedCategories": [],
55
+ "connectionId": ""
56
+ },
57
+ "eventSync": {
58
+ "enabled": false,
59
+ "sources": [
60
+ "event",
61
+ "calendar",
62
+ "deadline"
63
+ ],
64
+ "windowDays": 60,
65
+ "announceChannelId": "",
66
+ "connectionId": ""
67
+ },
68
+ "configSchema": [
69
+ {
70
+ "key": "reactCapture",
71
+ "label": "Capture on ✅ react",
72
+ "valueType": "boolean"
73
+ },
74
+ {
75
+ "key": "feedbackRouting",
76
+ "label": "Bot feedback routing",
77
+ "valueType": "string",
78
+ "inputType": "select",
79
+ "enumValues": [
80
+ "team",
81
+ "off"
82
+ ]
83
+ },
84
+ {
85
+ "key": "feedbackChannel",
86
+ "label": "Bot feedback channel (Discord channel id)",
87
+ "valueType": "string"
88
+ },
89
+ {
90
+ "key": "teamForum",
91
+ "label": "Team forum (Discord forum id for auto-created team threads)",
92
+ "valueType": "string"
93
+ },
94
+ {
95
+ "key": "captureChannel",
96
+ "label": "Capture channel (Discord channel id for ambient AI capture)",
97
+ "valueType": "string"
98
+ },
99
+ {
100
+ "key": "captureFlows",
101
+ "label": "Capture flows ([{channelId, focus, instructions}] — per-channel capture focus)",
102
+ "valueType": "json"
103
+ },
104
+ {
105
+ "key": "categoryRules",
106
+ "label": "Section rules (category → entity type + optional partner link)",
107
+ "valueType": "json"
108
+ },
109
+ {
110
+ "key": "mailFeed",
111
+ "label": "Mail feed ({enabled, channelId, gmailQuery, senderAllow, senderDeny, mutedCategories})",
112
+ "valueType": "json"
113
+ },
114
+ {
115
+ "key": "eventSync",
116
+ "label": "Event sync ({enabled, sources, windowDays, announceChannelId})",
117
+ "valueType": "json"
118
+ }
119
+ ]
120
+ }
121
+ }
122
+ }
123
+ ],
124
+ "playbooks": [
125
+ {
126
+ "name": "Client Onboarding",
127
+ "description": "Stand up a new client: ensure their CRM entity, room, and threads exist so the team has one place to work from.",
128
+ "goalTemplate": "Onboard the client \"{clientName}\". Ensure a `client` entity exists for them (create it if missing), set up their dedicated room/channel for collaboration, and post a short welcome summary of next steps. Surface anything still missing for kickoff.",
129
+ "params": [
130
+ {
131
+ "name": "clientName",
132
+ "label": "Client name",
133
+ "type": "text",
134
+ "required": true
135
+ }
136
+ ],
137
+ "status": "active"
138
+ },
139
+ {
140
+ "name": "Lead Outreach",
141
+ "description": "Per lead: draft a personalized first-touch message and propose sending it (proposal-gated — nothing goes out without approval).",
142
+ "goalTemplate": "Reach out to the lead \"{leadName}\". Review what we know about them, draft a short, personalized first-touch message tailored to their context, and PROPOSE sending it (connect + message). Do not send anything without explicit approval.",
143
+ "params": [
144
+ {
145
+ "name": "leadName",
146
+ "label": "Lead name",
147
+ "type": "text",
148
+ "required": true
149
+ }
150
+ ],
151
+ "status": "active"
152
+ }
153
+ ],
154
+ "provides": []
155
+ },
156
+ "dependencies": []
157
+ }