@contractspec/example.personalization 3.7.6 → 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/AGENTS.md +43 -19
- package/CHANGELOG.md +28 -0
- package/README.md +67 -16
- package/dist/behavior-tracking.js +3 -3
- package/dist/browser/behavior-tracking.js +3 -3
- package/dist/browser/index.js +154 -30
- package/dist/browser/overlay-customization.js +3 -3
- package/dist/browser/personalization.experiment.js +62 -0
- package/dist/browser/personalization.theme.js +64 -0
- package/dist/browser/workflow-extension.js +1 -1
- package/dist/contracts.test.d.ts +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +154 -30
- package/dist/node/behavior-tracking.js +3 -3
- package/dist/node/index.js +154 -30
- package/dist/node/overlay-customization.js +3 -3
- package/dist/node/personalization.experiment.js +62 -0
- package/dist/node/personalization.theme.js +64 -0
- package/dist/node/workflow-extension.js +1 -1
- package/dist/overlay-customization.js +3 -3
- 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/dist/workflow-extension.js +1 -1
- package/package.json +38 -10
- package/src/behavior-tracking.ts +37 -37
- package/src/contracts.test.ts +20 -0
- package/src/docs/personalization.docblock.ts +21 -21
- package/src/example.ts +26 -26
- package/src/index.ts +4 -2
- package/src/overlay-customization.ts +45 -45
- package/src/personalization.experiment.ts +61 -0
- package/src/personalization.feature.ts +16 -16
- package/src/personalization.theme.ts +63 -0
- package/src/workflow-extension.ts +47 -47
- package/tsconfig.json +17 -15
- package/tsdown.config.js +1 -1
|
@@ -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
|
+
};
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { defineFeature } from '@contractspec/lib.contracts-spec';
|
|
2
2
|
|
|
3
3
|
export const PersonalizationFeature = defineFeature({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
meta: {
|
|
5
|
+
key: 'personalization',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
title: 'Personalization Patterns',
|
|
8
|
+
description:
|
|
9
|
+
'Behavior tracking, overlay customization, and workflow extension patterns',
|
|
10
|
+
domain: 'personalization',
|
|
11
|
+
owners: ['@examples'],
|
|
12
|
+
tags: ['personalization', 'behavior', 'overlay', 'workflow'],
|
|
13
|
+
stability: 'experimental',
|
|
14
|
+
},
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
telemetry: [{ key: 'personalization.telemetry', version: '1.0.0' }],
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
docs: [
|
|
19
|
+
'docs.examples.personalization',
|
|
20
|
+
'docs.examples.personalization.usage',
|
|
21
|
+
],
|
|
22
22
|
});
|
|
@@ -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
|
+
};
|
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
import { StabilityEnum } from '@contractspec/lib.contracts-spec';
|
|
2
2
|
import type { WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow/spec';
|
|
3
|
-
import { WorkflowComposer } from '@contractspec/lib.workflow-composer';
|
|
4
3
|
import { Logger, LogLevel } from '@contractspec/lib.logger';
|
|
4
|
+
import { WorkflowComposer } from '@contractspec/lib.workflow-composer';
|
|
5
5
|
|
|
6
6
|
const logger = new Logger({
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
level: process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG,
|
|
8
|
+
environment:
|
|
9
|
+
(process.env.NODE_ENV as 'production' | 'development' | 'test') ||
|
|
10
|
+
'development',
|
|
11
|
+
enableColors: process.env.NODE_ENV !== 'production',
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
const BaseWorkflow: WorkflowSpec = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
15
|
+
meta: {
|
|
16
|
+
key: 'billing.invoiceApproval',
|
|
17
|
+
version: '1.0.0',
|
|
18
|
+
title: 'Invoice Approval',
|
|
19
|
+
owners: [],
|
|
20
|
+
tags: [],
|
|
21
|
+
description: '',
|
|
22
|
+
domain: 'billing',
|
|
23
|
+
stability: StabilityEnum.Stable,
|
|
24
|
+
},
|
|
25
|
+
definition: {
|
|
26
|
+
steps: [
|
|
27
|
+
{ id: 'validate-invoice', type: 'automation', label: 'Validate Invoice' },
|
|
28
|
+
{ id: 'final-approval', type: 'human', label: 'Final Approval' },
|
|
29
|
+
],
|
|
30
|
+
transitions: [{ from: 'validate-invoice', to: 'final-approval' }],
|
|
31
|
+
},
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
export function composeTenantWorkflowExample(): WorkflowSpec {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
35
|
+
const composer = new WorkflowComposer();
|
|
36
|
+
composer.register({
|
|
37
|
+
workflow: 'billing.invoiceApproval',
|
|
38
|
+
tenantId: 'acme',
|
|
39
|
+
customSteps: [
|
|
40
|
+
{
|
|
41
|
+
after: 'validate-invoice',
|
|
42
|
+
inject: {
|
|
43
|
+
id: 'acme-legal',
|
|
44
|
+
type: 'human',
|
|
45
|
+
label: 'ACME Legal Review',
|
|
46
|
+
},
|
|
47
|
+
transitionTo: 'final-approval',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
return composer.compose({
|
|
53
|
+
base: BaseWorkflow,
|
|
54
|
+
tenantId: 'acme',
|
|
55
|
+
});
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export function logTenantWorkflowSteps(workflow: WorkflowSpec): void {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
logger.info('Tenant workflow composed', {
|
|
60
|
+
workflow: workflow.meta.key,
|
|
61
|
+
steps: workflow.definition.steps.map((step) => step.id),
|
|
62
|
+
});
|
|
63
63
|
}
|
package/tsconfig.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
"extends": "@contractspec/tool.typescript/react-library.json",
|
|
3
|
+
"include": ["src"],
|
|
4
|
+
"exclude": ["node_modules", "dist"],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"paths": {
|
|
8
|
+
"@contractspec/lib.personalization/*": [
|
|
9
|
+
"../../libs/personalization/src/*"
|
|
10
|
+
],
|
|
11
|
+
"@contractspec/lib.contracts-spec/*": ["../../libs/contracts/src/*"],
|
|
12
|
+
"@contractspec/lib.contracts-spec": ["../../libs/contracts/src/index.ts"],
|
|
13
|
+
"@contractspec/lib.overlay-engine/*": ["../../libs/overlay-engine/src/*"],
|
|
14
|
+
"@contractspec/lib.overlay-engine": [
|
|
15
|
+
"../../libs/overlay-engine/src/index.ts"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
15
19
|
}
|
|
16
|
-
|
|
17
|
-
|
package/tsdown.config.js
CHANGED