@contractspec/example.personalization 3.7.7 → 3.7.10
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/.turbo/turbo-build.log +36 -30
- package/CHANGELOG.md +28 -0
- package/README.md +7 -1
- package/dist/browser/index.js +127 -3
- package/dist/browser/personalization.experiment.js +62 -0
- package/dist/browser/personalization.theme.js +64 -0
- package/dist/contracts.test.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +127 -3
- package/dist/node/index.js +127 -3
- package/dist/node/personalization.experiment.js +62 -0
- package/dist/node/personalization.theme.js +64 -0
- package/dist/personalization.experiment.d.ts +2 -0
- package/dist/personalization.experiment.js +63 -0
- package/dist/personalization.theme.d.ts +2 -0
- package/dist/personalization.theme.js +65 -0
- package/package.json +36 -8
- package/src/contracts.test.ts +20 -0
- package/src/index.ts +2 -0
- package/src/personalization.experiment.ts +61 -0
- package/src/personalization.theme.ts +63 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -2,40 +2,46 @@ $ contractspec-bun-build prebuild
|
|
|
2
2
|
$ bun run prebuild && bun run build:bundle && bun run build:types
|
|
3
3
|
$ contractspec-bun-build prebuild
|
|
4
4
|
$ contractspec-bun-build transpile
|
|
5
|
-
[contractspec-bun-build] transpile target=bun root=src entries=
|
|
6
|
-
Bundled
|
|
5
|
+
[contractspec-bun-build] transpile target=bun root=src entries=10 noBundle=false
|
|
6
|
+
Bundled 10 modules in 10ms
|
|
7
7
|
|
|
8
|
-
./behavior-tracking.js
|
|
9
|
-
./index.js
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
./
|
|
15
|
-
./
|
|
8
|
+
./behavior-tracking.js 1.33 KB (entry point)
|
|
9
|
+
./index.js 10.57 KB (entry point)
|
|
10
|
+
./personalization.theme.js 1.35 KB (entry point)
|
|
11
|
+
./workflow-extension.js 1.59 KB (entry point)
|
|
12
|
+
docs/index.js 1.48 KB (entry point)
|
|
13
|
+
docs/personalization.docblock.js 1.48 KB (entry point)
|
|
14
|
+
./example.js 0.99 KB (entry point)
|
|
15
|
+
./overlay-customization.js 1.53 KB (entry point)
|
|
16
|
+
./personalization.experiment.js 1.60 KB (entry point)
|
|
17
|
+
./personalization.feature.js 0.71 KB (entry point)
|
|
16
18
|
|
|
17
|
-
[contractspec-bun-build] transpile target=node root=src entries=
|
|
18
|
-
Bundled
|
|
19
|
+
[contractspec-bun-build] transpile target=node root=src entries=10 noBundle=false
|
|
20
|
+
Bundled 10 modules in 4ms
|
|
19
21
|
|
|
20
|
-
./behavior-tracking.js
|
|
21
|
-
./index.js
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
./
|
|
27
|
-
./
|
|
22
|
+
./behavior-tracking.js 1.32 KB (entry point)
|
|
23
|
+
./index.js 10.56 KB (entry point)
|
|
24
|
+
./personalization.theme.js 1.34 KB (entry point)
|
|
25
|
+
./workflow-extension.js 1.58 KB (entry point)
|
|
26
|
+
docs/index.js 1.47 KB (entry point)
|
|
27
|
+
docs/personalization.docblock.js 1.47 KB (entry point)
|
|
28
|
+
./example.js 0.99 KB (entry point)
|
|
29
|
+
./overlay-customization.js 1.52 KB (entry point)
|
|
30
|
+
./personalization.experiment.js 1.60 KB (entry point)
|
|
31
|
+
./personalization.feature.js 0.70 KB (entry point)
|
|
28
32
|
|
|
29
|
-
[contractspec-bun-build] transpile target=browser root=src entries=
|
|
30
|
-
Bundled
|
|
33
|
+
[contractspec-bun-build] transpile target=browser root=src entries=10 noBundle=false
|
|
34
|
+
Bundled 10 modules in 3ms
|
|
31
35
|
|
|
32
|
-
./behavior-tracking.js
|
|
33
|
-
./index.js
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
./
|
|
39
|
-
./
|
|
36
|
+
./behavior-tracking.js 1.32 KB (entry point)
|
|
37
|
+
./index.js 10.56 KB (entry point)
|
|
38
|
+
./personalization.theme.js 1.34 KB (entry point)
|
|
39
|
+
./workflow-extension.js 1.58 KB (entry point)
|
|
40
|
+
docs/index.js 1.47 KB (entry point)
|
|
41
|
+
docs/personalization.docblock.js 1.47 KB (entry point)
|
|
42
|
+
./example.js 0.99 KB (entry point)
|
|
43
|
+
./overlay-customization.js 1.52 KB (entry point)
|
|
44
|
+
./personalization.experiment.js 1.60 KB (entry point)
|
|
45
|
+
./personalization.feature.js 0.70 KB (entry point)
|
|
40
46
|
|
|
41
47
|
$ contractspec-bun-build types
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @contractspec/example.personalization
|
|
2
2
|
|
|
3
|
+
## 3.7.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1a44cb6: feat: improve examples to increase coverage of Contracts type
|
|
8
|
+
- Updated dependencies [1a44cb6]
|
|
9
|
+
- @contractspec/lib.workflow-composer@3.7.10
|
|
10
|
+
- @contractspec/lib.personalization@6.0.10
|
|
11
|
+
- @contractspec/lib.contracts-spec@4.1.2
|
|
12
|
+
- @contractspec/lib.overlay-engine@3.7.10
|
|
13
|
+
- @contractspec/lib.logger@3.7.8
|
|
14
|
+
|
|
15
|
+
## 3.7.9
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- fix: release
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @contractspec/lib.workflow-composer@3.7.9
|
|
22
|
+
- @contractspec/lib.personalization@6.0.9
|
|
23
|
+
- @contractspec/lib.contracts-spec@4.1.1
|
|
24
|
+
- @contractspec/lib.overlay-engine@3.7.9
|
|
25
|
+
- @contractspec/lib.logger@3.7.7
|
|
26
|
+
|
|
3
27
|
## 3.7.6
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -483,6 +507,7 @@
|
|
|
483
507
|
- 7f3203a: fix: make workspace test runs resilient when packages have no tests
|
|
484
508
|
|
|
485
509
|
Updates package test scripts to pass cleanly when no matching test files exist:
|
|
510
|
+
|
|
486
511
|
- Uses `bun test --pass-with-no-tests` in Bun-based packages that currently ship without test files.
|
|
487
512
|
- Uses `jest --passWithNoTests` for the UI kit web package.
|
|
488
513
|
- Adds `.vscode-test.mjs` for `vscode-contractspec` so VS Code extension test runs have an explicit config and stop failing on missing default configuration.
|
|
@@ -901,14 +926,17 @@
|
|
|
901
926
|
feat: Contract layers support (features, examples, app-configs)
|
|
902
927
|
|
|
903
928
|
### New CLI Commands
|
|
929
|
+
|
|
904
930
|
- `contractspec list layers` - List all contract layers with filtering
|
|
905
931
|
|
|
906
932
|
### Enhanced Commands
|
|
933
|
+
|
|
907
934
|
- `contractspec ci` - New `layers` check category validates features/examples/config
|
|
908
935
|
- `contractspec doctor` - New `layers` health checks
|
|
909
936
|
- `contractspec integrity` - Now shows layer statistics
|
|
910
937
|
|
|
911
938
|
### New APIs
|
|
939
|
+
|
|
912
940
|
- `discoverLayers()` - Scan workspace for all layer files
|
|
913
941
|
- `scanExampleSource()` - Parse ExampleSpec from source code
|
|
914
942
|
- `isExampleFile()` - Check if file is an example spec
|
package/README.md
CHANGED
|
@@ -7,11 +7,12 @@ Website: https://contractspec.io
|
|
|
7
7
|
## What This Demonstrates
|
|
8
8
|
|
|
9
9
|
- Behavior tracking integration pattern.
|
|
10
|
+
- Canonical `experiment` export via `PersonalizationExperiment`.
|
|
10
11
|
- Overlay customization via overlay-engine.
|
|
12
|
+
- Canonical `theme` export via `PersonalizationTheme`.
|
|
11
13
|
- Workflow extension via workflow-composer.
|
|
12
14
|
- Multi-lib composition in a single example.
|
|
13
15
|
- `src/docs/` contains docblocks and documentation-facing exports.
|
|
14
|
-
- `src/docs/` contains docblocks and documentation-facing exports.
|
|
15
16
|
|
|
16
17
|
## Running Locally
|
|
17
18
|
|
|
@@ -32,7 +33,9 @@ Use `@contractspec/example.personalization` as a reference implementation, or im
|
|
|
32
33
|
- `src/example.ts` is the runnable example entrypoint.
|
|
33
34
|
- `src/index.ts` is the root public barrel and package entrypoint.
|
|
34
35
|
- `src/overlay-customization.ts` is part of the package's public or composition surface.
|
|
36
|
+
- `src/personalization.experiment.ts` defines the exported experiment spec.
|
|
35
37
|
- `src/personalization.feature.ts` defines a feature entrypoint.
|
|
38
|
+
- `src/personalization.theme.ts` defines the exported theme spec.
|
|
36
39
|
- `src/workflow-extension.ts` is part of the package's public or composition surface.
|
|
37
40
|
|
|
38
41
|
## Public Entry Points
|
|
@@ -43,8 +46,11 @@ Use `@contractspec/example.personalization` as a reference implementation, or im
|
|
|
43
46
|
- Export `./docs/personalization.docblock` resolves through `./src/docs/personalization.docblock.ts`.
|
|
44
47
|
- Export `./example` resolves through `./src/example.ts`.
|
|
45
48
|
- Export `./overlay-customization` resolves through `./src/overlay-customization.ts`.
|
|
49
|
+
- Export `./personalization.experiment` resolves through `./src/personalization.experiment.ts`.
|
|
46
50
|
- Export `./personalization.feature` resolves through `./src/personalization.feature.ts`.
|
|
51
|
+
- Export `./personalization.theme` resolves through `./src/personalization.theme.ts`.
|
|
47
52
|
- Export `./workflow-extension` resolves through `./src/workflow-extension.ts`.
|
|
53
|
+
- The package publishes 9 total export subpaths; keep docs aligned with `package.json`.
|
|
48
54
|
|
|
49
55
|
## Local Commands
|
|
50
56
|
|
package/dist/browser/index.js
CHANGED
|
@@ -162,6 +162,66 @@ async function runOverlayCustomizationExample() {
|
|
|
162
162
|
logger2.info("Overlay applied", { fields: result.target.fields });
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
// src/personalization.experiment.ts
|
|
166
|
+
import {
|
|
167
|
+
OwnersEnum,
|
|
168
|
+
StabilityEnum
|
|
169
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
170
|
+
var PersonalizationExperiment = {
|
|
171
|
+
meta: {
|
|
172
|
+
key: "personalization.experiment.overlay-copy",
|
|
173
|
+
version: "1.0.0",
|
|
174
|
+
title: "Personalization Overlay Copy Experiment",
|
|
175
|
+
description: "Tests a control onboarding copy against a personalized overlay variant.",
|
|
176
|
+
domain: "personalization",
|
|
177
|
+
owners: [OwnersEnum.PlatformCore],
|
|
178
|
+
tags: ["personalization", "experiment", "overlay"],
|
|
179
|
+
stability: StabilityEnum.Experimental
|
|
180
|
+
},
|
|
181
|
+
controlVariant: "control",
|
|
182
|
+
variants: [
|
|
183
|
+
{
|
|
184
|
+
id: "control",
|
|
185
|
+
key: "control",
|
|
186
|
+
description: "Default onboarding copy and standard workflow."
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: "personalized-overlay",
|
|
190
|
+
key: "personalized-overlay",
|
|
191
|
+
description: "Personalized copy with a branded theme override.",
|
|
192
|
+
overrides: [
|
|
193
|
+
{
|
|
194
|
+
type: "theme",
|
|
195
|
+
target: "personalization.theme.guided-onboarding",
|
|
196
|
+
version: "1.0.0"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: "workflow",
|
|
200
|
+
target: "billing.invoiceApproval",
|
|
201
|
+
version: "1.0.0"
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
allocation: {
|
|
207
|
+
type: "sticky",
|
|
208
|
+
attribute: "userId",
|
|
209
|
+
salt: "personalization-overlay-copy"
|
|
210
|
+
},
|
|
211
|
+
successMetrics: [
|
|
212
|
+
{
|
|
213
|
+
key: "checklist-completion-rate",
|
|
214
|
+
telemetryEvent: {
|
|
215
|
+
key: "personalization.assignment.completed",
|
|
216
|
+
version: "1.0.0"
|
|
217
|
+
},
|
|
218
|
+
aggregation: "count",
|
|
219
|
+
target: 1
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
tags: ["personalization", "experiment"]
|
|
223
|
+
};
|
|
224
|
+
|
|
165
225
|
// src/personalization.feature.ts
|
|
166
226
|
import { defineFeature } from "@contractspec/lib.contracts-spec";
|
|
167
227
|
var PersonalizationFeature = defineFeature({
|
|
@@ -182,8 +242,70 @@ var PersonalizationFeature = defineFeature({
|
|
|
182
242
|
]
|
|
183
243
|
});
|
|
184
244
|
|
|
245
|
+
// src/personalization.theme.ts
|
|
246
|
+
import {
|
|
247
|
+
OwnersEnum as OwnersEnum2,
|
|
248
|
+
StabilityEnum as StabilityEnum2
|
|
249
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
250
|
+
var PersonalizationTheme = {
|
|
251
|
+
meta: {
|
|
252
|
+
key: "personalization.theme.guided-onboarding",
|
|
253
|
+
version: "1.0.0",
|
|
254
|
+
title: "Guided Onboarding Theme",
|
|
255
|
+
description: "Theme tokens used when the personalized onboarding experience is active.",
|
|
256
|
+
domain: "personalization",
|
|
257
|
+
owners: [OwnersEnum2.PlatformCore],
|
|
258
|
+
tags: ["personalization", "theme", "onboarding"],
|
|
259
|
+
stability: StabilityEnum2.Experimental,
|
|
260
|
+
scopes: ["tenant", "user"]
|
|
261
|
+
},
|
|
262
|
+
tokens: {
|
|
263
|
+
colors: {
|
|
264
|
+
surface: { value: "#FCF6E8" },
|
|
265
|
+
accent: { value: "#C8742A" },
|
|
266
|
+
text: { value: "#2F2419" }
|
|
267
|
+
},
|
|
268
|
+
radii: {
|
|
269
|
+
card: { value: 18 }
|
|
270
|
+
},
|
|
271
|
+
space: {
|
|
272
|
+
panel: { value: 24 }
|
|
273
|
+
},
|
|
274
|
+
typography: {
|
|
275
|
+
body: { value: 16 },
|
|
276
|
+
title: { value: 28 }
|
|
277
|
+
},
|
|
278
|
+
motion: {
|
|
279
|
+
stagger: { value: "180ms" }
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
components: [
|
|
283
|
+
{
|
|
284
|
+
component: "OnboardingChecklist",
|
|
285
|
+
variants: {
|
|
286
|
+
guided: {
|
|
287
|
+
props: {
|
|
288
|
+
emphasis: "warm"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
overrides: [
|
|
295
|
+
{
|
|
296
|
+
scope: "tenant",
|
|
297
|
+
target: "tenant:acme",
|
|
298
|
+
tokens: {
|
|
299
|
+
colors: {
|
|
300
|
+
accent: { value: "#8A4B12" }
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
|
|
185
307
|
// src/workflow-extension.ts
|
|
186
|
-
import { StabilityEnum } from "@contractspec/lib.contracts-spec";
|
|
308
|
+
import { StabilityEnum as StabilityEnum3 } from "@contractspec/lib.contracts-spec";
|
|
187
309
|
import { Logger as Logger3, LogLevel as LogLevel3 } from "@contractspec/lib.logger";
|
|
188
310
|
import { WorkflowComposer } from "@contractspec/lib.workflow-composer";
|
|
189
311
|
var logger3 = new Logger3({
|
|
@@ -200,7 +322,7 @@ var BaseWorkflow = {
|
|
|
200
322
|
tags: [],
|
|
201
323
|
description: "",
|
|
202
324
|
domain: "billing",
|
|
203
|
-
stability:
|
|
325
|
+
stability: StabilityEnum3.Stable
|
|
204
326
|
},
|
|
205
327
|
definition: {
|
|
206
328
|
steps: [
|
|
@@ -244,5 +366,7 @@ export {
|
|
|
244
366
|
logTenantWorkflowSteps,
|
|
245
367
|
example_default as example,
|
|
246
368
|
composeTenantWorkflowExample,
|
|
247
|
-
|
|
369
|
+
PersonalizationTheme,
|
|
370
|
+
PersonalizationFeature,
|
|
371
|
+
PersonalizationExperiment
|
|
248
372
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/personalization.experiment.ts
|
|
2
|
+
import {
|
|
3
|
+
OwnersEnum,
|
|
4
|
+
StabilityEnum
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
6
|
+
var PersonalizationExperiment = {
|
|
7
|
+
meta: {
|
|
8
|
+
key: "personalization.experiment.overlay-copy",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
title: "Personalization Overlay Copy Experiment",
|
|
11
|
+
description: "Tests a control onboarding copy against a personalized overlay variant.",
|
|
12
|
+
domain: "personalization",
|
|
13
|
+
owners: [OwnersEnum.PlatformCore],
|
|
14
|
+
tags: ["personalization", "experiment", "overlay"],
|
|
15
|
+
stability: StabilityEnum.Experimental
|
|
16
|
+
},
|
|
17
|
+
controlVariant: "control",
|
|
18
|
+
variants: [
|
|
19
|
+
{
|
|
20
|
+
id: "control",
|
|
21
|
+
key: "control",
|
|
22
|
+
description: "Default onboarding copy and standard workflow."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "personalized-overlay",
|
|
26
|
+
key: "personalized-overlay",
|
|
27
|
+
description: "Personalized copy with a branded theme override.",
|
|
28
|
+
overrides: [
|
|
29
|
+
{
|
|
30
|
+
type: "theme",
|
|
31
|
+
target: "personalization.theme.guided-onboarding",
|
|
32
|
+
version: "1.0.0"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: "workflow",
|
|
36
|
+
target: "billing.invoiceApproval",
|
|
37
|
+
version: "1.0.0"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
allocation: {
|
|
43
|
+
type: "sticky",
|
|
44
|
+
attribute: "userId",
|
|
45
|
+
salt: "personalization-overlay-copy"
|
|
46
|
+
},
|
|
47
|
+
successMetrics: [
|
|
48
|
+
{
|
|
49
|
+
key: "checklist-completion-rate",
|
|
50
|
+
telemetryEvent: {
|
|
51
|
+
key: "personalization.assignment.completed",
|
|
52
|
+
version: "1.0.0"
|
|
53
|
+
},
|
|
54
|
+
aggregation: "count",
|
|
55
|
+
target: 1
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
tags: ["personalization", "experiment"]
|
|
59
|
+
};
|
|
60
|
+
export {
|
|
61
|
+
PersonalizationExperiment
|
|
62
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/personalization.theme.ts
|
|
2
|
+
import {
|
|
3
|
+
OwnersEnum,
|
|
4
|
+
StabilityEnum
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
6
|
+
var PersonalizationTheme = {
|
|
7
|
+
meta: {
|
|
8
|
+
key: "personalization.theme.guided-onboarding",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
title: "Guided Onboarding Theme",
|
|
11
|
+
description: "Theme tokens used when the personalized onboarding experience is active.",
|
|
12
|
+
domain: "personalization",
|
|
13
|
+
owners: [OwnersEnum.PlatformCore],
|
|
14
|
+
tags: ["personalization", "theme", "onboarding"],
|
|
15
|
+
stability: StabilityEnum.Experimental,
|
|
16
|
+
scopes: ["tenant", "user"]
|
|
17
|
+
},
|
|
18
|
+
tokens: {
|
|
19
|
+
colors: {
|
|
20
|
+
surface: { value: "#FCF6E8" },
|
|
21
|
+
accent: { value: "#C8742A" },
|
|
22
|
+
text: { value: "#2F2419" }
|
|
23
|
+
},
|
|
24
|
+
radii: {
|
|
25
|
+
card: { value: 18 }
|
|
26
|
+
},
|
|
27
|
+
space: {
|
|
28
|
+
panel: { value: 24 }
|
|
29
|
+
},
|
|
30
|
+
typography: {
|
|
31
|
+
body: { value: 16 },
|
|
32
|
+
title: { value: 28 }
|
|
33
|
+
},
|
|
34
|
+
motion: {
|
|
35
|
+
stagger: { value: "180ms" }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
components: [
|
|
39
|
+
{
|
|
40
|
+
component: "OnboardingChecklist",
|
|
41
|
+
variants: {
|
|
42
|
+
guided: {
|
|
43
|
+
props: {
|
|
44
|
+
emphasis: "warm"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
overrides: [
|
|
51
|
+
{
|
|
52
|
+
scope: "tenant",
|
|
53
|
+
target: "tenant:acme",
|
|
54
|
+
tokens: {
|
|
55
|
+
colors: {
|
|
56
|
+
accent: { value: "#8A4B12" }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
PersonalizationTheme
|
|
64
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './behavior-tracking';
|
|
2
2
|
export { default as example } from './example';
|
|
3
3
|
export * from './overlay-customization';
|
|
4
|
+
export * from './personalization.experiment';
|
|
4
5
|
export * from './personalization.feature';
|
|
6
|
+
export * from './personalization.theme';
|
|
5
7
|
export * from './workflow-extension';
|
|
6
8
|
import './docs';
|
package/dist/index.js
CHANGED
|
@@ -163,6 +163,66 @@ async function runOverlayCustomizationExample() {
|
|
|
163
163
|
logger2.info("Overlay applied", { fields: result.target.fields });
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
// src/personalization.experiment.ts
|
|
167
|
+
import {
|
|
168
|
+
OwnersEnum,
|
|
169
|
+
StabilityEnum
|
|
170
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
171
|
+
var PersonalizationExperiment = {
|
|
172
|
+
meta: {
|
|
173
|
+
key: "personalization.experiment.overlay-copy",
|
|
174
|
+
version: "1.0.0",
|
|
175
|
+
title: "Personalization Overlay Copy Experiment",
|
|
176
|
+
description: "Tests a control onboarding copy against a personalized overlay variant.",
|
|
177
|
+
domain: "personalization",
|
|
178
|
+
owners: [OwnersEnum.PlatformCore],
|
|
179
|
+
tags: ["personalization", "experiment", "overlay"],
|
|
180
|
+
stability: StabilityEnum.Experimental
|
|
181
|
+
},
|
|
182
|
+
controlVariant: "control",
|
|
183
|
+
variants: [
|
|
184
|
+
{
|
|
185
|
+
id: "control",
|
|
186
|
+
key: "control",
|
|
187
|
+
description: "Default onboarding copy and standard workflow."
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: "personalized-overlay",
|
|
191
|
+
key: "personalized-overlay",
|
|
192
|
+
description: "Personalized copy with a branded theme override.",
|
|
193
|
+
overrides: [
|
|
194
|
+
{
|
|
195
|
+
type: "theme",
|
|
196
|
+
target: "personalization.theme.guided-onboarding",
|
|
197
|
+
version: "1.0.0"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
type: "workflow",
|
|
201
|
+
target: "billing.invoiceApproval",
|
|
202
|
+
version: "1.0.0"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
],
|
|
207
|
+
allocation: {
|
|
208
|
+
type: "sticky",
|
|
209
|
+
attribute: "userId",
|
|
210
|
+
salt: "personalization-overlay-copy"
|
|
211
|
+
},
|
|
212
|
+
successMetrics: [
|
|
213
|
+
{
|
|
214
|
+
key: "checklist-completion-rate",
|
|
215
|
+
telemetryEvent: {
|
|
216
|
+
key: "personalization.assignment.completed",
|
|
217
|
+
version: "1.0.0"
|
|
218
|
+
},
|
|
219
|
+
aggregation: "count",
|
|
220
|
+
target: 1
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
tags: ["personalization", "experiment"]
|
|
224
|
+
};
|
|
225
|
+
|
|
166
226
|
// src/personalization.feature.ts
|
|
167
227
|
import { defineFeature } from "@contractspec/lib.contracts-spec";
|
|
168
228
|
var PersonalizationFeature = defineFeature({
|
|
@@ -183,8 +243,70 @@ var PersonalizationFeature = defineFeature({
|
|
|
183
243
|
]
|
|
184
244
|
});
|
|
185
245
|
|
|
246
|
+
// src/personalization.theme.ts
|
|
247
|
+
import {
|
|
248
|
+
OwnersEnum as OwnersEnum2,
|
|
249
|
+
StabilityEnum as StabilityEnum2
|
|
250
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
251
|
+
var PersonalizationTheme = {
|
|
252
|
+
meta: {
|
|
253
|
+
key: "personalization.theme.guided-onboarding",
|
|
254
|
+
version: "1.0.0",
|
|
255
|
+
title: "Guided Onboarding Theme",
|
|
256
|
+
description: "Theme tokens used when the personalized onboarding experience is active.",
|
|
257
|
+
domain: "personalization",
|
|
258
|
+
owners: [OwnersEnum2.PlatformCore],
|
|
259
|
+
tags: ["personalization", "theme", "onboarding"],
|
|
260
|
+
stability: StabilityEnum2.Experimental,
|
|
261
|
+
scopes: ["tenant", "user"]
|
|
262
|
+
},
|
|
263
|
+
tokens: {
|
|
264
|
+
colors: {
|
|
265
|
+
surface: { value: "#FCF6E8" },
|
|
266
|
+
accent: { value: "#C8742A" },
|
|
267
|
+
text: { value: "#2F2419" }
|
|
268
|
+
},
|
|
269
|
+
radii: {
|
|
270
|
+
card: { value: 18 }
|
|
271
|
+
},
|
|
272
|
+
space: {
|
|
273
|
+
panel: { value: 24 }
|
|
274
|
+
},
|
|
275
|
+
typography: {
|
|
276
|
+
body: { value: 16 },
|
|
277
|
+
title: { value: 28 }
|
|
278
|
+
},
|
|
279
|
+
motion: {
|
|
280
|
+
stagger: { value: "180ms" }
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
components: [
|
|
284
|
+
{
|
|
285
|
+
component: "OnboardingChecklist",
|
|
286
|
+
variants: {
|
|
287
|
+
guided: {
|
|
288
|
+
props: {
|
|
289
|
+
emphasis: "warm"
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
overrides: [
|
|
296
|
+
{
|
|
297
|
+
scope: "tenant",
|
|
298
|
+
target: "tenant:acme",
|
|
299
|
+
tokens: {
|
|
300
|
+
colors: {
|
|
301
|
+
accent: { value: "#8A4B12" }
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
};
|
|
307
|
+
|
|
186
308
|
// src/workflow-extension.ts
|
|
187
|
-
import { StabilityEnum } from "@contractspec/lib.contracts-spec";
|
|
309
|
+
import { StabilityEnum as StabilityEnum3 } from "@contractspec/lib.contracts-spec";
|
|
188
310
|
import { Logger as Logger3, LogLevel as LogLevel3 } from "@contractspec/lib.logger";
|
|
189
311
|
import { WorkflowComposer } from "@contractspec/lib.workflow-composer";
|
|
190
312
|
var logger3 = new Logger3({
|
|
@@ -201,7 +323,7 @@ var BaseWorkflow = {
|
|
|
201
323
|
tags: [],
|
|
202
324
|
description: "",
|
|
203
325
|
domain: "billing",
|
|
204
|
-
stability:
|
|
326
|
+
stability: StabilityEnum3.Stable
|
|
205
327
|
},
|
|
206
328
|
definition: {
|
|
207
329
|
steps: [
|
|
@@ -245,5 +367,7 @@ export {
|
|
|
245
367
|
logTenantWorkflowSteps,
|
|
246
368
|
example_default as example,
|
|
247
369
|
composeTenantWorkflowExample,
|
|
248
|
-
|
|
370
|
+
PersonalizationTheme,
|
|
371
|
+
PersonalizationFeature,
|
|
372
|
+
PersonalizationExperiment
|
|
249
373
|
};
|
package/dist/node/index.js
CHANGED
|
@@ -162,6 +162,66 @@ async function runOverlayCustomizationExample() {
|
|
|
162
162
|
logger2.info("Overlay applied", { fields: result.target.fields });
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
// src/personalization.experiment.ts
|
|
166
|
+
import {
|
|
167
|
+
OwnersEnum,
|
|
168
|
+
StabilityEnum
|
|
169
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
170
|
+
var PersonalizationExperiment = {
|
|
171
|
+
meta: {
|
|
172
|
+
key: "personalization.experiment.overlay-copy",
|
|
173
|
+
version: "1.0.0",
|
|
174
|
+
title: "Personalization Overlay Copy Experiment",
|
|
175
|
+
description: "Tests a control onboarding copy against a personalized overlay variant.",
|
|
176
|
+
domain: "personalization",
|
|
177
|
+
owners: [OwnersEnum.PlatformCore],
|
|
178
|
+
tags: ["personalization", "experiment", "overlay"],
|
|
179
|
+
stability: StabilityEnum.Experimental
|
|
180
|
+
},
|
|
181
|
+
controlVariant: "control",
|
|
182
|
+
variants: [
|
|
183
|
+
{
|
|
184
|
+
id: "control",
|
|
185
|
+
key: "control",
|
|
186
|
+
description: "Default onboarding copy and standard workflow."
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: "personalized-overlay",
|
|
190
|
+
key: "personalized-overlay",
|
|
191
|
+
description: "Personalized copy with a branded theme override.",
|
|
192
|
+
overrides: [
|
|
193
|
+
{
|
|
194
|
+
type: "theme",
|
|
195
|
+
target: "personalization.theme.guided-onboarding",
|
|
196
|
+
version: "1.0.0"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: "workflow",
|
|
200
|
+
target: "billing.invoiceApproval",
|
|
201
|
+
version: "1.0.0"
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
allocation: {
|
|
207
|
+
type: "sticky",
|
|
208
|
+
attribute: "userId",
|
|
209
|
+
salt: "personalization-overlay-copy"
|
|
210
|
+
},
|
|
211
|
+
successMetrics: [
|
|
212
|
+
{
|
|
213
|
+
key: "checklist-completion-rate",
|
|
214
|
+
telemetryEvent: {
|
|
215
|
+
key: "personalization.assignment.completed",
|
|
216
|
+
version: "1.0.0"
|
|
217
|
+
},
|
|
218
|
+
aggregation: "count",
|
|
219
|
+
target: 1
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
tags: ["personalization", "experiment"]
|
|
223
|
+
};
|
|
224
|
+
|
|
165
225
|
// src/personalization.feature.ts
|
|
166
226
|
import { defineFeature } from "@contractspec/lib.contracts-spec";
|
|
167
227
|
var PersonalizationFeature = defineFeature({
|
|
@@ -182,8 +242,70 @@ var PersonalizationFeature = defineFeature({
|
|
|
182
242
|
]
|
|
183
243
|
});
|
|
184
244
|
|
|
245
|
+
// src/personalization.theme.ts
|
|
246
|
+
import {
|
|
247
|
+
OwnersEnum as OwnersEnum2,
|
|
248
|
+
StabilityEnum as StabilityEnum2
|
|
249
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
250
|
+
var PersonalizationTheme = {
|
|
251
|
+
meta: {
|
|
252
|
+
key: "personalization.theme.guided-onboarding",
|
|
253
|
+
version: "1.0.0",
|
|
254
|
+
title: "Guided Onboarding Theme",
|
|
255
|
+
description: "Theme tokens used when the personalized onboarding experience is active.",
|
|
256
|
+
domain: "personalization",
|
|
257
|
+
owners: [OwnersEnum2.PlatformCore],
|
|
258
|
+
tags: ["personalization", "theme", "onboarding"],
|
|
259
|
+
stability: StabilityEnum2.Experimental,
|
|
260
|
+
scopes: ["tenant", "user"]
|
|
261
|
+
},
|
|
262
|
+
tokens: {
|
|
263
|
+
colors: {
|
|
264
|
+
surface: { value: "#FCF6E8" },
|
|
265
|
+
accent: { value: "#C8742A" },
|
|
266
|
+
text: { value: "#2F2419" }
|
|
267
|
+
},
|
|
268
|
+
radii: {
|
|
269
|
+
card: { value: 18 }
|
|
270
|
+
},
|
|
271
|
+
space: {
|
|
272
|
+
panel: { value: 24 }
|
|
273
|
+
},
|
|
274
|
+
typography: {
|
|
275
|
+
body: { value: 16 },
|
|
276
|
+
title: { value: 28 }
|
|
277
|
+
},
|
|
278
|
+
motion: {
|
|
279
|
+
stagger: { value: "180ms" }
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
components: [
|
|
283
|
+
{
|
|
284
|
+
component: "OnboardingChecklist",
|
|
285
|
+
variants: {
|
|
286
|
+
guided: {
|
|
287
|
+
props: {
|
|
288
|
+
emphasis: "warm"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
overrides: [
|
|
295
|
+
{
|
|
296
|
+
scope: "tenant",
|
|
297
|
+
target: "tenant:acme",
|
|
298
|
+
tokens: {
|
|
299
|
+
colors: {
|
|
300
|
+
accent: { value: "#8A4B12" }
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
|
|
185
307
|
// src/workflow-extension.ts
|
|
186
|
-
import { StabilityEnum } from "@contractspec/lib.contracts-spec";
|
|
308
|
+
import { StabilityEnum as StabilityEnum3 } from "@contractspec/lib.contracts-spec";
|
|
187
309
|
import { Logger as Logger3, LogLevel as LogLevel3 } from "@contractspec/lib.logger";
|
|
188
310
|
import { WorkflowComposer } from "@contractspec/lib.workflow-composer";
|
|
189
311
|
var logger3 = new Logger3({
|
|
@@ -200,7 +322,7 @@ var BaseWorkflow = {
|
|
|
200
322
|
tags: [],
|
|
201
323
|
description: "",
|
|
202
324
|
domain: "billing",
|
|
203
|
-
stability:
|
|
325
|
+
stability: StabilityEnum3.Stable
|
|
204
326
|
},
|
|
205
327
|
definition: {
|
|
206
328
|
steps: [
|
|
@@ -244,5 +366,7 @@ export {
|
|
|
244
366
|
logTenantWorkflowSteps,
|
|
245
367
|
example_default as example,
|
|
246
368
|
composeTenantWorkflowExample,
|
|
247
|
-
|
|
369
|
+
PersonalizationTheme,
|
|
370
|
+
PersonalizationFeature,
|
|
371
|
+
PersonalizationExperiment
|
|
248
372
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/personalization.experiment.ts
|
|
2
|
+
import {
|
|
3
|
+
OwnersEnum,
|
|
4
|
+
StabilityEnum
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
6
|
+
var PersonalizationExperiment = {
|
|
7
|
+
meta: {
|
|
8
|
+
key: "personalization.experiment.overlay-copy",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
title: "Personalization Overlay Copy Experiment",
|
|
11
|
+
description: "Tests a control onboarding copy against a personalized overlay variant.",
|
|
12
|
+
domain: "personalization",
|
|
13
|
+
owners: [OwnersEnum.PlatformCore],
|
|
14
|
+
tags: ["personalization", "experiment", "overlay"],
|
|
15
|
+
stability: StabilityEnum.Experimental
|
|
16
|
+
},
|
|
17
|
+
controlVariant: "control",
|
|
18
|
+
variants: [
|
|
19
|
+
{
|
|
20
|
+
id: "control",
|
|
21
|
+
key: "control",
|
|
22
|
+
description: "Default onboarding copy and standard workflow."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "personalized-overlay",
|
|
26
|
+
key: "personalized-overlay",
|
|
27
|
+
description: "Personalized copy with a branded theme override.",
|
|
28
|
+
overrides: [
|
|
29
|
+
{
|
|
30
|
+
type: "theme",
|
|
31
|
+
target: "personalization.theme.guided-onboarding",
|
|
32
|
+
version: "1.0.0"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: "workflow",
|
|
36
|
+
target: "billing.invoiceApproval",
|
|
37
|
+
version: "1.0.0"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
allocation: {
|
|
43
|
+
type: "sticky",
|
|
44
|
+
attribute: "userId",
|
|
45
|
+
salt: "personalization-overlay-copy"
|
|
46
|
+
},
|
|
47
|
+
successMetrics: [
|
|
48
|
+
{
|
|
49
|
+
key: "checklist-completion-rate",
|
|
50
|
+
telemetryEvent: {
|
|
51
|
+
key: "personalization.assignment.completed",
|
|
52
|
+
version: "1.0.0"
|
|
53
|
+
},
|
|
54
|
+
aggregation: "count",
|
|
55
|
+
target: 1
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
tags: ["personalization", "experiment"]
|
|
59
|
+
};
|
|
60
|
+
export {
|
|
61
|
+
PersonalizationExperiment
|
|
62
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/personalization.theme.ts
|
|
2
|
+
import {
|
|
3
|
+
OwnersEnum,
|
|
4
|
+
StabilityEnum
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
6
|
+
var PersonalizationTheme = {
|
|
7
|
+
meta: {
|
|
8
|
+
key: "personalization.theme.guided-onboarding",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
title: "Guided Onboarding Theme",
|
|
11
|
+
description: "Theme tokens used when the personalized onboarding experience is active.",
|
|
12
|
+
domain: "personalization",
|
|
13
|
+
owners: [OwnersEnum.PlatformCore],
|
|
14
|
+
tags: ["personalization", "theme", "onboarding"],
|
|
15
|
+
stability: StabilityEnum.Experimental,
|
|
16
|
+
scopes: ["tenant", "user"]
|
|
17
|
+
},
|
|
18
|
+
tokens: {
|
|
19
|
+
colors: {
|
|
20
|
+
surface: { value: "#FCF6E8" },
|
|
21
|
+
accent: { value: "#C8742A" },
|
|
22
|
+
text: { value: "#2F2419" }
|
|
23
|
+
},
|
|
24
|
+
radii: {
|
|
25
|
+
card: { value: 18 }
|
|
26
|
+
},
|
|
27
|
+
space: {
|
|
28
|
+
panel: { value: 24 }
|
|
29
|
+
},
|
|
30
|
+
typography: {
|
|
31
|
+
body: { value: 16 },
|
|
32
|
+
title: { value: 28 }
|
|
33
|
+
},
|
|
34
|
+
motion: {
|
|
35
|
+
stagger: { value: "180ms" }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
components: [
|
|
39
|
+
{
|
|
40
|
+
component: "OnboardingChecklist",
|
|
41
|
+
variants: {
|
|
42
|
+
guided: {
|
|
43
|
+
props: {
|
|
44
|
+
emphasis: "warm"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
overrides: [
|
|
51
|
+
{
|
|
52
|
+
scope: "tenant",
|
|
53
|
+
target: "tenant:acme",
|
|
54
|
+
tokens: {
|
|
55
|
+
colors: {
|
|
56
|
+
accent: { value: "#8A4B12" }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
PersonalizationTheme
|
|
64
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/personalization.experiment.ts
|
|
3
|
+
import {
|
|
4
|
+
OwnersEnum,
|
|
5
|
+
StabilityEnum
|
|
6
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
7
|
+
var PersonalizationExperiment = {
|
|
8
|
+
meta: {
|
|
9
|
+
key: "personalization.experiment.overlay-copy",
|
|
10
|
+
version: "1.0.0",
|
|
11
|
+
title: "Personalization Overlay Copy Experiment",
|
|
12
|
+
description: "Tests a control onboarding copy against a personalized overlay variant.",
|
|
13
|
+
domain: "personalization",
|
|
14
|
+
owners: [OwnersEnum.PlatformCore],
|
|
15
|
+
tags: ["personalization", "experiment", "overlay"],
|
|
16
|
+
stability: StabilityEnum.Experimental
|
|
17
|
+
},
|
|
18
|
+
controlVariant: "control",
|
|
19
|
+
variants: [
|
|
20
|
+
{
|
|
21
|
+
id: "control",
|
|
22
|
+
key: "control",
|
|
23
|
+
description: "Default onboarding copy and standard workflow."
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "personalized-overlay",
|
|
27
|
+
key: "personalized-overlay",
|
|
28
|
+
description: "Personalized copy with a branded theme override.",
|
|
29
|
+
overrides: [
|
|
30
|
+
{
|
|
31
|
+
type: "theme",
|
|
32
|
+
target: "personalization.theme.guided-onboarding",
|
|
33
|
+
version: "1.0.0"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: "workflow",
|
|
37
|
+
target: "billing.invoiceApproval",
|
|
38
|
+
version: "1.0.0"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
allocation: {
|
|
44
|
+
type: "sticky",
|
|
45
|
+
attribute: "userId",
|
|
46
|
+
salt: "personalization-overlay-copy"
|
|
47
|
+
},
|
|
48
|
+
successMetrics: [
|
|
49
|
+
{
|
|
50
|
+
key: "checklist-completion-rate",
|
|
51
|
+
telemetryEvent: {
|
|
52
|
+
key: "personalization.assignment.completed",
|
|
53
|
+
version: "1.0.0"
|
|
54
|
+
},
|
|
55
|
+
aggregation: "count",
|
|
56
|
+
target: 1
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
tags: ["personalization", "experiment"]
|
|
60
|
+
};
|
|
61
|
+
export {
|
|
62
|
+
PersonalizationExperiment
|
|
63
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/personalization.theme.ts
|
|
3
|
+
import {
|
|
4
|
+
OwnersEnum,
|
|
5
|
+
StabilityEnum
|
|
6
|
+
} from "@contractspec/lib.contracts-spec/ownership";
|
|
7
|
+
var PersonalizationTheme = {
|
|
8
|
+
meta: {
|
|
9
|
+
key: "personalization.theme.guided-onboarding",
|
|
10
|
+
version: "1.0.0",
|
|
11
|
+
title: "Guided Onboarding Theme",
|
|
12
|
+
description: "Theme tokens used when the personalized onboarding experience is active.",
|
|
13
|
+
domain: "personalization",
|
|
14
|
+
owners: [OwnersEnum.PlatformCore],
|
|
15
|
+
tags: ["personalization", "theme", "onboarding"],
|
|
16
|
+
stability: StabilityEnum.Experimental,
|
|
17
|
+
scopes: ["tenant", "user"]
|
|
18
|
+
},
|
|
19
|
+
tokens: {
|
|
20
|
+
colors: {
|
|
21
|
+
surface: { value: "#FCF6E8" },
|
|
22
|
+
accent: { value: "#C8742A" },
|
|
23
|
+
text: { value: "#2F2419" }
|
|
24
|
+
},
|
|
25
|
+
radii: {
|
|
26
|
+
card: { value: 18 }
|
|
27
|
+
},
|
|
28
|
+
space: {
|
|
29
|
+
panel: { value: 24 }
|
|
30
|
+
},
|
|
31
|
+
typography: {
|
|
32
|
+
body: { value: 16 },
|
|
33
|
+
title: { value: 28 }
|
|
34
|
+
},
|
|
35
|
+
motion: {
|
|
36
|
+
stagger: { value: "180ms" }
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
components: [
|
|
40
|
+
{
|
|
41
|
+
component: "OnboardingChecklist",
|
|
42
|
+
variants: {
|
|
43
|
+
guided: {
|
|
44
|
+
props: {
|
|
45
|
+
emphasis: "warm"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
overrides: [
|
|
52
|
+
{
|
|
53
|
+
scope: "tenant",
|
|
54
|
+
target: "tenant:acme",
|
|
55
|
+
tokens: {
|
|
56
|
+
colors: {
|
|
57
|
+
accent: { value: "#8A4B12" }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
export {
|
|
64
|
+
PersonalizationTheme
|
|
65
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/example.personalization",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.10",
|
|
4
4
|
"description": "Personalization examples: behavior tracking, overlay customization, workflow extension.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -47,6 +47,13 @@
|
|
|
47
47
|
"node": "./dist/node/overlay-customization.js",
|
|
48
48
|
"default": "./dist/overlay-customization.js"
|
|
49
49
|
},
|
|
50
|
+
"./personalization.experiment": {
|
|
51
|
+
"types": "./dist/personalization.experiment.d.ts",
|
|
52
|
+
"browser": "./dist/browser/personalization.experiment.js",
|
|
53
|
+
"bun": "./dist/personalization.experiment.js",
|
|
54
|
+
"node": "./dist/node/personalization.experiment.js",
|
|
55
|
+
"default": "./dist/personalization.experiment.js"
|
|
56
|
+
},
|
|
50
57
|
"./personalization.feature": {
|
|
51
58
|
"types": "./dist/personalization.feature.d.ts",
|
|
52
59
|
"browser": "./dist/browser/personalization.feature.js",
|
|
@@ -54,6 +61,13 @@
|
|
|
54
61
|
"node": "./dist/node/personalization.feature.js",
|
|
55
62
|
"default": "./dist/personalization.feature.js"
|
|
56
63
|
},
|
|
64
|
+
"./personalization.theme": {
|
|
65
|
+
"types": "./dist/personalization.theme.d.ts",
|
|
66
|
+
"browser": "./dist/browser/personalization.theme.js",
|
|
67
|
+
"bun": "./dist/personalization.theme.js",
|
|
68
|
+
"node": "./dist/node/personalization.theme.js",
|
|
69
|
+
"default": "./dist/personalization.theme.js"
|
|
70
|
+
},
|
|
57
71
|
"./workflow-extension": {
|
|
58
72
|
"types": "./dist/workflow-extension.d.ts",
|
|
59
73
|
"browser": "./dist/browser/workflow-extension.js",
|
|
@@ -78,16 +92,16 @@
|
|
|
78
92
|
"typecheck": "tsc --noEmit"
|
|
79
93
|
},
|
|
80
94
|
"dependencies": {
|
|
81
|
-
"@contractspec/lib.personalization": "6.0.
|
|
82
|
-
"@contractspec/lib.overlay-engine": "3.7.
|
|
83
|
-
"@contractspec/lib.workflow-composer": "3.7.
|
|
84
|
-
"@contractspec/lib.contracts-spec": "4.
|
|
85
|
-
"@contractspec/lib.logger": "3.7.
|
|
95
|
+
"@contractspec/lib.personalization": "6.0.10",
|
|
96
|
+
"@contractspec/lib.overlay-engine": "3.7.10",
|
|
97
|
+
"@contractspec/lib.workflow-composer": "3.7.10",
|
|
98
|
+
"@contractspec/lib.contracts-spec": "4.1.2",
|
|
99
|
+
"@contractspec/lib.logger": "3.7.8"
|
|
86
100
|
},
|
|
87
101
|
"devDependencies": {
|
|
88
|
-
"@contractspec/tool.typescript": "3.7.
|
|
102
|
+
"@contractspec/tool.typescript": "3.7.8",
|
|
89
103
|
"typescript": "^5.9.3",
|
|
90
|
-
"@contractspec/tool.bun": "3.7.
|
|
104
|
+
"@contractspec/tool.bun": "3.7.8"
|
|
91
105
|
},
|
|
92
106
|
"publishConfig": {
|
|
93
107
|
"access": "public",
|
|
@@ -134,6 +148,13 @@
|
|
|
134
148
|
"node": "./dist/node/overlay-customization.js",
|
|
135
149
|
"default": "./dist/overlay-customization.js"
|
|
136
150
|
},
|
|
151
|
+
"./personalization.experiment": {
|
|
152
|
+
"types": "./dist/personalization.experiment.d.ts",
|
|
153
|
+
"browser": "./dist/browser/personalization.experiment.js",
|
|
154
|
+
"bun": "./dist/personalization.experiment.js",
|
|
155
|
+
"node": "./dist/node/personalization.experiment.js",
|
|
156
|
+
"default": "./dist/personalization.experiment.js"
|
|
157
|
+
},
|
|
137
158
|
"./personalization.feature": {
|
|
138
159
|
"types": "./dist/personalization.feature.d.ts",
|
|
139
160
|
"browser": "./dist/browser/personalization.feature.js",
|
|
@@ -141,6 +162,13 @@
|
|
|
141
162
|
"node": "./dist/node/personalization.feature.js",
|
|
142
163
|
"default": "./dist/personalization.feature.js"
|
|
143
164
|
},
|
|
165
|
+
"./personalization.theme": {
|
|
166
|
+
"types": "./dist/personalization.theme.d.ts",
|
|
167
|
+
"browser": "./dist/browser/personalization.theme.js",
|
|
168
|
+
"bun": "./dist/personalization.theme.js",
|
|
169
|
+
"node": "./dist/node/personalization.theme.js",
|
|
170
|
+
"default": "./dist/personalization.theme.js"
|
|
171
|
+
},
|
|
144
172
|
"./workflow-extension": {
|
|
145
173
|
"types": "./dist/workflow-extension.d.ts",
|
|
146
174
|
"browser": "./dist/browser/workflow-extension.js",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import {
|
|
3
|
+
PersonalizationExperiment,
|
|
4
|
+
PersonalizationFeature,
|
|
5
|
+
PersonalizationTheme,
|
|
6
|
+
} from './index';
|
|
7
|
+
|
|
8
|
+
describe('@contractspec/example.personalization', () => {
|
|
9
|
+
test('exports the canonical experiment and theme', () => {
|
|
10
|
+
expect(PersonalizationExperiment.meta.key).toBe(
|
|
11
|
+
'personalization.experiment.overlay-copy'
|
|
12
|
+
);
|
|
13
|
+
expect(PersonalizationExperiment.variants).toHaveLength(2);
|
|
14
|
+
expect(PersonalizationTheme.meta.key).toBe(
|
|
15
|
+
'personalization.theme.guided-onboarding'
|
|
16
|
+
);
|
|
17
|
+
expect(PersonalizationTheme.overrides).toHaveLength(1);
|
|
18
|
+
expect(PersonalizationFeature.meta.key).toBe('personalization');
|
|
19
|
+
});
|
|
20
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './behavior-tracking';
|
|
2
2
|
export { default as example } from './example';
|
|
3
3
|
export * from './overlay-customization';
|
|
4
|
+
export * from './personalization.experiment';
|
|
4
5
|
export * from './personalization.feature';
|
|
6
|
+
export * from './personalization.theme';
|
|
5
7
|
export * from './workflow-extension';
|
|
6
8
|
import './docs';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ExperimentSpec } from '@contractspec/lib.contracts-spec/experiments/spec';
|
|
2
|
+
import {
|
|
3
|
+
OwnersEnum,
|
|
4
|
+
StabilityEnum,
|
|
5
|
+
} from '@contractspec/lib.contracts-spec/ownership';
|
|
6
|
+
|
|
7
|
+
export const PersonalizationExperiment: ExperimentSpec = {
|
|
8
|
+
meta: {
|
|
9
|
+
key: 'personalization.experiment.overlay-copy',
|
|
10
|
+
version: '1.0.0',
|
|
11
|
+
title: 'Personalization Overlay Copy Experiment',
|
|
12
|
+
description:
|
|
13
|
+
'Tests a control onboarding copy against a personalized overlay variant.',
|
|
14
|
+
domain: 'personalization',
|
|
15
|
+
owners: [OwnersEnum.PlatformCore],
|
|
16
|
+
tags: ['personalization', 'experiment', 'overlay'],
|
|
17
|
+
stability: StabilityEnum.Experimental,
|
|
18
|
+
},
|
|
19
|
+
controlVariant: 'control',
|
|
20
|
+
variants: [
|
|
21
|
+
{
|
|
22
|
+
id: 'control',
|
|
23
|
+
key: 'control',
|
|
24
|
+
description: 'Default onboarding copy and standard workflow.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'personalized-overlay',
|
|
28
|
+
key: 'personalized-overlay',
|
|
29
|
+
description: 'Personalized copy with a branded theme override.',
|
|
30
|
+
overrides: [
|
|
31
|
+
{
|
|
32
|
+
type: 'theme',
|
|
33
|
+
target: 'personalization.theme.guided-onboarding',
|
|
34
|
+
version: '1.0.0',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'workflow',
|
|
38
|
+
target: 'billing.invoiceApproval',
|
|
39
|
+
version: '1.0.0',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
allocation: {
|
|
45
|
+
type: 'sticky',
|
|
46
|
+
attribute: 'userId',
|
|
47
|
+
salt: 'personalization-overlay-copy',
|
|
48
|
+
},
|
|
49
|
+
successMetrics: [
|
|
50
|
+
{
|
|
51
|
+
key: 'checklist-completion-rate',
|
|
52
|
+
telemetryEvent: {
|
|
53
|
+
key: 'personalization.assignment.completed',
|
|
54
|
+
version: '1.0.0',
|
|
55
|
+
},
|
|
56
|
+
aggregation: 'count',
|
|
57
|
+
target: 1,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
tags: ['personalization', 'experiment'],
|
|
61
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OwnersEnum,
|
|
3
|
+
StabilityEnum,
|
|
4
|
+
} from '@contractspec/lib.contracts-spec/ownership';
|
|
5
|
+
import type { ThemeSpec } from '@contractspec/lib.contracts-spec/themes';
|
|
6
|
+
|
|
7
|
+
export const PersonalizationTheme: ThemeSpec = {
|
|
8
|
+
meta: {
|
|
9
|
+
key: 'personalization.theme.guided-onboarding',
|
|
10
|
+
version: '1.0.0',
|
|
11
|
+
title: 'Guided Onboarding Theme',
|
|
12
|
+
description:
|
|
13
|
+
'Theme tokens used when the personalized onboarding experience is active.',
|
|
14
|
+
domain: 'personalization',
|
|
15
|
+
owners: [OwnersEnum.PlatformCore],
|
|
16
|
+
tags: ['personalization', 'theme', 'onboarding'],
|
|
17
|
+
stability: StabilityEnum.Experimental,
|
|
18
|
+
scopes: ['tenant', 'user'],
|
|
19
|
+
},
|
|
20
|
+
tokens: {
|
|
21
|
+
colors: {
|
|
22
|
+
surface: { value: '#FCF6E8' },
|
|
23
|
+
accent: { value: '#C8742A' },
|
|
24
|
+
text: { value: '#2F2419' },
|
|
25
|
+
},
|
|
26
|
+
radii: {
|
|
27
|
+
card: { value: 18 },
|
|
28
|
+
},
|
|
29
|
+
space: {
|
|
30
|
+
panel: { value: 24 },
|
|
31
|
+
},
|
|
32
|
+
typography: {
|
|
33
|
+
body: { value: 16 },
|
|
34
|
+
title: { value: 28 },
|
|
35
|
+
},
|
|
36
|
+
motion: {
|
|
37
|
+
stagger: { value: '180ms' },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
components: [
|
|
41
|
+
{
|
|
42
|
+
component: 'OnboardingChecklist',
|
|
43
|
+
variants: {
|
|
44
|
+
guided: {
|
|
45
|
+
props: {
|
|
46
|
+
emphasis: 'warm',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
overrides: [
|
|
53
|
+
{
|
|
54
|
+
scope: 'tenant',
|
|
55
|
+
target: 'tenant:acme',
|
|
56
|
+
tokens: {
|
|
57
|
+
colors: {
|
|
58
|
+
accent: { value: '#8A4B12' },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|