@synap-core/workspace-templates 0.11.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 (249) 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 +189 -900
  57. package/dist/index.js +24654 -21639
  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 +41 -27
  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.template.test.ts +25 -19
  139. package/src/base.yaml +95 -39
  140. package/src/blockchain-ecosystem.yaml +1 -0
  141. package/src/brand-library.yaml +525 -14
  142. package/src/builder-dev-fold.template.test.ts +113 -0
  143. package/src/builder.yaml +798 -92
  144. package/src/business-model-catalog-description.test.ts +47 -0
  145. package/src/business-model-grp.template.test.ts +214 -0
  146. package/src/business-model.yaml +598 -0
  147. package/src/catalog-safety.test.ts +198 -0
  148. package/src/catalog.template-items.test.ts +75 -0
  149. package/src/catalog.ts +85 -2
  150. package/src/civic-france.yaml +102 -0
  151. package/src/concept-guard.test.ts +28 -8
  152. package/src/concept-guard.ts +2 -2
  153. package/src/content-creation.template.test.ts +52 -0
  154. package/src/content-creation.yaml +192 -0
  155. package/src/content-os.edit-loop.template.test.ts +210 -0
  156. package/src/content-os.publish-due-posts.template.test.ts +261 -0
  157. package/src/content-os.template.test.ts +322 -0
  158. package/src/content-os.video-takes.template.test.ts +338 -0
  159. package/src/content-os.work-a-take.template.test.ts +125 -0
  160. package/src/content-os.yaml +1830 -39
  161. package/src/content-studio-retired.template.test.ts +82 -0
  162. package/src/corpus-flow-validity.test.ts +4 -5
  163. package/src/crm-absorbs-outreach.template.test.ts +117 -0
  164. package/src/crm-build-plan.template.test.ts +128 -0
  165. package/src/crm-lists.template.test.ts +96 -0
  166. package/src/crm-messages-cadence.template.test.ts +164 -0
  167. package/src/crm-one-send-door.template.test.ts +65 -0
  168. package/src/crm.yaml +1456 -181
  169. package/src/decisions-wave.template.test.ts +186 -0
  170. package/src/define.ts +130 -17
  171. package/src/design-to-implementation.template.test.ts +94 -0
  172. package/src/dist-freshness.test.ts +97 -0
  173. package/src/domain-template-type.test.ts +75 -0
  174. package/src/ecosystem.yaml +27 -66
  175. package/src/enterprise-os.yaml +10 -134
  176. package/src/facecam-edit.audio-studio.test.ts +188 -0
  177. package/src/fal-generate-image.test.ts +200 -0
  178. package/src/fal-media-lab-pod-files.test.ts +180 -0
  179. package/src/finance.yaml +254 -1
  180. package/src/foundation.yaml +130 -28
  181. package/src/frame-host-modules.d.mts +6 -0
  182. package/src/frame-host-modules.mjs +58 -0
  183. package/src/generate.mjs +9 -3
  184. package/src/github-merge.test.ts +210 -0
  185. package/src/grants.yaml +57 -17
  186. package/src/hr.yaml +39 -6
  187. package/src/index.ts +36 -1
  188. package/src/intent.test.ts +161 -0
  189. package/src/internal-runbook.yaml +19 -1
  190. package/src/jev.test.ts +356 -0
  191. package/src/legal.yaml +33 -1
  192. package/src/life-os.yaml +65 -240
  193. package/src/lifecycle-coverage.test.ts +124 -0
  194. package/src/lifecycle-declarations.test.ts +252 -0
  195. package/src/lifecycle-presets.test.ts +468 -0
  196. package/src/lifecycle-presets.ts +494 -0
  197. package/src/lifecycle-stuck.test.ts +46 -0
  198. package/src/lifecycle-waits.parity.test.ts +319 -0
  199. package/src/marketing.yaml +108 -4
  200. package/src/meetings-knowledge.yaml +18 -0
  201. package/src/networking.yaml +23 -2
  202. package/src/operations.yaml +304 -4
  203. package/src/pipeline-views.template.test.ts +88 -0
  204. package/src/playbook-goal-placeholders.test.ts +57 -0
  205. package/src/postiz-contract.test.ts +134 -0
  206. package/src/presentation-declarations.test.ts +174 -0
  207. package/src/process-contract.validate.test.ts +352 -0
  208. package/src/project-management.yaml +39 -740
  209. package/src/publish-body.d.mts +29 -0
  210. package/src/publish-body.mjs +74 -0
  211. package/src/publish-body.test.ts +74 -0
  212. package/src/publish-official-lib.test.ts +176 -0
  213. package/src/replicate-rvm.test.ts +504 -0
  214. package/src/research-base.yaml +119 -20
  215. package/src/research-decision.yaml +60 -3
  216. package/src/reserved-profile-slugs.test.ts +83 -0
  217. package/src/retired-goal-kinds.test.ts +58 -0
  218. package/src/role-reference-and-step-domain.test.ts +192 -0
  219. package/src/seed-obligation.test.ts +176 -0
  220. package/src/send-message-maps.test.ts +227 -0
  221. package/src/shared-role-ssot.test.ts +42 -1
  222. package/src/ship-a-change.template.test.ts +177 -0
  223. package/src/skills.test.ts +170 -0
  224. package/src/social.yaml +85 -27
  225. package/src/space-packages.freshness.test.ts +97 -0
  226. package/src/space-packages.generated.ts +40 -0
  227. package/src/space-packages.test.ts +125 -0
  228. package/src/space-packages.ts +73 -0
  229. package/src/start.test.ts +188 -0
  230. package/src/task-intents.test.ts +293 -0
  231. package/src/templates.ts +21639 -21522
  232. package/src/types.ts +443 -60
  233. package/src/unipile-publish-post.test.ts +162 -0
  234. package/src/validate-flow.drift.test.ts +2 -3
  235. package/src/validate-flow.ts +32 -2
  236. package/src/validate-onboarding.test.ts +59 -0
  237. package/src/validate.test.ts +156 -3
  238. package/src/validate.ts +1384 -7
  239. package/src/wire-core.ts +231 -0
  240. package/src/wire.test.ts +159 -0
  241. package/src/wire.ts +107 -0
  242. package/src/__fixtures__/report-automation-flow.json +0 -393
  243. package/src/agent-fleet.yaml +0 -1645
  244. package/src/business-developer.template.test.ts +0 -351
  245. package/src/business-developer.yaml +0 -860
  246. package/src/content-studio.yaml +0 -361
  247. package/src/dev-dashboard.yaml +0 -990
  248. package/src/outreach-comms.yaml +0 -486
  249. package/src/the-arch.yaml +0 -201
