@sema-agent/server 7.125.1 → 7.127.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 (275) hide show
  1. package/MIGRATION.md +229 -2
  2. package/README.md +2 -2
  3. package/README.zh-CN.md +2 -2
  4. package/USAGE.md +346 -145
  5. package/deploy/sema-up/README.md +1 -1
  6. package/deploy/sema-up/chart/templates/networkpolicy-sandbox.yaml +57 -0
  7. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +32 -1
  8. package/deploy/sema-up/chart/templates/server-v4pro.yaml +3 -2
  9. package/deploy/sema-up/chart/templates/server.yaml +2 -1
  10. package/deploy/sema-up/chart/values.yaml +22 -0
  11. package/deploy/sema-up/cluster-up.sh +10 -10
  12. package/deploy/sema-up/kube-up.sh +20 -13
  13. package/deploy/sema-up/lib/dataroot.sh +1 -1
  14. package/deploy/sema-up/lib/envf.sh +5 -5
  15. package/deploy/sema-up/lib/flagshape.sh +5 -5
  16. package/deploy/sema-up/lib/lanes.py +1 -1
  17. package/deploy/sema-up/lib/node-addrs.sh +42 -0
  18. package/deploy/sema-up/lib/parse-machines.py +2 -2
  19. package/deploy/sema-up/lib/shell-access.sh +1 -1
  20. package/deploy/sema-up/preflight.sh +4 -4
  21. package/deploy/sema-up/sema-up.sh +33 -33
  22. package/deploy/sema-up/smoke.sh +3 -3
  23. package/deploy/sema-up/stack/compose.yaml +1 -1
  24. package/deploy/sema-up/stack/sema-stack-cluster.yaml +26 -3
  25. package/dist/approval-card.d.ts +20 -4
  26. package/dist/approval-content-kind.d.ts +38 -22
  27. package/dist/approval-content-kind.js +20 -4
  28. package/dist/audit.js +3 -0
  29. package/dist/bench/s1/arms.d.ts +9 -37
  30. package/dist/bench/s1/arms.js +4 -61
  31. package/dist/bench/s1/live-deps.d.ts +4 -10
  32. package/dist/bench/s1/live-deps.js +1 -222
  33. package/dist/bench/s1/oracle.d.ts +1 -1
  34. package/dist/bench/s1/reviewer.d.ts +1 -1
  35. package/dist/bench/s1/row.d.ts +5 -7
  36. package/dist/bench/s1/row.js +0 -2
  37. package/dist/bench/s1/run-firm.d.ts +2 -2
  38. package/dist/bench/s1/run-firm.js +1 -4
  39. package/dist/bench/s1/runner-ctx.d.ts +17 -29
  40. package/dist/bench/s1/runner-ctx.js +3 -7
  41. package/dist/bench/s1/tasks.d.ts +9 -46
  42. package/dist/bench/s1/tasks.js +4 -63
  43. package/dist/boot/execution-env.d.ts +38 -26
  44. package/dist/boot/execution-env.js +87 -41
  45. package/dist/boot/leader.d.ts +2 -1
  46. package/dist/boot/memory-boundary.d.ts +1 -1
  47. package/dist/boot/memory-consolidation.d.ts +37 -3
  48. package/dist/boot/memory-consolidation.js +18 -2
  49. package/dist/boot/parked-revive-gate.d.ts +0 -3
  50. package/dist/boot/parked-revive-gate.js +2 -2
  51. package/dist/boot/resolve-spec.d.ts +0 -2
  52. package/dist/boot/resolve-spec.js +12 -17
  53. package/dist/boot/retention-lane.d.ts +12 -1
  54. package/dist/boot/retention-lane.js +2 -0
  55. package/dist/boot/runner-deps.d.ts +7 -6
  56. package/dist/boot/runner-deps.js +5 -16
  57. package/dist/boot/session-faces.d.ts +7 -2
  58. package/dist/boot/session-faces.js +37 -1
  59. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  60. package/dist/boot/stage-03-store-backend.js +2 -2
  61. package/dist/boot/stage-04-stores.d.ts +1 -0
  62. package/dist/boot/stage-05-execution-env.d.ts +2 -2
  63. package/dist/boot/stage-05-execution-env.js +7 -4
  64. package/dist/boot/stage-06-runners.d.ts +2 -3
  65. package/dist/boot/stage-06-runners.js +13 -9
  66. package/dist/boot/stage-07-capability-layer.d.ts +2 -3
  67. package/dist/boot/stage-07-capability-layer.js +3 -4
  68. package/dist/boot/stage-08-reapers.d.ts +2 -3
  69. package/dist/boot/stage-08-reapers.js +2 -2
  70. package/dist/boot/stage-09-leader.d.ts +2 -3
  71. package/dist/boot/stage-09-leader.js +2 -1
  72. package/dist/boot/stage-10-http-server.d.ts +2 -3
  73. package/dist/boot/stage-10-http-server.js +2 -2
  74. package/dist/boot/stores.d.ts +1 -0
  75. package/dist/boot/stores.js +4 -3
  76. package/dist/boot/web-admin.d.ts +5 -0
  77. package/dist/boot/web-admin.js +28 -14
  78. package/dist/brain.d.ts +2 -2
  79. package/dist/brain.js +1 -1
  80. package/dist/capabilities/builtin-tools.d.ts +2 -1
  81. package/dist/capabilities/composite-members.d.ts +1 -1
  82. package/dist/capabilities/composite-members.js +1 -1
  83. package/dist/capabilities/hands-lane.d.ts +9 -6
  84. package/dist/capabilities/hands-lane.js +2 -2
  85. package/dist/capabilities/memory-notice.d.ts +27 -22
  86. package/dist/capabilities/memory-notice.js +15 -17
  87. package/dist/capabilities/scenarios.d.ts +9 -14
  88. package/dist/capabilities/scenarios.js +5 -50
  89. package/dist/capability-facts.d.ts +22 -11
  90. package/dist/capability-facts.js +13 -6
  91. package/dist/config-catalog.js +14 -5
  92. package/dist/config-provider.d.ts +5 -1
  93. package/dist/config-provider.js +23 -4
  94. package/dist/config-types.d.ts +19 -2
  95. package/dist/config.js +41 -6
  96. package/dist/deployment-governance.d.ts +19 -21
  97. package/dist/deployment-governance.js +7 -8
  98. package/dist/env-name-allowlist-knobs.d.ts +5 -5
  99. package/dist/env-name-allowlist-knobs.js +1 -0
  100. package/dist/execution-lane-caps.d.ts +12 -0
  101. package/dist/execution-lane-caps.js +18 -4
  102. package/dist/fleet/subagent-tail-bus.js +15 -5
  103. package/dist/hooks/hook-runner.d.ts +84 -30
  104. package/dist/hooks/hook-runner.js +74 -41
  105. package/dist/http/admission.js +17 -10
  106. package/dist/http/durable-run-leg.d.ts +5 -4
  107. package/dist/http/durable-run-leg.js +2 -4
  108. package/dist/http/idempotency.d.ts +28 -6
  109. package/dist/http/idempotency.js +10 -2
  110. package/dist/http/principal-gate.d.ts +14 -0
  111. package/dist/http/principal-gate.js +7 -0
  112. package/dist/http/request-guards.d.ts +2 -1
  113. package/dist/http/request-guards.js +14 -14
  114. package/dist/http/resume-legs.d.ts +2 -2
  115. package/dist/http/resume-legs.js +20 -10
  116. package/dist/http/route-ctx.d.ts +15 -7
  117. package/dist/http/routes/a2a-serve.js +11 -7
  118. package/dist/http/routes/approvals-assistant.js +18 -3
  119. package/dist/http/routes/background.d.ts +1 -1
  120. package/dist/http/routes/background.js +1 -1
  121. package/dist/http/routes/capabilities.js +10 -2
  122. package/dist/http/routes/mcp-reconnect.js +1 -1
  123. package/dist/http/routes/runs.d.ts +4 -3
  124. package/dist/http/routes/runs.js +35 -14
  125. package/dist/http/routes/session-sync.js +14 -11
  126. package/dist/http/routes/sessions.js +9 -9
  127. package/dist/http/routes/side-query.js +6 -19
  128. package/dist/http/routes/tasks.js +29 -19
  129. package/dist/http/routes/workflows.js +8 -0
  130. package/dist/http/server.d.ts +4 -0
  131. package/dist/http/server.js +3 -5
  132. package/dist/http/submit-replay.d.ts +15 -8
  133. package/dist/http/submit-replay.js +6 -0
  134. package/dist/http/wire-types.d.ts +7 -9
  135. package/dist/index.d.ts +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/internal-run-env.d.ts +30 -0
  138. package/dist/internal-run-env.js +11 -0
  139. package/dist/leader/wire.js +3 -2
  140. package/dist/lsp/manager.js +1 -1
  141. package/dist/memory-scope.d.ts +19 -7
  142. package/dist/memory-scope.js +25 -8
  143. package/dist/observability/fail-open.d.ts +31 -3
  144. package/dist/observability/fail-open.js +31 -3
  145. package/dist/observability/metrics.d.ts +0 -1
  146. package/dist/observability/metrics.js +1 -4
  147. package/dist/observability/run-terminal.js +72 -4
  148. package/dist/permission-rule-vocab.d.ts +3 -2
  149. package/dist/permission-rule-vocab.js +1 -1
  150. package/dist/plan-cache-probe.d.ts +3 -2
  151. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  152. package/dist/plugins/caching-session-store.d.ts +42 -22
  153. package/dist/plugins/caching-session-store.js +19 -9
  154. package/dist/plugins/checkpoint-store-sql.d.ts +42 -28
  155. package/dist/plugins/checkpoint-store-sql.js +57 -11
  156. package/dist/plugins/file-run-store.d.ts +25 -21
  157. package/dist/plugins/file-run-store.js +70 -34
  158. package/dist/plugins/k8s-exec-protocol.js +3 -0
  159. package/dist/plugins/local-checkpoint-store.d.ts +8 -5
  160. package/dist/plugins/local-checkpoint-store.js +5 -15
  161. package/dist/plugins/local-session-store.d.ts +66 -7
  162. package/dist/plugins/local-session-store.js +168 -101
  163. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +1 -1
  164. package/dist/plugins/memory-run-store.d.ts +19 -3
  165. package/dist/plugins/memory-run-store.js +38 -3
  166. package/dist/plugins/one-time-migrations.d.ts +165 -39
  167. package/dist/plugins/one-time-migrations.js +51 -144
  168. package/dist/plugins/pg-pool.js +11 -1
  169. package/dist/plugins/pg-session-storage.d.ts +2 -0
  170. package/dist/plugins/pg-session-storage.js +9 -5
  171. package/dist/plugins/remote-env-adb.d.ts +3 -0
  172. package/dist/plugins/remote-env-adb.js +1 -0
  173. package/dist/plugins/remote-env-device.d.ts +3 -0
  174. package/dist/plugins/remote-env-device.js +1 -0
  175. package/dist/plugins/remote-env-e2b.d.ts +4 -0
  176. package/dist/plugins/remote-env-e2b.js +2 -1
  177. package/dist/plugins/remote-env-host.d.ts +23 -1
  178. package/dist/plugins/remote-env-host.js +20 -2
  179. package/dist/plugins/remote-env-k8s.d.ts +264 -41
  180. package/dist/plugins/remote-env-k8s.js +551 -82
  181. package/dist/plugins/remote-env-local-docker.d.ts +4 -0
  182. package/dist/plugins/remote-env-local-docker.js +2 -1
  183. package/dist/plugins/remote-env-ssh.d.ts +3 -0
  184. package/dist/plugins/remote-env-ssh.js +1 -0
  185. package/dist/plugins/retention-store-sql.d.ts +4 -1
  186. package/dist/plugins/retention-store-sql.js +11 -9
  187. package/dist/plugins/run-store-sql.d.ts +44 -6
  188. package/dist/plugins/run-store-sql.js +92 -27
  189. package/dist/plugins/session-capture-record-store-sql.d.ts +2 -3
  190. package/dist/plugins/session-store.d.ts +4 -3
  191. package/dist/plugins/session-store.js +1 -1
  192. package/dist/plugins/sql-driver.d.ts +2 -1
  193. package/dist/plugins/store-backend.d.ts +12 -5
  194. package/dist/plugins/store-backend.js +13 -4
  195. package/dist/plugins/store-contracts.d.ts +20 -3
  196. package/dist/plugins/store-open-wait.js +3 -0
  197. package/dist/plugins/tidb-pool.js +15 -3
  198. package/dist/plugins/tidb-session-storage.js +3 -2
  199. package/dist/plugins/tidb-session-store.d.ts +2 -0
  200. package/dist/plugins/tidb-session-store.js +6 -2
  201. package/dist/request-key-closure.d.ts +32 -7
  202. package/dist/request-key-closure.js +25 -9
  203. package/dist/router/route-orchestration.d.ts +3 -11
  204. package/dist/router/route-orchestration.js +0 -4
  205. package/dist/rule-entry-list.js +0 -4
  206. package/dist/rules-consent.js +3 -0
  207. package/dist/run-acceptance.d.ts +51 -0
  208. package/dist/run-acceptance.js +27 -0
  209. package/dist/run-local.d.ts +5 -4
  210. package/dist/run-local.js +23 -17
  211. package/dist/runs.d.ts +7 -11
  212. package/dist/runs.js +6 -16
  213. package/dist/sandbox-egress-policy.d.ts +61 -0
  214. package/dist/sandbox-egress-policy.js +235 -0
  215. package/dist/security.d.ts +7 -0
  216. package/dist/security.js +5 -0
  217. package/dist/server-secret-env.d.ts +10 -4
  218. package/dist/server-secret-env.js +4 -1
  219. package/dist/session-error-wire.d.ts +2 -2
  220. package/dist/session-incarnation.d.ts +46 -2
  221. package/dist/session-incarnation.js +14 -3
  222. package/dist/session-sync-kernel.d.ts +10 -3
  223. package/dist/session-titler.d.ts +5 -3
  224. package/dist/spec-fields.d.ts +24 -8
  225. package/dist/spec-fields.js +21 -2
  226. package/dist/task-workflow.d.ts +6 -4
  227. package/dist/task-workflow.js +3 -2
  228. package/dist/tool-approval.d.ts +78 -6
  229. package/dist/tool-approval.js +7 -3
  230. package/dist/trace/core-keyset-guard.d.ts +6 -5
  231. package/dist/trace/engine-notice-wire.d.ts +26 -1
  232. package/dist/trace/engine-notice-wire.js +7 -2
  233. package/dist/trace/ledger-events.d.ts +9 -3
  234. package/dist/trace/ledger-sink.d.ts +7 -0
  235. package/dist/trace/ledger-sink.js +14 -4
  236. package/dist/trace/project.d.ts +57 -11
  237. package/dist/trace/project.js +54 -8
  238. package/dist/trace/self-minted-wire.d.ts +94 -2
  239. package/dist/trace/self-minted-wire.js +28 -0
  240. package/dist/trace/tool-output-media.d.ts +26 -0
  241. package/dist/trace/tool-output-media.js +57 -0
  242. package/dist/trace/wire-projection-faces.d.ts +7 -1
  243. package/dist/trace/wire-projection-faces.js +2 -1
  244. package/dist/web-admin-client/apply-effective.d.ts +13 -7
  245. package/dist/web-admin-client/apply-effective.js +11 -26
  246. package/dist/web-admin-client/apply-ledger.d.ts +2 -2
  247. package/dist/web-admin-client/candidate-gate.d.ts +39 -4
  248. package/dist/web-admin-client/candidate-gate.js +9 -2
  249. package/dist/web-admin-client/facade.d.ts +2 -2
  250. package/dist/web-admin-client/http-client.d.ts +3 -1
  251. package/dist/web-admin-client/http-client.js +4 -3
  252. package/dist/web-admin-client/read-warnings.d.ts +33 -5
  253. package/dist/web-admin-client/read-warnings.js +41 -6
  254. package/dist/web-admin-client/types.d.ts +11 -5
  255. package/dist/workspace-cache.d.ts +45 -0
  256. package/dist/workspace-cache.js +30 -0
  257. package/dist/workspace-space-commit.d.ts +116 -0
  258. package/dist/workspace-space-commit.js +117 -0
  259. package/dist/workspace-space.d.ts +75 -9
  260. package/dist/workspace-space.js +52 -1
  261. package/package.json +4 -4
  262. package/dist/boot/session-incarnation-seat.d.ts +0 -41
  263. package/dist/boot/session-incarnation-seat.js +0 -69
  264. package/dist/capabilities/code-review-council.d.ts +0 -49
  265. package/dist/capabilities/code-review-council.js +0 -111
  266. package/dist/capabilities/collab-wire.d.ts +0 -36
  267. package/dist/capabilities/collab-wire.js +0 -2
  268. package/dist/capabilities/collab-workflows.d.ts +0 -47
  269. package/dist/capabilities/collab-workflows.js +0 -90
  270. package/dist/capabilities/prompts/code-review.d.ts +0 -25
  271. package/dist/capabilities/prompts/code-review.js +0 -39
  272. package/dist/capabilities/prompts/team.d.ts +0 -10
  273. package/dist/capabilities/prompts/team.js +0 -6
  274. package/dist/capabilities/team.d.ts +0 -113
  275. package/dist/capabilities/team.js +0 -70
