@case-framework/survey-assistant 0.8.0 → 0.9.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.
Files changed (114) hide show
  1. package/dist/{authoring-references-DbuOKerg.mjs → authoring-references-CmwLc_C8.mjs} +40 -32
  2. package/dist/authoring-references-CmwLc_C8.mjs.map +1 -0
  3. package/dist/capabilities-D55dq-fO.mjs +582 -0
  4. package/dist/capabilities-D55dq-fO.mjs.map +1 -0
  5. package/dist/capabilities-default.d.mts +4 -12
  6. package/dist/capabilities-default.d.mts.map +1 -1
  7. package/dist/capabilities-default.mjs +2 -2
  8. package/dist/capabilities-z95e1mti.d.mts +117 -0
  9. package/dist/capabilities-z95e1mti.d.mts.map +1 -0
  10. package/dist/{constants-B6HzpEsx.d.mts → constants-HL_klgJl.d.mts} +4 -4
  11. package/dist/{constants-B6HzpEsx.d.mts.map → constants-HL_klgJl.d.mts.map} +1 -1
  12. package/dist/{controller-proxy-DEeFl9IA.mjs → controller-proxy-BQ1YsVxJ.mjs} +4 -3
  13. package/dist/controller-proxy-BQ1YsVxJ.mjs.map +1 -0
  14. package/dist/{controller-proxy-D7uQfm5f.d.mts → controller-proxy-Cmzdr9tV.d.mts} +4 -4
  15. package/dist/{controller-proxy-D7uQfm5f.d.mts.map → controller-proxy-Cmzdr9tV.d.mts.map} +1 -1
  16. package/dist/default-D22AKTqE.mjs +233 -0
  17. package/dist/default-D22AKTqE.mjs.map +1 -0
  18. package/dist/{digest-C39WyAWG.d.mts → digest-FnTTDBq2.d.mts} +2 -2
  19. package/dist/digest-FnTTDBq2.d.mts.map +1 -0
  20. package/dist/digest.d.mts +1 -1
  21. package/dist/engine-D950TfvC.mjs +3098 -0
  22. package/dist/engine-D950TfvC.mjs.map +1 -0
  23. package/dist/engine.d.mts +4 -3
  24. package/dist/engine.mjs +3 -3
  25. package/dist/{index-WB5kfnz0.d.mts → index-B8TLBd1G.d.mts} +8 -6
  26. package/dist/index-B8TLBd1G.d.mts.map +1 -0
  27. package/dist/index-CaX3hZmr.d.mts +23813 -0
  28. package/dist/index-CaX3hZmr.d.mts.map +1 -0
  29. package/dist/{index-r5riv4md.d.mts → index-CeUlGkoU.d.mts} +27 -6
  30. package/dist/index-CeUlGkoU.d.mts.map +1 -0
  31. package/dist/{index-D7wT6P3t.d.mts → index-DYHdvSE8.d.mts} +83 -41
  32. package/dist/index-DYHdvSE8.d.mts.map +1 -0
  33. package/dist/lifecycle-DFzxVxpq.d.mts +54346 -0
  34. package/dist/lifecycle-DFzxVxpq.d.mts.map +1 -0
  35. package/dist/{memory-thread-repository-DAnOGIB3.mjs → memory-thread-repository-DmLadygY.mjs} +15 -9
  36. package/dist/{memory-thread-repository-DAnOGIB3.mjs.map → memory-thread-repository-DmLadygY.mjs.map} +1 -1
  37. package/dist/protocol-BQ7uIDYT.mjs +569 -0
  38. package/dist/protocol-BQ7uIDYT.mjs.map +1 -0
  39. package/dist/protocol.d.mts +4 -4
  40. package/dist/protocol.mjs +3 -2
  41. package/dist/{react-C_GY-Fsc.mjs → react-DybJ5pWw.mjs} +17 -11
  42. package/dist/react-DybJ5pWw.mjs.map +1 -0
  43. package/dist/react-integration.d.mts +1 -1
  44. package/dist/react-integration.mjs +1 -1
  45. package/dist/react.d.mts +2 -2
  46. package/dist/react.mjs +2 -2
  47. package/dist/references/assistant-operations.md +190 -215
  48. package/dist/references/core-rules.md +2 -2
  49. package/dist/references/element-types.md +189 -0
  50. package/dist/references/expressions.md +215 -238
  51. package/dist/references/follow-ups.md +151 -0
  52. package/dist/references/localization.md +26 -12
  53. package/dist/references/response-variables.md +3 -3
  54. package/dist/references/rich-text-content.md +22 -43
  55. package/dist/references/source-material-surveys.md +20 -25
  56. package/dist/references/survey-data-model.md +36 -117
  57. package/dist/{request-context-Dg4jSwN1.mjs → request-context-KVh8VjgH.mjs} +4 -4
  58. package/dist/request-context-KVh8VjgH.mjs.map +1 -0
  59. package/dist/server-agent.d.mts +28 -7
  60. package/dist/server-agent.d.mts.map +1 -1
  61. package/dist/server-agent.mjs +33 -25
  62. package/dist/server-agent.mjs.map +1 -1
  63. package/dist/server-runtime.d.mts +6 -5
  64. package/dist/server-runtime.d.mts.map +1 -1
  65. package/dist/server-runtime.mjs +3 -3
  66. package/dist/server-tasks.d.mts +1 -1
  67. package/dist/server-tasks.mjs +1 -1
  68. package/dist/server-tools.d.mts +1 -1
  69. package/dist/server-tools.mjs +1 -1
  70. package/dist/server.d.mts +7 -6
  71. package/dist/server.d.mts.map +1 -1
  72. package/dist/server.mjs +3 -3
  73. package/dist/{tasks-BZEiwgxA.mjs → tasks-Coh5N027.mjs} +16 -15
  74. package/dist/tasks-Coh5N027.mjs.map +1 -0
  75. package/dist/{tasks-B9h3LPam.d.mts → tasks-wb9M-bak.d.mts} +11 -11
  76. package/dist/{tasks-B9h3LPam.d.mts.map → tasks-wb9M-bak.d.mts.map} +1 -1
  77. package/dist/{thread-handlers-Bef0td9N.d.mts → thread-handlers-C3Iya92v.d.mts} +6 -5
  78. package/dist/thread-handlers-C3Iya92v.d.mts.map +1 -0
  79. package/dist/{tools-CEsv-WoO.mjs → tools-D0KBDolR.mjs} +435 -408
  80. package/dist/tools-D0KBDolR.mjs.map +1 -0
  81. package/dist/turn-survey-draft-B34lggSG.d.mts +185 -0
  82. package/dist/turn-survey-draft-B34lggSG.d.mts.map +1 -0
  83. package/dist/ui.d.mts +3 -3
  84. package/dist/ui.d.mts.map +1 -1
  85. package/dist/ui.mjs +35 -23
  86. package/dist/ui.mjs.map +1 -1
  87. package/package.json +7 -7
  88. package/dist/authoring-references-DbuOKerg.mjs.map +0 -1
  89. package/dist/capabilities-CmeeAjEc.d.mts +0 -192
  90. package/dist/capabilities-CmeeAjEc.d.mts.map +0 -1
  91. package/dist/capabilities-DCMA71PP.mjs +0 -58
  92. package/dist/capabilities-DCMA71PP.mjs.map +0 -1
  93. package/dist/controller-proxy-DEeFl9IA.mjs.map +0 -1
  94. package/dist/default-fhSon2RM.mjs +0 -760
  95. package/dist/default-fhSon2RM.mjs.map +0 -1
  96. package/dist/digest-C39WyAWG.d.mts.map +0 -1
  97. package/dist/engine-nXoCWYpQ.mjs +0 -6888
  98. package/dist/engine-nXoCWYpQ.mjs.map +0 -1
  99. package/dist/index-Ciq7vHIs.d.mts +0 -716
  100. package/dist/index-Ciq7vHIs.d.mts.map +0 -1
  101. package/dist/index-D7wT6P3t.d.mts.map +0 -1
  102. package/dist/index-WB5kfnz0.d.mts.map +0 -1
  103. package/dist/index-r5riv4md.d.mts.map +0 -1
  104. package/dist/lifecycle-Dm8u7QFh.d.mts +0 -545
  105. package/dist/lifecycle-Dm8u7QFh.d.mts.map +0 -1
  106. package/dist/protocol-CF4Bh_Ch.mjs +0 -1255
  107. package/dist/protocol-CF4Bh_Ch.mjs.map +0 -1
  108. package/dist/react-C_GY-Fsc.mjs.map +0 -1
  109. package/dist/references/embedded-forms.md +0 -146
  110. package/dist/references/item-types.md +0 -641
  111. package/dist/request-context-Dg4jSwN1.mjs.map +0 -1
  112. package/dist/tasks-BZEiwgxA.mjs.map +0 -1
  113. package/dist/thread-handlers-Bef0td9N.d.mts.map +0 -1
  114. package/dist/tools-CEsv-WoO.mjs.map +0 -1