@@ -0,0 +1,75 @@
1
+ /**
2
+ * A template that DECLARES entity kinds must be installable as a workspace
3
+ * that can HOLD them.
4
+ *
5
+ * The pod refuses to file entities into a workspace whose type is
6
+ * `operational` or `agent` (`isDomainHomeWorkspace`, synap-backend
7
+ * `packages/database/src/services/workspace-resolution-service.ts`; enforced at
8
+ * `routers/entities/create.ts` with DOMAIN_INTO_NON_DOMAIN_HOME_MESSAGE) and
9
+ * leaves it out of auto-placement and of the orient domain map. That rule is
10
+ * deliberate — for real admin/system surfaces. Finance, People (hr), Legal and
11
+ * Internal Runbook are DOMAINS that ship profiles (account, invoice, contract,
12
+ * …) yet were typed `operational`, so live 2026-09-25 no entity could be filed
13
+ * into Finance at all.
14
+ *
15
+ * Reads the YAML SOURCES (not the generated `templates.ts`), and derives the
16
+ * set by globbing every `src/*.yaml` — a new template joins by existing.
17
+ */
18
+ import { readdirSync, readFileSync } from "fs";
19
+ import { dirname, join } from "path";
20
+ import { fileURLToPath } from "url";
21
+ import { load } from "js-yaml";
22
+ import { describe, expect, it } from "vitest";
23
+
24
+ const HERE = dirname(fileURLToPath(import.meta.url));
25
+ const NON_DOMAIN_TYPES = new Set(["operational", "agent"]);
26
+
27
+ // Declares kinds AND is a non-domain type — an OPEN founder decision, not a
28
+ // silent pass. A ratchet: delete a line once the template is retyped (or its
29
+ // profiles move out); the test fails on a stale entry.
30
+ // Empty since R7 (2026-09-27): both former entries — dev-dashboard and
31
+ // agent-fleet — were retired as templates (option A); their useful views were
32
+ // folded into builder-workspace.
33
+ const KNOWN_CONTRADICTIONS = new Set<string>([]);
34
+
35
+ type Tpl = {
36
+ meta?: { slug?: string };
37
+ workspace?: { workspaceType?: string };
38
+ profiles?: unknown[];
39
+ };
40
+
41
+ const templates = readdirSync(HERE)
42
+ .filter((f) => f.endsWith(".yaml"))
43
+ .map((f) => load(readFileSync(join(HERE, f), "utf8")) as Tpl)
44
+ .filter((t) => t && typeof t === "object" && t.meta?.slug);
45
+
46
+ describe("a template that declares kinds can hold them", () => {
47
+ it("scans a plausible corpus (non-vacuity)", () => {
48
+ expect(templates.length).toBeGreaterThan(20);
49
+ const slugs = templates.map((t) => t.meta!.slug);
50
+ expect(slugs).toEqual(expect.arrayContaining(["finance", "crm"]));
51
+ });
52
+
53
+ it("no kind-declaring template is typed operational/agent (except the ratchet)", () => {
54
+ const offenders = templates
55
+ .filter(
56
+ (t) =>
57
+ (t.profiles?.length ?? 0) > 0 &&
58
+ NON_DOMAIN_TYPES.has(t.workspace?.workspaceType ?? "")
59
+ )
60
+ .map((t) => t.meta!.slug!)
61
+ .sort();
62
+ expect(offenders.filter((s) => !KNOWN_CONTRADICTIONS.has(s))).toEqual([]);
63
+ expect(
64
+ [...KNOWN_CONTRADICTIONS].filter((s) => !offenders.includes(s)),
65
+ "resolved — remove from KNOWN_CONTRADICTIONS"
66
+ ).toEqual([]);
67
+ });
68
+
69
+ it("the four domains named in the 2026-09-25 bug are domain homes", () => {
70
+ const bySlug = new Map(templates.map((t) => [t.meta!.slug, t]));
71
+ for (const slug of ["finance", "hr", "legal", "internal-runbook"]) {
72
+ expect(bySlug.get(slug)?.workspace?.workspaceType, slug).toBe("personal");
73
+ }
74
+ });
75
+ });
@@ -9,12 +9,15 @@
9
9
  meta:
