@sema-agent/server 7.130.0 → 7.132.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 (294) hide show
  1. package/MIGRATION.md +396 -0
  2. package/README.md +13 -6
  3. package/README.zh-CN.md +9 -5
  4. package/USAGE.md +187 -50
  5. package/dist/approval-card.d.ts +3 -1
  6. package/dist/approval-card.js +2 -3
  7. package/dist/audit.d.ts +7 -10
  8. package/dist/audit.js +4 -1
  9. package/dist/auth-bridge.d.ts +4 -0
  10. package/dist/auth-bridge.js +10 -11
  11. package/dist/bench/s1/live-deps.js +2 -0
  12. package/dist/boot/deployment-mods.d.ts +31 -0
  13. package/dist/boot/deployment-mods.js +26 -0
  14. package/dist/boot/execution-env.d.ts +1 -1
  15. package/dist/boot/execution-env.js +19 -6
  16. package/dist/boot/memory-boundary.d.ts +2 -2
  17. package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
  18. package/dist/boot/read-deny-anchor-audit.js +36 -0
  19. package/dist/boot/resolve-spec.d.ts +1 -5
  20. package/dist/boot/resolve-spec.js +56 -61
  21. package/dist/boot/runner-deps.d.ts +19 -8
  22. package/dist/boot/runner-deps.js +14 -2
  23. package/dist/boot/session-faces.d.ts +1 -7
  24. package/dist/boot/stage-02-web-admin-pull.js +9 -1
  25. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  26. package/dist/boot/stage-03-store-backend.js +2 -2
  27. package/dist/boot/stage-04-stores.d.ts +1 -1
  28. package/dist/boot/stage-05-execution-env.d.ts +4 -4
  29. package/dist/boot/stage-05-execution-env.js +7 -10
  30. package/dist/boot/stage-06-runners.d.ts +2 -2
  31. package/dist/boot/stage-06-runners.js +5 -4
  32. package/dist/boot/stage-07-capability-layer.d.ts +2 -2
  33. package/dist/boot/stage-07-capability-layer.js +3 -3
  34. package/dist/boot/stage-08-reapers.d.ts +2 -2
  35. package/dist/boot/stage-09-leader.d.ts +3 -9
  36. package/dist/boot/stage-10-http-server.d.ts +3 -9
  37. package/dist/boot/stage-10-http-server.js +12 -10
  38. package/dist/boot/stores.d.ts +1 -1
  39. package/dist/boot/stores.js +5 -6
  40. package/dist/boot/web-admin.d.ts +0 -3
  41. package/dist/boot/web-admin.js +35 -35
  42. package/dist/brain.js +17 -22
  43. package/dist/budget.js +5 -4
  44. package/dist/caller-text-echo.d.ts +20 -0
  45. package/dist/caller-text-echo.js +24 -0
  46. package/dist/capabilities/brand-identity.d.ts +26 -0
  47. package/dist/capabilities/brand-identity.js +27 -0
  48. package/dist/capabilities/builtin-tools.js +2 -1
  49. package/dist/capabilities/center-plugins.js +1 -1
  50. package/dist/capabilities/center-prompts.d.ts +32 -59
  51. package/dist/capabilities/center-prompts.js +18 -32
  52. package/dist/capabilities/composite-members.d.ts +1 -0
  53. package/dist/capabilities/composite-members.js +1 -0
  54. package/dist/capabilities/engine-capabilities.js +2 -1
  55. package/dist/capabilities/hands-lane.d.ts +9 -6
  56. package/dist/capabilities/hands-lane.js +3 -3
  57. package/dist/capabilities/host-tool-names.d.ts +17 -0
  58. package/dist/capabilities/host-tool-names.js +15 -0
  59. package/dist/capabilities/mcp-probe.d.ts +14 -1
  60. package/dist/capabilities/mcp-probe.js +22 -133
  61. package/dist/capabilities/repo-tools.js +4 -3
  62. package/dist/capabilities/scenarios.d.ts +42 -47
  63. package/dist/capabilities/scenarios.js +19 -35
  64. package/dist/capabilities/select-environment-tool.js +2 -1
  65. package/dist/capabilities/send-user-file-tool.d.ts +0 -1
  66. package/dist/capabilities/send-user-file-tool.js +2 -2
  67. package/dist/capabilities/skills.d.ts +19 -4
  68. package/dist/capabilities/skills.js +30 -10
  69. package/dist/capabilities/tool-defer.js +2 -1
  70. package/dist/config-catalog.js +22 -11
  71. package/dist/config-invariants.js +2 -2
  72. package/dist/config-lkg.d.ts +9 -9
  73. package/dist/config-lkg.js +20 -4
  74. package/dist/config-provider.d.ts +3 -1
  75. package/dist/config-provider.js +14 -6
  76. package/dist/config-types.d.ts +13 -9
  77. package/dist/config.d.ts +2 -2
  78. package/dist/config.js +34 -20
  79. package/dist/device-ws-protocol.d.ts +1 -1
  80. package/dist/device-ws-protocol.js +1 -0
  81. package/dist/elicitation.d.ts +7 -0
  82. package/dist/elicitation.js +20 -5
  83. package/dist/env-name-allowlist-knobs.d.ts +12 -2
  84. package/dist/env-name-allowlist-knobs.js +5 -4
  85. package/dist/exec-bounds.d.ts +15 -3
  86. package/dist/exec-bounds.js +4 -0
  87. package/dist/execution-lane-caps.d.ts +9 -2
  88. package/dist/execution-lane-caps.js +11 -0
  89. package/dist/hooks/classic-stations.d.ts +86 -0
  90. package/dist/hooks/classic-stations.js +27 -0
  91. package/dist/hooks/hook-llm.d.ts +8 -5
  92. package/dist/hooks/hook-llm.js +80 -37
  93. package/dist/hooks/hook-runner.d.ts +273 -75
  94. package/dist/hooks/hook-runner.js +293 -317
  95. package/dist/http/admission.d.ts +8 -2
  96. package/dist/http/admission.js +103 -59
  97. package/dist/http/approval-sweeps.js +59 -18
  98. package/dist/http/checkpoint-ctx.d.ts +36 -18
  99. package/dist/http/checkpoint-ctx.js +14 -10
  100. package/dist/http/claimed-run.d.ts +13 -0
  101. package/dist/http/claimed-run.js +15 -0
  102. package/dist/http/device-placement.js +5 -10
  103. package/dist/http/dispatch.d.ts +0 -4
  104. package/dist/http/dispatch.js +6 -10
  105. package/dist/http/durable-run-leg.d.ts +2 -1
  106. package/dist/http/durable-run-leg.js +5 -3
  107. package/dist/http/health-self-report.d.ts +7 -5
  108. package/dist/http/health-self-report.js +4 -18
  109. package/dist/http/principal-gate.d.ts +23 -6
  110. package/dist/http/principal-gate.js +24 -5
  111. package/dist/http/refusal-body.d.ts +21 -0
  112. package/dist/http/refusal-body.js +4 -0
  113. package/dist/http/request-guards.d.ts +27 -0
  114. package/dist/http/request-guards.js +24 -3
  115. package/dist/http/resume-legs.d.ts +25 -0
  116. package/dist/http/resume-legs.js +48 -26
  117. package/dist/http/routes/approvals-assistant.js +1 -1
  118. package/dist/http/routes/capabilities.js +7 -17
  119. package/dist/http/routes/diagnostics.js +1 -1
  120. package/dist/http/routes/rules.js +2 -2
  121. package/dist/http/routes/runs.js +13 -17
  122. package/dist/http/routes/session-sync.js +4 -2
  123. package/dist/http/routes/sessions.js +23 -11
  124. package/dist/http/routes/shared-memory.js +2 -13
  125. package/dist/http/routes/side-query.js +2 -3
  126. package/dist/http/routes/tasks.js +34 -19
  127. package/dist/http/scenario-read-face.d.ts +14 -0
  128. package/dist/http/scenario-read-face.js +5 -0
  129. package/dist/http/send.d.ts +13 -1
  130. package/dist/http/send.js +12 -1
  131. package/dist/http/server.d.ts +37 -23
  132. package/dist/http/server.js +30 -4
  133. package/dist/http/stored-body-replay.d.ts +10 -3
  134. package/dist/http/stored-body-replay.js +27 -6
  135. package/dist/http/submit-ctx.d.ts +25 -0
  136. package/dist/http/submit-ctx.js +39 -0
  137. package/dist/http/wire-types.d.ts +18 -5
  138. package/dist/index.d.ts +3 -2
  139. package/dist/index.js +3 -2
  140. package/dist/lane-home-probe.d.ts +43 -0
  141. package/dist/lane-home-probe.js +35 -0
  142. package/dist/limit-refusal.d.ts +47 -0
  143. package/dist/limit-refusal.js +12 -0
  144. package/dist/main.js +1 -1
  145. package/dist/mcp-assertion-header.d.ts +3 -11
  146. package/dist/mcp-assertion-header.js +3 -9
  147. package/dist/mcp-tool-faces.d.ts +5 -0
  148. package/dist/mcp-tool-faces.js +5 -1
  149. package/dist/memory-scope.d.ts +1 -1
  150. package/dist/model-entry-refusal.d.ts +1 -7
  151. package/dist/model-provider.d.ts +39 -12
  152. package/dist/model-provider.js +19 -2
  153. package/dist/model-route-endpoint.d.ts +52 -12
  154. package/dist/model-route-endpoint.js +48 -26
  155. package/dist/model-route-gap.d.ts +5 -4
  156. package/dist/model-route-gap.js +1 -1
  157. package/dist/model-select.d.ts +58 -0
  158. package/dist/model-select.js +31 -0
  159. package/dist/namespaced-rule-name.d.ts +7 -4
  160. package/dist/namespaced-rule-name.js +4 -3
  161. package/dist/observability/cost-taxonomy.d.ts +7 -7
  162. package/dist/observability/fail-open.d.ts +53 -12
  163. package/dist/observability/fail-open.js +47 -7
  164. package/dist/observability/metrics.js +3 -1
  165. package/dist/observability/prompt-manifest.d.ts +47 -82
  166. package/dist/observability/prompt-manifest.js +119 -17
  167. package/dist/observability/run-terminal.js +14 -6
  168. package/dist/observability/secret-env-scrub.d.ts +13 -1
  169. package/dist/observability/secret-env-scrub.js +13 -1
  170. package/dist/observability/tool-trace.d.ts +16 -21
  171. package/dist/observability/tool-trace.js +51 -42
  172. package/dist/per-task-image.d.ts +7 -1
  173. package/dist/per-task-image.js +3 -3
  174. package/dist/plain-string-record.d.ts +25 -0
  175. package/dist/plain-string-record.js +32 -0
  176. package/dist/plugins/blob-backend.d.ts +68 -13
  177. package/dist/plugins/blob-backend.js +53 -10
  178. package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
  179. package/dist/plugins/checkpoint-store-sql.js +39 -26
  180. package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
  181. package/dist/plugins/k8s-bg-scripts.js +22 -0
  182. package/dist/plugins/local-checkpoint-store.js +5 -2
  183. package/dist/plugins/local-session-store.js +3 -3
  184. package/dist/plugins/one-time-migrations.d.ts +147 -91
  185. package/dist/plugins/one-time-migrations.js +372 -208
  186. package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
  187. package/dist/plugins/permission-rule-store-sql.js +4 -18
  188. package/dist/plugins/pg-session-storage.d.ts +4 -5
  189. package/dist/plugins/pg-session-storage.js +7 -17
  190. package/dist/plugins/remote-env-adb.d.ts +6 -0
  191. package/dist/plugins/remote-env-adb.js +9 -4
  192. package/dist/plugins/remote-env-device.js +3 -0
  193. package/dist/plugins/remote-env-e2b.d.ts +1 -1
  194. package/dist/plugins/remote-env-e2b.js +21 -9
  195. package/dist/plugins/remote-env-host.d.ts +9 -9
  196. package/dist/plugins/remote-env-host.js +10 -32
  197. package/dist/plugins/remote-env-k8s.d.ts +95 -26
  198. package/dist/plugins/remote-env-k8s.js +265 -90
  199. package/dist/plugins/remote-env-local-docker.d.ts +20 -1
  200. package/dist/plugins/remote-env-local-docker.js +77 -9
  201. package/dist/plugins/remote-env-ssh.d.ts +15 -0
  202. package/dist/plugins/remote-env-ssh.js +109 -3
  203. package/dist/plugins/remote-shell.d.ts +0 -1
  204. package/dist/plugins/remote-shell.js +1 -2
  205. package/dist/plugins/retention-store-sql.js +6 -2
  206. package/dist/plugins/schema-consistency.d.ts +54 -0
  207. package/dist/plugins/schema-consistency.js +52 -0
  208. package/dist/plugins/session-epoch-anchor.d.ts +13 -0
  209. package/dist/plugins/session-epoch-anchor.js +23 -0
  210. package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
  211. package/dist/plugins/shared-memory-store-sql.js +5 -16
  212. package/dist/plugins/sql-driver.d.ts +141 -0
  213. package/dist/plugins/sql-driver.js +115 -1
  214. package/dist/plugins/sql-errors.d.ts +41 -0
  215. package/dist/plugins/sql-errors.js +36 -0
  216. package/dist/plugins/store-backend.js +2 -1
  217. package/dist/plugins/tidb-session-storage.d.ts +7 -11
  218. package/dist/plugins/tidb-session-storage.js +6 -16
  219. package/dist/plugins/tidb-session-store.js +1 -1
  220. package/dist/prompts-domain-validate.d.ts +17 -61
  221. package/dist/prompts-domain-validate.js +9 -119
  222. package/dist/question.d.ts +18 -9
  223. package/dist/question.js +21 -13
  224. package/dist/request-key-closure.d.ts +4 -4
  225. package/dist/request-key-closure.js +18 -13
  226. package/dist/rule-entry-list.d.ts +134 -24
  227. package/dist/rule-entry-list.js +162 -30
  228. package/dist/run-local.d.ts +3 -3
  229. package/dist/run-local.js +26 -25
  230. package/dist/runs.d.ts +48 -2
  231. package/dist/runs.js +61 -2
  232. package/dist/server-secret-env.d.ts +44 -18
  233. package/dist/server-secret-env.js +49 -8
  234. package/dist/session-incarnation.d.ts +15 -5
  235. package/dist/session-incarnation.js +16 -9
  236. package/dist/session-titler.js +12 -2
  237. package/dist/spec-fields.d.ts +34 -18
  238. package/dist/spec-fields.js +46 -53
  239. package/dist/sql-engine-posture.d.ts +29 -4
  240. package/dist/sql-engine-posture.js +36 -1
  241. package/dist/stored-request-hooks-m20.d.ts +23 -0
  242. package/dist/stored-request-hooks-m20.js +124 -0
  243. package/dist/stored-request-tool-axes-m19.d.ts +20 -5
  244. package/dist/stored-request-tool-axes-m19.js +30 -2
  245. package/dist/task-a2a.d.ts +9 -1
  246. package/dist/task-a2a.js +73 -47
  247. package/dist/task-mcp.d.ts +54 -102
  248. package/dist/task-mcp.js +194 -92
  249. package/dist/task-settings.d.ts +47 -25
  250. package/dist/task-settings.js +46 -61
  251. package/dist/text-bidi.d.ts +3 -46
  252. package/dist/text-bidi.js +3 -3
  253. package/dist/tool-approval.d.ts +1 -1
  254. package/dist/trace/core-keyset-guard.d.ts +24 -4
  255. package/dist/trace/engine-notice-wire.d.ts +11 -3
  256. package/dist/trace/engine-notice-wire.js +8 -1
  257. package/dist/trace/ledger-events.d.ts +3 -1
  258. package/dist/trace/ledger-sink.d.ts +29 -0
  259. package/dist/trace/ledger-sink.js +15 -1
  260. package/dist/trace/model-segment.js +1 -1
  261. package/dist/trace/project.d.ts +25 -6
  262. package/dist/trace/project.js +68 -22
  263. package/dist/trace/wire-projection-faces.d.ts +80 -2
  264. package/dist/trace/wire-projection-faces.js +23 -1
  265. package/dist/user-authored-text.d.ts +7 -0
  266. package/dist/user-authored-text.js +3 -0
  267. package/dist/web-admin-client/apply-effective.js +10 -5
  268. package/dist/web-admin-client/candidate-gate.d.ts +6 -6
  269. package/dist/web-admin-client/candidate-gate.js +3 -3
  270. package/dist/web-admin-client/http-client.js +0 -6
  271. package/dist/web-admin-client/read-warnings.d.ts +13 -0
  272. package/dist/web-admin-client/read-warnings.js +10 -0
  273. package/dist/web-admin-client/skills-mcp.d.ts +3 -0
  274. package/dist/web-admin-client/skills-mcp.js +9 -6
  275. package/dist/web-admin-client/types.d.ts +3 -4
  276. package/dist/workspace-cache.d.ts +35 -0
  277. package/dist/workspace-cache.js +36 -0
  278. package/dist/workspace-space.d.ts +3 -2
  279. package/dist/workspace-space.js +2 -0
  280. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
  281. package/package.json +4 -4
  282. package/scripts/drain-check-local.mjs +37 -3
  283. package/scripts/drain-check.mysql.sql +30 -2
  284. package/scripts/drain-check.pg.sql +29 -2
  285. package/dist/capabilities/memory-notice.d.ts +0 -138
  286. package/dist/capabilities/memory-notice.js +0 -64
  287. package/dist/capabilities/prompt.d.ts +0 -17
  288. package/dist/capabilities/prompt.js +0 -6
  289. package/dist/mcp-content-origin.d.ts +0 -34
  290. package/dist/mcp-content-origin.js +0 -10
  291. package/dist/tool-axis-words.d.ts +0 -27
  292. package/dist/tool-axis-words.js +0 -9
  293. package/dist/wire-name-bound.d.ts +0 -14
  294. package/dist/wire-name-bound.js +0 -13
