@synap-core/workspace-templates 0.9.2 → 0.9.4
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.
- package/dist/index.d.ts +202 -31
- package/dist/index.js +782 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/business-developer.yaml +24 -6
- package/src/content-os.yaml +19 -0
- package/src/crm.yaml +94 -2
- package/src/define.primary-surface.test.ts +183 -0
- package/src/define.ts +142 -19
- package/src/index.ts +26 -3
- package/src/marketing.yaml +19 -0
- package/src/templates.ts +186 -8
- package/src/types.ts +111 -32
- package/src/validate-flow.drift.test.ts +83 -0
- package/src/validate-flow.ts +555 -0
- package/src/validate-onboarding.test.ts +88 -0
- package/src/validate.test.ts +121 -0
- package/src/validate.ts +247 -12
package/src/index.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* const template = getWorkspaceTemplate('brand-library');
|
|
12
12
|
* // template.workspace.name === 'Brand Library'
|
|
13
13
|
* // template.app.kind === 'native'
|
|
14
|
-
* // template.
|
|
14
|
+
* // template.app.appId === 'brandLibrary'
|
|
15
15
|
*
|
|
16
16
|
* YAML source files live in src/*.yaml — AI-friendly, commentable, mergeable.
|
|
17
17
|
* Run `pnpm build` to regenerate src/templates.ts from YAML.
|
|
@@ -22,6 +22,10 @@ export type {
|
|
|
22
22
|
TemplateMeta,
|
|
23
23
|
TemplateAppRef,
|
|
24
24
|
TemplateAppKind,
|
|
25
|
+
WorkspaceJsonValue,
|
|
26
|
+
WorkspacePrimarySurface,
|
|
27
|
+
WorkspacePrimarySurfaceViewReference,
|
|
28
|
+
TemplatePrimarySurface,
|
|
25
29
|
TemplateProfile,
|
|
26
30
|
TemplateProperty,
|
|
27
31
|
TemplateView,
|
|
@@ -86,8 +90,7 @@ export type {
|
|
|
86
90
|
} from "./catalog.js";
|
|
87
91
|
|
|
88
92
|
export {
|
|
89
|
-
layerTemplateGraph,
|
|
90
|
-
bundledEdgesOf,
|
|
93
|
+
layerTemplateGraph, bundledEdgesOf
|
|
91
94
|
} from "./composition-graph.js";
|
|
92
95
|
export type {
|
|
93
96
|
CompositionInstalledEntry,
|
|
@@ -138,10 +141,30 @@ export type {
|
|
|
138
141
|
TemplateConverters,
|
|
139
142
|
} from "./validate.js";
|
|
140
143
|
|
|
144
|
+
// The pure, DB-free automation-flow node-contract validator. `validateTemplate`
|
|
145
|
+
// runs it over every `automations[].flow` so broken flows (unknown node type,
|
|
146
|
+
// dangling edge, cycle, typo'd channelType, verb-less capability node) fail at
|
|
147
|
+
// author time instead of silently never firing on a live pod. Exported so the
|
|
148
|
+
// pod's persist doors + the (post-publish) backend re-export share this SSOT.
|
|
149
|
+
|
|
150
|
+
export {
|
|
151
|
+
validateFlowDefinition,
|
|
152
|
+
flowValidationErrorMessage,
|
|
153
|
+
FLOW_NODE_TYPES,
|
|
154
|
+
FLOW_OUTPUT_TYPES,
|
|
155
|
+
CHANNEL_MESSAGE_CHANNEL_TYPES,
|
|
156
|
+
} from "./validate-flow.js";
|
|
157
|
+
export type {
|
|
158
|
+
FlowValidationError,
|
|
159
|
+
FlowValidationResult,
|
|
160
|
+
FlowValidationResolvers,
|
|
161
|
+
} from "./validate-flow.js";
|
|
162
|
+
|
|
141
163
|
export {
|
|
142
164
|
toWorkspaceDefinition,
|
|
143
165
|
toPackageDefinition,
|
|
144
166
|
splitBentoBlocks,
|
|
167
|
+
normalizeTemplateLayout,
|
|
145
168
|
} from "./define.js";
|
|
146
169
|
export type {
|
|
147
170
|
WorkspaceDefinitionInput,
|
package/src/marketing.yaml
CHANGED
|
@@ -92,6 +92,25 @@ profiles:
|
|
|
92
92
|
label: Notes
|
|
93
93
|
valueType: string
|
|
94
94
|
inputType: textarea
|
|
95
|
+
# `campaign-type` is the campaign's NATURE/phase, orthogonal to
|
|
96
|
+
# `campaign-channel` (the delivery medium). scoping/outreach/live have no
|
|
97
|
+
# channel equivalent, so folding them into `campaign-channel` would lose
|
|
98
|
+
# them — they get their own def. Kept verbatim across the three campaign
|
|
99
|
+
# declarations (business-developer / content-os / here) so there is no drift.
|
|
100
|
+
- slug: campaign-type
|
|
101
|
+
label: Type
|
|
102
|
+
valueType: string
|
|
103
|
+
inputType: select
|
|
104
|
+
enumValues:
|
|
105
|
+
[scoping, outreach, live, partnership, event, other]
|
|
106
|
+
constraints: { defaultValue: outreach }
|
|
107
|
+
# `campaign-color` backs the per-campaign colour the CRM surfaces render.
|
|
108
|
+
# Stored as a palette NAME (see apps/crm/lib/campaignColors.ts), not a hex.
|
|
109
|
+
- slug: campaign-color
|
|
110
|
+
label: Color
|
|
111
|
+
valueType: string
|
|
112
|
+
inputType: select
|
|
113
|
+
enumValues: [indigo, violet, amber, cyan, pink, teal]
|
|
95
114
|
|
|
96
115
|
- slug: contact
|
|
97
116
|
displayName: Contact
|
package/src/templates.ts
CHANGED
|
@@ -6833,14 +6833,13 @@ const DATA = {
|
|
|
6833
6833
|
"valueType": "string",
|
|
6834
6834
|
"inputType": "select",
|
|
6835
6835
|
"enumValues": [
|
|
6836
|
-
"
|
|
6837
|
-
"referral",
|
|
6836
|
+
"cold-outreach",
|
|
6838
6837
|
"linkedin",
|
|
6839
|
-
"
|
|
6838
|
+
"twitter",
|
|
6839
|
+
"landing-page",
|
|
6840
|
+
"inbound-call",
|
|
6841
|
+
"referral",
|
|
6840
6842
|
"event",
|
|
6841
|
-
"inbound",
|
|
6842
|
-
"partner",
|
|
6843
|
-
"import",
|
|
6844
6843
|
"other"
|
|
6845
6844
|
]
|
|
6846
6845
|
},
|
|
@@ -7210,6 +7209,37 @@ const DATA = {
|
|
|
7210
7209
|
"label": "Notes",
|
|
7211
7210
|
"valueType": "string",
|
|
7212
7211
|
"inputType": "textarea"
|
|
7212
|
+
},
|
|
7213
|
+
{
|
|
7214
|
+
"slug": "campaign-type",
|
|
7215
|
+
"label": "Type",
|
|
7216
|
+
"valueType": "string",
|
|
7217
|
+
"inputType": "select",
|
|
7218
|
+
"enumValues": [
|
|
7219
|
+
"scoping",
|
|
7220
|
+
"outreach",
|
|
7221
|
+
"live",
|
|
7222
|
+
"partnership",
|
|
7223
|
+
"event",
|
|
7224
|
+
"other"
|
|
7225
|
+
],
|
|
7226
|
+
"constraints": {
|
|
7227
|
+
"defaultValue": "outreach"
|
|
7228
|
+
}
|
|
7229
|
+
},
|
|
7230
|
+
{
|
|
7231
|
+
"slug": "campaign-color",
|
|
7232
|
+
"label": "Color",
|
|
7233
|
+
"valueType": "string",
|
|
7234
|
+
"inputType": "select",
|
|
7235
|
+
"enumValues": [
|
|
7236
|
+
"indigo",
|
|
7237
|
+
"violet",
|
|
7238
|
+
"amber",
|
|
7239
|
+
"cyan",
|
|
7240
|
+
"pink",
|
|
7241
|
+
"teal"
|
|
7242
|
+
]
|
|
7213
7243
|
}
|
|
7214
7244
|
]
|
|
7215
7245
|
}
|
|
@@ -8909,6 +8939,37 @@ const DATA = {
|
|
|
8909
8939
|
"label": "Notes",
|
|
8910
8940
|
"valueType": "string",
|
|
8911
8941
|
"inputType": "textarea"
|
|
8942
|
+
},
|
|
8943
|
+
{
|
|
8944
|
+
"slug": "campaign-type",
|
|
8945
|
+
"label": "Type",
|
|
8946
|
+
"valueType": "string",
|
|
8947
|
+
"inputType": "select",
|
|
8948
|
+
"enumValues": [
|
|
8949
|
+
"scoping",
|
|
8950
|
+
"outreach",
|
|
8951
|
+
"live",
|
|
8952
|
+
"partnership",
|
|
8953
|
+
"event",
|
|
8954
|
+
"other"
|
|
8955
|
+
],
|
|
8956
|
+
"constraints": {
|
|
8957
|
+
"defaultValue": "outreach"
|
|
8958
|
+
}
|
|
8959
|
+
},
|
|
8960
|
+
{
|
|
8961
|
+
"slug": "campaign-color",
|
|
8962
|
+
"label": "Color",
|
|
8963
|
+
"valueType": "string",
|
|
8964
|
+
"inputType": "select",
|
|
8965
|
+
"enumValues": [
|
|
8966
|
+
"indigo",
|
|
8967
|
+
"violet",
|
|
8968
|
+
"amber",
|
|
8969
|
+
"cyan",
|
|
8970
|
+
"pink",
|
|
8971
|
+
"teal"
|
|
8972
|
+
]
|
|
8912
8973
|
}
|
|
8913
8974
|
]
|
|
8914
8975
|
},
|
|
@@ -10009,6 +10070,12 @@ const DATA = {
|
|
|
10009
10070
|
],
|
|
10010
10071
|
"isPublic": true
|
|
10011
10072
|
},
|
|
10073
|
+
"app": {
|
|
10074
|
+
"kind": "url",
|
|
10075
|
+
"appId": "crm",
|
|
10076
|
+
"url": "https://crm.synap.live",
|
|
10077
|
+
"title": "CRM"
|
|
10078
|
+
},
|
|
10012
10079
|
"dependencies": [
|
|
10013
10080
|
{
|
|
10014
10081
|
"slug": "foundation",
|
|
@@ -10079,7 +10146,17 @@ const DATA = {
|
|
|
10079
10146
|
"slug": "source",
|
|
10080
10147
|
"label": "Source",
|
|
10081
10148
|
"valueType": "string",
|
|
10082
|
-
"inputType": "
|
|
10149
|
+
"inputType": "select",
|
|
10150
|
+
"enumValues": [
|
|
10151
|
+
"cold-outreach",
|
|
10152
|
+
"linkedin",
|
|
10153
|
+
"twitter",
|
|
10154
|
+
"landing-page",
|
|
10155
|
+
"inbound-call",
|
|
10156
|
+
"referral",
|
|
10157
|
+
"event",
|
|
10158
|
+
"other"
|
|
10159
|
+
]
|
|
10083
10160
|
},
|
|
10084
10161
|
{
|
|
10085
10162
|
"slug": "icpScore",
|
|
@@ -10168,7 +10245,17 @@ const DATA = {
|
|
|
10168
10245
|
"slug": "source",
|
|
10169
10246
|
"label": "Source",
|
|
10170
10247
|
"valueType": "string",
|
|
10171
|
-
"inputType": "
|
|
10248
|
+
"inputType": "select",
|
|
10249
|
+
"enumValues": [
|
|
10250
|
+
"cold-outreach",
|
|
10251
|
+
"linkedin",
|
|
10252
|
+
"twitter",
|
|
10253
|
+
"landing-page",
|
|
10254
|
+
"inbound-call",
|
|
10255
|
+
"referral",
|
|
10256
|
+
"event",
|
|
10257
|
+
"other"
|
|
10258
|
+
]
|
|
10172
10259
|
},
|
|
10173
10260
|
{
|
|
10174
10261
|
"slug": "icpScore",
|
|
@@ -10556,6 +10643,66 @@ const DATA = {
|
|
|
10556
10643
|
"type": "linked_to_deal"
|
|
10557
10644
|
}
|
|
10558
10645
|
],
|
|
10646
|
+
"onboarding": {
|
|
10647
|
+
"goal": "Turn the user's real commercial motion into a usable pipeline — the right companies and people, their active opportunities, and an explicit next step for every deal — so CRM becomes the place sales work moves forward.\n",
|
|
10648
|
+
"framing": "THE REVENUE OPERATOR: Act as a pragmatic sales lead setting up a CRM people will actually maintain. Start from the user's existing motion, vocabulary, and active conversations. Resolve before creating so imported or Pod-wide people are reused rather than duplicated. Push for a concrete next step and date; never invent revenue, probability, or contact details.\n",
|
|
10649
|
+
"expertise": {
|
|
10650
|
+
"starters": [
|
|
10651
|
+
"A useful first pipeline is deliberately small. Start with the few stages that change how the team acts — contacted, qualifying, proposal, negotiating, won, and lost — and keep the template's default stages unless the user's real process needs a different view.\n",
|
|
10652
|
+
"Populate the workspace with live work, not a perfect historical archive: propose the three to five opportunities the user is actively trying to move, then add the companies and people needed to understand those deals.\n",
|
|
10653
|
+
"Every active deal needs one observable next step with a date. If the next step is \"follow up\" or \"keep warm\", help turn it into a specific action such as \"send the revised proposal Thursday\" before capturing it.\n"
|
|
10654
|
+
],
|
|
10655
|
+
"blindSpots": [
|
|
10656
|
+
"A deal without a real person is usually an account-shaped hope. If an opportunity has no stakeholder, surface the gap instead of fabricating a placeholder contact.\n",
|
|
10657
|
+
"Pipelines become fiction when stages describe confidence rather than an event the buyer completed. Ask what evidence moves a deal into its current stage, especially around proposal and negotiation.\n",
|
|
10658
|
+
"More fields do not create better sales hygiene. Prioritize stage, value when known, expected close date, and next step; leave unverifiable fields empty and offer enrichment separately.\n"
|
|
10659
|
+
],
|
|
10660
|
+
"bar": "A sales lead can open the pipeline and immediately see the few live opportunities, the real company and stakeholder behind each one, its evidence-based stage, and the dated next action — with no duplicate people and no invented commercial data.\n"
|
|
10661
|
+
},
|
|
10662
|
+
"collect": [
|
|
10663
|
+
{
|
|
10664
|
+
"profileSlug": "company",
|
|
10665
|
+
"what": "The real prospect organisations behind current conversations.",
|
|
10666
|
+
"cardinality": "few",
|
|
10667
|
+
"keyFields": [
|
|
10668
|
+
"website",
|
|
10669
|
+
"industry",
|
|
10670
|
+
"companySize",
|
|
10671
|
+
"source",
|
|
10672
|
+
"nextStep"
|
|
10673
|
+
]
|
|
10674
|
+
},
|
|
10675
|
+
{
|
|
10676
|
+
"profileSlug": "person",
|
|
10677
|
+
"what": "The known stakeholders for those organisations and opportunities.",
|
|
10678
|
+
"cardinality": "few",
|
|
10679
|
+
"keyFields": [
|
|
10680
|
+
"email",
|
|
10681
|
+
"jobTitle",
|
|
10682
|
+
"company",
|
|
10683
|
+
"source",
|
|
10684
|
+
"nextFollowUpDate"
|
|
10685
|
+
]
|
|
10686
|
+
},
|
|
10687
|
+
{
|
|
10688
|
+
"profileSlug": "deal",
|
|
10689
|
+
"what": "The live opportunities worth actively moving through the pipeline.",
|
|
10690
|
+
"cardinality": "few",
|
|
10691
|
+
"keyFields": [
|
|
10692
|
+
"dealStage",
|
|
10693
|
+
"value",
|
|
10694
|
+
"closeDate",
|
|
10695
|
+
"nextStep"
|
|
10696
|
+
]
|
|
10697
|
+
}
|
|
10698
|
+
],
|
|
10699
|
+
"openingQuestions": [
|
|
10700
|
+
"Which three to five opportunities are you actively trying to move right now?",
|
|
10701
|
+
"For the most important one, which company and real stakeholder are involved?",
|
|
10702
|
+
"What has the buyer actually done so far, and what is the next dated action?"
|
|
10703
|
+
],
|
|
10704
|
+
"doneWhen": "At least one real opportunity is linked to its company or stakeholder and has an evidence-based stage plus a concrete next step; the user can see how to add or import the rest without duplicating existing people.\n"
|
|
10705
|
+
},
|
|
10559
10706
|
"playbooks": [
|
|
10560
10707
|
{
|
|
10561
10708
|
"name": "Enrich Lead/Company",
|
|
@@ -22004,6 +22151,37 @@ const DATA = {
|
|
|
22004
22151
|
"label": "Notes",
|
|
22005
22152
|
"valueType": "string",
|
|
22006
22153
|
"inputType": "textarea"
|
|
22154
|
+
},
|
|
22155
|
+
{
|
|
22156
|
+
"slug": "campaign-type",
|
|
22157
|
+
"label": "Type",
|
|
22158
|
+
"valueType": "string",
|
|
22159
|
+
"inputType": "select",
|
|
22160
|
+
"enumValues": [
|
|
22161
|
+
"scoping",
|
|
22162
|
+
"outreach",
|
|
22163
|
+
"live",
|
|
22164
|
+
"partnership",
|
|
22165
|
+
"event",
|
|
22166
|
+
"other"
|
|
22167
|
+
],
|
|
22168
|
+
"constraints": {
|
|
22169
|
+
"defaultValue": "outreach"
|
|
22170
|
+
}
|
|
22171
|
+
},
|
|
22172
|
+
{
|
|
22173
|
+
"slug": "campaign-color",
|
|
22174
|
+
"label": "Color",
|
|
22175
|
+
"valueType": "string",
|
|
22176
|
+
"inputType": "select",
|
|
22177
|
+
"enumValues": [
|
|
22178
|
+
"indigo",
|
|
22179
|
+
"violet",
|
|
22180
|
+
"amber",
|
|
22181
|
+
"cyan",
|
|
22182
|
+
"pink",
|
|
22183
|
+
"teal"
|
|
22184
|
+
]
|
|
22007
22185
|
}
|
|
22008
22186
|
]
|
|
22009
22187
|
},
|
package/src/types.ts
CHANGED
|
@@ -10,24 +10,97 @@
|
|
|
10
10
|
// App Reference — what opens as first screen when entering this workspace
|
|
11
11
|
// ============================================================================
|
|
12
12
|
|
|
13
|
-
export type TemplateAppKind =
|
|
13
|
+
export type TemplateAppKind = "native" | "stored" | "url";
|
|
14
14
|
|
|
15
15
|
export interface TemplateAppRef {
|
|
16
16
|
kind: TemplateAppKind;
|
|
17
17
|
/** For kind='native': the appId registered in the browser manifest */
|
|
18
18
|
appId?: string;
|
|
19
19
|
/** For kind='native': how the platform renders the app */
|
|
20
|
-
rendererType?:
|
|
20
|
+
rendererType?: "native" | "external" | "iframe-srcdoc";
|
|
21
21
|
/** For kind='stored': the cell key registered in the cell registry */
|
|
22
22
|
cellKey?: string;
|
|
23
23
|
/** For kind='stored': default props passed to the cell */
|
|
24
|
-
props?: Record<string,
|
|
24
|
+
props?: Record<string, WorkspaceJsonValue>;
|
|
25
25
|
/** For kind='url': external URL to open */
|
|
26
26
|
url?: string;
|
|
27
27
|
/** Human label */
|
|
28
28
|
title?: string;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Workspace primary surface — JSON-safe persisted subset of SurfaceDescriptor
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
export type WorkspaceJsonValue =
|
|
36
|
+
| string
|
|
37
|
+
| number
|
|
38
|
+
| boolean
|
|
39
|
+
| null
|
|
40
|
+
| WorkspaceJsonValue[]
|
|
41
|
+
| { [key: string]: WorkspaceJsonValue };
|
|
42
|
+
|
|
43
|
+
export type WorkspacePrimarySurface =
|
|
44
|
+
| {
|
|
45
|
+
kind: "app";
|
|
46
|
+
appId: string;
|
|
47
|
+
rendererType: "native";
|
|
48
|
+
title?: string;
|
|
49
|
+
props?: Record<string, WorkspaceJsonValue>;
|
|
50
|
+
}
|
|
51
|
+
| {
|
|
52
|
+
kind: "app";
|
|
53
|
+
appId: string;
|
|
54
|
+
rendererType: "external";
|
|
55
|
+
url: string;
|
|
56
|
+
title?: string;
|
|
57
|
+
props?: Record<string, WorkspaceJsonValue>;
|
|
58
|
+
}
|
|
59
|
+
| {
|
|
60
|
+
kind: "cell";
|
|
61
|
+
cellKey: string;
|
|
62
|
+
title?: string;
|
|
63
|
+
props?: Record<string, WorkspaceJsonValue>;
|
|
64
|
+
}
|
|
65
|
+
| {
|
|
66
|
+
/**
|
|
67
|
+
* Ordinary website. Unlike an external `app`, this has no trusted app
|
|
68
|
+
* identity and is always opened through the Browser's unprivileged URL
|
|
69
|
+
* surface.
|
|
70
|
+
*/
|
|
71
|
+
kind: "url";
|
|
72
|
+
url: string;
|
|
73
|
+
title?: string;
|
|
74
|
+
}
|
|
75
|
+
| {
|
|
76
|
+
kind: "view";
|
|
77
|
+
viewId: string;
|
|
78
|
+
title?: string;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Authoring-time view reference. View IDs do not exist until provisioning, so
|
|
83
|
+
* templates and packages address a view by its stable authored name and/or
|
|
84
|
+
* slug. The pod resolves this to `WorkspacePrimarySurface` before persistence.
|
|
85
|
+
*/
|
|
86
|
+
export type WorkspacePrimarySurfaceViewReference =
|
|
87
|
+
| {
|
|
88
|
+
kind: "view";
|
|
89
|
+
viewName: string;
|
|
90
|
+
viewSlug?: string;
|
|
91
|
+
title?: string;
|
|
92
|
+
}
|
|
93
|
+
| {
|
|
94
|
+
kind: "view";
|
|
95
|
+
viewName?: string;
|
|
96
|
+
viewSlug: string;
|
|
97
|
+
title?: string;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export type TemplatePrimarySurface =
|
|
101
|
+
| WorkspacePrimarySurface
|
|
102
|
+
| WorkspacePrimarySurfaceViewReference;
|
|
103
|
+
|
|
31
104
|
// ============================================================================
|
|
32
105
|
// Property / Profile / View (mirrors WorkspaceProposal from onboarding)
|
|
33
106
|
// ============================================================================
|
|
@@ -53,8 +126,7 @@ export interface TemplateProfile {
|
|
|
53
126
|
* Visibility of the profile DEFINITION — who can USE this vocabulary.
|
|
54
127
|
* `system` = pod-wide; `shared` = ONE row reachable from other workspaces via
|
|
55
128
|
* a `profile_workspace_access` grant; omit or `workspace` = this workspace
|
|
56
|
-
* only. Orthogonal to `entityScope` below — do not conflate the two axes.
|
|
57
|
-
*/
|
|
129
|
+
* only. Orthogonal to `entityScope` below — do not conflate the two axes. */
|
|
58
130
|
scope?: string;
|
|
59
131
|
/**
|
|
60
132
|
* Placement of the profile's ENTITY ROWS — where the data LANDS.
|
|
@@ -72,7 +144,7 @@ export interface TemplateProfile {
|
|
|
72
144
|
* `entity_scope` of an existing profile (a divergence is reported as an
|
|
73
145
|
* advisory `scopeConflict` and the live row is left alone).
|
|
74
146
|
*/
|
|
75
|
-
entityScope?:
|
|
147
|
+
entityScope?: "pod" | "workspace";
|
|
76
148
|
/** Semantic slug for system profiles. */
|
|
77
149
|
semanticSlug?: string;
|
|
78
150
|
/** Kind vs role profile. Omit for default ('kind'). */
|
|
@@ -139,22 +211,22 @@ export interface TemplateDisplayTemplate {
|
|
|
139
211
|
// ============================================================================
|
|
140
212
|
|
|
141
213
|
export interface TemplateSidebarSurface {
|
|
142
|
-
kind:
|
|
214
|
+
kind: "cell" | "view" | "entity" | "document" | "channel" | "app" | "url";
|
|
143
215
|
cellKey?: string;
|
|
144
216
|
viewId?: string;
|
|
145
217
|
viewName?: string;
|
|
146
218
|
appId?: string;
|
|
147
219
|
url?: string;
|
|
148
|
-
rendererType?:
|
|
149
|
-
placement?:
|
|
150
|
-
displayMode?:
|
|
220
|
+
rendererType?: "native" | "external" | "iframe-srcdoc";
|
|
221
|
+
placement?: "main" | "side" | "floating" | "modal" | "popover" | "embed";
|
|
222
|
+
displayMode?: "compact" | "medium" | "full";
|
|
151
223
|
props?: Record<string, unknown>;
|
|
152
224
|
title?: string;
|
|
153
225
|
meta?: Record<string, unknown>;
|
|
154
226
|
}
|
|
155
227
|
|
|
156
228
|
export interface TemplateSidebarItem {
|
|
157
|
-
kind:
|
|
229
|
+
kind: "app" | "view" | "profile" | "external" | "cell";
|
|
158
230
|
appId?: string;
|
|
159
231
|
viewName?: string;
|
|
160
232
|
viewId?: string;
|
|
@@ -173,7 +245,14 @@ export interface TemplateSidebarItem {
|
|
|
173
245
|
export interface TemplateLayoutConfig {
|
|
174
246
|
pinnedApps?: string[];
|
|
175
247
|
defaultView?: string;
|
|
176
|
-
/**
|
|
248
|
+
/**
|
|
249
|
+
* Canonical first screen for this workspace.
|
|
250
|
+
*
|
|
251
|
+
* `undefined` means the template has no opinion during reconciliation,
|
|
252
|
+
* `null` explicitly returns the workspace to its home surface, and a
|
|
253
|
+
* descriptor replaces the current primary surface. */
|
|
254
|
+
primarySurface?: TemplatePrimarySurface | null;
|
|
255
|
+
/** Compatibility input only. New templates should use `app:` or `primarySurface`. */
|
|
177
256
|
defaultApp?: string | null;
|
|
178
257
|
theme?: string;
|
|
179
258
|
sidebarItems?: TemplateSidebarItem[];
|
|
@@ -184,7 +263,7 @@ export interface TemplateLayoutConfig {
|
|
|
184
263
|
// ============================================================================
|
|
185
264
|
|
|
186
265
|
export interface TemplateBentoBlock {
|
|
187
|
-
kind:
|
|
266
|
+
kind: "view" | "widget";
|
|
188
267
|
viewName?: string;
|
|
189
268
|
widgetType?: string;
|
|
190
269
|
pos: { x: number; y: number; w: number; h: number };
|
|
@@ -203,7 +282,7 @@ export interface TemplateProfileEntityBentoTemplates {
|
|
|
203
282
|
// ============================================================================
|
|
204
283
|
|
|
205
284
|
/** Mirrors `WorkspaceSourceRole` in synap-backend `schema/workspaces.ts`. */
|
|
206
|
-
export type TemplateSourceRole =
|
|
285
|
+
export type TemplateSourceRole = "provider" | "consumer" | "provider-consumer";
|
|
207
286
|
|
|
208
287
|
/** Mirrors `WorkspaceDefaultSource` in synap-backend `schema/workspaces.ts`. */
|
|
209
288
|
export interface TemplateDefaultSource {
|
|
@@ -233,7 +312,7 @@ export interface TemplateOnboardingCollectTarget {
|
|
|
233
312
|
/** Human description of what to capture for this target. */
|
|
234
313
|
what: string;
|
|
235
314
|
/** Roughly how many to expect — guides interview depth. */
|
|
236
|
-
cardinality?:
|
|
315
|
+
cardinality?: "one" | "few" | "several";
|
|
237
316
|
/** Key fields the agent should make sure to fill. */
|
|
238
317
|
keyFields?: string[];
|
|
239
318
|
}
|
|
@@ -288,7 +367,7 @@ export interface TemplateOnboarding {
|
|
|
288
367
|
|
|
289
368
|
export interface TemplatePlaybookParam {
|
|
290
369
|
name: string;
|
|
291
|
-
type:
|
|
370
|
+
type: "text" | "number" | "entity" | "choice" | "boolean";
|
|
292
371
|
label?: string;
|
|
293
372
|
required?: boolean;
|
|
294
373
|
defaultValue?: unknown;
|
|
@@ -299,12 +378,12 @@ export interface TemplatePlaybook {
|
|
|
299
378
|
description?: string;
|
|
300
379
|
goalTemplate: string;
|
|
301
380
|
params?: TemplatePlaybookParam[];
|
|
302
|
-
executor?:
|
|
303
|
-
inputStrategy?:
|
|
381
|
+
executor?: "is-agent" | "external-agent" | "hybrid";
|
|
382
|
+
inputStrategy?: "none" | "static" | "rotating" | "query";
|
|
304
383
|
channelSpec?: {
|
|
305
|
-
type:
|
|
384
|
+
type: "GROUP" | "AGENT_COLLAB" | "THREAD";
|
|
306
385
|
members?: string[];
|
|
307
|
-
aiReactionMode?:
|
|
386
|
+
aiReactionMode?: "on_mention" | "always" | "never";
|
|
308
387
|
};
|
|
309
388
|
/**
|
|
310
389
|
* A cron schedule that maintains ONE backing cron automation (a single
|
|
@@ -330,7 +409,7 @@ export interface TemplatePlaybook {
|
|
|
330
409
|
* captured entity of this kind can auto-launch the playbook as a session.
|
|
331
410
|
*/
|
|
332
411
|
subjectProfile?: { profileSlug: string; filter?: Record<string, unknown> };
|
|
333
|
-
status?:
|
|
412
|
+
status?: "draft" | "active" | "paused";
|
|
334
413
|
}
|
|
335
414
|
|
|
336
415
|
// ============================================================================
|
|
@@ -360,10 +439,10 @@ export interface TemplateAutomation {
|
|
|
360
439
|
key?: string;
|
|
361
440
|
name: string;
|
|
362
441
|
description?: string;
|
|
363
|
-
triggerType:
|
|
442
|
+
triggerType: "event" | "cron" | "webhook" | "manual";
|
|
364
443
|
triggerConfig?: Record<string, unknown>;
|
|
365
444
|
flow: { nodes: unknown[]; edges: unknown[]; precondition?: string };
|
|
366
|
-
status?:
|
|
445
|
+
status?: "draft" | "active" | "paused";
|
|
367
446
|
}
|
|
368
447
|
|
|
369
448
|
// ============================================================================
|
|
@@ -395,9 +474,9 @@ export interface TemplateActionPlacement {
|
|
|
395
474
|
/** Entity kind whose detail surface this action appears on. */
|
|
396
475
|
profileSlug: string;
|
|
397
476
|
/** Where the action renders. Only "entity-detail" is consumed today. */
|
|
398
|
-
surface:
|
|
477
|
+
surface: "entity-detail" | string;
|
|
399
478
|
/** What the action does when clicked. */
|
|
400
|
-
kind:
|
|
479
|
+
kind: "capability" | "playbook" | "automation";
|
|
401
480
|
/**
|
|
402
481
|
* Reference to the thing to run: a capability verb key, or a playbook /
|
|
403
482
|
* automation NAME (resolved to a row id at apply time).
|
|
@@ -440,7 +519,7 @@ export interface TemplateIntegration {
|
|
|
440
519
|
/** Override default params with {{var}} interpolation. */
|
|
441
520
|
params?: Record<string, string>;
|
|
442
521
|
/** "apply" (create+update) or "install" (create only). */
|
|
443
|
-
mode?:
|
|
522
|
+
mode?: "apply" | "install";
|
|
444
523
|
}
|
|
445
524
|
|
|
446
525
|
// ============================================================================
|
|
@@ -514,10 +593,10 @@ export interface TemplateExtendsRef {
|
|
|
514
593
|
* 3. Once no payload carries `'automation'`, drop it from the wire enums and this tuple.
|
|
515
594
|
*/
|
|
516
595
|
export const PACKAGE_DEPENDENCY_KINDS = [
|
|
517
|
-
|
|
518
|
-
|
|
596
|
+
"workspace",
|
|
597
|
+
"capability",
|
|
519
598
|
/** @deprecated Retired by CP 0049 in favour of `workflow`. See note above. */
|
|
520
|
-
|
|
599
|
+
"automation",
|
|
521
600
|
] as const;
|
|
522
601
|
|
|
523
602
|
/** What a `TemplateDependency` points at. Derived — never re-declare the list. */
|
|
@@ -541,7 +620,7 @@ export interface TemplateDependency {
|
|
|
541
620
|
* - `'require'` (default): the dependency must be present on the pod as its
|
|
542
621
|
* own artifact, but this template does not merge into it.
|
|
543
622
|
*/
|
|
544
|
-
relation?:
|
|
623
|
+
relation?: "compose" | "require";
|
|
545
624
|
/**
|
|
546
625
|
* Short human reason shown in the install-time "this also installs…" prompt.
|
|
547
626
|
*/
|
|
@@ -585,7 +664,7 @@ export interface WorkspaceYaml {
|
|
|
585
664
|
* Workspace classifier — consumed by createFromDefinition (settings.workspaceType,
|
|
586
665
|
* creator-role + agent-workspace behavior). Mirrors the backend union.
|
|
587
666
|
*/
|
|
588
|
-
workspaceType?:
|
|
667
|
+
workspaceType?: "personal" | "agent" | "project" | "operational";
|
|
589
668
|
visibility?: string;
|
|
590
669
|
/** Capabilities this workspace provides (e.g. "brand.library", "content.pipeline") */
|
|
591
670
|
capabilities?: string[];
|
|
@@ -682,7 +761,7 @@ export interface WorkspaceYaml {
|
|
|
682
761
|
|
|
683
762
|
export interface ResolvedWorkspaceTemplate {
|
|
684
763
|
meta: TemplateMeta;
|
|
685
|
-
definition: WorkspaceYaml[
|
|
764
|
+
definition: WorkspaceYaml["workspace"] & {
|
|
686
765
|
profiles: TemplateProfile[];
|
|
687
766
|
views: TemplateView[];
|
|
688
767
|
entityLinks: TemplateEntityLink[];
|