10
10
  slug: ecosystem
11
11
  domain: strategy
12
- name: Ecosystem
12
+ name: Market
13
13
  description: Map the market you operate in — the partners, competitors, and players, the segments and trends, and the relationships between them.
14
14
  icon: radar
15
15
  color: "#0EA5E9"
16
16
  tags: [ecosystem, market, partners, competitors, graph]
17
17
  isPublic: true
18
+ # A LIBRARY: it produces nothing a home counts (homes).
19
+ intent:
20
+ label: Ecosystem
18
21
 
19
22
  # SSOT ordering guarantee — this template REFERENCES foundation's pod-wide
20
23
  # shared `partner` role. The apply engine seeds a shared profile's pod-wide BASE
@@ -30,7 +33,7 @@ dependencies:
30
33
  reason: "Provides the pod-wide partner role vocabulary this workspace reuses."
31
34
 
32
35
  workspace:
33
- name: Ecosystem
36
+ name: Market
34
37
  description: Map the market you operate in — the partners, competitors, and players, the segments and trends, and the relationships between them.
35
38
  subtype: ecosystem
36
39
  visibility: pod_visible
@@ -253,74 +256,16 @@ profiles:
253
256
  constraints: { defaultValue: watching }
254
257
 
255
258
  # Partner (shared ecosystem role — SSOT is foundation.yaml) ─────────────────
256
- # `scope: shared` dedups to the ONE pod-wide `partner` profile seeded by
257
- # foundation; provisioning grants THIS workspace access to it (SHARED profiles
258
- # are grant-gated, so the reference is required). Shapes match foundation
259
- # verbatim, so no property drift.
259
+ # A REFERENCE (W4a): slug + displayName + scope + profileKind only. It
260
+ # resolves to the ONE pod-wide `partner` row foundation seeds and grants THIS
261
+ # workspace access (shared profiles are grant-gated, so the reference is
262
+ # required); the body is never restated. validate.ts rule
263
+ # `shared-role-reference-*` requires foundation in the dependency chain.
260
264
  - slug: partner