@@ -1,145 +1,64 @@
1
- # Survey Data Model
1
+ # Survey data model
2
2
 
3
- ## RawSurvey
3
+ The current survey format is schema version **3**. The trusted installed registry supplies every element schema; inspect the current draft and focused operation contracts before constructing payloads. There are no legacy question wrappers or form modes.
4
4
 
5
- A survey JSON object has this shape:
5
+ ## Survey and flow
6
+
7
+ Keep `$schema` and `schemaVersion` unchanged. A survey has `surveyItems`, exactly one root `group`, and optional `maxItemsPerPage`, `metadata`, `templateValues`, `assets`, `translations` and `defaultLocale` (the source language; must be a `translations` key). Flow items are `content`, `group`, or `page-break`. Groups order child item IDs in `config.items`; they may shuffle children. A page break has empty config. Use `reorder-items` with the complete child list or `move-item` with an inspected destination.
8
+
9
+ Minimal survey document (for understanding the format, not for replacing an existing survey):
6
10
 
7
11
  ```json
8
12
  {
9
- "schemaVersion": 2,
10
13
  "$schema": "https://github.com/case-framework/case-survey-toolkit/packages/survey-core/schemas/survey-schema.json",
11
- "maxItemsPerPage": {
12
- "large": 1,
13
- "small": 1
14
- },
15
- "surveyItems": [],
16
- "assets": {},
17
- "metadata": {},
18
- "templateValues": {},
14
+ "schemaVersion": 3,
15
+ "surveyItems": [
16
+ {
17
+ "id": "root",
18
+ "itemType": "group",
19
+ "config": { "isRoot": true, "items": [], "shuffleItems": false }
20
+ }
21
+ ],
19
22
  "translations": {}
20
23
  }
21
24
  ```
22
25
 
23
- Required fields:
24
-
25
- - `$schema`: keep the current schema string; never remove or edit it.
26
- - `schemaVersion`: exactly `2`; never remove or edit it.
27
- - `surveyItems`: array of raw survey items.
28
-
29
- Optional fields:
30
-
31
- - `maxItemsPerPage`: object with numeric `large` and `small` page-size limits.
32
- - `metadata`: survey-level string map.
33
- - `templateValues`: reusable expression values; see expressions.md.
34
- - `assets`: image assets keyed by asset id.
35
- - `translations`: locale-keyed translated content.
36
-
37
- ## RawSurveyItem
38
-
39
- Minimal item shape:
40
-
41
- ```json
42
- {
43
- "id": "stable-unique-id",
44
- "itemType": "choiceItem",
45
- "config": {
46
- "variableName": "coding_key"
47
- }
48
- }
49
- ```
26
+ `surveyItems` is a flat list. Flow nesting is represented by the ordered child IDs in groups, not nested item objects. Every non-root item belongs to exactly one group. By contrast, elements, layouts, sections and follow-up bodies are nested directly inside their containing content item. Flow parent IDs and composition layout/body destinations are different kinds of targets; inspect the intended destination before editing.
50
27
 
51
- Conventions:
28
+ A content item has optional localized title, subtitle and footer, and `config.body`. It may contain one element (the common case) or several. An element preset inserted into the survey creates a content item containing that element; inserting into a layout adds it to that item. This is the same element definition, with no simple/custom mode transition.
52
29
 
53
- - `id` is globally unique and is the durable reference used by groups, translations, response slots, expressions, and patches.
54
- - Items have no `key`. Inspection resolves `editorName` and `breadcrumb` for discovery; both may be duplicated and neither is an identity. Mutations take exact item IDs.
55
- - Response slots have separate persistent IDs and survey-wide unique `variableName` coding names. See response-variables.md.
56
- - `itemType` must exist in the current editor registry.
30
+ ## Composition
57
31
 
58
- Identifier rules apply to every built-in and custom item type:
32
+ A body is `{ "blocks": [...] }`. Each block is either:
59
33
 
60
- - Keep inspected identifiers byte-for-byte exact when displaying, explaining, comparing, or
61
- reusing them. Do not replace separators, split camelCase, change capitalization, or substitute
62
- visible labels.
63
- - Choose new IDs and variable names for stable data roles, not the current wording or position. Avoid names
64
- such as `question_about_apples` or suffixes such as `q1`; labels and question text can change
65
- without changing durable identities.
66
- - Do not silently derive one configured identifier from another. If a required identifier is
67
- omitted and a typed operation generates it, inspect the result before using it in another
68
- reference.
69
- - Custom item response slots come from that item's registered capability. Preserve their exact
70
- slot ids just like built-in slots.
34
+ - A layout: `{ "kind": "layout", "id": "layout-id", "layout": { "mode": "automatic", "maxColumns": 2 }, "elements": [...] }`.
35
+ - A semantic section: `{ "kind": "section", "id": "section-id", "body": { "blocks": [...] } }`.
71
36
 
72
- Optional fields:
37
+ Sections take the full width and structure the body vertically. A section cannot sit in a layout alongside elements, nor contain another section. Its title may be empty while drafting but should be supplied for a useful semantic grouping. Follow-up bodies may also contain sections. No follow-up may contain another follow-up, including through sections or custom elements.
73
38
 
74
- - `metadata`: string map. `metadata.itemLabel` is the internal editor label, not respondent-visible text. `metadata.editorItemColor` stores the editor item color as a hex string such as `#0369a1`.
75
- - `config`: item-type-specific configuration. Many item types need config; simple structural/content items can be sparse.
76
- - `validations`: map of validation key to `JsonExpression`.
77
- - `displayConditions`: item/root and component display expressions.
78
- - `disabledConditions`: component disabled expressions.
79
- - `prefills`: configured prefill rules; see expressions.md.
39
+ Layout columns align across rows. Automatic `maxColumns` is an upper bound: available space, minimum element widths and full-width controls determine the actual count. Advanced mode specifies `columns` at `base`, `xs`, `sm`, `md`, and `xl`; use it only for deliberate breakpoint requirements. Elements may set `placement.width` to `auto` or `full` and `placement.minWidthRem`. Radio and checkbox lists, matrices, information and consent require a full row. Dropdowns can share a row and cannot own inline follow-ups.
80
40
 
81
- ## Tree Structure
41
+ An element has `kind: "element"`, `id`, `elementType`, and registered `config`, plus optional `visibility`, `disabled`, `placement`, `exportSettings` and `prefills`. Conditions also belong directly to applicable structural owners, including items, sections and options. No condition means visible/enabled. Inspect declared owners before editing a condition.
82
42
 
83
- There must be exactly one root group:
43
+ ## Identity and content
84
44
 
