@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
package/src/types.ts CHANGED
@@ -1,3 +1,21 @@
1
+ import type { ProfilePresentation } from "@synap-core/types/presentation";
2
+ import type {
3
+ SpaceBrief,
4
+ SpaceBriefAnchor,
5
+ SpaceBriefCollectTarget,
6
+ SpaceBriefExpertise,
7
+ SpaceBriefFetchHint,
8
+ SpaceTemplateRule,
9
+ SpaceTemplateSkill,
10
+ } from "@synap-core/types/space-brief";
11
+
12
+ // The intent vocabulary is imported as a TYPE here (no runtime import), so this
13
+ // file keeps its "zero runtime imports" property that `build.mjs` depends on —
14
+ // it loads `validate.ts` under Node's type-stripper BEFORE `tsup` builds dist/.
15
+ // The RUNTIME membership test lives in `validate.ts`, which is the only place
16
+ // that needs a value.
17
+ import type { CapabilityIntentSlug } from "@synap-core/types/capability-intents";
18
+
1
19
  /**
2
20
  * @synap-core/workspace-templates — Types
3
21
  *
@@ -71,6 +89,14 @@ export type WorkspacePrimarySurface =
71
89
  kind: "url";
72
90
  url: string;
73
91
  title?: string;
92
+ /**
93
+ * The pod app this website is (spec 17 §7.1): its Client ID Metadata
94
+ * Document URL. A launch hint only: the Browser opens the site with the
95
+ * space's pod `iss` so the app starts that pod's OAuth flow. It grants
96
+ * no identity, bridge or credential; the site stays an unprivileged URL.
97
+ * Mirrors the pod's `WorkspacePrimarySurface` (@synap/database).
98
+ */
99
+ podApp?: { clientId: string };
74
100
  }
