@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
@@ -1,486 +0,0 @@
1
- # Outreach & Comms workspace template
2
- # A standalone, channel-first outreach workspace: personalized LinkedIn and
3
- # email sequences run against people and companies you already track pod-wide.
4
- # Owns the outreach data (campaigns + individual touches) and the playbook
5
- # that drafts and sends the next message — not a CRM, not a content calendar.
6
- # Reuses the pod-wide `person`/`company` kinds so a contact worked here is the
7
- # same entity a CRM or Ecosystem workspace sees, not a workspace-local twin.
8
-
9
- meta:
10
- slug: outreach-comms
11
- domain: revenue
12
- name: Outreach & Comms
13
- description: Personalized LinkedIn and email outreach — sequenced touches against real people and companies, drafted and sent by an agent.
14
- icon: send
15
- color: "#0EA5E9"
16
- tags: [outreach, linkedin, email, comms, sequences]
17
- isPublic: true
18
-
19
- workspace:
20
- name: Outreach & Comms
21
- description: Personalized LinkedIn and email outreach — sequenced touches against real people and companies, drafted and sent by an agent.
22
- subtype: outreach-comms
23
- visibility: pod_visible
24
- capabilities:
25
- - outreach.campaigns
26
- - outreach.touches
27
- sourceRoles:
28
- outreach: provider
29
-
30
- profiles:
31
- # ── Actors ────────────────────────────────────────────────────────────────
32
- # The pod-wide person and company kinds — declared minimally so campaign and
33
- # touch links resolve. Kept light on purpose: identity lives elsewhere.
34
- - slug: person
35
- displayName: Person
36
- icon: user
37
- color: amber
38
- description: A person you are reaching out to — a prospect, partner, or contact.
39
- properties:
40
- - slug: email
41
- label: Email
42
- valueType: string
43
- inputType: email
44
- - slug: notes
45
- label: Notes
46
- valueType: string
47
- inputType: textarea
48
-
49
- - slug: company
50
- displayName: Company
51
- icon: building-2
52
- color: "#10B981"
53
- description: A company you are reaching out to.
54
- properties:
55
- - slug: website
56
- label: Website
57
- valueType: string
58
- inputType: url
59
- - slug: industry
60
- label: Industry
61
- valueType: string
62
- inputType: text
63
-
64
- # ── Outreach data (owned here) ───────────────────────────────────────────
65
- - slug: outreach-campaign
66
- displayName: Outreach Campaign
67
- icon: target
68
- color: sky
69
- description: A sequence of personalized touches aimed at a segment — the "why we're reaching out" and the offer.
70
- properties:
71
- - slug: channel
72
- label: Channel
73
- valueType: string
74
- inputType: select
75
- enumValues: [linkedin, email, both]
76
- constraints: { defaultValue: linkedin }
77
- - slug: status
78
- label: Status
79
- valueType: string
80
- inputType: select
81
- enumValues: [draft, active, paused, completed]
82
- constraints: { defaultValue: draft }
83
- - slug: targetSegment
84
- label: Target segment
85
- valueType: string
86
- inputType: text
87
- placeholder: e.g. Series A-B B2B SaaS founders
88
- - slug: valueProp
89
- label: Value proposition
90
- valueType: string
91
- inputType: textarea
92
- - slug: callToAction
93
- label: Call to action
94
- valueType: string
95
- inputType: text
96
- - slug: startDate
97
- label: Start date
98
- valueType: date
99
- inputType: date
100
- - slug: notes
101
- label: Notes
102
- valueType: string
103
- inputType: textarea
104
-
105
- - slug: outreach-touch
106
- displayName: Outreach Touch
107
- icon: message-circle
108
- color: blue
109
- description: A single message sent (or drafted) to one person as part of a campaign.
110
- properties:
111
- - slug: channel
112
- label: Channel
113
- valueType: string
114
- inputType: select
115
- enumValues: [linkedin, email]
116
- - slug: touchType
117
- label: Touch type
118
- valueType: string
119
- inputType: select
120
- enumValues: [connection_request, follow_up, intro_email, reply]
121
- - slug: status
122
- label: Status
123
- valueType: string
124
- inputType: select
125
- enumValues: [drafted, sent, opened, replied, bounced, no_response]
126
- constraints: { defaultValue: drafted }
127
- - slug: sentDate
128
- label: Sent date
129
- valueType: date
130
- inputType: date
131
- - slug: messageContent
132
- label: Message content
133
- valueType: string
134
- inputType: textarea
135
-
136
- views:
137
- - name: Campaigns
138
- slug: outreach-campaigns
139
- type: table
140
- scopeProfileSlug: outreach-campaign
141
- description: Every outreach sequence, its channel, and its status.
142
- config:
143
- columns: [title, channel, status, targetSegment, startDate]
144
- defaultView: true
145
- - name: Touches
146
- slug: outreach-touches
147
- type: kanban
148
- scopeProfileSlug: outreach-touch
149
- groupBy: status
150
- description: Individual messages, grouped by where they stand — drafted through replied.
151
- config:
152
- groupBy: status
153
- cardFields: [channel, touchType, sentDate]
154
-
155
- entityLinks:
156
- - sourceProfileSlug: outreach-campaign
157
- targetProfileSlug: person
158
- type: targets
159
- label: Targets
160
- - sourceProfileSlug: outreach-campaign
161
- targetProfileSlug: company
162
- type: targets
163
- label: Targets
164
- - sourceProfileSlug: outreach-touch
165
- targetProfileSlug: person
166
- type: sent_to
167
- label: Sent to
168
- - sourceProfileSlug: outreach-touch
169
- targetProfileSlug: outreach-campaign
170
- type: part_of
171
- label: Part of
172
-
173
- # Playbook — drafts and sends the next personalized touch for a target, using
174
- # whatever we already know about them so the message isn't generic. Bound to
175
- # the campaign kind so a captured/updated campaign can offer this as a session.
176
- playbooks:
177
- - name: Personalized Outreach
178
- description: Draft a personalized LinkedIn or email message to a target contact, send it, and log the touch.
179
- goalTemplate: >-
180
- Reach out to {target} on {channel} as part of the "{campaign}" campaign.
181
- Research them first using what we already know (their company, role, and
182
- any prior touches) so the message is specific, not generic. Campaign
183
- context — value proposition and call to action: {campaignContext}. Draft
184
- the message, send it via {channel}, then create an outreach-touch record
185
- logging what was sent and update the target's contact record with the
186
- outcome.
187
- subjectProfile:
188
- profileSlug: outreach-campaign
189
- params:
190
- - { name: target, type: entity, label: Target contact, required: true }
191
- - { name: campaign, type: text, label: Campaign name, required: true }
192
- - { name: channel, type: choice, label: Channel, defaultValue: linkedin }
193
- - {
194
- name: campaignContext,
195
- type: text,
196
- label: Value prop + call to action,
197
- }
198
- executor: is-agent
199
- grants:
200
- - linkedin_send_invite
201
- - unipile_send_message
202
- - gmail_send
203
- - entity.create
204
- status: active
205
-
206
- # ── LinkedIn conversation ingest (PURE-CONFIG automation — PROPOSAL) ─────────
207
- # Pulls LinkedIn threads via Unipile and records each as an EXTERNAL channel +
208
- # messages through the GENERIC `channel.ingest` verb. No provider code in the
209
- # pod — this composes existing verbs (unipile_list_accounts /
210
- # unipile_list_conversations / unipile_list_messages + channel.ingest).
211
- #
212
- # TRIGGER MODEL — ONE automation, both jobs (no high-freq polling):
213
- # • RECONCILIATION: `triggerType: cron` at a LOW frequency (daily 06:00).
214
- # • BACKFILL / on-demand: fire the SAME automation via
215
- # `POST /automations/{id}/trigger` (MCP `synap_trigger_automation`), which
216
- # "bypasses the automation's normal trigger config" and runs the flow once.
217
- # channel.ingest is idempotent, so cron sweeps and manual backfills are safe to
218
- # overlap and repeat.
219
- #
220
- # ⚠️ NEEDS-REVIEW — TWO verified engine constraints shape this flow; see the
221
- # handoff report. (1) The automation engine has NO nested loops
222
- # (LOOP_BODY_NODE_TYPES excludes `loop`/`sub_automation`), so the requested
223
- # `loop conversations → loop messages → channel.ingest per message` graph is
224
- # not expressible. This does ONE loop over conversations and hands each thread's
225
- # whole `messages` array to channel.ingest in a single call. (2) A `transform`
226
- # `map:` pipe can only project a single field/string per item, so it cannot
227
- # normalize messages into `{text, sentAt, participant, idempotencySeed}` objects
228
- # in-flow. => channel.ingest must accept a BATCH `messages: [...]` of raw
229
- # provider rows and do the per-message normalization + idempotent dedup
230
- # SERVER-SIDE. That is a contract change vs the single-message signature.
231
- # Kept `status: draft` until that batch shape ships; then activate.
232
- automations:
233
- - key: linkedin-conversation-ingest
234
- name: LinkedIn conversation ingest
235
- description: >-
236
- Pull LinkedIn conversations via Unipile and record each thread as an
237
- external channel + its messages through channel.ingest (idempotent, so
238
- re-runs are safe). Cron = low-frequency reconciliation; manual trigger =
239
- on-demand backfill.
240
- triggerType: cron
241
- triggerConfig:
242
- expression: "0 6 * * *"
243
- status: draft
244
- flow:
245
- nodes:
246
- - id: trigger
247
- type: trigger
248
- position: { x: 0, y: 0 }
249
- data:
250
- label: Daily 06:00 reconciliation (also fired manually for backfill)
251
- triggerType: cron
252
- config:
253
- expression: "0 6 * * *"
254
-
255
- # Resolve the connected account AT RUNTIME so the cron sweep needs no
256
- # payload. A multi-account / multi-provider pod would still need a
257
- # run-param accountId to sweep MORE than the first LinkedIn account — a
258
- # per-account sweep would itself need the nested loop this engine lacks
259
- # (secondary follow-up, noted in the report).
260
- - id: list-accounts
261
- type: capability
262
- position: { x: 0, y: 120 }
263
- data:
264
- label: Resolve the connected Unipile account
265
- verbId: unipile_list_accounts
266
-
267
- # F5 — PROVIDER FILTER. `unipile_list_accounts` returns RAW Unipile v2
268
- # account rows and a pod can connect several providers, so a non-LinkedIn
269
- # account (WhatsApp / Telegram / Gmail) can sit at index 0. Taking a blind
270
- # `accounts.0` would ingest that provider's threads AS linkedin. This
271
- # `transform` node's array `filter:` pipe keeps ONLY LinkedIn accounts;
272
- # every step below takes `.0` of the FILTERED list.
273
- # Field: the predicate matches the RAW Unipile v2 account shape
274
- # `type: 'LINKEDIN' | 'GMAIL' | 'WHATSAPP' | …` (verified in
275
- # UnipileConnector's UnipileAccountSchema, NOT the capability's loose
276
- # "provider" prose). evaluateCondition does an EXACT, case-sensitive
277
- # `==`, hence the uppercase literal.
278
- # Failure mode: if no LinkedIn account is connected (or the raw field
279
- # shape ever drifts) the filtered list is empty → the accountId below
280
- # resolves to "" → the run FAILS VISIBLY at list-conversations. It never
281
- # silently ingests the wrong provider — that is the point of F5.
282
- # Multi-LinkedIn-account: still takes the first; a run-param accountId
283
- # is the multi-account follow-up (noted in the report).
284
- - id: filter-linkedin-account
285
- type: transform
286
- position: { x: 0, y: 180 }
287
- data:
288
- label: Keep only LinkedIn Unipile accounts
289
- expression: "{{steps.list-accounts.output.accounts}} | filter:item.type == 'LINKEDIN'"
290
-
291
- - id: list-conversations
292
- type: capability
293
- position: { x: 0, y: 240 }
294
- data:
295
- label: List LinkedIn conversations for the account
296
- verbId: unipile_list_conversations
297
- inputMapping:
298
- accountId: "{{steps.filter-linkedin-account.output.result.0.id}}"
299
-
300
- # NOTE: the automation engine caps loops at MAX_LOOP_ITERATIONS=100 per run
301
- # (logs a warning, then truncates). So one cron pass reconciles the 100
302
- # most-recent conversations; accounts with >100 threads need either a
303
- # newest-first list (so the active threads are always covered) or a paged
304
- # sweep (blocked today — would need the nested loops the engine lacks).
305
- # Fine for the current dogfood scale; revisit if a user exceeds ~100 threads.
306
- - id: conversations-loop
307
- type: loop
308
- position: { x: 0, y: 360 }
309
- data:
310
- label: For each conversation
311
- iteratorExpression: steps.list-conversations.output.conversations
312
- itemVariable: conversation
313
-
314
- # Loop body (owned by conversations-loop): list this thread's messages,
315
- # then ingest. `{{loop.item.id}}` is the chat/thread id for THIS
316
- # iteration; `steps.list-messages` is re-bound per iteration.
317
- - id: list-messages
318
- type: capability
319
- position: { x: 0, y: 480 }
320
- data:
321
- label: List this thread's messages
322
- verbId: unipile_list_messages
323
- inputMapping:
324
- threadId: "{{loop.item.id}}"
325
- accountId: "{{steps.filter-linkedin-account.output.result.0.id}}"
326
-
327
- # GENERIC ingest — records the external channel for this thread and its
328
- # messages, idempotently (dedup on a per-message idempotency seed derived
329
- # SERVER-SIDE, e.g. `${externalId}:${sentAt}:${body}`). See the ⚠️ note:
330
- # `messages` is a BATCH of raw provider rows (pending channel.ingest's
331
- # batch contract).
332
- - id: ingest
333
- type: capability
334
- position: { x: 0, y: 600 }
335
- data:
336
- label: Ingest thread + messages (idempotent, generic)
337
- verbId: channel.ingest
338
- inputMapping:
339
- provider: linkedin
340
- externalId: "{{loop.item.id}}"
341
- title: "{{loop.item.name}}"
342
- accountExternalId: "{{steps.filter-linkedin-account.output.result.0.id}}"
343
- # F1 — TARGET THE CRM WORKSPACE. Without this, channel.ingest lands
344
- # in the automation's OWN workspace, but the dashboard inbox reads
345
- # "The arch CRM". Single-tenant target = the inbox/CRM workspace.
346
- # TODO(multi-tenant): make this an install/run param instead of a
347
- # literal (the flow schema has no template-var/param mechanism for a
348
- # capability inputMapping today, so a documented literal is the
349
- # single-tenant path — see the report).
350
- workspaceId: "499328b7-fd35-4143-b1bc-67b9e45d9b4b"
351
- # F2 — SUPPRESS THE BACKFILL STORM. This is a poll / reconciliation
352
- # of HISTORICAL messages, so it must NOT emit
353
- # `external_message.received` per message (channel resolve + dedup
354
- # insert still run). Without this, one backfill of N threads fans
355
- # out through the webhook + automation-trigger reactors N×messages.
356
- suppressSideEffects: true
357
- # BATCH mode: hand the whole thread's messages[] to the generic verb
358
- # in ONE call (the engine has no nested loops). channel.ingest stays
359
- # provider-agnostic — messageMap tells it (in CONFIG) where each field
360
- # lives inside a raw Unipile v2 message row. Verified live 2026-07-27:
361
- # a message = { id, text, timestamp (ISO), sender_id, is_sender, ... }.
362
- messages: "{{steps.list-messages.output.messages}}"
363
- messageMap:
364
- text: text
365
- id: id
366
- sentAt: timestamp
367
- # F3 — DIRECTION. `is_sender` (dot-path to a boolean per row) marks
368
- # the operator's OWN sent messages as OUTBOUND so the inbox renders
369
- # them right-aligned, instead of everything looking inbound.
370
- isOutbound: is_sender
371
- # F6 — participantExternalId DROPPED on purpose. link-at-birth
372
- # binds the channel to the participant of the first-processed
373
- # (newest) message, which — when that message is the account
374
- # OWNER's own reply — mis-binds the whole thread to yourself. The
375
- # channel `title` already carries the conversation (contact) name,
376
- # so dropping the per-message sender id lets link-at-birth avoid
377
- # the mis-bind.
378
- edges:
379
- - { id: e-trigger-accounts, source: trigger, target: list-accounts }
380
- - {
381
- id: e-accounts-filter,
382
- source: list-accounts,
383
- target: filter-linkedin-account,
384
- }
385
- - {
386
- id: e-filter-convos,
387
- source: filter-linkedin-account,
388
- target: list-conversations,
389
- }
390
- - {
391
- id: e-convos-loop,
392
- source: list-conversations,
393
- target: conversations-loop,
394
- }
395
- - {
396
- id: e-loop-messages,
397
- source: conversations-loop,
398
- target: list-messages,
399
- }
400
- - { id: e-messages-ingest, source: list-messages, target: ingest }
401
-
402
- # LinkedIn send/search via Unipile, email send via Gmail (nango-google). The
403
- # user connects each once on install; a missing key fails gracefully per-skill.
404
- integrations:
405
- - templateKey: unipile-linkedin
406
- - templateKey: nango-google
407
-
408
- onboarding:
409
- goal: >
410
- Stand up an outreach motion — who we're targeting, on which channel, with
411
- what offer — so the agent can start drafting and sending real touches
412
- instead of waiting for a blank campaign.
413
- framing: |
414
- THE OUTBOUND LEAD: Act as a sharp SDR/outbound lead. Push for a SPECIFIC
415
- segment and a SPECIFIC offer, not "reach out to everyone about our product".
416
- A campaign with no segment and no value prop is just a contact list.
417
- expertise:
418
- starters:
419
- - >
420
- Name the segment as a person, not a market — "Head of Growth at
421
- seed-to-Series-A B2B SaaS", not "SaaS companies". The agent personalizes
422
- against a person, not a category.
423
- - >
424
- Every campaign needs ONE call to action, stated plainly — a call, a demo,
425
- a reply. If the founder gives a vague goal ("build awareness"), push for
426
- the concrete next step a touch should provoke.
427
- blindSpots:
428
- - >
429
- Founders default to email when LinkedIn converts better for cold B2B —
430
- ask which channel the target segment actually lives on before defaulting.
431
- - >
432
- A campaign with no target contacts yet is fine to create, but flag it —
433
- the first touch needs at least one real person or company to reach.
434
- bar: >
435
- At least one real campaign exists with a named segment, a stated value
436
- prop and call to action, and — ideally — a first target contact ready for
437
- the Personalized Outreach playbook to run against.
438
- collect:
439
- - profileSlug: outreach-campaign
440
- what: The outreach sequences to run — channel, target segment, and offer.
441
- cardinality: few
442
- keyFields: [channel, targetSegment, valueProp, callToAction]
443
- - profileSlug: person
444
- what: The first contacts to target with this campaign.
445
- cardinality: few
446
- keyFields: [email]
447
- openingQuestions:
448
- - "Who are you trying to reach — what role, at what kind of company?"
449
- - "LinkedIn, email, or both?"
450
- - "What's the one thing you want them to do after reading your message?"
451
- doneWhen: At least one campaign captured with a channel, segment, and value prop, plus one target contact.
452
-
453
- app:
454
- kind: stored
455
- cellKey: entity-detail
456
-
457
- layout:
458
- defaultView: Campaigns
459
- defaultApp: null
460
- pinnedApps: [dashboard, data, chat]
461
- sidebarItems:
462
- - kind: view
463
- viewName: Campaigns
464
- label: Campaigns
465
- icon: target
466
- - kind: view
467
- viewName: Touches
468
- label: Touches
469
- icon: message-circle
470
- - kind: app
471
- appId: data
472
- label: Data
473
- icon: database
474
-
475
- bento:
476
- # Distinct from the "Campaigns" table it embeds — see meetings-knowledge:
477
- # the bento becomes its own view row, so a shared name collides in the
478
- # switcher and makes layout.defaultView ambiguous.
479
- viewName: Outreach Home
480
- blocks:
481
- - kind: view
482
- viewName: Campaigns
483
- pos: { x: 0, y: 0, w: 8, h: 5 }
484
- - kind: view
485
- viewName: Touches
486
- pos: { x: 8, y: 0, w: 4, h: 5 }
package/src/the-arch.yaml DELETED
@@ -1,201 +0,0 @@
1
- # The Arch — the private command layer (addon on top of Enterprise OS)
2
- # =====================================================================
3
- # A PRIVATE suite template (isPublic: false → served only through the Control
4
- # Plane to its owner, never in the public catalog). It is the full company brain:
5
- # the whole public Enterprise OS PLUS the private flagship workspaces that make it
6
- # "The Arch" — the grant pipeline, the web3 ecosystem overlay, and the dev
7
- # dashboard.
8
- #
9
- # What it composes:
10
- # • enterprise-os — the whole public operating core (transitively brings
11
- # foundation / ecosystem / operations / crm)
12
- # • grants — the grant-agency pipeline (composes onto operations)
13
- # • blockchain-ecosystem — web3 market actors + relations (composes onto ecosystem)
14
- # • dev-dashboard — the engineering/ops dashboard
15
- #
16
- # Ordering is safe by construction: `require` is deps-first, and grants /
17
- # blockchain-ecosystem declare their OWN compose bases (operations / ecosystem)
18
- # which enterprise-os installs first — so the overlays always land on a base that
19
- # already exists. Idempotent: install Enterprise OS first, then The Arch, and the
20
- # resolver reuses the OS workspaces instead of duplicating them.
21
-
22
- meta:
23
- slug: the-arch
24
- domain: company
25
- name: The Arch
26
- description: The complete private company brain — the whole Enterprise OS plus the grant pipeline, the web3 ecosystem overlay, and the dev dashboard.
27
- icon: landmark
28
- color: "#7C3AED"
29
- tags: [suite, private, arch, grants, web3, flagship]
30
- isPublic: false
31
-
32
- # `require` (deps-first). enterprise-os brings the public core; the three private
33
- # flagships overlay onto it (grants→operations, blockchain-ecosystem→ecosystem)
34
- # or stand alongside it (dev-dashboard). Transitive: enterprise-os's own deps
35
- # resolve before the overlays that compose onto them.
36
- dependencies:
37
- - slug: enterprise-os
38
- kind: workspace
39
- relation: require
40
- reason: "The whole public operating core — strategy, market, operations, and pipeline — that the private flagships extend."
41
- - slug: grants
42
- kind: workspace
43
- relation: require
44
- reason: "The grant-agency pipeline; composes its operations onto the Operations workspace the OS installs."
45
- - slug: blockchain-ecosystem
46
- kind: workspace
47
- relation: require
48
- reason: "Web3 market actors + relations; composes onto the Ecosystem workspace the OS installs."
49
- - slug: dev-dashboard
50
- kind: workspace
51
- relation: require
52
- reason: "The engineering / ops dashboard — the build-side view of the company."
53
- - slug: networking
54
- kind: workspace
55
- relation: require
56
- reason: "The partner-intro layer — need → intro-matcher → intro → billed_as → deal, with the A↔B confidentiality firewall; the Stellar Client-Sync emits needs that depend on it."
57
-
58
- workspace:
59
- name: The Arch
60
- description: The private command layer over the full company brain — track the cross-workspace initiatives that span the operating system and its private flagships.
61
- subtype: the-arch
62
- visibility: private
63
-
64
- profiles:
65
- # The Arch's one native profile: a cross-cutting initiative that spans several
66
- # of the workspaces this suite installs (a grant round that touches operations,
67
- # ecosystem, and the dev dashboard, say). The place to stand above the lenses.
68
- - slug: initiative
69
- displayName: Initiative
70
- icon: flag
71
- color: "#7C3AED"
72
- description: A cross-workspace initiative that spans the operating system and its private flagships.
73
- properties:
74
- - slug: summary
75
- label: Summary
76
- valueType: string
77
- inputType: textarea
78
- - slug: stage
79
- label: Stage
80
- valueType: string
81
- inputType: select
82
- enumValues: [shaping, active, blocked, shipped, archived]
83
- constraints: { defaultValue: shaping }
84
- - slug: lead
85
- label: Lead
86
- valueType: string
87
- inputType: text
88
- - slug: priority
89
- label: Priority
90
- valueType: string
91
- inputType: select
92
- enumValues: [low, medium, high, critical]
93
- constraints: { defaultValue: medium }
94
- - slug: dueDate
95
- label: Due Date
96
- valueType: date
97
- inputType: date
98
-
99
- views:
100
- - name: Initiatives
101
- slug: initiatives
102
- type: table
103
- scopeProfileSlug: initiative
104
- description: The cross-workspace initiatives spanning the full company brain, by stage and priority.
105
- defaultView: true
106
- config:
107
- columns: [title, stage, priority, lead, dueDate]
108
- - name: Initiative Board
109
- slug: initiative-board
110
- type: kanban
111
- scopeProfileSlug: initiative
112
- description: Initiatives grouped by stage — the command view over everything in flight.
113
- config:
114
- groupBy: stage
115
-
116
- # The Arch now OWNS the per-client comms digest capability. `client-comms-report`
117
- # is the one capability no constituent template installs today — the portable,
118
- # message-only client digest that any pod can run. The Arch, as the full company
119
- # brain, is where it belongs: it rides in alongside the operations-native durable
120
- # briefing so the founder has BOTH the entity-first record and the lightweight
121
- # recap. (discord-bot / agency-skills / stellar-grant-client already ride in via
122
- # the `grants` constituent's own integrations, so they are not re-declared here.)
123
- integrations:
124
- - templateKey: client-comms-report
125
- # The Arch's OWN backend agents, callable from Synap over A2A (the reverse of the
126
- # consume-a-service connectors): discover + dispatch the read-only intelligence
127
- # agents. Reachable surface is bounded by the pasted A2A key's server-side scope.
128
- - templateKey: arch-backend
129
-
130
- onboarding:
131
- goal: >
132
- Name the cross-workspace initiatives that span the operating system and its
133
- private flagships — the few big things in flight that touch more than one
134
- lens — so The Arch is a real command layer, not just an aggregate of apps.
135
- framing: |
136
- THE FOUNDER'S COMMAND LAYER: Act from the seat above every lens. The whole
137
- company brain is installed — operating core plus the private grant, web3, and
138
- dev flagships. Your job is to surface the handful of initiatives that cut
139
- across them and give each a stage, a lead, and a priority.
140
- expertise:
141
- starters:
142
- - >
143
- Name the cross-cutting few. An initiative earns a place here only if it
144
- spans more than one workspace — a grant round that pulls in operations,
145
- ecosystem, and dev. Single-lens work stays in its lens.
146
- - >
147
- Give each initiative a real stage and lead. Shaping / active / blocked /
148
- shipped is the honest status; a lead is who to ask. Without them the
149
- command layer is a wish list.
150
- blindSpots:
151
- - >
152
- Everything marked "high priority" is the same as nothing marked. Force
153
- the ranking — what is actually critical this week?
154
- - >
155
- A blocked initiative with no note about the blocker is invisible risk.
156
- Name what is stuck and on whom.
157
- bar: >
158
- A short command board: the few genuinely cross-workspace initiatives, each
159
- with a stage, a lead, and an honest priority — sitting over a fully
160
- installed company brain.
161
- collect:
162
- - profileSlug: initiative
163
- what: The cross-workspace initiatives currently in flight.
164
- cardinality: few
165
- keyFields: [stage, priority, lead]
166
- openingQuestions:
167
- - "What are the few big initiatives in flight that span more than one part of the company?"
168
- - "For each, what stage is it in and who is the lead?"
169
- doneWhen: A few cross-workspace initiatives captured, each with a stage and a lead.
170
-
171
- app:
172
- kind: stored
173
- cellKey: entity-detail
174
-
175
- layout:
176
- defaultView: Initiatives
177
- defaultApp: null
178
- pinnedApps: [dashboard, data]
179
- sidebarItems:
180
- - kind: view
181
- viewName: Initiatives
182
- label: Initiatives
183
- icon: flag
184
- - kind: view
185
- viewName: Initiative Board
186
- label: Board
187
- icon: kanban-square
188
- - kind: app
189
- appId: data
190
- label: Data
191
- icon: database
192
-
193
- bento:
194
- viewName: Initiatives
195
- blocks:
196
- - kind: view
197
- viewName: Initiatives
198
- pos: { x: 0, y: 0, w: 8, h: 4 }
199
- - kind: view
200
- viewName: Initiative Board
201
- pos: { x: 8, y: 0, w: 4, h: 4 }