261
265
  displayName: Partner
262
- icon: handshake
263
- color: teal
264
- description: A partner relationship — both a referral source and a co-delivery collaborator, distinguished by partner type.
265
266
  scope: shared
266
267
  profileKind: role
267
- applicableKinds:
268
- - company
269
- - person
270
- properties:
271
- - slug: partnerStatus
272
- label: Status
273
- valueType: string
274
- inputType: select
275
- enumValues:
276
- - prospect
277
- - active
278
- - paused
279
- - churned
280
- - slug: partnerType
281
- label: Partner Type
282
- valueType: string
283
- inputType: select
284
- enumValues:
285
- - referral
286
- - co-delivery
287
- - both
288
- - slug: accountManager
289
- label: Account Manager
290
- valueType: string
291
- inputType: text
292
- - slug: engagementStartDate
293
- label: Engagement Start
294
- valueType: date
295
- inputType: date
296
- - slug: satisfactionScore
297
- label: Satisfaction
298
- valueType: number
299
- inputType: number
300
- - slug: lifetimeValue
301
- label: Lifetime Value
302
- valueType: number
303
- inputType: number
304
- - slug: notes
305
- label: Notes
306
- valueType: string
307
- inputType: textarea
308
- - slug: contractValue
309
- label: Contract Value
310
- valueType: number
311
- inputType: number
312
- - slug: renewalDate
313
- label: Renewal Date
314
- valueType: date
315
- inputType: date
316
- - slug: healthScore
317
- label: Health
318
- valueType: string
319
- inputType: select
320
- enumValues:
321
- - healthy
322
- - at_risk
323
- - critical
268
+ properties: []
324
269
 
325
270
  views:
326
271
  - name: Ecosystem Map
@@ -470,6 +415,20 @@ integrations:
470
415
  - templateKey: exa
471
416
  - templateKey: apify
472
417
 
418
+ # ── taskIntents — WHAT THIS WORKSPACE NEEDS TO FUNCTION ───────────────────
419
+ # Closed vocabulary: `@synap-core/types/capability-intents` (pod migrations
420
+ # 0283/0284). DERIVED from the declared intents of this template's own
421
+ # `integrations` capability packs — not hand-guessed. Checked at authoring
422
+ # time by `validateTemplate` (`task-intent-unknown`) and by
423
+ # `src/task-intents.test.ts`.
424
+ taskIntents:
425
+ - search_external
426
+ - fetch_record
427
+ - list_records
428
+ - run_external_job
429
+ - capture_into_pod
430
+ - enrich_entity
431
+
473
432
  onboarding:
474
433
  goal: >
475
434
  Map the real ecosystem — the key players (companies and people), who partners
@@ -519,10 +478,12 @@ onboarding:
519
478
  the threats, and the open lane, not just a pile of logos.
520
479
  collect:
521
480
  - profileSlug: company
481
+ min: 1
522
482
  what: The real companies in your ecosystem — the players you operate around.
523
483
  cardinality: several
524
484
  keyFields: [industry, website]
525
485
  - profileSlug: market-segment
486
+ min: 1
526
487
  what: The market slices you play in, with rough size and ocean.
527
488
  cardinality: few
528
489
  keyFields: [ocean, tam]
@@ -2,11 +2,12 @@
2
2
  # ==================================================
3
3
  # A SUITE template: it stands up a whole company's public operating core in one
4
4
  # install by REQUIRING its constituent workspaces (deps-first), then adds a thin
5
- # "command tower" home of its own — a place to track the company's objectives
6
- # across the lenses it just installed.
5
+ # home of its own that owns no data (`profiles: []`). What the company is driving
6
+ # toward is a goal on the pod (a track), not a kind in this space.
7
7
  #
8
8
  # What it composes (all public, all bundled):
9
9
  # • foundation — strategic DNA (mission, audience, positioning, principles)
10
+ # • business-model — the GRP method (a track template) layered onto foundation
10
11
  # • ecosystem — the market graph (partners, competitors, segments, trends)
