@sema-agent/client-core 0.98.0 → 0.99.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 (192) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +35 -22
  3. package/dist/adapt/arms.js +61 -20
  4. package/dist/adapt/panelTasks.d.ts +1 -1
  5. package/dist/adapt/panelTasks.js +2 -2
  6. package/dist/adapter/activeRunSelfHeal.d.ts +4 -3
  7. package/dist/adapter/activeRunSelfHeal.js +162 -293
  8. package/dist/adapter/downstream/eventToSdkMessage.js +52 -4
  9. package/dist/adapter/runStream.js +52 -37
  10. package/dist/adapter/types.js +2 -1
  11. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  12. package/dist/agentsWireCaps.d.ts +0 -3
  13. package/dist/agentsWireCaps.js +33 -24
  14. package/dist/cloudConfigWireCaps.d.ts +1 -1
  15. package/dist/cloudConfigWireCaps.js +26 -4
  16. package/dist/controlRouter.d.ts +4 -2
  17. package/dist/controlRouter.js +39 -51
  18. package/dist/coreValuePorts.d.ts +26 -1
  19. package/dist/coreValuePorts.js +10 -0
  20. package/dist/corruptSessionCopy.d.ts +2 -1
  21. package/dist/corruptSessionCopy.js +3 -3
  22. package/dist/declared/supportFloorDeclared.js +1 -1
  23. package/dist/detachWire.js +3 -2
  24. package/dist/devicesFace.d.ts +34 -0
  25. package/dist/devicesFace.js +90 -0
  26. package/dist/displayUntrusted.d.ts +1 -0
  27. package/dist/displayUntrusted.js +3 -0
  28. package/dist/engineAgentPanelStore.d.ts +7 -0
  29. package/dist/engineAgentPanelStore.js +14 -0
  30. package/dist/engineCapReader.d.ts +2 -1
  31. package/dist/engineCapReader.js +7 -5
  32. package/dist/engineCapsCache.d.ts +8 -0
  33. package/dist/engineCapsCache.js +59 -6
  34. package/dist/engineCapsChange.d.ts +2 -0
  35. package/dist/engineCapsChange.js +9 -0
  36. package/dist/engineErrorCodes.d.ts +2 -1
  37. package/dist/engineErrorCodes.js +2 -7
  38. package/dist/engineRowRef.js +3 -0
  39. package/dist/engineSessionMessages.d.ts +1 -0
  40. package/dist/engineSessionMessages.js +7 -1
  41. package/dist/engineTargetSeat.d.ts +27 -0
  42. package/dist/engineTargetSeat.js +199 -0
  43. package/dist/engineWireFor.js +3 -8
  44. package/dist/env/uiLanguage.d.ts +2 -1
  45. package/dist/env/uiLanguage.js +3 -2
  46. package/dist/eventLeg.d.ts +8 -0
  47. package/dist/eventLeg.js +61 -41
  48. package/dist/fileHistoryCaptureCapability.d.ts +2 -1
  49. package/dist/fileHistoryCaptureCapability.js +12 -18
  50. package/dist/fileHistoryLegNotice.d.ts +2 -1
  51. package/dist/fileHistoryLegNotice.js +3 -3
  52. package/dist/frameBinding.d.ts +3 -0
  53. package/dist/frameBinding.js +12 -0
  54. package/dist/gateOutcome.js +16 -2
  55. package/dist/gateVocabulary.d.ts +8 -7
  56. package/dist/gateVocabulary.js +71 -73
  57. package/dist/generated/engineFactTables.d.ts +17 -1
  58. package/dist/generated/engineFactTables.js +29 -0
  59. package/dist/generated/engineNoticeTables.js +9 -3
  60. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  61. package/dist/generated/settingsSchemaFns.js +57 -0
  62. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  63. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  64. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  65. package/dist/generated/settingsSchemaTables.js +4 -0
  66. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  67. package/dist/generated/settingsSchemaTypes.js +1 -0
  68. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  69. package/dist/hitl/allowRuleShadow.js +17 -14
  70. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  71. package/dist/hitl/approvalCardReasons.js +27 -28
  72. package/dist/hitl/approvalHolds.d.ts +3 -0
  73. package/dist/hitl/approvalHolds.js +73 -29
  74. package/dist/hitl/askClassPair.d.ts +1 -1
  75. package/dist/hitl/askClassPair.js +16 -0
  76. package/dist/hitl/askGateWire.js +2 -1
  77. package/dist/hitl/askSettlementLine.d.ts +14 -4
  78. package/dist/hitl/askSettlementLine.js +67 -47
  79. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  80. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  81. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  82. package/dist/hitl/crashConvergedNotice.js +28 -41
  83. package/dist/hitl/frameRouter.js +7 -8
  84. package/dist/hitl/hitlBridge.d.ts +1 -0
  85. package/dist/hitl/hitlBridge.js +3 -3
  86. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  87. package/dist/hitl/persistedRulesWire.js +55 -73
  88. package/dist/hitl/planReviewWire.d.ts +5 -0
  89. package/dist/hitl/planReviewWire.js +8 -0
  90. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  91. package/dist/hitl/sessionPolicyDeliverable.js +46 -3
  92. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  93. package/dist/hitl/sessionPolicyWire.js +23 -24
  94. package/dist/hitl/suspendedReopen.d.ts +2 -1
  95. package/dist/hitl/suspendedReopen.js +7 -10
  96. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  97. package/dist/hitl/toolApprovalWire.js +79 -40
  98. package/dist/hooksWireCaps.js +145 -56
  99. package/dist/host.d.ts +21 -0
  100. package/dist/hostTurnSettings.d.ts +71 -0
  101. package/dist/hostTurnSettings.js +291 -0
  102. package/dist/humanTurn.d.ts +14 -1
  103. package/dist/humanTurn.js +100 -12
  104. package/dist/humanTurnRead.d.ts +2 -0
  105. package/dist/humanTurnRead.js +22 -1
  106. package/dist/i18n/messages.en.d.ts +582 -0
  107. package/dist/i18n/messages.en.js +582 -0
  108. package/dist/i18n/messages.zh.js +718 -1
  109. package/dist/index.d.ts +29 -13
  110. package/dist/index.js +18 -9
  111. package/dist/inheritEnvCapability.d.ts +3 -2
  112. package/dist/inheritEnvCapability.js +3 -3
  113. package/dist/inheritEnvWire.d.ts +3 -2
  114. package/dist/inheritEnvWire.js +12 -14
  115. package/dist/interactiveHalt.js +17 -6
  116. package/dist/liveModelCatalog.d.ts +2 -1
  117. package/dist/liveModelCatalog.js +14 -8
  118. package/dist/mcpPanel.d.ts +10 -1
  119. package/dist/mcpPanel.js +40 -13
  120. package/dist/mcpProbeCapability.d.ts +2 -1
  121. package/dist/mcpProbeCapability.js +7 -11
  122. package/dist/mcpProbeWire.d.ts +3 -1
  123. package/dist/mcpProbeWire.js +5 -0
  124. package/dist/mcpWireCaps.d.ts +34 -0
  125. package/dist/mcpWireCaps.js +117 -17
  126. package/dist/memoryEntriesWire.js +5 -10
  127. package/dist/model/onboardJudgement.d.ts +93 -0
  128. package/dist/model/onboardJudgement.js +415 -0
  129. package/dist/model/tierVocabulary.d.ts +2 -0
  130. package/dist/model/tierVocabulary.js +17 -5
  131. package/dist/modelCapabilityProbe.d.ts +64 -0
  132. package/dist/modelCapabilityProbe.js +600 -0
  133. package/dist/modelIdentityResolvability.d.ts +3 -0
  134. package/dist/modelIdentityResolvability.js +26 -17
  135. package/dist/ownKey.d.ts +7 -0
  136. package/dist/ownKey.js +34 -0
  137. package/dist/panelReduce.d.ts +6 -1
  138. package/dist/panelReduce.js +50 -3
  139. package/dist/permissionRuleIssue.js +2 -0
  140. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  141. package/dist/permissionRulesWriteCapability.js +8 -6
  142. package/dist/pluginHooksWire.d.ts +46 -3
  143. package/dist/pluginHooksWire.js +217 -11
  144. package/dist/printModelStatus.d.ts +63 -0
  145. package/dist/printModelStatus.js +155 -0
  146. package/dist/request/taskRequest.d.ts +11 -5
  147. package/dist/request/taskRequest.js +112 -16
  148. package/dist/resumeRefusalCopy.d.ts +12 -9
  149. package/dist/resumeRefusalCopy.js +70 -143
  150. package/dist/retryStatus.d.ts +37 -0
  151. package/dist/retryStatus.js +79 -0
  152. package/dist/scenarioRefusal.d.ts +9 -0
  153. package/dist/scenarioRefusal.js +111 -0
  154. package/dist/seam.d.ts +25 -1
  155. package/dist/seam.js +10 -1
  156. package/dist/seatContract.d.ts +260 -10
  157. package/dist/seatContract.js +692 -19
  158. package/dist/selfOrchestrationDenial.js +7 -19
  159. package/dist/sessionIdSegment.d.ts +6 -0
  160. package/dist/sessionIdSegment.js +24 -0
  161. package/dist/sessionMemoryStatus.js +6 -11
  162. package/dist/sessionPolicyCapability.d.ts +2 -1
  163. package/dist/sessionPolicyCapability.js +8 -6
  164. package/dist/settingsHooksSalvage.d.ts +44 -0
  165. package/dist/settingsHooksSalvage.js +211 -0
  166. package/dist/skillToolListsCapability.d.ts +2 -1
  167. package/dist/skillToolListsCapability.js +8 -6
  168. package/dist/sseIdleTriage.js +3 -2
  169. package/dist/subagent/engineSubagentResume.js +15 -9
  170. package/dist/subagentContentStore.d.ts +3 -0
  171. package/dist/subagentContentStore.js +22 -0
  172. package/dist/toolHistoryMismatch.js +3 -2
  173. package/dist/toolRoster.d.ts +3 -2
  174. package/dist/toolRoster.js +21 -20
  175. package/dist/turnFailurePresentation.d.ts +12 -1
  176. package/dist/turnFailurePresentation.js +212 -15
  177. package/dist/usageAnalytics.js +6 -11
  178. package/dist/userAttachmentEnvelope.d.ts +1 -0
  179. package/dist/userAttachmentEnvelope.js +37 -7
  180. package/dist/userAttachmentSeat.d.ts +21 -0
  181. package/dist/userAttachmentSeat.js +75 -0
  182. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  183. package/dist/userInvokedSkillsCapability.js +31 -7
  184. package/dist/wireErrorTriage.d.ts +7 -0
  185. package/dist/wireErrorTriage.js +23 -1
  186. package/dist/wireFailureShape.js +2 -1
  187. package/dist/wireRefusalCopy.d.ts +13 -1
  188. package/dist/wireRefusalCopy.js +24 -28
  189. package/dist/workflowsJournalCapability.d.ts +2 -1
  190. package/dist/workflowsJournalCapability.js +8 -6
  191. package/docs/INTEGRATION-CLIENTS.md +542 -30
  192. package/package.json +5 -5