@@ -76,7 +76,6 @@ export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>):
76
76
  fleetBus: import("../fleet/fleet-bus.js").FleetEventBus;
77
77
  governanceSeams: import("./governance-seams.js").GovernanceSeams;
78
78
  handslessRunner: import("@sema-agent/core").Runner;
79
- handslessSubRunner: import("@sema-agent/core").Runner;
80
79
  hookAgent: import("../hooks/hook-runner.js").HookLlmCall;
81
80
  hookAgentRunner: import("@sema-agent/core").Runner;
82
81
  hookLlm: import("../hooks/hook-runner.js").HookLlmCall;
@@ -123,12 +122,11 @@ export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>):
123
122
  executionEnvFactory: import("@sema-agent/core").ExecutionEnvFactory | undefined;
124
123
  fenceSessionOwner: (sid: string, owner: string | null) => void;
125
124
  lspManager: import("@sema-agent/core").NodeLspManager | import("../lsp/manager.js").E2bLspManager | undefined;
126
- noteSessionIncarnation: (sid: string, incarnation: string | undefined) => void;
125
+ spaceReclaimer: import("../workspace-space.js").SpaceReclaimer | undefined;
127
126
  perSessionCwd: Map<string, string>;
128
127
  perTaskImage: import("../per-task-image.js").PerTaskImageRegistry;