11
12
  # • operations — how the company runs (the operational lens)
12
13
  # • crm — the pipeline (contacts, leads, clients, deals)
@@ -22,7 +23,7 @@ meta:
22
23
  slug: enterprise-os
23
24
  domain: company
24
25
  name: Enterprise OS
25
- description: Stand up a company's public operating core in one install — strategy, market, operations, and pipeline — plus a command tower to track objectives across them.
26
+ description: Stand up a company's public operating core in one install — strategy, market, operations, and pipeline. What you are driving toward lives on your pod as goals.
26
27
  icon: layout-dashboard
27
28
  color: "#4F46E5"
28
29
  tags: [suite, enterprise, os, foundation, crm, operations, ecosystem]
@@ -36,6 +37,10 @@ dependencies:
36
37
  kind: workspace
37
38
  relation: require
38
39
  reason: "Strategic DNA + the pod-wide role vocabulary (partner/client/lead) every other lens reuses. Must resolve first."
40
+ - slug: business-model
41
+ kind: workspace
42
+ relation: require
43
+ reason: "The canonical GRP — the business-model track template (six steps across strategy, finance and research) plus the convention/projection kinds. An overlay: it composes onto the Foundation installed above, it never creates a workspace."
39
44
  - slug: ecosystem
40
45
  kind: workspace
41
46
  relation: require
@@ -48,10 +53,6 @@ dependencies:
48
53
  kind: workspace
49
54
  relation: require
50
55
  reason: "The pipeline — contacts, leads, clients, and deals."
51
- - slug: business-developer
52
- kind: workspace
53
- relation: require
54
- reason: "The lead-first sales motion (the business-development overlay on the pod-wide lead/client roles, commercial proposals, commission handoff) that the CRM app runs on. Composes onto the CRM workspace above — without it the CRM lens has the bare lead/client roles with no lifecycle or handoff fields and the app's pipeline is empty."
55
56
  - slug: content-os
56
57
  kind: workspace
57
58
  relation: require
@@ -59,135 +60,10 @@ dependencies:
59
60
 
60
61
  workspace:
61
62
  name: Enterprise OS
62
- description: The command tower for the company operating system — track strategic objectives across the strategy, market, operations, and pipeline lenses this suite installs.
63
+ description: The home of the company operating system — the strategy, market, operations, and pipeline lenses this suite installs.
63
64
  subtype: enterprise-os
64
65
  visibility: pod_visible
65
66
  sourceRoles:
66
67
  strategy: consumer
67
68
 
