@synap-core/workspace-templates 0.7.1 → 0.7.3

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 (50) hide show
  1. package/dist/index.d.ts +266 -8
  2. package/dist/index.js +2314 -1440
  3. package/dist/index.js.map +1 -1
  4. package/package.json +4 -3
  5. package/src/agent-fleet.yaml +666 -108
  6. package/src/blockchain-ecosystem.yaml +1 -0
  7. package/src/brand-library.yaml +127 -12
  8. package/src/builder.yaml +116 -12
  9. package/src/business-developer.yaml +110 -18
  10. package/src/catalog.test.ts +2 -2
  11. package/src/catalog.ts +13 -3
  12. package/src/communication.yaml +23 -453
  13. package/src/composition-graph.test.ts +28 -2
  14. package/src/concept-guard.test.ts +176 -0
  15. package/src/concept-guard.ts +219 -0
  16. package/src/content-os.yaml +103 -10
  17. package/src/content-studio.yaml +1 -0
  18. package/src/crm.yaml +1 -0
  19. package/src/define.ts +8 -8
  20. package/src/dev-dashboard.yaml +43 -9
  21. package/src/domains.test.ts +117 -0
  22. package/src/domains.ts +102 -0
  23. package/src/ecosystem.yaml +25 -5
  24. package/src/enterprise-os.yaml +1 -0
  25. package/src/finance.yaml +46 -5
  26. package/src/foundation.yaml +13 -1
  27. package/src/generate.d.mts +15 -0
  28. package/src/generate.mjs +86 -0
  29. package/src/grants.yaml +1 -0
  30. package/src/hr.yaml +61 -8
  31. package/src/index.ts +40 -0
  32. package/src/internal-runbook.yaml +36 -5
  33. package/src/legal.yaml +97 -12
  34. package/src/life-os.yaml +188 -27
  35. package/src/marketing.yaml +15 -2
  36. package/src/meetings-knowledge.yaml +143 -23
  37. package/src/operations.yaml +347 -0
  38. package/src/outreach-comms.yaml +11 -3
  39. package/src/project-management.yaml +840 -111
  40. package/src/research-base.yaml +516 -0
  41. package/src/research-decision.yaml +158 -0
  42. package/src/shared-role-ssot.test.ts +268 -0
  43. package/src/social.yaml +105 -37
  44. package/src/templates-freshness.test.ts +55 -0
  45. package/src/templates.ts +4620 -4278
  46. package/src/the-arch.yaml +1 -0
  47. package/src/types.ts +9 -0
  48. package/src/validate.test.ts +81 -0
  49. package/src/validate.ts +561 -0
  50. package/src/personal.yaml +0 -177
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ var DATA = {
11
11
  "agent-fleet": {
12
12
  "meta": {
13
13
  "slug": "agent-fleet",
14
+ "domain": "build",
14
15
  "name": "Agent Fleet",
15
16
  "description": "Manage your fleet of AI agents \u2014 the agents, their providers, skills, and the work they do.",
16
17
  "icon": "bot",
@@ -2738,6 +2739,7 @@ var DATA = {
2738
2739
  "blockchain-ecosystem": {
2739
2740
  "meta": {
2740
2741
  "slug": "blockchain-ecosystem",
2742
+ "domain": "strategy",
2741
2743
  "name": "Blockchain Ecosystem",
2742
2744
  "description": "Web3 market actors \u2014 market-makers, auditors, dev shops, KOLs \u2014 and how they connect. Overlays the Ecosystem workspace.",
2743
2745
  "icon": "boxes",
@@ -3210,6 +3212,7 @@ var DATA = {
3210
3212
  "brand-library": {
3211
3213
  "meta": {
3212
3214
  "slug": "brand-library",
3215
+ "domain": "content",
3213
3216
  "name": "Brand Library",
3214
3217
  "description": "Reusable source of truth for brand identity, colors, typography, assets, tokens, templates, and generation rules.",
3215
3218
  "icon": "palette",
@@ -4348,6 +4351,7 @@ var DATA = {
4348
4351
  "builder-workspace": {
4349
4352
  "meta": {
4350
4353
  "slug": "builder-workspace",
4354
+ "domain": "build",
4351
4355
  "name": "Builder",
4352
4356
  "description": "Builder workspace \u2014 apps, features, services, packages, environments, deployments, recipes, decisions, incidents, plus delegated agent tasks/projects/skills/providers.",
4353
4357
  "icon": "wrench",
@@ -6761,6 +6765,7 @@ var DATA = {
6761
6765
  "business-developer": {
6762
6766
  "meta": {
6763
6767
  "slug": "business-developer",
6768
+ "domain": "revenue",
6764
6769
  "name": "Business Developer",
6765
6770
  "description": "A lead-first sales motion for a CRM workspace: qualify leads, work commercial proposals, and hand won clients to the next system.",
6766
6771
  "icon": "target",
@@ -6798,6 +6803,7 @@ var DATA = {
6798
6803
  "description": "A person or company actively being qualified or contacted by this CRM workspace.",
6799
6804
  "scope": "WORKSPACE",
6800
6805
  "profileKind": "role",
6806
+ "semanticSlug": "crm.lead",
6801
6807
  "applicableKinds": [
6802
6808
  "person",
6803
6809
  "company"
@@ -6905,6 +6911,7 @@ var DATA = {
6905
6911
  "description": "A CRM lead converted by a won commercial proposal and ready for handoff.",
6906
6912
  "scope": "WORKSPACE",
6907
6913
  "profileKind": "role",
6914
+ "semanticSlug": "crm.client",
6908
6915
  "applicableKinds": [
6909
6916
  "person",
6910
6917
  "company"
@@ -7791,6 +7798,7 @@ var DATA = {
7791
7798
  "communication": {
7792
7799
  "meta": {
7793
7800
  "slug": "communication",
7801
+ "domain": "content",
7794
7802
  "name": "Communication",
7795
7803
  "description": "Owns brand identity, voice, and narrative/positioning \u2014 the on-brand source of truth every downstream domain (Content, Marketing, Social) reads from so everything ships on-brand and on-message.",
7796
7804
  "icon": "messages-square",
@@ -7804,931 +7812,132 @@ var DATA = {
7804
7812
  ],
7805
7813
  "isPublic": true
7806
7814
  },
7815
+ "dependencies": [
7816
+ {
7817
+ "slug": "brand-library",
7818
+ "kind": "workspace",
7819
+ "relation": "compose",
7820
+ "reason": "Layers positioning, narrative, and audience onto your Brand Library."
7821
+ }
7822
+ ],
7807
7823
  "workspace": {
7808
- "name": "Communication",
7809
- "description": "Owns brand identity, voice, and narrative/positioning \u2014 the on-brand source of truth every downstream domain reads from.",
7810
- "subtype": "communication",
7811
- "visibility": "pod_visible",
7824
+ "name": "Brand Library",
7825
+ "description": "The strategic messaging layer \u2014 positioning, narrative, audience, and differentiators \u2014 layered onto your Brand Library.",
7826
+ "subtype": "brand-library",
7812
7827
  "capabilities": [
7813
- "brand.library",
7814
- "brand.identity",
7815
7828
  "brand.voice",
7816
- "brand.assets",
7817
- "brand.templates",
7818
- "brand.components",
7819
7829
  "narrative.positioning"
7820
7830
  ],
7821
7831
  "sourceRoles": {
7822
- "brand": "consumer",
7823
7832
  "narrative": "provider"
7824
7833
  }
7825
7834
  },
7826
7835
  "profiles": [
7827
7836
  {
7828
- "slug": "brand-identity",
7829
- "displayName": "Brand Identity",
7830
- "icon": "fingerprint",
7831
- "color": "amber",
7832
- "description": "Root brand context: positioning, audience, website, voice summary, and generation intent.",
7833
- "semanticSlug": "brand.identity",
7837
+ "slug": "positioning",
7838
+ "displayName": "Positioning",
7839
+ "icon": "crosshair",
7840
+ "color": "cyan",
7841
+ "description": "Market category, who we stand against, and why we win.",
7834
7842
  "properties": [
7835
7843
  {
7836
- "slug": "brand-type",
7837
- "label": "Brand type",
7838
- "valueType": "string",
7839
- "inputType": "select",
7840
- "enumValues": [
7841
- "product-digital",
7842
- "product-physical",
7843
- "agency",
7844
- "personal-brand",
7845
- "nonprofit",
7846
- "institutional",
7847
- "universal"
7848
- ],
7849
- "constraints": {
7850
- "defaultValue": "universal"
7851
- }
7852
- },
7853
- {
7854
- "slug": "brand-status",
7855
- "label": "Status",
7856
- "valueType": "string",
7857
- "inputType": "select",
7858
- "enumValues": [
7859
- "draft",
7860
- "active",
7861
- "archived"
7862
- ],
7863
- "constraints": {
7864
- "defaultValue": "active"
7865
- }
7866
- },
7867
- {
7868
- "slug": "brand-tagline",
7869
- "label": "Tagline",
7870
- "valueType": "string",
7871
- "inputType": "text"
7872
- },
7873
- {
7874
- "slug": "brand-website",
7875
- "label": "Website",
7876
- "valueType": "string",
7877
- "inputType": "url"
7878
- },
7879
- {
7880
- "slug": "brand-industry",
7881
- "label": "Industry",
7844
+ "slug": "category",
7845
+ "label": "Category",
7882
7846
  "valueType": "string",
7883
7847
  "inputType": "text"
7884
7848
  },
7885
7849
  {
7886
- "slug": "brand-positioning",
7887
- "label": "Positioning",
7888
- "valueType": "string",
7889
- "inputType": "textarea"
7890
- },
7891
- {
7892
- "slug": "brand-audience-primary",
7893
- "label": "Primary audience",
7894
- "valueType": "string",
7895
- "inputType": "textarea"
7896
- },
7897
- {
7898
- "slug": "brand-audience-secondary",
7899
- "label": "Secondary audience",
7900
- "valueType": "string",
7901
- "inputType": "textarea"
7902
- },
7903
- {
7904
- "slug": "brand-voice-summary",
7905
- "label": "Voice summary",
7850
+ "slug": "against",
7851
+ "label": "Against",
7906
7852
  "valueType": "string",
7907
7853
  "inputType": "textarea"
7908
7854
  },
7909
7855
  {
7910
- "slug": "brand-notes",
7911
- "label": "Notes",
7856
+ "slug": "because",
7857
+ "label": "Because",
7912
7858
  "valueType": "string",
7913
7859
  "inputType": "textarea"
7914
7860
  }
7915
7861
  ]
7916
7862
  },
7917
7863
  {
7918
- "slug": "brand-color",
7919
- "displayName": "Brand Color",
7920
- "icon": "swatch-book",
7921
- "color": "violet",
7922
- "description": "Approved palette entry with semantic role, usage notes, and print references.",
7923
- "semanticSlug": "brand.color",
7864
+ "slug": "narrative",
7865
+ "displayName": "Narrative",
7866
+ "icon": "book-open",
7867
+ "color": "amber",
7868
+ "description": "The origin -> insight -> mission story arc.",
7924
7869
  "properties": [
7925
7870
  {
7926
- "slug": "color-role",
7927
- "label": "Role",
7871
+ "slug": "arc",
7872
+ "label": "Story arc",
7928
7873
  "valueType": "string",
7929
- "inputType": "select",
7930
- "enumValues": [
7931
- "primary",
7932
- "secondary",
7933
- "accent",
7934
- "background",
7935
- "surface",
7936
- "surface-elevated",
7937
- "text",
7938
- "text-muted",
7939
- "border",
7940
- "success",
7941
- "warning",
7942
- "error",
7943
- "info",
7944
- "neutral",
7945
- "campaign",
7946
- "custom"
7947
- ],
7948
- "constraints": {
7949
- "defaultValue": "custom"
7950
- }
7874
+ "inputType": "textarea"
7951
7875
  },
7952
7876
  {
7953
- "slug": "color-group",
7954
- "label": "Group",
7877
+ "slug": "status",
7878
+ "label": "Status",
7955
7879
  "valueType": "string",
7956
7880
  "inputType": "select",
7957
7881
  "enumValues": [
7958
- "core",
7959
- "extended",
7960
- "semantic",
7961
- "neutral",
7962
- "seasonal",
7963
- "campaign"
7882
+ "draft",
7883
+ "active",
7884
+ "archived"
7964
7885
  ],
7965
7886
  "constraints": {
7966
- "defaultValue": "core"
7887
+ "defaultValue": "active"
7967
7888
  }
7968
- },
7969
- {
7970
- "slug": "color-hex",
7971
- "label": "Hex",
7972
- "valueType": "string",
7973
- "inputType": "color"
7974
- },
7975
- {
7976
- "slug": "color-rgb",
7977
- "label": "RGB",
7978
- "valueType": "string",
7979
- "inputType": "text"
7980
- },
7981
- {
7982
- "slug": "color-cmyk",
7983
- "label": "CMYK",
7984
- "valueType": "string",
7985
- "inputType": "text"
7986
- },
7987
- {
7988
- "slug": "color-pantone",
7989
- "label": "Pantone",
7990
- "valueType": "string",
7991
- "inputType": "text"
7992
- },
7889
+ }
7890
+ ]
7891
+ },
7892
+ {
7893
+ "slug": "audience",
7894
+ "displayName": "Audience",
7895
+ "icon": "users",
7896
+ "color": "blue",
7897
+ "description": "An ideal customer profile \u2014 who we are built for.",
7898
+ "properties": [
7993
7899
  {
7994
- "slug": "color-ral",
7995
- "label": "RAL",
7900
+ "slug": "segment",
7901
+ "label": "Segment",
7996
7902
  "valueType": "string",
7997
7903
  "inputType": "text"
7998
7904
  },
7999
7905
  {
8000
- "slug": "color-token-name",
8001
- "label": "Token name",
7906
+ "slug": "persona",
7907
+ "label": "Persona",
8002
7908
  "valueType": "string",
8003
- "inputType": "text"
7909
+ "inputType": "textarea"
8004
7910
  },
8005
7911
  {
8006
- "slug": "color-usage",
8007
- "label": "Usage note",
7912
+ "slug": "jobs-to-be-done",
7913
+ "label": "Jobs to be done",
8008
7914
  "valueType": "string",
8009
7915
  "inputType": "textarea"
8010
7916
  },
8011
7917
  {
8012
- "slug": "color-status",
8013
- "label": "Status",
8014
- "valueType": "string",
8015
- "inputType": "select",
8016
- "enumValues": [
8017
- "draft",
8018
- "approved",
8019
- "deprecated"
8020
- ],
8021
- "constraints": {
8022
- "defaultValue": "approved"
8023
- }
7918
+ "slug": "traits",
7919
+ "label": "Traits",
7920
+ "valueType": "array",
7921
+ "inputType": "text"
8024
7922
  }
8025
7923
  ]
8026
7924
  },
8027
7925
  {
8028
- "slug": "brand-font",
8029
- "displayName": "Brand Typeface",
8030
- "icon": "type",
8031
- "color": "blue",
8032
- "description": "Typeface with role, family, licensing, import URL, weights, and fallback stack.",
8033
- "semanticSlug": "brand.font",
7926
+ "slug": "differentiator",
7927
+ "displayName": "Differentiator",
7928
+ "icon": "sparkles",
7929
+ "color": "green",
7930
+ "description": "One thing only we do, believe, or refuse.",
8034
7931
  "properties": [
8035
7932
  {
8036
- "slug": "font-role",
8037
- "label": "Role",
7933
+ "slug": "statement",
7934
+ "label": "Statement",
8038
7935
  "valueType": "string",
8039
- "inputType": "select",
8040
- "enumValues": [
8041
- "heading",
8042
- "body",
8043
- "display",
8044
- "mono",
8045
- "accent",
8046
- "ui",
8047
- "caption"
8048
- ],
8049
- "constraints": {
8050
- "defaultValue": "body"
8051
- }
7936
+ "inputType": "textarea"
8052
7937
  },
8053
7938
  {
8054
- "slug": "font-family",
8055
- "label": "Family",
8056
- "valueType": "string",
8057
- "inputType": "text"
8058
- },
8059
- {
8060
- "slug": "font-foundry",
8061
- "label": "Foundry",
8062
- "valueType": "string",
8063
- "inputType": "text"
8064
- },
8065
- {
8066
- "slug": "font-license",
8067
- "label": "License",
8068
- "valueType": "string",
8069
- "inputType": "select",
8070
- "enumValues": [
8071
- "open-source",
8072
- "google-fonts",
8073
- "adobe-fonts",
8074
- "licensed",
8075
- "custom",
8076
- "system"
8077
- ],
8078
- "constraints": {
8079
- "defaultValue": "google-fonts"
8080
- }
8081
- },
8082
- {
8083
- "slug": "font-weights",
8084
- "label": "Weights",
8085
- "valueType": "string",
8086
- "inputType": "text"
8087
- },
8088
- {
8089
- "slug": "font-fallback",
8090
- "label": "Fallback stack",
8091
- "valueType": "string",
8092
- "inputType": "text"
8093
- },
8094
- {
8095
- "slug": "font-url",
8096
- "label": "Import URL",
8097
- "valueType": "string",
8098
- "inputType": "url"
8099
- },
8100
- {
8101
- "slug": "font-document-id",
8102
- "label": "Font document ID",
8103
- "valueType": "string",
8104
- "inputType": "text"
8105
- },
8106
- {
8107
- "slug": "font-status",
8108
- "label": "Status",
8109
- "valueType": "string",
8110
- "inputType": "select",
8111
- "enumValues": [
8112
- "active",
8113
- "draft",
8114
- "deprecated"
8115
- ],
8116
- "constraints": {
8117
- "defaultValue": "active"
8118
- }
8119
- }
8120
- ]
8121
- },
8122
- {
8123
- "slug": "brand-asset",
8124
- "displayName": "Brand Asset",
8125
- "icon": "image",
8126
- "color": "green",
8127
- "description": "Document-backed or URL-backed reusable media: logos, imagery, icons, fonts, video, references, and documents.",
8128
- "semanticSlug": "brand.asset",
8129
- "properties": [
8130
- {
8131
- "slug": "asset-kind",
8132
- "label": "Kind",
8133
- "valueType": "string",
8134
- "inputType": "select",
8135
- "enumValues": [
8136
- "logo",
8137
- "wordmark",
8138
- "symbol",
8139
- "monogram",
8140
- "pattern",
8141
- "texture",
8142
- "icon-set",
8143
- "illustration",
8144
- "photo",
8145
- "video",
8146
- "document",
8147
- "font",
8148
- "3d-model",
8149
- "print-ready",
8150
- "reference",
8151
- "other"
8152
- ]
8153
- },
8154
- {
8155
- "slug": "asset-variant",
8156
- "label": "Variant",
8157
- "valueType": "string",
8158
- "inputType": "select",
8159
- "enumValues": [
8160
- "primary",
8161
- "secondary",
8162
- "horizontal",
8163
- "stacked",
8164
- "mono-dark",
8165
- "mono-light",
8166
- "white",
8167
- "reversed",
8168
- "favicon",
8169
- "social-avatar",
8170
- "og-image",
8171
- "other"
8172
- ]
8173
- },
8174
- {
8175
- "slug": "asset-status",
8176
- "label": "Status",
8177
- "valueType": "string",
8178
- "inputType": "select",
8179
- "enumValues": [
8180
- "draft",
8181
- "approved",
8182
- "deprecated"
8183
- ],
8184
- "constraints": {
8185
- "defaultValue": "approved"
8186
- }
8187
- },
8188
- {
8189
- "slug": "asset-usage",
8190
- "label": "Usage notes",
8191
- "valueType": "string",
8192
- "inputType": "textarea"
8193
- },
8194
- {
8195
- "slug": "asset-tags",
8196
- "label": "Tags",
8197
- "valueType": "string",
8198
- "inputType": "text"
8199
- },
8200
- {
8201
- "slug": "asset-url",
8202
- "label": "External URL",
8203
- "valueType": "string",
8204
- "inputType": "url"
8205
- },
8206
- {
8207
- "slug": "asset-document-id",
8208
- "label": "Document ID",
8209
- "valueType": "string",
8210
- "inputType": "text"
8211
- },
8212
- {
8213
- "slug": "asset-file-id",
8214
- "label": "Legacy file ID",
8215
- "valueType": "string",
8216
- "inputType": "text"
8217
- },
8218
- {
8219
- "slug": "asset-alt-text",
8220
- "label": "Alt text",
8221
- "valueType": "string",
8222
- "inputType": "textarea"
8223
- }
8224
- ]
8225
- },
8226
- {
8227
- "slug": "brand-reference",
8228
- "displayName": "Brand Reference",
8229
- "icon": "bookmark",
8230
- "color": "teal",
8231
- "description": "Website, competitor, campaign, moodboard, or example used as source context for generation.",
8232
- "semanticSlug": "brand.reference",
8233
- "properties": [
8234
- {
8235
- "slug": "reference-kind",
8236
- "label": "Kind",
8237
- "valueType": "string",
8238
- "inputType": "select",
8239
- "enumValues": [
8240
- "website",
8241
- "competitor",
8242
- "campaign",
8243
- "moodboard",
8244
- "copy-example",
8245
- "design-example",
8246
- "customer-example",
8247
- "other"
8248
- ]
8249
- },
8250
- {
8251
- "slug": "reference-url",
8252
- "label": "URL",
8253
- "valueType": "string",
8254
- "inputType": "url"
8255
- },
8256
- {
8257
- "slug": "reference-notes",
8258
- "label": "Notes",
8259
- "valueType": "string",
8260
- "inputType": "textarea"
8261
- },
8262
- {
8263
- "slug": "reference-status",
8264
- "label": "Status",
8265
- "valueType": "string",
8266
- "inputType": "select",
8267
- "enumValues": [
8268
- "draft",
8269
- "approved",
8270
- "archived"
8271
- ],
8272
- "constraints": {
8273
- "defaultValue": "approved"
8274
- }
8275
- }
8276
- ]
8277
- },
8278
- {
8279
- "slug": "brand-token-set",
8280
- "displayName": "Token Set",
8281
- "icon": "code-2",
8282
- "color": "violet",
8283
- "description": "Generated or curated design tokens for color, typography, spacing, radii, and exported CSS variables.",
8284
- "semanticSlug": "brand.tokens",
8285
- "properties": [
8286
- {
8287
- "slug": "token-status",
8288
- "label": "Status",
8289
- "valueType": "string",
8290
- "inputType": "select",
8291
- "enumValues": [
8292
- "draft",
8293
- "active",
8294
- "archived"
8295
- ],
8296
- "constraints": {
8297
- "defaultValue": "active"
8298
- }
8299
- },
8300
- {
8301
- "slug": "token-mode",
8302
- "label": "Mode",
8303
- "valueType": "string",
8304
- "inputType": "select",
8305
- "enumValues": [
8306
- "base",
8307
- "light",
8308
- "dark",
8309
- "high-contrast",
8310
- "campaign",
8311
- "experimental"
8312
- ],
8313
- "constraints": {
8314
- "defaultValue": "base"
8315
- }
8316
- },
8317
- {
8318
- "slug": "token-source-ids",
8319
- "label": "Source IDs",
8320
- "valueType": "string",
8321
- "inputType": "textarea"
8322
- },
8323
- {
8324
- "slug": "token-json",
8325
- "label": "Tokens JSON",
8326
- "valueType": "string",
8327
- "inputType": "textarea"
8328
- },
8329
- {
8330
- "slug": "token-css",
8331
- "label": "CSS variables",
8332
- "valueType": "string",
8333
- "inputType": "textarea"
8334
- },
8335
- {
8336
- "slug": "token-notes",
8337
- "label": "Notes",
8338
- "valueType": "string",
8339
- "inputType": "textarea"
8340
- }
8341
- ]
8342
- },
8343
- {
8344
- "slug": "brand-voice-guide",
8345
- "displayName": "Voice Guide",
8346
- "icon": "message-circle",
8347
- "color": "orange",
8348
- "description": "Generated or curated voice guidance by context: traits, tone, vocabulary, and copy examples.",
8349
- "semanticSlug": "brand.voice",
8350
- "properties": [
8351
- {
8352
- "slug": "voice-context",
8353
- "label": "Context",
8354
- "valueType": "string",
8355
- "inputType": "select",
8356
- "enumValues": [
8357
- "general",
8358
- "marketing",
8359
- "product",
8360
- "support",
8361
- "social",
8362
- "legal",
8363
- "editorial",
8364
- "investor"
8365
- ],
8366
- "constraints": {
8367
- "defaultValue": "general"
8368
- }
8369
- },
8370
- {
8371
- "slug": "voice-status",
8372
- "label": "Status",
8373
- "valueType": "string",
8374
- "inputType": "select",
8375
- "enumValues": [
8376
- "draft",
8377
- "approved",
8378
- "deprecated"
8379
- ],
8380
- "constraints": {
8381
- "defaultValue": "approved"
8382
- }
8383
- },
8384
- {
8385
- "slug": "voice-personality-traits",
8386
- "label": "Personality",
8387
- "valueType": "string",
8388
- "inputType": "textarea"
8389
- },
8390
- {
8391
- "slug": "voice-tone-descriptors",
8392
- "label": "Tone",
8393
- "valueType": "string",
8394
- "inputType": "text"
8395
- },
8396
- {
8397
- "slug": "voice-vocabulary",
8398
- "label": "Vocabulary",
8399
- "valueType": "string",
8400
- "inputType": "textarea"
8401
- },
8402
- {
8403
- "slug": "voice-example-do",
8404
- "label": "Do",
8405
- "valueType": "string",
8406
- "inputType": "textarea"
8407
- },
8408
- {
8409
- "slug": "voice-example-dont",
8410
- "label": "Don't",
8411
- "valueType": "string",
8412
- "inputType": "textarea"
8413
- },
8414
- {
8415
- "slug": "voice-source-ids",
8416
- "label": "Source IDs",
8417
- "valueType": "string",
8418
- "inputType": "textarea"
8419
- }
8420
- ]
8421
- },
8422
- {
8423
- "slug": "brand-rule",
8424
- "displayName": "Brand Rule",
8425
- "icon": "shield-check",
8426
- "color": "red",
8427
- "description": "Usage constraints, accessibility requirements, do/don't examples, and generation guidance.",
8428
- "semanticSlug": "brand.rule",
8429
- "properties": [
8430
- {
8431
- "slug": "rule-kind",
8432
- "label": "Kind",
8433
- "valueType": "string",
8434
- "inputType": "select",
8435
- "enumValues": [
8436
- "visual",
8437
- "voice",
8438
- "legal",
8439
- "accessibility",
8440
- "sizing",
8441
- "clearance",
8442
- "color-usage",
8443
- "typography-usage",
8444
- "do",
8445
- "dont",
8446
- "generation",
8447
- "other"
8448
- ]
8449
- },
8450
- {
8451
- "slug": "rule-subject",
8452
- "label": "Subject",
8453
- "valueType": "string",
8454
- "inputType": "select",
8455
- "enumValues": [
8456
- "logo",
8457
- "color",
8458
- "typography",
8459
- "pattern",
8460
- "asset",
8461
- "voice",
8462
- "general",
8463
- "digital",
8464
- "print",
8465
- "packaging"
8466
- ]
8467
- },
8468
- {
8469
- "slug": "rule-severity",
8470
- "label": "Severity",
8471
- "valueType": "string",
8472
- "inputType": "select",
8473
- "enumValues": [
8474
- "guideline",
8475
- "important",
8476
- "mandatory"
8477
- ],
8478
- "constraints": {
8479
- "defaultValue": "important"
8480
- }
8481
- },
8482
- {
8483
- "slug": "rule-content",
8484
- "label": "Rule",
8485
- "valueType": "string",
8486
- "inputType": "textarea"
8487
- },
8488
- {
8489
- "slug": "rule-example",
8490
- "label": "Example",
8491
- "valueType": "string",
8492
- "inputType": "textarea"
8493
- },
8494
- {
8495
- "slug": "rule-source-ids",
8496
- "label": "Source IDs",
8497
- "valueType": "string",
8498
- "inputType": "textarea"
8499
- }
8500
- ]
8501
- },
8502
- {
8503
- "slug": "brand-template",
8504
- "displayName": "Brand Template",
8505
- "icon": "layout-template",
8506
- "color": "pink",
8507
- "description": "Reusable output template for artboards, decks, carousels, banners, documents, or generated HTML.",
8508
- "semanticSlug": "brand.template",
8509
- "properties": [
8510
- {
8511
- "slug": "template-kind",
8512
- "label": "Kind",
8513
- "valueType": "string",
8514
- "inputType": "select",
8515
- "enumValues": [
8516
- "artboard",
8517
- "deck",
8518
- "carousel",
8519
- "banner",
8520
- "document",
8521
- "html",
8522
- "social",
8523
- "other"
8524
- ]
8525
- },
8526
- {
8527
- "slug": "template-status",
8528
- "label": "Status",
8529
- "valueType": "string",
8530
- "inputType": "select",
8531
- "enumValues": [
8532
- "draft",
8533
- "approved",
8534
- "deprecated"
8535
- ],
8536
- "constraints": {
8537
- "defaultValue": "approved"
8538
- }
8539
- },
8540
- {
8541
- "slug": "template-format",
8542
- "label": "Format",
8543
- "valueType": "string",
8544
- "inputType": "select",
8545
- "enumValues": [
8546
- "tldraw",
8547
- "html",
8548
- "json",
8549
- "markdown",
8550
- "image",
8551
- "mixed"
8552
- ]
8553
- },
8554
- {
8555
- "slug": "template-config",
8556
- "label": "Config JSON",
8557
- "valueType": "string",
8558
- "inputType": "textarea"
8559
- },
8560
- {
8561
- "slug": "template-usage",
8562
- "label": "Usage notes",
8563
- "valueType": "string",
8564
- "inputType": "textarea"
8565
- }
8566
- ]
8567
- },
8568
- {
8569
- "slug": "brand-component",
8570
- "displayName": "Brand Component",
8571
- "icon": "component",
8572
- "color": "green",
8573
- "description": "Reusable branded UI or content component: hero, CTA, card, quote, banner, section, or HTML snippet.",
8574
- "semanticSlug": "brand.component",
8575
- "properties": [
8576
- {
8577
- "slug": "component-kind",
8578
- "label": "Kind",
8579
- "valueType": "string",
8580
- "inputType": "select",
8581
- "enumValues": [
8582
- "hero",
8583
- "card",
8584
- "cta",
8585
- "quote",
8586
- "banner",
8587
- "section",
8588
- "layout",
8589
- "html",
8590
- "other"
8591
- ]
8592
- },
8593
- {
8594
- "slug": "component-status",
8595
- "label": "Status",
8596
- "valueType": "string",
8597
- "inputType": "select",
8598
- "enumValues": [
8599
- "draft",
8600
- "approved",
8601
- "deprecated"
8602
- ],
8603
- "constraints": {
8604
- "defaultValue": "approved"
8605
- }
8606
- },
8607
- {
8608
- "slug": "component-html",
8609
- "label": "HTML",
8610
- "valueType": "string",
8611
- "inputType": "textarea"
8612
- },
8613
- {
8614
- "slug": "component-props",
8615
- "label": "Props JSON",
8616
- "valueType": "string",
8617
- "inputType": "textarea"
8618
- },
8619
- {
8620
- "slug": "component-usage",
8621
- "label": "Usage notes",
8622
- "valueType": "string",
8623
- "inputType": "textarea"
8624
- }
8625
- ]
8626
- },
8627
- {
8628
- "slug": "positioning",
8629
- "displayName": "Positioning",
8630
- "icon": "crosshair",
8631
- "color": "cyan",
8632
- "description": "Market category, who we stand against, and why we win.",
8633
- "properties": [
8634
- {
8635
- "slug": "category",
8636
- "label": "Category",
8637
- "valueType": "string",
8638
- "inputType": "text"
8639
- },
8640
- {
8641
- "slug": "against",
8642
- "label": "Against",
8643
- "valueType": "string",
8644
- "inputType": "textarea"
8645
- },
8646
- {
8647
- "slug": "because",
8648
- "label": "Because",
8649
- "valueType": "string",
8650
- "inputType": "textarea"
8651
- }
8652
- ]
8653
- },
8654
- {
8655
- "slug": "narrative",
8656
- "displayName": "Narrative",
8657
- "icon": "book-open",
8658
- "color": "amber",
8659
- "description": "The origin -> insight -> mission story arc.",
8660
- "properties": [
8661
- {
8662
- "slug": "arc",
8663
- "label": "Story arc",
8664
- "valueType": "string",
8665
- "inputType": "textarea"
8666
- },
8667
- {
8668
- "slug": "status",
8669
- "label": "Status",
8670
- "valueType": "string",
8671
- "inputType": "select",
8672
- "enumValues": [
8673
- "draft",
8674
- "active",
8675
- "archived"
8676
- ],
8677
- "constraints": {
8678
- "defaultValue": "active"
8679
- }
8680
- }
8681
- ]
8682
- },
8683
- {
8684
- "slug": "audience",
8685
- "displayName": "Audience",
8686
- "icon": "users",
8687
- "color": "blue",
8688
- "description": "An ideal customer profile \u2014 who we are built for.",
8689
- "properties": [
8690
- {
8691
- "slug": "segment",
8692
- "label": "Segment",
8693
- "valueType": "string",
8694
- "inputType": "text"
8695
- },
8696
- {
8697
- "slug": "persona",
8698
- "label": "Persona",
8699
- "valueType": "string",
8700
- "inputType": "textarea"
8701
- },
8702
- {
8703
- "slug": "jobs-to-be-done",
8704
- "label": "Jobs to be done",
8705
- "valueType": "string",
8706
- "inputType": "textarea"
8707
- },
8708
- {
8709
- "slug": "traits",
8710
- "label": "Traits",
8711
- "valueType": "array",
8712
- "inputType": "text"
8713
- }
8714
- ]
8715
- },
8716
- {
8717
- "slug": "differentiator",
8718
- "displayName": "Differentiator",
8719
- "icon": "sparkles",
8720
- "color": "green",
8721
- "description": "One thing only we do, believe, or refuse.",
8722
- "properties": [
8723
- {
8724
- "slug": "statement",
8725
- "label": "Statement",
8726
- "valueType": "string",
8727
- "inputType": "textarea"
8728
- },
8729
- {
8730
- "slug": "proof",
8731
- "label": "Proof",
7939
+ "slug": "proof",
7940
+ "label": "Proof",
8732
7941
  "valueType": "string",
8733
7942
  "inputType": "textarea"
8734
7943
  }
@@ -8903,6 +8112,7 @@ var DATA = {
8903
8112
  "content-os": {
8904
8113
  "meta": {
8905
8114
  "slug": "content-os",
8115
+ "domain": "content",
8906
8116
  "name": "Content OS",
8907
8117
  "description": "Your editorial operating system \u2014 pillars, posts, platforms, and newsletters. Turn raw thinking into a published content engine, all connected to your campaigns and brand voice.",
8908
8118
  "icon": "pen-tool",
@@ -9182,7 +8392,7 @@ var DATA = {
9182
8392
  "icon": "share-2",
9183
8393
  "color": "#06B6D4",
9184
8394
  "description": "A social account, newsletter publication, or podcast channel. Each platform has its own audience metrics and publishing rhythm.",
9185
- "scope": "WORKSPACE",
8395
+ "scope": "shared",
9186
8396
  "properties": [
9187
8397
  {
9188
8398
  "slug": "platform-type",
@@ -9203,6 +8413,13 @@ var DATA = {
9203
8413
  "Other"
9204
8414
  ]
9205
8415
  },
8416
+ {
8417
+ "slug": "handle",
8418
+ "label": "Handle",
8419
+ "valueType": "string",
8420
+ "inputType": "text",
8421
+ "placeholder": "@username"
8422
+ },
9206
8423
  {
9207
8424
  "slug": "platform-status",
9208
8425
  "label": "Status",
@@ -9738,6 +8955,7 @@ var DATA = {
9738
8955
  "content-studio": {
9739
8956
  "meta": {
9740
8957
  "slug": "content-studio",
8958
+ "domain": "content",
9741
8959
  "name": "Content Studio",
9742
8960
  "description": "HyperFrames + Remotion video pipeline \u2014 script, design, compose, render, publish.",
9743
8961
  "icon": "clapperboard",
@@ -10273,6 +9491,7 @@ var DATA = {
10273
9491
  "crm": {
10274
9492
  "meta": {
10275
9493
  "slug": "crm",
9494
+ "domain": "revenue",
10276
9495
  "name": "CRM",
10277
9496
  "description": "Sales pipeline and contact management from first contact to handoff.",
10278
9497
  "icon": "handshake",
@@ -10842,6 +10061,7 @@ var DATA = {
10842
10061
  "dev-dashboard": {
10843
10062
  "meta": {
10844
10063
  "slug": "dev-dashboard",
10064
+ "domain": "build",
10845
10065
  "name": "Synap Dev \u2014 Infrastructure Command Center",
10846
10066
  "description": "Internal DevOps dashboard for monitoring Synap infrastructure. Tracks services, vendors, and environments with health status, architecture flow map, and quick access to admin panels.",
10847
10067
  "icon": "server",
@@ -12552,6 +11772,7 @@ var DATA = {
12552
11772
  "ecosystem": {
12553
11773
  "meta": {
12554
11774
  "slug": "ecosystem",
11775
+ "domain": "strategy",
12555
11776
  "name": "Ecosystem",
12556
11777
  "description": "Map the market you operate in \u2014 the partners, competitors, and players, the segments and trends, and the relationships between them.",
12557
11778
  "icon": "radar",
@@ -13260,7 +12481,7 @@ var DATA = {
13260
12481
  ]
13261
12482
  },
13262
12483
  "bento": {
13263
- "viewName": "Ecosystem Map",
12484
+ "viewName": "Ecosystem Home",
13264
12485
  "blocks": [
13265
12486
  {
13266
12487
  "kind": "view",
@@ -13298,6 +12519,7 @@ var DATA = {
13298
12519
  "enterprise-os": {
13299
12520
  "meta": {
13300
12521
  "slug": "enterprise-os",
12522
+ "domain": "company",
13301
12523
  "name": "Enterprise OS",
13302
12524
  "description": "Stand up a company's public operating core in one install \u2014 strategy, market, operations, and pipeline \u2014 plus a command tower to track objectives across them.",
13303
12525
  "icon": "layout-dashboard",
@@ -13534,6 +12756,7 @@ var DATA = {
13534
12756
  "finance": {
13535
12757
  "meta": {
13536
12758
  "slug": "finance",
12759
+ "domain": "company",
13537
12760
  "name": "Finance",
13538
12761
  "description": "The company's money model \u2014 accounts, receivables, spend, revenue streams, budgets, and runway.",
13539
12762
  "icon": "banknote",
@@ -14375,6 +13598,7 @@ var DATA = {
14375
13598
  "foundation": {
14376
13599
  "meta": {
14377
13600
  "slug": "foundation",
13601
+ "domain": "strategy",
14378
13602
  "name": "Foundation",
14379
13603
  "description": "The strategic DNA \u2014 mission, audience, positioning, and principles \u2014 that every workspace inherits.",
14380
13604
  "icon": "compass",
@@ -15215,6 +14439,7 @@ var DATA = {
15215
14439
  "grants": {
15216
14440
  "meta": {
15217
14441
  "slug": "grants",
14442
+ "domain": "revenue",
15218
14443
  "name": "Grants Pipeline",
15219
14444
  "description": "Grant-agency operations \u2014 submissions, rounds, analyses. Overlays the Operations workspace.",
15220
14445
  "icon": "award",
@@ -16690,6 +15915,7 @@ var DATA = {
16690
15915
  "hr": {
16691
15916
  "meta": {
16692
15917
  "slug": "hr",
15918
+ "domain": "company",
16693
15919
  "name": "HR",
16694
15920
  "description": "The people operating system \u2014 team, hiring, performance reviews, and policies in one place.",
16695
15921
  "icon": "users-round",
@@ -17516,6 +16742,7 @@ var DATA = {
17516
16742
  "internal-runbook": {
17517
16743
  "meta": {
17518
16744
  "slug": "internal-runbook",
16745
+ "domain": "company",
17519
16746
  "name": "Internal Runbook",
17520
16747
  "description": "The company's operating system \u2014 SOPs, workflows, vendors, tools, metrics, and rituals that keep the business running.",
17521
16748
  "icon": "settings-2",
@@ -17531,7 +16758,6 @@ var DATA = {
17531
16758
  "workspace": {
17532
16759
  "name": "Internal Runbook",
17533
16760
  "description": "The operating layer of the company \u2014 documented procedures, recurring processes, the tool stack and vendors behind them, operational metrics, and the rituals that keep the team aligned.",
17534
- "proposalId": "operations-v1",
17535
16761
  "subtype": "internal-runbook",
17536
16762
  "visibility": "members",
17537
16763
  "workspaceType": "operational",
@@ -18352,6 +17578,7 @@ var DATA = {
18352
17578
  "legal": {
18353
17579
  "meta": {
18354
17580
  "slug": "legal",
17581
+ "domain": "company",
18355
17582
  "name": "Legal",
18356
17583
  "description": "The company's legal operating system \u2014 contracts, compliance, IP, entities, and matters.",
18357
17584
  "icon": "scale",
@@ -19215,6 +18442,7 @@ var DATA = {
19215
18442
  "life-os": {
19216
18443
  "meta": {
19217
18444
  "slug": "life-os",
18445
+ "domain": "knowledge",
19218
18446
  "name": "Second Brain \u2014 Knowledge OS",
19219
18447
  "description": "A sovereign personal knowledge management workspace. Capture everything, connect ideas, build your external brain.",
19220
18448
  "icon": "brain",
@@ -22048,6 +21276,7 @@ var DATA = {
22048
21276
  "marketing-campaign": {
22049
21277
  "meta": {
22050
21278
  "slug": "marketing-campaign",
21279
+ "domain": "revenue",
22051
21280
  "name": "Marketing Campaigns",
22052
21281
  "description": "Track leads, manage campaigns, and let AI help run your outreach. Contacts, pipeline, tasks, and AI briefings \u2014 all connected.",
22053
21282
  "icon": "megaphone",
@@ -22479,6 +21708,7 @@ var DATA = {
22479
21708
  "meetings-knowledge": {
22480
21709
  "meta": {
22481
21710
  "slug": "meetings-knowledge",
21711
+ "domain": "knowledge",
22482
21712
  "name": "Meetings & Knowledge",
22483
21713
  "description": "Import and summarize meetings \u2014 transcripts become notes, action items become tasks, and attendees become tracked people.",
22484
21714
  "icon": "video",
@@ -22507,18 +21737,92 @@ var DATA = {
22507
21737
  },
22508
21738
  "profiles": [
22509
21739
  {
22510
- "slug": "meeting",
22511
- "displayName": "Meeting",
22512
- "icon": "video",
21740
+ "slug": "person",
21741
+ "displayName": "Person",
21742
+ "icon": "user",
21743
+ "color": "amber",
21744
+ "description": "A meeting attendee.",
21745
+ "properties": [
21746
+ {
21747
+ "slug": "email",
21748
+ "label": "Email",
21749
+ "valueType": "string",
21750
+ "inputType": "email"
21751
+ }
21752
+ ]
21753
+ },
21754
+ {
21755
+ "slug": "task",
21756
+ "displayName": "Task",
21757
+ "icon": "check-square",
21758
+ "color": "blue",
21759
+ "description": "An action item that came out of a meeting.",
21760
+ "properties": [
21761
+ {
21762
+ "slug": "status",
21763
+ "label": "Status",
21764
+ "valueType": "string",
21765
+ "inputType": "select",
21766
+ "enumValues": [
21767
+ "todo",
21768
+ "in-progress",
21769
+ "done",
21770
+ "cancelled"
21771
+ ],
21772
+ "constraints": {
21773
+ "defaultValue": "todo"
21774
+ }
21775
+ },
21776
+ {
21777
+ "slug": "dueDate",
21778
+ "label": "Due",
21779
+ "valueType": "date",
21780
+ "inputType": "date"
21781
+ }
21782
+ ]
21783
+ },
21784
+ {
21785
+ "slug": "note",
21786
+ "displayName": "Note",
21787
+ "icon": "file-text",
22513
21788
  "color": "violet",
22514
- "description": "A meeting \u2014 its date, attendees, and what came out of it.",
21789
+ "description": "A note or summary captured from a meeting.",
22515
21790
  "properties": [
22516
21791
  {
22517
- "slug": "meetingDate",
22518
- "label": "Date",
21792
+ "slug": "content",
21793
+ "label": "Content",
21794
+ "valueType": "string",
21795
+ "inputType": "textarea"
21796
+ }
21797
+ ]
21798
+ },
21799
+ {
21800
+ "slug": "event",
21801
+ "displayName": "Event",
21802
+ "icon": "calendar",
21803
+ "color": "sky",
21804
+ "description": "A calendar event \u2014 the thing a meeting actually is.",
21805
+ "properties": [
21806
+ {
21807
+ "slug": "startDate",
21808
+ "label": "Start",
22519
21809
  "valueType": "date",
22520
21810
  "inputType": "date"
22521
- },
21811
+ }
21812
+ ]
21813
+ },
21814
+ {
21815
+ "slug": "meeting",
21816
+ "displayName": "Meeting",
21817
+ "icon": "video",
21818
+ "color": "violet",
21819
+ "scope": "shared",
21820
+ "profileKind": "role",
21821
+ "applicableKinds": [
21822
+ "event"
21823
+ ],
21824
+ "description": "The meeting hat an event wears \u2014 platform, transcript, and what came out of it.",
21825
+ "properties": [
22522
21826
  {
22523
21827
  "slug": "platform",
22524
21828
  "label": "Platform",
@@ -22532,12 +21836,6 @@ var DATA = {
22532
21836
  "other"
22533
21837
  ]
22534
21838
  },
22535
- {
22536
- "slug": "attendees",
22537
- "label": "Attendees",
22538
- "valueType": "array",
22539
- "inputType": "text"
22540
- },
22541
21839
  {
22542
21840
  "slug": "status",
22543
21841
  "label": "Status",
@@ -22577,19 +21875,44 @@ var DATA = {
22577
21875
  "config": {
22578
21876
  "columns": [
22579
21877
  "title",
22580
- "meetingDate",
21878
+ "startDate",
22581
21879
  "platform",
22582
21880
  "status"
22583
21881
  ]
21882
+ }
21883
+ },
21884
+ {
21885
+ "name": "Needs Processing",
21886
+ "slug": "meetings-unprocessed",
21887
+ "type": "list",
21888
+ "scopeProfileSlug": "meeting",
21889
+ "description": "Meetings that happened but haven't been imported and summarized yet.",
21890
+ "config": {
21891
+ "filterBy": {
21892
+ "field": "status",
21893
+ "operator": "is",
21894
+ "value": "completed"
21895
+ }
22584
21896
  },
22585
21897
  "defaultView": true
22586
21898
  },
21899
+ {
21900
+ "name": "Meeting Notes",
21901
+ "slug": "meeting-notes",
21902
+ "type": "list",
21903
+ "scopeProfileSlug": "note",
21904
+ "description": "Summaries and notes produced from meetings."
21905
+ },
22587
21906
  {
22588
21907
  "name": "Meetings Calendar",
22589
21908
  "slug": "meetings-calendar",
22590
21909
  "type": "calendar",
22591
21910
  "scopeProfileSlug": "meeting",
22592
- "description": "Meetings on a calendar, keyed on their date."
21911
+ "description": "Meetings on a calendar, keyed on their date.",
21912
+ "config": {
21913
+ "dateField": "properties.startDate",
21914
+ "colorBy": "status"
21915
+ }
22593
21916
  },
22594
21917
  {
22595
21918
  "name": "Action Items",
@@ -22673,27 +21996,29 @@ var DATA = {
22673
21996
  ],
22674
21997
  "blindSpots": [
22675
21998
  `Recurring meetings (standups, 1:1s) get skipped because they feel routine \u2014 but their action items are exactly what falls through the cracks. Don't let "it's just a standup" excuse skipping capture.
22676
- `
21999
+ `,
22000
+ `"Attendees" as a list of names is not attendee capture \u2014 it's a string. If the summary says "Sarah will send the deck" and Sarah isn't a tracked person linked to that task, the next meeting with Sarah starts from zero again. Resolve every attendee to a real person, or say out loud that you're choosing not to.
22001
+ `,
22002
+ "A summary nobody re-reads is theatre. The test for a good meeting note is whether someone who missed the call could act from it alone \u2014 if it needs the transcript to make sense, it isn't a summary yet.\n"
22677
22003
  ],
22678
- "bar": "A handful of recent meetings are logged with a real summary and at least one action item each, so the Import & Summarize playbook has something concrete to run against.\n"
22004
+ "bar": 'The PIPE is live, not the rows: transcript source and calendar connected, the Import & Summarize playbook run once end-to-end on a real recent meeting, and the output inspected together \u2014 a note a human would actually keep, tasks that are genuinely actionable, and attendees resolved to tracked people rather than name strings. If the first import produces vague tasks ("follow up"), fix the extraction bar now, not after fifty meetings.\n'
22679
22005
  },
22680
22006
  "collect": [
22681
22007
  {
22682
22008
  "profileSlug": "meeting",
22683
- "what": "Recent or upcoming meetings worth tracking.",
22009
+ "what": "Which recurring meetings are worth importing every time \u2014 the standing 1:1s, the weekly ops call. A watchlist, not a backlog.\n",
22684
22010
  "cardinality": "few",
22685
22011
  "keyFields": [
22686
- "meetingDate",
22687
22012
  "platform"
22688
22013
  ]
22689
22014
  }
22690
22015
  ],
22691
22016
  "openingQuestions": [
22692
- "What meetings do you want tracked \u2014 recurring ones, or just the important ones?",
22693
- "Where do your meetings live \u2014 Zoom, Google Meet, somewhere else?",
22694
- "Do you already record/transcribe them, or should that start now?"
22017
+ "Name a meeting from last week whose outcome you can't remember. What did that cost you?",
22018
+ "When a meeting produces an action item, where does it go today \u2014 and does it survive the week?",
22019
+ "Which recurring meeting would you cancel if you could see its action-item completion rate?"
22695
22020
  ],
22696
- "doneWhen": "A few meetings captured with a date and platform, at least one with a summary."
22021
+ "doneWhen": "Transcript source connected and one real meeting imported end-to-end \u2014 summary note, at least one action item, and attendees resolved to people.\n"
22697
22022
  },
22698
22023
  "app": {
22699
22024
  "kind": "stored",
@@ -22704,7 +22029,8 @@ var DATA = {
22704
22029
  "defaultApp": null,
22705
22030
  "pinnedApps": [
22706
22031
  "dashboard",
22707
- "data"
22032
+ "data",
22033
+ "chat"
22708
22034
  ],
22709
22035
  "sidebarItems": [
22710
22036
  {
@@ -22734,7 +22060,7 @@ var DATA = {
22734
22060
  ]
22735
22061
  },
22736
22062
  "bento": {
22737
- "viewName": "Meetings",
22063
+ "viewName": "Meetings Home",
22738
22064
  "blocks": [
22739
22065
  {
22740
22066
  "kind": "view",
@@ -22762,6 +22088,7 @@ var DATA = {
22762
22088
  "operations": {
22763
22089
  "meta": {
22764
22090
  "slug": "operations",
22091
+ "domain": "company",
22765
22092
  "name": "Operations",
22766
22093
  "description": "Deliver client work end to end \u2014 the engagements you're running, the deliverables due inside them, and the contracts that govern them. Won deals from CRM hand off into engagements here.",
22767
22094
  "icon": "briefcase",
@@ -22789,6 +22116,14 @@ var DATA = {
22789
22116
  "operations": "provider"
22790
22117
  }
22791
22118
  },
22119
+ "dependencies": [
22120
+ {
22121
+ "slug": "foundation",
22122
+ "kind": "workspace",
22123
+ "relation": "require",
22124
+ "reason": "Provides the pod-wide `client` role the daily client-briefing automation queries."
22125
+ }
22126
+ ],
22792
22127
  "profiles": [
22793
22128
  {
22794
22129
  "slug": "engagement",
@@ -22976,6 +22311,72 @@ var DATA = {
22976
22311
  "inputType": "textarea"
22977
22312
  }
22978
22313
  ]
22314
+ },
22315
+ {
22316
+ "slug": "client-briefing",
22317
+ "displayName": "Client Briefing",
22318
+ "icon": "newspaper",
22319
+ "color": "#F59E0B",
22320
+ "description": "A dated internal recap of one client's recent communications \u2014 what moved, what's at risk, what's next. For the team, never for the client.",
22321
+ "properties": [
22322
+ {
22323
+ "slug": "briefing-client",
22324
+ "label": "Client",
22325
+ "valueType": "entity_id",
22326
+ "targetProfileSlug": "company",
22327
+ "inputType": "entity_select"
22328
+ },
22329
+ {
22330
+ "slug": "briefing-date",
22331
+ "label": "Written At",
22332
+ "valueType": "date",
22333
+ "inputType": "date"
22334
+ },
22335
+ {
22336
+ "slug": "briefing-key",
22337
+ "label": "Run Key",
22338
+ "valueType": "string",
22339
+ "inputType": "text"
22340
+ },
22341
+ {
22342
+ "slug": "briefing-headline",
22343
+ "label": "Headline",
22344
+ "valueType": "string",
22345
+ "inputType": "text"
22346
+ },
22347
+ {
22348
+ "slug": "briefing-summary",
22349
+ "label": "Summary",
22350
+ "valueType": "string",
22351
+ "inputType": "textarea"
22352
+ },
22353
+ {
22354
+ "slug": "briefing-risks",
22355
+ "label": "Risks",
22356
+ "valueType": "string",
22357
+ "inputType": "textarea"
22358
+ },
22359
+ {
22360
+ "slug": "briefing-next-actions",
22361
+ "label": "Next Actions",
22362
+ "valueType": "string",
22363
+ "inputType": "textarea"
22364
+ },
22365
+ {
22366
+ "slug": "briefing-message-count",
22367
+ "label": "Messages Read",
22368
+ "valueType": "number",
22369
+ "inputType": "number"
22370
+ }
22371
+ ]
22372
+ }
22373
+ ],
22374
+ "entityLinks": [
22375
+ {
22376
+ "sourceProfileSlug": "client-briefing",
22377
+ "targetProfileSlug": "company",
22378
+ "type": "briefing_about_client",
22379
+ "label": "Client"
22979
22380
  }
22980
22381
  ],
22981
22382
  "views": [
@@ -23001,6 +22402,13 @@ var DATA = {
23001
22402
  "type": "table",
23002
22403
  "scopeProfileSlug": "contract",
23003
22404
  "description": "Contracts with their status, value, and term."
22405
+ },
22406
+ {
22407
+ "name": "Client Briefings",
22408
+ "slug": "client-briefings",
22409
+ "type": "list",
22410
+ "scopeProfileSlug": "client-briefing",
22411
+ "description": "The daily internal recaps, newest first."
23004
22412
  }
23005
22413
  ],
23006
22414
  "onboarding": {
@@ -23090,12 +22498,259 @@ var DATA = {
23090
22498
  "h": 5
23091
22499
  }
23092
22500
  }
23093
- ]
23094
- }
22501
+ ]
22502
+ },
22503
+ "automations": [
22504
+ {
22505
+ "key": "operations-daily-client-briefing",
22506
+ "name": "Daily client briefing",
22507
+ "description": "Each morning, for every client, distil their recent comms into one batched digest, save it as a durable client-briefing, and post the recap to the client's internal TEAM channel (never the client-facing channel).",
22508
+ "triggerType": "cron",
22509
+ "triggerConfig": {
22510
+ "expression": "0 8 * * *"
22511
+ },
22512
+ "status": "active",
22513
+ "metadata": {
22514
+ "templateKey": "operations-daily-client-briefing",
22515
+ "requiresPodWideEntityQueryLens": true
22516
+ },
22517
+ "flow": {
22518
+ "nodes": [
22519
+ {
22520
+ "id": "trigger",
22521
+ "type": "trigger",
22522
+ "position": {
22523
+ "x": 0,
22524
+ "y": 0
22525
+ },
22526
+ "data": {
22527
+ "label": "Daily at 08:00",
22528
+ "triggerType": "cron",
22529
+ "config": {
22530
+ "expression": "0 8 * * *"
22531
+ }
22532
+ }
22533
+ },
22534
+ {
22535
+ "id": "list-clients",
22536
+ "type": "capability",
22537
+ "position": {
22538
+ "x": 0,
22539
+ "y": 120
22540
+ },
22541
+ "data": {
22542
+ "label": "List clients (pod-wide `client` role)",
22543
+ "verbId": "entity.query",
22544
+ "inputMapping": {
22545
+ "profileSlug": "client",
22546
+ "scope": "pod",
22547
+ "limit": "100"
22548
+ }
22549
+ }
22550
+ },
22551
+ {
22552
+ "id": "clients-loop",
22553
+ "type": "loop",
22554
+ "position": {
22555
+ "x": 0,
22556
+ "y": 240
22557
+ },
22558
+ "data": {
22559
+ "label": "For each client",
22560
+ "iteratorExpression": "steps.list-clients.output.entities",
22561
+ "itemVariable": "client"
22562
+ }
22563
+ },
22564
+ {
22565
+ "id": "read-comms",
22566
+ "type": "messages_query",
22567
+ "position": {
22568
+ "x": 0,
22569
+ "y": 360
22570
+ },
22571
+ "data": {
22572
+ "label": "Read this client's recent comms",
22573
+ "subjectEntityId": "{{loop.item.id}}",
22574
+ "limit": 40
22575
+ }
22576
+ },
22577
+ {
22578
+ "id": "digest",
22579
+ "type": "capability",
22580
+ "position": {
22581
+ "x": 0,
22582
+ "y": 480
22583
+ },
22584
+ "data": {
22585
+ "label": "Distil the real signal \u2192 JSON",
22586
+ "verbId": "ai.generate",
22587
+ "inputMapping": {
22588
+ "json": "true",
22589
+ "maxTokens": "1200",
22590
+ "system": "You advise a client-delivery team. You read one client's recent inbound messages and surface only what genuinely matters. You are firewall-aware: your output is for the INTERNAL team, never the client.",
22591
+ "prompt": `Digest the recent communications for the client "{{loop.item.title}}" into a concise internal briefing for OUR delivery team.
22592
+ PEOPLE GUARD (do not break): distinguish the CLIENT's people from OUR team members who also appear in the thread. Never treat a teammate as a client contact, lead, or new person. Only real, client-side signal counts.
22593
+ Surface ONLY real signal: status changes, decisions, deals/opportunities, competitor mentions, new client-side leads/contacts, risks/blockers, and deadlines/commitments. Skip small talk and noise. Lead with what matters; keep it tight.
22594
+ Respond with STRICT JSON and NOTHING else: {
22595
+ "hasSignal": "true" or "false" (a STRING),
22596
+ "headline": "<one-line summary; empty string when hasSignal is 'false'>",
22597
+ "summary": "<a short markdown digest for the team; empty string when 'false'>",
22598
+ "risks": "<risks/blockers as short markdown, or empty string>",
22599
+ "nextActions": "<recommended next actions as short markdown, or empty string>"
22600
+ } Set hasSignal to "false" when there is no notable activity (no messages, or only chatter).
22601
+ Recent conversation (oldest first, JSON): {{steps.read-comms.output.messages}}`
22602
+ }
22603
+ }
22604
+ },
22605
+ {
22606
+ "id": "signal-gate",
22607
+ "type": "condition",
22608
+ "position": {
22609
+ "x": 0,
22610
+ "y": 600
22611
+ },
22612
+ "data": {
22613
+ "label": "Only continue when there's real signal",
22614
+ "expression": "steps.digest.output.hasSignal === true"
22615
+ }
22616
+ },
22617
+ {
22618
+ "id": "write-briefing",
22619
+ "type": "output",
22620
+ "position": {
22621
+ "x": 0,
22622
+ "y": 720
22623
+ },
22624
+ "data": {
22625
+ "label": "Save the client briefing",
22626
+ "outputType": "entity_create",
22627
+ "config": {
22628
+ "profileSlug": "client-briefing",
22629
+ "title": "Briefing \u2014 {{loop.item.title}}",
22630
+ "dedupeBy": "briefing-key",
22631
+ "properties": {
22632
+ "briefing-key": "{{loop.item.id}}::{{trigger.payload.scheduledAt}}",
22633
+ "briefing-client": "{{loop.item.id}}",
22634
+ "briefing-date": "{{trigger.payload.scheduledAt}}",
22635
+ "briefing-headline": "{{steps.digest.output.headline}}",
22636
+ "briefing-summary": "{{steps.digest.output.summary}}",
22637
+ "briefing-risks": "{{steps.digest.output.risks}}",
22638
+ "briefing-next-actions": "{{steps.digest.output.nextActions}}",
22639
+ "briefing-message-count": "{{steps.read-comms.output.count}}"
22640
+ }
22641
+ }
22642
+ }
22643
+ },
22644
+ {
22645
+ "id": "link-briefing",
22646
+ "type": "output",
22647
+ "position": {
22648
+ "x": 0,
22649
+ "y": 840
22650
+ },
22651
+ "data": {
22652
+ "label": "Link briefing \u2192 client",
22653
+ "outputType": "relation_create",
22654
+ "config": {
22655
+ "fromEntityId": "{{steps.write-briefing.output.entityId}}",
22656
+ "toEntityId": "{{loop.item.id}}",
22657
+ "relationType": "briefing_about_client"
22658
+ }
22659
+ }
22660
+ },
22661
+ {
22662
+ "id": "resolve-team",
22663
+ "type": "capability",
22664
+ "position": {
22665
+ "x": 0,
22666
+ "y": 960
22667
+ },
22668
+ "data": {
22669
+ "label": "Resolve the client's TEAM channel (FIREWALL)",
22670
+ "verbId": "channel.resolve",
22671
+ "inputMapping": {
22672
+ "contextObjectType": "entity",
22673
+ "contextObjectId": "{{loop.item.id}}",
22674
+ "branchPurpose": "team"
22675
+ }
22676
+ }
22677
+ },
22678
+ {
22679
+ "id": "post-recap",
22680
+ "type": "output",
22681
+ "position": {
22682
+ "x": 0,
22683
+ "y": 1080
22684
+ },
22685
+ "data": {
22686
+ "label": "Post the recap to the TEAM channel (FIREWALL)",
22687
+ "outputType": "channel_message",
22688
+ "config": {
22689
+ "channelId": "{{steps.resolve-team.output.channelId}}",
22690
+ "content": "**{{loop.item.title}} \u2014 daily briefing**\n{{steps.digest.output.headline}}\n{{steps.digest.output.summary}}\n**Risks:** {{steps.digest.output.risks}}\n**Next:** {{steps.digest.output.nextActions}}",
22691
+ "metadata": {
22692
+ "automationMessage": true,
22693
+ "kind": "client-briefing"
22694
+ }
22695
+ }
22696
+ }
22697
+ }
22698
+ ],
22699
+ "edges": [
22700
+ {
22701
+ "id": "e-trigger-list",
22702
+ "source": "trigger",
22703
+ "target": "list-clients"
22704
+ },
22705
+ {
22706
+ "id": "e-list-loop",
22707
+ "source": "list-clients",
22708
+ "target": "clients-loop"
22709
+ },
22710
+ {
22711
+ "id": "e-loop-read",
22712
+ "source": "clients-loop",
22713
+ "target": "read-comms"
22714
+ },
22715
+ {
22716
+ "id": "e-read-digest",
22717
+ "source": "read-comms",
22718
+ "target": "digest"
22719
+ },
22720
+ {
22721
+ "id": "e-digest-gate",
22722
+ "source": "digest",
22723
+ "target": "signal-gate"
22724
+ },
22725
+ {
22726
+ "id": "e-gate-write",
22727
+ "source": "signal-gate",
22728
+ "target": "write-briefing"
22729
+ },
22730
+ {
22731
+ "id": "e-write-link",
22732
+ "source": "write-briefing",
22733
+ "target": "link-briefing"
22734
+ },
22735
+ {
22736
+ "id": "e-link-resolve",
22737
+ "source": "link-briefing",
22738
+ "target": "resolve-team"
22739
+ },
22740
+ {
22741
+ "id": "e-resolve-post",
22742
+ "source": "resolve-team",
22743
+ "target": "post-recap"
22744
+ }
22745
+ ]
22746
+ }
22747
+ }
22748
+ ]
23095
22749
  },
23096
22750
  "outreach-comms": {
23097
22751
  "meta": {
23098
22752
  "slug": "outreach-comms",
22753
+ "domain": "revenue",
23099
22754
  "name": "Outreach & Comms",
23100
22755
  "description": "Personalized LinkedIn and email outreach \u2014 sequenced touches against real people and companies, drafted and sent by an agent.",
23101
22756
  "icon": "send",
@@ -23374,364 +23029,136 @@ var DATA = {
23374
23029
  {
23375
23030
  "name": "campaign",
23376
23031
  "type": "text",
23377
- "label": "Campaign name",
23378
- "required": true
23379
- },
23380
- {
23381
- "name": "channel",
23382
- "type": "choice",
23383
- "label": "Channel",
23384
- "defaultValue": "linkedin"
23385
- },
23386
- {
23387
- "name": "campaignContext",
23388
- "type": "text",
23389
- "label": "Value prop + call to action"
23390
- }
23391
- ],
23392
- "executor": "is-agent",
23393
- "grants": [
23394
- "linkedin_send_invite",
23395
- "unipile_send_message",
23396
- "gmail_send",
23397
- "entity.create"
23398
- ],
23399
- "status": "active"
23400
- }
23401
- ],
23402
- "integrations": [
23403
- {
23404
- "templateKey": "unipile-linkedin"
23405
- },
23406
- {
23407
- "templateKey": "nango-google"
23408
- }
23409
- ],
23410
- "onboarding": {
23411
- "goal": "Stand up an outreach motion \u2014 who we're targeting, on which channel, with what offer \u2014 so the agent can start drafting and sending real touches instead of waiting for a blank campaign.\n",
23412
- "framing": 'THE OUTBOUND LEAD: Act as a sharp SDR/outbound lead. Push for a SPECIFIC\nsegment and a SPECIFIC offer, not "reach out to everyone about our product".\nA campaign with no segment and no value prop is just a contact list.\n',
23413
- "expertise": {
23414
- "starters": [
23415
- 'Name the segment as a person, not a market \u2014 "Head of Growth at seed-to-Series-A B2B SaaS", not "SaaS companies". The agent personalizes against a person, not a category.\n',
23416
- 'Every campaign needs ONE call to action, stated plainly \u2014 a call, a demo, a reply. If the founder gives a vague goal ("build awareness"), push for the concrete next step a touch should provoke.\n'
23417
- ],
23418
- "blindSpots": [
23419
- "Founders default to email when LinkedIn converts better for cold B2B \u2014 ask which channel the target segment actually lives on before defaulting.\n",
23420
- "A campaign with no target contacts yet is fine to create, but flag it \u2014 the first touch needs at least one real person or company to reach.\n"
23421
- ],
23422
- "bar": "At least one real campaign exists with a named segment, a stated value prop and call to action, and \u2014 ideally \u2014 a first target contact ready for the Personalized Outreach playbook to run against.\n"
23423
- },
23424
- "collect": [
23425
- {
23426
- "profileSlug": "outreach-campaign",
23427
- "what": "The outreach sequences to run \u2014 channel, target segment, and offer.",
23428
- "cardinality": "few",
23429
- "keyFields": [
23430
- "channel",
23431
- "targetSegment",
23432
- "valueProp",
23433
- "callToAction"
23434
- ]
23435
- },
23436
- {
23437
- "profileSlug": "person",
23438
- "what": "The first contacts to target with this campaign.",
23439
- "cardinality": "few",
23440
- "keyFields": [
23441
- "email"
23442
- ]
23443
- }
23444
- ],
23445
- "openingQuestions": [
23446
- "Who are you trying to reach \u2014 what role, at what kind of company?",
23447
- "LinkedIn, email, or both?",
23448
- "What's the one thing you want them to do after reading your message?"
23449
- ],
23450
- "doneWhen": "At least one campaign captured with a channel, segment, and value prop, plus one target contact."
23451
- },
23452
- "app": {
23453
- "kind": "stored",
23454
- "cellKey": "entity-detail"
23455
- },
23456
- "layout": {
23457
- "defaultView": "Campaigns",
23458
- "defaultApp": null,
23459
- "pinnedApps": [
23460
- "dashboard",
23461
- "data"
23462
- ],
23463
- "sidebarItems": [
23464
- {
23465
- "kind": "view",
23466
- "viewName": "Campaigns",
23467
- "label": "Campaigns",
23468
- "icon": "target"
23469
- },
23470
- {
23471
- "kind": "view",
23472
- "viewName": "Touches",
23473
- "label": "Touches",
23474
- "icon": "message-circle"
23475
- },
23476
- {
23477
- "kind": "app",
23478
- "appId": "data",
23479
- "label": "Data",
23480
- "icon": "database"
23481
- }
23482
- ]
23483
- },
23484
- "bento": {
23485
- "viewName": "Campaigns",
23486
- "blocks": [
23487
- {
23488
- "kind": "view",
23489
- "viewName": "Campaigns",
23490
- "pos": {
23491
- "x": 0,
23492
- "y": 0,
23493
- "w": 8,
23494
- "h": 5
23495
- }
23496
- },
23497
- {
23498
- "kind": "view",
23499
- "viewName": "Touches",
23500
- "pos": {
23501
- "x": 8,
23502
- "y": 0,
23503
- "w": 4,
23504
- "h": 5
23505
- }
23506
- }
23507
- ]
23508
- }
23509
- },
23510
- "personal": {
23511
- "meta": {
23512
- "slug": "personal",
23513
- "name": "Personal Knowledge",
23514
- "description": "Capture notes, bookmarks, and articles \u2014 your AI-organized second brain.",
23515
- "icon": "brain",
23516
- "color": "#0891B2",
23517
- "tags": [
23518
- "personal",
23519
- "knowledge",
23520
- "notes",
23521
- "second-brain"
23522
- ],
23523
- "isPublic": true
23524
- },
23525
- "workspace": {
23526
- "name": "Personal",
23527
- "description": "Your personal knowledge base \u2014 capture anything, let AI organize it.",
23528
- "proposalId": "personal-v1",
23529
- "subtype": "personal",
23530
- "visibility": "pod_visible",
23531
- "capabilities": [
23532
- "knowledge.capture",
23533
- "knowledge.organize"
23534
- ]
23535
- },
23536
- "profiles": [
23537
- {
23538
- "slug": "note",
23539
- "displayName": "Note",
23540
- "icon": "file-text",
23541
- "color": "amber",
23542
- "description": "A quick note or idea.",
23543
- "properties": [
23544
- {
23545
- "slug": "tags",
23546
- "label": "Tags",
23547
- "valueType": "array",
23548
- "inputType": "text"
23549
- }
23550
- ]
23551
- },
23552
- {
23553
- "slug": "bookmark",
23554
- "displayName": "Bookmark",
23555
- "icon": "bookmark",
23556
- "color": "blue",
23557
- "description": "A saved URL or web reference.",
23558
- "properties": [
23559
- {
23560
- "slug": "url",
23561
- "label": "URL",
23562
- "valueType": "string",
23563
- "inputType": "url"
23564
- }
23565
- ]
23566
- },
23567
- {
23568
- "slug": "article",
23569
- "displayName": "Article",
23570
- "icon": "book-open",
23571
- "color": "violet",
23572
- "description": "A long-form article or reading-list item.",
23573
- "properties": [
23574
- {
23575
- "slug": "readStatus",
23576
- "label": "Status",
23577
- "valueType": "string",
23578
- "inputType": "select",
23579
- "enumValues": [
23580
- "to-read",
23581
- "reading",
23582
- "read",
23583
- "archived"
23584
- ]
23585
- },
23586
- {
23587
- "slug": "url",
23588
- "label": "Source URL",
23589
- "valueType": "string",
23590
- "inputType": "url"
23591
- }
23592
- ]
23593
- },
23594
- {
23595
- "slug": "project",
23596
- "displayName": "Project",
23597
- "icon": "folder",
23598
- "color": "green",
23599
- "description": "A project grouping related notes and references.",
23600
- "properties": [
23032
+ "label": "Campaign name",
23033
+ "required": true
23034
+ },
23601
23035
  {
23602
- "slug": "status",
23603
- "label": "Status",
23604
- "valueType": "string",
23605
- "inputType": "select",
23606
- "enumValues": [
23607
- "active",
23608
- "paused",
23609
- "done",
23610
- "archived"
23611
- ]
23036
+ "name": "channel",
23037
+ "type": "choice",
23038
+ "label": "Channel",
23039
+ "defaultValue": "linkedin"
23040
+ },
23041
+ {
23042
+ "name": "campaignContext",
23043
+ "type": "text",
23044
+ "label": "Value prop + call to action"
23612
23045
  }
23613
- ]
23046
+ ],
23047
+ "executor": "is-agent",
23048
+ "grants": [
23049
+ "linkedin_send_invite",
23050
+ "unipile_send_message",
23051
+ "gmail_send",
23052
+ "entity.create"
23053
+ ],
23054
+ "status": "active"
23614
23055
  }
23615
23056
  ],
23616
- "views": [
23617
- {
23618
- "name": "Feed",
23619
- "type": "masonry",
23620
- "scopeProfileSlugs": [
23621
- "note",
23622
- "bookmark",
23623
- "article",
23624
- "project"
23625
- ],
23626
- "description": "Everything you captured, newest first."
23627
- },
23057
+ "integrations": [
23628
23058
  {
23629
- "name": "Reading List",
23630
- "type": "table",
23631
- "scopeProfileSlug": "article",
23632
- "description": "Articles to read, in progress, and read."
23059
+ "templateKey": "unipile-linkedin"
23633
23060
  },
23634
23061
  {
23635
- "name": "Bookmarks",
23636
- "type": "grid",
23637
- "scopeProfileSlug": "bookmark",
23638
- "description": "Saved web references."
23062
+ "templateKey": "nango-google"
23639
23063
  }
23640
23064
  ],
23641
23065
  "onboarding": {
23642
- "goal": "Capture the shape of the user's world \u2014 what they're working on, what they're reading and saving, and how they think \u2014 so the workspace starts grounded in who they actually are.",
23643
- "framing": "THE KNOWLEDGE COACH: Act as a gentle, thoughtful personal-knowledge coach. You're here to understand their world, not audit it \u2014 curious, warm, never pushy. Meet them where they are: a couple of honest notes beat a perfect system. Reflect back what you hear so it feels captured, not interrogated.\n",
23066
+ "goal": "Stand up an outreach motion \u2014 who we're targeting, on which channel, with what offer \u2014 so the agent can start drafting and sending real touches instead of waiting for a blank campaign.\n",
23067
+ "framing": 'THE OUTBOUND LEAD: Act as a sharp SDR/outbound lead. Push for a SPECIFIC\nsegment and a SPECIFIC offer, not "reach out to everyone about our product".\nA campaign with no segment and no value prop is just a contact list.\n',
23644
23068
  "expertise": {
23645
23069
  "starters": [
23646
- `Start from ONE real recurring need, not a structure. Ask "what do you keep losing track of?" \u2014 the tab you meant to read, the idea you forgot, the link you can't find again \u2014 and seed that single thing. A personal space earns trust by solving one nagging friction, then grows; it dies if it opens as an empty filing cabinet.
23647
- `,
23648
- "Propose the 2-3 things they ACTUALLY want to track, then stop. Most people need exactly: a place for stray notes, a reading list, and a bookmark pile. Name those, seed one item in each, and resist adding projects/tags/statuses they didn't ask for. The default here is deliberately lean \u2014 under-structure on purpose.\n",
23649
- "Mirror their own capture habit instead of imposing one. Ask what a jotted thought usually looks like for them \u2014 a link, a one-liner, a voice-note-to-self \u2014 and map the workspace to that shape. If they dump links, lead with bookmarks; if they write, lead with notes. Match reality; don't teach them a new ritual.\n"
23070
+ 'Name the segment as a person, not a market \u2014 "Head of Growth at seed-to-Series-A B2B SaaS", not "SaaS companies". The agent personalizes against a person, not a category.\n',
23071
+ 'Every campaign needs ONE call to action, stated plainly \u2014 a call, a demo, a reply. If the founder gives a vague goal ("build awareness"), push for the concrete next step a touch should provoke.\n'
23650
23072
  ],
23651
23073
  "blindSpots": [
23652
- "The productivity-system graveyard: elaborate setups \u2014 nested tags, six statuses, color-coded areas \u2014 built with enthusiasm on day one and abandoned by day seven. The failure mode is over-structuring, not under-structuring. Every field you add is a field they must maintain; keep it embarrassingly simple and let it grow later.\n",
23653
- `People try to design the "perfect system" before they have any content, and stall. Structure should emerge FROM real notes, not precede them. If they're deliberating over categories with an empty workspace, cut it short \u2014 capture three real things first, and let the shape reveal itself.
23654
- `,
23655
- 'A reading list nobody triages just becomes guilt. People pile "to-read" articles and never mark anything read or dropped, so the list rots into a backlog they avoid. Give it a lightweight status (to-read / reading / read / archived) and normalize archiving unread \u2014 a shrinking list is a healthy one.\n'
23074
+ "Founders default to email when LinkedIn converts better for cold B2B \u2014 ask which channel the target segment actually lives on before defaulting.\n",
23075
+ "A campaign with no target contacts yet is fine to create, but flag it \u2014 the first touch needs at least one real person or company to reach.\n"
23656
23076
  ],
23657
- "bar": `A GREAT result is TWO OR THREE things they genuinely care about, each with a real item already in it \u2014 not an empty scaffold. It should feel like a lean personal shelf they'll actually open tomorrow, with nothing to maintain that they didn't ask for. If it looks like a "productivity system", it's already too much.
23658
- `
23077
+ "bar": "At least one real campaign exists with a named segment, a stated value prop and call to action, and \u2014 ideally \u2014 a first target contact ready for the Personalized Outreach playbook to run against.\n"
23659
23078
  },
23660
23079
  "collect": [
23661
23080
  {
23662
- "profileSlug": "project",
23663
- "what": "The handful of things they're actively working on or care about right now.",
23081
+ "profileSlug": "outreach-campaign",
23082
+ "what": "The outreach sequences to run \u2014 channel, target segment, and offer.",
23664
23083
  "cardinality": "few",
23665
23084
  "keyFields": [
23666
- "name",
23667
- "status"
23668
- ]
23669
- },
23670
- {
23671
- "profileSlug": "note",
23672
- "what": "A few ideas, thoughts, or things on their mind \u2014 however rough.",
23673
- "cardinality": "several",
23674
- "keyFields": [
23675
- "name",
23676
- "tags"
23677
- ]
23678
- },
23679
- {
23680
- "profileSlug": "article",
23681
- "what": "What they're reading or mean to read \u2014 their reading list.",
23682
- "cardinality": "several",
23683
- "keyFields": [
23684
- "name",
23685
- "readStatus"
23085
+ "channel",
23086
+ "targetSegment",
23087
+ "valueProp",
23088
+ "callToAction"
23686
23089
  ]
23687
23090
  },
23688
23091
  {
23689
- "profileSlug": "bookmark",
23690
- "what": "Web references and links worth keeping.",
23691
- "cardinality": "several",
23092
+ "profileSlug": "person",
23093
+ "what": "The first contacts to target with this campaign.",
23094
+ "cardinality": "few",
23692
23095
  "keyFields": [
23693
- "name",
23694
- "url"
23096
+ "email"
23695
23097
  ]
23696
23098
  }
23697
23099
  ],
23698
23100
  "openingQuestions": [
23699
- "What are you working on or thinking about most these days?",
23700
- "What have you been reading, saving, or meaning to get to?",
23701
- "When you jot something down, what does it usually look like \u2014 a link, a note, a task?"
23101
+ "Who are you trying to reach \u2014 what role, at what kind of company?",
23102
+ "LinkedIn, email, or both?",
23103
+ "What's the one thing you want them to do after reading your message?"
23702
23104
  ],
23703
- "doneWhen": "at least one project or note captured, plus one thing they're reading or saving."
23105
+ "doneWhen": "At least one campaign captured with a channel, segment, and value prop, plus one target contact."
23704
23106
  },
23705
23107
  "app": {
23706
23108
  "kind": "stored",
23707
23109
  "cellKey": "entity-detail"
23708
23110
  },
23709
23111
  "layout": {
23112
+ "defaultView": "Campaigns",
23113
+ "defaultApp": null,
23710
23114
  "pinnedApps": [
23711
23115
  "dashboard",
23712
23116
  "data",
23713
23117
  "chat"
23714
23118
  ],
23715
- "defaultView": "Feed",
23716
- "defaultApp": null,
23717
23119
  "sidebarItems": [
23718
23120
  {
23719
23121
  "kind": "view",
23720
- "viewName": "Feed",
23721
- "label": "Feed",
23722
- "icon": "layout-dashboard"
23122
+ "viewName": "Campaigns",
23123
+ "label": "Campaigns",
23124
+ "icon": "target"
23723
23125
  },
23724
23126
  {
23725
23127
  "kind": "view",
23726
- "viewName": "Reading List",
23727
- "label": "Reading List",
23728
- "icon": "book-open"
23128
+ "viewName": "Touches",
23129
+ "label": "Touches",
23130
+ "icon": "message-circle"
23729
23131
  },
23132
+ {
23133
+ "kind": "app",
23134
+ "appId": "data",
23135
+ "label": "Data",
23136
+ "icon": "database"
23137
+ }
23138
+ ]
23139
+ },
23140
+ "bento": {
23141
+ "viewName": "Outreach Home",
23142
+ "blocks": [
23730
23143
  {
23731
23144
  "kind": "view",
23732
- "viewName": "Bookmarks",
23733
- "label": "Bookmarks",
23734
- "icon": "bookmark"
23145
+ "viewName": "Campaigns",
23146
+ "pos": {
23147
+ "x": 0,
23148
+ "y": 0,
23149
+ "w": 8,
23150
+ "h": 5
23151
+ }
23152
+ },
23153
+ {
23154
+ "kind": "view",
23155
+ "viewName": "Touches",
23156
+ "pos": {
23157
+ "x": 8,
23158
+ "y": 0,
23159
+ "w": 4,
23160
+ "h": 5
23161
+ }
23735
23162
  }
23736
23163
  ]
23737
23164
  }
@@ -23739,6 +23166,7 @@ var DATA = {
23739
23166
  "project-management": {
23740
23167
  "meta": {
23741
23168
  "slug": "project-management",
23169
+ "domain": "build",
23742
23170
  "name": "Project Management OS",
23743
23171
  "description": "OKR-first project management workspace. Objectives, key results, projects, sprints, and tasks as connected entities \u2014 navigable from any direction in a relationship graph. Designed for solo founders and small teams who want goal-execution alignment without per-seat overhead.",
23744
23172
  "icon": "kanban-square",
@@ -25860,14 +25288,159 @@ var DATA = {
25860
25288
  "w": 4,
25861
25289
  "h": 6
25862
25290
  }
25863
- }
25864
- ]
25865
- },
25866
- "profileEntityBentoTemplates": {
25867
- "okr": {
25291
+ }
25292
+ ]
25293
+ },
25294
+ "profileEntityBentoTemplates": {
25295
+ "okr": {
25296
+ "blocks": [
25297
+ {
25298
+ "id": "okr-eb-header",
25299
+ "kind": "widget",
25300
+ "widgetType": "entity-header",
25301
+ "pos": {
25302
+ "x": 0,
25303
+ "y": 0,
25304
+ "w": 12,
25305
+ "h": 2
25306
+ }
25307
+ },
25308
+ {
25309
+ "id": "okr-eb-props",
25310
+ "kind": "widget",
25311
+ "widgetType": "entity-properties",
25312
+ "pos": {
25313
+ "x": 0,
25314
+ "y": 2,
25315
+ "w": 4,
25316
+ "h": 8
25317
+ }
25318
+ },
25319
+ {
25320
+ "id": "okr-eb-projects",
25321
+ "kind": "widget",
25322
+ "widgetType": "entity-list",
25323
+ "pos": {
25324
+ "x": 4,
25325
+ "y": 2,
25326
+ "w": 8,
25327
+ "h": 4
25328
+ },
25329
+ "config": {
25330
+ "profileSlug": "project",
25331
+ "title": "Projects",
25332
+ "limit": 6,
25333
+ "variant": "compact"
25334
+ }
25335
+ },
25336
+ {
25337
+ "id": "okr-eb-content",
25338
+ "kind": "widget",
25339
+ "widgetType": "entity-content",
25340
+ "pos": {
25341
+ "x": 4,
25342
+ "y": 6,
25343
+ "w": 8,
25344
+ "h": 4
25345
+ }
25346
+ }
25347
+ ]
25348
+ },
25349
+ "project": {
25350
+ "blocks": [
25351
+ {
25352
+ "id": "proj-eb-header",
25353
+ "kind": "widget",
25354
+ "widgetType": "entity-header",
25355
+ "pos": {
25356
+ "x": 0,
25357
+ "y": 0,
25358
+ "w": 12,
25359
+ "h": 2
25360
+ }
25361
+ },
25362
+ {
25363
+ "id": "proj-eb-props",
25364
+ "kind": "widget",
25365
+ "widgetType": "entity-properties",
25366
+ "pos": {
25367
+ "x": 0,
25368
+ "y": 2,
25369
+ "w": 4,
25370
+ "h": 8
25371
+ }
25372
+ },
25373
+ {
25374
+ "id": "proj-eb-tasks",
25375
+ "kind": "widget",
25376
+ "widgetType": "entity-list",
25377
+ "pos": {
25378
+ "x": 4,
25379
+ "y": 2,
25380
+ "w": 8,
25381
+ "h": 4
25382
+ },
25383
+ "config": {
25384
+ "profileSlug": "task",
25385
+ "title": "Tasks",
25386
+ "limit": 8,
25387
+ "variant": "compact"
25388
+ }
25389
+ },
25390
+ {
25391
+ "id": "proj-eb-content",
25392
+ "kind": "widget",
25393
+ "widgetType": "entity-content",
25394
+ "pos": {
25395
+ "x": 4,
25396
+ "y": 6,
25397
+ "w": 8,
25398
+ "h": 4
25399
+ }
25400
+ }
25401
+ ]
25402
+ },
25403
+ "task": {
25404
+ "blocks": [
25405
+ {
25406
+ "id": "task-eb-header",
25407
+ "kind": "widget",
25408
+ "widgetType": "entity-header",
25409
+ "pos": {
25410
+ "x": 0,
25411
+ "y": 0,
25412
+ "w": 12,
25413
+ "h": 2
25414
+ }
25415
+ },
25416
+ {
25417
+ "id": "task-eb-props",
25418
+ "kind": "widget",
25419
+ "widgetType": "entity-properties",
25420
+ "pos": {
25421
+ "x": 0,
25422
+ "y": 2,
25423
+ "w": 5,
25424
+ "h": 8
25425
+ }
25426
+ },
25427
+ {
25428
+ "id": "task-eb-content",
25429
+ "kind": "widget",
25430
+ "widgetType": "entity-content",
25431
+ "pos": {
25432
+ "x": 5,
25433
+ "y": 2,
25434
+ "w": 7,
25435
+ "h": 8
25436
+ }
25437
+ }
25438
+ ]
25439
+ },
25440
+ "sprint": {
25868
25441
  "blocks": [
25869
25442
  {
25870
- "id": "okr-eb-header",
25443
+ "id": "sprint-eb-header",
25871
25444
  "kind": "widget",
25872
25445
  "widgetType": "entity-header",
25873
25446
  "pos": {
@@ -25878,272 +25451,994 @@ var DATA = {
25878
25451
  }
25879
25452
  },
25880
25453
  {
25881
- "id": "okr-eb-props",
25454
+ "id": "sprint-eb-props",
25882
25455
  "kind": "widget",
25883
25456
  "widgetType": "entity-properties",
25884
25457
  "pos": {
25885
25458
  "x": 0,
25886
25459
  "y": 2,
25887
25460
  "w": 4,
25888
- "h": 8
25461
+ "h": 6
25889
25462
  }
25890
25463
  },
25891
25464
  {
25892
- "id": "okr-eb-projects",
25465
+ "id": "sprint-eb-tasks",
25893
25466
  "kind": "widget",
25894
25467
  "widgetType": "entity-list",
25895
25468
  "pos": {
25896
25469
  "x": 4,
25897
25470
  "y": 2,
25898
25471
  "w": 8,
25899
- "h": 4
25472
+ "h": 6
25900
25473
  },
25901
25474
  "config": {
25902
- "profileSlug": "project",
25903
- "title": "Projects",
25904
- "limit": 6,
25475
+ "profileSlug": "task",
25476
+ "title": "Sprint Tasks",
25477
+ "limit": 10,
25905
25478
  "variant": "compact"
25906
25479
  }
25907
- },
25480
+ }
25481
+ ]
25482
+ }
25483
+ },
25484
+ "playbooks": [
25485
+ {
25486
+ "name": "Sprint Retrospective",
25487
+ "goalTemplate": "Run a retrospective for {sprint} to review what went well, what didn't, and what to improve next sprint.",
25488
+ "params": [
25908
25489
  {
25909
- "id": "okr-eb-content",
25910
- "kind": "widget",
25911
- "widgetType": "entity-content",
25912
- "pos": {
25913
- "x": 4,
25914
- "y": 6,
25915
- "w": 8,
25916
- "h": 4
25490
+ "name": "sprint",
25491
+ "type": "entity",
25492
+ "label": "Sprint",
25493
+ "required": true
25494
+ }
25495
+ ]
25496
+ }
25497
+ ],
25498
+ "onboarding": {
25499
+ "goal": "Capture the user's goals, the projects in flight, the current sprint, and who's involved \u2014 so the workspace mirrors how their team actually plans and delivers.",
25500
+ "framing": "Act as a sharp delivery lead / chief of staff. Tease out what outcomes matter this quarter, what's actively being worked, what's in the current cycle, and who owns what. Translate that into OKRs, projects, a sprint, and people.",
25501
+ "expertise": {
25502
+ "starters": [
25503
+ `Don't collect a wishlist of goals \u2014 force ONE north-star metric and 2-3 key results that move it. Propose "the single number that means this quarter succeeded" first, then the handful of measurable KRs under it. Five objectives is zero objectives; a team that's aiming at everything is aiming at nothing.
25504
+ `,
25505
+ `Capture what's actually in flight and impose a WIP limit as you go. Ask "what's genuinely being worked THIS week" \u2014 not the backlog \u2014 and if it's more than the team can finish, that's the finding. Too many projects in progress means nothing ships; the map should make the overload visible.
25506
+ `,
25507
+ 'Every project and KR gets a named owner before anything else. Lead with "who owns this?" \u2014 a goal with no owner is a hope, and it will quietly slip. Capture the person on the project the moment you capture the project; ownerless work is the first thing to surface, not the last.\n'
25508
+ ],
25509
+ "blindSpots": [
25510
+ `"Everything is P1" is the prioritization failure that guarantees the wrong things ship. When every project is Critical, priority carries no information and the team defaults to whatever's loudest. Push back on the priority field \u2014 force a real ranking, because if you can't say what's LESS important, you haven't prioritized at all.
25511
+ `,
25512
+ `A goal with no owner is a hope, and hopes don't ship. Teams write beautiful OKRs with an empty owner field, and the KR that belongs to "the team" belongs to no one. Surface every ownerless objective, project, and KR \u2014 accountability is a name, not a shared intention.
25513
+ `,
25514
+ 'Too much work-in-progress is the silent throughput killer. Founders equate "many things started" with progress, but a dozen 60%-done projects deliver nothing while three finished ones deliver value. Watch the count of In-Progress items and flag when it exceeds what the team can actually close in a cycle.\n'
25515
+ ],
25516
+ "bar": `A great result is a workspace where the line from a single north-star metric down to the task in flight this week is unbroken: one clear objective with measurable KRs, every project and goal owned by a named person, a real priority ranking (not all-P1), and a WIP that matches capacity. You can answer "are we on track, who owns the thing that's slipping, and what should we STOP to ship what matters?" in one look.
25517
+ `
25518
+ },
25519
+ "collect": [
25520
+ {
25521
+ "profileSlug": "okr",
25522
+ "what": "The goals / OKRs that define success this quarter",
25523
+ "cardinality": "few",
25524
+ "keyFields": [
25525
+ "title",
25526
+ "okr-quarter",
25527
+ "okr-owner",
25528
+ "kr1-label"
25529
+ ]
25530
+ },
25531
+ {
25532
+ "profileSlug": "project",
25533
+ "what": "The projects actively in flight and their priority",
25534
+ "cardinality": "several",
25535
+ "keyFields": [
25536
+ "title",
25537
+ "project-status",
25538
+ "project-priority",
25539
+ "project-linked-okr"
25540
+ ]
25541
+ },
25542
+ {
25543
+ "profileSlug": "sprint",
25544
+ "what": "The current cycle / sprint and its goal",
25545
+ "cardinality": "one",
25546
+ "keyFields": [
25547
+ "title",
25548
+ "sprint-goal",
25549
+ "sprint-start",
25550
+ "sprint-end"
25551
+ ]
25552
+ },
25553
+ {
25554
+ "profileSlug": "person",
25555
+ "what": "The key people on the team and their roles",
25556
+ "cardinality": "several",
25557
+ "keyFields": [
25558
+ "name",
25559
+ "person-role",
25560
+ "person-email"
25561
+ ]
25562
+ }
25563
+ ],
25564
+ "openingQuestions": [
25565
+ "What are the big outcomes you're trying to hit this quarter?",
25566
+ "What projects are actively in flight right now, and which matter most?",
25567
+ "Who's on the team, and what does each person own?"
25568
+ ],
25569
+ "doneWhen": "This quarter's goals exist, active projects are captured with priority, a current sprint is defined, and the core team is on the board."
25570
+ }
25571
+ },
25572
+ "research-base": {
25573
+ "meta": {
25574
+ "slug": "research-base",
25575
+ "domain": "knowledge",
25576
+ "name": "Research",
25577
+ "description": "A research substrate \u2014 turn a question into a fully-recorded investigation. Sources ranked (nothing dropped), hypotheses weighed, findings mapped onto a living graph of fields and concepts.",
25578
+ "icon": "microscope",
25579
+ "color": "#8B5CF6",
25580
+ "tags": [
25581
+ "research",
25582
+ "knowledge",
25583
+ "graph",
25584
+ "sources",
25585
+ "evidence",
25586
+ "learning"
25587
+ ],
25588
+ "isPublic": true
25589
+ },
25590
+ "workspace": {
25591
+ "name": "Research",
25592
+ "description": "Turn a question into a fully-recorded investigation \u2014 sources ranked, hypotheses weighed, findings mapped onto a living graph of fields and concepts.",
25593
+ "subtype": "research-base",
25594
+ "visibility": "pod_visible",
25595
+ "capabilities": [
25596
+ "research.graph",
25597
+ "research.sources"
25598
+ ],
25599
+ "sourceRoles": {
25600
+ "research": "provider"
25601
+ }
25602
+ },
25603
+ "profiles": [
25604
+ {
25605
+ "slug": "question",
25606
+ "displayName": "Question",
25607
+ "icon": "help-circle",
25608
+ "color": "blue",
25609
+ "description": "An open question driving an investigation \u2014 the thing research answers.",
25610
+ "properties": [
25611
+ {
25612
+ "slug": "questionStatus",
25613
+ "label": "Status",
25614
+ "valueType": "string",
25615
+ "inputType": "select",
25616
+ "enumValues": [
25617
+ "open",
25618
+ "exploring",
25619
+ "answered",
25620
+ "abandoned"
25621
+ ],
25622
+ "constraints": {
25623
+ "defaultValue": "open"
25917
25624
  }
25918
25625
  }
25919
25626
  ]
25920
25627
  },
25921
- "project": {
25922
- "blocks": [
25628
+ {
25629
+ "slug": "research",
25630
+ "displayName": "Research",
25631
+ "icon": "microscope",
25632
+ "color": "violet",
25633
+ "description": "An investigation \u2014 the sources consulted, the findings, the confidence, and the conclusion.",
25634
+ "properties": [
25635
+ {
25636
+ "slug": "researchStatus",
25637
+ "label": "Status",
25638
+ "valueType": "string",
25639
+ "inputType": "select",
25640
+ "enumValues": [
25641
+ "ongoing",
25642
+ "concluded",
25643
+ "abandoned"
25644
+ ],
25645
+ "constraints": {
25646
+ "defaultValue": "ongoing"
25647
+ }
25648
+ },
25649
+ {
25650
+ "slug": "conclusion",
25651
+ "label": "Conclusion",
25652
+ "valueType": "string",
25653
+ "inputType": "textarea"
25654
+ },
25655
+ {
25656
+ "slug": "researchConfidence",
25657
+ "label": "Confidence",
25658
+ "valueType": "string",
25659
+ "inputType": "select",
25660
+ "enumValues": [
25661
+ "low",
25662
+ "medium",
25663
+ "high"
25664
+ ]
25665
+ }
25666
+ ]
25667
+ },
25668
+ {
25669
+ "slug": "field",
25670
+ "displayName": "Field",
25671
+ "icon": "layers",
25672
+ "color": "indigo",
25673
+ "description": "A domain of knowledge \u2014 Mathematics, Physics, AI, Philosophy. Fields overlap and feed each other.",
25674
+ "properties": [
25675
+ {
25676
+ "slug": "description",
25677
+ "label": "Description",
25678
+ "valueType": "string",
25679
+ "inputType": "textarea"
25680
+ },
25681
+ {
25682
+ "slug": "aliases",
25683
+ "label": "Also known as",
25684
+ "valueType": "array",
25685
+ "inputType": "tags"
25686
+ }
25687
+ ]
25688
+ },
25689
+ {
25690
+ "slug": "concept",
25691
+ "displayName": "Concept",
25692
+ "icon": "lightbulb",
25693
+ "color": "amber",
25694
+ "description": "An atomic idea \u2014 Bayesian inference, gradient descent, qualia. Belongs to one or more fields; has prerequisites.",
25695
+ "properties": [
25696
+ {
25697
+ "slug": "definition",
25698
+ "label": "Definition",
25699
+ "valueType": "string",
25700
+ "inputType": "textarea"
25701
+ },
25702
+ {
25703
+ "slug": "aliases",
25704
+ "label": "Also known as",
25705
+ "valueType": "array",
25706
+ "inputType": "tags"
25707
+ }
25708
+ ]
25709
+ },
25710
+ {
25711
+ "slug": "source",
25712
+ "displayName": "Source",
25713
+ "icon": "file-text",
25714
+ "color": "cyan",
25715
+ "description": "Anything consulted \u2014 a paper, article, dataset, or post. Ranked by credibility and NEVER discarded; rejected sources are kept with a reason.",
25716
+ "properties": [
25717
+ {
25718
+ "slug": "url",
25719
+ "label": "URL",
25720
+ "valueType": "string",
25721
+ "inputType": "url"
25722
+ },
25723
+ {
25724
+ "slug": "author",
25725
+ "label": "Author",
25726
+ "valueType": "string",
25727
+ "inputType": "text"
25728
+ },
25729
+ {
25730
+ "slug": "publishedAt",
25731
+ "label": "Published",
25732
+ "valueType": "date",
25733
+ "inputType": "date"
25734
+ },
25923
25735
  {
25924
- "id": "proj-eb-header",
25925
- "kind": "widget",
25926
- "widgetType": "entity-header",
25927
- "pos": {
25928
- "x": 0,
25929
- "y": 0,
25930
- "w": 12,
25931
- "h": 2
25736
+ "slug": "sourceType",
25737
+ "label": "Type",
25738
+ "valueType": "string",
25739
+ "inputType": "select",
25740
+ "enumValues": [
25741
+ "paper",
25742
+ "article",
25743
+ "book",
25744
+ "dataset",
25745
+ "blog",
25746
+ "video",
25747
+ "forum",
25748
+ "other"
25749
+ ],
25750
+ "constraints": {
25751
+ "defaultValue": "article"
25932
25752
  }
25933
25753
  },
25934
25754
  {
25935
- "id": "proj-eb-props",
25936
- "kind": "widget",
25937
- "widgetType": "entity-properties",
25938
- "pos": {
25939
- "x": 0,
25940
- "y": 2,
25941
- "w": 4,
25942
- "h": 8
25755
+ "slug": "credibilityBand",
25756
+ "label": "Credibility",
25757
+ "valueType": "string",
25758
+ "inputType": "select",
25759
+ "enumValues": [
25760
+ "high",
25761
+ "medium",
25762
+ "low",
25763
+ "unknown"
25764
+ ],
25765
+ "constraints": {
25766
+ "defaultValue": "unknown"
25943
25767
  }
25944
25768
  },
25945
25769
  {
25946
- "id": "proj-eb-tasks",
25947
- "kind": "widget",
25948
- "widgetType": "entity-list",
25949
- "pos": {
25950
- "x": 4,
25951
- "y": 2,
25952
- "w": 8,
25953
- "h": 4
25954
- },
25955
- "config": {
25956
- "profileSlug": "task",
25957
- "title": "Tasks",
25958
- "limit": 8,
25959
- "variant": "compact"
25770
+ "slug": "qualityScore",
25771
+ "label": "Quality (0\u2013100)",
25772
+ "valueType": "number",
25773
+ "inputType": "number",
25774
+ "constraints": {
25775
+ "min": 0,
25776
+ "max": 100
25960
25777
  }
25961
25778
  },
25962
25779
  {
25963
- "id": "proj-eb-content",
25964
- "kind": "widget",
25965
- "widgetType": "entity-content",
25966
- "pos": {
25967
- "x": 4,
25968
- "y": 6,
25969
- "w": 8,
25970
- "h": 4
25780
+ "slug": "status",
25781
+ "label": "Status",
25782
+ "valueType": "string",
25783
+ "inputType": "select",
25784
+ "enumValues": [
25785
+ "cited",
25786
+ "considered",
25787
+ "rejected"
25788
+ ],
25789
+ "constraints": {
25790
+ "defaultValue": "considered"
25971
25791
  }
25792
+ },
25793
+ {
25794
+ "slug": "whyRejected",
25795
+ "label": "Why rejected",
25796
+ "valueType": "string",
25797
+ "inputType": "textarea"
25798
+ },
25799
+ {
25800
+ "slug": "retrievedAt",
25801
+ "label": "Retrieved",
25802
+ "valueType": "date",
25803
+ "inputType": "date"
25972
25804
  }
25973
25805
  ]
25974
25806
  },
25975
- "task": {
25976
- "blocks": [
25807
+ {
25808
+ "slug": "hypothesis",
25809
+ "displayName": "Hypothesis",
25810
+ "icon": "git-branch",
25811
+ "color": "violet",
25812
+ "description": "A candidate theory or answer under test \u2014 argued for and against by sources.",
25813
+ "properties": [
25977
25814
  {
25978
- "id": "task-eb-header",
25979
- "kind": "widget",
25980
- "widgetType": "entity-header",
25981
- "pos": {
25982
- "x": 0,
25983
- "y": 0,
25984
- "w": 12,
25985
- "h": 2
25986
- }
25815
+ "slug": "statement",
25816
+ "label": "Statement",
25817
+ "valueType": "string",
25818
+ "inputType": "textarea"
25987
25819
  },
25988
25820
  {
25989
- "id": "task-eb-props",
25990
- "kind": "widget",
25991
- "widgetType": "entity-properties",
25992
- "pos": {
25993
- "x": 0,
25994
- "y": 2,
25995
- "w": 5,
25996
- "h": 8
25821
+ "slug": "stance",
25822
+ "label": "Stance",
25823
+ "valueType": "string",
25824
+ "inputType": "select",
25825
+ "enumValues": [
25826
+ "proposed",
25827
+ "supported",
25828
+ "contested",
25829
+ "refuted",
25830
+ "superseded"
25831
+ ],
25832
+ "constraints": {
25833
+ "defaultValue": "proposed"
25997
25834
  }
25998
25835
  },
25999
25836
  {
26000
- "id": "task-eb-content",
26001
- "kind": "widget",
26002
- "widgetType": "entity-content",
26003
- "pos": {
26004
- "x": 5,
26005
- "y": 2,
26006
- "w": 7,
26007
- "h": 8
26008
- }
25837
+ "slug": "confidence",
25838
+ "label": "Confidence",
25839
+ "valueType": "string",
25840
+ "inputType": "select",
25841
+ "enumValues": [
25842
+ "low",
25843
+ "medium",
25844
+ "high"
25845
+ ]
25846
+ },
25847
+ {
25848
+ "slug": "reasoning",
25849
+ "label": "Reasoning",
25850
+ "valueType": "string",
25851
+ "inputType": "textarea"
26009
25852
  }
26010
25853
  ]
26011
25854
  },
26012
- "sprint": {
26013
- "blocks": [
25855
+ {
25856
+ "slug": "finding",
25857
+ "displayName": "Finding",
25858
+ "icon": "check-circle",
25859
+ "color": "#10B981",
25860
+ "description": "A validated fact \u2014 the thing established between the question, the sources, and the reasoning. Carries calibrated confidence and links to its evidence.",
25861
+ "properties": [
26014
25862
  {
26015
- "id": "sprint-eb-header",
26016
- "kind": "widget",
26017
- "widgetType": "entity-header",
26018
- "pos": {
26019
- "x": 0,
26020
- "y": 0,
26021
- "w": 12,
26022
- "h": 2
26023
- }
25863
+ "slug": "claim",
25864
+ "label": "Claim",
25865
+ "valueType": "string",
25866
+ "inputType": "textarea"
26024
25867
  },
26025
25868
  {
26026
- "id": "sprint-eb-props",
26027
- "kind": "widget",
26028
- "widgetType": "entity-properties",
26029
- "pos": {
26030
- "x": 0,
26031
- "y": 2,
26032
- "w": 4,
26033
- "h": 6
25869
+ "slug": "confidence",
25870
+ "label": "Confidence (0\u20131)",
25871
+ "valueType": "number",
25872
+ "inputType": "number",
25873
+ "constraints": {
25874
+ "min": 0,
25875
+ "max": 1
26034
25876
  }
26035
25877
  },
26036
25878
  {
26037
- "id": "sprint-eb-tasks",
26038
- "kind": "widget",
26039
- "widgetType": "entity-list",
26040
- "pos": {
26041
- "x": 4,
26042
- "y": 2,
26043
- "w": 8,
26044
- "h": 6
26045
- },
26046
- "config": {
26047
- "profileSlug": "task",
26048
- "title": "Sprint Tasks",
26049
- "limit": 10,
26050
- "variant": "compact"
25879
+ "slug": "evidenceSummary",
25880
+ "label": "Evidence summary",
25881
+ "valueType": "string",
25882
+ "inputType": "textarea"
25883
+ },
25884
+ {
25885
+ "slug": "status",
25886
+ "label": "Status",
25887
+ "valueType": "string",
25888
+ "inputType": "select",
25889
+ "enumValues": [
25890
+ "validated",
25891
+ "provisional",
25892
+ "retracted"
25893
+ ],
25894
+ "constraints": {
25895
+ "defaultValue": "provisional"
26051
25896
  }
26052
25897
  }
26053
25898
  ]
26054
25899
  }
26055
- },
25900
+ ],
25901
+ "views": [
25902
+ {
25903
+ "name": "Knowledge Map",
25904
+ "slug": "research-knowledge-map",
25905
+ "type": "graph",
25906
+ "scopeProfileSlugs": [
25907
+ "field",
25908
+ "concept",
25909
+ "finding"
25910
+ ],
25911
+ "description": "The cartography \u2014 fields and concepts, their overlaps and prerequisites, and the findings attached to them.",
25912
+ "defaultView": true,
25913
+ "config": {
25914
+ "layout": "force",
25915
+ "showRelations": true
25916
+ }
25917
+ },
25918
+ {
25919
+ "name": "Open Questions",
25920
+ "slug": "research-open-questions",
25921
+ "type": "list",
25922
+ "scopeProfileSlug": "question",
25923
+ "description": "Questions still open \u2014 the research backlog.",
25924
+ "config": {
25925
+ "filterBy": {
25926
+ "field": "questionStatus",
25927
+ "operator": "is",
25928
+ "value": "open"
25929
+ }
25930
+ }
25931
+ },
25932
+ {
25933
+ "name": "Sources",
25934
+ "slug": "research-sources",
25935
+ "type": "table",
25936
+ "scopeProfileSlug": "source",
25937
+ "description": "Every source consulted, ranked by credibility \u2014 including the ones that were considered and rejected.",
25938
+ "config": {
25939
+ "columns": [
25940
+ "title",
25941
+ "sourceType",
25942
+ "credibilityBand",
25943
+ "qualityScore",
25944
+ "status"
25945
+ ]
25946
+ }
25947
+ },
25948
+ {
25949
+ "name": "Hypotheses",
25950
+ "slug": "research-hypotheses",
25951
+ "type": "kanban",
25952
+ "scopeProfileSlug": "hypothesis",
25953
+ "groupBy": "stance",
25954
+ "description": "Candidate theories, grouped by where the evidence has left them.",
25955
+ "config": {
25956
+ "groupBy": "stance"
25957
+ }
25958
+ },
25959
+ {
25960
+ "name": "Findings",
25961
+ "slug": "research-findings",
25962
+ "type": "table",
25963
+ "scopeProfileSlug": "finding",
25964
+ "description": "What's been established, with its confidence.",
25965
+ "config": {
25966
+ "columns": [
25967
+ "title",
25968
+ "confidence",
25969
+ "status"
25970
+ ]
25971
+ }
25972
+ },
25973
+ {
25974
+ "name": "Research Log",
25975
+ "slug": "research-log",
25976
+ "type": "table",
25977
+ "scopeProfileSlug": "research",
25978
+ "description": "Every investigation and where it stands.",
25979
+ "config": {
25980
+ "columns": [
25981
+ "title",
25982
+ "researchStatus",
25983
+ "researchConfidence"
25984
+ ]
25985
+ }
25986
+ }
25987
+ ],
25988
+ "entityLinks": [
25989
+ {
25990
+ "sourceProfileSlug": "field",
25991
+ "targetProfileSlug": "field",
25992
+ "type": "overlaps_with",
25993
+ "label": "Overlaps with"
25994
+ },
25995
+ {
25996
+ "sourceProfileSlug": "concept",
25997
+ "targetProfileSlug": "field",
25998
+ "type": "part_of",
25999
+ "label": "Part of"
26000
+ },
26001
+ {
26002
+ "sourceProfileSlug": "concept",
26003
+ "targetProfileSlug": "concept",
26004
+ "type": "prerequisite_of",
26005
+ "label": "Prerequisite of"
26006
+ },
26007
+ {
26008
+ "sourceProfileSlug": "concept",
26009
+ "targetProfileSlug": "concept",
26010
+ "type": "relates_to",
26011
+ "label": "Relates to"
26012
+ },
26013
+ {
26014
+ "sourceProfileSlug": "research",
26015
+ "targetProfileSlug": "question",
26016
+ "type": "investigates",
26017
+ "label": "Investigates"
26018
+ },
26019
+ {
26020
+ "sourceProfileSlug": "hypothesis",
26021
+ "targetProfileSlug": "question",
26022
+ "type": "answers",
26023
+ "label": "Answers"
26024
+ },
26025
+ {
26026
+ "sourceProfileSlug": "research",
26027
+ "targetProfileSlug": "source",
26028
+ "type": "explored",
26029
+ "label": "Explored"
26030
+ },
26031
+ {
26032
+ "sourceProfileSlug": "research",
26033
+ "targetProfileSlug": "finding",
26034
+ "type": "concluded",
26035
+ "label": "Concluded"
26036
+ },
26037
+ {
26038
+ "sourceProfileSlug": "source",
26039
+ "targetProfileSlug": "hypothesis",
26040
+ "type": "supports",
26041
+ "label": "Supports"
26042
+ },
26043
+ {
26044
+ "sourceProfileSlug": "source",
26045
+ "targetProfileSlug": "hypothesis",
26046
+ "type": "contradicts",
26047
+ "label": "Contradicts"
26048
+ },
26049
+ {
26050
+ "sourceProfileSlug": "source",
26051
+ "targetProfileSlug": "source",
26052
+ "type": "cites",
26053
+ "label": "Cites"
26054
+ },
26055
+ {
26056
+ "sourceProfileSlug": "finding",
26057
+ "targetProfileSlug": "research",
26058
+ "type": "derived_from",
26059
+ "label": "Derived from"
26060
+ },
26061
+ {
26062
+ "sourceProfileSlug": "finding",
26063
+ "targetProfileSlug": "source",
26064
+ "type": "supported_by",
26065
+ "label": "Supported by"
26066
+ },
26067
+ {
26068
+ "sourceProfileSlug": "finding",
26069
+ "targetProfileSlug": "concept",
26070
+ "type": "about",
26071
+ "label": "About"
26072
+ }
26073
+ ],
26056
26074
  "playbooks": [
26057
26075
  {
26058
- "name": "Sprint Retrospective",
26059
- "goalTemplate": "Run a retrospective for {sprint} to review what went well, what didn't, and what to improve next sprint.",
26076
+ "name": "Research a Question",
26077
+ "description": "Investigate a question end-to-end \u2014 gather and rank sources (keeping the rejected ones), weigh hypotheses, emit findings with calibrated confidence, and map them onto the knowledge graph.",
26078
+ "goalTemplate": "Investigate the question {question} and record the WHOLE investigation, not just the answer. Steps: (1) Use the source-triage skill to gather sources widely via web search, classify each by type and credibility, and create a `source` entity for every one \u2014 including the ones you rejected, marked rejected with a reason (never silently drop a source). (2) Form the candidate answers as `hypothesis` entities and link each to the question; link every source that bears on a hypothesis with `supports` or `contradicts`. (3) Use the evidence-synthesis skill to weigh the supporting vs contradicting sources and emit `finding` entities with honestly calibrated confidence, each `supported_by` its sources and `derived_from` this research. (4) Use the concept-cartography skill to place the findings onto the knowledge map \u2014 resolve or create the `field`/`concept` entities and wire `about` / `part_of` / `overlaps_with` / `prerequisite_of` edges, deduping against what already exists. (5) Create the `research` entity that `investigates` the question and `explored` the sources, write its conclusion and confidence, and set the question's status to answered. Every write is proposal-gated and reviewable.",
26079
+ "subjectProfile": {
26080
+ "profileSlug": "question"
26081
+ },
26060
26082
  "params": [
26061
26083
  {
26062
- "name": "sprint",
26084
+ "name": "question",
26063
26085
  "type": "entity",
26064
- "label": "Sprint",
26086
+ "label": "Question",
26065
26087
  "required": true
26066
26088
  }
26067
- ]
26089
+ ],
26090
+ "executor": "is-agent",
26091
+ "grants": [
26092
+ "source-triage",
26093
+ "evidence-synthesis",
26094
+ "concept-cartography",
26095
+ "exa_search",
26096
+ "entity.create"
26097
+ ],
26098
+ "status": "active"
26099
+ }
26100
+ ],
26101
+ "actionPlacements": [
26102
+ {
26103
+ "profileSlug": "question",
26104
+ "surface": "entity-detail",
26105
+ "kind": "playbook",
26106
+ "ref": "Research a Question",
26107
+ "label": "Research this"
26108
+ }
26109
+ ],
26110
+ "integrations": [
26111
+ {
26112
+ "templateKey": "research-methods"
26113
+ },
26114
+ {
26115
+ "templateKey": "exa"
26068
26116
  }
26069
26117
  ],
26070
26118
  "onboarding": {
26071
- "goal": "Capture the user's goals, the projects in flight, the current sprint, and who's involved \u2014 so the workspace mirrors how their team actually plans and delivers.",
26072
- "framing": "Act as a sharp delivery lead / chief of staff. Tease out what outcomes matter this quarter, what's actively being worked, what's in the current cycle, and who owns what. Translate that into OKRs, projects, a sprint, and people.",
26119
+ "goal": "Seed the workspace with the first real questions worth researching and the fields they live in \u2014 so the agent has something concrete to investigate, not a blank graph.\n",
26120
+ "framing": `THE RESEARCH LEAD: Act as a sharp research lead who cares about the QUESTION
26121
+ being well-formed and the EVIDENCE being honest. A vague question ("learn
26122
+ about AI") produces vague research; push for a question with a real edge \u2014 one
26123
+ a good answer would actually change. And insist the work keeps its
26124
+ counter-evidence: research that only kept what agreed with it isn't research.
26125
+ `,
26073
26126
  "expertise": {
26074
26127
  "starters": [
26075
- `Don't collect a wishlist of goals \u2014 force ONE north-star metric and 2-3 key results that move it. Propose "the single number that means this quarter succeeded" first, then the handful of measurable KRs under it. Five objectives is zero objectives; a team that's aiming at everything is aiming at nothing.
26076
- `,
26077
- `Capture what's actually in flight and impose a WIP limit as you go. Ask "what's genuinely being worked THIS week" \u2014 not the backlog \u2014 and if it's more than the team can finish, that's the finding. Too many projects in progress means nothing ships; the map should make the overload visible.
26078
- `,
26079
- 'Every project and KR gets a named owner before anything else. Lead with "who owns this?" \u2014 a goal with no owner is a hope, and it will quietly slip. Capture the person on the project the moment you capture the project; ownerless work is the first thing to surface, not the last.\n'
26128
+ 'A researchable question names what would count as an answer. "Is X better than Y for Z?" beats "tell me about X" \u2014 the first has a shape the evidence can fill; the second is a topic, not a question.\n',
26129
+ "Name the field(s) the question lives in up front \u2014 even roughly. It's the first anchor on the map, and it's what lets the system later surface the neighbouring field you didn't think to look in.\n"
26080
26130
  ],
26081
26131
  "blindSpots": [
26082
- `"Everything is P1" is the prioritization failure that guarantees the wrong things ship. When every project is Critical, priority carries no information and the team defaults to whatever's loudest. Push back on the priority field \u2014 force a real ranking, because if you can't say what's LESS important, you haven't prioritized at all.
26083
- `,
26084
- `A goal with no owner is a hope, and hopes don't ship. Teams write beautiful OKRs with an empty owner field, and the KR that belongs to "the team" belongs to no one. Surface every ownerless objective, project, and KR \u2014 accountability is a name, not a shared intention.
26085
- `,
26086
- 'Too much work-in-progress is the silent throughput killer. Founders equate "many things started" with progress, but a dozen 60%-done projects deliver nothing while three finished ones deliver value. Watch the count of In-Progress items and flag when it exceeds what the team can actually close in a cycle.\n'
26087
- ],
26088
- "bar": `A great result is a workspace where the line from a single north-star metric down to the task in flight this week is unbroken: one clear objective with measurable KRs, every project and goal owned by a named person, a real priority ranking (not all-P1), and a WIP that matches capacity. You can answer "are we on track, who owns the thing that's slipping, and what should we STOP to ship what matters?" in one look.
26089
- `
26132
+ "The most valuable sources are often the ones that DISAGREE. If the founder only wants confirmation, say plainly that a one-sided answer is a weaker answer \u2014 the method keeps both sides on purpose.\n",
26133
+ '"I already know the answer" is where research quietly stops being research. If the conclusion is decided before the sources are gathered, flag it \u2014 the point is to be able to be wrong.\n'
26134
+ ]
26090
26135
  },
26091
26136
  "collect": [
26092
26137
  {
26093
- "profileSlug": "okr",
26094
- "what": "The goals / OKRs that define success this quarter",
26138
+ "profileSlug": "question",
26139
+ "what": "The first real questions worth investigating \u2014 each with a genuine edge, not a topic.",
26095
26140
  "cardinality": "few",
26096
26141
  "keyFields": [
26097
- "title",
26098
- "okr-quarter",
26099
- "okr-owner",
26100
- "kr1-label"
26142
+ "questionStatus"
26101
26143
  ]
26102
26144
  },
26103
26145
  {
26104
- "profileSlug": "project",
26105
- "what": "The projects actively in flight and their priority",
26106
- "cardinality": "several",
26146
+ "profileSlug": "field",
26147
+ "what": "The fields these questions live in \u2014 the first anchors on the knowledge map.",
26148
+ "cardinality": "few",
26107
26149
  "keyFields": [
26108
- "title",
26109
- "project-status",
26110
- "project-priority",
26111
- "project-linked-okr"
26150
+ "description"
26112
26151
  ]
26152
+ }
26153
+ ],
26154
+ "openingQuestions": [
26155
+ "What's a question you actually want a well-evidenced answer to \u2014 one where a good answer would change what you do?",
26156
+ "Which field(s) does it sit in \u2014 and is there a neighbouring field it might borrow from?",
26157
+ "What would count as a convincing answer, and what would change your mind?"
26158
+ ],
26159
+ "doneWhen": "At least one well-formed question captured with its field(s) anchored on the map, ready for the Research a Question playbook to run against.\n"
26160
+ },
26161
+ "app": {
26162
+ "kind": "stored",
26163
+ "cellKey": "entity-detail"
26164
+ },
26165
+ "layout": {
26166
+ "defaultView": "Knowledge Map",
26167
+ "defaultApp": null,
26168
+ "pinnedApps": [
26169
+ "dashboard",
26170
+ "data",
26171
+ "chat"
26172
+ ],
26173
+ "sidebarItems": [
26174
+ {
26175
+ "kind": "view",
26176
+ "viewName": "Knowledge Map",
26177
+ "label": "Map",
26178
+ "icon": "layers"
26113
26179
  },
26114
26180
  {
26115
- "profileSlug": "sprint",
26116
- "what": "The current cycle / sprint and its goal",
26117
- "cardinality": "one",
26118
- "keyFields": [
26119
- "title",
26120
- "sprint-goal",
26121
- "sprint-start",
26122
- "sprint-end"
26123
- ]
26181
+ "kind": "view",
26182
+ "viewName": "Open Questions",
26183
+ "label": "Questions",
26184
+ "icon": "help-circle"
26124
26185
  },
26125
26186
  {
26126
- "profileSlug": "person",
26127
- "what": "The key people on the team and their roles",
26128
- "cardinality": "several",
26129
- "keyFields": [
26130
- "name",
26131
- "person-role",
26132
- "person-email"
26187
+ "kind": "view",
26188
+ "viewName": "Sources",
26189
+ "label": "Sources",
26190
+ "icon": "file-text"
26191
+ },
26192
+ {
26193
+ "kind": "view",
26194
+ "viewName": "Findings",
26195
+ "label": "Findings",
26196
+ "icon": "check-circle"
26197
+ },
26198
+ {
26199
+ "kind": "app",
26200
+ "appId": "data",
26201
+ "label": "Data",
26202
+ "icon": "database"
26203
+ }
26204
+ ]
26205
+ },
26206
+ "bento": {
26207
+ "viewName": "Research Home",
26208
+ "blocks": [
26209
+ {
26210
+ "kind": "view",
26211
+ "viewName": "Knowledge Map",
26212
+ "pos": {
26213
+ "x": 0,
26214
+ "y": 0,
26215
+ "w": 8,
26216
+ "h": 6
26217
+ }
26218
+ },
26219
+ {
26220
+ "kind": "view",
26221
+ "viewName": "Open Questions",
26222
+ "pos": {
26223
+ "x": 8,
26224
+ "y": 0,
26225
+ "w": 4,
26226
+ "h": 3
26227
+ }
26228
+ },
26229
+ {
26230
+ "kind": "view",
26231
+ "viewName": "Findings",
26232
+ "pos": {
26233
+ "x": 8,
26234
+ "y": 3,
26235
+ "w": 4,
26236
+ "h": 3
26237
+ }
26238
+ }
26239
+ ]
26240
+ }
26241
+ },
26242
+ "research-decision": {
26243
+ "meta": {
26244
+ "slug": "research-decision",
26245
+ "domain": "knowledge",
26246
+ "name": "Decision Analysis",
26247
+ "description": "Turn an open question into a decision \u2014 options weighed with evidence, and the roads-not-taken preserved with the reasons they lost. Composes onto the Research substrate.",
26248
+ "icon": "scale",
26249
+ "color": "#F59E0B",
26250
+ "tags": [
26251
+ "research",
26252
+ "decision",
26253
+ "ibis",
26254
+ "analysis",
26255
+ "evidence"
26256
+ ],
26257
+ "isPublic": true
26258
+ },
26259
+ "workspace": {
26260
+ "name": "Research",
26261
+ "description": "Adds the IBIS decision-analysis method to the Research substrate \u2014 weigh options with evidence and record the decision, not just the winner.",
26262
+ "subtype": "research-base"
26263
+ },
26264
+ "dependencies": [
26265
+ {
26266
+ "slug": "research-base",
26267
+ "relation": "compose",
26268
+ "reason": "Decision Analysis is a research method \u2014 it needs the Research substrate (question / source / hypothesis / finding) to work over."
26269
+ }
26270
+ ],
26271
+ "profiles": [
26272
+ {
26273
+ "slug": "question",
26274
+ "displayName": "Question",
26275
+ "icon": "help-circle",
26276
+ "color": "blue",
26277
+ "description": "The open question being decided.",
26278
+ "properties": [
26279
+ {
26280
+ "slug": "questionStatus",
26281
+ "label": "Status",
26282
+ "valueType": "string",
26283
+ "inputType": "select",
26284
+ "enumValues": [
26285
+ "open",
26286
+ "exploring",
26287
+ "answered",
26288
+ "abandoned"
26289
+ ],
26290
+ "constraints": {
26291
+ "defaultValue": "open"
26292
+ }
26293
+ }
26294
+ ]
26295
+ },
26296
+ {
26297
+ "slug": "hypothesis",
26298
+ "displayName": "Option",
26299
+ "icon": "git-branch",
26300
+ "color": "violet",
26301
+ "description": "A candidate option under consideration \u2014 argued for and against by sources.",
26302
+ "properties": [
26303
+ {
26304
+ "slug": "stance",
26305
+ "label": "Stance",
26306
+ "valueType": "string",
26307
+ "inputType": "select",
26308
+ "enumValues": [
26309
+ "proposed",
26310
+ "supported",
26311
+ "contested",
26312
+ "refuted",
26313
+ "superseded"
26314
+ ],
26315
+ "constraints": {
26316
+ "defaultValue": "proposed"
26317
+ }
26318
+ }
26319
+ ]
26320
+ },
26321
+ {
26322
+ "slug": "decision",
26323
+ "displayName": "Decision",
26324
+ "icon": "scale",
26325
+ "color": "amber",
26326
+ "description": "A resolved decision \u2014 the recommendation, why it won, and the alternatives that lost (and why).",
26327
+ "properties": [
26328
+ {
26329
+ "slug": "summary",
26330
+ "label": "Summary",
26331
+ "valueType": "string",
26332
+ "inputType": "text"
26333
+ },
26334
+ {
26335
+ "slug": "rationale",
26336
+ "label": "Rationale",
26337
+ "valueType": "string",
26338
+ "inputType": "textarea"
26339
+ },
26340
+ {
26341
+ "slug": "alternatives",
26342
+ "label": "Alternatives considered",
26343
+ "valueType": "string",
26344
+ "inputType": "textarea"
26345
+ },
26346
+ {
26347
+ "slug": "decisionStatus",
26348
+ "label": "Status",
26349
+ "valueType": "string",
26350
+ "inputType": "select",
26351
+ "enumValues": [
26352
+ "proposed",
26353
+ "accepted",
26354
+ "superseded",
26355
+ "rejected"
26356
+ ],
26357
+ "constraints": {
26358
+ "defaultValue": "proposed"
26359
+ }
26360
+ }
26361
+ ]
26362
+ }
26363
+ ],
26364
+ "views": [
26365
+ {
26366
+ "name": "Decisions",
26367
+ "slug": "research-decisions",
26368
+ "type": "table",
26369
+ "scopeProfileSlug": "decision",
26370
+ "description": "Every decision reached, its recommendation, and where it stands.",
26371
+ "config": {
26372
+ "columns": [
26373
+ "title",
26374
+ "summary",
26375
+ "decisionStatus"
26133
26376
  ]
26134
26377
  }
26135
- ],
26136
- "openingQuestions": [
26137
- "What are the big outcomes you're trying to hit this quarter?",
26138
- "What projects are actively in flight right now, and which matter most?",
26139
- "Who's on the team, and what does each person own?"
26140
- ],
26141
- "doneWhen": "This quarter's goals exist, active projects are captured with priority, a current sprint is defined, and the core team is on the board."
26142
- }
26378
+ }
26379
+ ],
26380
+ "entityLinks": [
26381
+ {
26382
+ "sourceProfileSlug": "decision",
26383
+ "targetProfileSlug": "question",
26384
+ "type": "resolves",
26385
+ "label": "Resolves"
26386
+ },
26387
+ {
26388
+ "sourceProfileSlug": "hypothesis",
26389
+ "targetProfileSlug": "decision",
26390
+ "type": "considered_in",
26391
+ "label": "Considered in"
26392
+ }
26393
+ ],
26394
+ "playbooks": [
26395
+ {
26396
+ "name": "Decision Analysis",
26397
+ "description": "Structure an open question as a decision via IBIS \u2014 enumerate the options, argue each with evidence (keeping the rejected sources), weigh against explicit criteria, and record the decision with its roads-not-taken.",
26398
+ "goalTemplate": "Analyze the question {question} as a DECISION and record the reasoning, not just the verdict, using the ibis-decision-analysis skill. Steps: (1) State the issue sharply so the options are genuinely mutually exclusive. (2) Enumerate the real options \u2014 including the status-quo \u2014 as `hypothesis` entities linked to the question, and to the resulting decision via `considered_in`. (3) For each option, gather the sources that `supports` and those that `contradicts` it (use source gathering; KEEP the rejected sources with a reason \u2014 never drop the counter-evidence). (4) Weigh the options against explicit, named criteria (cost, reversibility, risk, time, evidence strength). (5) Record the recommendation as a `decision` entity that `resolves` the question \u2014 its rationale explains why it won, and its `alternatives` field preserves the options that lost and WHY. (6) Note what evidence would change the decision. Every write is proposal-gated.",
26399
+ "subjectProfile": {
26400
+ "profileSlug": "question"
26401
+ },
26402
+ "params": [
26403
+ {
26404
+ "name": "question",
26405
+ "type": "entity",
26406
+ "label": "Question",
26407
+ "required": true
26408
+ }
26409
+ ],
26410
+ "executor": "is-agent",
26411
+ "grants": [
26412
+ "ibis-decision-analysis",
26413
+ "source-triage",
26414
+ "exa_search",
26415
+ "entity.create"
26416
+ ],
26417
+ "status": "active"
26418
+ }
26419
+ ],
26420
+ "actionPlacements": [
26421
+ {
26422
+ "profileSlug": "question",
26423
+ "surface": "entity-detail",
26424
+ "kind": "playbook",
26425
+ "ref": "Decision Analysis",
26426
+ "label": "Analyze as decision"
26427
+ }
26428
+ ],
26429
+ "integrations": [
26430
+ {
26431
+ "templateKey": "research-methods"
26432
+ },
26433
+ {
26434
+ "templateKey": "exa"
26435
+ }
26436
+ ]
26143
26437
  },
26144
26438
  "social": {
26145
26439
  "meta": {
26146
26440
  "slug": "social",
26441
+ "domain": "content",
26147
26442
  "name": "Social",
26148
26443
  "description": "Plan, schedule, and publish across your channels \u2014 then track how each post performs. Channels, posts, schedules, and engagement signals, all connected.",
26149
26444
  "icon": "share-2",
@@ -26156,6 +26451,14 @@ var DATA = {
26156
26451
  ],
26157
26452
  "isPublic": true
26158
26453
  },
26454
+ "dependencies": [
26455
+ {
26456
+ "slug": "content-os",
26457
+ "kind": "workspace",
26458
+ "relation": "require",
26459
+ "reason": "Reuses Content OS's shared platform (publishing-account) vocabulary."
26460
+ }
26461
+ ],
26159
26462
  "workspace": {
26160
26463
  "name": "Social",
26161
26464
  "description": "The distribution layer \u2014 the channels you publish on, the posts and schedules that pace them, and the engagement signals that tell you what's working.",
@@ -26174,59 +26477,110 @@ var DATA = {
26174
26477
  },
26175
26478
  "profiles": [
26176
26479
  {
26177
- "slug": "channel",
26178
- "displayName": "Channel",
26179
- "icon": "radio",
26180
- "color": "#1D9BF0",
26181
- "description": "A social account you publish on \u2014 a platform, a handle, and its audience.",
26480
+ "slug": "platform",
26481
+ "displayName": "Platform",
26482
+ "icon": "share-2",
26483
+ "color": "#06B6D4",
26484
+ "description": "A social account, newsletter publication, or podcast channel. Each platform has its own audience metrics and publishing rhythm.",
26485
+ "scope": "shared",
26182
26486
  "properties": [
26183
26487
  {
26184
- "slug": "platform",
26185
- "label": "Platform",
26488
+ "slug": "platform-type",
26489
+ "label": "Type",
26186
26490
  "valueType": "string",
26187
26491
  "inputType": "select",
26188
26492
  "enumValues": [
26189
- "x",
26190
- "linkedin",
26191
- "instagram",
26192
- "tiktok",
26193
- "youtube",
26194
- "facebook",
26195
- "threads",
26196
- "other"
26493
+ "LinkedIn",
26494
+ "Instagram",
26495
+ "TikTok",
26496
+ "YouTube",
26497
+ "Twitter / X",
26498
+ "Threads",
26499
+ "Bluesky",
26500
+ "Newsletter",
26501
+ "Podcast",
26502
+ "Blog / Website",
26503
+ "Other"
26197
26504
  ]
26198
26505
  },
26199
26506
  {
26200
26507
  "slug": "handle",
26201
26508
  "label": "Handle",
26202
26509
  "valueType": "string",
26203
- "inputType": "text"
26510
+ "inputType": "text",
26511
+ "placeholder": "@username"
26204
26512
  },
26205
26513
  {
26206
- "slug": "channel-url",
26207
- "label": "URL",
26514
+ "slug": "platform-status",
26515
+ "label": "Status",
26208
26516
  "valueType": "string",
26209
- "inputType": "url"
26517
+ "inputType": "select",
26518
+ "enumValues": [
26519
+ "Active",
26520
+ "Building",
26521
+ "Maintenance Mode",
26522
+ "Inactive"
26523
+ ]
26524
+ },
26525
+ {
26526
+ "slug": "platform-url",
26527
+ "label": "Profile URL",
26528
+ "valueType": "string",
26529
+ "inputType": "text",
26530
+ "placeholder": "https://...",
26531
+ "constraints": {
26532
+ "format": "url"
26533
+ }
26210
26534
  },
26211
26535
  {
26212
26536
  "slug": "follower-count",
26213
- "label": "Followers",
26537
+ "label": "Follower / Subscriber Count",
26214
26538
  "valueType": "number",
26215
26539
  "inputType": "number"
26216
26540
  },
26217
26541
  {
26218
- "slug": "channel-status",
26219
- "label": "Status",
26542
+ "slug": "follower-target",
26543
+ "label": "Target Count",
26544
+ "valueType": "number",
26545
+ "inputType": "number"
26546
+ },
26547
+ {
26548
+ "slug": "avg-engagement-rate",
26549
+ "label": "Avg Engagement Rate (%)",
26550
+ "valueType": "number",
26551
+ "inputType": "number"
26552
+ },
26553
+ {
26554
+ "slug": "platform-posting-freq",
26555
+ "label": "Posting Frequency",
26220
26556
  "valueType": "string",
26221
26557
  "inputType": "select",
26222
26558
  "enumValues": [
26223
- "active",
26224
- "paused",
26225
- "archived"
26226
- ],
26227
- "constraints": {
26228
- "defaultValue": "active"
26229
- }
26559
+ "Daily",
26560
+ "3x / week",
26561
+ "2x / week",
26562
+ "Weekly",
26563
+ "Bi-weekly",
26564
+ "Monthly",
26565
+ "As Needed"
26566
+ ]
26567
+ },
26568
+ {
26569
+ "slug": "last-post-date",
26570
+ "label": "Last Post Date",
26571
+ "valueType": "date"
26572
+ },
26573
+ {
26574
+ "slug": "platform-notes",
26575
+ "label": "Notes",
26576
+ "valueType": "string",
26577
+ "inputType": "text",
26578
+ "placeholder": "What works here? Tone, format, best times..."
26579
+ },
26580
+ {
26581
+ "slug": "platform-tags",
26582
+ "label": "Tags",
26583
+ "valueType": "array"
26230
26584
  }
26231
26585
  ]
26232
26586
  },
@@ -26253,10 +26607,10 @@ var DATA = {
26253
26607
  }
26254
26608
  },
26255
26609
  {
26256
- "slug": "post-channel",
26257
- "label": "Channel",
26610
+ "slug": "post-platform",
26611
+ "label": "Platform",
26258
26612
  "valueType": "entity_id",
26259
- "targetProfileSlug": "channel",
26613
+ "targetProfileSlug": "platform",
26260
26614
  "inputType": "entity_select"
26261
26615
  },
26262
26616
  {
@@ -26299,10 +26653,10 @@ var DATA = {
26299
26653
  "description": "A recurring cadence for a channel \u2014 the slot pattern that keeps posting consistent.",
26300
26654
  "properties": [
26301
26655
  {
26302
- "slug": "schedule-channel",
26303
- "label": "Channel",
26656
+ "slug": "schedule-platform",
26657
+ "label": "Platform",
26304
26658
  "valueType": "entity_id",
26305
- "targetProfileSlug": "channel",
26659
+ "targetProfileSlug": "platform",
26306
26660
  "inputType": "entity_select"
26307
26661
  },
26308
26662
  {
@@ -26340,10 +26694,10 @@ var DATA = {
26340
26694
  "description": "A performance reading for a channel over a period \u2014 reach, impressions, and the reactions that came back.",
26341
26695
  "properties": [
26342
26696
  {
26343
- "slug": "signal-channel",
26344
- "label": "Channel",
26697
+ "slug": "signal-platform",
26698
+ "label": "Platform",
26345
26699
  "valueType": "entity_id",
26346
- "targetProfileSlug": "channel",
26700
+ "targetProfileSlug": "platform",
26347
26701
  "inputType": "entity_select"
26348
26702
  },
26349
26703
  {
@@ -26407,11 +26761,11 @@ var DATA = {
26407
26761
  "description": "Posts on a board by status \u2014 draft to published."
26408
26762
  },
26409
26763
  {
26410
- "name": "Channels",
26411
- "slug": "channels",
26764
+ "name": "Platforms",
26765
+ "slug": "platforms",
26412
26766
  "type": "table",
26413
- "scopeProfileSlug": "channel",
26414
- "description": "The channels you publish on, with platform, handle, and audience."
26767
+ "scopeProfileSlug": "platform",
26768
+ "description": "The platforms you publish on, with type, handle, and audience."
26415
26769
  },
26416
26770
  {
26417
26771
  "name": "Signals",
@@ -26426,21 +26780,21 @@ var DATA = {
26426
26780
  "framing": 'THE SOCIAL LEAD: Act as a sharp distribution lead. Anchor every post to a real Content asset or a Marketing brief \u2014 social is the distribution arm, not a separate content factory. Push for one channel done genuinely well over spraying thin across five. Refuse "we post everywhere" \u2014 ask which channel actually earns attention, and what the real cadence is.\n',
26427
26781
  "collect": [
26428
26782
  {
26429
- "profileSlug": "channel",
26430
- "what": "The channels you actually publish on \u2014 one per real account, with its platform and handle.",
26783
+ "profileSlug": "platform",
26784
+ "what": "The platforms you actually publish on \u2014 one per real account, with its type and handle.",
26431
26785
  "cardinality": "few",
26432
26786
  "keyFields": [
26433
- "platform",
26787
+ "platform-type",
26434
26788
  "handle"
26435
26789
  ]
26436
26790
  },
26437
26791
  {
26438
26792
  "profileSlug": "social-post",
26439
- "what": "The posts in motion \u2014 drafts, scheduled, and recently published \u2014 each tied to its channel.",
26793
+ "what": "The posts in motion \u2014 drafts, scheduled, and recently published \u2014 each tied to its platform.",
26440
26794
  "cardinality": "several",
26441
26795
  "keyFields": [
26442
26796
  "post-status",
26443
- "post-channel"
26797
+ "post-platform"
26444
26798
  ]
26445
26799
  }
26446
26800
  ],
@@ -26471,8 +26825,8 @@ var DATA = {
26471
26825
  },
26472
26826
  {
26473
26827
  "kind": "view",
26474
- "viewName": "Channels",
26475
- "label": "Channels",
26828
+ "viewName": "Platforms",
26829
+ "label": "Platforms",
26476
26830
  "icon": "radio"
26477
26831
  },
26478
26832
  {
@@ -26488,7 +26842,7 @@ var DATA = {
26488
26842
  "blocks": [
26489
26843
  {
26490
26844
  "kind": "view",
26491
- "viewName": "Channels",
26845
+ "viewName": "Platforms",
26492
26846
  "pos": {
26493
26847
  "x": 0,
26494
26848
  "y": 0,
@@ -26512,6 +26866,7 @@ var DATA = {
26512
26866
  "the-arch": {
26513
26867
  "meta": {
26514
26868
  "slug": "the-arch",
26869
+ "domain": "company",
26515
26870
  "name": "The Arch",
26516
26871
  "description": "The complete private company brain \u2014 the whole Enterprise OS plus the grant pipeline, the web3 ecosystem overlay, and the dev dashboard.",
26517
26872
  "icon": "landmark",
@@ -26756,6 +27111,7 @@ function rowToRemoteEntry(row, isPrivate) {
26756
27111
  name: row.displayName,
26757
27112
  description: row.description ?? void 0,
26758
27113
  category: row.category,
27114
+ domain: row.domain ?? void 0,
26759
27115
  tags: row.tags ?? [],
26760
27116
  icon: row.icon ?? null,
26761
27117
  isPrivate
@@ -26785,10 +27141,12 @@ function bundledToEntry(tpl) {
26785
27141
  slug: tpl.meta.slug,
26786
27142
  name: tpl.meta.name,
26787
27143
  description: tpl.meta.description,
26788
- // Every bundled template is a full workspace — the CP calls this category
26789
- // "workspace" (PACKAGE_TYPES). Finer display grouping is derived from `tags`
26790
- // by the consumer (browser `categoryFor`), not baked in here.
27144
+ // `category` is the PACKAGE TYPE — every bundled template is a full
27145
+ // workspace (PACKAGE_TYPES). Human display grouping is the SEPARATE
27146
+ // authored `domain` field (see ./domains.ts), read straight from meta —
27147
+ // not re-derived from tags by each consumer, which is what drifted before.
26791
27148
  category: "workspace",
27149
+ domain: tpl.meta.domain,
26792
27150
  tags: tpl.meta.tags ?? [],
26793
27151
  icon: tpl.meta.icon,
26794
27152
  isPrivate: tpl.meta.isPublic === false,
@@ -26802,6 +27160,7 @@ function remoteToEntry(row) {
26802
27160
  name: row.name,
26803
27161
  description: row.description,
26804
27162
  category: row.category,
27163
+ domain: row.domain,
26805
27164
  tags: row.tags ?? [],
26806
27165
  icon: row.icon ?? null,
26807
27166
  isPrivate: row.isPrivate ?? false,
@@ -27010,6 +27369,505 @@ function layerTemplateGraph(input) {
27010
27369
  return { nodes, edges, layers, cycles };
27011
27370
  }
27012
27371
 
27372
+ // src/concept-guard.ts
27373
+ var DECLARED_DIVERGENCES = {
27374
+ // Two-tier lead vocabulary, documented at business-developer.yaml:1-16.
27375
+ // Foundation's `lead` is a SHARED pod-wide role: being a lead is true
27376
+ // everywhere. `crm-lead` is a WORKSPACE-scoped role so a person can be a lead
27377
+ // inside one CRM workspace without becoming a lead across the whole pod. The
27378
+ // tiers are intentionally separate rows; `semanticSlug: crm.lead` records the
27379
+ // kinship so the two are discoverable as one concept via getBySemanticSlug.
27380
+ "crm-lead|lead": "business-developer: workspace-tier lead, deliberately NOT pod-wide foundation `lead` (two-tier CRM design)",
27381
+ // Same reasoning for the post-sale side of the same lifecycle.
27382
+ "client|crm-client": "business-developer: workspace-tier client, deliberately NOT pod-wide foundation `client` (two-tier CRM design)"
27383
+ };
27384
+ function effectiveSemanticSlug(profile) {
27385
+ return profile.semanticSlug ?? profile.slug;
27386
+ }
27387
+ function conceptTerm(semanticSlug) {
27388
+ const tokens = semanticSlug.split(/[.\-_]/).filter(Boolean);
27389
+ return (tokens[tokens.length - 1] ?? semanticSlug).toLowerCase();
27390
+ }
27391
+ function declaredValue(profile, field) {
27392
+ const raw = profile[field];
27393
+ if (raw === void 0 || raw === null) return null;
27394
+ if (field === "applicableKinds") {
27395
+ return Array.isArray(raw) ? JSON.stringify([...raw].sort()) : null;
27396
+ }
27397
+ return JSON.stringify(String(raw).toLowerCase());
27398
+ }
27399
+ function pairKey(a, b) {
27400
+ return [a, b].sort().join("|");
27401
+ }
27402
+ function findConceptViolations(templates = WORKSPACE_TEMPLATES) {
27403
+ const violations = [];
27404
+ const all = [];
27405
+ for (const [templateSlug, template] of Object.entries(templates)) {
27406
+ for (const profile of template.profiles ?? []) {
27407
+ all.push({ template: templateSlug, profile });
27408
+ }
27409
+ }
27410
+ const roles = all.filter((r) => r.profile.profileKind === "role");
27411
+ const usedAllowlistKeys = /* @__PURE__ */ new Set();
27412
+ const reportedPairs = /* @__PURE__ */ new Set();
27413
+ for (let i = 0; i < roles.length; i++) {
27414
+ for (let j = i + 1; j < roles.length; j++) {
27415
+ const a = roles[i];
27416
+ const b = roles[j];
27417
+ if (a.template === b.template) continue;
27418
+ if (a.profile.slug === b.profile.slug) continue;
27419
+ const term = conceptTerm(effectiveSemanticSlug(a.profile));
27420
+ if (term !== conceptTerm(effectiveSemanticSlug(b.profile))) continue;
27421
+ const key = pairKey(a.profile.slug, b.profile.slug);
27422
+ if (key in DECLARED_DIVERGENCES) {
27423
+ usedAllowlistKeys.add(key);
27424
+ continue;
27425
+ }
27426
+ if (reportedPairs.has(key)) continue;
27427
+ reportedPairs.add(key);
27428
+ violations.push({
27429
+ rule: "concept-collision",
27430
+ concept: term,
27431
+ message: `two role profiles denote the concept "${term}" under different slugs: "${a.profile.slug}" (${a.template}) vs "${b.profile.slug}" (${b.template}). Either REUSE the existing slug, or \u2014 if the divergence is intentional \u2014 declare it: set an explicit \`semanticSlug\` on the new profile and add "${key}" to DECLARED_DIVERGENCES in src/concept-guard.ts with the reason.`
27432
+ });
27433
+ }
27434
+ }
27435
+ const bySemantic = /* @__PURE__ */ new Map();
27436
+ for (const ref of all) {
27437
+ const key = effectiveSemanticSlug(ref.profile);
27438
+ const bucket = bySemantic.get(key);
27439
+ if (bucket) bucket.push(ref);
27440
+ else bySemantic.set(key, [ref]);
27441
+ }
27442
+ for (const [semantic, group] of bySemantic) {
27443
+ if (new Set(group.map((r) => r.profile.slug)).size < 2) continue;
27444
+ for (const field of ["profileKind", "scope", "applicableKinds"]) {
27445
+ const claims = /* @__PURE__ */ new Map();
27446
+ for (const ref of group) {
27447
+ const value = declaredValue(ref.profile, field);
27448
+ if (value === null) continue;
27449
+ const existing = claims.get(value);
27450
+ if (!existing) claims.set(value, `${ref.template}:${ref.profile.slug}`);
27451
+ }
27452
+ if (claims.size > 1) {
27453
+ violations.push({
27454
+ rule: "alias-shape-divergence",
27455
+ concept: semantic,
27456
+ message: `profiles aliased to semanticSlug "${semantic}" disagree on \`${field}\`: ` + [...claims].map(([v, who]) => `${who} declares ${v}`).join(", ") + `. Aliased profiles assert one concept \u2014 make the shapes agree, or drop the alias.`
27457
+ });
27458
+ }
27459
+ }
27460
+ }
27461
+ for (const key of Object.keys(DECLARED_DIVERGENCES)) {
27462
+ if (usedAllowlistKeys.has(key)) continue;
27463
+ violations.push({
27464
+ rule: "stale-allowlist",
27465
+ concept: key,
27466
+ message: `DECLARED_DIVERGENCES entry "${key}" no longer matches any collision \u2014 the divergence was resolved or the profiles were renamed. Delete the entry.`
27467
+ });
27468
+ }
27469
+ return violations;
27470
+ }
27471
+ function formatConceptViolations(violations) {
27472
+ return violations.map((v) => ` \u2022 [${v.rule}] ${v.message}`).join("\n");
27473
+ }
27474
+
27475
+ // src/domains.ts
27476
+ var OTHER_DOMAIN_ID = "other";
27477
+ var OTHER_DOMAIN_LABEL = "More";
27478
+ var TEMPLATE_DOMAINS = [
27479
+ { id: "strategy", label: "Strategy & Market" },
27480
+ { id: "revenue", label: "Sales & Marketing" },
27481
+ { id: "content", label: "Content & Social" },
27482
+ { id: "company", label: "Company & Operations" },
27483
+ { id: "build", label: "Build & Operate" },
27484
+ { id: "knowledge", label: "Knowledge & Research" }
27485
+ ];
27486
+ var KNOWN = new Map(
27487
+ TEMPLATE_DOMAINS.map((d, i) => [d.id, { label: d.label, order: i }])
27488
+ );
27489
+ function isKnownDomain(id) {
27490
+ return id != null && KNOWN.has(id);
27491
+ }
27492
+ function domainLabel(id) {
27493
+ if (!id) return OTHER_DOMAIN_LABEL;
27494
+ const known = KNOWN.get(id);
27495
+ if (known) return known.label;
27496
+ return id.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
27497
+ }
27498
+ function groupByDomain(items, domainOf) {
27499
+ const buckets = /* @__PURE__ */ new Map();
27500
+ for (const item of items) {
27501
+ const id = domainOf(item) || OTHER_DOMAIN_ID;
27502
+ const bucket = buckets.get(id);
27503
+ if (bucket) bucket.push(item);
27504
+ else buckets.set(id, [item]);
27505
+ }
27506
+ const rank = (id) => {
27507
+ if (id === OTHER_DOMAIN_ID) return Number.MAX_SAFE_INTEGER;
27508
+ const known = KNOWN.get(id);
27509
+ return known ? known.order : 1e6;
27510
+ };
27511
+ return [...buckets.entries()].sort(([a], [b]) => {
27512
+ const ra = rank(a);
27513
+ const rb = rank(b);
27514
+ if (ra !== rb) return ra - rb;
27515
+ return a < b ? -1 : a > b ? 1 : 0;
27516
+ }).map(([id, groupItems]) => ({
27517
+ id,
27518
+ label: id === OTHER_DOMAIN_ID ? OTHER_DOMAIN_LABEL : domainLabel(id),
27519
+ items: groupItems
27520
+ }));
27521
+ }
27522
+
27523
+ // src/validate.ts
27524
+ var REQUIRED_META_FIELDS = [
27525
+ "slug",
27526
+ "name",
27527
+ "description",
27528
+ "icon",
27529
+ "color"
27530
+ ];
27531
+ var REQUIRED_WORKSPACE_FIELDS = ["name", "description"];
27532
+ var SCOPE_EXEMPT = /* @__PURE__ */ new Set(["whiteboard", "mindmap", "bento"]);
27533
+ var SYSTEM_PROFILES = /* @__PURE__ */ new Set([
27534
+ // Core capture hierarchy
27535
+ "note",
27536
+ "task",
27537
+ "event",
27538
+ "bookmark",
27539
+ "website",
27540
+ "article",
27541
+ // People / orgs / CRM
27542
+ "person",
27543
+ "contact",
27544
+ "company",
27545
+ "deal",
27546
+ // Files + programmatic kinds
27547
+ "file",
27548
+ "anchor",
27549
+ "signal_item",
27550
+ // Knowledge-work flow
27551
+ "decision",
27552
+ "question",
27553
+ "research",
27554
+ "knowledge",
27555
+ "user_observation"
27556
+ ]);
27557
+ function isPodWideProfile(p) {
27558
+ return String(p.scope || "").toLowerCase() === "shared";
27559
+ }
27560
+ function collectBaseProfileSlugs(data, resolveDep, seen = /* @__PURE__ */ new Set()) {
27561
+ const out = /* @__PURE__ */ new Set();
27562
+ for (const dep of data.dependencies || []) {
27563
+ if (dep.relation !== "compose" && dep.relation !== "require") continue;
27564
+ if (seen.has(dep.slug)) continue;
27565
+ seen.add(dep.slug);
27566
+ const base = resolveDep(dep.slug);
27567
+ if (!base) continue;
27568
+ const podWideOnly = dep.relation === "require";
27569
+ for (const p of base.profiles || []) {
27570
+ if (podWideOnly && !isPodWideProfile(p)) continue;
27571
+ out.add(p.slug);
27572
+ }
27573
+ for (const s of collectBaseProfileSlugs(base, resolveDep, seen)) out.add(s);
27574
+ }
27575
+ return out;
27576
+ }
27577
+ function collectProfileSlugRefs(node, path, out) {
27578
+ if (node == null || typeof node !== "object") return;
27579
+ if (Array.isArray(node)) {
27580
+ node.forEach((v, i) => collectProfileSlugRefs(v, `${path}[${i}]`, out));
27581
+ return;
27582
+ }
27583
+ for (const [k, v] of Object.entries(node)) {
27584
+ if (k === "profileSlug" && typeof v === "string" && !v.includes("{{")) {
27585
+ out.push({ where: `${path}.profileSlug`, slug: v });
27586
+ } else {
27587
+ collectProfileSlugRefs(v, `${path}.${k}`, out);
27588
+ }
27589
+ }
27590
+ }
27591
+ function resolveDepFrom(opts) {
27592
+ if (opts.resolveDep) return opts.resolveDep;
27593
+ if (opts.corpus) {
27594
+ const bySlug = /* @__PURE__ */ new Map();
27595
+ for (const t of opts.corpus) {
27596
+ const s = t.meta?.slug;
27597
+ if (s) bySlug.set(s, t);
27598
+ }
27599
+ return (slug) => bySlug.get(slug);
27600
+ }
27601
+ return () => void 0;
27602
+ }
27603
+ function validateTemplate(tpl, opts = {}) {
27604
+ const errors = [];
27605
+ const add = (rule, path, message) => errors.push({ rule, path, message });
27606
+ if (!tpl.meta) add("meta-required", "meta", "Missing required field: meta");
27607
+ else {
27608
+ for (const f of REQUIRED_META_FIELDS) {
27609
+ if (!tpl.meta[f]) add("meta-field-required", `meta.${f}`, `meta.${f} is required`);
27610
+ }
27611
+ }
27612
+ if (!tpl.workspace)
27613
+ add("workspace-required", "workspace", "Missing required field: workspace");
27614
+ else {
27615
+ for (const f of REQUIRED_WORKSPACE_FIELDS) {
27616
+ if (!tpl.workspace[f])
27617
+ add("workspace-field-required", `workspace.${f}`, `workspace.${f} is required`);
27618
+ }
27619
+ }
27620
+ if (!tpl.profiles || tpl.profiles.length === 0) {
27621
+ add("profiles-required", "profiles", "At least one profile is required");
27622
+ }
27623
+ const baseProfileSlugs = collectBaseProfileSlugs(tpl, resolveDepFrom(opts));
27624
+ const slugs = new Set((tpl.profiles || []).map((p) => p.slug));
27625
+ const known = (s) => slugs.has(s) || SYSTEM_PROFILES.has(s) || baseProfileSlugs.has(s);
27626
+ for (const v of tpl.views || []) {
27627
+ const type = String(v.type || "").toLowerCase();
27628
+ const scoped = v.scopeProfileSlug || v.scopeProfileSlugs && v.scopeProfileSlugs.length;
27629
+ if (!SCOPE_EXEMPT.has(type) && !scoped) {
27630
+ add(
27631
+ "view-missing-scope",
27632
+ `views."${v.name}"`,
27633
+ `view "${v.name}" (${type}) needs scopeProfileSlug(s) \u2014 structured views require a scope`
27634
+ );
27635
+ }
27636
+ if (v.scopeProfileSlug && !known(v.scopeProfileSlug))
27637
+ add(
27638
+ "view-scope-unknown",
27639
+ `views."${v.name}".scopeProfileSlug`,
27640
+ `view "${v.name}" scopes unknown profile "${v.scopeProfileSlug}"`
27641
+ );
27642
+ for (const s of v.scopeProfileSlugs || [])
27643
+ if (!known(s))
27644
+ add(
27645
+ "view-scope-unknown",
27646
+ `views."${v.name}".scopeProfileSlugs`,
27647
+ `view "${v.name}" scopes unknown profile "${s}"`
27648
+ );
27649
+ }
27650
+ for (const p of tpl.profiles || []) {
27651
+ for (const pr of p.properties || []) {
27652
+ if (pr.targetProfileSlug && !known(pr.targetProfileSlug)) {
27653
+ add(
27654
+ "property-target-unknown",
27655
+ `profiles.${p.slug}.${pr.slug}.targetProfileSlug`,
27656
+ `property ${p.slug}.${pr.slug} targets unknown profile "${pr.targetProfileSlug}"`
27657
+ );
27658
+ }
27659
+ }
27660
+ }
27661
+ for (const el of tpl.entityLinks || []) {
27662
+ if (!known(el.sourceProfileSlug))
27663
+ add(
27664
+ "entitylink-source-unknown",
27665
+ "entityLinks",
27666
+ `entityLink source "${el.sourceProfileSlug}" is unknown`
27667
+ );
27668
+ if (!known(el.targetProfileSlug))
27669
+ add(
27670
+ "entitylink-target-unknown",
27671
+ "entityLinks",
27672
+ `entityLink target "${el.targetProfileSlug}" is unknown`
27673
+ );
27674
+ if (typeof el.type !== "string" || !el.type) {
27675
+ add(
27676
+ "entitylink-missing-type",
27677
+ "entityLinks",
27678
+ `entityLink ${el.sourceProfileSlug}\u2192${el.targetProfileSlug} is missing its \`type\` (the predicate)`
27679
+ );
27680
+ }
27681
+ }
27682
+ for (const c of tpl.onboarding?.collect || []) {
27683
+ if (!known(c.profileSlug))
27684
+ add(
27685
+ "onboarding-ref-unknown",
27686
+ "onboarding.collect",
27687
+ `onboarding.collect references unknown profile "${c.profileSlug}"`
27688
+ );
27689
+ }
27690
+ for (const s of tpl.seedEntities || []) {
27691
+ if (!known(s.profileSlug))
27692
+ add(
27693
+ "seedentity-ref-unknown",
27694
+ "seedEntities",
27695
+ `seedEntity references unknown profile "${s.profileSlug}"`
27696
+ );
27697
+ }
27698
+ for (const a of tpl.automations || []) {
27699
+ const refs = [];
27700
+ collectProfileSlugRefs(a.triggerConfig, `automation "${a.name}".triggerConfig`, refs);
27701
+ collectProfileSlugRefs(a.flow, `automation "${a.name}".flow`, refs);
27702
+ for (const r of refs)
27703
+ if (!known(r.slug))
27704
+ add("automation-ref-unknown", r.where, `${r.where} references unknown profile "${r.slug}"`);
27705
+ }
27706
+ for (const pb of tpl.playbooks || []) {
27707
+ const ps = pb.subjectProfile?.profileSlug;
27708
+ if (ps && !known(ps))
27709
+ add(
27710
+ "playbook-ref-unknown",
27711
+ `playbooks."${pb.name}".subjectProfile`,
27712
+ `playbook "${pb.name}".subjectProfile references unknown profile "${ps}"`
27713
+ );
27714
+ }
27715
+ for (const ap of tpl.actionPlacements || []) {
27716
+ if (ap.profileSlug && !known(ap.profileSlug)) {
27717
+ add(
27718
+ "actionplacement-ref-unknown",
27719
+ "actionPlacements",
27720
+ `actionPlacement "${ap.label ?? ap.ref}" references unknown profile "${ap.profileSlug}"`
27721
+ );
27722
+ }
27723
+ }
27724
+ for (const si of tpl.layout?.sidebarItems || []) {
27725
+ if (si.profileSlug && !known(si.profileSlug)) {
27726
+ add(
27727
+ "sidebar-ref-unknown",
27728
+ "layout.sidebarItems",
27729
+ `layout.sidebarItems ("${si.label ?? si.profileSlug}") references unknown profile "${si.profileSlug}"`
27730
+ );
27731
+ }
27732
+ }
27733
+ for (const dt of tpl.displayTemplates || []) {
27734
+ if (dt.entityType && !known(dt.entityType)) {
27735
+ add(
27736
+ "displaytemplate-ref-unknown",
27737
+ `displayTemplates."${dt.name}".entityType`,
27738
+ `displayTemplate "${dt.name}" targets unknown profile "${dt.entityType}" (entityType)`
27739
+ );
27740
+ }
27741
+ }
27742
+ for (const key of Object.keys(tpl.profileEntityBentoTemplates || {})) {
27743
+ if (!known(key))
27744
+ add(
27745
+ "bentotemplate-ref-unknown",
27746
+ "profileEntityBentoTemplates",
27747
+ `profileEntityBentoTemplates has an entry for unknown profile "${key}"`
27748
+ );
27749
+ }
27750
+ const composeDeps = (tpl.dependencies || []).filter((d) => d.relation === "compose");
27751
+ for (const dep of composeDeps) {
27752
+ if (tpl.workspace?.visibility !== void 0) {
27753
+ add(
27754
+ "overlay-visibility",
27755
+ "workspace.visibility",
27756
+ `overlay (compose on "${dep.slug}") must OMIT workspace.visibility \u2014 it overwrites the base's on additive reconcile`
27757
+ );
27758
+ }
27759
+ if (tpl.workspace?.subtype !== dep.slug) {
27760
+ add(
27761
+ "overlay-subtype",
27762
+ "workspace.subtype",
27763
+ `overlay (compose on "${dep.slug}") must set workspace.subtype to "${dep.slug}" (found "${tpl.workspace?.subtype}")`
27764
+ );
27765
+ }
27766
+ }
27767
+ const blocks = tpl.bento?.blocks ?? [];
27768
+ const authoredWidgets = blocks.filter((b) => b.kind === "widget");
27769
+ const authoredViews = blocks.filter((b) => b.kind === "view");
27770
+ const unknownKind = blocks.filter((b) => b.kind !== "widget" && b.kind !== "view");
27771
+ if (unknownKind.length) {
27772
+ add(
27773
+ "bento-unknown-kind",
27774
+ "bento.blocks",
27775
+ `${unknownKind.length} bento block(s) with unknown kind: ${unknownKind.map((b) => String(b.kind)).join(", ")}`
27776
+ );
27777
+ }
27778
+ const badWidgets = authoredWidgets.filter((b) => !b.widgetType);
27779
+ const badViews = authoredViews.filter((b) => !b.viewName);
27780
+ if (badWidgets.length) {
27781
+ add(
27782
+ "bento-widget-missing-type",
27783
+ "bento.blocks",
27784
+ `${badWidgets.length} widget block(s) missing widgetType`
27785
+ );
27786
+ }
27787
+ if (badViews.length) {
27788
+ add(
27789
+ "bento-view-missing-name",
27790
+ "bento.blocks",
27791
+ `${badViews.length} view block(s) missing viewName`
27792
+ );
27793
+ }
27794
+ if (opts.converters) {
27795
+ const { toWorkspaceDefinition: toWorkspaceDefinition2, toPackageDefinition: toPackageDefinition2 } = opts.converters;
27796
+ const { definition } = toWorkspaceDefinition2(tpl);
27797
+ const pkg = toPackageDefinition2(tpl);
27798
+ if (blocks.length > 0) {
27799
+ const expectW = authoredWidgets.length - badWidgets.length;
27800
+ const expectV = authoredViews.length - badViews.length;
27801
+ const doors = [
27802
+ ["tRPC createFromDefinition", definition.bentoLayout ?? [], definition.bentoViewBlocks ?? []],
27803
+ ["CP packages/apply", pkg.bentoLayout ?? [], pkg.bentoViewBlocks ?? []]
27804
+ ];
27805
+ for (const [door, layout, viewBlocks] of doors) {
27806
+ if (layout.length !== expectW || viewBlocks.length !== expectV) {
27807
+ add(
27808
+ "bento-split-count",
27809
+ "bento.blocks",
27810
+ `[${door}]: authored ${expectW} widget/${expectV} view \u2192 got ${layout.length} bentoLayout/${viewBlocks.length} bentoViewBlocks`
27811
+ );
27812
+ }
27813
+ const layoutBad = layout.filter((b) => typeof b.widgetType !== "string");
27814
+ const viewsBad = viewBlocks.filter(
27815
+ (b) => typeof b.viewName !== "string" || b.kind !== "view"
27816
+ );
27817
+ if (layoutBad.length) {
27818
+ add(
27819
+ "bento-layout-shape",
27820
+ "bento.blocks",
27821
+ `[${door}]: ${layoutBad.length} bentoLayout block(s) without a string widgetType (mis-routed view block?)`
27822
+ );
27823
+ }
27824
+ if (viewsBad.length) {
27825
+ add(
27826
+ "bento-viewblocks-shape",
27827
+ "bento.blocks",
27828
+ `[${door}]: ${viewsBad.length} bentoViewBlocks entry(s) without kind:'view' + string viewName (mis-routed widget block?)`
27829
+ );
27830
+ }
27831
+ }
27832
+ }
27833
+ const authoredViewName = tpl.bento?.viewName;
27834
+ if (authoredViewName) {
27835
+ if (definition.bentoViewName !== authoredViewName) {
27836
+ add(
27837
+ "bento-viewname-parity",
27838
+ "bento.viewName",
27839
+ `[tRPC]: authored bento.viewName "${authoredViewName}" \u2192 got "${definition.bentoViewName}"`
27840
+ );
27841
+ }
27842
+ if (pkg.bentoViewName !== authoredViewName) {
27843
+ add(
27844
+ "bento-viewname-parity",
27845
+ "bento.viewName",
27846
+ `[CP]: authored bento.viewName "${authoredViewName}" \u2192 got "${pkg.bentoViewName}"`
27847
+ );
27848
+ }
27849
+ }
27850
+ const authored = tpl.integrations ?? [];
27851
+ const wsCaps = definition.capabilities ?? [];
27852
+ const pkgCaps = pkg.capabilities ?? [];
27853
+ if (wsCaps.length !== authored.length) {
27854
+ add(
27855
+ "capabilities-count",
27856
+ "integrations",
27857
+ `[tRPC]: authored ${authored.length} integration(s) \u2192 got ${wsCaps.length} capabilities`
27858
+ );
27859
+ }
27860
+ if (JSON.stringify(wsCaps) !== JSON.stringify(pkgCaps)) {
27861
+ add(
27862
+ "capabilities-parity",
27863
+ "integrations",
27864
+ `capability parity mismatch \u2014 tRPC door and CP door emit different capabilities`
27865
+ );
27866
+ }
27867
+ }
27868
+ return { ok: errors.length === 0, errors };
27869
+ }
27870
+
27013
27871
  // src/define.ts
27014
27872
  function toAutomationWire(automations) {
27015
27873
  return automations?.map((a) => ({
@@ -27134,6 +27992,7 @@ function toPackageDefinition(slugOrYaml) {
27134
27992
  slug: tpl.meta.slug,
27135
27993
  icon: tpl.meta.icon,
27136
27994
  color: tpl.meta.color,
27995
+ domain: tpl.meta.domain,
27137
27996
  tags: tpl.meta.tags,
27138
27997
  isPublic: tpl.meta.isPublic ?? true
27139
27998
  },
@@ -27165,13 +28024,27 @@ function toPackageDefinition(slugOrYaml) {
27165
28024
  };
27166
28025
  }
27167
28026
  export {
28027
+ DECLARED_DIVERGENCES,
28028
+ OTHER_DOMAIN_ID,
28029
+ OTHER_DOMAIN_LABEL,
27168
28030
  PACKAGE_DEPENDENCY_KINDS,
28031
+ REQUIRED_META_FIELDS,
28032
+ REQUIRED_WORKSPACE_FIELDS,
28033
+ SYSTEM_PROFILES,
28034
+ TEMPLATE_DOMAINS,
27169
28035
  WORKSPACE_TEMPLATES,
27170
28036
  assembleCatalog,
27171
28037
  bundledEdgesOf,
28038
+ collectBaseProfileSlugs,
27172
28039
  computeTemplateUpdates,
28040
+ conceptTerm,
28041
+ domainLabel,
28042
+ findConceptViolations,
28043
+ formatConceptViolations,
27173
28044
  getWorkspaceTemplate,
28045
+ groupByDomain,
27174
28046
  isHashVersion,
28047
+ isKnownDomain,
27175
28048
  layerTemplateGraph,
27176
28049
  listPublicTemplates,
27177
28050
  listWorkspaceTemplates,
@@ -27179,6 +28052,7 @@ export {
27179
28052
  rowToRemoteEntry,
27180
28053
  splitBentoBlocks,
27181
28054
  toPackageDefinition,
27182
- toWorkspaceDefinition
28055
+ toWorkspaceDefinition,
28056
+ validateTemplate
27183
28057
  };
27184
28058
  //# sourceMappingURL=index.js.map