85
- ```json
86
- {
87
- "itemType": "group",
88
- "config": {
89
- "isRoot": true,
90
- "items": [],
91
- "shuffleItems": false
92
- }
93
- }
94
- ```
45
+ IDs are survey-wide stable identities, independent of labels, layout, position, variable names and export codes. Preserve inspected identifiers byte-for-byte. Never infer an ID from a name or humanize it when reusing it. Duplicate editor names are legal. Choose fresh IDs for new owners and slots; preserve them when moving or translating. Custom slots come from the installed definition, not naming guesses.
95
46
 
96
- Groups order children by id in `config.items`. Use `reorder-items` with the exact parent ID and the complete child-ID list.
47
+ - Items have no `key`. Inspection resolves `editorName` and `breadcrumb` for discovery; neither is an identity. Mutations take exact IDs.
48
+ - Choose new IDs and variable names for stable data roles, not current wording or position. Avoid names such as `question_about_apples` or positional suffixes such as `q1`: labels and order can change without changing durable identities.
49
+ - Do not silently derive one configured identifier from another. When a preset or typed operation generates IDs, inspect its result before using them in another reference.
50
+ - Custom element response slots come from that element's registered capability. Preserve their exact slot IDs just like built-in slots; do not assume that an element ID is also its slot ID.
97
51
 
98
- ## Translations And Content
52
+ Element settings and prefills are keyed by its declared slot IDs. Cross-input validation rules live in the content item's `config.validationRules` and target slots in that item. A cross-item move must respect the explicit rule-transfer contract; do not detach referenced targets through raw patches.
99
53
 
100
- Visible text is stored under translations, not usually in item config:
54
+ Respondent content lives at `translations[locale].content[ownerId][role]`. Owners include the item, section, element, option, row, column and validation rule, as declared by their schemas. A move does not relocate translation keys. Use exact localization refs from inspection:
101
55
 
102
56
  ```json
103
- {
104
- "translations": {
105
- "en": {
106
- "itemTranslations": {
107
- "<itemId>": {
108
- "title": {
109
- "type": "md",
110
- "content": "Question text"
111
- }
112
- }
113
- },
114
- "surveyCardContent": {},
115
- "navigationContent": {},
116
- "validationMessages": {}
117
- }
118
- }
119
- }
57
+ { "scope": "content", "ownerId": "option-other", "role": "label" }
120
58
  ```
121
59
 
122
- Content values may be:
123
-
124
- - `{ "type": "md", "content": "Text" }`
125
- - `{ "type": "plain", "content": "Plain text" }`
126
- - `{ "type": "richText", "version": 1, "doc": { "type": "doc", "blocks": [...] } }`
127
-
128
- Important:
129
-
130
- - `md` and `plain` content are rendered as plain text with line breaks. Markdown syntax such as `# Heading`, `**bold**`, or `- item` is not parsed into formatting.
131
- - For unformatted text, use typed translation operations with `plainText`.
132
- - For formatted content on a surface documented as rendering rich text, use typed translation operations. The model-facing `richTextBlocks` shorthand normalizes to canonical richText `content` wherever the typed translation accepts structured `content`, but structural acceptance alone does not guarantee formatted rendering. See rich-text-content.md.
133
- - If the user asks for another language or the source material is clearly in another language, write respondent-visible translations under that locale code. A translation operation may introduce a missing locale; do not store Dutch, German, French, etc. text under `en` just because `en` exists.
134
-
135
- Common item content keys:
60
+ The item roles are `title`, `subtitle`, `footer`; section roles are `title`, `description`. Element and component roles come from capabilities. Survey wording uses `{ "scope": "survey", "surface": "navigationContent", "contentKey": "..." }`; inspect existing or declared keys.
136
61
 
137
- - `title`: question title or group/page title.
138
- - `subtitle`: question subtitle.
139
- - `topContent`: content before the response controls.
140
- - `bottomContent`: content after the response controls.
141
- - `cardFooter`: footer inside the question card.
142
- - `content`: info item body.
62
+ Content is plain text (`plain` or `md`, both rendered without Markdown parsing) or canonical `richText`. Use `update-content` with a ref, locale and exactly one of `plainText` or `content`; `content: null` clears a surface. Rich-text shorthand is normalized before validation. See rich-text-content for supported formatting. Never replace a translation container to edit a leaf, and never put target-language text under the wrong locale.
143
63
 
144
- JSON Patch paths are relative to the survey document root. Do not prefix paths with `/survey`.
145
- Escape JSON Pointer segments: `/` becomes `~1`, `~` becomes `~0`.
64
+ Item `metadata.itemLabel` and `metadata.editorItemColor` are editor-only. Coding names are also separate from respondent translations. JSON Pointer paths are rooted at the survey, without `/survey`; escape `~` as `~0` and `/` as `~1`. Inspect paths instead of guessing array indexes.
@@ -1,6 +1,6 @@
1
- import { V as surveyAssistantSnapshotPayloadSchema, W as surveyDocumentVersionSchema, o as surveyAssistantApplyOutcomeSchema } from "./protocol-CF4Bh_Ch.mjs";
2
- import { ht as createSurveyAssistantEngineContext } from "./engine-nXoCWYpQ.mjs";
3
- import { a as defaultSurveyAssistantCapabilitySet } from "./default-fhSon2RM.mjs";
1
+ import { G as surveyDocumentVersionSchema, H as surveyAssistantSnapshotPayloadSchema, o as surveyAssistantApplyOutcomeSchema } from "./protocol-BQ7uIDYT.mjs";
2
+ import { et as createSurveyAssistantEngineContext } from "./engine-D950TfvC.mjs";
3
+ import { n as defaultSurveyAssistantCapabilitySet } from "./default-D22AKTqE.mjs";
4
4
  import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
5
5
  //#region src/server/request-context.ts