@@ -2,18 +2,17 @@ import { realpathSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { NodeExecutionEnv, QUESTION_AWAITS_RESUME, WRITE_EXEMPT_DIR_COVERS_ROOT_CODE, deriveAskEffective, expandTiers, modePolicyOf, resolveAskSeamForm } from "@sema-agent/core";
4
4
  import { cappedCeiling } from "../budget.js";
5
- import { centerPromptProvider, centerIdentityAssembled } from "../capabilities/center-prompts.js";
5
+ import { recordFailOpen } from "../observability/fail-open.js";
6
6
  import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
7
7
  import { sendUserFileTool } from "../capabilities/send-user-file-tool.js";
8
- import { createScenarioGate, mergeUserSkills, selectScenario } from "../capabilities/scenarios.js";
8
+ import { buildPromptSeats, createScenarioGate, mergeUserSkills, selectScenario } from "../capabilities/scenarios.js";
9
9
  import { stampHandsLane, toolPolicyForHands } from "../capabilities/hands-lane.js";
10
- import { buildNoticeLaneFacts, noPersistentMemoryNotice, withNoPersistentMemoryNotice } from "../capabilities/memory-notice.js";
11
10
  import { applyLongtailDefer } from "../capabilities/tool-defer.js";
12
11
  import { assertGuardPatternsUsable, buildApprovalGrantNotice, buildOnlySensitiveBaselineWarning, createApprovalBaselinePolicy, createDeploymentGovernanceInputs } from "../deployment-governance.js";
13
12
  import { createDeploymentListExemption, gateIntentUnserviceableReason, singleUserAutoAcceptBaselineApplies } from "../approval.js";
14
13
  import { acceptShellScratchpadDir, buildEnvFacts, egressForRemoteExec, ensureScratchpadDir, resumeFactsForLane, scratchpadCoveringTaskRoot } from "../env-facts.js";
15
14
  import { FleetEventBus } from "../fleet/fleet-bus.js";
16
- import { composeHooks, createTaskHooks } from "../hooks/hook-runner.js";
15
+ import { createSettingsHooksRegistration, settingsHooksBudgetMs } from "../hooks/hook-runner.js";
17
16
  import { HOST_POSTURE_REFUSED_CODE, taskInheritEnvRefusal, taskWriteFaceRefusal } from "../hosted-posture.js";
18
17
  import { headerStr } from "../http/principal-gate.js";
19
18
  import { explicitOperatorOk } from "../http/server.js";
@@ -35,19 +34,19 @@ import { normalizeAttachments, normalizeResilience, normalizeResumeAtMode, norma
35
34
  import { isAbsoluteHostPath } from "@sema-agent/settings-schema";
36
35
  import { cwdHonored, deviceCwdHonored, effectiveHostWorkspace, inProcessSingleUserLane, parseAdditionalDirectories, satisfiedByProcessCwd, shellEnvMismatchCount } from "../task-cwd.js";
37
36
  import { assertRequestA2aUnlocked, resolveRequestA2a } from "../task-a2a.js";
38
- import { assertRequestMcpContentOrigin, assertRequestMcpIdentityHeaders, assertRequestMcpToolAxes, assertRequestMcpUnlocked, resolveRequestMcp } from "../task-mcp.js";
37
+ import { assertRequestMcpEntries, assertRequestMcpUnlocked, resolveRequestMcp } from "../task-mcp.js";
39
38
  import { storedToolAxesRereadM19 } from "../stored-request-tool-axes-m19.js";
40
- import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, acceptAppendSystemPrompt, applyTaskSettings, effectivePermissionMode, effectiveThinking, hasConstitutionAnchors, parseTaskSettings, taskHooksHonored, providerDropsAppend, settingsPermissionBucketIssue, withPermissionMode } from "../task-settings.js";
41
- import { skillDenyInertEntryOf } from "../rule-entry-list.js";
39
+ import { storedHooksRereadM20 } from "../stored-request-hooks-m20.js";
40
+ import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, REQUEST_SETTINGS_REFUSAL_PREFIX, acceptAppendSystemPrompt, applyTaskSettings, effectivePermissionMode, effectiveThinking, parseTaskSettings, taskHooksHonored, settingsPermissionBucketIssue, withPermissionMode } from "../task-settings.js";
41
+ import { inertToolListEntryOf } from "../rule-entry-list.js";
42
42
  import { TENANCY_WALL_CLOCK_BASE_SEC, enableForkFromBody, normalizeRetainSubagentSessions, selfOrchestrationFromBody } from "../task-workflow.js";