@@ -115,5 +115,587 @@ const EN = {
115
115
  'model.subagent.chainUnbound': "Subagent model {word} is not bound on this engine (neither it nor any tier below it has a model) — the subagent will run on its parent's model.",
116
116
  'model.subagent.bindingNotInCatalog': "Subagent model {word} is bound to a model that is not in this engine's model catalog — the subagent will run on its parent's model.",
117
117
  'model.subagent.ambiguous': "Subagent model {word} matches more than one model name that differ only in case — spell it exactly; the subagent will run on its parent's model.",
118
+ 'session.devices.laneAbsent': 'This backend has no remote-control lane',
119
+ 'session.devices.laneUnreported': "This backend doesn't report a remote-control lane",
120
+ 'session.devices.verbsOff': "This backend's device lane is on, but its device-management verbs are off — devices can't be listed or changed here",
121
+ 'session.devices.probePending': 'Checking whether this backend has a remote-control lane…',
122
+ 'session.devices.probeFailedTransport': "Couldn't reach the engine to check for a remote-control lane — try again",
123
+ 'session.devices.probeFailedRefused': 'The engine refused the device-list check — try again',
124
+ 'session.devices.probeFailedUnreadable': "The engine's device list couldn't be read — try again",
125
+ 'config.cloudLogin.accessDenied': 'Sign-in was declined.',
126
+ 'config.cloudLogin.expiredToken': 'The sign-in code expired before it was approved — start again.',
127
+ 'config.cloudLogin.invalidGrant': 'The Cloud sign-in can no longer be renewed — sign in again.',
128
+ 'config.cloudLogin.cancelled': 'Sign-in was cancelled.',
129
+ 'config.cloudLogin.transport': 'Cannot reach the registry (network error, redirect or timeout).',
130
+ 'config.cloudLogin.refused': 'The registry refused the request.',
131
+ 'config.cloudLogin.refusedStatus': 'The registry refused the request (HTTP {status}).',
132
+ 'config.cloudLogin.noTokens': 'Sign-in failed (the registry returned no usable tokens).',
133
+ 'config.cloudLogin.other': 'Sign-in failed.',
134
+ 'config.engineTarget.busy': 'A session is still running — stop it before switching engines.',
135
+ 'config.engineTarget.switching': 'A switch is already in progress.',
136
+ 'config.engineTarget.notConfigured': "Cloud isn't set up yet — sign in and connect a Cloud engine first.",
137
+ 'config.engineTarget.notSignedIn': 'Sign in to Sema Cloud first (or paste an engine token under Advanced).',
138
+ 'config.engineTarget.probeFailed': "The engine didn't pass the connection check. Nothing was saved.",
139
+ 'config.engineTarget.orgPolicy': 'Your organization requires a different Cloud engine address.',
140
+ 'config.engineTarget.urlRefused': "That engine address can't be used — it must be an http(s) address without credentials.",
141
+ 'config.engineTarget.loginFailed': 'Sign-in failed.',
142
+ 'config.engineTarget.storageUnavailable': "Secure storage isn't available on this device, so the Cloud credential can't be kept. Nothing was changed.",
143
+ 'config.engineTarget.noLocalRuntime': "There's no local engine on this device.",
144
+ 'config.engineTarget.input': "The request wasn't in the expected shape, so nothing was changed.",
145
+ 'config.engineTarget.unknown': "The engine switch didn't go through.",
146
+ 'onboard.probe.endpointReachable': '{method} {path} → {status} (endpoint reachable)',
147
+ 'onboard.probe.modelSuggest': '{error} — listed similar id: "{near}"',
148
+ 'onboard.probe.redirected': 'the endpoint redirected ({status}) to {where} — Sema does not forward your key across redirects; use the final URL as the base URL',
149
+ 'onboard.probe.anotherAddress': 'another address',
150
+ 'onboard.probe.keyEchoed': "(the provider's reply echoed your key in an encoded form — not shown)",
151
+ 'onboard.probe.incomplete': 'The probe needs a base URL and an API shape — nothing was sent.',
152
+ 'onboard.probe.noFetch': 'This host has no network client for the probe — nothing was sent.',
153
+ 'onboard.probe.judgeAbsent': "This host hasn't installed the engine's route judge, so the probe can't build the request URL — nothing was sent.",
154
+ 'onboard.baseUrl.invalid': 'Base URL is not a valid URL.',
155
+ 'onboard.baseUrl.spaces': 'Base URL must not contain spaces or tabs.',
156
+ 'onboard.baseUrl.scheme': 'Base URL must be http(s).',
157
+ 'onboard.baseUrl.userinfo': 'Base URL must not carry credentials.',
158
+ 'onboard.baseUrl.fragment': 'Base URL must not have a fragment.',
159
+ 'onboard.baseUrl.pathKey': "Base URL's path looks like it carries a credential — put the key in the API key field.",
160
+ 'onboard.baseUrl.queryKey': 'Base URL must not carry credentials in its query — put the key in the API key field.',
161
+ 'onboard.baseUrl.queryValueKey': "Base URL's query looks like it carries a credential — put the key in the API key field.",
162
+ 'onboard.baseUrl.encoding': 'Base URL has malformed percent-encoding.',
163
+ 'onboard.catalog.keyEnvUnset': '"{name}" reads its key from {keyEnv}, which is not set — the engine refuses this model by name.',
164
+ 'onboard.catalog.unpaired': '"{name}" has its own base URL ({host}) but no key of its own (no apiKeyEnv), and the deployment key is paired with {root} — requests would go out with the wrong key or none. Set this model up again with its own key.',
165
+ 'onboard.catalog.noRoot': 'no {rootKey}',
166
+ 'onboard.catalog.unparseableHost': 'an unparseable URL',
167
+ 'onboard.catalog.judgeAbsent': "This host hasn't installed the engine's route judge, so \"{name}\" can't be checked for a usable key.",
168
+ 'onboard.plan.notObject': 'The model catalog is not a JSON object — not overwriting it. Fix or move the file, then try again.',
169
+ 'onboard.plan.modelsNotList': 'The model catalog has a "models" that is not a list — not rewriting it.',
170
+ 'onboard.plan.modelsItemNotObject': 'The model catalog has a models[] item that is not an object — not rewriting it.',
171
+ 'onboard.plan.envNotObject': 'The settings file has an "env" that is not an object — not rewriting it.',
172
+ 'onboard.plan.envCatalogPresent': 'The engine is serving "{model}" from environment settings and the catalog has no enabled model; a first catalog model would replace the environment models. Add them to the catalog first.',
173
+ 'onboard.input.keyInFields': 'The model ID / base URL contains the API key — check the fields.',
174
+ 'onboard.refusal.input': 'The model setup is incomplete or not in the expected shape — nothing was saved.',
175
+ 'onboard.refusal.probeFailed': 'The provider did not accept this setup — nothing was saved.',
176
+ 'onboard.refusal.probeUnverified': "The provider couldn't be checked, so nothing was saved — try again, or save it as unverified.",
177
+ 'onboard.refusal.credentialUnpaired': 'This model would have no usable key on the engine, so nothing was saved.',
178
+ 'onboard.refusal.catalogUnreadable': "The model catalog on this device can't be read, so it was not overwritten.",
179
+ 'onboard.refusal.writeConflict': 'Another program changed the configuration while saving — nothing was saved; try again.',
180
+ 'onboard.refusal.writeFailed': 'The model configuration could not be saved.',
181
+ 'onboard.refusal.engineIsRemote': "The Cloud engine is in use — local model setup doesn't apply to it. Switch to the local engine first.",
182
+ 'onboard.refusal.envCatalogPresent': 'The engine is serving models from environment settings; adding the first catalog model would replace them, so nothing was saved. Add those models to the catalog first.',
183
+ 'config.mcp.nameBlank': 'An MCP server entry{where} has an empty name ({name}), so it was not started. Give it a name, or remove the entry.',
184
+ 'config.mcp.nameEdgeWhitespace': 'MCP server {name}{where} was not started: its name has leading or trailing whitespace, so it would not match the same name in other settings (for example a list of disabled servers). Remove the extra whitespace from the name.',
185
+ 'config.mcp.nameCollides': 'MCP server {name}{where} was not started: its name has leading or trailing whitespace and, without it, would be the same name as another MCP server entry. Remove the extra whitespace from the name, or delete the duplicate entry.',
186
+ 'config.mcp.toolAxesInvalid': 'MCP server {name}{where} was not started: its toolAxes setting is not valid — {problem}. Fix the toolAxes entry for this server (or remove it); the other MCP servers are unaffected.',
187
+ 'config.mcp.toolAxesFallbackProblem': 'the declaration is not a valid set of per-tool safety settings',
188
+ 'config.mcp.elicitationInvalid': 'MCP server {name}{where} was not started: its elicitation setting must be true or false. Fix the elicitation entry for this server (or remove it); the other MCP servers are unaffected.',
189
+ 'config.mcp.cloudElicitationInvalid': 'cloud config: MCP server entries left out because their elicitation setting is not true or false — fix or remove the elicitation entry: {who}',
190
+ 'config.mcp.cloudToolAxesInvalid': 'cloud config: MCP server entries left out because their toolAxes setting is not valid (per-tool safety overrides take only effect, egress and irreversibility, each with a legal value) — fix or remove the toolAxes entry: {who}',
191
+ 'approval.boundGrants.notActivated.one': "Approving this does not activate the skill shown on the card: 1 entry on its refuse list reads as nothing, and the engine does not drop a refusal it cannot read, so the skill's instructions are not loaded and nothing it lists is granted.",
192
+ 'approval.boundGrants.notActivated.other': "Approving this does not activate the skill shown on the card: {count} entries on its refuse list read as nothing, and the engine does not drop a refusal it cannot read, so the skill's instructions are not loaded and nothing it lists is granted.",
193
+ 'approval.boundGrants.listsNoToolsWithNothing.one': 'Approving this activates the skill shown on the card; it lists no tools to run without asking and none to refuse. 1 listed entry reads as nothing and grants nothing.',
194
+ 'approval.boundGrants.listsNoToolsWithNothing.other': 'Approving this activates the skill shown on the card; it lists no tools to run without asking and none to refuse. {count} listed entries read as nothing and grant nothing.',
195
+ 'approval.boundGrants.activatesWithNothing.one': 'Approving this activates the skill shown on the card: {allow}, and {deny}. 1 listed entry reads as nothing and grants nothing.',
196
+ 'approval.boundGrants.activatesWithNothing.other': 'Approving this activates the skill shown on the card: {allow}, and {deny}. {count} listed entries read as nothing and grant nothing.',
197
+ 'approval.settle.cause.routingFailureFailClosed': 'the engine could not route it to anywhere that can answer it, so it closed it',
198
+ 'approval.settle.cause.runCancelled': 'the run that asked for it was cancelled',
199
+ 'approval.settle.cause.runExited': 'the run that asked for it exited before anyone answered',
200
+ 'approval.settle.cause.batchAborted': 'the batch of tool calls it belonged to was aborted',
201
+ 'approval.settle.cause.batchSiblingWithdrawn': 'another approval in the same batch was refused or withdrawn, which withdrew this one too',
202
+ 'approval.settle.cause.batchBoundElsewhere': 'the decision for its batch was bound to a different approval',
203
+ 'approval.settle.cause.adhocLegNoDurableDomain': 'this kind of request cannot be kept waiting for an answer on this deployment',
204
+ 'approval.settle.cause.orphanTtlExceeded': "it was left without an owner past the engine's time limit",
205
+ 'approval.settle.cause.crashedBeforePark': 'the engine process stopped before it could keep the request waiting',
206
+ 'approval.settle.cause.shutdownBeforePark': 'the engine shut down before it could keep the request waiting',
207
+ 'approval.settle.cause.ttlExpired': 'nobody answered within the approval window',
208
+ 'approval.settle.cause.broadcastLost': 'it never reached any open connection',
209
+ 'approval.settle.cause.streamDisconnected': 'the connection carrying this card dropped',
210
+ 'approval.settle.cause.undeliverable': 'it could not be delivered to any approval surface',
211
+ 'approval.settle.subject.named': 'the approval request for {tool}',
212
+ 'approval.settle.subject.generic': 'this approval request',
213
+ 'approval.settle.endedKnown': '{subject} ended on the engine without an answer: {clause}. Nothing was approved from this card; if the step is still needed, ask for it again.',
214
+ 'approval.settle.endedUnknown': "{subject} ended on the engine without an answer (the engine's reason is one this build does not know yet). Nothing was approved from this card; if the step is still needed, ask for it again.",
215
+ 'approval.settle.what.approved': 'approved',
216
+ 'approval.settle.what.denied': 'denied',
217
+ 'approval.settle.what.answered': 'answered',
218
+ 'approval.settle.late': ' late',
219
+ 'approval.settle.where': ' (task {task})',
220
+ 'approval.settle.follow.following': 'sema is following that run here',
221
+ 'approval.settle.follow.alreadyFollowing': 'this screen is already following that run',
222
+ 'approval.settle.executed.allowed': ' The engine also reports that the already-decided step was ALLOWED when it ran.',
223
+ 'approval.settle.executed.denied': ' The engine also reports that the already-decided step was DENIED at execution time (a deployment review can overturn an approval after the fact).',
224
+ 'approval.settle.acceptedFollowing': '{what}{late} — the engine took this decision{where}; {follow}, so what it does next shows up below.{tail}',
225
+ 'approval.settle.acceptedNotFollowing': '{what}{late} — the engine took this decision{where}. Whether the parked call has resumed yet is not something this reply can say; this screen is not following that run, so what it does next will not show up here by itself.{tail}',
226
+ 'approval.settle.parkedNote.approval': "This step was already parked in the engine's durable queue and waiting for a decision before this card went up. Yes approves it now and lets the step run late; No abandons the step — the model gets a refusal and can take another route.",
227
+ 'approval.settle.parkedNote.question': "This step was already parked in the engine's durable queue and waiting for a decision before this card went up. Answering now sends your decision late and lets the parked step continue with it; closing this card without answering abandons the step — the model gets a refusal and can take another route.",
228
+ 'approval.settle.parkedNote.queueNoDeadline': "{subject} is in the engine's durable queue (no deadline was reported for it). It waits for your decision — nothing has been decided on your behalf.",
229
+ 'approval.settle.parkedSubject.named': 'the approval for {tool}',
230
+ 'approval.settle.parkedSubject.generic': 'this approval',
231
+ 'session.crashConverged.reason.approvedThenInterrupted.one': 'had already been approved and may have been running when the previous engine run ended, so a side effect may have partly landed',
232
+ 'session.crashConverged.reason.approvedThenInterrupted.many': 'had already been approved and may have been running when the previous engine run ended, so a side effect may have partly landed',
233
+ 'session.crashConverged.reason.pendingUnsafe.one': 'had not started, based on what was recorded, but the engine did not mark it as safe to re-run',
234
+ 'session.crashConverged.reason.pendingUnsafe.many': 'had not started, based on what was recorded, but the engine did not mark them as safe to re-run',
235
+ 'session.crashConverged.reason.contradictory.one': 'has a contradictory record',
236
+ 'session.crashConverged.reason.contradictory.many': 'have contradictory records',
237
+ 'session.crashConverged.reason.unstableRow.one': 'has a record that read differently each time it was read',
238
+ 'session.crashConverged.reason.unstableRow.many': 'have records that read differently each time they were read',
239
+ 'session.crashConverged.fallback.one': 'had already been approved, or cannot be accounted for, so a side effect may have partly landed',
240
+ 'session.crashConverged.fallback.many': 'had already been approved, or cannot be accounted for, so a side effect may have partly landed',
241
+ 'session.crashConverged.resumeSafe': 'had not started, based on what was recorded, and can be re-run',
242
+ 'session.crashConverged.counted': '{n} of {total} {clause}',
243
+ 'session.crashConverged.clauseJoin': '; ',
244
+ 'session.crashConverged.needsHumanBody.one': '{clauses} — check it by hand before re-running',
245
+ 'session.crashConverged.needsHumanBody.many': '{clauses} — check them by hand before re-running',
246
+ 'session.crashConverged.rerunnable.one': 'based on what was recorded, it can be re-run',
247
+ 'session.crashConverged.rerunnable.many': 'based on what was recorded, they can be re-run',
248
+ 'session.crashConverged.droppedOnly.one': 'the previous session left {count} crash-converged approval record that this version could not read. sema has not re-run anything.',
249
+ 'session.crashConverged.droppedOnly.many': 'the previous session left {count} crash-converged approval records that this version could not read. sema has not re-run anything.',
250
+ 'session.crashConverged.recordedAs': ' (recorded as {causes})',
251
+ 'session.crashConverged.head.one': 'the previous engine run ended with {total} approval still waiting{recorded}, and the engine converged it to denied',
252
+ 'session.crashConverged.head.many': 'the previous engine run ended with {total} approvals still waiting{recorded}, and the engine converged them to denied',
253
+ 'session.crashConverged.droppedTail.one': ' ({count} further record could not be read.)',
254
+ 'session.crashConverged.droppedTail.many': ' ({count} further records could not be read.)',
255
+ 'session.crashConverged.line': '{head}; {body}. sema has not re-run anything.{dropped}',
256
+ 'session.crashConverged.cause.neutral': 'the decision converged automatically',
257
+ 'session.crashConverged.cause.withClause': '{clause}, and the decision converged automatically',
258
+ 'session.corrupt.content': "This session's saved history cannot be read — its stored log is damaged — so the engine cannot open this session. Retrying will not help: whoever operates this engine has to repair or remove that stored log. Until then, continue in a new session.",
259
+ 'resume.reopen.first.envFailed': 'The execution environment for this parked work could not be brought back',
260
+ 'resume.reopen.first.toolUnavailable': 'The tool this approval was granted for is not available on this engine',
261
+ 'resume.reopen.first.toolContractMismatch': 'The tool this approval was granted for has changed since the approval was recorded',
262
+ 'resume.reopen.content': '{first} · The engine re-parked the work before consuming anything — the approval is still pending and your decision was not consumed · Re-fetch the pending approvals and decide again on an engine where the same tool is available',
263
+ 'session.inheritEnv.notConfirmed': 'The engine has not confirmed that it withholds its own credentials from tool shells, so the tool shell gets a filtered environment (credential-looking variables such as GH_TOKEN are omitted) until the engine is upgraded.',
264
+ 'session.inheritEnv.withheld.all': "Not sent with this request: the engine's version is not known yet, and an engine that does not know the setting that lets the shell inherit this machine's whole environment refuses the whole request, so it was held back; this run's shell gets the default environment, with credential-like variables removed, and on an engine that does know the setting, leaving it out also clears an earlier whole-environment choice for this session.",
265
+ 'session.inheritEnv.withheld.scrub': "Not sent with this request: the engine's version is not known yet, so the default-environment setting was left out; that has the same effect, because leaving it out also gives this run the default environment (credential-like variables removed).",
266
+ 'session.inheritEnv.withheld.unknown': 'Not sent with this request: the shell-environment setting was held back for a reason this version does not recognize.',
267
+ 'session.inheritEnv.refusal': "The engine refused this request as invalid, under a refusal code that many different request fields share · This request asked for the shell to inherit this machine's whole environment, which the engine accepts only when tools run directly on its own machine and the request belongs to a session; if that is what it refused, send it again without that setting (or with the default)",
268
+ 'session.fileHistoryLeg.notHonored': 'The engine is still capturing file history for this session, though your settings asked it not to.',
269
+ 'resume.refusal.placementMismatch': 'This resume named a different placement root than the one recorded when the work was parked · The engine refused it before consuming anything — the parked work is untouched · Retry with the recorded root, or omit the placement root to inherit it',
270
+ 'resume.refusal.preflightWaitable': "The deployment's resume preflight refused this attempt · The refusal happened before the commit — your decision was not consumed · The engine supplied a wait, so this token stays redeemable once the obstacle clears",
271
+ 'resume.refusal.preflightNoWait': "The deployment's resume preflight refused this attempt · The refusal happened before the commit — your decision was not consumed · The engine supplied no wait, so this refusal does not say whether the token stays redeemable",
272
+ 'resume.refusal.policyBlock': "The engine refused to resume this parked work at its admission check (the engine reports that its admission policy changed since the work was first accepted) · {reason} · This refusal does not say whether anything was consumed before it or whether a retry would pass — check the task's current state before deciding again, and ask whoever operates this deployment if it keeps happening",
273
+ 'resume.refusal.policyBlockReason.coarse': 'The refusal did not name a more specific check (it carried only the generic code for its HTTP status: {code})',
274
+ 'resume.refusal.policyBlockReason.named': 'The check that refused it: {code}',
275
+ 'resume.refusal.policyBlockReason.absent': 'The refusal did not name a more specific check',
276
+ 'resume.refusal.policyBlockReason.unreadable': 'The refusal carried a more specific reason that could not be read',
277
+ 'resume.refusal.requireExisting.sessionNotFound': 'The engine did not continue this conversation: the conversation it was asked to continue does not exist there (it may have expired, been removed, or never been created on that engine; this client cannot tell which), and this request asked to continue only an existing one, so no new conversation was started · Start a new conversation, or pick another one to continue',
278
+ 'resume.refusal.requireExisting.sessionIdMissing': 'The engine did not continue this conversation: this request asked to continue only an existing conversation but named none, so there was nothing to continue and no new conversation was started · Name the conversation to continue, or start a new one',
279
+ 'resume.refusal.requireExisting.generic': 'The engine did not continue this conversation: this request asked to continue only an existing conversation and there was none it could continue, so no new conversation was started · Start a new conversation, or pick another one to continue',
280
+ 'resume.refusal.contextUnavailable': 'This approval has nowhere to be delivered: the conversation that started this run has no usable context to continue it right now · Nothing was decided and your decision was not consumed; this card is still waiting · {third}',
281
+ 'resume.refusal.contextThird.withRun': "The error carries this run's id: use it to recover the run yourself, then decide again; raising the conversation retention time only prevents this from happening again and cannot rescue this one{retention}",
282
+ 'resume.refusal.contextThird.noRun': 'The error carries no run id: go back to the run list, find this run and recover it yourself, then decide again; raising the conversation retention time only prevents this from happening again and cannot rescue this one{retention}',
283
+ 'resume.refusal.contextRetention': ' (this deployment keeps conversations for {sec} seconds)',
284
+ 'resume.refusal.startup.resumeRejected': 'The engine could not start the parked work to apply this decision (its session may be gone, or the engine rejected the decision itself; this client cannot tell which) · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · If the card is still there, decide it again from the fresh list',
285
+ 'resume.refusal.startup.undetermined': 'The engine could not start the parked work to apply this decision · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · If the card is still there: when the engine rejected the decision itself (for example an answer given to the wrong question), correct it and decide again; when the approved tool is one the agent inherits from the task that started it, approving it again will not work on this server — deny the card, or wait for a server upgrade',
286
+ 'resume.refusal.startup.cause.environment': 'The engine could not start the parked work to apply this decision: the environment it runs in failed to come up (for example the workspace could not be restored); the decision itself was not rejected · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · If the card is still there, deciding it again replays the same decision',
287
+ 'resume.refusal.startup.cause.sessionGone': 'The engine could not start the parked work to apply this decision: the session of the agent it would resume is gone · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · If the card is still there, deny it to close it; the work it was waiting on cannot be resumed',
288
+ 'resume.refusal.startup.cause.toolUnavailable': 'The engine could not start the parked work to apply this decision: the approved tool is not available to the resumed work (it is gone, or a different tool now has its name) · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · This approval cannot run as decided — if the card is still there, decide it afresh (denying it settles it)',
289
+ 'resume.refusal.startup.cause.configuration': "The engine could not start the parked work to apply this decision: this deployment's configuration refuses the resumed work · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · Deciding again under the same configuration fails the same way — the configuration has to change first; denying the card settles it",
290
+ 'resume.refusal.startup.cause.decisionRejected': 'The engine could not start the parked work to apply this decision: the engine rejected the decision itself (for example an answer given to the wrong question, or an edited input the constraints refuse) · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · If the card is still there, correct the decision and decide it again from the fresh list',
291
+ 'resume.refusal.startup.cause.transcriptCorrupt': 'The engine could not start the parked work to apply this decision: the transcript of the agent it would resume is there but cannot be read as a session (it is corrupt) · This refusal does not say whether the card is still waiting — re-fetch the pending approvals · Deciding again fails the same way until that transcript is repaired or restored; denying the card settles it',
292
+ 'resume.refusal.checkpoint.newerEngine': 'This parked work was stored by a newer engine version ({writer}) than this engine ({reader}) · Nothing was decided or resumed and the parked work is still waiting, but sending the same request again will not by itself continue it · Continue it on an engine at version {writer} or newer',
293
+ 'resume.refusal.checkpoint.content': "This server cannot continue this parked work in the form it was stored in · Nothing was decided or resumed and the parked work is still waiting, but sending the same request again will not by itself continue it · {outlet} — whoever operates this deployment can find such parked work before an upgrade with the server's pre-upgrade drain check",
294
+ 'resume.refusal.checkpoint.outletWithRun': 'If it was parked before this server was upgraded, cancel its run{named} first, then submit the work again as a new task',
295
+ 'resume.refusal.checkpoint.runNamed': ' ({runId})',
296
+ 'resume.refusal.checkpoint.outletNoRun': 'If it was parked before this server was upgraded, there is no run to cancel: start a new task in that conversation',
297
+ 'resume.refusal.checkpoint.outletUnknownKind': 'If it was parked before this server was upgraded, submit the work again as a new task (this client cannot tell which kind of parked work this is, so both ways out are given): when it still has a run waiting on it (a tool approval, a plan review or a paused resource), cancel that run first; when it was waiting to be woken up, or was a workflow step continuing its host conversation, there is no run to cancel, so start a new task in that conversation',
298
+ 'resume.refusal.park.whyWalltime': 'its run carries a wall-clock time allowance, which this engine version no longer enforces',
299
+ 'resume.refusal.park.whyInheritedGate': 'the permission-mode setting it was parked with can no longer be read',
300
+ 'resume.refusal.park.whyConfigRefused': 'the engine refuses the task configuration it was parked with',
301
+ 'resume.refusal.park.whyUnsupported': 'it was parked under conditions this engine version does not support (for example, by an earlier engine version)',
302
+ 'resume.refusal.park.whatDefault': 'parked step',
303
+ 'resume.refusal.park.head': 'This {what} cannot be resumed by this engine version: {why}. The same refusal comes back every time, so answering it again will not help (nothing was decided and nothing was resumed).',
304
+ 'resume.refusal.park.configMayReturn': ' If that configuration is restored, the same answer can go through again.',
305
+ 'resume.refusal.park.printEnded': '{head} The engine ended that run ({code}); submit the work again as a new task.',
306
+ 'resume.refusal.park.printHolds': '{head}{configMayReturn} The parked run still holds this session ({code}): cancel it ({cancel}), then submit the work again as a new task.',
307
+ 'resume.refusal.park.interactiveEnded': '{head} The engine ended that parked run, so this conversation is free: send the work again as a new message.',
308
+ 'resume.refusal.park.interactiveBusy': '{head}{configMayReturn} The parked run keeps this conversation busy until it is cancelled.',
309
+ 'resume.refusal.park.blockedPrint': 'sema will not put the card for run {run} back on screen by itself: this engine version refuses to resume it. Cancel the run ({cancel}) and submit the work again as a new task.',
310
+ 'resume.refusal.park.blockedInteractive': 'sema will not put the card for run {run} back on screen by itself: this engine version refuses to resume it. To free this conversation, send a message to bring the card back and answer it — sema then offers to cancel that run, after which you can send the work again as a new message.',
311
+ 'session.selfHeal.wayOut.interactive': 'run /clear to keep working in a fresh session',
312
+ 'session.selfHeal.freshSession.default': 'start a new session (drop --resume/--continue)',
313
+ 'session.selfHeal.freshSession.defaultCapitalized': 'Start a new session (drop --resume/--continue)',
314
+ 'session.selfHeal.gate.kind': 'a {kind} decision',
315
+ 'session.selfHeal.gate.generic': 'a decision',
316
+ 'session.selfHeal.handle.run': ' (run {taskId})',
317
+ 'session.selfHeal.viaEngine': ' You can also decide it on the engine directly: POST {decidePath}.',
318
+ 'session.selfHeal.decidePathClause': ' The engine says that run is waiting on {gate} and that it is decided at POST {decidePath} — deciding it releases the session.',
319
+ 'session.selfHeal.governanceOrigin': " That gate is enforced by this deployment's governance policy, not by a permission rule you set.",
320
+ 'session.selfHeal.lastActivity': ' The engine last recorded activity on that run {ago} ago.',
321
+ 'session.selfHeal.noCardView.afterColon': ': this session has no view attached that can show decision cards',
322
+ 'session.selfHeal.noCardView.inParens': ' (this session has no view attached that can show decision cards)',
323
+ 'session.selfHeal.userClosedCardNotPutBack': 'sema does not put a card you closed back on screen by itself',
324
+ 'session.selfHeal.lastEngineStatus': ' (last engine status: {status})',
325
+ 'session.selfHeal.injected.lead': 'A follow-up message sema sent on its own (not one you typed)',
326
+ 'session.selfHeal.injected.id': ' (id {id})',
327
+ 'session.selfHeal.injected.attach': '{lead} was not delivered: you chose to watch the reply already in progress{id} instead, and sema is replaying that reply here, so the part already shown above will appear again below. sema did not retry, so the model has not seen it.',
328
+ 'session.selfHeal.injected.steerUnknown': '{lead} was passed to the reply already in progress{id}, but its delivery could not be confirmed ({detail}) — that reply may or may not have received it. sema did not retry, because sending it twice is not safe; watch that reply for what it does next.',
329
+ 'session.selfHeal.injected.steerRejected': '{lead} was not delivered: passing it to the reply already in progress{id} was refused ({detail}). sema did not retry, so the model has not seen it.',
330
+ 'session.selfHeal.injected.decisionInFlight': '{lead} was not delivered: this session is still busy with an earlier reply{id}, and your answer to the decision it is waiting on is still on its way. sema did not retry, so the model has not seen it.',
331
+ 'session.selfHeal.injected.dismissedPlan': '{lead} was not delivered: this session is held by an earlier reply{id} whose plan is waiting for your review, and you closed that approval card — {closed}. Send a message when you want the card back; sema did not retry, so the model has not seen it.',
332
+ 'session.selfHeal.injected.queuedOn': '{lead} is queued on an earlier reply{id} that is paused waiting for a decision',
333
+ 'session.selfHeal.injected.queuedShown': '{queuedOn}; sema has shown that decision card, and the message is picked up once you answer it.',
334
+ 'session.selfHeal.injected.queuedInFlight': '{queuedOn}; your answer to it is still on its way, and the message is picked up once that answer is applied.',
335
+ 'session.selfHeal.injected.queuedDismissed': '{queuedOn}; you closed that card yourself, so sema did not put it back on screen — send a message to bring it back, and the message is picked up once that decision is made.',
336
+ 'session.selfHeal.injected.queuedCannotShow': '{queuedOn} sema could not show here{noView}; the message is picked up only once that decision is made.',
337
+ 'session.selfHeal.injected.parkedForWake': '{lead} has not reached the model: the earlier reply{id} had already finished, so the message was set aside on it instead of starting a new reply, and sema did not retry it.',
338
+ 'session.selfHeal.injected.unknownDelivery': '{lead} was accepted for the reply already in progress{id}, but how it will be delivered was not reported, so sema cannot tell whether that reply will pick it up',
339
+ 'session.selfHeal.injected.unknownDeliveryFollowing': '{unknown}. sema is following that reply and will show whatever it asks for next; check what it does before deciding whether anything needs to be sent again.',
340
+ 'session.selfHeal.injected.unknownDeliveryWatch': '{unknown} — watch that reply before deciding whether anything needs to be sent again.',
341
+ 'session.selfHeal.injected.heldForDecision': '{lead} is on hold: this session is busy with an earlier reply{id} that is waiting on a decision. sema kept the message queued and will send it after you answer the open card.',
342
+ 'session.selfHeal.injected.resendingConfirmed': '{lead} was held back because this session was busy with an earlier reply{id}; the session is free again, so sema is sending the message now — nothing for you to do.',
343
+ 'session.selfHeal.injected.resendingInferred': '{lead} was held back because this session was busy with an earlier reply{id}; that reply is now reported as finished, so sema is sending the message now — nothing for you to do (if the session has not quite freed up yet, it may be held back once more).',
344
+ 'session.selfHeal.injected.handedOffFollowing': '{lead} was passed to the reply already in progress{id} instead of starting a new one. sema is following that reply and will show whatever it asks for next; nothing for you to do now.',
345
+ 'session.selfHeal.injected.handedOffWatch': '{lead} was passed to the reply already in progress{id} instead of starting a new one — watch that reply for what it does with it.',
346
+ 'session.selfHeal.injected.notDelivered': '{lead} was not delivered: this session was still busy with an earlier reply{id}, and there was no open card you could answer to free it{noView}. sema did not retry, so the model has not seen it.',
347
+ 'session.selfHeal.decisionInFlight': 'The previous turn is parked {parkedOn} and your answer to that card is still on its way to the engine, so sema did not show the card again — answering it a second time would send a second decision. It did NOT cancel the run. Your message was NOT sent; send it again in a moment, once the engine has applied that decision.',
348
+ 'session.selfHeal.parkedOn.ask': 'waiting for your decision (run {taskId})',
349
+ 'session.selfHeal.parkedOn.plan': 'on a plan review (run {taskId})',
350
+ 'session.selfHeal.row.decisionPending': 'This session is held by an earlier turn{handle} that is waiting on a decision you have not made yet, and there is a decision card open for it. sema did NOT cancel it — answering that card is what releases the session, and cancelling would decide it for you. Your message was NOT sent; answer the open card and send it again.',
351
+ 'session.selfHeal.row.askReopened.firstSight': 'The previous turn advanced to a decision it needs from you (run {taskId}), which is why nothing new could start — sema has surfaced that decision card. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have decided it for you.)',
352
+ 'session.selfHeal.row.askReopened.reseen': 'The previous turn is parked waiting for your decision (run {taskId}), which is why nothing new could start — that card was closed without being answered, so sema reopened it. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have decided it for you.)',
353
+ 'session.selfHeal.row.planReviewReopened.firstSight': 'The previous turn produced a plan that is waiting for your review (run {taskId}), which is why nothing new could start — sema has surfaced the review card. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have thrown the plan away on your behalf.)',
354
+ 'session.selfHeal.row.planReviewReopened.reseen': 'The previous turn is parked waiting for you to review its plan (run {taskId}), which is why nothing new could start — that approval card was closed without being answered, so sema reopened it. Answer it and send your message again. (sema did NOT cancel the run: cancelling would have thrown the plan away on your behalf.)',
355
+ 'session.selfHeal.row.askDecided.confirmed': 'The previous turn was parked on an approval that your permission rules decided on their own (no card was needed); run {taskId} resumed and the engine confirmed it is no longer holding this session — sema is re-sending your message.',
356
+ 'session.selfHeal.row.askDecided.inferred': 'The previous turn was parked on an approval that your permission rules decided on their own (no card was needed); run {taskId} resumed and has since finished — sema is re-sending your message; if that run has not fully let go of the session yet, you may have to send it once more.',
357
+ 'session.selfHeal.row.askDecided.releaseUnknown': 'The previous turn was parked on an approval that your permission rules decided on their own (no card was needed), so run {taskId} should be resuming{status}. sema could not yet confirm it finished, so your message was not sent — wait a moment and send it again.',
358
+ 'session.selfHeal.row.askReopenFailed.withKeep': 'The previous turn is parked waiting for your decision (run {taskId}) and sema could not reopen that card here{noView}. It did NOT cancel the run — that would have decided it for you. Your message was NOT sent. To keep this conversation, {keep}: the card comes back when the session resumes, if it is still waiting. Or {wayOut} if you no longer want it.{viaEngine}',
359
+ 'session.selfHeal.row.askReopenFailed.noKeep': 'The previous turn is parked waiting for your decision (run {taskId}) and sema could not reopen that card here{noView}. It did NOT cancel the run — that would have decided it for you. Your message was NOT sent; {wayOut} if you no longer want it.{viaEngine}',
360
+ 'session.selfHeal.row.planReopenFailed.dismissed': 'The previous turn is parked waiting for a plan review (run {taskId}), and you closed its approval card — {closed}. It did NOT cancel the run — that would have discarded the plan for you. Your message was NOT sent; send it again to bring the card back.',
361
+ 'session.selfHeal.row.planReopenFailed.withKeep': 'The previous turn is parked waiting for a plan review (run {taskId}) and sema could not reopen that approval card{noView}. It did NOT cancel the run — that would have discarded the plan for you. Your message was NOT sent. To keep this conversation, {keep}: the card comes back when the session resumes, if it is still waiting. Or {wayOut} if you no longer want that plan.{viaEngine}',
362
+ 'session.selfHeal.row.planReopenFailed.noKeep': 'The previous turn is parked waiting for a plan review (run {taskId}) and sema could not reopen that approval card{noView}. It did NOT cancel the run — that would have discarded the plan for you. Your message was NOT sent; {wayOut} if you no longer want that plan.{viaEngine}',
363
+ 'session.selfHeal.row.steered.textOnly': 'Only the TEXT of your message was handed over — a steer carries no attachments, so any images in that submission were NOT sent.',
364
+ 'session.selfHeal.row.steered.tail.following': 'sema is following that run and will surface whatever it asks for next.',
365
+ 'session.selfHeal.row.steered.tail.watch': 'watch that run for what it does with it.',
366
+ 'session.selfHeal.row.steered.unknownTail.following': 'sema is following that run and will surface whatever it asks for next before you send it again.',
367
+ 'session.selfHeal.row.steered.unknownTail.watch': 'watch that run before sending it again.',
368
+ 'session.selfHeal.row.steered.applied': "sema handed your message to the run that is already working (run {taskId}) — the engine applied it to that run, so it is picked up at that run's next step. {textOnly} Nothing was cancelled, and your message did NOT start a new turn — {tail}",
369
+ 'session.selfHeal.row.steered.parked.withStatus': 'parked (status {status})',
370
+ 'session.selfHeal.row.steered.parked.plain': 'parked',
371
+ 'session.selfHeal.row.steered.next.shown': 'sema has surfaced that decision card — answering it is what lets that run resume and pick your message up.',
372
+ 'session.selfHeal.row.steered.next.inFlight': 'Your answer to that decision is still on its way to the engine, so sema did not show the card again; that run moves on once the engine applies it.',
373
+ 'session.selfHeal.row.steered.next.dismissed': 'You closed that decision card yourself, so sema did not put it back on screen; nothing will resume that run until that decision is made — send a message to bring the card back.',
374
+ 'session.selfHeal.row.steered.next.cannotShow': 'sema could not surface that decision card here{noView}, so nothing will resume that run until that decision is made; {wayOut} if you no longer want it.',
375
+ 'session.selfHeal.row.steered.queued': 'run {taskId} is not actually working right now: the engine reports it {parked} on a decision it needs from you, so it queued your message on that park instead of running it. {next} {textOnly} Nothing was cancelled, and your message did NOT start a new turn.',
376
+ 'session.selfHeal.row.steered.parkedForWake': 'run {taskId} had already finished, so the engine parked your message on that finished run instead of running it — a parked message is delivered only if this session is woken on the engine (POST /v1/sessions/:id/wake), which sema does not do here. That run is no longer holding this session: send your message again to run it as a new turn — but note that the parked copy is NOT discarded, so if anything ever wakes this session on the engine that instruction would run a second time. {textOnly} Nothing was cancelled.',
377
+ 'session.selfHeal.row.steered.reported': ' (it reported that run as {status})',
378
+ 'session.selfHeal.row.steered.unknown': 'sema handed your message to run {taskId}, but the engine did not say how it will be delivered{reported}. {textOnly} Nothing was cancelled, and your message did NOT start a new turn — {tail}',
379
+ 'session.selfHeal.row.steerFailed.rejected': 'Handing your message to the running run (run {taskId}) was refused: {detail}. sema did NOT retry it (a steer is not safe to send twice) and it did NOT cancel that run. Your message was NOT sent; send it again if you still want it.',
380
+ 'session.selfHeal.row.steerFailed.unknown': 'sema sent your message to the running run (run {taskId}) but could not confirm what happened to it ({detail}). A steer is not safe to send twice, so sema did NOT retry it, and it did NOT cancel that run. That run may or may not have received your message — watch what it does next before sending it again.',
381
+ 'session.selfHeal.row.attach': '{disclosure} Your message was NOT sent; send it again once that run has finished.',
382
+ 'session.selfHeal.row.cancelled.confirmed': 'You chose to cancel run {taskId}. The engine confirmed it is no longer holding this session, so sema is sending your message now.',
383
+ 'session.selfHeal.row.cancelled.reported': 'You chose to cancel run {taskId}. The engine now reports that run as finished, so sema is sending your message now; if that run has not fully let go of the session yet, you may have to send it once more.',
384
+ 'session.selfHeal.row.cancelTimeout.aborted': 'sema asked the engine to cancel run {taskId} and you interrupted while it was still confirming ({waited} in). Cancelling is asynchronous, so that run may still be winding down and may still hold this session. Your message was NOT sent; send it again in a moment, or {wayOut}.',
385
+ 'session.selfHeal.row.cancelTimeout.unread': "sema asked the engine to cancel run {taskId} but could not read that run's state back within {waited}, so it cannot confirm whether the session was released. Your message was NOT sent; send it again in a moment (if that run really is gone it will just run), or {wayOut}.",
386
+ 'session.selfHeal.row.cancelTimeout.held': 'sema asked the engine to cancel run {taskId}, but that run still held this session {waited} later — cancelling is asynchronous and it may still be winding down. Your message was NOT sent; send it again in a moment, or {wayOut}.',
387
+ 'session.selfHeal.row.cancelFailed.unknown': 'sema sent the cancel for run {taskId} but could not confirm what happened to it ({detail}), and it could not read that run back as released either. That run may or may not still be holding this session. Your message was NOT sent; send it again in a moment, or {wayOut}.',
388
+ 'session.selfHeal.row.cancelFailed.rejected': 'sema could not cancel run {taskId} — the engine rejected that request ({detail}), so nothing was cancelled and sema cannot tell whether that run is still holding this session. Your message was NOT sent; send it again to find out, or {wayOut}.',
389
+ 'session.selfHeal.row.askRunNotFound': 'The previous turn is recorded as parked on a decision (run {taskId}), but the approval it was waiting on is no longer on the engine, and asking the engine about that run directly comes back not-found — a lookup that cannot separate a run that is really gone from one this session is simply not allowed to read. Either way sema has nothing it can act on here, so it did NOT cancel anything. Your message was NOT sent; send it again (if the session really is free it will just run), or {wayOut}.',
390
+ 'session.selfHeal.row.askRunSettled': 'The previous turn was recorded as parked on a decision (run {taskId}), but that run has already finished (status {status}) — there is nothing left to answer and nothing to cancel, so sema did NOT cancel anything. Your message was NOT sent; send it again (once that run has let go of the session it will just run), or {wayOut}.',
391
+ 'session.selfHeal.row.stale.cancelled.confirmed': 'Run {taskId} was parked on an approval that no longer exists on the engine, so there was nothing left for you to answer. You chose to cancel that run, and the engine confirmed it is no longer holding this session, so sema is sending your message again now.',
392
+ 'session.selfHeal.row.stale.cancelled.reported': 'Run {taskId} was parked on an approval that no longer exists on the engine, so there was nothing left for you to answer. You chose to cancel that run: the engine now reports it as finished, so it will not resume — whatever that turn had left to do is not coming back. sema is sending your message again now; if that run has not fully let go of the session yet, you may have to send it once more.',
393
+ 'session.selfHeal.row.stale.cancelTimeout.aborted': 'sema asked the engine to cancel run {taskId} (it was parked on an approval that no longer exists there) and you interrupted while it was still confirming ({waited} in). Cancelling is asynchronous, so that run may still be winding down and may still hold this session. Your message was NOT sent; send it again in a moment, or {wayOut}.',
394
+ 'session.selfHeal.row.stale.cancelTimeout.unread': "sema asked the engine to cancel run {taskId} (parked on an approval that no longer exists there) but could not read that run's state back within {waited}, so it cannot confirm whether the session was released. Your message was NOT sent; send it again in a moment (if that run really is gone it will just run), or {wayOut}.",
395
+ 'session.selfHeal.row.stale.cancelTimeout.held': 'sema asked the engine to cancel run {taskId} (parked on an approval that no longer exists there), but that run still held this session {waited} later — cancelling is asynchronous and it may still be winding down. Your message was NOT sent; send it again in a moment, or {wayOut}.',
396
+ 'session.selfHeal.row.stale.cancelFailed.unknown': 'sema sent the cancel for run {taskId} (parked on an approval that no longer exists on the engine) but could not confirm what happened to it ({detail}), and it could not read that run back as released either. That run may or may not still be holding this session. Your message was NOT sent; send it again in a moment, or {wayOut}.',
397
+ 'session.selfHeal.row.stale.wait.offered': 'Run {taskId} is still parked (status {status}) on an approval that no longer exists on the engine. sema already asked what to do with it and you chose to leave it alone, so it is not asking again. Your message was NOT sent; cancel that run on the engine (POST /v1/runs/{taskId}/cancel — that ends it for good), or {wayOut}.',
398
+ 'session.selfHeal.row.stale.wait.first': 'Run {taskId} is still parked (status {status}) on an approval that no longer exists on the engine, so there is no card left to answer and that run will not settle on its own. sema did NOT cancel it — you chose to leave it alone. Your message was NOT sent; cancel that run on the engine (POST /v1/runs/{taskId}/cancel — that ends it for good), or {wayOut}.',
399
+ 'session.selfHeal.row.runNotFound': 'The engine reported this session as held by run {taskId} (status running), but it no longer recognizes that run when asked directly — that claim looks stale (the run most likely no longer exists). sema did not offer to steer or cancel it: there is nothing left to act on. Your message was NOT sent; send it again (if the session really is free it will just run), or {wayOut}.',
400
+ 'session.selfHeal.row.runSettled': 'Run {taskId} has already finished (status {status}), but the engine still reported it as holding this session — that claim looks stale or mid-release. sema did not offer to steer or cancel it: the run is over. Your message was NOT sent; send it again (once the claim clears it will just run), or {wayOut}.',
401
+ 'session.selfHeal.row.notParked.offered': 'Run {taskId} is still holding this session (status {status}). sema already asked what to do with it and you chose to leave it alone, so it is not asking again. Your message was NOT sent; wait for that run, cancel it on the engine (POST /v1/runs/{taskId}/cancel), or {wayOut}.',
402
+ 'session.selfHeal.row.notParked.parkedOn': 'This session is held by an earlier run (run {taskId}, status {status}) that is waiting on {parkedOn} — it will not finish on its own. sema did NOT cancel it, because cancelling would decide that item for you. Your message was NOT sent; {wayOut} if you no longer want it.',
403
+ 'session.selfHeal.row.notParked.inFlight': 'This session already has a run in flight (run {taskId}, status {status}) — most likely a turn you sent to the background. sema did NOT cancel it, because that would throw away work you asked for. Wait for it to finish, or {wayOut}.',
404
+ 'session.selfHeal.row.stateUnknown': "A run is still active on this session{handle} and sema could not read that run's state, so it did not touch it ({detail}). sema did NOT send your message: this session cannot start a new turn until that run settles — {wayOut}.",
405
+ 'session.selfHeal.headless.status': ' (status {status})',
406
+ 'session.selfHeal.headless.decide': 'This session is held by an earlier run{handle}{status} that is parked waiting on {gate}, so this message was NOT sent. Decide it and the session unlocks: POST {decidePath}. Cancelling instead ({cancelPath}) also unlocks it, but it decides that item against you. Or {freshSession}.{governance}',
407
+ 'session.selfHeal.headless.statusOnly': 'This session is held by an earlier run{handle} with status {status}, so this message was NOT sent. The engine reported no decision pending on that run: if it is still working, wait for it to finish; if it will never settle, release it with {cancelPath} (that discards whatever it was doing). Or {freshSession}.',
408
+ 'session.selfHeal.headless.neverReleased': 'A run is still active on this session{handle} and was never released, so sema did NOT send this message. Nothing here clears on its own. {startOver}, or release the run on the engine: {cancelPath}',
409
+ 'approval.deniedBy.policy': "denied by this deployment's permission policy",
410
+ 'approval.deniedBy.hook': 'denied by a PreToolUse hook',
411
+ 'approval.deniedBy.org': 'denied by an organization rule',
412
+ 'approval.deniedBy.persistedRule': 'denied by a persisted rule',
413
+ 'approval.deniedBy.classifier': 'denied by the auto-mode classifier',
414
+ 'approval.deniedBy.compliance': 'denied by a compliance lock',
415
+ 'approval.deniedBy.writeProtection': 'denied because the write landed on a write-protected path',
416
+ 'approval.deniedBy.askResolution': 'denied when the approval was resolved',
417
+ 'approval.deniedBy.readBoundary': 'denied by the read boundary',
418
+ 'approval.deniedBy.mode': "denied by this session's permission mode",
419
+ 'approval.deniedBy.unknown': 'denied by a layer this build does not know ({word}) — this build does not know this layer name, so it cannot say which layer refused this call or why',
420
+ 'approval.card.noWord': '(none)',
421
+ 'approval.origin.contentQuestion': 'the tool itself asked you a question',
422
+ 'approval.origin.planReview': 'the model paused its run for your verdict on the plan it proposed',
423
+ 'approval.origin.ancestorMarked': 'an ancestor marked this call (an inherited approver-unavailable float, or a durable mandate; this client cannot tell which from the origin alone): it must reach the park with no synchronous decision-maker in between',
424
+ 'approval.origin.orgUnavailable': 'the organization policy was unavailable, so this call asks',
425
+ 'approval.origin.orgRule': 'an organization rule asks about this call',
426
+ 'approval.origin.ruleStoreUnavailable': 'this call could not be checked against your standing deny/ask rules, so it asks',
427
+ 'approval.origin.hook': 'a PreToolUse hook asked about this call',
428
+ 'approval.origin.askRule': 'a persisted ask rule matches this call',
429
+ 'approval.origin.denialLimitFallback': 'the auto-mode classifier hit its denial limit and handed this call back to you',
430
+ 'approval.origin.shellGateTighten': 'the coarse shell check rates this command above the tier it lets through, so it asks',
431
+ 'approval.origin.safetyTighten': 'the gate tightened on this call’s own facts (network egress, irreversibility, or a protected write; this client cannot tell which from the origin alone)',
432
+ 'approval.origin.policy': 'this deployment’s permission policy, or the permission mode’s default, asks about this call',
433
+ 'approval.origin.unknownWithWord': 'this call asks; its origin {word} is a word newer than this client, so answer it as usual',
434
+ 'approval.origin.unknownNoWord': 'this call asks; its origin is a word newer than this client, so answer it as usual',
435
+ 'approval.ruleOffer.absence.allowOutranked': 'no "don\'t ask again" option here: an allow rule already matches this call, but this question outranks it — another allow rule would be outranked the same way',
436
+ 'approval.ruleOffer.absence.askRuleMatched': 'no "don\'t ask again" option here: an ask rule matches this call and keeps asking — an allow rule changes nothing while it stands; to stop being asked, review your ask rules',
437
+ 'approval.ruleOffer.absence.askRuleMatchedDeploymentList': 'no "don\'t ask again" option here: this deployment asks about every call to this tool and your own rules cannot switch that off — the "in this session" option stops it asking again until the session ends',
438
+ 'approval.ruleOffer.absence.laneCannotSpeak': 'no "don\'t ask again" option here: this approval lane cannot persist rules',
439
+ 'approval.ruleOffer.absence.unknown': 'no "don\'t ask again" option here (the reason is one this build does not know yet)',
440
+ 'approval.ruleOffer.uncovered.redirection': 'always asks (shell redirection)',
441
+ 'approval.ruleOffer.uncovered.noRuleForm': 'no coverable rule form',
442
+ 'approval.ruleOffer.uncovered.capOverflow': 'trimmed by the offer cap',
443
+ 'approval.ruleOffer.uncovered.unknown': 'a reason this build does not know yet',
444
+ 'approval.mandate.generic': 'no saved allow rule and no remembered answer can retire this question; each call is settled on its own — by you here or by an automatic check the deployment runs — and an answer covers only that call',
445
+ 'approval.mandate.noAutomaticCheck': 'no saved allow rule and no remembered answer can retire this question, and no automatic check answers it; each call is settled on its own, by you here, and an answer covers only that call',
446
+ 'approval.mandate.word.operatorAlways': 'this deployment requires a separate confirmation for each shell command, and this call is one of them',
447
+ 'approval.mandate.word.toolMarks': 'this tool declares that it reaches outside this machine or makes changes that cannot be undone',
448
+ 'approval.mandate.word.probeMandate': 'the check run on this call marked it as needing its own confirmation (the built-in shell check does so for a read outside the directories allowed for this session)',
449
+ 'approval.mandate.word.probeUnanswered': 'the check run on this call did not answer (it timed out or failed; this client cannot tell which), so whether the call stays inside the directories allowed for this session is unknown',
450
+ 'approval.mandate.word.writeProtection': "this change lands on a protected location (the agent's own configuration), which is confirmed one change at a time",
451
+ 'approval.mandate.word.targetUnresolved': 'where this change lands on disk could not be determined (a link on the way could not be examined, or the target could not be resolved), so whether it lands on a guarded location is unknown',
452
+ 'approval.mandate.unknownWord': 'the reason reported for this confirmation is not one this client recognises, so it shows no reason',
453
+ 'approval.card.payloadUnreadable': 'This client cannot read the format of this approval card, so only its basic facts are shown — decide from those, or deny it if you are not sure what it will do.',
454
+ 'approval.card.more.one': '1 more reason for this card is not shown.',
455
+ 'approval.card.more.other': '{count} more reasons for this card are not shown.',
456
+ 'approval.card.denialLimit.plain': 'auto-deny limit reached — auto mode denied enough calls on its own that the engine now wants a real human decision; {consecutive} consecutive / {total} total automatic denials so far; the limit that tripped: {limit}',
457
+ 'approval.card.denialLimit.withAutoDeny': 'auto-deny limit reached — auto mode denied enough calls on its own that the engine now wants a real human decision; {consecutive} consecutive / {total} total automatic denials so far; the limit that tripped: {limit}; the engine auto-denies it in {seconds}s if nobody answers',
458
+ 'approval.card.shadow.unreadable': 'An allow rule matched this call but cannot clear it; which rule could not be read, so this one is confirmed individually.',
459
+ 'approval.card.shadow.single': 'Your saved permission rule {entry} still exists — it just cannot clear this particular call, so this one is confirmed individually.',
460
+ 'approval.card.shadow.several': 'Allow rules matched this call but cannot clear it, so this one is confirmed individually — {members}.',
461
+ 'approval.card.shadow.unrecognisedSource': 'an unrecognised source',
462
+ 'approval.card.shadow.memberUnreadable': '{word} (could not be read)',
463
+ 'approval.card.shadow.memberWithParts': '{word}: {parts}',
464
+ 'approval.card.shadow.partJoin': '; ',
465
+ 'approval.card.shadow.moreNotListed': 'and {count} more not listed',
466
+ 'approval.card.shadow.notListed': '{count} not listed',
467
+ 'approval.card.shadow.partUnreadable': 'part of it could not be read',
468
+ 'approval.probe.withProse': 'An automatic check could not clear this call, so it is asking you.',
469
+ 'approval.probe.withProseCode': 'An automatic check could not clear this call, so it is asking you (check code: {code}).',
470
+ 'approval.probe.noProse': 'An automatic check could not clear this call, so it is asking you; the engine did not say the specific reason.',
471
+ 'approval.probe.noProseCode': 'An automatic check could not clear this call, so it is asking you; the engine did not say the specific reason (check code: {code}).',
472
+ 'approval.probe.proseJoin': '{sentence} {prose}',
473
+ 'approval.priorCard.earlier.allowed': 'you already approved an earlier one',
474
+ 'approval.priorCard.earlier.denied': 'an earlier one was denied',
475
+ 'approval.priorCard.earlier.shown': 'an earlier one was shown first',
476
+ 'approval.priorCard.fromRule': 'This is a second approval for the same call: {earlier}, which your ask rule asked for. This one is a separate check, not from your ask rule, and needs its own answer.',
477
+ 'approval.priorCard.plain': 'This is a second approval for the same call: {earlier}. This one is a separate check and needs its own answer.',
478
+ 'approval.classifier.noRulingError': 'The auto-mode classifier could not run for this call (it failed), so it is asking you instead.',
479
+ 'approval.classifier.noRulingTimeout': 'The auto-mode classifier could not run for this call (it timed out), so it is asking you instead.',
480
+ 'approval.classifier.noRulingParseError': 'The auto-mode classifier answered for this call but gave no verdict it could use, so it is asking you instead.',
481
+ 'approval.classifier.noRulingOther': 'The auto-mode classifier did not rule on this call (reason: {reason}), so it is asking you instead.',
482
+ 'approval.classifier.noRulingBare': 'The auto-mode classifier did not rule on this call, so it is asking you instead.',
483
+ 'approval.boundGrants.noSkill': 'This call names no loaded skill, so approving it grants nothing beyond this call.',
484
+ 'approval.boundGrants.listsNoTools': 'Approving this activates the skill shown on the card; it lists no tools to run without asking and none to refuse.',
485
+ 'approval.boundGrants.allowPart.one': '1 tool entry it lists runs without asking once it is active',
486
+ 'approval.boundGrants.allowPart.other': '{count} tool entries it lists run without asking once it is active',
487
+ 'approval.boundGrants.denyPart.one': '1 tool entry is refused for the rest of this run',
488
+ 'approval.boundGrants.denyPart.other': '{count} tool entries are refused for the rest of this run',
489
+ 'approval.boundGrants.activates': 'Approving this activates the skill shown on the card: {allow}, and {deny}.',
490
+ 'session.fileHistoryRefusal.notYet': "Nothing was sent: file checkpointing is turned off in your settings, but this engine's capabilities have not been read yet, so whether it can stop recording file history for a session is unknown and sending now could record it anyway. Try again in a moment; to send regardless and let file history be recorded this time, turn file checkpointing back on in your settings.",
491
+ 'session.fileHistoryRefusal.notSaid': 'Nothing was sent: file checkpointing is turned off in your settings, but this engine did not report whether it can stop recording file history for a session, so sending now could record it anyway. Trying again will not change that while this engine reports the same; to send and let file history be recorded this time, turn file checkpointing back on in your settings.',
492
+ 'session.fileHistoryRefusal.unrecognized': 'Nothing was sent: file checkpointing is turned off in your settings, but this engine reported a file-history capture mode this client does not recognize, so whether it can stop recording file history for a session is unknown and sending now could record it anyway. Trying again will not change that while this engine reports the same; to send and let file history be recorded this time, turn file checkpointing back on in your settings.',
493
+ 'session.fileHistoryRefusal.unreadable': "Nothing was sent: file checkpointing is turned off in your settings, but this engine's report on whether it can stop recording file history for a session could not be read by this client, so sending now could record it anyway. Trying again will not change that while this engine reports the same; to send and let file history be recorded this time, turn file checkpointing back on in your settings.",
494
+ 'model.identity.lane.processEnv': 'the environment this client was started with',
495
+ 'model.identity.lane.settingsEnv': "this client's settings file",
496
+ 'model.identity.lane.modelCatalogFile': 'the local model catalog file',
497
+ 'model.identity.lane.followedSettingsFile': "another tool's settings file that this client follows",
498
+ 'model.identity.lane.followedProviderEnv': 'the provider environment variables this client follows',
499
+ 'model.identity.routeGap.fact.endpointMissing': 'the model rides the OpenAI-compatible route and no gateway address (MODEL_GATEWAY_BASEURL) is set, and the engine refuses to start without one',
500
+ 'model.identity.routeGap.fact.laneCredentialMissing': 'the anthropic channel is selected (MODEL_PROVIDER=anthropic), neither ANTHROPIC_API_KEY nor ANTHROPIC_AUTH_TOKEN is set, and there is no gateway address (MODEL_GATEWAY_BASEURL) to fall back to, so the engine cannot start on any route',
501
+ 'model.identity.routeGap.sentence': '{lane} supplies a model name, but the local engine has no route to reach it — {fact}',
502
+ 'config.hooks.valueShape.nothing': 'nothing',
503
+ 'config.hooks.valueShape.null': 'null',
504
+ 'config.hooks.valueShape.array': 'an array',
505
+ 'config.hooks.valueShape.object': 'an object',
506
+ 'config.hooks.valueShape.typeof': 'a {type}',
507
+ 'config.hooks.valueShape.unreadable': 'unreadable',
508
+ 'config.hooks.forWire.gotShape': 'hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — got {shape}.',
509
+ 'config.hooks.forWire.readPlanThrew': 'hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — reading opts.plan threw.',
510
+ 'config.hooks.forWire.readWireThrew': "hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — reading the plan's wire threw.",
511
+ 'config.hooks.forWire.planUnreadable': 'hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — opts.plan could not be read as a plan.',
512
+ 'config.hooks.forWire.planPassedBare': 'hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — the plan itself was passed; wrap it as { plan }.',
513
+ 'config.hooks.forWire.planMissing': 'hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — opts.plan is missing.',
514
+ 'config.hooks.forWire.planNotPlan': 'hooksForWire: pass { plan } with the plan returned by hooksWirePlan() for this turn — opts.plan is not such a plan (got {shape}).',
515
+ 'config.taskRequest.memoryOff.settingsSectionNotObject': 'memoryOffDeclared: the memory section of settings must be an object — got {shape}.',
516
+ 'config.taskRequest.memoryOff.enabledNotBoolean': 'memoryOffDeclared: memory.enabled in settings must be a boolean when present — got {shape}.',
517
+ 'config.taskRequest.inputKeysUnreadable': 'buildTaskRequest: the key set / property descriptors of the input could not be read (a proxy trap threw) — the declarations cannot be snapshotted safely, so assembly was refused. The error text reports shapes only and never echoes values.',
518
+ 'config.taskRequest.userInvokedSkillsMalformed': 'buildTaskRequest: userInvokedSkills accepts only an array of strings (`[]` / absent = nothing was invoked by name) — got {shape}. This slot carries the skills a person invoked by name: if this layer silently dropped a malformed value, the run would proceed as if nothing was invoked while the declarer believes it was. The value is supplied through the fragment helper userInvokedSkillsDeclaration. The error text reports shapes only and never echoes values.',
519
+ 'config.taskRequest.hostSettingsMalformed': 'buildTaskRequest: hostSettings accepts only the product of hostTurnSettings({ sources }) or absence — got {shape}. The four host-supplied settings sub-keys (hooks / resolved / webSearch / outputStyle) enter the request body only through that product; treating an unreadable product as absent would silently drop the permission snapshot and the hooks. The error text reports shapes only and never echoes values.',
520
+ 'config.taskRequest.hostSuppliedKeysByHand': 'buildTaskRequest: {keys} are supplied by the host through the assembly product — pass hostSettings: hostTurnSettings({ sources: { {fields} } }) instead. From 0.99.0 that is the only path these keys take into the request body (a key left unwired shows up as one row on the product); the input settings keep only the ultracode key the renderer carries. The error text reports key names only and never echoes values.',
521
+ 'config.taskRequest.requireExisting.shapeAbsent': 'absent',
522
+ 'config.taskRequest.requireExisting.shapeEmpty': 'an empty string',
523
+ 'config.taskRequest.requireExisting.layerAssembly': 'this layer rejects it before assembly so it does not cost a round trip.',
524
+ 'config.taskRequest.requireExisting.layerLive': 'this layer (the live defaults layer) re-checks after placement: the mock session constant supplied by the host made this layer remove the session id, and there is no captured session id, while the assertion is not removed (removing it would silently open a new session when none is found) — so it is rejected before sending, without a round trip.',
525
+ 'config.taskRequest.requireExisting.noSession': '{where}: requireExistingSession: true asks to continue an existing session, but sessionId is not a session id ({shape}) — there is no session to continue. The upstream service rejects this shape too (it neither opens a new session nor continues anything); {layer} Fix: pass the id of the session to continue as sessionId; to start a new session, omit requireExistingSession (or pass false). The error text reports shapes only and never echoes values.',
526
+ 'config.assembly.thrownDuringAssembly': '{who}: an error occurred during assembly, so assembly was refused (the original thrown value is in cause).',
527
+ 'session.steerRefusal.notRunning.happened': 'that run is not accepting messages right now — it has just finished, is running on another server, or is not the active run of its session',
528
+ 'session.steerRefusal.notRunning.nextStep': 'check its current state and send the message to the run that is active',
529
+ 'session.steerRefusal.invalidContent.happened': 'the message was refused because its text contains control markers the engine does not accept, so nothing was delivered',
530
+ 'session.steerRefusal.invalidContent.nextStep': 'rewrite the message and send it again',
531
+ 'session.steerRefusal.queueFull.happened': 'that run is paused and already holds as many waiting messages as it can, so this one was not accepted',
532
+ 'session.steerRefusal.queueFull.nextStep': 'send it again once the waiting messages have been delivered (when the run resumes or the session is woken)',
533
+ 'session.steerRefusal.duplicateInputId.happened': 'a different instruction was already accepted under this idempotency key, and that earlier instruction stands',
534
+ 'session.steerRefusal.duplicateInputId.nextStep': 'if you changed the text, send the new text under a new key; otherwise do not resend it — a new key would deliver the same instruction twice',
535
+ 'session.steerRefusal.ambiguousTarget.happened': 'more than one running agent matches that target, so the message was not delivered',
536
+ 'session.steerRefusal.ambiguousTarget.nextStep': 'address a sub-agent by its tool-call id; a workflow agent cannot be singled out while another running agent shares its label, so send it again once only one does',
537
+ 'session.steerRefusal.stillRunning.happened': 'that agent is still running, so it cannot be resumed',
538
+ 'session.steerRefusal.stillRunning.nextStep': 'send it a message instead, or wait for it to finish',
539
+ 'session.steerRefusal.blockedByHook.happened': 'the message was not accepted: a prompt check on this deployment blocked it, so nothing was delivered',
540
+ 'session.steerRefusal.blockedByHook.nextStep': 'edit the message and send it again — that is not a duplicate submission',
541
+ 'session.steerRefusal.ledgerUnavailable.happened': 'the server could not record the message and refused it before anything reached the engine, so nothing was delivered',
542
+ 'session.steerRefusal.ledgerUnavailable.nextStep': 'send the same text again later',
543
+ 'session.steerRefusal.steeringOther.happened': 'the message was refused for a reason this version does not recognise, so it did not land',
544
+ 'session.steerRefusal.steeringOther.nextStep': 'report its error code if this keeps happening; do not guess what it means',
545
+ 'session.steerRefusal.steeringOtherUnknown.happened': 'the message was refused for a reason this version does not recognise, and whether it was delivered is not known',
546
+ 'session.steerRefusal.steeringOtherUnknown.nextStep': 'do not resend it as if it had certainly been dropped — check the run first, and report its error code if this keeps happening',
547
+ 'session.steerRefusal.advice': '{happened} — {nextStep}',
548
+ 'session.steerRefusal.hostQueue.queued': 'it stays queued and will be submitted as-is when this turn ends',
549
+ 'session.steerRefusal.hostQueue.dropped': 'it was not kept; {nextStep}',
550
+ 'notice.capability.subject.userInvokedSkills': 'user-invoked skills',
551
+ 'notice.capability.subject.skillToolLists': 'skill tool lists',
552
+ 'notice.capability.subject.permissionRulesWrite': 'permission-rule write entry',
553
+ 'notice.capability.subject.workflowsJournal': 'workflow journal',
554
+ 'notice.capability.subject.sessionPolicy': 'per-session rule face',
555
+ 'notice.capability.subject.mcpProbe': 'per-server MCP status face',
556
+ 'notice.capability.unreadable.subject': "{subject} could not be read — the engine's /v1/capabilities report arrived, but this entry is not in a form this client reads, so it is shown as unknown, not as absent; probing the same engine again will not change it while the engine reports it this way",
557
+ 'notice.capability.unreadable.bare': "could not be read — the engine's /v1/capabilities report arrived, but this entry is not in a form this client reads, so it is shown as unknown, not as absent; probing the same engine again will not change it while the engine reports it this way",
558
+ 'notice.capability.unobserved': '{subject} not observed — the engine reports it on /v1/capabilities ({key}); this process has no usable capabilities reading cached for it (none received, the last one was unreadable, or the last one was discarded when the engine connection was reset; this process cannot tell which)',
559
+ 'notice.capability.userInvokedSkills.notReported': 'user-invoked skills not reported by this engine — this does not say whether it accepts them, so skills the user names on a request are not sent',
560
+ 'notice.capability.userInvokedSkills.absent': 'user-invoked skills off on this deployment — naming skills on a request is not accepted',
561
+ 'notice.capability.userInvokedSkills.present': 'user-invoked skills on — skills the user names on a request take effect when the run starts',
562
+ 'notice.capability.skillToolLists.notReported': 'skill tool lists not reported by this engine — this does not say whether it reads them, so the tool lists on request skills may not limit any tool',
563
+ 'notice.capability.skillToolLists.absent': 'skill tool lists off on this deployment — tool lists on request skills are not read',
564
+ 'notice.capability.skillToolLists.present': 'skill tool lists on — a request skill’s allowed and disallowed tool lists are read as this run’s rules',
565
+ 'notice.capability.permissionRulesWrite.notReported': 'permission-rule write entry not reported by this engine — this does not say whether the entry exists, so hide it rather than calling it',
566
+ 'notice.capability.permissionRulesWrite.absent': 'permission-rule write entry unreachable for this call — either the rules lane is not open on this deployment, or this call cannot bring a verifiable identity; the engine reports one bit for both, so this client cannot tell which',
567
+ 'notice.capability.permissionRulesWrite.present': 'permission-rule write entry reachable for this call — a per-call attempt still answers for itself whether the direction, text, and scope are accepted',
568
+ 'notice.capability.workflowsJournal.notReported': 'workflow journal not reported by this engine — this does not say whether it has the separate journal flag, so the workflow listing flag still covers the journal',
569
+ 'notice.capability.workflowsJournal.absent': 'no workflow journal on this deployment — workflows can be listed and followed, but their execution journal cannot be read',
570
+ 'notice.capability.workflowsJournal.present': 'workflow journal on — a workflow’s execution journal can be read',
571
+ 'notice.capability.sessionPolicy.notReported': 'per-session rule face not reported by this engine — this says nothing about whether the face exists, so read the rules rather than writing them blind',
572
+ 'notice.capability.sessionPolicy.absent': 'no per-session rule store on this deployment — reading and writing this session’s tool rules is unavailable here',
573
+ 'notice.capability.sessionPolicy.present': 'per-session rule face on — this session’s tool rules can be read, and a tightening write is accepted or refused by the engine call by call',
574
+ 'notice.capability.mcpProbe.unobserved': 'per-server MCP status face not observed — the engine reports whether it has one on /v1/capabilities; this process has no usable capabilities reading cached for it (none received, the last one was unreadable, or the last one was discarded when the engine connection was reset; this process cannot tell which)',
575
+ 'notice.capability.mcpProbe.notReported': 'per-server MCP status face not reported by this engine — this says nothing about whether the face exists, so that path may not exist here (asking it may answer with a machine-readable route-not-found, though a timeout or an uncoded gateway answer says nothing either way); prefer the session panel last-leg roster where that panel carries one, and otherwise show this reason rather than an entry that cannot answer',
576
+ 'notice.capability.mcpProbe.absent': 'per-server MCP status face reported off on this deployment — this engine answers no readings there; this client does not guess why, and whether caller-supplied declarations are honored is a separate position with its own answer',
577
+ 'notice.capability.mcpProbe.present': 'per-server MCP status face on — this engine dials its own declared MCP servers on request, with no run, and a probe of caller-supplied declarations answers with the very same body shape',
578
+ 'notice.capability.hands.noneStem': 'this leg of the run was assembled with NO built-in file-and-shell tools',
579
+ 'notice.capability.hands.noneTail': "so on this leg the model had no tool of the engine's own for editing files or running commands (tools mounted by other conditions, such as external servers, and sub-runs delegated to other legs are not covered by this reading)",
580
+ 'notice.capability.hands.noneLine': '{stem} — {why}, {tail}',
581
+ 'notice.capability.hands.notReported': 'whether this leg has built-in file-and-shell tools is not stated here — the engine did not report its hands seam (the static half of a manifest never does); the tool roster may still answer it',
582
+ 'notice.capability.hands.seamMounted': 'this leg of the run was assembled with its built-in file tools mounted — the engine says so; whether a shell is reachable is answered by the tool roster, not by this statement',
583
+ 'notice.capability.hands.whyNoReason': 'the engine states it mounted no hands on this leg (it gave no reason)',
584
+ 'notice.capability.hands.whyNoExecutionEnv': 'the engine states it mounted no hands on this leg because no execution environment was supplied',
585
+ 'notice.capability.hands.whyUnknownReason': 'the engine states it mounted no hands on this leg (reason: {reason}, a word this build does not know)',
586
+ 'notice.capability.hands.rosterMounted': 'this run was assembled with file-and-shell tools mounted ({rows} of them)',
587
+ 'notice.capability.hands.rosterNotMounted': '{stem} — the engine reports a roster and not one row was mounted by that condition, {tail}',
588
+ 'notice.capability.hands.unknownNoManifest': 'whether this run has file-and-shell tools is unknown — no assembly manifest was observed for it',
589
+ 'notice.capability.hands.unknownNoRoster': 'whether this run has file-and-shell tools is unknown — the manifest carries no tool roster (the static half never does; only an engine-minted effective manifest reports one)',
590
+ 'notice.capability.hands.unknownRosterUnreadable': 'whether this run has file-and-shell tools is unknown — the tool roster could not be read in the shape this reader knows',
591
+ 'notice.capability.hands.unknownMountConditionAbsent': 'whether this run has file-and-shell tools is unknown — this engine does not report which condition mounted each tool, so an empty count here would be a fact about the reader, not about the run',
592
+ 'rules.sessionPolicy.tighten.written': 'Session rules saved (version {rev}) — the record now holds everything it already had plus the entries sent here, and it applies from this session’s next tool gate onward; the step already running is not interrupted.',
593
+ 'rules.sessionPolicy.tighten.conflict': 'Session rules were changed by someone else while this tightening was being written, twice in a row — nothing was written. Re-read the current rules and try again, or let the other writer finish first.',
594
+ 'rules.sessionPolicy.tighten.loosenForbidden': 'The engine refused this write because it would relax the session rules: at least one entry sent here widens what is allowed rather than narrowing it. Only entries that add restrictions are accepted on this path.',
595
+ 'rules.sessionPolicy.tighten.capabilityAbsent': 'This deployment does not keep per-session tool rules, so there is nothing to tighten here.',
596
+ 'rules.sessionPolicy.tighten.capabilityNotReported': 'This engine does not say whether it keeps per-session tool rules, so the tightening entry stays hidden rather than being written blind.',
597
+ 'rules.sessionPolicy.tighten.earlierGrammar': 'Nothing was written: this session’s rules were saved before the current rule grammar, when an allow entry written in a tool’s own rule form (such as Bash(git:*)) was read as a plain tool name and so allowed nothing. Writing the record back now would read those entries in the current grammar, where they do allow calls — a widening nobody asked for — so the record was left as it is. Rewrite this session’s allow entries in the current form, or take those entries out, before changing its rules here.',
598
+ 'rules.sessionPolicy.tighten.inertEntry': 'The engine refused to write these session rules, and the stored record was not changed at all: one entry in them reads as matching nothing — written in, it would neither block nor allow any call (the engine’s own error text names the entry and why). Correct that entry or take it out, then write the rules again. If that entry was already in this session’s rule record, it has to be removed from the record before the record can be written again.',
599
+ 'rules.sessionPolicy.tighten.unknown.faceUnavailable': 'This deployment does not keep per-session tool rules, so nothing was written.',
600
+ 'rules.sessionPolicy.tighten.unknown.sessionNotFound': 'This session is not readable from here — it may not exist, or it may belong to someone else (the engine answers both the same way, so this client cannot tell which); nothing was written.',
601
+ 'rules.sessionPolicy.tighten.unknown.sessionOwnerless': 'This session has no owner, so a rule written for it could never be read back; nothing was written. Attach an identity to the session and try again.',
602
+ 'rules.sessionPolicy.tighten.unknown.unauthorized': 'This call could not present a verifiable identity, so nothing was written.',
603
+ 'rules.sessionPolicy.tighten.unknown.requestRejected': 'The engine rejected the shape of this rule record, so nothing was written. Fix the entries before sending them again.',
604
+ 'rules.sessionPolicy.tighten.unknown.storeCorrupt': 'The engine could not establish which version this session’s rules are at and refused to stamp a new one, so nothing was written. The entries sent here are not the problem — this needs an operator to look at the rule store.',
605
+ 'rules.sessionPolicy.tighten.unknown.readUnreadable': 'The session’s current rules could not be read, so nothing was written — writing over a record that cannot be read would replace real restrictions with an empty one.',
606
+ 'rules.sessionPolicy.tighten.unknown.readFailed': 'The session’s current rules could not be fetched, so nothing was written.',
607
+ 'rules.sessionPolicy.tighten.unknown.writeRefused': 'The engine refused this write, so nothing was written. Re-read the current rules before trying again.',
608
+ 'rules.sessionPolicy.tighten.unknown.writeIndeterminate': 'The write never came back with an answer from the engine — it may or may not have taken effect. Re-read the current rules before writing anything else.',
609
+ 'rules.sessionPolicy.tighten.unknown.writeReceiptUnreadable': 'The tightening was sent but the engine’s answer could not be read — it may already be in effect. Re-read the current rules before writing anything else.',
610
+ 'rules.sessionPolicy.tighten.unknown.writeReceiptMismatch': 'The tightening was sent but the engine’s answer does not account for it (the version did not advance, the entries sent here are not in the returned record, or the record came back without the rule-grammar mark it was sent with, so its entries may now read differently) — it may already be in effect. Re-read the current rules before writing anything else.',
611
+ 'approval.settleHuman.resumed': '{what} — the engine accepted this decision and resumed the parked call{where}. Watch the transcript for what that call does.{tail}',
612
+ 'approval.settleHuman.resumedLate': '{what} late — the engine accepted this decision after the approval window had closed and resumed the parked call{where}. Watch the transcript for what that call does.{tail}',
613
+ 'approval.settleHuman.expiredReaped': 'that approval sat past its deadline and the engine reaped it — nothing was run, and your answer was NOT recorded. If the step is still needed, ask for it again.',
614
+ 'approval.settleHuman.settledElsewhere': 'the engine is no longer holding that approval for you — your answer was NOT recorded. It may already have been decided elsewhere (and that step may have run): check the transcript before asking for it again.',
615
+ 'rules.origin.user': 'added by you',
616
+ 'rules.origin.importedCc': 'imported',
617
+ 'rules.origin.starter': 'preset',
618
+ 'rules.origin.unknownWord': 'an origin this build does not know',
619
+ 'rules.origin.none': 'unknown origin',
620
+ 'rules.origin.join': ' + ',
621
+ 'rules.scope.all': 'all projects',
622
+ 'rules.scope.unknown': 'a scope this build does not know',
623
+ 'rules.revoke.thisRule': 'this rule',
624
+ 'rules.revoke.removed.yes.notice': '{rule}: a tombstone was written, but the rule is still live — it was approved again during the call.',
625
+ 'rules.revoke.removed.yes.change': 'Revoked saved rule {rule} (still live — approved again meanwhile)',
626
+ 'rules.revoke.removed.unknown.notice': '{rule}: a tombstone was written, but whether the rule is still live could not be confirmed — treat it as still in effect and check the list.',
627
+ 'rules.revoke.removed.unknown.change': 'Revoked saved rule {rule} (liveness could not be confirmed — treated as still in effect)',
628
+ 'rules.revoke.removed.no.notice': 'Removed {rule}.',
629
+ 'rules.revoke.removed.no.change': 'Revoked saved rule {rule}',
630
+ 'rules.revoke.nothingWritten.yes.notice': '{rule}: nothing was written, and the rule is still live — it was not removed; check the list.',
631
+ 'rules.revoke.nothingWritten.yes.change': 'Removing saved rule {rule} wrote nothing — the rule is still live',
632
+ 'rules.revoke.nothingWritten.unknown.notice': '{rule}: nothing was written, and whether the rule is still live could not be confirmed — treat it as still in effect and check the list.',
633
+ 'rules.revoke.nothingWritten.unknown.change': 'Removing saved rule {rule} wrote nothing — liveness could not be confirmed',
634
+ 'rules.revoke.nothingWritten.no.notice': '{rule}: nothing to remove.',
635
+ 'rules.revoke.nothingWritten.no.change': 'Removing saved rule {rule} wrote nothing (nothing to remove)',
636
+ 'rules.revoke.absent.notice': '{rule}: the engine did not say what this removal did, so whether anything was removed is unclear — check the list.',
637
+ 'rules.revoke.absent.change': 'Removing saved rule {rule} came back without saying what it did',
638
+ 'rules.revoke.unrecognised.notice': '{rule}: the engine answered with a status this build does not know, so whether anything was removed is unclear — check the list.',
639
+ 'rules.revoke.unrecognised.change': 'Removing saved rule {rule} returned a status this build does not know',
640
+ 'rules.revoke.liveness.yes': ' It also reports the rule is still live.',
641
+ 'rules.revoke.liveness.unknown': ' Whether the rule is still live could not be confirmed either.',
642
+ 'rules.match.exact': 'exact match',
643
+ 'rules.match.prefix': 'prefix match',
644
+ 'rules.match.wildcard': 'wildcard match',
645
+ 'rules.match.subpath': 'subpath match',
646
+ 'rules.match.path': 'path match',
647
+ 'rules.match.name': 'skill name match',
648
+ 'rules.match.namePrefix': 'skill name prefix match',
649
+ 'rules.match.host': 'web domain match (one host)',
650
+ 'rules.match.subdomain': 'web domain match (every host under the domain)',
651
+ 'rules.match.unreported': 'an unreported match form',
652
+ 'rules.match.unknown': 'a match form this build does not know',
653
+ 'model.tier.blurb.ultra': 'reserved above max — binds when a stronger model lands',
654
+ 'model.tier.blurb.max': 'hardest problems — deep reasoning, big refactors',
655
+ 'model.tier.blurb.pro': 'everyday driving — the default tier',
656
+ 'model.tier.blurb.flash': 'fast + cheap — titles, recaps, volume work',
657
+ 'model.tier.blurb.lite': 'cheapest — bulk classification, simple lookups',
658
+ 'model.catalog.candidateRejected': 'The deployment refused its most recent configuration change{which} and is still running on the configuration before it — models or settings added by that change are not in effect',
659
+ 'notice.failure.headline.connectionLostNotSent': 'The engine is unreachable — your message did not run. Check that the engine is up, then send it again.',
660
+ 'notice.failure.headline.connectionLost': 'The connection to the engine was lost — it is not known whether your message ran. Check the run’s status, or reattach to it, before sending it again.',
661
+ 'notice.failure.headline.timeout': 'The event stream went silent — the run may still be going on the engine. Check its status before sending again.',
662
+ 'notice.failure.headline.parked': 'The event stream ended while the run had not reached a terminal state — the run is likely parked waiting for a decision, not crashed. Check its status and decide anything pending; the turn did not complete here.',
663
+ 'notice.failure.headline.internal': 'This client hit an internal error — it is a bug in the client, not an engine outage, and the turn did not complete.',
664
+ 'notice.failure.quota.fiveHour': 'Your 5-hour quota is used up',
665
+ 'notice.failure.quota.weekly': 'Your weekly quota is used up',
666
+ 'notice.failure.quota.budgetPersonal': 'Your personal budget is used up',
667
+ 'notice.failure.quota.budgetPool': 'Budget pool "{pool}" quota is used up',
668
+ 'notice.failure.quota.budget': 'Your budget quota is used up',
669
+ 'notice.failure.quota.usage': 'Your usage quota is used up',
670
+ 'notice.failure.quota.remainingBudget': '{amount} remaining',
671
+ 'notice.failure.quota.remainingTokens': '{count} tokens remaining',
672
+ 'notice.failure.quota.resetAt': 'expected to reset at {time}',
673
+ 'notice.failure.quota.resetAround': 'expected to reset around {time} (estimated)',
674
+ 'notice.failure.quota.refresh': 'you can also request a quota refresh',
675
+ 'notice.failure.quota.noBypass': 'switching models does not bypass this limit',
676
+ 'notice.failure.quota.join': ' · ',
677
+ 'notice.failure.quota.instantOtherDay': '{month} {day} {time}',
678
+ 'notice.failure.month.jan': 'Jan',
679
+ 'notice.failure.month.feb': 'Feb',
680
+ 'notice.failure.month.mar': 'Mar',
681
+ 'notice.failure.month.apr': 'Apr',
682
+ 'notice.failure.month.may': 'May',
683
+ 'notice.failure.month.jun': 'Jun',
684
+ 'notice.failure.month.jul': 'Jul',
685
+ 'notice.failure.month.aug': 'Aug',
686
+ 'notice.failure.month.sep': 'Sep',
687
+ 'notice.failure.month.oct': 'Oct',
688
+ 'notice.failure.month.nov': 'Nov',
689
+ 'notice.failure.month.dec': 'Dec',
690
+ 'notice.failure.settings.lead': 'This submit was refused before it ran, so the settings it carried are NOT in effect for this message. If the row above names settings keys: the ones listed unknown are a spelling problem — fix the name in the settings file and send again; the ones listed unsupported are settings this service does not wire — stop sending them (extra directories ride the request itself, not settings).',
691
+ 'notice.failure.settings.safety': 'SAFETY: that includes {risks} — this turn ran (or failed) without them, so do not treat it as if they applied.',
692
+ 'notice.failure.settings.stillLocal': 'These keys still apply locally — do not delete them from the settings file to make the error go away.',
693
+ 'notice.failure.settings.denyRules.one': '{count} deny rule',
694
+ 'notice.failure.settings.denyRules.other': '{count} deny rules',
695
+ 'notice.failure.settings.askRules.one': '{count} ask rule',
696
+ 'notice.failure.settings.askRules.other': '{count} ask rules',
697
+ 'notice.failure.settings.riskJoin': ', ',
698
+ 'notice.failure.wait.one': 'The server asked to retry after 1 second (Retry-After).',
699
+ 'notice.failure.wait.other': 'The server asked to retry after {seconds} seconds (Retry-After).',
118
700
  };
119
701
  export const EN_MESSAGES = Object.freeze(EN);