@case-framework/survey-assistant 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -7
- package/dist/{attachments-B0hg3vpT.mjs → attachments-BuNni5vB.mjs} +1 -1
- package/dist/{attachments-B0hg3vpT.mjs.map → attachments-BuNni5vB.mjs.map} +1 -1
- package/dist/{authoring-references-CW38pYzK.mjs → authoring-references-DbuOKerg.mjs} +13 -4
- package/dist/authoring-references-DbuOKerg.mjs.map +1 -0
- package/dist/{capabilities-DVTfogjv.d.mts → capabilities-CmeeAjEc.d.mts} +3 -4
- package/dist/capabilities-CmeeAjEc.d.mts.map +1 -0
- package/dist/capabilities-DCMA71PP.mjs +58 -0
- package/dist/capabilities-DCMA71PP.mjs.map +1 -0
- package/dist/capabilities-default.d.mts +13 -12
- package/dist/capabilities-default.d.mts.map +1 -1
- package/dist/capabilities-default.mjs +2 -414
- package/dist/{constants-BMGTgfjv.d.mts → constants-B6HzpEsx.d.mts} +7 -28
- package/dist/constants-B6HzpEsx.d.mts.map +1 -0
- package/dist/{constants-0UHGFcRJ.mjs → constants-Ct-vv9cu.mjs} +1 -1
- package/dist/{constants-0UHGFcRJ.mjs.map → constants-Ct-vv9cu.mjs.map} +1 -1
- package/dist/controller-proxy-D7uQfm5f.d.mts +65 -0
- package/dist/controller-proxy-D7uQfm5f.d.mts.map +1 -0
- package/dist/{controller-proxy-DMTqer6T.mjs → controller-proxy-DEeFl9IA.mjs} +29 -26
- package/dist/controller-proxy-DEeFl9IA.mjs.map +1 -0
- package/dist/default-fhSon2RM.mjs +760 -0
- package/dist/default-fhSon2RM.mjs.map +1 -0
- package/dist/{digest-SJmoYVaK.d.mts → digest-C39WyAWG.d.mts} +2 -3
- package/dist/digest-C39WyAWG.d.mts.map +1 -0
- package/dist/digest.d.mts +1 -1
- package/dist/digest.mjs.map +1 -1
- package/dist/{engine-CQwOAcwK.mjs → engine-nXoCWYpQ.mjs} +2821 -2018
- package/dist/engine-nXoCWYpQ.mjs.map +1 -0
- package/dist/engine.d.mts +3 -3
- package/dist/engine.mjs +3 -3
- package/dist/{fair-guidance-CRYCRxQm.mjs → fair-guidance-BmO4PswW.mjs} +1 -1
- package/dist/{fair-guidance-CRYCRxQm.mjs.map → fair-guidance-BmO4PswW.mjs.map} +1 -1
- package/dist/{index-D6nqkz0O.d.mts → index-Ciq7vHIs.d.mts} +121 -197
- package/dist/index-Ciq7vHIs.d.mts.map +1 -0
- package/dist/{index-DvTqML-0.d.mts → index-D7wT6P3t.d.mts} +294 -63
- package/dist/index-D7wT6P3t.d.mts.map +1 -0
- package/dist/index-WB5kfnz0.d.mts +348 -0
- package/dist/index-WB5kfnz0.d.mts.map +1 -0
- package/dist/{index-B0lxsAzx.d.mts → index-r5riv4md.d.mts} +50 -29
- package/dist/index-r5riv4md.d.mts.map +1 -0
- package/dist/{lifecycle-BmGAIUlv.d.mts → lifecycle-Dm8u7QFh.d.mts} +40 -18
- package/dist/lifecycle-Dm8u7QFh.d.mts.map +1 -0
- package/dist/{memory-thread-repository-CjFGVNZh.mjs → memory-thread-repository-DAnOGIB3.mjs} +89 -34
- package/dist/memory-thread-repository-DAnOGIB3.mjs.map +1 -0
- package/dist/{protocol-DJUP4gc0.mjs → protocol-CF4Bh_Ch.mjs} +182 -50
- package/dist/protocol-CF4Bh_Ch.mjs.map +1 -0
- package/dist/protocol.d.mts +4 -4
- package/dist/protocol.mjs +3 -3
- package/dist/react-C_GY-Fsc.mjs +1727 -0
- package/dist/react-C_GY-Fsc.mjs.map +1 -0
- package/dist/react-integration.d.mts +2 -2
- package/dist/react-integration.mjs +2 -2
- package/dist/react.d.mts +3 -3
- package/dist/react.mjs +3 -3
- package/dist/references/assistant-operations.md +143 -68
- package/dist/references/core-rules.md +6 -3
- package/dist/references/embedded-forms.md +34 -14
- package/dist/references/expressions.md +238 -48
- package/dist/references/fair-by-design.md +9 -9
- package/dist/references/item-types.md +306 -72
- package/dist/references/localization.md +5 -4
- package/dist/references/response-variables.md +38 -0
- package/dist/references/rich-text-content.md +60 -27
- package/dist/references/source-material-surveys.md +13 -5
- package/dist/references/survey-data-model.md +32 -9
- package/dist/{request-context-BjTHNcDd.mjs → request-context-Dg4jSwN1.mjs} +4 -10
- package/dist/request-context-Dg4jSwN1.mjs.map +1 -0
- package/dist/{request-guardrails-TmgQtqp4.mjs → request-guardrails-C0ugBOp0.mjs} +6 -5
- package/dist/request-guardrails-C0ugBOp0.mjs.map +1 -0
- package/dist/server-agent.d.mts +53 -44
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +48 -27
- package/dist/server-agent.mjs.map +1 -1
- package/dist/server-runtime.d.mts +36 -49
- package/dist/server-runtime.d.mts.map +1 -1
- package/dist/server-runtime.mjs +17 -12
- package/dist/server-runtime.mjs.map +1 -1
- package/dist/server-tasks.d.mts +2 -2
- package/dist/server-tasks.mjs +2 -313
- package/dist/server-tools.d.mts +1 -1
- package/dist/server-tools.mjs +1 -1
- package/dist/server.d.mts +13 -36
- package/dist/server.d.mts.map +1 -1
- package/dist/server.mjs +5 -5
- package/dist/server.mjs.map +1 -1
- package/dist/storage-postgres.d.mts +9 -25
- package/dist/storage-postgres.d.mts.map +1 -1
- package/dist/storage-postgres.mjs +5 -4
- package/dist/storage-postgres.mjs.map +1 -1
- package/dist/{tasks-DxzD25Zc.d.mts → tasks-B9h3LPam.d.mts} +19 -35
- package/dist/tasks-B9h3LPam.d.mts.map +1 -0
- package/dist/tasks-BZEiwgxA.mjs +396 -0
- package/dist/tasks-BZEiwgxA.mjs.map +1 -0
- package/dist/thread-documents-DrHbaXqP.d.mts +119 -0
- package/dist/thread-documents-DrHbaXqP.d.mts.map +1 -0
- package/dist/{thread-handlers-AbQbt4sX.d.mts → thread-handlers-Bef0td9N.d.mts} +10 -40
- package/dist/thread-handlers-Bef0td9N.d.mts.map +1 -0
- package/dist/{tools-CFh35R4d.mjs → tools-CEsv-WoO.mjs} +705 -578
- package/dist/tools-CEsv-WoO.mjs.map +1 -0
- package/dist/ui.css +1 -1
- package/dist/ui.d.mts +17 -55
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +759 -171
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +51 -1
- package/package.json +49 -42
- package/dist/authoring-references-CW38pYzK.mjs.map +0 -1
- package/dist/capabilities-DVTfogjv.d.mts.map +0 -1
- package/dist/capabilities-default.mjs.map +0 -1
- package/dist/constants-BMGTgfjv.d.mts.map +0 -1
- package/dist/controller-proxy-DMTqer6T.mjs.map +0 -1
- package/dist/controller-proxy-mRvez2qw.d.mts +0 -85
- package/dist/controller-proxy-mRvez2qw.d.mts.map +0 -1
- package/dist/digest-SJmoYVaK.d.mts.map +0 -1
- package/dist/engine-CQwOAcwK.mjs.map +0 -1
- package/dist/form-authoring-kQDgC5oz.mjs +0 -155
- package/dist/form-authoring-kQDgC5oz.mjs.map +0 -1
- package/dist/index-B0lxsAzx.d.mts.map +0 -1
- package/dist/index-BS-Xjk1h.d.mts +0 -224
- package/dist/index-BS-Xjk1h.d.mts.map +0 -1
- package/dist/index-D6nqkz0O.d.mts.map +0 -1
- package/dist/index-DvTqML-0.d.mts.map +0 -1
- package/dist/lifecycle-BmGAIUlv.d.mts.map +0 -1
- package/dist/memory-thread-repository-CjFGVNZh.mjs.map +0 -1
- package/dist/protocol-DJUP4gc0.mjs.map +0 -1
- package/dist/react-Dqlmasrs.mjs +0 -768
- package/dist/react-Dqlmasrs.mjs.map +0 -1
- package/dist/request-context-BjTHNcDd.mjs.map +0 -1
- package/dist/request-guardrails-TmgQtqp4.mjs.map +0 -1
- package/dist/server-tasks.mjs.map +0 -1
- package/dist/tasks-DxzD25Zc.d.mts.map +0 -1
- package/dist/thread-documents-rmd6nyX9.d.mts +0 -107
- package/dist/thread-documents-rmd6nyX9.d.mts.map +0 -1
- package/dist/thread-handlers-AbQbt4sX.d.mts.map +0 -1
- package/dist/tools-CFh35R4d.mjs.map +0 -1
|
@@ -5,6 +5,8 @@ Use `survey_expression` for expression work. It is the expression capability bun
|
|
|
5
5
|
- `action: "context"` returns available response refs and optional existing expression locations.
|
|
6
6
|
- `action: "prepare"` validates expression refs/return types and registers a candidate change set.
|
|
7
7
|
- Prefer this tool over hand-written raw JSON Patch for expression-bearing locations.
|
|
8
|
+
- Provider adapters normalize optional fields when strict tool calling requires nullable wire
|
|
9
|
+
properties. Supply only the fields used by the chosen action.
|
|
8
10
|
|
|
9
11
|
## JsonExpression
|
|
10
12
|
|
|
@@ -12,7 +14,7 @@ Expression JSON has four node types:
|
|
|
12
14
|
|
|
13
15
|
```json
|
|
14
16
|
{ "type": "const", "value": { "type": "boolean", "value": true } }
|
|
15
|
-
{ "type": "responseVariable", "variableRef": "<
|
|
17
|
+
{ "type": "responseVariable", "variableRef": { "slotId": "<slotId>", "method": "get" } }
|
|
16
18
|
{ "type": "contextVariable", "contextType": "locale" }
|
|
17
19
|
{ "type": "function", "functionName": "and", "arguments": [] }
|
|
18
20
|
```
|
|
@@ -26,18 +28,38 @@ Response values are typed objects:
|
|
|
26
28
|
- string: `{ "type": "string", "value": "abc" }`
|
|
27
29
|
- number: `{ "type": "number", "value": 42 }`
|
|
28
30
|
- boolean: `{ "type": "boolean", "value": true }`
|
|
29
|
-
- date: `{ "type": "date", "value":
|
|
31
|
+
- date: `{ "type": "date", "value": "2026-01-01" }`
|
|
30
32
|
- duration: `{ "type": "duration", "value": 3, "unit": "days" }`
|
|
31
33
|
- reference: `{ "type": "reference", "value": "<optionId>" }`
|
|
32
34
|
- arrays use `string[]`, `number[]`, `date[]`, `duration[]`, `reference[]`.
|
|
33
35
|
|
|
34
|
-
Response variable refs
|
|
35
|
-
`<itemId>...<method>...<slotId>`
|
|
36
|
+
Response variable refs are structured objects: `{ "slotId": "<persistent-slot-id>", "method": "get" }`. There is no item ID, dotted path, variable name, or encoded string in a reference.
|
|
36
37
|
|
|
37
38
|
Methods:
|
|
38
39
|
|
|
39
|
-
- `get`: returns the current slot value.
|
|
40
|
-
- `isDefined`: returns boolean true when
|
|
40
|
+
- `get`: returns the current active slot value.
|
|
41
|
+
- `isDefined`: returns boolean true when an active response exists.
|
|
42
|
+
|
|
43
|
+
`isDefined` means only "this slot currently has an active answer." It never means a particular answer
|
|
44
|
+
such as Yes, selected, eligible, consented, or has children. When the user's condition names or
|
|
45
|
+
implies a choice, inspect the source choice item's exact option ids and labels, then compare the
|
|
46
|
+
`get` response with that option's reference using `eq` (single choice) or `list_contains`
|
|
47
|
+
(multiple choice). Do not substitute `isDefined` merely because the exact option id is not yet
|
|
48
|
+
known.
|
|
49
|
+
|
|
50
|
+
Visibility dependencies must be acyclic. The runtime rejects self-reference, mutual
|
|
51
|
+
question dependencies, parent groups controlled by their descendants, and cycles through
|
|
52
|
+
conditional components or computed scores. Prefills do not make these cycles valid.
|
|
53
|
+
Use an independent controlling answer or serialized custom context value. A component may
|
|
54
|
+
reference another slot in the same item only when its active value does not depend on that
|
|
55
|
+
component's visibility. Repair rejected changes using the returned retry linkage.
|
|
56
|
+
|
|
57
|
+
Hidden answers remain stored for the session and return when shown again, but are unavailable
|
|
58
|
+
to expressions, validation, scoring and submission while hidden. `get` returns undefined and
|
|
59
|
+
`isDefined` returns false for an inactive answer. This includes hidden groups, matrix rows,
|
|
60
|
+
form groups, hidden choice options and unselected embedded fields. Display conditions with
|
|
61
|
+
undefined or non-boolean results hide their target. Visibility cannot use `customExpression`
|
|
62
|
+
callbacks; supply serialized `customValue` context instead.
|
|
41
63
|
|
|
42
64
|
Never invent response refs. Use the current context response-slots scope or item details.
|
|
43
65
|
This rule is item-type independent: preserve every item id, slot id, component/validation key,
|
|
@@ -55,13 +77,12 @@ in its `create-item.item` object in one `survey_change` call. When a genuine dep
|
|
|
55
77
|
separate calls, inspect the updated request-scoped draft and use `survey_expression` against the
|
|
56
78
|
newly available ids and response slots.
|
|
57
79
|
|
|
58
|
-
Each response slot
|
|
59
|
-
`<sourceItemId>...get...<slotId>`, with a boolean presence check at
|
|
60
|
-
`<sourceItemId>...isDefined...<slotId>`. Use the slot's actual value type to choose the
|
|
80
|
+
Each declared response slot is available as `{ "slotId": "<slotId>", "method": "get" }`, with a presence check using the same slot ID and `method: "isDefined"`. Use the slot's actual value type to choose the
|
|
61
81
|
function and constant. For example, a single-choice `reference` slot uses `eq` with a
|
|
62
82
|
`reference` const; this is only one typed case, not a restriction on source item types.
|
|
63
83
|
Always check the response slot value type before choosing a function:
|
|
64
84
|
|
|
85
|
+
- Consent items return `boolean` in their persistent `config.slotId`; compare with `eq` and boolean `true` for agreement or `false` for refusal. Unanswered is neither. `isDefined` means either decision was recorded. Display conditions hide dependent content while retaining session answers; hidden items are omitted from submission.
|
|
65
86
|
- Single-choice choice items return `reference`; compare them with `eq` and a `reference` const.
|
|
66
87
|
- Multiple-choice choice items return `reference[]`; check selected options with `list_contains` and a `reference` const.
|
|
67
88
|
- `list_contains` must receive `string[]` + `string` or `reference[]` + `reference`. Never use it with a single `reference` response.
|
|
@@ -75,7 +96,26 @@ List containment: `list_contains`.
|
|
|
75
96
|
Equality/comparison: `eq`, `gt`, `gte`, `lt`, `lte`, `in_range`.
|
|
76
97
|
Numeric aggregation: `sum`, `min`, `max`.
|
|
77
98
|
String equality: `str_eq`.
|
|
78
|
-
|
|
99
|
+
Calendar dates use `YYYY`, `YYYY-MM`, or `YYYY-MM-DD`; numeric timestamps and date-time strings are invalid. Preserve the answer's precision.
|
|
100
|
+
|
|
101
|
+
Date comparisons: `date_eq`, `date_gt`, `date_gte`, `date_lt`, `date_lte` (two date arguments).
|
|
102
|
+
Equality includes precision; ordering requires matching precision and returns undefined otherwise.
|
|
103
|
+
`date_min` / `date_max` take one or more dates of matching precision and return a date.
|
|
104
|
+
`date_add_days`, `date_add_months`, `date_add_years` take a date and a signed integer number.
|
|
105
|
+
Offsets retain precision; month/year offsets clamp to the last day of the destination month.
|
|
106
|
+
Nonzero day offsets require full dates, nonzero month offsets require at least month precision.
|
|
107
|
+
`date_diff(a, b)` returns signed `a - b`, in days for full dates, months for month values,
|
|
108
|
+
or years for year values. Both arguments must have matching precision. Missing arguments' values
|
|
109
|
+
propagate undefined; do not use timestamps or divide by seconds to calculate calendar differences.
|
|
110
|
+
|
|
111
|
+
Form and form-matrix `minDate` / `maxDate` rules can use `valueExpression` instead of `value`.
|
|
112
|
+
Use a date response reference or date arithmetic expression. For example, a latest date seven days
|
|
113
|
+
after another answer uses `date_add_days(responseVariable(...), const(number, 7))`.
|
|
114
|
+
Use the form-field or matrix configuration operation to set these field rules. The normal expression
|
|
115
|
+
operations remain appropriate for item validations, prefills, and display conditions.
|
|
116
|
+
Bounds are inclusive: minimum uses the start of its calendar period, maximum uses its end.
|
|
117
|
+
The entire answer period must fit within the bound. An unanswered optional date remains valid;
|
|
118
|
+
a supplied answer with an unresolved bound fails validation until the source is available.
|
|
79
119
|
|
|
80
120
|
Example: show an item when option "yes" is selected on choice item q1:
|
|
81
121
|
|
|
@@ -84,8 +124,20 @@ Example: show an item when option "yes" is selected on choice item q1:
|
|
|
84
124
|
"type": "function",
|
|
85
125
|
"functionName": "eq",
|
|
86
126
|
"arguments": [
|
|
87
|
-
{
|
|
88
|
-
|
|
127
|
+
{
|
|
128
|
+
"type": "responseVariable",
|
|
129
|
+
"variableRef": {
|
|
130
|
+
"slotId": "q1",
|
|
131
|
+
"method": "get"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"type": "const",
|
|
136
|
+
"value": {
|
|
137
|
+
"type": "reference",
|
|
138
|
+
"value": "yes"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
89
141
|
]
|
|
90
142
|
}
|
|
91
143
|
```
|
|
@@ -97,8 +149,20 @@ Example: multiple-select contains option "apple" when the inspected response slo
|
|
|
97
149
|
"type": "function",
|
|
98
150
|
"functionName": "list_contains",
|
|
99
151
|
"arguments": [
|
|
100
|
-
{
|
|
101
|
-
|
|
152
|
+
{
|
|
153
|
+
"type": "responseVariable",
|
|
154
|
+
"variableRef": {
|
|
155
|
+
"slotId": "q2",
|
|
156
|
+
"method": "get"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"type": "const",
|
|
161
|
+
"value": {
|
|
162
|
+
"type": "reference",
|
|
163
|
+
"value": "apple"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
102
166
|
]
|
|
103
167
|
}
|
|
104
168
|
```
|
|
@@ -113,91 +177,175 @@ raw item, never inside `config` or `translations`.
|
|
|
113
177
|
[
|
|
114
178
|
{
|
|
115
179
|
"kind": "create-item",
|
|
116
|
-
"target": {
|
|
180
|
+
"target": {
|
|
181
|
+
"parentItemId": "<parent-group-id>"
|
|
182
|
+
},
|
|
117
183
|
"item": {
|
|
118
184
|
"id": "routing_choice",
|
|
119
|
-
"key": "routing_choice",
|
|
120
185
|
"itemType": "choiceItem",
|
|
121
186
|
"config": {
|
|
122
187
|
"id": "routing_choice",
|
|
123
188
|
"maxSelection": 1,
|
|
124
189
|
"shuffleOptions": false,
|
|
125
190
|
"options": [
|
|
126
|
-
{
|
|
127
|
-
|
|
128
|
-
|
|
191
|
+
{
|
|
192
|
+
"id": "option_a",
|
|
193
|
+
"code": "option_a"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "option_b",
|
|
197
|
+
"code": "option_b"
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
"variableName": "routing_choice"
|
|
129
201
|
}
|
|
130
202
|
},
|
|
131
203
|
"translations": [
|
|
132
|
-
{
|
|
133
|
-
|
|
134
|
-
|
|
204
|
+
{
|
|
205
|
+
"locale": "en",
|
|
206
|
+
"contentKey": "title",
|
|
207
|
+
"plainText": "Choose an option"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"locale": "en",
|
|
211
|
+
"contentKey": "options.option_a.label",
|
|
212
|
+
"plainText": "Option A"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"locale": "en",
|
|
216
|
+
"contentKey": "options.option_b.label",
|
|
217
|
+
"plainText": "Option B"
|
|
218
|
+
}
|
|
135
219
|
]
|
|
136
220
|
},
|
|
137
221
|
{
|
|
138
222
|
"kind": "create-item",
|
|
139
|
-
"target": {
|
|
223
|
+
"target": {
|
|
224
|
+
"parentItemId": "<parent-group-id>"
|
|
225
|
+
},
|
|
140
226
|
"item": {
|
|
141
227
|
"id": "follow_up_a",
|
|
142
|
-
"key": "follow_up_a",
|
|
143
228
|
"itemType": "choiceItem",
|
|
144
229
|
"config": {
|
|
145
230
|
"id": "follow_up_a",
|
|
146
231
|
"maxSelection": 1,
|
|
147
232
|
"shuffleOptions": false,
|
|
148
233
|
"options": [
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
234
|
+
{
|
|
235
|
+
"id": "yes",
|
|
236
|
+
"code": "yes"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"id": "no",
|
|
240
|
+
"code": "no"
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
"variableName": "follow_up_a"
|
|
152
244
|
},
|
|
153
245
|
"displayConditions": {
|
|
154
246
|
"root": {
|
|
155
247
|
"type": "function",
|
|
156
248
|
"functionName": "eq",
|
|
157
249
|
"arguments": [
|
|
158
|
-
{
|
|
159
|
-
|
|
250
|
+
{
|
|
251
|
+
"type": "responseVariable",
|
|
252
|
+
"variableRef": {
|
|
253
|
+
"slotId": "routing_choice",
|
|
254
|
+
"method": "get"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"type": "const",
|
|
259
|
+
"value": {
|
|
260
|
+
"type": "reference",
|
|
261
|
+
"value": "option_a"
|
|
262
|
+
}
|
|
263
|
+
}
|
|
160
264
|
]
|
|
161
265
|
}
|
|
162
266
|
}
|
|
163
267
|
},
|
|
164
268
|
"translations": [
|
|
165
|
-
{
|
|
166
|
-
|
|
167
|
-
|
|
269
|
+
{
|
|
270
|
+
"locale": "en",
|
|
271
|
+
"contentKey": "title",
|
|
272
|
+
"plainText": "Follow-up for option A"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"locale": "en",
|
|
276
|
+
"contentKey": "options.yes.label",
|
|
277
|
+
"plainText": "Yes"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"locale": "en",
|
|
281
|
+
"contentKey": "options.no.label",
|
|
282
|
+
"plainText": "No"
|
|
283
|
+
}
|
|
168
284
|
]
|
|
169
285
|
},
|
|
170
286
|
{
|
|
171
287
|
"kind": "create-item",
|
|
172
|
-
"target": {
|
|
288
|
+
"target": {
|
|
289
|
+
"parentItemId": "<parent-group-id>"
|
|
290
|
+
},
|
|
173
291
|
"item": {
|
|
174
292
|
"id": "follow_up_b",
|
|
175
|
-
"key": "follow_up_b",
|
|
176
293
|
"itemType": "choiceItem",
|
|
177
294
|
"config": {
|
|
178
295
|
"id": "follow_up_b",
|
|
179
296
|
"maxSelection": 1,
|
|
180
297
|
"shuffleOptions": false,
|
|
181
298
|
"options": [
|
|
182
|
-
{
|
|
183
|
-
|
|
184
|
-
|
|
299
|
+
{
|
|
300
|
+
"id": "yes",
|
|
301
|
+
"code": "yes"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"id": "no",
|
|
305
|
+
"code": "no"
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"variableName": "follow_up_b"
|
|
185
309
|
},
|
|
186
310
|
"displayConditions": {
|
|
187
311
|
"root": {
|
|
188
312
|
"type": "function",
|
|
189
313
|
"functionName": "eq",
|
|
190
314
|
"arguments": [
|
|
191
|
-
{
|
|
192
|
-
|
|
315
|
+
{
|
|
316
|
+
"type": "responseVariable",
|
|
317
|
+
"variableRef": {
|
|
318
|
+
"slotId": "routing_choice",
|
|
319
|
+
"method": "get"
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"type": "const",
|
|
324
|
+
"value": {
|
|
325
|
+
"type": "reference",
|
|
326
|
+
"value": "option_b"
|
|
327
|
+
}
|
|
328
|
+
}
|
|
193
329
|
]
|
|
194
330
|
}
|
|
195
331
|
}
|
|
196
332
|
},
|
|
197
333
|
"translations": [
|
|
198
|
-
{
|
|
199
|
-
|
|
200
|
-
|
|
334
|
+
{
|
|
335
|
+
"locale": "en",
|
|
336
|
+
"contentKey": "title",
|
|
337
|
+
"plainText": "Follow-up for option B"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"locale": "en",
|
|
341
|
+
"contentKey": "options.yes.label",
|
|
342
|
+
"plainText": "Yes"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"locale": "en",
|
|
346
|
+
"contentKey": "options.no.label",
|
|
347
|
+
"plainText": "No"
|
|
348
|
+
}
|
|
201
349
|
]
|
|
202
350
|
}
|
|
203
351
|
]
|
|
@@ -209,6 +357,10 @@ creates in this one operations array.
|
|
|
209
357
|
|
|
210
358
|
## survey_expression Mutations
|
|
211
359
|
|
|
360
|
+
The shapes below are the canonical mutations. Send the complete array once as `mutations`; the
|
|
361
|
+
server validates every entry against these canonical shapes before changing the request-scoped
|
|
362
|
+
draft.
|
|
363
|
+
|
|
212
364
|
Item visibility:
|
|
213
365
|
|
|
214
366
|
```json
|
|
@@ -219,8 +371,20 @@ Item visibility:
|
|
|
219
371
|
"type": "function",
|
|
220
372
|
"functionName": "eq",
|
|
221
373
|
"arguments": [
|
|
222
|
-
{
|
|
223
|
-
|
|
374
|
+
{
|
|
375
|
+
"type": "responseVariable",
|
|
376
|
+
"variableRef": {
|
|
377
|
+
"slotId": "q1",
|
|
378
|
+
"method": "get"
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"type": "const",
|
|
383
|
+
"value": {
|
|
384
|
+
"type": "reference",
|
|
385
|
+
"value": "yes"
|
|
386
|
+
}
|
|
387
|
+
}
|
|
224
388
|
]
|
|
225
389
|
}
|
|
226
390
|
}
|
|
@@ -277,10 +441,24 @@ Prefill shape:
|
|
|
277
441
|
```json
|
|
278
442
|
{
|
|
279
443
|
"id": "prefill-1",
|
|
280
|
-
"target": {
|
|
281
|
-
|
|
444
|
+
"target": {
|
|
445
|
+
"type": "itemResponse"
|
|
446
|
+
},
|
|
447
|
+
"when": {
|
|
448
|
+
"type": "const",
|
|
449
|
+
"value": {
|
|
450
|
+
"type": "boolean",
|
|
451
|
+
"value": true
|
|
452
|
+
}
|
|
453
|
+
},
|
|
282
454
|
"apply": "ifEmpty",
|
|
283
|
-
"source": {
|
|
455
|
+
"source": {
|
|
456
|
+
"type": "static",
|
|
457
|
+
"value": {
|
|
458
|
+
"type": "string",
|
|
459
|
+
"value": "x"
|
|
460
|
+
}
|
|
461
|
+
}
|
|
284
462
|
}
|
|
285
463
|
```
|
|
286
464
|
|
|
@@ -305,8 +483,20 @@ Template value shape:
|
|
|
305
483
|
{
|
|
306
484
|
"type": "default",
|
|
307
485
|
"returnType": "string",
|
|
308
|
-
"expression": {
|
|
486
|
+
"expression": {
|
|
487
|
+
"type": "const",
|
|
488
|
+
"value": {
|
|
489
|
+
"type": "string",
|
|
490
|
+
"value": "x"
|
|
491
|
+
}
|
|
492
|
+
}
|
|
309
493
|
}
|
|
310
494
|
```
|
|
311
495
|
|
|
312
496
|
Date formatting template values use `type: "date2string"`, `returnType: "string"`, and `dateFormat`.
|
|
497
|
+
|
|
498
|
+
## Bounded context and atomic batches
|
|
499
|
+
|
|
500
|
+
`survey_expression` action `context` filters response slots and expression locations with `itemIds` (exact persistent item IDs). Follow `nextCursor` with the same filter and `limit` until absent; restart after a draft mutation. The returned model text contains the actual page and distinguishes filtered totals from the survey-wide response-slot count. For a controlling question outside the filter, omit itemIds and cursor to retrieve the survey-wide catalog. Unresolved identifiers are reported explicitly, not as evidence that an item has no response.
|
|
501
|
+
|
|
502
|
+
A `prepare` mutation array is executed in order within one atomic delta. Later mutations see earlier additions, replacements, and removals, including new containers and shifted prefill indexes. If any mutation fails, none of the delta is staged. Retry all requested mutations from that rejected delta; `pendingRepairs` tracks every remaining operation and surface. For missing or invalid targets, use the indicated `retryOfChangeIds` with the complete corrected input. If an expression location is already empty, inspect and acknowledge that rejected request with a linked `survey_change` using `operations: []`; other identifiable pending edits remain required. Clearing a condition is not a repair of a requested condition change.
|
|
@@ -14,7 +14,7 @@ not a universal override of the user's request or an established survey conventi
|
|
|
14
14
|
|
|
15
15
|
1. **Presentation:** respondent-visible questions, instructions, and answer labels. These are
|
|
16
16
|
localized content and may be reworded.
|
|
17
|
-
2. **Stored identifiers and codes:** stable item and option identifiers,
|
|
17
|
+
2. **Stored identifiers and codes:** stable item and option identifiers, variable names, typed values,
|
|
18
18
|
and standard formats. These are for machines and should not depend on display language.
|
|
19
19
|
3. **Metadata:** definitions, labels for codes, units, data types, missing-value meanings, versions,
|
|
20
20
|
provenance, and mappings to standards. Meaning belongs here rather than being packed into a
|
|
@@ -22,13 +22,13 @@ not a universal override of the user's request or an established survey conventi
|
|
|
22
22
|
|
|
23
23
|
Do not use a respondent-visible label as though it were a stable stored code. Do not expose a raw
|
|
24
24
|
identifier as respondent wording. In CASE, visible item, option, field, and validation text belongs
|
|
25
|
-
in locale translations;
|
|
25
|
+
in locale translations; IDs, variable names, option codes, and response-slot references remain exact data.
|
|
26
26
|
|
|
27
|
-
## Identifiers and
|
|
27
|
+
## Identifiers and variable names
|
|
28
28
|
|
|
29
|
-
- Preserve stable internal ids and existing
|
|
29
|
+
- Preserve stable internal ids and existing variable names unless the user asks to change them. Never
|
|
30
30
|
silently repurpose an existing identifier when meaning changes.
|
|
31
|
-
- When FAIR
|
|
31
|
+
- When FAIR-oriented variable naming is relevant, start with a letter; use lowercase ASCII letters, digits,
|
|
32
32
|
and underscores; use `snake_case`; stay at or below 32 characters; avoid programming and
|
|
33
33
|
database reserved words; prefer a stable, language-neutral English concept name; reuse the same
|
|
34
34
|
concept name across waves and studies; use established instrument prefixes and sortable item
|
|
@@ -37,7 +37,7 @@ in locale translations; ids, keys, option values, and response-slot references r
|
|
|
37
37
|
metadata.
|
|
38
38
|
- For a standard instrument, preserve its established identity and predictable structure, such as
|
|
39
39
|
an instrument prefix plus a zero-padded item number, rather than inventing unrelated names.
|
|
40
|
-
- Choice option
|
|
40
|
+
- Choice option IDs and export codes should be stable and coding-friendly. Their localized labels
|
|
41
41
|
remain separate translations.
|
|
42
42
|
- Follow an explicit user-supplied identifier or established local convention when FAIR naming was
|
|
43
43
|
not requested. If a FAIR alternative would materially help, explain the tradeoff rather than
|
|
@@ -51,9 +51,7 @@ in locale translations; ids, keys, option values, and response-slot references r
|
|
|
51
51
|
- Reuse established code lists and formats when the task calls for interoperability: ISO 8601 for
|
|
52
52
|
dates, ISO 3166 for countries, ISO 639 for languages, UCUM for units, and appropriate domain
|
|
53
53
|
vocabularies such as LOINC or SNOMED CT when supported and relevant.
|
|
54
|
-
-
|
|
55
|
-
reasons. Never invent an ordinary numeric value such as `99` or `-9` that could be analyzed as a
|
|
56
|
-
real response unless the surrounding data model explicitly declares and documents it as missing.
|
|
54
|
+
- The current response envelope distinguishes typed answers from missing answers. It does not encode every missingness reason. Explain that limitation; do not claim skipped, refused, not asked and not applicable are automatically distinguishable. Explicit questionnaire options can represent such meanings when deliberately authored. Never conflate absent answers with zero, false, or an empty selection. Do not invent sentinel values.
|
|
57
55
|
- Do not invent CASE fields or ad hoc codes to simulate missing-value semantics that the installed
|
|
58
56
|
editor capabilities do not support. Explain the capability gap instead.
|
|
59
57
|
|
|
@@ -78,3 +76,5 @@ capabilities before changing existing identifiers, codes, values, or metadata. D
|
|
|
78
76
|
rewrite a survey merely because this reference was loaded. Apply the parts material to the user's
|
|
79
77
|
goal, state important tradeoffs, and identify platform-level FAIR requirements that remain outside
|
|
80
78
|
the editor.
|
|
79
|
+
|
|
80
|
+
These naming rules are CASE project conventions supporting FAIR practice, not requirements imposed by FAIR. Names alone do not make data FAIR; metadata, provenance, access, licensing and documented meaning remain necessary.
|