75
101
  | {
76
102
  kind: "view";
@@ -152,6 +178,79 @@ export interface TemplateProfile {
152
178
  /** For profileKind='role': which base-kind profile slugs this role can attach to. */
153
179
  applicableKinds?: string[];
154
180
  properties: TemplateProperty[];
181
+ /**
182
+ * The kind's / role's ONE lifecycle (work model L1): which select property it
183
+ * is, and a category for each of its options. The pod folds the options onto
184
+ * that property and declares it (`declareLifecycle`); boards, pipelines and
185
+ * governance then read the category, never the option name.
186
+ * `validate.ts` (`lifecycle-*` rules) requires the option keys to be the
187
+ * property's `enumValues`, same order, and every template that declares this
188
+ * profile to declare the same lifecycle.
189
+ *
190
+ * This is the COMPILED shape. The YAML may instead adopt one of the ten base
191
+ * lifecycles (`TemplateLifecycleAdoption`, `lifecycle-presets.ts`) and may
192
+ * omit the select's `enumValues`; `resolveLifecyclePresets` compiles both
193
+ * into this shape before validation, generation and publish.
194
+ */
195
+ lifecycle?: TemplateLifecycle;
196
+ /**
197
+ * How entities of this kind PRESENT themselves (entity rendering, decision
198
+ * 8): the family (media · document · link · record · work), where its media
199
+ * lives, and optional per-altitude fields. Stored on the pod as
200
+ * `uiHints.presentation` and converged on every apply. Parsed by the ONE
201
+ * parser, `parseProfilePresentation` (`@synap-core/types/presentation`);
202
+ * `validate.ts` (`presentation-*` rules) also requires every named property
203
+ * to exist on this profile and every declaration of the slug to agree.
204
+ */
205
+ presentation?: ProfilePresentation;
206
+ }
207
+
208
+ /** Fixed categories (`@synap-core/types/lifecycle` LIFECYCLE_CATEGORIES). */
209
+ export type TemplateLifecycleCategory = "open" | "active" | "paused" | "done" | "lost";
210
+
211
+ export interface TemplateLifecycleOption {
212
+ /** The stored value — one of the property's `enumValues`. */
213
+ key: string;
214
+ label?: string;
215
+ category: TemplateLifecycleCategory;
216
+ /** A `UnitTone` token; absent ⇒ the category's default tone. */
217
+ tone?: string;
218
+ /** Only a person may move a thing INTO this option. */
219
+ humanOnly?: boolean;
220
+ /**
221
+ * Days a thing may sit in this option before it is STUCK (an intent
222
+ * surface's Stuck count). Whole days, 1–3650; open/active/paused only.
223
+ */
224
+ stuckAfterDays?: number;
225
+ /**
226
+ * The date property this step is bound to (an invoice's `dueDate` while
227
+ * `sent`): the thing is LATE once that date passes while it stands here.
228
+ * A property slug; open/active/paused only.
229
+ */
230
+ dateBinding?: string;
231
+ /**
232
+ * The wait this step declares: an ACTIVE step such as "sent" waits on
233
+ * someone without being a pause. Open/active/paused only.
234
+ */
235
+ waits?: TemplateLifecycleOptionWaits;
236
+ }
237
+
238
+ /** A step's declared wait (the pod's `LifecycleOptionWaits`). */
239
+ export interface TemplateLifecycleOptionWaits {
240
+ /** A hold's `on`, never `unspecified`: person · agent · external · thing · decision · date · nobody. */
241
+ on: "person" | "agent" | "external" | "thing" | "decision" | "date" | "nobody";
242
+ /** The finer kind (`WAIT_KINDS`: "signature", "payment"…); absent ⇒ derived from `on`. */
243
+ waitKind?: string;
244
+ /** The property or relation naming WHO or WHAT is waited on (a deal's `contactId`). */
245
+ refFrom?: string;
246
+ /** The date property that ends the wait (a lead's `nextActionAt`). */
247
+ dateBinding?: string;
248
+ }
249
+
250
+ export interface TemplateLifecycle {
251
+ /** The lifecycle property's slug (a select of this profile). */
252
+ property: string;
253
+ options: TemplateLifecycleOption[];
155
254
  }
156
255
 
157
256
  export interface TemplateView {
@@ -172,6 +271,16 @@ export interface TemplateEntityLink {
172
271
  targetProfileSlug: string;
173
272
  type: string;
174
273
  label?: string;
274
+ /**
275
+ * Every record of the source kind should carry this link (an edge of `type`
276
+ * to the target kind). Several rows of one source kind and one `type` are ONE
277
+ * rule, met by an edge to any of their targets. The pod's template reconcile
278
+ * stores it on `profile_relations.metadata` (`required`, `requiredBy`); its
279
+ * create doors warn when a new record leaves it out (never refuse yet) and
280
+ * template health lists the records missing it. Omitted = says nothing (a
281
+ * mark another template set stays); `false` clears the mark.
282
+ */
283
+ required?: boolean;
175
284
  }
176
285
 
177
286
  /**
@@ -320,65 +429,40 @@ export interface TemplateDefaultSource {
320
429
  }
321
430
 
322
431
  // ============================================================================
323
- // Onboarding spec — the per-workspace dynamic onboarding CONTEXT
432
+ // The space brief — `onboarding:` in a template, stored at
433
+ // workspace.settings.onboarding.
324
434
  //
325
- // Written to workspace.settings.onboarding. The SHARED `onboard` skill (the
326
- // reusable adaptive interview PROCESS) reads this to know WHAT a given
327
- // workspace needs — without a per-domain skill file. The domain knowledge
328
- // lives here as data, declared by each template. Mirrors `OnboardingSpec` in
329
- // synap-backend `package-definition.ts` so the wire shape never drifts.
435
+ // ONE type: `SpaceBrief` in `@synap-core/types/space-brief` (type-only import;
436
+ // tsup inlines it into this package's .d.ts, so there is no runtime
437
+ // dependency). The interview fields (goal / collect / openingQuestions /
438
+ // doneWhen) are the brief's ONBOARDING MODE, read by the shared `onboard`
439
+ // skill; purpose / anchors / fetch are its steady state, read by every agent
440
+ // that enters the space. The names below are aliases, not declarations.
330
441
  // ============================================================================
331
442
 
332
- export interface TemplateOnboardingCollectTarget {
333
- /** Profile slug to populate (e.g. "audience", "competitor"). */
334
- profileSlug: string;
335
- /** Human description of what to capture for this target. */
336
- what: string;
337
- /** Roughly how many to expect — guides interview depth. */
338
- cardinality?: "one" | "few" | "several";
339
- /** Key fields the agent should make sure to fill. */
340
- keyFields?: string[];
341
- }
342
-
343
- // Authored domain expertise the onboarding agent LEADS with — so it resolves
344
- // the founder's gaps (brings best practices they lack, surfaces what they miss)
345
- // instead of only extracting what they already know. Consumed by the `onboard`
346
- // skill; see its "Lead with your expertise" step.
347
- export interface TemplateOnboardingExpertise {
348
- /**
349
- * Concrete starting points the agent PROPOSES instead of asking blank —
350
- * "most X do Y, want that as a starting point?". Grounds the agent's
351
- * proposals in real domain knowledge (never fabricates strategy — for
352
- * mission/positioning these FRAME, they don't invent the answer).
353
- */
354
- starters?: string[];
355
- /**
356
- * Blind spots founders in this domain commonly miss. The agent proactively
357
- * surfaces these if the founder hasn't — catching what they don't say.
358
- */
359
- blindSpots?: string[];
360
- /** What a GREAT result looks like here — the bar the agent pushes toward. */
361
- bar?: string;
362
- }
363
-
364
- export interface TemplateOnboarding {
365
- /** The outcome this onboarding achieves, in one sentence. */
366
- goal: string;
367
- /** Domain framing/voice the agent adopts for THIS workspace (the persona). */
368
- framing: string;
369
- /**
370
- * Authored domain expertise the agent leads with (optional). Turns the
371
- * interview from "extract what the founder knows" into "resolve what they
372
- * lack". See the `onboard` skill's "Lead with your expertise" step.
373
- */
374
- expertise?: TemplateOnboardingExpertise;
375
- /** What structured data to collect (entities to create + their key fields). */
376
- collect: TemplateOnboardingCollectTarget[];
377
- /** A few opening questions — the agent adapts from here, never rigid. */
378
- openingQuestions?: string[];
379
- /** "Done" signal the agent self-evaluates against. */
380
- doneWhen?: string;
381
- }
443
+ export type TemplateOnboardingCollectTarget = SpaceBriefCollectTarget;
444
+ export type TemplateOnboardingExpertise = SpaceBriefExpertise;
445
+ export type TemplateBriefAnchor = SpaceBriefAnchor;
446
+ export type TemplateBriefFetchHint = SpaceBriefFetchHint;
447
+ /**
448
+ * A template's brief. `rules` is NOT authored here — a template declares its
449
+ * rules at the top level (`rules:`); the pod stores only refs to them.
450
+ */
451
+ export type TemplateOnboarding = Omit<SpaceBrief, "rules">;
452
+ /**
453
+ * A rule a template installs in its space — applied through the pod's ONE rule
454
+ * door, stamped so a later template update never overwrites a rule the user
455
+ * edited. `key` is its stable identity across template versions.
456
+ */
457
+ export type TemplateRule = SpaceTemplateRule;
458
+ /**
459
+ * A SKILL a template declares for its space (`skills:`). Same shape as a rule —
460
+ * the template declares, the pod LINKS the skill to the space at install and
461
+ * keeps a ref in the brief. `mode: "always"` is prepended to every session or
462
+ * run started in the space; `on-demand` is surfaced and ranked first instead.
463
+ * Validation (`validateSpaceSkillDeclaration`) is shared with the pod's applier.
464
+ */
465
+ export type TemplateSkill = SpaceTemplateSkill;
382
466
 
383
467
  // ============================================================================
384
468
  // Playbooks — session templates seeded with the workspace
@@ -402,7 +486,23 @@ export interface TemplatePlaybook {
402
486
  goalTemplate: string;
403
487
  params?: TemplatePlaybookParam[];
404
488
  executor?: "is-agent" | "external-agent" | "hybrid";
405
- inputStrategy?: "none" | "static" | "rotating" | "query";
489
+ /**
490
+ * Legacy fan-out modes stay strings. `pinned` is an object: first eligible
491
+ * pin, then `fallback`. Entity ids are not part of this shape.
492
+ */
493
+ inputStrategy?:
494
+ | "none"
495
+ | "static"
496
+ | "rotating"
497
+ | "query"
498
+ | {
499
+ kind: "pinned";
500
+ fallback?: {
501
+ filter?: Record<string, unknown>;
502
+ orderBy?: string;
503
+ orderDir?: "asc" | "desc";
504
+ };
505
+ };
406
506
  channelSpec?: {
407
507
  type: "GROUP" | "AGENT_COLLAB" | "THREAD";
408
508
  members?: string[];
@@ -423,16 +523,183 @@ export interface TemplatePlaybook {
423
523
  * governance marker for unattended maintenance playbooks:
424
524
  * `{ governance: { forceProposeWrites: true } }` — every agent write in the
425
525
  * playbook's scheduled sessions then routes to a reviewable proposal.
526
+ * `lineage` is a CONVENTION (no reader enforces it): where the process comes
527
+ * from (an APQC PCF id, a named method, O*NET task ids).
426
528
  */
427
- metadata?: Record<string, unknown>;
529
+ metadata?: Record<string, unknown> & { lineage?: TemplatePlaybookLineage };
428
530
  /**
429
531
  * The entity kind this playbook operates over, persisted to
430
532
  * `playbooks.subject_profile`. Makes the playbook matchable by
431
533
  * `playbooks.matchForEntity` (filters `subject_profile->>'profileSlug'`), so a
432
534
  * captured entity of this kind can auto-launch the playbook as a session.
535
+ *
536
+ * `statusProperty` names the subject kind's SELECT property that holds its
537
+ * lifecycle (e.g. `post-status`). It is what ties `stages[].subjectStatus`
538
+ * to the subject: advancing into a stage writes that value (governed), and
539
+ * the subject entering the value advances an open run to the stage.
540
+ * `validate.ts` checks it is a select property of the kind, and that every
541
+ * `subjectStatus` / activator `status` is one of its enum values.
433
542
  */
434
- subjectProfile?: { profileSlug: string; filter?: Record<string, unknown> };
543
+ subjectProfile?: {
544
+ profileSlug: string;
545
+ /**
546
+ * Narrows a kind-bound SCHEDULE's fan-out: a JSON string of
547
+ * `{ "properties.<key>": value }`. A STRING, because the pod's cron door
548
+ * keeps only a string (`readSubjectProfile`, synap-backend
549
+ * cron-automation.ts) — an object would be dropped, and an unfiltered AI
550
+ * fan-out is refused, so the schedule would silently never be created.
551
+ */
552
+ filter?: string;
553
+ statusProperty?: string;
554
+ };
555
+ /**
556
+ * Playbook-level slots: what a run of this process is expected to produce.
557
+ * Instantiated as the session's owed slots (`sanitizeDeclaredOutputs`).
558
+ */
559
+ expectedOutputs?: TemplateExpectedOutput[];
560
+ /** Binary acceptance criteria every run is graded against (pod `sessionCriteriaSchema`). */
561
+ criteria?: TemplateCriterion[];
562
+ /**
563
+ * The abstract intents the process needs the pod to be able to do — the
564
+ * closed `capability_intents` vocabulary (`@synap-core/types/capability-intents`).
565
+ */
566
+ requiredIntents?: string[];
567
+ /**
568
+ * DECLARATIONS of when the process starts. Compiled at install/apply into
569
+ * governed rules through the pod's ONE rule door and linked in
570
+ * `playbook_automations` (role `activator`) — never hand-written template
571
+ * `automations:`. Public templates default to `mode: propose`.
572
+ */
573
+ activators?: TemplatePlaybookActivator[];
574
+ /**
575
+ * TEMPLATE-AUTHORING ONLY. Values of `subjectProfile.statusProperty` that no
576
+ * stage owns because a PERSON sets them (e.g. Idea, Archived). The lifecycle
577
+ * coverage ratchet (`lifecycle-coverage.test.ts`) requires every enum value
578
+ * of the status property to be either a stage's `subjectStatus` or listed
579
+ * here, so a lifecycle state can never be silently orphaned by a process.
580
+ */
581
+ humanOnlyStatuses?: string[];
435
582
  status?: "draft" | "active" | "paused";
583
+ /**
584
+ * `project` = a TRACK template (a method a project runs over its `stages`);
585
+ * `session` / omitted = a work template. The kind is DERIVED from this, never
586
+ * declared elsewhere (concepts.md).
587
+ */
588
+ scope?: "session" | "project";
589
+ /** Ordered steps. Validated at the pod door by `playbookStageSchema`. */
590
+ stages?: TemplatePlaybookStage[];
591
+ }
592
+
593
+ /**
594
+ * One step of a playbook. Mirrors the pod's `PlaybookStage` (@synap/playbooks)
595
+ * for the fields templates author; the pod schema stays the authority.
596
+ */
597
+ export interface TemplatePlaybookStage {
598
+ key: string;
599
+ name: string;
600
+ category: "backlog" | "planned" | "started" | "paused" | "completed" | "canceled";
601
+ description?: string;
602
+ goal?: string;
603
+ suggestedTasks?: string[];
604
+ indefinite?: boolean;
605
+ /**
606
+ * The DOMAIN the step is worked in: a workspace TEMPLATE slug that becomes a
607
+ * workspace's `package_slug` (e.g. `foundation`, `finance`) — never an
608
+ * overlay's slug (an overlay never owns a workspace), a workspace id or a
609
+ * display name. `validate.ts` rule `stage-domain-*` enforces it.
610
+ */
611
+ domain?: string;
612
+ expectedOutputs?: TemplateExpectedOutput[];
613
+ /** Binary acceptance criteria of THIS stage (a `check` gate evaluates them). */
614
+ criteria?: TemplateCriterion[];
615
+ /**
616
+ * Entry gate. `human` files a review; `check` evaluates the criteria of the
617
+ * stage being LEFT before the run may continue (pod `stage-gate.ts`).
618
+ */
619
+ gate?: { kind: "human" | "check"; proposalType?: "playbook.stage_gate" };
620
+ /**
621
+ * The value of the playbook's `subjectProfile.statusProperty` this stage
622
+ * corresponds to. Advancing INTO the stage writes it to the subject
623
+ * (governed); the subject ENTERING it advances an open run to the stage.
624
+ */
625
+ subjectStatus?: string;
626
+ /** Where a rejected human gate / failed check sends the run back (a stage key or name). */
627
+ onFail?: { toStage: string };
628
+ [key: string]: unknown;
629
+ }
630
+
631
+ /**
632
+ * One declared output slot (playbook- or stage-level). Mirrors the pod's
633
+ * `ExpectedOutput` (@synap/playbooks) for the fields templates author.
634
+ */
635
+ export interface TemplateExpectedOutput {
636
+ /** The output's kind — a profile slug for entities. */
637
+ kind: string;
638
+ label: string;
639
+ icon?: string;
640
+ owner?: "human" | "agent";
641
+ key?: string;
642
+ /**
643
+ * Relation type written output → subject when the slot is satisfied (e.g.
644
+ * `made_for`, `derived_from`). Must resolve to a relation the corpus defines
645
+ * (`entityLinks[].type` / `relationDefs[].slug`). `none` = deliberately no
646
+ * edge (a playbook with no subject, whose outputs stand alone).
647
+ */
648
+ relationToSubject?: string;
649
+ /**
650
+ * `true` = nobody owes this slot (synap-backend 30a9ab85): no needs-you row,
651
+ * never an unmet outcome at a gate or at completion; filled, it counts like
652
+ * any slot. Absent = required. Read STRICTLY — only a boolean `true`
653
+ * (validate.ts `output-optional-not-boolean`). A BIRTH declaration: a change
654
+ * reaches new runs and new stage entries only.
655
+ */
656
+ optional?: boolean;
657
+ [key: string]: unknown;
658
+ }
659
+
660
+ /** A binary acceptance criterion — mirrors the pod's strict `sessionCriterionSchema`. */
661
+ export interface TemplateCriterion {
662
+ /** Lowercase slug, unique within the list. */
663
+ key: string;
664
+ statement: string;
665
+ required?: boolean;
666
+ check: {
667
+ kind: "evidence" | "capability" | "judge" | "human";
668
+ capability?: string;
669
+ evidenceKey?: string;
670
+ hint?: string;
671
+ };
672
+ stageKey?: string;
673
+ }
674
+
675
+ /** A declared process activator (compiled to a governed rule at install). */
676
+ export interface TemplatePlaybookActivator {
677
+ /**
678
+ * `created` / `enters_status` per thing; `count` (≥ `min` things in
679
+ * `status`) and `schedule` (on `cron`) over the whole set; `manual` a
680
+ * button that compiles no rule. The pod's grammar (`ACTIVATOR_ON`).
681
+ */
682
+ on: "created" | "enters_status" | "count" | "schedule" | "manual";
683
+ /** Required for `enters_status` / `count`, optional for `schedule`: a value of the status property. */
684
+ status?: string;
685
+ /** Required for `schedule` (UTC). */
686
+ cron?: string;
687
+ /** Required for `count`. */
688
+ min?: number;
689
+ /** `per_thing` (default) or `per_moment`; count/schedule are per_moment. */
690
+ size?: "per_thing" | "per_moment";
691
+ mode: "run" | "propose";
692
+ /** Pending approvals before the worker stops starting runs (default 20). */
693
+ maxPendingApprovals?: number;
694
+ /** Per-thing `created` / `enters_status` only: leave out a thing that carries this property. */
695
+ unless?: { property: string; present: true };
696
+ }
697
+
698
+ /** Where a process comes from — convention only, read by nobody yet. */
699
+ export interface TemplatePlaybookLineage {
700
+ apqc?: string;
701
+ method?: string;
702
+ onet?: string[];
436
703
  }
437
704
 
438
705
  // ============================================================================
@@ -612,7 +879,7 @@ export interface TemplateExtendsRef {
612
879
  * in repos this package does not own, so they must match this list EXACTLY:
613
880
  *
614
881
  * - marketplace `features/marketplace/src/types.ts`
615
- * - onboarding `features/onboarding/src/{templates/workspace-templates,components/WorkspacePreview}.ts(x)`
882
+ * - onboarding `features/onboarding/src/templates/workspace-templates.ts`
616
883
  * - browser `InstallPackageDialog.tsx`
617
884
  * - synap-backend `package-definition.ts` (`PackageDependencyKind`)
618
885
  * - hub-protocol REST `rest/packages.ts` (zod enum)
@@ -697,12 +964,80 @@ export interface TemplateMeta {
697
964
  * or missing value is grouped, never dropped — see `./domains.ts`.
698
965
  */
699
966
  domain?: string;
967
+ /**
968
+ * WHAT THE SPACE PRODUCES — the purpose word shown first ("Product · Dev")
969
+ * and the kinds/roles it makes, in order. An empty `produces` (or none) makes
970
+ * the space a LIBRARY. Every produced profile is the template's own or one
971
+ * it depends on, and declares a lifecycle (`validate.ts` `intent-*` rules).
972
+ * Forwarded to the pod (top-level `intent` on both doors), which projects it into
973
+ * `workspaces.settings.intent`.
974
+ */
975
+ intent?: TemplateIntent;
976
+ /**
977
+ * An ONBOARDING START: this space offers itself as a first thing to run
978
+ * ("What should Synap run first?"). Declared once here, read by the pod, the
979
+ * CP and the landing. Rules: `validate.ts` `start-*`. Forwarded as top-level
980
+ * `start` on the package door, never in `_meta`.
981
+ */
982
+ start?: TemplateStart;
983
+ }
984
+
985
+ /** `meta.start.label` reuses {@link INTENT_LABEL_MAX}; these bound the lists. */
986
+ export const START_VIEWS_MAX = 3;
987
+ export const START_EXAMPLE_RANGE = [4, 6] as const;
988
+ export const START_STARTERS_RANGE = [3, 6] as const;
989
+
990
+ /** `meta.start` — see {@link TemplateMeta.start}. */
991
+ export interface TemplateStart {
992
+ /** Card order; unique across the catalog's starts. */
993
+ order: number;
994
+ /** ≤ {@link INTENT_LABEL_MAX} chars. */
995
+ label: string;
996
+ promise: string;
997
+ /** Identity ids this start is suggested for; each id belongs to one start. */
998
+ suggestFor: string[];
999
+ /** The produced kind the views and the first session are about. */
1000
+ profile: string;
1001
+ /** 1-3 slugs of THIS template's views, scoped to `profile`; first = default. */
1002
+ views: string[];
1003
+ /** Preview rows, never written. `values` keys are properties of `profile`. */
1004
+ example: Array<{ title: string; values?: Record<string, unknown> }>;
1005
+ firstSession: { title: string; goal: string };
1006
+ /** "Build it with me" chips. */
1007
+ starters: string[];
1008
+ }
1009
+
1010
+ /** `meta.intent.label` max — the purpose word must fit before " · <name>". */
1011
+ export const INTENT_LABEL_MAX = 24;
1012
+
1013
+ /** `meta.intent` — see {@link TemplateMeta.intent}. */
1014
+ export interface TemplateIntent {
1015
+ /** ≤ {@link INTENT_LABEL_MAX} chars. */
1016
+ label: string;
1017
+ produces?: Array<{ profile: string }>;
700
1018
  }
701
1019
 
702
1020
  export interface WorkspaceYaml {
703
1021
  /** Template metadata — not sent to backend, used for listing/UI */
704
1022
  meta: TemplateMeta;
705
1023
 
1024
+ /**
1025
+ * THE WORKSPACE'S TASK REQUIREMENTS — the specific intents (closed
1026
+ * vocabulary, `@synap-core/types/capability-intents`) this workspace needs to
1027
+ * function. The SSOT for WHAT THE SPACE REQUIRES, as distinct from
1028
+ * `workspace.capabilities`, which names what it PROVIDES to others.
1029
+ *
1030
+ * Every value is validated against the closed vocabulary by
1031
+ * `validateTemplate` (`task-intent-unknown`), so a typo fails at authoring
1032
+ * time rather than installing a capability axis nobody can route.
1033
+ *
1034
+ * Deliberately NOT forwarded by either converter yet: the backend has no
1035
+ * `taskIntents` sink on `createFromDefinition` (see `WorkspaceDefinitionDropped`
1036
+ * in `define.ts`, which records that). Phase 1 is the declaration + its
1037
+ * guard; wiring it to a sink is a follow-up that must edit that ledger.
1038
+ */
1039
+ taskIntents?: CapabilityIntentSlug[];
1040
+
706
1041
  /** The workspace definition sent to createFromDefinition */
707
1042
  workspace: {
708
1043
  name: string;
@@ -807,6 +1142,27 @@ export interface WorkspaceYaml {
807
1142
  */
808
1143
  onboarding?: TemplateOnboarding;
809
1144
 
1145
+ /**
1146
+ * Rules this template installs in its space (package `rules[]`). See
1147
+ * {@link TemplateRule}.
1148
+ */
1149
+ rules?: TemplateRule[];
1150
+
1151
+ /**
1152
+ * Skills this template declares for its space (package `skills[]`). The pod
1153
+ * links each to the new space at install, approved skills only, so every AI
1154
+ * working there is told them. See {@link TemplateSkill}.
1155
+ */
1156
+ skills?: TemplateSkill[];
1157
+
1158
+ /**
1159
+ * The space's own experience as CODE: the modules this template builds into
1160
+ * sandboxed frame cells and installs in its space (package `cells[]`, typeKey
1161
+ * `cell:<meta.slug>:<key>`). The template's `app: {kind: stored, cellKey}`
1162
+ * opens one of them. See {@link TemplateSpacePackage}.
1163
+ */
1164
+ spacePackage?: TemplateSpacePackage;
1165
+
810
1166
  /** Inherit profiles/views from other workspaces */
811
1167
  extends?: TemplateExtendsRef[];
812
1168
 
@@ -819,6 +1175,33 @@ export interface WorkspaceYaml {
819
1175
  dependencies?: TemplateDependency[];
820
1176
  }
821
1177
 
1178
+ // ============================================================================
1179
+ // Space package — the space's experience as built code
1180
+ // ============================================================================
1181
+
1182
+ /**
1183
+ * One module of a space package. `source` is the entry file, relative to the
1184
+ * synap-app repo root and under `packages/web/src/space-packages/`, so the
1185
+ * package is built from the SAME shared components every surface uses, never
1186
+ * from a copy. `scripts/build-space-packages.mjs` bundles it (React external,
1187
+ * host-inlined in the frame; its CSS injected by the module) into
1188
+ * `src/space-packages.generated.ts`, and `toPackageDefinition` carries it as a
1189
+ * `frame` cell.
1190
+ */
1191
+ export interface TemplateSpacePackageCell {
1192
+ /** Cell key inside the package: the installed typeKey is `cell:<meta.slug>:<key>`. */
1193
+ key: string;
1194
+ /** Display name of the installed cell. */
1195
+ name: string;
1196
+ /** Entry module, repo-relative (`packages/web/src/space-packages/<pkg>/<file>.tsx`). */
1197
+ source: string;
1198
+ }
1199
+
1200
+ /** The space package a template installs (base layer; the person's overlay comes later). */
1201
+ export interface TemplateSpacePackage {
1202
+ cells: TemplateSpacePackageCell[];
1203
+ }
1204
+
822
1205
  // ============================================================================
823
1206
  // Resolved template — meta + fully typed definition ready for provisioning
824
1207
  // ============================================================================