129
128
  sendUserFileTaskEnvs: import("../capabilities/sandbox-file-send.js").TaskEnvRegistry | undefined;
130
129
  sessionEnvSelection: import("../capabilities/select-environment-tool.js").SessionEnvironmentSelection;
131
- sessionIncarnationOf: (sid: string) => string | undefined;
132
130
  setSessionCwd: (sid: string, cwd: string) => void;
133
131
  setSessionInheritEnv: (sid: string, policy: import("../request-value-closure.js").TaskInheritEnv | undefined) => void;
134
132
  setSessionShellEnv: (sid: string, env: Record<string, string>) => void;
@@ -177,6 +175,7 @@ export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>):
177
175
  backend: import("../plugins/store-backend.js").StoreBackend | undefined;
178
176
  backgroundAgentStore: import("@sema-agent/core").BackgroundAgentStore | undefined;
179
177
  breakerState: import("../plugins/breaker-state-sql.js").TiDBBreakerState | import("../plugins/breaker-state-sql.js").PgBreakerState | undefined;
178
+ engineDataRoot: string;
180
179
  instanceId: string;
181
180
  mailboxRecipientLifecycle: import("../plugins/mailbox-recipient-lifecycle.js").MailboxRecipientLifecycle | undefined;
182
181
  mailboxStore: import("@sema-agent/core").MailboxStore | undefined;
@@ -29,7 +29,7 @@ import { bindServerLateSeats } from "./late-binds.js";
29
29
  import { serviceVersion } from "../service-version.js";
30
30
  import { buildDisplaySafeUrl } from "../trace/redact.js";