43
43
  import { redactSecrets } from "../trace/redact.js";
44
44
  import { DeferredSandboxPathEnv, isSandboxPathAdjudicationLane, sandboxPathEnvSlots } from "./deferred-sandbox-path-env.js";
45
45
  import { executionLaneCaps, executionLaneHomeDir, executionLaneOf } from "../execution-lane-caps.js";
46
46
  import { effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
47
47
  import { withUnattendedLeg } from "../unattended-permission-mode.js";
48
- import { memoryFaceMounted } from "../memory-scope.js";
49
48
  export function createResolveSpec(ctx) {
50
- const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getCenterPrompts, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, durableEnabled, approvalExemptionStore, checkpointStore, deploymentHooks, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, } = ctx;
49
+ const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, durableEnabled, approvalExemptionStore, checkpointStore, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, } = ctx;
51
50
  const scenarioGate = createScenarioGate({ config, scenarios, principalCaps, logger }, "enforce");
52
51
  assertGuardPatternsUsable(config);
53
52
  const onlySensitiveBaseline = buildOnlySensitiveBaselineWarning(config, {
@@ -71,11 +70,7 @@ export function createResolveSpec(ctx) {
71
70
  throw createCodedHttpError(501, "capability.checkpoint_store_required", seatRefusal);
72
71
  assertRequestMcpUnlocked(body.mcpServers, lockedKeys);
73
72
  if (opts?.leg === "fresh")
74
- assertRequestMcpContentOrigin(body.mcpServers);
75
- if (opts?.leg === "fresh")
76
- assertRequestMcpIdentityHeaders(body.mcpServers);
77
- if (opts?.leg === "fresh")
78
- assertRequestMcpToolAxes(body.mcpServers);
73
+ assertRequestMcpEntries(body.mcpServers);
79
74
  if (opts?.leg === "fresh") {
80
75
  const conflict = scratchpadCoveringTaskRoot({
81
76
  cwd: body.cwd,
@@ -115,9 +110,21 @@ export function createResolveSpec(ctx) {
115
110
  throw new HttpError(400, bucketIssue.message, { code: "request.field_invalid", extra: bucketIssue.fields });
116
111
  }
117
112
  {
118
- const skillDeny = skillDenyInertEntryOf(body);
119
- if (skillDeny !== undefined)
120
- throw new HttpError(400, skillDeny.message, { code: "request.field_invalid" });
113
+ const replay = opts?.leg === "resume";
114
+ const inertList = inertToolListEntryOf(body, replay ? ["deny"] : undefined);
115
+ if (inertList !== undefined)
116
+ throw new HttpError(400, inertList.message, { code: inertList.code, ...(inertList.extra !== undefined ? { extra: { ...inertList.extra } } : {}) });
117
+ if (replay) {
118
+ const stale = inertToolListEntryOf(body, ["allow"]);
119
+ if (stale !== undefined) {
120
+ logger.warn("stored_allow_list_inert_resumed", {
121
+ sessionId: auth?.sessionId ?? null,
122
+ layer: stale.layer,
123
+ sentence: stale.message,
124
+ note: "this resumed task's stored request carries an allow-list entry the engine reads as nothing (a retired name, a case twin, an unreadable spelling or a content form): the entry stays as written and grants nothing — the task ran that way before the upgrade, so it continues; fix the entry in a new submission to get what it was meant to allow",
125
+ });
126
+ }
127
+ }
121
128
  }
122
129
  assertRequestA2aUnlocked(body.a2aPeers, lockedKeys);
123
130
  const gated = await gateScenarioAndAppend(body, auth, opts);
@@ -143,22 +150,23 @@ export function createResolveSpec(ctx) {
143
150
  const scenarioName = await scenarioGate(auth?.principal, body.scenario);
144
151
  gateExecutionLane(await principalCaps?.executionRuling(auth?.principal), executionLaneOf(config.remoteExec?.provider), logger);
145
152
  const cap = selectScenario(scenarios, scenarioName)(body, auth?.principal, auth?.sessionId !== undefined ? { sessionId: auth.sessionId } : {});
146
- const centerDecls = getCenterPrompts()?.declarations;
147
- const appendLessPack = centerDecls
148
- ? centerIdentityAssembled(centerDecls, scenarioName, hasConstitutionAnchors)
149
- : providerDropsAppend(cap.promptProvider, typeof body.systemPrompt === "string" ? body.systemPrompt : undefined);
150
- const acceptedAppend = acceptAppendSystemPrompt(body.appendSystemPrompt, (detail) => logger.warn("append_system_prompt_dropped", { detail, sessionId: auth?.sessionId ?? null }), appendLessPack);
153
+ const acceptedAppend = acceptAppendSystemPrompt(body.appendSystemPrompt, (detail) => logger.warn("append_system_prompt_dropped", { detail, sessionId: auth?.sessionId ?? null }));
151
154
  const objective = typeof body.objective === "string" ? body.objective : "";
152
- const parsedSettings = parseTaskSettings(body.settings);
153
- if (opts?.leg === "fresh" && appendLessPack) {
154
- const riderPresent = typeof body.appendSystemPrompt === "string" && body.appendSystemPrompt.length > 0;
155
- if (riderPresent || parsedSettings.settings?.outputStyle) {
156
- throw new HttpError(400, `${riderPresent ? "appendSystemPrompt" : "settings.outputStyle"} is not supported when the effective prompt is already assembled (constitution anchors in systemPrompt, or a center assembled-identity pack for this scenario): the assembler's pass-through path cannot mount the append slot — fold it into the assembled prompt instead`);
157
- }
158
- }
155
+ const parsedSettings = parseTaskSettings(body.settings, opts?.leg === "fresh" || !taskHooksHonored(config) ? {} : { storedHooksReread: storedHooksRereadM20(new Date().toISOString().slice(0, 10)) });
159
156
  if (parsedSettings.deferred.length > 0) {
160
157
  logger.warn("task_settings_deferred", { fields: parsedSettings.deferred, sessionId: auth?.sessionId ?? null });
161
158
  }
159
+ if (parsedSettings.hooksReread !== undefined) {
160
+ logger.warn("hooks_read_as_before_upgrade", {
161
+ migration: "M20",
162
+ sessionId: auth?.sessionId ?? null,
163
+ stripped: parsedSettings.hooksReread.stripped,
164
+ note: "this replayed request was stored before the upgrade and its settings.hooks carries a shape the hooks reader now refuses (a key the reader does not know that hides a guard-event member, or a JSON `__proto__` event key); while one-time migration M20 is open the keys named in `stripped` are dropped — what the pre-upgrade reader dropped — and the rest goes through the same reader again, so the guard hooks keep running; once the window closes the same request has its whole settings.hooks left out",
165
+ });
166
+ }
167
+ if (parsedSettings.deferred.includes("hooks") && taskHooksHonored(config)) {
168
+ recordFailOpen("server.hooks.resume-reader-refused", `leg=${opts?.leg ?? "resume"}`);
169
+ }
162
170
  let attachmentNotice;
163
171
  {
164
172
  const reqAtt = body.attachmentIds;
@@ -191,7 +199,7 @@ export function createResolveSpec(ctx) {
191
199
  }
192
200
  }
193
201
  }
194
- return { scenarioName, cap, hands: cap.hands, centerDecls, appendLessPack, acceptedAppend, objective, parsedSettings, attachmentNotice };
202
+ return { scenarioName, cap, hands: cap.hands, acceptedAppend, objective, parsedSettings, attachmentNotice };
195
203
  };
196
204
  const bindSettingsCwdEnvAndModel = (body, auth, gated, opts) => {
197
205
  const { objective, parsedSettings } = gated;
@@ -229,7 +237,7 @@ export function createResolveSpec(ctx) {
229
237
  logger.warn("task_hooks_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
230
238
  return undefined;
231
239
  }
232
- return createTaskHooks(hc, {
240
+ return createSettingsHooksRegistration(hc, {
233
241
  logger,
234
242
  sessionId: auth?.sessionId ?? "",
235
243
  cwd: (auth?.sessionId ? perSessionCwd.get(auth.sessionId) : undefined) ?? process.cwd(),
@@ -249,7 +257,7 @@ export function createResolveSpec(ctx) {
249
257
  : false,
250
258
  }
251
259
  : {}),
252
- });
260
+ }, settingsHooksBudgetMs(config));
253
261
  })();
254
262
  const rawAddDirs = body.additionalDirectories;
255
263
  const additionalDirectories = cwdHonored(config) ? parseAdditionalDirectories(rawAddDirs) : undefined;
@@ -289,6 +297,7 @@ export function createResolveSpec(ctx) {
289
297
  }
290
298
  return { taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked };
291
299
  };
300
+ const NO_ANCHOR_HINT = "no rewind anchor is recorded under that handle (a prompt that carried attachments records none when its attachment frames were interrupted or their count did not match)";
292
301
  const resolveHistoryAnchors = async (body, auth) => {
293
302
  let resumeAtEntryId;
294
303
  if (typeof body.resumeAt === "string" && body.resumeAt.length > 0) {
@@ -298,7 +307,7 @@ export function createResolveSpec(ctx) {
298
307
  throw new HttpError(501, "resume-at is not available on this worker (no session-store backend for the anchor map)");
299
308
  resumeAtEntryId = await resumeAnchorStore.resolve(auth.sessionId, body.resumeAt, auth.principal ?? null);
300
309
  if (resumeAtEntryId === undefined)
301
- throw new HttpError(404, "resumeAt: no such message in this session (resume_at.unknown_event)", { code: "resume_at.unknown_event" });
310
+ throw new HttpError(404, `resumeAt: no such message in this session (resume_at.unknown_event) — ${NO_ANCHOR_HINT}; give an explicit resumeAt`, { code: "resume_at.unknown_event" });
302
311
  }
303
312
  let rewindFilesToEntryId;
304
313
  if (resumeAtEntryId === undefined && typeof body.rewindFilesTo === "string" && body.rewindFilesTo.length > 0) {
@@ -308,7 +317,7 @@ export function createResolveSpec(ctx) {
308
317
  throw new HttpError(501, "rewind-files-to is not available on this worker (no session-store backend for the anchor map)");
309
318
  rewindFilesToEntryId = await resumeAnchorStore.resolve(auth.sessionId, body.rewindFilesTo, auth.principal ?? null);
310
319
  if (rewindFilesToEntryId === undefined)
311
- throw new HttpError(404, "rewindFilesTo: no such message in this session (rewind_files_to.unknown_event)", { code: "rewind_files_to.unknown_event" });
320
+ throw new HttpError(404, `rewindFilesTo: no such message in this session (rewind_files_to.unknown_event) — ${NO_ANCHOR_HINT}; name another prompt`, { code: "rewind_files_to.unknown_event" });
312
321
  }
313
322
  const s4ProjectId = auth?.resolvedProjectId ?? (typeof body.projectId === "string" && body.projectId ? body.projectId.toLowerCase() : undefined);
314
323
  const s4DefaultScopes = s4ProjectId ? config.projects[s4ProjectId]?.defaultScopes : undefined;
@@ -329,15 +338,17 @@ export function createResolveSpec(ctx) {
329
338
  return deriveAskEffective(askForm.form, "unresolved") === "human_reachable";
330
339
  };
331
340
  const assembleSpecLiteral = (body, auth, req, opts, parts, effMode) => {
332
- const { scenarioName, cap, hands, centerDecls, acceptedAppend, parsedSettings, attachmentNotice, taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked, resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, } = parts;
341
+ const { scenarioName, cap, hands, acceptedAppend, parsedSettings, attachmentNotice, taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked, resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, } = parts;
342
+ const storedToolAxes = opts?.leg === "fresh" ? undefined : storedToolAxesRereadM19(new Date().toISOString().slice(0, 10));
333
343
  const spec = {
334
344
  objective: attachmentNotice ? `${picked.cleanedObjective}\n\n${attachmentNotice}` : picked.cleanedObjective,
335
- systemPrompt: typeof body.systemPrompt === "string" ? body.systemPrompt : undefined,
345
+ ...buildPromptSeats(scenarioName, cap.prompt, typeof body.systemPrompt === "string" ? body.systemPrompt : undefined),
336
346
  appendSystemPrompt: acceptedAppend,
337
347
  ...(body.outputStyle !== undefined ? { outputStyle: body.outputStyle } : {}),
338
348
  sessionId: auth?.sessionId,
339
349
  principal: auth?.principal,
340
350
  images: body.images,
351
+ ...(body.userAttachments !== undefined ? { userAttachments: body.userAttachments } : {}),
341
352
  ...(body.clientContext ? { clientContext: { timeZone: body.clientContext.timeZone, userEmail: body.clientContext.userEmail } } : {}),
342
353
  ...(() => {
343
354
  const ct = body.compaction?.clampTolerance;
@@ -381,7 +392,7 @@ export function createResolveSpec(ctx) {
381
392
  resilience: normalizeResilience(body.resilience, explicitOperatorOk(auth?.principal, config.operatorPrincipals)),
382
393
  finalVerification: cap.finalVerification === true || body.finalVerification === true ? true : undefined,
383
394
  attachments: normalizeAttachments(body.attachments),
384
- ...(taskHooks ? { hooks: composeHooks(deploymentHooks, taskHooks) } : {}),
395
+ ...(taskHooks ? { mods: [taskHooks] } : {}),
385
396
  model: picked.model,
386
397
  ...((() => {
387
398
  if (typeof body.compactionModel !== "string" || body.compactionModel.length === 0)
@@ -460,9 +471,8 @@ export function createResolveSpec(ctx) {
460
471
  ...(() => { const v = toolNameListFromBody(body.userInvokedSkills); return v ? { userInvokedSkills: v } : {}; })(),
461
472
  ...(parsedSettings.settings?.skillListingBudgetFraction !== undefined ? { skillListingBudgetFraction: parsedSettings.settings.skillListingBudgetFraction } : {}),
462
473
  ...(parsedSettings.settings?.skillListingMaxDescChars !== undefined ? { skillListingMaxDescChars: parsedSettings.settings.skillListingMaxDescChars } : {}),
463
- mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, logger, opts?.onNotice !== undefined ? { sessionId: auth?.sessionId, emit: opts.onNotice } : undefined, opts?.leg === "fresh" ? undefined : storedToolAxesRereadM19(new Date().toISOString().slice(0, 10))),
464
- a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), body.a2aPeers, config, logger),
465
- promptProvider: centerDecls ? centerPromptProvider(centerDecls, scenarioName) : cap.promptProvider,
474
+ mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, logger, opts?.onNotice !== undefined ? { sessionId: auth?.sessionId, emit: opts.onNotice } : undefined, storedToolAxes),
475
+ a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), body.a2aPeers, config, logger, opts?.leg === "fresh" ? "fresh" : "resume", storedToolAxes),
466
476
  toolPolicy: toolPolicyForHands(hands, durableEnabled
467
477
  ? createApprovalBaselinePolicy(config, {
468
478
  kind: "durable",
@@ -496,7 +506,7 @@ export function createResolveSpec(ctx) {
496
506
  return spec;
497
507
  };
498
508
  const foldGovernanceAndSettings = async (body, auth, spec, gated, effMode) => {
499
- const { appendLessPack, acceptedAppend, parsedSettings } = gated;
509
+ const { acceptedAppend, parsedSettings } = gated;
500
510
  const hostSemanticsLane = !isSandboxPathAdjudicationLane(config.remoteExec?.provider);
501
511
  const laneHomeBase = () => {
502
512
  const home = executionLaneHomeDir(config);
@@ -524,11 +534,6 @@ export function createResolveSpec(ctx) {
524
534
  const governedBase = applyRuntimeGovernance(spec, createDeploymentGovernanceInputs(config, pathAdjudication));
525
535
  let governed = governedBase;
526
536
  let effectiveSettings = effMode ? withPermissionMode(parsedSettings.settings, effMode) : parsedSettings.settings;
527
- if (appendLessPack && effectiveSettings?.outputStyle) {
528
- logger.warn("output_style_dropped", { detail: "the effective prompt pack cannot mount the append slot (already-assembled systemPrompt or center assembled-identity declaration)", sessionId: auth?.sessionId ?? null });
529
- const { outputStyle: _dropped, ...rest } = effectiveSettings;
530
- effectiveSettings = Object.keys(rest).length > 0 ? rest : undefined;
531
- }
532
537
  if (effectiveSettings?.outputStyle && acceptedAppend && acceptedAppend.length + 2 + effectiveSettings.outputStyle.length > MAX_SETTINGS_OUTPUT_STYLE_CHARS) {
533
538
  logger.warn("output_style_dropped", { detail: `combined append carriers exceed the ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} cap (rider ${acceptedAppend.length} + style ${effectiveSettings.outputStyle.length}) — style dropped (pre-cap stored body on a resume leg?)`, sessionId: auth?.sessionId ?? null });
534
539
  const { outputStyle: _dropped2, ...rest2 } = effectiveSettings;
@@ -600,19 +605,9 @@ export function createResolveSpec(ctx) {
600
605
  ...(e.detail !== undefined ? { extra: { writeExemptDirCoversRoot: e.detail } } : {}),
601
606
  });
602
607
  }
603
- throw new HttpError(422, `request settings cannot be applied as written: ${e.message}`);
608
+ throw new HttpError(422, `${REQUEST_SETTINGS_REFUSAL_PREFIX}${e.message}`);
604
609
  }
605
610
  }
606
- const notice = noPersistentMemoryNotice({
607
- memoryFaceMounted: memoryFaceMounted(governed.memory),
608
- declaredCapable: effectiveMemoryPersistenceCapable(config),
609
- hands: gated.hands,
610
- handsReadOnly: governed.handsReadOnly === true,
611
- ...buildNoticeLaneFacts(executionLaneOf(config.remoteExec?.provider)),
612
- });
613
- if (notice !== "silent") {
614
- governed = { ...governed, promptProvider: withNoPersistentMemoryNotice(governed.promptProvider, notice) };
615
- }
616
611
  return { governed, scratchpadDir, hostSemanticsLane };
617
612
  };
618
613
  const applyImageFactsAndRouting = async (body, auth, governed, folded) => {
@@ -622,13 +617,13 @@ export function createResolveSpec(ctx) {
622
617
  let resolvedImageCaps;
623
618
  if (taskImageProfile !== undefined) {
624
619
  if (config.remoteExec?.provider !== "k8s") {
625
- throw new HttpError(400, "sandboxImageProfile is only supported on the k8s sandbox backend");
620
+ throw createCodedHttpError(501, "capability.k8s_lane_required", "sandboxImageProfile is only supported on the k8s sandbox backend");
626
621
  }
627
622
  if (!imageIndex) {
628
- throw new HttpError(400, "sandboxImageProfile requires the image index (web-admin backend not configured)");
623
+ throw createCodedHttpError(501, "capability.image_index_required", "sandboxImageProfile requires the sandbox-image-pool, which needs a SQL store backend (DB_BACKEND=mysql|pg) — this deployment's store wires no image index");
629
624
  }
630
625
  if (!auth?.sessionId) {
631
- throw new HttpError(400, "sandboxImageProfile requires a resolved session");
626
+ throw createCodedHttpError(400, "request.precondition_unmet", "sandboxImageProfile requires a resolved session");
632
627
  }
633
628
  const capsNeeded = Array.isArray(body.capabilitiesNeeded)
634
629
  ? body.capabilitiesNeeded.filter((c) => typeof c === "string")
@@ -640,7 +635,7 @@ export function createResolveSpec(ctx) {
640
635
  index: imageIndex,
641
636
  });
642
637
  if (!resolved.ok)
643
- throw new HttpError(resolved.status, resolved.message);
638
+ throw createCodedHttpError(resolved.status, resolved.errorCode, resolved.message);
644
639
  perTaskImage.set(auth.sessionId, resolved.ref);
645
640
  resolvedImageCaps = resolved.capabilities;
646
641
  }
@@ -56,13 +56,16 @@ import type { MailboxRecipientLifecycle } from "../plugins/mailbox-recipient-lif
56
56
  export type RunnerDepsOnAsk = (req: Parameters<ToolApprovalCoordinator["ask"]>[0], signal?: AbortSignal) => Promise<AskOutcome>;
57
57
  export declare function createRunnerDepsOnAsk(toolApproval: ToolApprovalCoordinator | undefined): RunnerDepsOnAsk | undefined;
58
58
  /** [ref] 件⑤:core `onError(phase:"config")` 的 `classification` 已知词表。⚠️ core d.ts(`RunnerDeps.onError` 注)只登记了
59
- * prompt-cache 相的五词,config 相的词**只在 dist js 出现**(7.35.0 亲扫 dist 下全部 js 的 `phase: "config"` 发射点:四词——
60
- * `interaction-posture-refused`(prepare-config-doors)/ `memory-tools-not-mounted` / `shared-memory-not-mounted`
61
- * (prepare-defer-classify / prepare-project-context)/ `sandbox-admission-unavailable`(prepare-policy-chain));
59
+ * prompt-cache 相的五词,config 相的词**只在 dist js 出现**,发射点有两种写法:字面量(`classification: "<词>"`)与经变量 / 表行发射
60
+ * (`classification: <变量>` 取自同文件的字面量初值,或 `classification: <表>.classification` 取自同文件的表行)。7.52.0 亲扫六词 ——
61
+ * `interaction-posture-refused`(prepare-config-doors,字面量)/ `sandbox-admission-unavailable`(prepare-policy-chain,字面量)/
62
+ * `memory-tools-not-mounted` / `shared-memory-not-mounted`(core 7.52.0 起一只铸点 `announceMemoryNotMounted`,词在
63
+ * announce-once-ledger 的表行)/ `file-history-no-store` / `file-history-no-env`(prepare-file-history 的 `livenessArm` 变量,core 7.30 起
64
+ * 就在 —— 只认字面量的旧扫描看不见它们,两词一直被标 `classificationKnown:false`、指标折 `unknown`,本版随扫描改读两种写法一并收进表)。
62
65
  * S-877:第五词 `shell-gate-off` 随 core 7.34.0 的 off 车道一起退役(引擎侧零发射点),同批删 —— 它唯一的本仓消费者
63
66
  * (「本 session 显式 bypass ⇒ 降级 info」那条回查腿与 `boot/session-shell-gate-registry.ts` 登记簿)一并删干净。所以这是「按实现亲读」的开集快照,不是 core 类型闭集——词表外的值原样进日志并标
64
67
  * `classificationKnown:false`(指标标签折 `unknown`),不吞不编;与安装包的锁步由 test/boot-runner-deps-shared-base.test.ts
65
- * 的 dist 扫描格钉住(core 加词/收进 d.ts 那天先红)。 */
68
+ * 的 dist 扫描格钉住(两种发射写法都读;读不出词的经变量发射点本身红;core 加词/收进 d.ts 那天先红)。 */
66
69
  export declare const CONFIG_ADVISORY_CLASSIFICATIONS: ReadonlySet<string>;
67
70
  /** S-386:core 的 [ref] 前缀缓存**断裂**探测器交给宿主的根因**闭集**,以及每个词的日志级别。
68
71
  * 闭集**不抄词**:词源直接取 core 公开导出的 `CacheBreakFinding["cause"]`(`@sema-agent/core` 根导出,
@@ -218,14 +221,15 @@ export interface RunnerDepsCtx {
218
221
  * 的「差异键」注释块逐条列了 sessionStore / checkpointStore / 四个座位,**都没提 hands**
219
222
  * —— 也就是说它不是一次有理由的分歧,是漏配(与本函数头注记的 [ref]§三族A 同一个病族)。
220
223
  * 由**调用方**给值(而不是在基座里按 `config` 现算):两条腿的判据本就不同(HTTP 腿按
221
- * `configProvider === "local"` 分 branded/非 branded,run-local 恒是 Sema 本地形),
224
+ * 品牌判官 `isBrandedDeployment`(`capabilities/brand-identity.ts`)分 branded/非 branded,run-local 恒是 Sema 本地形),
222
225
  * 各自算一次、传进来一次,两只 Runner 自动同源。
223
226
  */
224
227
  hands: RunnerDeps["hands"];
225
228
  executionEnvFactory: RunnerDeps["executionEnvFactory"];
226
229
  lspManager: RunnerDeps["lspManager"];
227
230
  fleetBus: FleetEventBus;
228
- deploymentHooks: NonNullable<RunnerDeps["hooks"]>;
231
+ /** 部署座的 mods 注册(stage-05 `createDeploymentMods` 铸、起服自证过)—— 共享基座 ⇒ 主 / handless / hookAgent / sub 每一只 Runner 同一份。 */
232
+ deploymentMods: NonNullable<RunnerDeps["mods"]>;
229
233
  workflowRunStore: WorkflowRunStore | undefined;
230
234
  workflowJournalStore: ServiceWorkflowJournalStore | undefined;
231
235
  workflowAgentRegistry: WorkflowAgentRegistry | undefined;
@@ -237,7 +241,7 @@ export interface RunnerDepsCtx {
237
241
  }
238
242
  /** [ref] A10 留档发现②:main runner `RunnerDeps` 与 main.ts subRunner 字面量之间此前手工重复
239
243
  * 的 ~15 个键,类型标注见 {@link createSharedRunnerDeps} 头注。 */
240
- export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "memoryEngineDir" | "allowedTools" | "models" | "roles" | "tiers" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "hooks" | "toolResultStore" | "checkpointStore" | "hands" | "sessionPolicyStore" | "usageWindows" | "usageWindowStore" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "sharedMemoryStores" | "compliancePostureResolver" | "lockedConfig" | "retentionPolicy" | "onNotice" | "mcpRevocations">;
244
+ export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "memoryEngineDir" | "allowedTools" | "models" | "roles" | "tiers" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "mods" | "toolResultStore" | "checkpointStore" | "hands" | "sessionPolicyStore" | "usageWindows" | "usageWindowStore" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "sharedMemoryStores" | "compliancePostureResolver" | "lockedConfig" | "retentionPolicy" | "onNotice" | "mcpRevocations">;
241
245
  /**
242
246
  * [ref] A10 留档发现②(review 2026-07-29,[ref]§三族A 同源修补的延续):main runner 的
243
247
  * `RunnerDeps` 字面量(下方 `createRunnerDeps`)与 `main.ts` 里 subRunner 的 `new Runner({...})`
@@ -264,7 +268,7 @@ export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDeny
264
268
  * 属性,比再抽一层共享基座更强的同源保证),不重复收纳进这里。
265
269
  */
266
270
  /** 基座真实消费的窄面(Pick)——subRunner 调用点(main.ts)只需凑这 13 个字段,不必造全量 ctx。 */
267
- export type SharedRunnerDepsCtx = Pick<RunnerDepsCtx, "config" | "brain" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "deploymentHooks" | "toolResultStore" | "checkpointStore" | "sessionPolicyStore" | "hands" | "usageWindowStore" | "orgMemoryAdmission" | "sharedMemoryStores" | "logger" | "governanceSeams" | "mcpRevocations" | "metrics" | "engineDataRoot">;
271
+ export type SharedRunnerDepsCtx = Pick<RunnerDepsCtx, "config" | "brain" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "deploymentMods" | "toolResultStore" | "checkpointStore" | "sessionPolicyStore" | "hands" | "usageWindowStore" | "orgMemoryAdmission" | "sharedMemoryStores" | "logger" | "governanceSeams" | "mcpRevocations" | "metrics" | "engineDataRoot">;
268
272
  /** 转发席只需要 `inc` —— 刻意窄到这一个动词,免得把整只 Metrics 拖进这条纯转发腿。 */
269
273
  export interface EngineNoticeMetricsSeat {
270
274
  inc: (name: string, labels?: Record<string, string>) => void;
@@ -317,6 +321,13 @@ export type DeploymentPostureSeats = Pick<RunnerDeps, "readFace" | "readDenyPatt
317
321
  * + LKG 覆写路径(`readDenyPatterns` 席并入它派生的读拒行,`lkgReadDenyRows`)。 */
318
322
  export type DeploymentPostureConfig = Pick<ServiceConfig, Exclude<keyof DeploymentPostureSeats, "allowedTools"> | "approvalGrant" | "configLkgPath">;
319
323
  export declare function buildDeploymentPostureSeats(config: DeploymentPostureConfig): DeploymentPostureSeats;
324
+ /**
325
+ * 部署读拒行**进场**的唯一告知点(非锚定行一行 `read_deny_unanchored_rows`;判据与行形在 `read-deny-anchor-audit.ts`)。律:**一份读拒行的值第一次装进 Runner 席时点名一次** ——
326
+ * 三条入口都经这里:server 起服与 run-local 经 {@link createSharedRunnerDeps}(server 的主 / 子 Runner 各展开一次共享基座、同一份 config ⇒ 只说一次),中心热换在换席成功之后
327
+ * (`boot/web-admin.ts` `applyLiveReadFace`;换席抛 ⇒ config 回滚、不到这里)。值没变 ⇒ 不重复说(只改 face 的热换、同一 config 的第二只 Runner);值变了(热换 A → B → A)⇒ 每次都说。
328
+ * 喂的是 `config.readDenyPatterns`(运维 ∪ 中心 read-face 的行),不是座席族并入 LKG 派生行之后的那一份 —— 派生行是根锚。绝不抛(纯诊断面)。
329
+ */
330
+ export declare function announceReadDenyRows(config: Pick<ServiceConfig, "readDenyPatterns">, logger: Pick<Logger, "warn">): void;
320
331
  export declare function createSharedRunnerDeps(ctx: SharedRunnerDepsCtx): SharedRunnerDeps;
321
332
  export declare function createRunnerDeps(ctx: RunnerDepsCtx): RunnerDeps;
322
333
  //# sourceMappingURL=runner-deps.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { createFileWorkflowScriptStore } from "@sema-agent/core";
2
2
  import { join } from "node:path";
3
3
  import { lkgReadDenyRows } from "../config-lkg.js";
4
+ import { auditReadDenyAnchoring } from "./read-deny-anchor-audit.js";
4
5
  import { fleetBackgroundChildPublisher, FleetEventBus } from "../fleet/fleet-bus.js";
5
6
  import { createMemoryEngineIncidentSink } from "../memory-incident-sink.js";
6
7
  import { assertAutoConsolidationWirable } from "./memory-consolidation.js";
@@ -24,6 +25,8 @@ export function createRunnerDepsOnAsk(toolApproval) {
24
25
  return (req, signal) => toolApproval.ask(req, signal);
25
26
  }
26
27
  export const CONFIG_ADVISORY_CLASSIFICATIONS = new Set([
28
+ "file-history-no-env",
29
+ "file-history-no-store",
27
30
  "interaction-posture-refused",
28
31
  "memory-tools-not-mounted",
29
32
  "sandbox-admission-unavailable",
@@ -76,7 +79,16 @@ export function buildDeploymentPostureSeats(config) {
76
79
  };
77
80
  return seats;
78
81
  }
82
+ const announcedReadDenyRows = new WeakMap();
83
+ export function announceReadDenyRows(config, logger) {
84
+ const key = JSON.stringify(config.readDenyPatterns ?? null);
85
+ if (announcedReadDenyRows.get(config) === key)
86
+ return;
87
+ announcedReadDenyRows.set(config, key);
88
+ auditReadDenyAnchoring({ rows: config.readDenyPatterns, logger });
89
+ }
79
90
  export function createSharedRunnerDeps(ctx) {
91
+ announceReadDenyRows(ctx.config, ctx.logger);
80
92
  const shared = {
81
93
  brain: ctx.brain,
82
94
  onNotice: createEngineNoticeForwarder(ctx.logger, defaultEngineNoticeRouter, ctx.metrics),
@@ -92,7 +104,7 @@ export function createSharedRunnerDeps(ctx) {
92
104
  backgroundAgentStore: ctx.backgroundAgentStore ? ctx.backgroundAgentStore : undefined,
93
105
  mailboxStore: ctx.mailboxStore ? ctx.mailboxStore : undefined,
94
106
  rosterStore: ctx.rosterStore ? ctx.rosterStore : undefined,
95
- hooks: ctx.deploymentHooks,
107
+ mods: ctx.deploymentMods,
96
108
  hands: ctx.hands,
97
109
  toolResultStore: ctx.toolResultStore,
98
110
  checkpointStore: ctx.checkpointStore ? ctx.checkpointStore : undefined,
@@ -226,7 +238,7 @@ export function createRunnerDeps(ctx) {
226
238
  return;
227
239
  }
228
240
  if (ctx.phase === "prompt-constitution") {
229
- logger.warn("prompt_provider_needs_upgrade", { sessionId: ctx.sessionId, info: String(err) });
241
+ logger.warn("prompt_composition_warning", { sessionId: ctx.sessionId, info: String(err) });
230
242
  return;
231
243
  }
232
244
  if (ctx.phase === "rewind") {
@@ -79,13 +79,7 @@ export declare function createSessionFaces(ctx: SessionFacesCtx): {
79
79
  modelId: string;
80
80
  } | null;
81
81
  messages: unknown[];
82
- promptEpoch?: {
83
- epoch: number;
84
- artifactDigest: string;
85
- packId: string;
86
- assemblyApi: number;
87
- activatedBy: "session_start" | "compaction" | "legacy_migration";
88
- };
82
+ promptEpoch?: import("@sema-agent/core").StoredPromptEpoch;
89
83
  } | undefined>) | undefined;
90
84
  sessionWatchRegistry: SessionWatchRegistry | undefined;
91
85
  purgeSession: ((sessionId: string, owner: string | null) => Promise<{
@@ -4,6 +4,9 @@ import { composeExecutionLane, FILE_SOURCED_LANES } from "./execution-lane.js";
4
4
  import { serviceConfigSourceKind } from "../config-provider.js";
5
5
  import { logConfigDirMigration, migrateLocalConfigDirectory } from "../config-d-migration.js";
6
6
  import { defaultModelRefusal, refusedNameMintedRefusal } from "../model-entry-refusal.js";
7
+ import { isRosterGateArmed } from "../config.js";
8
+ import { judgeServedModelRoute } from "../model-route-endpoint.js";
9
+ import { servedModelTableLeg } from "../model-select.js";
7
10
  export async function runStage02(ctx) {
8
11
  const { config, localRoot, logger, metrics } = ctx;
9
12
  const configSource = serviceConfigSourceKind(config);
@@ -11,10 +14,15 @@ export async function runStage02(ctx) {
11
14
  logConfigDirMigration(logger, await migrateLocalConfigDirectory(localRoot));
12
15
  await composeExecutionLane(config, { configSource, localRoot, logger, drivesFromFile: FILE_SOURCED_LANES });
13
16
  const webAdmin = await createWebAdminRuntime({ config, logger, metrics, localRoot });
14
- const noDefaultModel = defaultModelRefusal(config, "env");
17
+ const servedLeg = servedModelTableLeg(config);
18
+ const noDefaultModel = defaultModelRefusal(config, servedLeg);
15
19
  if (noDefaultModel !== undefined) {
16
20
  throw new Error(noDefaultModel);
17
21
  }
22
+ const routeVerdict = judgeServedModelRoute(config, { envTableIsPlaceholder: isRosterGateArmed(config.webAdmin) });
23
+ if (routeVerdict !== undefined) {
24
+ throw new Error(routeVerdict.reason);
25
+ }
18
26
  const mintedRefused = refusedNameMintedRefusal(config);
19
27
  if (mintedRefused !== undefined) {
20
28
  throw new Error(mintedRefused);
@@ -19,7 +19,7 @@ export declare function runStage03(ctx: Awaited<ReturnType<typeof runStage02>>):
19
19
  sessionCaptureRecordStore: import("@sema-agent/core").SessionCaptureRecordStore | undefined;
20
20
  sessionCaptureRecords: import("../index.js").SessionCaptureRecordSource | undefined;
21
21
  sessionStore: import("@sema-agent/core").SessionStore;
22
- sqlEngineFacts: (() => import("../plugins/sql-driver.js").SqlEngineFacts | null) | undefined;
22
+ sqlEngine: import("../plugins/sql-driver.js").SqlEngineReading | undefined;
23
23
  storePosture: import("../store-posture.js").StorePosture;
24
24
  taskAttachmentStore: import("../plugins/task-attachment-store.js").TaskAttachmentStore | undefined;
25
25
  taskListLane: import("./task-list-lane.js").TaskListLane;
@@ -2,10 +2,10 @@ import { uuidv7 } from "@sema-agent/core";
2
2
  import { openStores } from "./stores.js";
3
3
  export async function runStage03(ctx) {
4
4
  const { config, localRoot, logger, metrics } = ctx;
5
- const { backend, storePosture, memoryEngine, engineDataRoot, memorySyncCursors, rosterStore, backgroundAgentStore, taskAttachmentStore, mailboxStore, mailboxRecipientLifecycle, memoryExportBackend, memorySyncRunner, sessionStore, breakerState, usageWindowStore, memoryPosture, taskListLane, sqlEngineFacts, } = await openStores({ config, logger, metrics, localRoot });
5
+ const { backend, storePosture, memoryEngine, engineDataRoot, memorySyncCursors, rosterStore, backgroundAgentStore, taskAttachmentStore, mailboxStore, mailboxRecipientLifecycle, memoryExportBackend, memorySyncRunner, sessionStore, breakerState, usageWindowStore, memoryPosture, taskListLane, sqlEngine, } = await openStores({ config, logger, metrics, localRoot });
6
6
  const instanceId = uuidv7();
7
7
  const sessionCaptureRecords = backend?.sessionCaptureRecords();
8
8
  const sessionCaptureRecordStore = sessionCaptureRecords?.();
9
- return { ...ctx, backend, backgroundAgentStore, breakerState, engineDataRoot, instanceId, mailboxRecipientLifecycle, mailboxStore, memoryEngine, memoryExportBackend, memoryPosture, memorySyncCursors, memorySyncRunner, rosterStore, sessionCaptureRecordStore, sessionCaptureRecords, sessionStore, sqlEngineFacts, storePosture, taskAttachmentStore, taskListLane, usageWindowStore };
9
+ return { ...ctx, backend, backgroundAgentStore, breakerState, engineDataRoot, instanceId, mailboxRecipientLifecycle, mailboxStore, memoryEngine, memoryExportBackend, memoryPosture, memorySyncCursors, memorySyncRunner, rosterStore, sessionCaptureRecordStore, sessionCaptureRecords, sessionStore, sqlEngine, storePosture, taskAttachmentStore, taskListLane, usageWindowStore };
10
10
  }
11
11
  //# sourceMappingURL=stage-03-store-backend.js.map
@@ -60,7 +60,7 @@ export declare function runStage04(ctx: Awaited<ReturnType<typeof runStage03>>):
60
60
  sessionCaptureRecordStore: import("@sema-agent/core").SessionCaptureRecordStore | undefined;
61
61
  sessionCaptureRecords: import("../index.js").SessionCaptureRecordSource | undefined;
62
62
  sessionStore: import("@sema-agent/core").SessionStore;
63
- sqlEngineFacts: (() => import("../plugins/sql-driver.js").SqlEngineFacts | null) | undefined;
63
+ sqlEngine: import("../plugins/sql-driver.js").SqlEngineReading | undefined;
64
64
  storePosture: import("../store-posture.js").StorePosture;
65
65
  taskAttachmentStore: import("../plugins/task-attachment-store.js").TaskAttachmentStore | undefined;
66
66
  taskListLane: import("./task-list-lane.js").TaskListLane;
@@ -1,6 +1,6 @@
1
1
  import type { runStage04 } from "./stage-04-stores.js";
2
- export declare function runStage05(ctx: Awaited<ReturnType<typeof runStage04>>): {
3
- deploymentHooks: import("@sema-agent/core").Hooks;
2
+ export declare function runStage05(ctx: Awaited<ReturnType<typeof runStage04>>): Promise<{
3
+ deploymentMods: readonly import("@sema-agent/core").ModRegistration<import("@sema-agent/core").EngineDollar>[];
4
4
  deviceLane: import("./device-lane.js").DeviceLane | undefined;
5
5
  dropSessionScoped: (sid: string) => void;
6
6
  executionEnvFactory: import("@sema-agent/core").ExecutionEnvFactory | undefined;
@@ -75,7 +75,7 @@ export declare function runStage05(ctx: Awaited<ReturnType<typeof runStage04>>):
75
75
  sessionCaptureRecordStore: import("@sema-agent/core").SessionCaptureRecordStore | undefined;
76
76
  sessionCaptureRecords: import("../index.js").SessionCaptureRecordSource | undefined;
77
77
  sessionStore: import("@sema-agent/core").SessionStore;
78
- sqlEngineFacts: (() => import("../plugins/sql-driver.js").SqlEngineFacts | null) | undefined;
78
+ sqlEngine: import("../plugins/sql-driver.js").SqlEngineReading | undefined;
79
79
  storePosture: import("../store-posture.js").StorePosture;
80
80
  taskAttachmentStore: import("../plugins/task-attachment-store.js").TaskAttachmentStore | undefined;
81
81
  taskListLane: import("./task-list-lane.js").TaskListLane;
@@ -86,5 +86,5 @@ export declare function runStage05(ctx: Awaited<ReturnType<typeof runStage04>>):
86
86
  localRoot: string;
87
87
  logger: import("../index.js").Logger;
88
88
  metrics: import("../index.js").Metrics;
89
- };
89
+ }>;
90
90
  //# sourceMappingURL=stage-05-execution-env.d.ts.map
@@ -1,12 +1,12 @@
1
- import { createToolTracer, createPermissionDeniedMeter } from "../observability/tool-trace.js";
2
- import { composeHooks } from "../hooks/hook-runner.js";
1
+ import { assertDeploymentModsAdmitted, createDeploymentMods } from "./deployment-mods.js";
2
+ import { isBrandedDeployment } from "../capabilities/brand-identity.js";
3
3
  import { assertDeviceLaneWired, createDeviceLane } from "./device-lane.js";
4
4
  import { assertWorkspaceSpaceReadable, createExecutionEnv } from "./execution-env.js";
5
5
  import { incarnationReadOf } from "../session-incarnation.js";
6
6
  import * as facts from "../capability-facts.js";
7
7
  import { sessionStoreLabelOf } from "../store-posture.js";
8
8
  import { runStore } from "./late-binds.js";
9
- export function runStage05(ctx) {
9
+ export async function runStage05(ctx) {
10
10
  const { backend, config, instanceId, logger, metrics, sessionStore, taskAttachmentStore } = ctx;
11
11
  const deviceLane = config.remoteExec?.provider === "device" ? createDeviceLane({ config, logger, metrics, backend, replicaId: instanceId }) : undefined;
12
12
  const incarnationOf = incarnationReadOf(sessionStore);
@@ -14,13 +14,10 @@ export function runStage05(ctx) {
14
14
  const { perTaskImage, sessionEnvSelection, perSessionCwd, setSessionCwd, setSessionShellEnv, setSessionInheritEnv, fenceSessionOwner, dropSessionScoped, executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer, } = createExecutionEnv({ config, logger, metrics, taskAttachmentStore, ...(deviceLane ? { deviceLane } : {}), ...(spaceCommits !== undefined ? { spaceCommits } : {}), ...(incarnationOf !== undefined ? { incarnationOf } : {}) });
15
15
  assertDeviceLaneWired(config.remoteExec?.provider === "device", deviceLane, executionEnvFactory !== undefined);
16
16
  assertWorkspaceSpaceReadable(facts.workspaceSpace(config), { incarnationOf, spaceCommits }, facts.workspaceCache(config), sessionStoreLabelOf(config.sessionBackend, backend?.kind));
17
- const toolTracer = config.toolTrace ? createToolTracer(logger) : undefined;
18
- if (toolTracer)
17
+ const deploymentMods = createDeploymentMods({ metrics, ...(config.toolTrace ? { traceLogger: logger } : {}), brandIdentity: isBrandedDeployment(config) });
18
+ if (config.toolTrace)
19
19
  logger.info("tool_trace_enabled", {});
20
- const deploymentHooks = {
21
- ...(toolTracer ? composeHooks(createPermissionDeniedMeter(metrics), toolTracer) : createPermissionDeniedMeter(metrics)),
22
- ...(config.hooksTimeoutMs !== undefined ? { timeoutMs: config.hooksTimeoutMs } : {}),
23
- };
24
- return { ...ctx, deploymentHooks, deviceLane, dropSessionScoped, executionEnvFactory, fenceSessionOwner, lspManager, spaceReclaimer, perSessionCwd, perTaskImage, sendUserFileTaskEnvs, sessionEnvSelection, setSessionCwd, setSessionInheritEnv, setSessionShellEnv, worktreeReap };
20
+ await assertDeploymentModsAdmitted(deploymentMods);
21
+ return { ...ctx, deploymentMods, deviceLane, dropSessionScoped, executionEnvFactory, fenceSessionOwner, lspManager, spaceReclaimer, perSessionCwd, perTaskImage, sendUserFileTaskEnvs, sessionEnvSelection, setSessionCwd, setSessionInheritEnv, setSessionShellEnv, worktreeReap };
25
22
  }
26
23
  //# sourceMappingURL=stage-05-execution-env.js.map
@@ -60,7 +60,7 @@ export declare function runStage06(ctx: Awaited<ReturnType<typeof runStage05>>):
60
60
  };
61
61
  workflowRunStore: import("../orchestration/workflow-notify-journal.js").JournalingWorkflowRunStore | undefined;
62
62
  workflowsCapable: boolean;
63
- deploymentHooks: import("@sema-agent/core").Hooks;
63
+ deploymentMods: readonly import("@sema-agent/core").ModRegistration<import("@sema-agent/core").EngineDollar>[];
64
64
  deviceLane: import("./device-lane.js").DeviceLane | undefined;
65
65
  dropSessionScoped: (sid: string) => void;
66
66
  executionEnvFactory: import("@sema-agent/core").ExecutionEnvFactory | undefined;
@@ -135,7 +135,7 @@ export declare function runStage06(ctx: Awaited<ReturnType<typeof runStage05>>):
135
135
  sessionCaptureRecordStore: import("@sema-agent/core").SessionCaptureRecordStore | undefined;
136
136
  sessionCaptureRecords: import("../index.js").SessionCaptureRecordSource | undefined;
137
137
  sessionStore: import("@sema-agent/core").SessionStore;
138
- sqlEngineFacts: (() => import("../plugins/sql-driver.js").SqlEngineFacts | null) | undefined;
138
+ sqlEngine: import("../plugins/sql-driver.js").SqlEngineReading | undefined;
139
139
  storePosture: import("../store-posture.js").StorePosture;
140
140
  taskAttachmentStore: import("../plugins/task-attachment-store.js").TaskAttachmentStore | undefined;
141
141
  taskListLane: import("./task-list-lane.js").TaskListLane;