68
- profiles:
69
- # The one native profile the command tower owns: a strategic objective the
70
- # company is driving across the lenses this suite installs. Deliberately light
71
- # — the depth lives in the constituent workspaces; this is the cross-cutting
72
- # scoreboard that ties them together.
73
- - slug: objective
74
- displayName: Objective
75
- icon: target
76
- color: "#4F46E5"
77
- description: A company objective the operating system is driving toward — the cross-cutting outcome the lenses serve.
78
- properties:
79
- - slug: outcome
80
- label: Outcome
81
- valueType: string
82
- inputType: textarea
83
- - slug: status
84
- label: Status
85
- valueType: string
86
- inputType: select
87
- enumValues: [on-track, at-risk, off-track, achieved]
88
- constraints: { defaultValue: on-track }
89
- - slug: horizon
90
- label: Horizon
91
- valueType: string
92
- inputType: select
93
- enumValues: [now, next, later]
94
- constraints: { defaultValue: now }
95
- - slug: owner
96
- label: Owner
97
- valueType: string
98
- inputType: text
99
- - slug: targetDate
100
- label: Target Date
101
- valueType: date
102
- inputType: date
103
-
104
- views:
105
- - name: Objectives
106
- slug: objectives
107
- type: table
108
- scopeProfileSlug: objective
109
- description: The company's strategic objectives across every lens, by horizon and status.
110
- defaultView: true
111
- config:
112
- columns: [title, status, horizon, owner, targetDate]
113
- - name: Objective Board
114
- slug: objective-board
115
- type: kanban
116
- scopeProfileSlug: objective
117
- description: Objectives grouped by status — a running scoreboard for the operating system.
118
- config:
119
- groupBy: status
120
-
121
- onboarding:
122
- goal: >
123
- Stand up the company's operating core and name the handful of strategic
124
- objectives it is driving — so strategy, market, operations, and pipeline are
125
- all in place and pointed at the same outcomes from day one.
126
- framing: |
127
- THE CHIEF OF STAFF: Act as a sharp chief of staff standing up the company OS.
128
- The four lenses (foundation, ecosystem, operations, CRM) are already
129
- installed — your job is to name the 3-5 objectives that cut across them, so
130
- the operating system has a scoreboard, not just structure.
131
- expertise:
132
- starters:
133
- - >
134
- Name few, real objectives. An operating system with 20 objectives has
135
- none; force the 3-5 that actually decide the year, each with an owner and
136
- a horizon (now / next / later).
137
- - >
138
- Tie each objective to a lens. A good objective names where it lives —
139
- pipeline growth (CRM), a market move (ecosystem), an operational fix
140
- (operations), or a positioning shift (foundation) — so the scoreboard
141
- maps to the structure underneath it.
142
- blindSpots:
143
- - >
144
- Objectives with no owner and no date are wishes. Every one needs a single
145
- owner and a target date, or it will not move.
146
- - >
147
- "Grow the business" is not an objective — it is a category. Push for the
148
- specific outcome that would make this quarter a win.
149
- bar: >
150
- A short, honest scoreboard: 3-5 objectives, each owned, dated, placed on a
151
- horizon, and tied to the lens that serves it — sitting on top of a fully
152
- installed operating core.
153
- collect:
154
- - profileSlug: objective
155
- what: The 3-5 strategic objectives the company is driving this horizon.
156
- cardinality: few
157
- keyFields: [status, horizon, owner]
158
- openingQuestions:
159
- - "What are the 3-5 objectives that will decide this year for the company?"
160
- - "Who owns each one, and is it a now, next, or later horizon?"
161
- doneWhen: A few objectives captured, each with an owner and a horizon.
162
-
163
- app:
164
- kind: stored
165
- cellKey: entity-detail
166
-
167
- layout:
168
- defaultView: Objectives
169
- defaultApp: null
170
- pinnedApps: [dashboard, data]
171
- sidebarItems:
172
- - kind: view
173
- viewName: Objectives
174
- label: Objectives
175
- icon: target
176
- - kind: view
177
- viewName: Objective Board
178
- label: Board
179
- icon: kanban-square
180
- - kind: app
181
- appId: data
182
- label: Data
183
- icon: database
184
-
185
- bento:
186
- viewName: Objectives
187
- blocks:
188
- - kind: view
189
- viewName: Objectives
190
- pos: { x: 0, y: 0, w: 8, h: 4 }
191
- - kind: view
192
- viewName: Objective Board
193
- pos: { x: 8, y: 0, w: 4, h: 4 }
69
+ profiles: []
@@ -0,0 +1,188 @@
1
+ /**
2
+ * facecam-edit, round 2 (31 Oct, wave session 742c7d5a):
3
+ *
4
+ * - Audio. Run 22dcabe8's delivery was re-encoded to fit the upload: the
5
+ * voice's third AAC encode (125 kb/s), with coding noise ~5 dB under the
6
+ * voice at 12-16 kHz, which the founder heard. The voice is encoded once
7
+ * after the take; every render gets the cut's audio stream back by a
8
+ * remux, checked by hash; a size re-encode touches the video only.
9
+ * Loudness moves only on the person's answer (pod knowledge f47a2a76).
10
+ * - Studio names a place (contract with Content Studio, lane cs-studio-bg):
11
+ * the desktop app is opened on the edit folder (`open -a HyperFrames
12
+ * <dir>`, the open-file event a running app also receives), recorded as
13
+ * `studio-app`; a missing app is the `needs-tool-hyperframes-app` slot;
14
+ * `studio` is retired whenever the preview process stops.
15
+ *
16
+ * Read from the skill JSON and the YAML source, so an edit is seen without a
17
+ * rebuild.
18
+ */
19
+ import { readFileSync } from "fs";
20
+ import { dirname, join } from "path";
21
+ import { fileURLToPath } from "url";
22
+ import { load } from "js-yaml";
23
+ import { describe, expect, it } from "vitest";
24
+ import type { TemplatePlaybook, WorkspaceYaml } from "./types.js";
25
+
26
+ const here = dirname(fileURLToPath(import.meta.url));
27
+ const skill = JSON.parse(
28
+ readFileSync(
29
+ join(here, "../skills/facecam-edit/facecam-edit.skill.json"),
30
+ "utf8"
31
+ )
32
+ ) as {
33
+ spec: { body: string };
34
+ };
35
+ const body = skill.spec.body;
36
+ const section = (from: string, to: string) => {
37
+ const start = body.indexOf(from);
38
+ const end = body.indexOf(to, start + 1);
39
+ expect(start).toBeGreaterThanOrEqual(0);
40
+ expect(end).toBeGreaterThan(start);
41
+ return body.slice(start, end);
42
+ };
43
+ const source = load(
44
+ readFileSync(join(here, "content-os.yaml"), "utf8")
45
+ ) as WorkspaceYaml;
46
+ const produce = (source.playbooks ?? []).find(
47
+ (p) => p.name === "Produce Content"
48
+ ) as TemplatePlaybook | undefined;
49
+ const draftGoal = (
50
+ produce?.stages?.find((s) => s.key === "draft")?.goal ?? ""
51
+ ).replace(/\s+/g, " ");
52
+
53
+ describe("facecam-edit encodes the voice once after the take", () => {
54
+ it("states the rule among the hard rules", () => {
55
+ const rules = section("## Hard rules", "## 1.");
56
+ expect(rules).toContain(
57
+ "**The voice is encoded once after the take, never again.**"
58
+ );
59
+ expect(rules).toContain("`media/cut-audio.m4a`");
60
+ });
61
+
62
+ it("builds the cut's audio from the take once, at 256 kb/s, with the clips' ramps", () => {
63
+ const cut = section("## 4. Apply the cut", "## 5.");
64
+ expect(cut).toContain("ffmpeg -i media/take-cfr.mp4 -filter_complex");
65
+ expect(cut).toContain("afade=t=in:d=0.03");
66
+ expect(cut).toContain("-c:a aac -b:a 256k -ar 48000 media/cut-audio.m4a");
67
+ expect(cut).toContain(
68
+ "Never build it from a file that is already a re-encode of the take."
69
+ );
70
+ });
71
+
72
+ it("encodes audio in exactly one command of the whole skill: the cut's audio", () => {
73
+ // Any other audio encoder in a command (a render step, a size re-encode) is the 31 Oct defect.
74
+ const encodes = body.match(/-c:a (?!copy)[a-z_]+/g) ?? [];
75
+ expect(encodes).toEqual(["-c:a aac"]);
76
+ expect(body.indexOf("-c:a aac")).toBe(
77
+ body.indexOf("-c:a aac -b:a 256k -ar 48000 media/cut-audio.m4a")
78
+ );
79
+ });
80
+
81
+ it("remuxes every render with the cut's audio and checks the hash before upload", () => {
82
+ const save = section("## 8. Review, render, save", "## Revisions");
83
+ const remux = save.indexOf(
84
+ "-i media/cut-audio.m4a -map 0:v:0 -map 1:a:0 -c copy -movflags +faststart <name>-final.mp4"
85
+ );
86
+ const hash = save.indexOf("-map 0:a:0 -f md5 -");
87
+ const sizeOnly = save.indexOf(
88
+ "-c:v libx264 -crf <a higher CRF> -preset slow -c:a copy"
89
+ );
90
+ const upload = save.indexOf("Upload the final MP4");
91
+ expect(remux).toBeGreaterThan(0);
92
+ expect(hash).toBeGreaterThan(remux);
93
+ expect(sizeOnly).toBeGreaterThan(hash);
94
+ expect(upload).toBeGreaterThan(sizeOnly);
95
+ expect(save).toContain("a pass's preview included");
96
+ expect(save).toContain("Different hashes: do not upload");
97
+ });
98
+
99
+ it("moves loudness only on the person's answer, and QA checks the level they chose", () => {
100
+ const cut = section("## 4. Apply the cut", "## 5.");
101
+ expect(cut).toContain("ask on the slot `ask-loudness`");
102
+ expect(cut).toContain(
103
+ "Never normalise without that answer, and never on a render."
104
+ );
105
+ const qa = section("## 7. QA", "## 8.");
106
+ expect(qa).not.toContain("target about -14 LUFS");
107
+ expect(qa).toContain("the level the person chose in §4");
108
+ });
109
+
110
+ it("says the same in Produce Content's Draft goal", () => {
111
+ expect(draftGoal).toContain(
112
+ "Every render the person hears, a preview included, carries the cut's audio copied (a remux, never the render's own encode), and a re-encode for size touches the video only"
113
+ );
114
+ });
115
+ });
116
+
117
+ describe("facecam-edit opens Studio where Content Studio asks", () => {
118
+ const setup = section("## 1. Recall and set up", "## 2.");
119
+
120
+ it("notes in step 0 whether the desktop app is installed, with no slot unless asked", () => {
121
+ expect(setup).toContain(
122
+ "test -d /Applications/HyperFrames.app || test -d ~/Applications/HyperFrames.app"
123
+ );
124
+ expect(setup).toContain("A missing app is not a slot by itself");
125
+ });
126
+
127
+ it("retires `studio` whenever the preview process stops", () => {
128
+ expect(setup).toContain(
129
+ 'Whenever your preview process stops (the run leaves Draft or ends, the worker stops, or you stop it): `npx hyperframes preview --stop` and `retireOutput: "studio"`'
130
+ );
131
+ });
132
+
133
+ it("opens the edit folder in the app as a document, never through --args, and records studio-app", () => {
134
+ const app = section("- **app**", "- **browser**:");
135
+ expect(app).toContain(
136
+ '`open -a HyperFrames "$HOME/synap-work/<run session id>/edit"`'
137
+ );
138
+ expect(app).toContain("ignored by a running app");
139
+ expect(app).toContain(
140
+ '{ key: "studio-app", kind: "app", label: "HyperFrames app on <this computer\'s name>", required: false }'
141
+ );
142
+ expect(app).toContain('`completeOutput: "studio-app"`');
143
+ });
144
+
145
+ it("hands a missing app to the person on needs-tool-hyperframes-app, install first, browser second", () => {
146
+ const app = section("- **app**", "- **browser**:");
147
+ for (const part of [
148
+ 'key: "needs-tool-hyperframes-app"',
149
+ 'owner: "human"',
150
+ 'blockedReason: "capability"',
151
+ "why: \"The HyperFrames desktop app isn't installed on <this computer's name>\"",
152
+ "https://hyperframes.dev/studio/download",
153
+ ]) {
154
+ expect(app).toContain(part);
155
+ }
156
+ const installed = app.indexOf('label: "I installed it", recommended: true');
157
+ const browser = app.indexOf('label: "Use the browser Studio"');
158
+ expect(installed).toBeGreaterThan(0);
159
+ expect(browser).toBeGreaterThan(installed);
160
+ expect(app).toContain(
161
+ '`retireOutput: "needs-tool-hyperframes-app"` and do **browser**'
162
+ );
163
+ });
164
+
165
+ it("starts the browser Studio as step 5 does, reusing a live address", () => {
166
+ const browser = section("- **browser**:", "## 2.");
167
+ expect(browser).toContain("record `studio` as in step 5");
168
+ expect(browser).toContain("never a second server");
169
+ });
170
+ });
171
+
172
+ describe("facecam-edit's local matte goes over the chosen background", () => {
173
+ const fallback = section("**Fallback, in order.**", "**Colour pass.**");
174
+
175
+ it("extracts the matte from remove-background's WebM with the libvpx decoder, gates it, and composites as the tool's matte", () => {
176
+ expect(fallback).toContain(
177
+ "npx hyperframes remove-background media/take-cfr.mp4 -o media/person-rb.webm --json"
178
+ );
179
+ expect(fallback).toContain(
180
+ "ffmpeg -c:v libvpx-vp9 -i media/person-rb.webm -vf alphaextract"
181
+ );
182
+ expect(fallback).toContain("Run the gate (step 3) on it");
183
+ expect(fallback).toContain("Then steps 4 to 6 as for the tool's matte");
184
+ expect(fallback).toContain(
185
+ "over the background the look chose: the photo, or the blurred room for `mode: blur`"
186
+ );
187
+ });
188
+ });