31
31
  export async function runStage10(ctx) {
32
- const { approvalAskAudit, approvalExemptionStore, approvalNonceStore, authorize, backend, backgroundAgentStore, brain, breakerState, centerRuntimeCapsResolver, checkpointStore, parkCommits, config, webAdmin, consolidationValve, costQuota, deploymentHooks, deviceLane, drainState, durableEnabled, elicitation, fenceSessionOwner, noteSessionIncarnation, fileHistoryStore, fleetBus, fleetLease, fleetUsage, governanceSeams, handslessRunner, hookAgent, hookLlm, hookWakeBus, imageBakes, imageIndex, instanceId, instrumentDegenerate, leaderEndpoint, localRoot, logger, lspManager, mcpRevocations, memoryBundleFaces, memoryComplianceFaces, memoryConsolidationFaces, memoryEngine, memoryExportBackend, memoryOptOutGrantStore, memoryOriginFaces, memoryPosture, memorySyncCursors, metrics, modelUsageTracker, orgMemoryAdmission, otelExporter, outcomeSink, ownerAware, parkedReviveInheritedGate, parkedReviveSurface, perSessionCwd, perTaskImage, planCacheProbe, pricing, principalCaps, promptManifestTracker, purgeSession, question, rateLimiter, reaper, webAdminJwtVerifier, resumeAnchorStore, retentionLaneStarted, retentionLaneStore, ruleConsent, runStore, runner, runnerDeps, runtimeCapsPeekResolver, scenarioDetails, scenarios, selectEnvTool, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionAudit, sessionEnvSelection, sessionMemoryStatusFace, sessionPolicyStore, sessionTitler, sessionWatchRegistry, setSessionCwd, setSessionInheritEnv, setSessionShellEnv, sharedMemoryStore, sideQueryAccounting, sqlEngineFacts, sqlWorkflowRunStore, staticWiring, storePosture, subRunner, subagentSteerRegistry, taskAttachmentStore, taskLimitCaps, taskTimeoutSec, toolApproval, toolResultStore, usageWindowStore, userInputLedger, webSearchProvider, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable } = ctx;
32
+ const { approvalAskAudit, approvalExemptionStore, approvalNonceStore, authorize, backend, backgroundAgentStore, brain, breakerState, centerRuntimeCapsResolver, checkpointStore, parkCommits, config, webAdmin, consolidationValve, costQuota, deploymentHooks, deviceLane, drainState, durableEnabled, elicitation, fenceSessionOwner, fileHistoryStore, fleetBus, fleetLease, fleetUsage, governanceSeams, handslessRunner, hookAgent, hookLlm, hookWakeBus, imageBakes, imageIndex, instanceId, instrumentDegenerate, leaderEndpoint, localRoot, logger, lspManager, mcpRevocations, memoryBundleFaces, memoryComplianceFaces, memoryConsolidationFaces, memoryEngine, memoryExportBackend, memoryOptOutGrantStore, memoryOriginFaces, memoryPosture, memorySyncCursors, metrics, modelUsageTracker, orgMemoryAdmission, otelExporter, outcomeSink, ownerAware, parkedReviveInheritedGate, parkedReviveSurface, perSessionCwd, perTaskImage, planCacheProbe, pricing, principalCaps, promptManifestTracker, purgeSession, question, rateLimiter, reaper, webAdminJwtVerifier, resumeAnchorStore, retentionLaneStarted, retentionLaneStore, ruleConsent, runStore, runner, runnerDeps, runtimeCapsPeekResolver, scenarioDetails, scenarios, selectEnvTool, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionAudit, sessionEnvSelection, sessionMemoryStatusFace, sessionPolicyStore, sessionTitler, sessionWatchRegistry, setSessionCwd, setSessionInheritEnv, setSessionShellEnv, sharedMemoryStore, sideQueryAccounting, sqlEngineFacts, sqlWorkflowRunStore, staticWiring, storePosture, subRunner, subagentSteerRegistry, taskAttachmentStore, taskLimitCaps, taskTimeoutSec, toolApproval, toolResultStore, usageWindowStore, userInputLedger, webSearchProvider, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable } = ctx;
33
33
  const stores = {
34
34
  runStore,
35
35
  resumeAnchorStore: resumeAnchorStore ? resumeAnchorStore : undefined,
@@ -177,6 +177,7 @@ export async function runStage10(ctx) {
177
177
  configApplyState: () => webAdmin.configApplyState(),
178
178
  centerCredentialState: () => webAdmin.centerCredentialState(),
179
179
  modelRefusalsState: () => webAdmin.modelRefusalsState(),
180
+ candidateRejectionState: () => webAdmin.candidateRejectionState(),
180
181
  configHandoffState: () => webAdmin.configHandoffState(),
181
182
  mcpRevocations,
182
183
  mcpRevocationState: () => webAdmin.mcpRevocationState(),
@@ -199,7 +200,6 @@ export async function runStage10(ctx) {
199
200
  getCenterPrompts: () => webAdmin.getCenterPrompts(),
200
201
  getKeyResolver: () => webAdmin.getKeyResolver(),
201
202
  taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner,
202
- noteSessionIncarnation,
203
203
  hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec,
204
204
  selectEnvTool, sendUserFileToolSpec, memoryEngine, durableEnabled, approvalExemptionStore,
205
205
  checkpointStore, deploymentHooks, imageIndex, perTaskImage,
@@ -20,6 +20,7 @@ export declare function openStores(ctx: OpenStoresCtx): Promise<{
20
20
  backend: MemoryBackend;
21
21
  root: string;
22
22
  } | undefined;
23
+ engineDataRoot: string;
23
24
  memorySyncCursors: MemorySyncStore | undefined;
24
25
  rosterStore: import("@sema-agent/core").RosterStore | undefined;
25
26
  backgroundAgentStore: import("@sema-agent/core").BackgroundAgentStore | undefined;
@@ -119,6 +119,7 @@ export async function openStores(ctx) {
119
119
  if (config.dbBackend === "local" && backend)
120
120
  config.sessionBackend = "tidb";
121
121
  let memoryEngine;
122
+ const engineDataRoot = memoryEngineRootFor(config, localRoot);
122
123
  let memorySyncCursors;
123
124
  let vectorMode;
124
125
  if (config.memoryEngineBackend !== "file" && config.memoryEngineEnabled) {
@@ -169,7 +170,7 @@ export async function openStores(ctx) {
169
170
  ...(embedder !== undefined ? { embedder } : {}),
170
171
  });
171
172
  vectorMode = pgMem.vectorMode;
172
- memoryEngine = { backend: pgMem, root: memoryEngineRootFor(config, localRoot) };
173
+ memoryEngine = { backend: pgMem, root: engineDataRoot };
173
174
  }
174
175
  else {
175
176
  const pool = backend?.mysqlPool();
@@ -181,7 +182,7 @@ export async function openStores(ctx) {
181
182
  memorySyncCursors = new TiDBMemorySyncStore(pool);
182
183
  const tidbMem = new TiDBMemoryEngineBackend(pool, { history: countedHistorySink(new TiDBMemoryHistoryStore(pool)) });
183
184
  vectorMode = tidbMem.vectorMode;
184
- memoryEngine = { backend: tidbMem, root: memoryEngineRootFor(config, localRoot) };
185
+ memoryEngine = { backend: tidbMem, root: engineDataRoot };
185
186
  }
186
187
  logger.info("memory_engine_enabled", {
187
188
  enabled: true,
@@ -447,7 +448,7 @@ export async function openStores(ctx) {
447
448
  .startRefresh()
448
449
  : undefined;
449
450
  return {
450
- backend, storePosture, memoryEngine, memorySyncCursors, rosterStore, backgroundAgentStore, mailboxRecipientLifecycle,
451
+ backend, storePosture, memoryEngine, engineDataRoot, memorySyncCursors, rosterStore, backgroundAgentStore, mailboxRecipientLifecycle,
451
452
  taskAttachmentStore, mailboxStore, memoryExportBackend, memorySyncRunner, sessionStore, breakerState,
452
453
  usageWindowStore, memoryPosture, taskListLane, sqlEngineFacts,
453
454
  };
@@ -15,6 +15,7 @@ import type { ConsolidationSeatWatch } from "./memory-consolidation.js";
15
15
  import type { DegradeRouteWatch } from "../brain.js";
16
16
  import { type EngineRestartSignal } from "../web-admin-client/facade.js";
17
17
  import { type ConfigHandoff } from "../fleet/engine-signal.js";
18
+ import { type CandidateRejection } from "../web-admin-client/candidate-gate.js";
18
19
  import { type ConfigApplyLedgerView } from "../web-admin-client/apply-ledger.js";
19
20
  import type { CenterPullView } from "../web-admin-client/pull-state.js";
20
21
  import type { LimitSync } from "./limit-sync.js";
@@ -117,6 +118,10 @@ export interface WebAdminRuntime {
117
118
  * 名 → 码 + 组拒码)。描述**最近一次被判的那份中心候选目录**(每次候选 apply 的报告 `ApplyReport.modelRefusals` 投影;组拒时就是被拒
118
119
  * 的那份 —— 引擎自己的拒因表不换代)。没有可报的拒 / 没有配置管道 / 还没判过候选 ⇒ `undefined`(键缺席)。值变了 ⇒ 通知自报订阅者。 */
119
120
  modelRefusalsState(): ModelRefusalsSignal | undefined;
121
+ /** S-1457:`GET /v1/models.candidateRejected` 的取值口 —— 最近一次候选被判官整拒的结论(`candidateRejection` 座;域集就是判官交出的 `rejected.domains`)。
122
+ * present-iff 当前生效的配置是因判官整拒了最近一份候选而回落的那一份:后来的候选被判 clean 即撤下;还没判过候选 / 没有配置管道 ⇒ `undefined`(键缺席)。
123
+ * dry-run 姿势(`webAdmin.dryRun`,compare-only)恒 `undefined`:候选从不被应用,生效配置恒是 env,拒判是预演读数(日志行照响),不是配置没换的原因。 */
124
+ candidateRejectionState(): CandidateRejection | undefined;
120
125
  /** [ref] 世代账:/health 的 target/applied/失败持续时长三键 + 诊断端点的 configApply 段(同一份读数)。
121
126
  * `undefined` = 本部署没有配置管道(纯 env worker)⇒ 两个读面的形状**逐字不变**(additive 纪律)。 */
122
127
  configApplyState(): ConfigApplyLedgerView | undefined;
@@ -23,7 +23,7 @@ import { applyEffective, applyCenterReadFace, mutateInPlace, logEffectiveDiff, a
23
23
  import { buildConfigHandoff, buildRestartSignal, configHandoffMissing } from "../fleet/engine-signal.js";
24
24
  import { createMcpRevocationLedger, enabledMcpEntries } from "../web-admin-client/mcp-revocation.js";
25
25
  import { buildUnreadConfigFileFields } from "../web-admin-client/read-warnings.js";
26
- import { CONFIG_DOMAIN_INVALID_NOTE, buildCandidateRejectedFields, judgeConfigCandidate } from "../web-admin-client/candidate-gate.js";
26
+ import { CONFIG_DOMAIN_INVALID_NOTE, buildCandidateRejectedFields, candidateRejectionOf, judgeConfigCandidate } from "../web-admin-client/candidate-gate.js";
27
27
  import { SHA256_HEX_RE } from "../digest-form.js";
28
28
  import { BOOT_REJUDGE_OF_REFUSED_GROUP, createConfigApplyLedger, modelPlaneCommitted, refusedGroups } from "../web-admin-client/apply-ledger.js";
29
29
  function lkgReadNote(scope) {
@@ -31,7 +31,7 @@ function lkgReadNote(scope) {
31
31
  case "whole":
32
32
  return "booting from the persisted last-known-good (all restart-to-apply faces included) — the live pull continues in the background and reconciles on arrival";
33
33
  case "model-plane":
34
- return "the live candidate's model plane was refused at boot — the persisted last-known-good supplies the model plane only (catalog and the collab templates that reference it); every other group and every restart-to-apply face stays the live candidate's";
34
+ return "the live candidate's model plane was refused at boot — the persisted last-known-good supplies the model plane only (the catalog and what rides with it); every other group and every restart-to-apply face stays the live candidate's";
35
35
  }
36
36
  }
37
37
  export async function createWebAdminRuntime(ctx) {
@@ -39,7 +39,14 @@ export async function createWebAdminRuntime(ctx) {
39
39
  let ccEtag;
40
40
  let effective;
41
41
  let latestEffective;
42
- let lastRejectedCandidate;
42
+ let candidateRejection;
43
+ let judgedOrdinal = 0;
44
+ const noteCandidateVerdict = (ordinal, rejection) => {
45
+ if (ordinal < judgedOrdinal)
46
+ return;
47
+ judgedOrdinal = ordinal;
48
+ candidateRejection = rejection;
49
+ };
43
50
  const applyLedger = createConfigApplyLedger();
44
51
  let lastPull = "none";
45
52
  let generationOrdinal = 0;
@@ -146,11 +153,16 @@ export async function createWebAdminRuntime(ctx) {
146
153
  });
147
154
  }
148
155
  };
149
- const announceCandidateRejected = (r, verdict, leg) => {
156
+ const rejectionSource = () => {
157
+ if (configProvider === undefined)
158
+ throw new Error("config candidate judged without a config provider (no pipeline ⇒ nothing was pulled)");
159
+ return configProvider.kind;
160
+ };
161
+ const announceCandidateRejected = (r, verdict, leg, ordinal) => {
150
162
  const domains = verdict.domains.join(",");
151
- if (lastRejectedCandidate?.version === r.effective.version && lastRejectedCandidate.domains === domains)
163
+ if (candidateRejection?.version === r.effective.version && candidateRejection.domains.join(",") === domains)
152
164
  return;
153
- lastRejectedCandidate = { version: r.effective.version, domains, at: Date.now() };
165
+ noteCandidateVerdict(ordinal, candidateRejectionOf(r, verdict, rejectionSource(), Date.now()));
154
166
  logger.warn("config_candidate_rejected", buildCandidateRejectedFields(r, verdict, leg, { lkgVersion: latestEffective?.version ?? "(env)", ...localDirField }));
155
167
  };
156
168
  const selfReportListeners = [];
@@ -503,7 +515,7 @@ export async function createWebAdminRuntime(ctx) {
503
515
  hint: rejected && modelsDomainErr
504
516
  ? "config.d/models.json 在场但 models 域判形失败,整份本地候选被拒(真因见本行 domainError)— 模型继续走 env 兜底"
505
517
  : rejected
506
- ? "config.d 里别的域判形失败,整份本地候选被拒(坏域与真因见 config_candidate_rejected)— config.d/models.json 的模型不用,继续走 env 兜底"
518
+ ? "config.d 里别的域让整份本地候选被拒(判形失败,或带事实的退役域文档;坏域与真因见 config_candidate_rejected)— config.d/models.json 的模型不用,继续走 env 兜底"
507
519
  : modelsDropped.length > 0 && totalModels === 0
508
520
  ? "config.d/models.json 的条目全部被逐条丢弃(逐条真因见 config_entry_dropped)— 模型继续走 env 兜底"
509
521
  : totalModels > 0
@@ -536,7 +548,7 @@ export async function createWebAdminRuntime(ctx) {
536
548
  if (dryRun) {
537
549
  const dryVerdict = judgeConfigCandidate(r);
538
550
  if (dryVerdict.verdict === "rejected") {
539
- announceCandidateRejected(r, dryVerdict, "boot");
551
+ announceCandidateRejected(r, dryVerdict, "boot", generationOrdinal);
540
552
  }
541
553
  else {
542
554
  warnReadNotices(r, "boot");
@@ -550,7 +562,7 @@ export async function createWebAdminRuntime(ctx) {
550
562
  await bootFallBackWhole(`boot candidate rejected: ${bootVerdict.domains.join(",")}`);
551
563
  const rejectedGen = generationOf(r.effective.version);
552
564
  applyLedger.seenTarget(rejectedGen, r.effective.version);
553
- announceCandidateRejected(r, bootVerdict, "boot");
565
+ announceCandidateRejected(r, bootVerdict, "boot", rejectedGen);
554
566
  if (configProvider.kind === "local")
555
567
  warnLocalNoModels(r, true);
556
568
  }
@@ -581,7 +593,7 @@ export async function createWebAdminRuntime(ctx) {
581
593
  applyEffective(config, withModelPlaneOf(r.effective, lkgPlane.effective), logger, { leg: "boot", sealedKeys, generation: bootGen, report: (rep) => (planeReport = rep) });
582
594
  if (modelPlaneCommitted(planeReport)) {
583
595
  bootPlaneEff = lkgPlane.effective;
584
- logger.warn("config_model_plane_from_lkg", { version: r.effective.version, lkgVersion: lkgPlane.effective.version, note: "the live candidate's model plane was refused at boot — serving the LKG's model plane (catalog and the collab templates that reference it) with the live candidate's other groups; the refresh cadence re-judges the candidate" });
596
+ logger.warn("config_model_plane_from_lkg", { version: r.effective.version, lkgVersion: lkgPlane.effective.version, note: "the live candidate's model plane was refused at boot — serving the LKG's model plane (the catalog and what rides with it) with the live candidate's other groups; the refresh cadence re-judges the candidate" });
585
597
  }
586
598
  }
587
599
  }
@@ -665,6 +677,7 @@ export async function createWebAdminRuntime(ctx) {
665
677
  restartState: () => buildRestartSignal(pendingRestart, planeDeferredNoHandoff),
666
678
  configHandoffState: () => (configProvider === undefined || configProvider.kind === "local" || !lkgSurvivesRestart ? undefined : buildConfigHandoff(latchHandoff(), handoffMissingSince)),
667
679
  modelRefusalsState: () => modelRefusals,
680
+ candidateRejectionState: () => (cc?.dryRun ? undefined : candidateRejection),
668
681
  configApplyState: () => (configProvider ? applyLedger.view() : undefined),
669
682
  centerPullState: () => {
670
683
  const view = applyLedger.view();
@@ -858,10 +871,10 @@ export async function createWebAdminRuntime(ctx) {
858
871
  applyLedger.seenTarget(tickGen, r.effective.version);
859
872
  const verdict = judgeConfigCandidate(r);
860
873
  if (verdict.verdict === "rejected") {
861
- announceCandidateRejected(r, verdict, arrival !== undefined ? "late-boot" : "refresh");
874
+ announceCandidateRejected(r, verdict, arrival !== undefined ? "late-boot" : "refresh", tickGen);
862
875
  return "ok";
863
876
  }
864
- lastRejectedCandidate = undefined;
877
+ noteCandidateVerdict(tickGen, undefined);
865
878
  warnReadNotices(r, "refresh");
866
879
  if (ccRef?.dryRun) {
867
880
  logEffectiveDiff(config, r.effective, logger);
@@ -918,7 +931,7 @@ export async function createWebAdminRuntime(ctx) {
918
931
  const signal = signalRestart({ applied: "complete", effective: r.effective, ...(r.etag !== undefined ? { etag: r.etag } : {}), baseline: effective, lkgPersisted });
919
932
  logger.info("web_admin_refreshed", {
920
933
  version: r.effective.version,
921
- note: "collab + runtime governance (incl. approvalRequire) + limits + models/roles/roster hot-applied; skills/mcp/a2a/scenarios are restart-to-apply",
934
+ note: "runtime governance (incl. approvalRequire) + limits + models/roles/roster hot-applied; skills/mcp/a2a/scenarios are restart-to-apply",
922
935
  ...restartLogFields(signal),
923
936
  });
924
937
  latestEffective = r.effective;
@@ -967,9 +980,10 @@ export async function createWebAdminRuntime(ctx) {
967
980
  applyLedger.seenTarget(lateGen, r.effective.version);
968
981
  const lateVerdict = judgeConfigCandidate(r);
969
982
  if (lateVerdict.verdict === "rejected") {
970
- announceCandidateRejected(r, lateVerdict, "late-boot");
983
+ announceCandidateRejected(r, lateVerdict, "late-boot", lateGen);
971
984
  return;
972
985
  }
986
+ noteCandidateVerdict(lateGen, undefined);
973
987
  warnReadNotices(r, "boot-deferred");
974
988
  if (ccRef?.dryRun) {
975
989
  logEffectiveDiff(config, r.effective, logger);
package/dist/brain.d.ts CHANGED
@@ -108,8 +108,8 @@ export interface DegradeRouteWatch {
108
108
  *
109
109
  * 缺省下首字节段不铸键(core 自缺省当家,[ref])、`0` = 该段不设引擎钟;而切备只发生在一次调用**失败之后**。于是主网关接了连接
110
110
  * 却不回响应头时:缺省 ⇒ 要等 core 的首字节 lane 走完(缺省首窗 + 一次加宽重试;本仓不铸 `firstByteRetries`,S-753 车PA)才切备,
111
- * 时间预算短于那一段的调用在备网关被尝试之前就被取消 —— 以 core 7.33.x 缺省计 lane ≈ 15 min,code-review council 每个镜头的 180 s 与 team
112
- * discuss 的 600 s 都在其内(车PA codex r1:600 s 在主网关的加宽重试窗里到点,不是「只剩余量」);
111
+ * 时间预算短于那一段的调用在备网关被尝试之前就被取消 —— 以 core 7.33.x 缺省计 lane ≈ 15 min,一次带短时间预算的调用
112
+ * (分钟级的工具 / 子任务预算)在主网关的加宽重试窗里就到点,不是「只剩余量」;
113
113
  * `0` ⇒ 首字节 lane 永不切备。启动日志里同行的 `gatewayRetryCap:"fast-fail:…"` 只管共享重试梯子,读起来却像「会快切」—— 这条披露把它补齐。
114
114
  * 显式设了正数窗 ⇒ `undefined`(部署已表态);单路由 ⇒ `undefined`(没有备可切)。**不替运维铸窗**:出路是旋钮,不是本仓的数。
115
115
  */
package/dist/brain.js CHANGED
@@ -193,7 +193,7 @@ export function buildFailoverFirstByteNotice(config) {
193
193
  firstByteTimeoutMs: r.firstByteTimeoutMs ?? null,
194
194
  effect: zero
195
195
  ? "the first-byte lane never fails over a primary that accepts the connection but sends no response headers (0 = no engine clock on that segment); only a run-level limit ends that wait"
196
- : "a primary that accepts the connection but sends no response headers is failed over only after core's default first-byte lane runs out (the first window, then one widened retry); a call with a time budget shorter than that — the code-review council's 180 s lenses and team discuss's 600 s, with core 7.33.x defaults — is cancelled before the backup is ever tried",
196
+ : "a primary that accepts the connection but sends no response headers is failed over only after core's default first-byte lane runs out (the first window, then one widened retry); a call with a time budget shorter than that (minutes, with core 7.33.x defaults) is cancelled before the backup is ever tried",
197
197
  fix: "set MODEL_FIRST_BYTE_TIMEOUT_MS to the longest response-header wait a healthy primary needs (queue + prefill), so a hung primary is cut over after that window and its one widened retry",
198
198
  };
199
199
  }
@@ -27,7 +27,8 @@ export interface SubagentExtraToolOptions {
27
27
  *
28
28
  * core 7.46.0 #1432 —— **工厂与名册一个来源**:返回委派工具的两键,`extraTools`(每次 spawn 交出 `forSpawn` 选中的那几只)与
29
29
  * `extraToolNames`(全部可能交出的那几只的名字 / 别名 / 内容来源,从同一批 `ToolSpec` 读出)。名册在场 ⇒ 引擎重新能列出子代的工具池:
30
- * 定义级 / 工具级 / `TaskSpec.agents` 清单里的退役拼法与大小写孪生回到开跑前拒(`config.agent.unknown_tool`),记忆内容来源读者按声明读这几只。
30
+ * 定义级 / 工具级 / `TaskSpec.agents` 清单里没有任何工具答应的名字(core 7.49.0 #1623 起含无人挂的名;退役拼法与大小写孪生 7.46.0 起)开跑前拒
31
+ * (`config.agent.unknown_tool`),记忆内容来源读者按声明读这几只。
31
32
  * 修前(core 7.32.0–7.45.x)工厂恒在场 ⇒ 池不可静态知 ⇒ 那一族拼法只告不拒、委派结果一律按「外部」读。
32
33
  * 工厂**不抛**:各组的 `tools` 是装配期就建好的对象;部署 `forSpawn` 的抛由 core 收成「这一 spawn 什么都不继承 + 模型面披露句」(onExtraToolsError 记 warn)。
33
34
  * 一种拼法出现在两只工具上(部署工具与 `Now` 撞名 / 别名撞)⇒ core 在建委派工具处抛 `config.extra_tool_names`(`shape`),不静默取其一。
@@ -53,7 +53,7 @@ export declare const COMPOSITE_CAPABILITY_MEMBERS: {
53
53
  readonly retention: readonly ["mode", "maxAgeDays"];
54
54
  readonly workflowsGate: readonly ["engineCan", "denial"];
55
55
  readonly sealedKey: readonly ["alg", "publicKeyId", "publicKey"];
56
- readonly workspaceSync: readonly ["persist", "keep"];
56
+ readonly workspaceSync: readonly ["persist", "keep", "timeoutMs", "cache"];
57
57
  };
58
58
  type CompositeTable = typeof COMPOSITE_CAPABILITY_MEMBERS;
59
59
  /** 值的**具名成员对象臂**(标量 / 字面词 / `false` / `null` / `undefined` / 数组 / 函数臂剥掉)。 */
@@ -14,7 +14,7 @@ export const COMPOSITE_CAPABILITY_MEMBERS = {
14
14
  retention: ["mode", "maxAgeDays"],
15
15
  workflowsGate: ["engineCan", "denial"],
16
16
  sealedKey: ["alg", "publicKeyId", "publicKey"],
17
- workspaceSync: ["persist", "keep"],
17
+ workspaceSync: ["persist", "keep", "timeoutMs", "cache"],
18
18
  };
19
19
  export function gateCompositeMembers(body) {
20
20
  return body;
@@ -4,8 +4,8 @@
4
4
  * 根本问题(设计小票 §1,案源 [ref]/[ref]/[ref]):core 的手带工具面是 **per-Runner 表态**
5
5
  * (`prepare-task`:`handsEnabled = ownedEnv || deps.executionEnv`,ownedEnv 只要挂了
6
6
  * `executionEnvFactory` 就每任务必铸)。server 此前全场景共享一只 runner + 一只 subRunner,
7
- * 于是任何 REMOTE_EXEC 部署里,声明 clone-free 的 `scan`、只有 `run_council` 的评审团、
8
- * 零工具人格的 team 成员,最终 roster 都被并集进全量可写手带(Bash/Edit/Write/…)。
7
+ * 于是任何 REMOTE_EXEC 部署里,声明 clone-free 的 `scan` / `code-review`(当年还有评审团与讨论成员两种零工具人格),
8
+ * 最终 roster 都被并集进全量可写手带(Bash/Edit/Write/…)。
9
9
  *
10
10
  * 本模块提供三件:
11
11
  * ① {@link ScenarioHands} 判别位 + {@link pickHandsRunner} 的**穷举** switch —— 新场景不表态 = 编译红,
@@ -19,14 +19,17 @@ import { type Runner, type TaskSpec, type ToolPolicy } from "@sema-agent/core";
19
19
  /** 场景对手带工具面的表态(闭集)。`full` = core 手带 band 照常 mount;`none` = 不挂 executionEnvFactory 的 Runner。 */
20
20
  export type ScenarioHands = "full" | "none";
21
21
  /**
22
- * 无手孪生 Runner 的 deps 构造:把 `executionEnvFactory` **摘键**(不是置 undefined)。
22
+ * 无手孪生 Runner 的 deps 构造:把 `executionEnvFactory` **与 `lspManager`** 一起**摘键**(不是置 undefined)。
23
23
  * 摘键让「这只 Runner 没有手」在 deps 字面量上自证;置 undefined 留下一个值为 undefined 的键,
24
24
  * 与 core 现在的 `deps.executionEnvFactory ||` 判读结果相同,但把正确性寄托在真值判断上。
25
+ * **无手就无 LSP**:LSP 管理器是手的附属(宿主车道的 `NodeLspManager` 经 `defaultLspReadText` 直读本地盘,
26
+ * 没有读面围栏;沙箱车道推断降级为 unavailable)—— 只摘手不摘它,无手 Runner 会在 StubExecutionEnv 上挂 LSP。
25
27
  */
26
- export declare function withoutExecutionEnv<T extends {
28
+ export declare function withoutHands<T extends {
27
29
  executionEnvFactory?: unknown;
28
- }>(deps: T): Omit<T, "executionEnvFactory">;
29
- /** 一对 Runner:同 deps,唯一差别是 `handsless` 不挂 `executionEnvFactory`。 */
30
+ lspManager?: unknown;
31
+ }>(deps: T): Omit<T, "executionEnvFactory" | "lspManager">;
32
+ /** 一对 Runner:同 deps,唯一差别是 `handsless` 不挂 `executionEnvFactory` 与 `lspManager`。 */
30
33
  export interface HandsRunnerPair {
31
34
  full: Runner;
32
35
  handsless: Runner;
@@ -1,7 +1,7 @@
1
1
  import { handBandEffects, judgeRuleToolName, combinePolicies, createAllowDenyPolicy } from "@sema-agent/core";
2
2
  import { NO_DECLARED_TOOL_NAMES } from "../namespaced-rule-name.js";
3
- export function withoutExecutionEnv(deps) {
4
- const { executionEnvFactory: _handsDropped, ...rest } = deps;
3
+ export function withoutHands(deps) {
4
+ const { executionEnvFactory: _handsDropped, lspManager: _lspDropped, ...rest } = deps;
5
5
  return rest;
6
6
  }
7
7
  export function pickHandsRunner(hands, pair) {
@@ -13,10 +13,11 @@
13
13
  * ⚠️ 两条边界,越界即双重注入/假话:
14
14
  * · **engine 在场就不是我们的座位**。哪怕 `memoryWrite:false`(writeScope null)——那恰恰是引擎自己
15
15
  * 挂只读披露的状态,server 再叠一句口径不同的「你没有持久记忆」= 同一件事两种说法同框。
16
- * · **推断到「有落盘路」就闭嘴**。判别式与 core 的 `rosterCanPersist` 同口径(已知落盘路 = 挂载且未
17
- * 排除的文件写工具 / 可写 shell)。⚠️ 名单确实要读(codex 复审 [medium] 之后加的 `excludeTools` 一位:
18
- * roster 把落盘路**整批**卸掉时,手带在场也等于没有写通道),但负控仍然成立:必须**全部**已知落盘路
19
- * 都不在才算断链 —— `excludeTools:["Write"]` 不算(Bash/Edit 还在),请求面摘一个工具名改不动结论。
16
+ * · **推断到「有落盘路」就闭嘴**。判别式与 core 的 `rosterCanPersist` 同口径(已知落盘路 = 这一 run 名册上
17
+ * 真挂着的文件写工具 / 可写 shell)。「名册上还剩什么」**只读引擎的答案**:core 7.49.0(#1623)起一 run 的可用工具是
18
+ * 引擎一只选择器(`allowTools` ∩ … − `excludeTools`,别名 / `Tool(content)` / `mcp__srv…` 都由它读)在 prepare 算出的,
19
+ * 本模块不再读请求的任何一张工具名表 —— 名册臂在装配时刻读 provider 拿到的 `ctx.tools`(选择器之后的名册)。
20
+ * 负控仍然成立:必须**全部**已知落盘路都不在名册上才算断链(摘掉 `Write`,Bash / Edit 还在)。
20
21
  */
21
22
  import { type PromptProvider, type ToolCatalogEntry } from "@sema-agent/core";
22
23
  import type { ScenarioHands } from "./hands-lane.js";
@@ -25,8 +26,8 @@ import { type ExecutionLane } from "../execution-lane-caps.js";
25
26
  * 「已知落盘路」的判据,作用在 core **静态工具目录**的一行上(S-503 / [ref])—— 与 core 自己的
26
27
  * `rosterCanPersist` 推断逐条同形,取的是同一批目录属性,不是它结论的抄件:
27
28
  * · `mountedBy` 落在 core 的 `HANDS_BAND_TAGS` 里 —— 手带 band 之外的定义(记忆面工具、调度族)
28
- * 不在本判别式说得着的面上:本判别式的输入全是**手带事实**(`hands` / `handsReadOnly` /
29
- * `excludeTools`),把一只 band 外的写工具算进来,就是拿一条根本没挂的通道去撤回披露(fail-open);
29
+ * 不在本判别式说得着的面上:本判别式的输入全是**手带事实**(`hands` / `handsReadOnly` / 名册上的手带名),
30
+ * 把一只 band 外的写工具算进来,就是拿一条根本没挂的通道去撤回披露(fail-open);
30
31
  * · `face.effect !== "read"`(缺席读 `write`,与 core 同缺省)—— 只读 shell 壳在这里出局,它与全壳
31
32
  * 共用 `Bash` 这个 wire 名,靠的正是这一位分开;
32
33
  * · `face.pathTarget.access !== "read"`(文件写工具)**或** `face.family === "shell"`(可写 shell)。
@@ -44,8 +45,8 @@ export declare function persistencePathToolNamesOf(entries: readonly ToolCatalog
44
45
  * 「已知落盘路」的工具名闭集 —— **由 core 的静态工具目录派生**,本仓不再存第二份名表
45
46
  * (S-503 / [ref];改前是手抄的四名表 Write / Edit / NotebookEdit / Bash,没有任何差集门)。
46
47
  *
47
- * 为什么手抄在这一位上特别危险:core 改名/加一只写工具,手抄表静默失配成「没有一个写工具被排除」
48
- * (fail-open 方向)—— `excludeTools` 把真正的落盘路全排掉了,而我们对着一张旧名单答「还剩」。
48
+ * 为什么手抄在这一位上特别危险:core 改名/加一只写工具,手抄表静默失配(fail-open 方向)—— 名册上真正的
49
+ * 落盘路已经全不在了,而我们对着一张旧名单答「还剩」。
49
50
  * 判据的属主现在是 {@link persistencePathToolNamesOf},值的属主是 core 的目录行。
50
51
  */
51
52
  export declare const KNOWN_PERSISTENCE_TOOL_NAMES: readonly string[];
@@ -69,15 +70,6 @@ export interface MemoryFaceFacts {
69
70
  hands: ScenarioHands;
70
71
  /** 折完 governance+settings 后的最终 `handsReadOnly`(`AUTONOMY=read-only` 收窄;plan 模式不点亮它 —— plan 的手带照挂、调用时由引擎问)。手带只剩读腿。 */
71
72
  handsReadOnly: boolean;
72
- /** 折完之后的最终 `TaskSpec.excludeAllTools`(S-493;core 7.8.0 [ref])。`true` = **整只**工具面卸空
73
- * (core `prepareDeferClassify` 对它直接 `roster.unmountWhere(() => true)`)⇒ 手带在场也一条落盘路都不剩。
74
- * 🔴 它与下面那张名单是**同一个语义面**(「哪些工具不在 roster 上」)的两种声明,判据合成一只
75
- * {@link isUnmounted} —— 上游同版的姊妹谓词 `fullShellReachable` 也正是把 `spec.excludeAllTools !== true`
76
- * 当一个合取项(`prepare-inherited-gate.js` 亲读),本仓与它同口径。 */
77
- excludeAllTools: boolean;
78
- /** 折完之后的最终 `TaskSpec.excludeTools`(roster 真卸载,不是延迟披露)。**全部**已知落盘路都被排掉
79
- * ⇒ 手带在场也等于没有写通道 —— core 的 `rosterCanPersist` 也是按排除后的 roster 算的,这里跟上。 */
80
- excludeTools: readonly string[] | undefined;
81
73
  /**
82
74
  * 本部署的手带**挂没挂**(= core 拿没拿到执行环境;能力表 `coreRemoteExecutionEnv` 位,经
83
75
  * {@link buildNoticeLaneFacts} 取)。`false` = `in-process`:core 落 `StubExecutionEnv`,手带整族不 mount
@@ -103,18 +95,31 @@ export interface MemoryFaceFacts {
103
95
  * 不在调用点手写 `config.remoteExec !== undefined`(门 D R4)。
104
96
  */
105
97
  export declare function buildNoticeLaneFacts(lane: ExecutionLane): Pick<MemoryFaceFacts, "handsWired" | "filePlaneRemote">;
98
+ /**
99
+ * 披露的三种结局。`"roster"` = 部署事实答不完,剩下的问题(「名册上还剩不剩已知落盘路」)只有引擎在 prepare
100
+ * 之后知道 —— 由 {@link withNoPersistentMemoryNotice} 在装配时刻读 provider 拿到的名册作答,不在 resolveSpec 期猜。
101
+ */
102
+ export type NoPersistentMemoryNotice = "disclose" | "silent" | "roster";
106
103
  /**
107
104
  * 该不该把 `NO_PERSISTENT_MEMORY_NOTICE` 组进本次任务的 system prompt。
108
105
  *
109
106
  * 优先序(每一条都有独立理由,不是同一条判据的三种写法):
110
- * ① engine 在场 ⇒ **否**(引擎的座位,见文件头注);
111
- * ② 部署显式声明(或 host 腿装配层自动声明)⇒ 声明说了算(`true` 撤回 / `false` 强制)—— operator 的部署
107
+ * ① engine 在场 ⇒ `silent`(引擎的座位,见文件头注);
108
+ * ② 部署显式声明(或 host 腿装配层自动声明)⇒ 声明说了算(`true` ⇒ `silent` / `false` ⇒ `disclose`)—— operator 的部署
112
109
  * 事实压过我们的推断,与 core 对 `memoryPersistenceCapable` 的处置同向;
113
- * ③ 否则推断:有已知落盘路(手带挂上、场景不摘手、不是只读、文件平面在本机、且没被卸载决定卸光)⇒ 否;没有 ⇒ 是。
110
+ * ③ 否则推断:手带没挂 / 场景摘手 / 只读 / 文件平面不在本机 ⇒ `disclose`;都不是 ⇒ `roster`(名册上还剩不剩已知落盘路,
111
+ * 读引擎选择器之后的名册 —— 本模块不读请求的任何工具名表,core 7.49.0 #1623 起那是引擎一只运算的输入)。
114
112
  * 🔴 S-602 只改臂③ 里「车道」那一段(`handsWired` / `filePlaneRemote`),①② 的优先序一字不动 —— 「in-process ⇒
115
113
  * 披露」只在这两臂**之后**成立(挂了记忆面、或声明了 capable 的 in-process 部署照旧不披露)。
116
114
  */
117
- export declare function shouldDiscloseNoPersistentMemory(facts: MemoryFaceFacts): boolean;
115
+ export declare function noPersistentMemoryNotice(facts: MemoryFaceFacts): NoPersistentMemoryNotice;
116
+ /**
117
+ * 名册臂:引擎选择器之后的名册上还剩不剩已知落盘路(`KNOWN_PERSISTENCE_TOOL_NAMES` 任一名在册)。⚠️ 负控:摘掉**一个**
118
+ * `Write` 不算断链(Bash / Edit 还在)—— 必须**全部**已知落盘路都不在名册上。名册为空(`excludeAllTools`)⇒ 一条都不剩。
119
+ */
120
+ export declare function rosterLeavesPersistencePath(tools: readonly {
121
+ readonly name: string;
122
+ }[]): boolean;
118
123
  /**
119
124
  * 把披露段组进一个 prompt provider,**按 provider 自己的钩子形分腿**(换形会改段身份与 append 座位):
120
125
  * · typed(`stableBlocks`)⇒ {@link mountNotice}(普通形追加 behavior 声明;已组装 identity 形接在其文本后)。
@@ -129,5 +134,5 @@ export declare function shouldDiscloseNoPersistentMemory(facts: MemoryFaceFacts)
129
134
  * 走 typed 声明腿就没有这条耦合:role 层仍由 core 按 `userSystemPrompt ?? DEFAULT_SYSTEM_PROMPT` 自己铸,
130
135
  * 我方只贡献一条 behavior 段,`providerDropsAppend` 的判决包装前后逐格相同。
131
136
  */
132
- export declare function withNoPersistentMemoryNotice(provider: PromptProvider | undefined): PromptProvider;
137
+ export declare function withNoPersistentMemoryNotice(provider: PromptProvider | undefined, when: Exclude<NoPersistentMemoryNotice, "silent">): PromptProvider;
133
138
  //# sourceMappingURL=memory-notice.d.ts.map
@@ -26,24 +26,21 @@ export function buildNoticeLaneFacts(lane) {
26
26
  const caps = executionLaneCaps(lane);
27
27
  return { handsWired: caps.coreRemoteExecutionEnv === "supported", filePlaneRemote: caps.hostFilePlane !== "supported" };
28
28
  }
29
- function isUnmounted(facts, name) {
30
- return facts.excludeAllTools || (facts.excludeTools?.includes(name) ?? false);
31
- }
32
- function anyPersistenceToolSurvives(facts) {
33
- return KNOWN_PERSISTENCE_TOOL_NAMES.some((name) => !isUnmounted(facts, name));
34
- }
35
- export function shouldDiscloseNoPersistentMemory(facts) {
29
+ export function noPersistentMemoryNotice(facts) {
36
30
  if (facts.memoryFaceMounted)
37
- return false;
31
+ return "silent";
38
32
  if (facts.declaredCapable !== undefined)
39
- return !facts.declaredCapable;
33
+ return facts.declaredCapable ? "silent" : "disclose";
40
34
  if (facts.hands === "none" || facts.handsReadOnly)
41
- return true;
35
+ return "disclose";
42
36
  if (!facts.handsWired)
43
- return true;
37
+ return "disclose";
44
38
  if (facts.filePlaneRemote)
45
- return true;
46
- return !anyPersistenceToolSurvives(facts);
39
+ return "disclose";
40
+ return "roster";
41
+ }
42
+ export function rosterLeavesPersistencePath(tools) {
43
+ return tools.some((t) => KNOWN_PERSISTENCE_TOOL_NAMES.includes(t.name));
47
44
  }
48
45
  const NOTICE_BLOCK = { id: NO_PERSISTENT_MEMORY_SECTION_ID, slot: "behavior", text: NO_PERSISTENT_MEMORY_NOTICE };
49
46
  function mountNotice(decls) {
@@ -52,15 +49,16 @@ function mountNotice(decls) {
52
49
  return [...decls, NOTICE_BLOCK];
53
50
  return decls.map((d) => (d === assembledIdentity ? { id: d.id, slot: d.slot, text: `${d.text}\n\n${NO_PERSISTENT_MEMORY_NOTICE}` } : d));
54
51
  }
55
- export function withNoPersistentMemoryNotice(provider) {
52
+ export function withNoPersistentMemoryNotice(provider, when) {
53
+ const due = (ctx) => when === "disclose" || !rosterLeavesPersistencePath(ctx.tools);
56
54
  if (provider?.stableBlocks) {
57
55
  const blocks = provider.stableBlocks.bind(provider);
58
- return { ...provider, stableBlocks: (ctx) => mountNotice(blocks(ctx)) };
56
+ return { ...provider, stableBlocks: (ctx) => (due(ctx) ? mountNotice(blocks(ctx)) : blocks(ctx)) };
59
57
  }
60
58
  if (provider?.stableSystem) {
61
59
  const stable = provider.stableSystem.bind(provider);
62
- return { ...provider, stableSystem: (ctx) => `${stable(ctx)}\n\n${NO_PERSISTENT_MEMORY_NOTICE}` };
60
+ return { ...provider, stableSystem: (ctx) => (due(ctx) ? `${stable(ctx)}\n\n${NO_PERSISTENT_MEMORY_NOTICE}` : stable(ctx)) };
63
61
  }
64
- return { stableBlocks: () => [NOTICE_BLOCK] };
62
+ return { stableBlocks: (ctx) => (due(ctx) ? [NOTICE_BLOCK] : []) };
65
63
  }
66
64
  //# sourceMappingURL=memory-notice.js.map
@@ -1,10 +1,9 @@
1
1
  import { type WebFetchConfig, type BackgroundAgentStore, type CheckpointStore, type PromptProvider, type Runner, type SkillSpec, type TaskListStore, type ToolSpec, type WebSearchConfig } from "@sema-agent/core";
2
- import type { Metrics } from "../observability/metrics.js";
3
2
  import type { Logger } from "../observability/logger.js";
4
3
  import { type SubagentExtraToolSet } from "./builtin-tools.js";
5
4
  import { type RepoReadClient } from "./repo-tools.js";
6
5
  import { type LoadedSkill } from "./skills.js";
7
- import { type ScenarioHands } from "./hands-lane.js";
6
+ import type { ScenarioHands } from "./hands-lane.js";
8
7
  /**
9
8
  * Scenario routing — a deployment serves many scenarios from one image. Each request's `scenario`
10
9
  * selects a pre-wired capability bundle: tools (incl. subagent roster) + a whole-harness prompt +
@@ -53,15 +52,8 @@ export interface ScenarioContext {
53
52
  export type Scenario = (req: ScenarioRequest, principal?: string, ctx?: ScenarioContext) => ScenarioBundle;
54
53
  export interface ScenarioDeps {
55
54
  runner: Runner;
56
- /** In-memory runner for ephemeral sub-tasks (council lenses/arbiter) — keeps them out of TiDB. */
55
+ /** The runner a delegated (Agent-tool) child runs on — same deps as `runner`, hands included (CC parity). */
57
56
  subRunner: Runner;
58
- /**
59
- * [ref]:`subRunner` 的无手孪生 —— 同 deps,唯独不挂 `executionEnvFactory`。hands=none 的场景把它交给
60
- * 自己造的子任务工具(council 的 lens/arbiter、discuss 的成员/synthesizer):那些子任务只该读仓库/讨论,
61
- * 拿全量可写手是 [ref] 病灶里最意外的一支(零工具人格照拿 Bash)。取用一律走 {@link pickHandsRunner},
62
- * 不在场景体内手挑 —— 判别位是唯一开关。
63
- */
64
- handslessSubRunner: Runner;
65
57
  model: string;
66
58
  skills: LoadedSkill[];
67
59
  repoClient?: RepoReadClient;
@@ -77,12 +69,11 @@ export interface ScenarioDeps {
77
69
  * 模型摘要而非整页灌上下文([ref] L1 的 ~660× 放大就是这缝);缺席 ⇒ `webFetch` 键不铸(修前
78
70
  * 字节形,core 落「summarization unavailable」诚实兜底)。 */
79
71
  webFetchSummarize?: NonNullable<NonNullable<WebFetchConfig["summarize"]>>;
80
- metrics?: Metrics;
81
72
  logger?: Logger;
82
73
  /**
83
74
  * When true, the `default` scenario carries the Sema product identity (see {@link semaIdentityProvider}).
84
75
  * Set by the local/TOC deployment (CONFIG_PROVIDER=local / run-local) so the local engine answers "who
85
- * are you" as Sema instead of the model's hallucinated identity. Business scenarios (discuss/code-review)
76
+ * are you" as Sema instead of the model's hallucinated identity. Business scenarios (code-review)
86
77
  * keep their own prompts; cloud (CONFIG_PROVIDER≠local) leaves the default scenario neutral unless turned
87
78
  * on, so integrators that inject their own persona are unaffected.
88
79
  */
@@ -205,9 +196,13 @@ export interface ScenarioDetail {
205
196
  /** 机读原因键;仅 `available:false` 时在场(缺席=没有理由)。消费方按键分支,禁匹配英文文案。 */
206
197
  unavailableReason?: ScenarioUnavailableReason;
207
198
  }
208
- /** 内建五场景详情。default/code/discuss 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
199
+ /** 内建四场景详情。default/code 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
209
200
  * fail-loud 语义(缺 GIT_API 配置/principal 即 throw)→ 探针失败落静态表兜底(表↔工厂一致性由测试锁:
210
201
  * 测试喂 fake deps 真调工厂对账工具名)。enabled 对内建恒 true(约定②)。 */
202
+ /** 内建场景名的闭集(`GET /v1/capabilities.scenarios` 与场景详情口的内建成员)。{@link builtinScenarioDetails} 的返回型按它键控 ⇒ 加 / 删一个内建场景而
203
+ * 这里没跟 = 编译红;wire 变更清单的自铸登记表(`trace/self-minted-wire.ts` 的 `builtinScenario`)同按它 `satisfies`。 */
204
+ export declare const BUILTIN_SCENARIO_NAMES: readonly ["code", "default", "code-review", "scan"];
205
+ export type BuiltinScenarioName = (typeof BUILTIN_SCENARIO_NAMES)[number];
211
206
  export declare function builtinScenarioDetails(scenarios: Record<string, Scenario>, deps: Pick<ScenarioDeps, "brandIdentity" | "repoClient">): Record<string, ScenarioDetail>;
212
207
  /** center 条目详情(有效性判定与 centerScenarios 完全同款:无效条目既不进 overlay 也不进详情——
213
208
  * 保证约定①「详情显示的来源=运行实际用的定义」永不错位)。 */
@@ -236,7 +231,7 @@ export type ScenarioAvailability = {
236
231
  *
237
232
  * 判据键 = **toolset**:内建详情与 center 条目都带这个字段,故两条产线天然共用同一份判据。
238
233
  * `requiresRepo` 的 toolset 需要部署配好 git 后端(`GIT_API_BASEURL` ⇒ `deps.repoClient`)。
239
- * 词表外的 toolset(内建的 `full-body`/`discuss`)不依赖后端 ⇒ 恒可用。
234
+ * 词表外的 toolset(内建的 `full-body`)不依赖后端 ⇒ 恒可用。
240
235
  */
241
236
  export declare function scenarioAvailability(deps: Pick<ScenarioDeps, "repoClient">, toolset: string): ScenarioAvailability;
242
237
  /** 拒绝文案的唯一属主:闭集穷举 switch(新增原因词不在这里表态即编译红)。 */