6
6
  const parseSurveyAssistantSnapshot = (value) => {
@@ -82,4 +82,4 @@ const requireSurveyAssistantTurnState = (requestContext) => {
82
82
  //#endregion
83
83
  export { parseSurveyAssistantPreviousSettledVersion as a, parseSurveyAssistantPreviousApplyOutcome as i, deriveSurveyAssistantDocumentTransition as n, parseSurveyAssistantSnapshot as o, getSurveyAssistantEngineContext as r, requireSurveyAssistantTurnState as s, buildSurveyAssistantRequestContext as t };
84
84
 
85
- //# sourceMappingURL=request-context-Dg4jSwN1.mjs.map
85
+ //# sourceMappingURL=request-context-KVh8VjgH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context-KVh8VjgH.mjs","names":[],"sources":["../src/server/request-context.ts"],"sourcesContent":["import {\n MASTRA_RESOURCE_ID_KEY,\n MASTRA_THREAD_ID_KEY,\n RequestContext,\n} from \"@mastra/core/request-context\";\nimport type { OpenAICompatibleConfig } from \"@mastra/core/llm\";\nimport type { AgentExecutionOptions } from \"@mastra/core/agent\";\nimport {\n surveyAssistantSnapshotPayloadSchema,\n surveyAssistantApplyOutcomeSchema,\n surveyDocumentVersionSchema,\n type SurveyAssistantApplyOutcome,\n type SurveyDocumentSnapshot,\n type SurveyDocumentVersion,\n} from \"../protocol\";\nimport {\n createSurveyAssistantEngineContext,\n type SurveyAssistantEngineContext,\n} from \"../engine/context\";\nimport type { TurnSurveyDraft } from \"../engine/turn-survey-draft\";\nimport type { SurveyAssistantCapabilitySet } from \"../engine/capabilities\";\nimport { defaultSurveyAssistantCapabilitySet } from \"../capabilities/default\";\nimport type {\n SurveyAssistantAttachmentAccess,\n SurveyAssistantModelAttachment,\n} from \"./thread-documents\";\n\nexport interface SurveyAssistantIdentityContext {\n authority: \"experimental-client-request\" | \"authenticated-host\";\n resourceId: string;\n surveyId?: string;\n threadId: string;\n}\n\nexport interface SurveyAssistantModelSelection {\n id: string;\n model: string | OpenAICompatibleConfig;\n providerName?: string;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n}\n\nexport type SurveyAssistantDocumentTransition =\n | { status: \"no-baseline\" }\n | {\n status: \"session-changed\";\n previousHistoryIndex: number;\n currentHistoryIndex: number;\n }\n | {\n status: \"unchanged\";\n previousHistoryIndex: number;\n currentHistoryIndex: number;\n capabilitiesChanged: boolean;\n }\n | {\n status: \"changed\";\n previousHistoryIndex: number;\n currentHistoryIndex: number;\n historyDirection: \"backward\" | \"forward\" | \"same-index\";\n recordedSources: Array<\"user\" | \"system\" | \"assistant\">;\n capabilitiesChanged: boolean;\n };\n\nexport interface SurveyAssistantRequestContext {\n turnId: string;\n turnDraft: TurnSurveyDraft;\n identity: SurveyAssistantIdentityContext;\n mastra__resourceId?: string;\n mastra__threadId?: string;\n documentTransition?: SurveyAssistantDocumentTransition;\n engineContext?: SurveyAssistantEngineContext;\n modelAttachments?: SurveyAssistantModelAttachment[];\n attachmentAccess?: SurveyAssistantAttachmentAccess;\n modelSelection?: SurveyAssistantModelSelection;\n previousApplyOutcome?: SurveyAssistantApplyOutcome;\n}\n\nexport const parseSurveyAssistantSnapshot = (value: unknown): SurveyDocumentSnapshot | null => {\n if (value === undefined || value === null) {\n return null;\n }\n\n return surveyAssistantSnapshotPayloadSchema.parse(value);\n};\n\nexport const parseSurveyAssistantPreviousSettledVersion = (\n value: unknown,\n): SurveyDocumentVersion | null => {\n if (value === undefined || value === null) {\n return null;\n }\n\n return surveyDocumentVersionSchema.parse(value);\n};\n\nexport const parseSurveyAssistantPreviousApplyOutcome = (\n value: unknown,\n): SurveyAssistantApplyOutcome | null => {\n if (value === undefined || value === null) {\n return null;\n }\n\n return surveyAssistantApplyOutcomeSchema.parse(value);\n};\n\nexport const deriveSurveyAssistantDocumentTransition = ({\n current,\n previous,\n}: {\n current: SurveyDocumentSnapshot | null;\n previous: SurveyDocumentVersion | null;\n}): SurveyAssistantDocumentTransition | undefined => {\n if (!current) return undefined;\n if (!previous) return { status: \"no-baseline\" };\n\n const previousHistoryIndex = previous.historyIndex;\n const currentHistoryIndex = current.version.historyIndex;\n if (previous.sessionId !== current.version.sessionId) {\n return {\n status: \"session-changed\",\n previousHistoryIndex,\n currentHistoryIndex,\n };\n }\n\n const capabilitiesChanged = previous.capabilityDigest !== current.version.capabilityDigest;\n if (previous.contentHash === current.version.contentHash) {\n return {\n status: \"unchanged\",\n previousHistoryIndex,\n currentHistoryIndex,\n capabilitiesChanged,\n };\n }\n\n const historyDirection =\n currentHistoryIndex > previousHistoryIndex\n ? \"forward\"\n : currentHistoryIndex < previousHistoryIndex\n ? \"backward\"\n : \"same-index\";\n const recordedSources =\n historyDirection === \"forward\"\n ? [\n ...new Set(\n (current.ui.history?.recent ?? [])\n .filter(\n (entry) => entry.index > previousHistoryIndex && entry.index <= currentHistoryIndex,\n )\n .flatMap((entry) => (entry.source ? [entry.source] : [])),\n ),\n ]\n : [];\n\n return {\n status: \"changed\",\n previousHistoryIndex,\n currentHistoryIndex,\n historyDirection,\n recordedSources,\n capabilitiesChanged,\n };\n};\n\nexport const buildSurveyAssistantRequestContext = ({\n turnDraft,\n identity,\n snapshot,\n previousSettledVersion = null,\n trustedCapabilities = defaultSurveyAssistantCapabilitySet,\n attachmentAccess,\n modelAttachments = [],\n modelSelection,\n previousApplyOutcome,\n}: {\n turnDraft: TurnSurveyDraft;\n identity: SurveyAssistantIdentityContext;\n snapshot: SurveyDocumentSnapshot | null;\n previousSettledVersion?: SurveyDocumentVersion | null;\n trustedCapabilities?: SurveyAssistantCapabilitySet;\n attachmentAccess?: SurveyAssistantAttachmentAccess;\n modelAttachments?: SurveyAssistantModelAttachment[];\n modelSelection?: SurveyAssistantModelSelection;\n previousApplyOutcome?: SurveyAssistantApplyOutcome | null;\n}): RequestContext<SurveyAssistantRequestContext> => {\n const requestContext = new RequestContext<SurveyAssistantRequestContext>();\n\n requestContext.set(\"turnId\", turnDraft.turnId);\n requestContext.set(\"turnDraft\", turnDraft);\n requestContext.set(\"identity\", identity);\n requestContext.set(MASTRA_RESOURCE_ID_KEY, identity.resourceId);\n requestContext.set(MASTRA_THREAD_ID_KEY, identity.threadId);\n const documentTransition = deriveSurveyAssistantDocumentTransition({\n current: snapshot,\n previous: previousSettledVersion,\n });\n if (documentTransition) {\n requestContext.set(\"documentTransition\", documentTransition);\n }\n if (attachmentAccess && attachmentAccess.documents.length > 0) {\n requestContext.set(\"attachmentAccess\", attachmentAccess);\n }\n if (modelAttachments.length > 0) {\n requestContext.set(\"modelAttachments\", modelAttachments);\n }\n if (modelSelection) {\n requestContext.set(\"modelSelection\", modelSelection);\n }\n if (previousApplyOutcome) {\n requestContext.set(\"previousApplyOutcome\", previousApplyOutcome);\n }\n\n if (!snapshot) {\n return requestContext;\n }\n\n const engineContext = createSurveyAssistantEngineContext(snapshot, trustedCapabilities);\n turnDraft.initialize(engineContext);\n requestContext.set(\"engineContext\", engineContext);\n\n return requestContext;\n};\n\n/**\n * Returns the materialized request-local survey state. The immutable\n * engineContext remains available as the turn baseline, while every tool uses\n * this accessor so successful same-turn mutations are immediately visible.\n */\nexport const getSurveyAssistantEngineContext = (\n requestContext: RequestContext<SurveyAssistantRequestContext> | undefined,\n): SurveyAssistantEngineContext | undefined =>\n requestContext?.get(\"turnDraft\")?.context ?? requestContext?.get(\"engineContext\");\n\nexport const requireSurveyAssistantTurnState = (\n requestContext: RequestContext<SurveyAssistantRequestContext> | undefined,\n) => {\n const turnId = requestContext?.get(\"turnId\");\n const turnDraft = requestContext?.get(\"turnDraft\");\n if (!turnId || !turnDraft || turnDraft.turnId !== turnId) {\n throw new Error(\"Survey assistant turn context is unavailable or inconsistent.\");\n }\n\n return { turnId, turnDraft };\n};\n"],"mappings":";;;;;AA6EA,MAAa,gCAAgC,UAAkD;CAC7F,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO;CAGT,OAAO,qCAAqC,MAAM,KAAK;AACzD;AAEA,MAAa,8CACX,UACiC;CACjC,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO;CAGT,OAAO,4BAA4B,MAAM,KAAK;AAChD;AAEA,MAAa,4CACX,UACuC;CACvC,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO;CAGT,OAAO,kCAAkC,MAAM,KAAK;AACtD;AAEA,MAAa,2CAA2C,EACtD,SACA,eAImD;CACnD,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,IAAI,CAAC,UAAU,OAAO,EAAE,QAAQ,cAAc;CAE9C,MAAM,uBAAuB,SAAS;CACtC,MAAM,sBAAsB,QAAQ,QAAQ;CAC5C,IAAI,SAAS,cAAc,QAAQ,QAAQ,WACzC,OAAO;EACL,QAAQ;EACR;EACA;CACF;CAGF,MAAM,sBAAsB,SAAS,qBAAqB,QAAQ,QAAQ;CAC1E,IAAI,SAAS,gBAAgB,QAAQ,QAAQ,aAC3C,OAAO;EACL,QAAQ;EACR;EACA;EACA;CACF;CAGF,MAAM,mBACJ,sBAAsB,uBAClB,YACA,sBAAsB,uBACpB,aACA;CAcR,OAAO;EACL,QAAQ;EACR;EACA;EACA;EACA,iBAjBA,qBAAqB,YACjB,CACE,GAAG,IAAI,KACJ,QAAQ,GAAG,SAAS,UAAU,CAAC,EAAA,CAC7B,QACE,UAAU,MAAM,QAAQ,wBAAwB,MAAM,SAAS,mBAClE,CAAC,CACA,SAAS,UAAW,MAAM,SAAS,CAAC,MAAM,MAAM,IAAI,CAAC,CAAE,CAC5D,CACF,IACA,CAAC;EAQL;CACF;AACF;AAEA,MAAa,sCAAsC,EACjD,WACA,UACA,UACA,yBAAyB,MACzB,sBAAsB,qCACtB,kBACA,mBAAmB,CAAC,GACpB,gBACA,2BAWmD;CACnD,MAAM,iBAAiB,IAAI,eAA8C;CAEzE,eAAe,IAAI,UAAU,UAAU,MAAM;CAC7C,eAAe,IAAI,aAAa,SAAS;CACzC,eAAe,IAAI,YAAY,QAAQ;CACvC,eAAe,IAAI,wBAAwB,SAAS,UAAU;CAC9D,eAAe,IAAI,sBAAsB,SAAS,QAAQ;CAC1D,MAAM,qBAAqB,wCAAwC;EACjE,SAAS;EACT,UAAU;CACZ,CAAC;CACD,IAAI,oBACF,eAAe,IAAI,sBAAsB,kBAAkB;CAE7D,IAAI,oBAAoB,iBAAiB,UAAU,SAAS,GAC1D,eAAe,IAAI,oBAAoB,gBAAgB;CAEzD,IAAI,iBAAiB,SAAS,GAC5B,eAAe,IAAI,oBAAoB,gBAAgB;CAEzD,IAAI,gBACF,eAAe,IAAI,kBAAkB,cAAc;CAErD,IAAI,sBACF,eAAe,IAAI,wBAAwB,oBAAoB;CAGjE,IAAI,CAAC,UACH,OAAO;CAGT,MAAM,gBAAgB,mCAAmC,UAAU,mBAAmB;CACtF,UAAU,WAAW,aAAa;CAClC,eAAe,IAAI,iBAAiB,aAAa;CAEjD,OAAO;AACT;;;;;;AAOA,MAAa,mCACX,mBAEA,gBAAgB,IAAI,WAAW,CAAC,EAAE,WAAW,gBAAgB,IAAI,eAAe;AAElF,MAAa,mCACX,mBACG;CACH,MAAM,SAAS,gBAAgB,IAAI,QAAQ;CAC3C,MAAM,YAAY,gBAAgB,IAAI,WAAW;CACjD,IAAI,CAAC,UAAU,CAAC,aAAa,UAAU,WAAW,QAChD,MAAM,IAAI,MAAM,+DAA+D;CAGjF,OAAO;EAAE;EAAQ;CAAU;AAC7B"}
@@ -1,6 +1,6 @@
1
- import { g as SurveyChangeSetShape } from "./lifecycle-Dm8u7QFh.mjs";
2
- import { o as SurveyAssistantRequestContext, t as SURVEY_ASSISTANT_AGENT_ID } from "./constants-B6HzpEsx.mjs";
3
- import { n as surveyAssistantTools } from "./index-r5riv4md.mjs";
1
+ import { g as SurveyChangeSetShape } from "./lifecycle-DFzxVxpq.mjs";
2
+ import { o as SurveyAssistantRequestContext, t as SURVEY_ASSISTANT_AGENT_ID } from "./constants-HL_klgJl.mjs";
3
+ import { n as surveyAssistantTools } from "./index-CeUlGkoU.mjs";
4
4
  import { Agent, AgentConfig } from "@mastra/core/agent";
5
5
  import { Memory } from "@mastra/memory";
6
6
  import { InputProcessor } from "@mastra/core/processors";
@@ -25,12 +25,24 @@ export interface CreateSurveyAssistantAgentOptions {
25
25
  }
26
26
  export declare const createSurveyAssistantAgent: ({ memory, model, observationalMemory }: CreateSurveyAssistantAgentOptions) => Agent<"survey-assistant-agent", Readonly<{
27
27
  survey_inspect: import("@mastra/core/tools").Tool<{
28
- action: "current-context" | "search-items" | "item-details" | "localization" | "assets" | "expression-diagnostics" | "raw-json";
28
+ action: "localization" | "current-context" | "search-items" | "item-details" | "assets" | "expression-diagnostics" | "raw-json";
29
29
  reason?: string | undefined;
30
30
  scopes?: ("summary" | "selected-item" | "outline" | "response-slots" | "ui-context" | "history")[] | undefined;
31
31
  query?: string | undefined;
32
+ itemTypes?: ("content" | "group" | "page-break")[] | undefined;
33
+ elementTypes?: string[] | undefined;
34
+ locales?: string[] | undefined;
32
35
  sourceLocale?: string | undefined;
33
36
  targetLocale?: string | undefined;
37
+ localizationRefs?: ({
38
+ scope: "content";
39
+ ownerId: string;
40
+ role: string;
41
+ } | {
42
+ scope: "survey";
43
+ surface: "surveyCardContent" | "navigationContent" | "validationMessages";
44
+ contentKey: string;
45
+ })[] | undefined;
34
46
  missingOnly?: boolean | undefined;
35
47
  itemRef?: string | undefined;
36
48
  cursor?: string | undefined;
@@ -42,7 +54,7 @@ export declare const createSurveyAssistantAgent: ({ memory, model, observational
42
54
  limit?: number | undefined;
43
55
  }, {
44
56
  ok: boolean;
45
- action: "current-context" | "search-items" | "item-details" | "localization" | "assets" | "expression-diagnostics" | "raw-json";
57
+ action: "localization" | "current-context" | "search-items" | "item-details" | "assets" | "expression-diagnostics" | "raw-json";
46
58
  modelSummary: string;
47
59
  reason?: string | undefined;
48
60
  result?: unknown;
@@ -54,7 +66,7 @@ export declare const createSurveyAssistantAgent: ({ memory, model, observational
54
66
  }, SurveyChangeSetShape, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "survey_change", unknown>;
55
67
  survey_authoring_reference: import("@mastra/core/tools").Tool<{
56
68
  topic: string;
57
- itemType?: string | undefined;
69
+ elementType?: string | undefined;
58
70
  operationKind?: string | undefined;
59
71
  detail?: "full" | "compact" | undefined;
60
72
  reason?: string | undefined;
@@ -63,7 +75,7 @@ export declare const createSurveyAssistantAgent: ({ memory, model, observational
63
75
  topic: string;
64
76
  title: string;
65
77
  content: string;
66
- itemType?: string | undefined;
78
+ elementType?: string | undefined;
67
79
  operationKind?: string | undefined;
68
80
  detail?: "full" | "compact" | undefined;
69
81
  }, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "survey_authoring_reference", unknown>;
@@ -95,6 +107,15 @@ export declare const createSurveyAssistantAgent: ({ memory, model, observational
95
107
  totalResponseSlots?: number | undefined;
96
108
  surveyResponseSlotCount?: number | undefined;
97
109
  totalExpressionLocations?: number | undefined;
110
+ totalStateTargets?: number | undefined;
111
+ stateTargets?: {
112
+ targetRef: {
113
+ ownerId: string;
114
+ };
115
+ state: "disabled";
116
+ itemId: string;
117
+ kind: string;
118
+ }[] | undefined;
98
119
  unresolvedItemIds?: string[] | undefined;
99
120
  expressionLocations?: {
100
121
  itemId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"server-agent.d.mts","names":[],"sources":["../src/server/agent.ts"],"mappings":";;;;;;;qBAyBa,0CAA0C;KAoUlD,6BAA6B,mBACzB,kCACA,iCAEP;KAGG,+BAA+B,YAClC,YAAY,6BAA6B;YA8E/B,4CAA4C,QACtD;KAIG,iDAAiD,QACpD,KAAK;EAEL,OAAO,YAAY;;qBAGR;;;;;qBAMA,oDAAmD,OAAA,aAAA,eAAA,aAK7D,mDAAiD;iBAkCnC;EACf,OAAO;EACP,SAAS;EACT,sBAAsB;;qBAGX,+BAA8B,QAAA,OAAA,uBAIxC,sCAAiC,gCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAAjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eA2BC,4DAAA"}
1
+ {"version":3,"file":"server-agent.d.mts","names":[],"sources":["../src/server/agent.ts"],"mappings":";;;;;;;qBAyBa,0CAA0C;KA8VlD,6BAA6B,mBACzB,kCACA,iCAEP;KAGG,+BAA+B,YAClC,YAAY,6BAA6B;YA8E/B,4CAA4C,QACtD;KAIG,iDAAiD,QACpD,KAAK;EAEL,OAAO,YAAY;;qBAGR;;;;;qBAMA,oDAAmD,OAAA,aAAA,eAAA,aAK7D,mDAAiD;iBAkCnC;EACf,OAAO;EACP,SAAS;EACT,sBAAsB;;qBAGX,+BAA8B,QAAA,OAAA,uBAIxC,sCAAiC,gCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAAjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eA2BC,4DAAA"}
@@ -1,8 +1,8 @@
1
- import { a as getDeterministicCreateItemTypes } from "./capabilities-DCMA71PP.mjs";
1
+ import { c as getDeterministicCreateElementTypes } from "./default-D22AKTqE.mjs";
2
2
  import { t as SURVEY_ASSISTANT_AGENT_ID } from "./constants-Ct-vv9cu.mjs";
3
- import { n as formatSurveyAuthoringReferenceRoutingInstructions } from "./authoring-references-DbuOKerg.mjs";
3
+ import { n as formatSurveyAuthoringReferenceRoutingInstructions } from "./authoring-references-CmwLc_C8.mjs";
4
4
  import { t as FAIR_BY_DESIGN_REFERENCE_ROUTING_INSTRUCTION } from "./fair-guidance-BmO4PswW.mjs";
5
- import { n as surveyAssistantTools, t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-CEsv-WoO.mjs";
5
+ import { n as surveyAssistantTools, t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-D0KBDolR.mjs";
6
6
  import { createHash } from "node:crypto";
7
7
  import { Agent } from "@mastra/core/agent";
8
8
  import { Memory } from "@mastra/memory";
@@ -83,22 +83,27 @@ const formatCurrentEditorContext = (snapshot) => {
83
83
  entry.label ? `label=${entry.label}` : void 0,
84
84
  entry.details ? `details=${entry.details}` : void 0
85
85
  ].filter(Boolean).join("; ")).join(", ") ?? "none";
86
+ const task = snapshot.ui.task;
87
+ const taskData = task?.data;
88
+ const localizationTarget = task?.kind.startsWith("localization.") && taskData && typeof taskData === "object" && !Array.isArray(taskData) && typeof taskData.targetLocale === "string" ? taskData.targetLocale : void 0;
89
+ const removedTaskLocale = localizationTarget && !snapshot.survey.translations?.[localizationTarget];
90
+ const launchedTask = task ? [
91
+ `kind=${task.kind}`,
92
+ task.title ? `title=${task.title}` : void 0,
93
+ task.instructions ? `instructions=${task.instructions}` : void 0,
94
+ task.data !== void 0 ? `data=${JSON.stringify(task.data)}` : void 0
95
+ ].filter(Boolean).join("; ") : void 0;
86
96
  const history = snapshot.ui.history;
87
97
  const currentHistoryEntry = history?.recent.find((entry) => entry.isCurrent);
88
98
  const surveyKey = snapshot.inspection.surveyKey ?? "not set";
89
99
  const locales = snapshot.inspection.locales.length > 0 ? snapshot.inspection.locales.join(", ") : "none";
90
- const deterministicCreateItemTypes = getDeterministicCreateItemTypes(snapshot.capabilities);
100
+ const deterministicCreateItemTypes = getDeterministicCreateElementTypes(snapshot.capabilities);
91
101
  const creatableItemTypes = deterministicCreateItemTypes.length > 0 ? deterministicCreateItemTypes.join(", ") : "none";
92
102
  const rootItem = snapshot.inspection.outline.find((item) => item.depth === 0);
93
103
  const rootItemDescription = rootItem ? JSON.stringify({ parentItemId: rootItem.itemId }) : "not found in the inspection outline";
94
- const itemTypeDetails = snapshot.capabilities.itemTypes.length > 0 ? snapshot.capabilities.itemTypes.map((entry) => {
95
- const primaryContentKey = entry.contentSurfaces.find((surface) => surface.role === "primary")?.key;
96
- const details = [
97
- `create=${entry.create}`,
98
- primaryContentKey ? `primary=${primaryContentKey}` : void 0,
99
- entry.authoring?.compactHint
100
- ].filter((value) => Boolean(value)).join("; ");
101
- return details ? `${entry.itemType} (${details})` : entry.itemType;
104
+ const itemTypeDetails = snapshot.capabilities.elementTypes.length > 0 ? snapshot.capabilities.elementTypes.map((entry) => {
105
+ const details = [`create=${entry.create}`, entry.authoring?.compactHint].filter((value) => Boolean(value)).join("; ");
106
+ return details ? `${entry.elementType} (${details})` : entry.elementType;
102
107
  }).join(", ") : "none";
103
108
  return [
104
109
  "Use this live editor snapshot as the authoritative current survey state for this turn.",
@@ -111,6 +116,8 @@ const formatCurrentEditorContext = (snapshot) => {
111
116
  `Active UI surface: ${snapshot.ui.activeSurface ?? "not provided"}`,
112
117
  `Open UI panels: ${snapshot.ui.openPanels?.join(", ") ?? "not provided"}`,
113
118
  `Highlighted UI targets: ${highlights}`,
119
+ ...launchedTask ? [`UI-launched task (structured parameters of the user's original request; retained for follow-up turns even if the UI selection changes. The visible message may only summarize them. Use these exact values for continuation unless the user explicitly changes the task in a later message): ${launchedTask}`] : [],
120
+ ...removedTaskLocale ? [`The retained localization task targets ${JSON.stringify(localizationTarget)}, which is no longer a registered survey locale. Do not silently recreate a removed language from this old task. Ask whether to restore it before writing, unless the current user message explicitly requests adding or restoring that language.`] : [],
114
121
  `History state: ${history ? `index=${history.currentIndex}; total=${history.totalEntries}; canUndo=${history.canUndo}; canRedo=${history.canRedo}; currentAction=${currentHistoryEntry?.label ?? "not available"}` : "not provided"}`,
115
122
  `Selected locale: ${snapshot.ui.selectedLocale}`,
116
123
  `Survey key: ${surveyKey}`,
@@ -118,8 +125,8 @@ const formatCurrentEditorContext = (snapshot) => {
118
125
  `Survey locales: ${locales}`,
119
126
  `Survey item count (excluding the structural root group): ${snapshot.inspection.itemCount}`,
120
127
  "Current-state completion rule: never claim that an edit request is already satisfied from conversation or observational memory. Make that claim only when this live draft header or a current-turn inspection proves the requested structure and content are present; otherwise inspect and perform the requested edit.",
121
- `Deterministically creatable item types: ${creatableItemTypes}`,
122
- `Installed item capabilities (compact): ${itemTypeDetails}. Load a composed assistant-operations reference with operationKind and itemType for supported operations, configuration, content surfaces, and focused authoring guidance.`
128
+ `Deterministically creatable element types: ${creatableItemTypes}`,
129
+ `Installed element capabilities (compact): ${itemTypeDetails}. Load a composed assistant-operations reference with operationKind and elementType for supported operations, configuration, content surfaces, and focused authoring guidance.`
123
130
  ].filter((line) => Boolean(line)).join("\n");
124
131
  };
125
132
  const formatDocumentTransition = (transition) => {
@@ -176,31 +183,32 @@ const buildInstructions = ({ requestContext }) => {
176
183
  "Infer whether the user wants an answer, explanation, critique, clarification, or concrete edit from their message and current editor context. Keep routine answers concise.",
177
184
  "Reply in the language of the user's current message unless they request another language. Respondent-facing survey text follows the requested survey locale, which may differ from the reply language.",
178
185
  "Authority order: the request-scoped survey draft and inspection tools define current turn state; the submitted snapshot is its immutable baseline and apply precondition; the capability manifest defines installed item behavior; authoring references define stable CASE conventions; Mastra memory is conversational history only.",
179
- "The capability manifest is authoritative for available item types, create modes, supported operations, content surfaces, response slots, and capability-owned references. Never guess unsupported item behavior.",
186
+ "The capability manifest is authoritative for installed element types, presets, supported operations, content roles, response slots, and capability-owned references. Never guess unsupported element behavior.",
180
187
  "Never claim that an item type, field type, controller, operation, or other editor capability is unavailable unless the current capability manifest or a loaded authoring reference explicitly excludes it. For a capability question, inspect or load the focused reference before answering; if support remains unclear, say that it is unverified rather than unsupported.",
181
- "For an installed custom item type, use survey_authoring_reference with both itemType and one of its advertised reference topics before creating or changing unfamiliar config. Use survey_inspect item-details to obtain capability-provided inspection details for existing items.",
182
- `Use ${INSPECT_TOOL_NAME} to inspect current draft context, UI context/highlights, recent editor history, search, item details, localization surfaces, image assets, expression-reference diagnostics, complete paged outlines, response slots, and exact raw JSON paths. Successful same-turn edits are immediately visible there. Use action "expression-diagnostics" before and after a survey-wide reference repair; it returns exact owning items, expression locations, invalid refs or option values, bounded replacement candidates, and each diagnostic's blocking or advisory disposition, category, and guidance. Repair blocking diagnostics. Review advisory diagnostics according to their category-specific guidance without changing them automatically. Use action "localization" to page source-locale respondent content and see which target-locale surfaces are missing; it covers survey-level and item-level translation maps without one item-details call per item. Use action "assets" to obtain explicit assetId values, metadata, and usage locations before asset changes; the key of /assets/<key> is the asset ID even though the stored asset object does not repeat it. Never guess what "this", "here", or "the highlighted part" refers to when the draft can resolve it. History explains recent actions but the current draft remains authoritative within the turn.`,
183
- "For any survey review, audit, defect check, or request to spot issues, run survey_audit before answering. Apply its key-semantic-consistency principle to the returned key/content evidence; for a comprehensive audit, page keyReviewOffset until all key-review evidence has been reviewed. Its deterministic logic findings distinguish blocking expression defects from advisory diagnostics. When it reports an expression-reference finding, use survey_inspect action expression-diagnostics for exact locations, disposition, category, guidance, and current replacement candidates. Do not describe blocking defects as resolved while they remain; report advisories separately and follow their category-specific guidance.",
188
+ "For unfamiliar built-in authoring, load element-types focused on the elementType; its worked examples and behavioral guidance complement the generated payload contract. In particular, load consent or matrix guidance before drafting their content or editing their structure. For an installed custom element type, use survey_authoring_reference with both elementType and one of its advertised reference topics before creating or changing unfamiliar config. Use survey_inspect item-details to obtain capability-provided inspection details for existing items.",
189
+ `Use ${INSPECT_TOOL_NAME} to inspect current draft context, UI context/highlights, recent editor history, search, item details, localization surfaces, image assets, expression-reference diagnostics, complete paged outlines, response slots, and exact raw JSON paths. Successful same-turn edits are immediately visible there. Use action "expression-diagnostics" before and after a survey-wide reference repair; it returns located diagnostics with codes, severity and guidanceByCode. Error severity is blocking; warnings are advisory. Inspect response slots and owner IDs to identify the intended replacement rather than guessing a reference from its spelling. Repair blocking diagnostics. Review advisory diagnostics according to their category-specific guidance without changing them automatically. Use action "localization" to page source-locale respondent content and see which target-locale surfaces are missing; it covers survey-level and item-level translation maps without one item-details call per item. Use action "assets" to obtain explicit assetId values, metadata, and usage locations before asset changes; the key of /assets/<key> is the asset ID even though the stored asset object does not repeat it. Never guess what "this", "here", or "the highlighted part" refers to when the draft can resolve it. History explains recent actions but the current draft remains authoritative within the turn.`,
190
+ "For any survey review, audit, defect check, or request to spot issues, run survey_audit before answering. Apply its key-semantic-consistency principle to the returned key/content evidence; for a comprehensive audit, page keyReviewOffset until all key-review evidence has been reviewed. Its deterministic logic findings distinguish blocking expression defects from advisory diagnostics. When it reports an expression-reference finding, use survey_inspect action expression-diagnostics for exact locations, severity, code and guidance; inspect the relevant slots and owners for replacement candidates. Do not describe blocking defects as resolved while they remain; report advisories separately and follow their category-specific guidance.",
191
+ "Authors may leave broken references (blocking invalid-reference diagnostics) while restructuring a survey; they block publication until repaired. Your changes never leave broken references: when you delete or replace referenced content, first update or clear its dependent conditions, rules and prefills with survey_expression in the same turn, then make the change, and report what you changed. Repair broken references the author left when the request concerns them or the user asks, and mention remaining ones in audits; do not guess a replacement from spelling.",
184
192
  `Use ${AUTHORING_REFERENCE_TOOL_NAME} to load focused stable authoring conventions and payload contracts.`,
185
193
  formatSurveyAuthoringReferenceRoutingInstructions(),
186
194
  FAIR_BY_DESIGN_REFERENCE_ROUTING_INSTRUCTION,
187
195
  `Use ${AUDIT_TOOL_NAME} for read-only deterministic technical checks and a structured questionnaire-quality review rubric. For quality feedback, combine its exact findings with survey-quality and inspect the relevant wording and flow. Clearly distinguish technical defects, design recommendations, and claims that would require cognitive testing or psychometric evidence.`,
188
196
  `Use ${CHANGE_TOOL_NAME} for typed survey operations and ${EXPRESSION_TOOL_NAME} for expressions. Prefer typed operations; use one inspected survey-json-patch operation only when no typed operation covers the requested field.`,
189
- `The typed ${CHANGE_TOOL_NAME} operations cover item structure/content/config, choices, forms, survey content, and assets. For an unfamiliar operation shape, load assistant-operations with operationKind and, when targeting an item type, itemType to receive a compact composed contract. Request full contract detail only for protocol debugging. Omit operationKind only when broader conventions are needed. Reorders replace the complete inspected list and use optionIds, groupIds, or itemIds as documented by the tool.`,
197
+ `The typed ${CHANGE_TOOL_NAME} operations cover survey flow, element composition/configuration, owner-role content, layout, response settings and assets. For an unfamiliar operation shape, load assistant-operations with operationKind and, when targeting an element type, elementType to receive a compact composed contract. Request full contract detail only for protocol debugging. Omit operationKind only when broader conventions are needed. Flow reorders use the complete inspected itemIds list; use shared element/block move operations within composition.`,
190
198
  "Survey languages are locale branches. An unqualified request to \"add a German localization\", \"add German\", or translate/localize the survey means make the existing respondent-facing content available in that language; an empty locale registration alone is incomplete. Inspect action \"localization\", translate every requested surface, and let the first real typed translation introduce an absent locale. Use add-survey-locale only when the user explicitly asks to register an empty language before content exists. When the user asks to remove or delete a survey language, use remove-survey-locale with the exact existing locale code; it destructively removes every survey-level and item-level translation stored for that locale. Load the focused assistant-operations contract before an explicit locale lifecycle change. Never substitute dummy translations, translation-by-translation deletion, or a raw patch.",
191
199
  "An unqualified request to add or change a survey item or question label means the editor-only item label and uses update-item-label. A question title/text, option label, or field label is respondent-visible translated content.",
192
- "A group is a hierarchy/container, not a decorative heading. Use a group for meaningful nested structure, an info item for standalone explanatory content, and a page break when only a respondent page boundary is needed. Create a non-root group empty, then create its children in parent-before-child order.",
200
+ "A group is a hierarchy/container, not a decorative heading. Use a group for meaningful nested structure, an information element in a content item for standalone explanatory content, and a page break when only a respondent page boundary is needed. Create a non-root group empty, then create its children in parent-before-child order.",
193
201
  "Write respondent-visible content under its actual locale. A real typed translation may introduce a missing locale; never place target-language text under an existing wrong locale or create dummy content merely to introduce a locale.",
194
202
  "Use plainText for ordinary unformatted copy. Load rich-text-content and use structured richText only for meaningful headings, lists, emphasis, links, images, info boxes, or other formatting on a surface documented as rendering rich text. For complete formatted values on those surfaces, prefer the compact richTextBlocks shorthand described there; use a full content.doc tree for structures the shorthand does not cover. A typed field accepting structured content does not by itself guarantee that its renderer preserves formatting. Markdown syntax inside md/plain content is not rendered as rich formatting.",
195
203
  "Do not refuse an edit merely because no narrow typed operation exists. Inspect the exact current raw item/path and use survey-json-patch for assistant-editable survey fields that have no typed or expression helper.",
196
- "A choice free-text follow-up such as Other, please specify is an option embeddedForm, not allowOther. For a newly created choiceItem, put the option and its embeddedForm directly in create-item. Default authoringMode to simple when the embedded form has exactly one supported field in one ordinary single-column group; use custom only for blank, multi-field, multi-group, conditional, or layout-customized follow-ups. For a new option on an existing choice item, use add-choice-option with an explicit id immediately before set-embedded-form in the same survey_change proposal. Load embedded-forms and use set-embedded-form with relative translations for existing choice options. Use a raw patch only when the typed operations cannot express the requested change.",
197
- "Survey schema version 2 separates persistent item/slot IDs from editor names and response variable names. Mutations use exact IDs; search resolves duplicated names and breadcrumbs to candidates. Expression references are {slotId, method: get|isDefined}. Load response-variables before response naming, matrix coding, option-code or export-format work; use update-response-settings for atomic coding edits. Labels, translations and moves preserve response identities and names.",
198
- "For choiceItem, maxSelection 1 is single choice, null is unlimited multiple choice, and a positive number is capped multiple choice. Choice config options use IDs, export codes and configuration; respondent-visible option labels belong in translations at options.<optionId>.label.",
199
- "Every form or embedded-form select option needs a visible translation. Do not rely on raw controller values as respondent labels.",
204
+ "For Other, please specify, use a radio/checkbox option followUp body directly below that option. It contains ordinary layouts, elements and optional semantic sections; no nested follow-ups. Dropdowns have no follow-up bodies: use a separately conditional element. Create new options, bodies and owner-role translations atomically, or inspect existing config and use patch-element-config. Load follow-ups for the contract.",
205
+ "Survey schema version 3 separates flow items (content/group/page-break), composable elements and persistent response slots. Use exact owner and slot IDs; editor names and breadcrumbs are discovery aids. For an ordinary request to add a question, create a new content item containing one element, including for custom element types. Use insert-preset with parentItemId when an advertised preset fits; otherwise use create-item with the complete content-item body. Add elements to an existing layout when the requested composition or placement calls for it. Load response-variables before naming, matrix coding, option-code or export work; use update-response-settings for atomic coding edits. Moves, labels and translations preserve response identities and names.",
206
+ "Choice presentation is radio, checkbox or dropdown. Only checkbox has maxSelection (null for unlimited, positive for a cap). Option labels belong to translations[locale].content[optionId].label; IDs, codes and labels are distinct. Every option and input needs usable localized content, including dropdowns and follow-ups.",
207
+ "Disabled active answers are retained, readable in expressions and submitted. Hidden answers are retained only in session storage and excluded from active expressions/submission. Use visibility for inapplicability and disabling for locking. Disabled checkboxes cannot be ticked or unticked; a disabled radio/dropdown selection can be replaced by an enabled option. Author expression-based exclusivity so the selected side stays enabled. Audit checkbox locks driven by other answers and conflicting prefills. isDisabled includes ancestors; selected-and-enabled shortcuts are expanded expressions and can create dependency cycles.",
200
208
  "When the user asks to implement or convert supplied source material, completeness is part of the task. Load source-material-surveys and implement coherent bounded chunks without sampling or silently omitting difficult respondent content.",
201
209
  `Use the attachment identities next to the current user message to distinguish currentMessageUploads from earlierConversationAttachments. When the user compares "this/new file" with earlier PDFs, the current upload is the subject and the earlier files are the comparison candidates; do not compare the current upload with itself. These are per-message roles, not document creation dates. A broad comparison may use sufficiently detailed descriptions already in the conversation. Load an earlier original with ${ATTACHMENT_TOOL_NAME} when exact wording, detailed differences, uncertain facts, or source-faithful authoring require it; conversational memory is not a lossless copy. Use only the needed document ids and provide documentRequests with a reading focus when known. Current uploads are supplied directly; successfully loaded originals are included in the next model input. Read those files directly, respect unavailable results, and do not ask for extracted text or re-upload of an available source.`,
202
210
  `Use ${ASSET_TOOL_NAME} to import an attached image into the turn draft without copying base64 through ${CHANGE_TOOL_NAME}, and to update or remove unreferenced image-asset metadata. A successful import makes its asset id available to later mutation calls in the same turn. To delete referenced images and their assets together, make one ${CHANGE_TOOL_NAME} call containing the reference-removal operations first and remove-image-asset last. Never import an image merely because it is attached; do so only when the user asks to use it as survey content.`,
203
- "For branching, conditions, expression validations, prefills, and template values, use survey_expression with exact inspected response refs and value types. Creation-time expressions may also be embedded directly in create-item.",
211
+ "For branching, conditions, expression validations, prefills, and template values, use survey_expression with exact inspected response refs and value types. Creation-time expressions may be included in new item/element payloads. Prefills initialize once in new sessions, including hidden/disabled/closed-follow-up targets, and never rerun on resume or while editing answers.",
204
212
  `Mutation tools maintain one request-scoped draft. Each successful call adds only its new delta, and later calls may target ids or assets created by earlier successful calls. The live editor remains unchanged during the response. Successful turn completion authorizes only the latest cumulative draft, which the editor applies as one undoable change.`,
205
213
  "A rejected mutation leaves the validated request-local draft unchanged and blocks turn authorization. Correct the same rejected target in another mutation call; unrelated valid edits do not clear the block. If the response ends while any rejection remains unresolved, none of the turn's prepared changes reach the live editor. In that case, never describe request-local draft content as present in the editor; state that no changes from the turn were applied. Never drop requested behavior merely to obtain validation.",
206
214
  "Current exposed tools and their current outputs are authoritative for what this response can do. Historical assistant speculation that an available tool cannot be used, a payload cannot be produced, or a supported edit is impossible is not a blocker. Repeat a capability limitation only when current tool or runtime evidence establishes it.",