@sema-agent/server 7.148.0 → 7.149.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 (247) hide show
  1. package/MIGRATION.md +429 -0
  2. package/README.md +16 -1
  3. package/README.zh-CN.md +4 -0
  4. package/USAGE.md +89 -55
  5. package/dist/adoption/wire.d.ts +3 -3
  6. package/dist/approval-card.d.ts +32 -32
  7. package/dist/approval-leg-origin.d.ts +33 -0
  8. package/dist/approval-leg-origin.js +4 -0
  9. package/dist/auth-bridge.d.ts +9 -1
  10. package/dist/auth-bridge.js +4 -4
  11. package/dist/auth-keys.d.ts +10 -1
  12. package/dist/auth-keys.js +8 -0
  13. package/dist/boot/execution-env.js +10 -11
  14. package/dist/boot/execution-lane.d.ts +6 -4
  15. package/dist/boot/execution-lane.js +3 -1
  16. package/dist/boot/org-delivery.d.ts +3 -2
  17. package/dist/boot/resolve-spec.js +6 -4
  18. package/dist/boot/runner-deps.js +3 -1
  19. package/dist/boot/stage-01-config.d.ts +1 -0
  20. package/dist/boot/stage-01-config.js +4 -3
  21. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  22. package/dist/boot/stage-02-web-admin-pull.js +10 -2
  23. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  24. package/dist/boot/stage-03-store-backend.js +2 -2
  25. package/dist/boot/stage-04-stores.d.ts +1 -0
  26. package/dist/boot/stage-05-execution-env.d.ts +1 -0
  27. package/dist/boot/stage-06-runners.d.ts +2 -1
  28. package/dist/boot/stage-07-capability-layer.d.ts +2 -1
  29. package/dist/boot/stage-08-reapers.d.ts +2 -1
  30. package/dist/boot/stage-09-leader.d.ts +2 -1
  31. package/dist/boot/stage-10-http-server.d.ts +2 -1
  32. package/dist/boot/stores.d.ts +3 -0
  33. package/dist/boot/stores.js +22 -19
  34. package/dist/capabilities/tool-defer.d.ts +1 -1
  35. package/dist/capability-facts.d.ts +5 -4
  36. package/dist/capability-facts.js +3 -14
  37. package/dist/card-settle-stored-scope.d.ts +56 -0
  38. package/dist/card-settle-stored-scope.js +27 -0
  39. package/dist/card-void.d.ts +7 -12
  40. package/dist/card-void.js +2 -7
  41. package/dist/config-catalog.d.ts +12 -0
  42. package/dist/config-catalog.js +36 -32
  43. package/dist/config-invariants.d.ts +5 -4
  44. package/dist/config-invariants.js +4 -4
  45. package/dist/config-types.d.ts +37 -5
  46. package/dist/config.d.ts +6 -5
  47. package/dist/config.js +35 -24
  48. package/dist/context-window-notice.d.ts +31 -0
  49. package/dist/context-window-notice.js +28 -0
  50. package/dist/deployment-shape.d.ts +20 -11
  51. package/dist/deployment-shape.js +1 -0
  52. package/dist/env-name-allowlist-knobs.d.ts +6 -5
  53. package/dist/env-name-allowlist-knobs.js +5 -0
  54. package/dist/execution-lane-caps.d.ts +20 -5
  55. package/dist/execution-lane-caps.js +18 -4
  56. package/dist/hooks/command-spawn.d.ts +7 -2
  57. package/dist/hooks/command-spawn.js +13 -6
  58. package/dist/hooks/hook-runner.d.ts +5 -0
  59. package/dist/hooks/hook-runner.js +11 -7
  60. package/dist/http/admission.js +3 -3
  61. package/dist/http/approval-sweeps.js +3 -2
  62. package/dist/http/claim-heartbeat.d.ts +3 -3
  63. package/dist/http/claim-heartbeat.js +3 -3
  64. package/dist/http/claimed-run.d.ts +16 -9
  65. package/dist/http/claimed-run.js +8 -0
  66. package/dist/http/dispatch.js +5 -3
  67. package/dist/http/durable-run-leg.d.ts +8 -1
  68. package/dist/http/durable-run-leg.js +30 -11
  69. package/dist/http/execution-context.d.ts +115 -14
  70. package/dist/http/execution-context.js +130 -40
  71. package/dist/http/owner-access.d.ts +3 -2
  72. package/dist/http/owner-access.js +2 -3
  73. package/dist/http/principal-gate.d.ts +18 -11
  74. package/dist/http/principal-gate.js +3 -1
  75. package/dist/http/resume-ctx-read.d.ts +14 -3
  76. package/dist/http/resume-ctx-read.js +8 -2
  77. package/dist/http/resume-legs.d.ts +35 -3
  78. package/dist/http/resume-legs.js +244 -92
  79. package/dist/http/route-ctx.d.ts +6 -0
  80. package/dist/http/routes/a2a-serve.js +2 -0
  81. package/dist/http/routes/approvals-assistant.js +3 -2
  82. package/dist/http/routes/capabilities.js +1 -1
  83. package/dist/http/routes/diagnostics.d.ts +3 -1
  84. package/dist/http/routes/diagnostics.js +30 -5
  85. package/dist/http/routes/principal-inbox.d.ts +3 -1
  86. package/dist/http/routes/principal-inbox.js +3 -2
  87. package/dist/http/routes/runs.js +10 -7
  88. package/dist/http/routes/session-sync.d.ts +24 -5
  89. package/dist/http/routes/session-sync.js +46 -34
  90. package/dist/http/routes/sessions-list.d.ts +1 -1
  91. package/dist/http/routes/tasks.js +127 -93
  92. package/dist/http/server.d.ts +4 -5
  93. package/dist/http/server.js +30 -5
  94. package/dist/http/submit-ctx.d.ts +1 -0
  95. package/dist/http/submit-ctx.js +2 -3
  96. package/dist/index.d.ts +3 -1
  97. package/dist/index.js +1 -0
  98. package/dist/leg-facts.d.ts +7 -2
  99. package/dist/leg-facts.js +1 -0
  100. package/dist/local-store-declaration.d.ts +54 -0
  101. package/dist/local-store-declaration.js +59 -0
  102. package/dist/mcp-assertion-header.d.ts +1 -1
  103. package/dist/mcp-assertion-header.js +1 -1
  104. package/dist/memory-project-layer.js +1 -1
  105. package/dist/memory-scope.d.ts +4 -4
  106. package/dist/memory-scope.js +4 -4
  107. package/dist/memory-sync-client.js +2 -2
  108. package/dist/model-context-window.d.ts +50 -11
  109. package/dist/model-context-window.js +20 -1
  110. package/dist/model-entry-refusal.d.ts +5 -4
  111. package/dist/model-entry-refusal.js +17 -3
  112. package/dist/model-reach-scope.d.ts +2 -1
  113. package/dist/observability/fail-open.d.ts +14 -2
  114. package/dist/observability/fail-open.js +14 -2
  115. package/dist/observability/metrics.js +1 -1
  116. package/dist/observability/run-terminal.js +1 -0
  117. package/dist/observability/secret-env-scrub.d.ts +1 -1
  118. package/dist/observability/secret-env-scrub.js +1 -1
  119. package/dist/org-delivery-gate.d.ts +31 -6
  120. package/dist/org-delivery-gate.js +7 -4
  121. package/dist/owner-faces.d.ts +3 -2
  122. package/dist/park-row-commit.d.ts +67 -0
  123. package/dist/park-row-commit.js +76 -0
  124. package/dist/parked-decide.d.ts +9 -7
  125. package/dist/parked-decide.js +25 -6
  126. package/dist/peer-directory.d.ts +1 -1
  127. package/dist/plugins/adoption-log-sql.d.ts +3 -3
  128. package/dist/plugins/adoption-log-sql.js +19 -19
  129. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  130. package/dist/plugins/approval-ask-store-sql.js +3 -5
  131. package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
  132. package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
  133. package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
  134. package/dist/plugins/approval-exemption-skill-m46.js +6 -10
  135. package/dist/plugins/approval-exemption-store.d.ts +26 -1
  136. package/dist/plugins/approval-exemption-store.js +28 -19
  137. package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
  138. package/dist/plugins/ensure-schema-lock-policy.js +75 -9
  139. package/dist/plugins/file-run-store.d.ts +22 -9
  140. package/dist/plugins/file-run-store.js +50 -22
  141. package/dist/plugins/local-checkpoint-store.d.ts +4 -0
  142. package/dist/plugins/local-checkpoint-store.js +2 -1
  143. package/dist/plugins/local-data-root-admission.d.ts +52 -0
  144. package/dist/plugins/local-data-root-admission.js +100 -0
  145. package/dist/plugins/local-engine-high-water.d.ts +28 -7
  146. package/dist/plugins/local-engine-high-water.js +27 -22
  147. package/dist/plugins/local-session-store.d.ts +134 -49
  148. package/dist/plugins/local-session-store.js +149 -108
  149. package/dist/plugins/memory-run-store.d.ts +14 -9
  150. package/dist/plugins/memory-run-store.js +47 -21
  151. package/dist/plugins/one-time-migration-marker.d.ts +19 -3
  152. package/dist/plugins/one-time-migration-marker.js +7 -1
  153. package/dist/plugins/one-time-migrations.d.ts +46 -20
  154. package/dist/plugins/one-time-migrations.js +102 -79
  155. package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
  156. package/dist/plugins/org-delivery-quota-store.js +29 -14
  157. package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
  158. package/dist/plugins/permission-rule-store-sql.js +5 -9
  159. package/dist/plugins/pg-pool.d.ts +1 -1
  160. package/dist/plugins/pg-pool.js +10 -12
  161. package/dist/plugins/remote-env-device.d.ts +3 -2
  162. package/dist/plugins/remote-env-e2b.d.ts +1 -7
  163. package/dist/plugins/remote-env-e2b.js +10 -7
  164. package/dist/plugins/remote-env-host.d.ts +50 -9
  165. package/dist/plugins/remote-env-host.js +77 -20
  166. package/dist/plugins/remote-env-k8s.js +4 -2
  167. package/dist/plugins/remote-env-local-docker.d.ts +6 -3
  168. package/dist/plugins/remote-env-local-docker.js +8 -23
  169. package/dist/plugins/run-store-sql.d.ts +26 -7
  170. package/dist/plugins/run-store-sql.js +44 -16
  171. package/dist/plugins/scenario-prefix-switch-m42.d.ts +3 -1
  172. package/dist/plugins/scenario-prefix-switch-m42.js +4 -3
  173. package/dist/plugins/schema-consistency.d.ts +89 -5
  174. package/dist/plugins/schema-consistency.js +176 -7
  175. package/dist/plugins/schema-drift-sentence.d.ts +6 -5
  176. package/dist/plugins/schema-drift-sentence.js +13 -5
  177. package/dist/plugins/session-placement.d.ts +5 -4
  178. package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
  179. package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
  180. package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
  181. package/dist/plugins/stop-then-start-sentence.js +7 -0
  182. package/dist/plugins/store-backend.d.ts +22 -8
  183. package/dist/plugins/store-backend.js +58 -24
  184. package/dist/plugins/store-contracts.d.ts +33 -3
  185. package/dist/plugins/store-contracts.js +16 -0
  186. package/dist/plugins/tidb-pool.d.ts +11 -6
  187. package/dist/plugins/tidb-pool.js +18 -12
  188. package/dist/plugins/workspace-custody.d.ts +44 -0
  189. package/dist/plugins/workspace-custody.js +47 -0
  190. package/dist/project-identity.d.ts +8 -7
  191. package/dist/project-identity.js +40 -17
  192. package/dist/project-layer-key.d.ts +13 -2
  193. package/dist/project-layer-key.js +9 -1
  194. package/dist/read-deny-floor-notice.d.ts +36 -0
  195. package/dist/read-deny-floor-notice.js +40 -0
  196. package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
  197. package/dist/request-declaration-disposition.js +39 -0
  198. package/dist/run-cancel-card.d.ts +28 -0
  199. package/dist/run-cancel-card.js +19 -0
  200. package/dist/run-cancel-context.d.ts +10 -0
  201. package/dist/run-cancel-context.js +1 -0
  202. package/dist/run-local.js +28 -13
  203. package/dist/runs.d.ts +31 -7
  204. package/dist/runs.js +34 -16
  205. package/dist/security.d.ts +2 -2
  206. package/dist/server-secret-env.d.ts +34 -20
  207. package/dist/server-secret-env.js +61 -18
  208. package/dist/session-agent.d.ts +3 -2
  209. package/dist/session-children-retire.d.ts +6 -3
  210. package/dist/session-children-retire.js +2 -5
  211. package/dist/session-workspace.d.ts +3 -3
  212. package/dist/store-admission.d.ts +33 -0
  213. package/dist/store-admission.js +49 -0
  214. package/dist/store-posture.d.ts +5 -0
  215. package/dist/store-posture.js +18 -1
  216. package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
  217. package/dist/stores-sql/checkpoint-store-sql.js +3 -5
  218. package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
  219. package/dist/stores-sql/file-history-store-sql.js +3 -5
  220. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  221. package/dist/stores-sql/tool-result-store-sql.js +4 -6
  222. package/dist/task-a2a.d.ts +3 -8
  223. package/dist/task-a2a.js +25 -27
  224. package/dist/task-cwd.d.ts +23 -7
  225. package/dist/task-cwd.js +3 -0
  226. package/dist/task-mcp.d.ts +3 -3
  227. package/dist/task-mcp.js +1 -1
  228. package/dist/task-settings.js +1 -0
  229. package/dist/terminal.d.ts +2 -0
  230. package/dist/terminal.js +21 -6
  231. package/dist/tool-approval.d.ts +44 -36
  232. package/dist/tool-approval.js +66 -47
  233. package/dist/trace/engine-notice-wire.d.ts +24 -21
  234. package/dist/trace/engine-notice-wire.js +7 -3
  235. package/dist/trace/ledger-sink.d.ts +3 -1
  236. package/dist/trace/project.d.ts +4 -2
  237. package/dist/trace/project.js +8 -7
  238. package/dist/trace/redact.d.ts +12 -0
  239. package/dist/trace/redact.js +5 -1
  240. package/dist/trace/self-minted-wire.d.ts +131 -52
  241. package/dist/trace/self-minted-wire.js +71 -39
  242. package/dist/web-admin-client/apply-effective.js +22 -9
  243. package/docs/error-text-lexicon.json +317 -0
  244. package/package.json +3 -1
  245. package/scripts/embed-minimal.mjs +183 -0
  246. package/wire-changes/server@7.149.0.json +372 -0
  247. package/dist/plain-string-record.js +0 -70
@@ -1,7 +1,8 @@
1
1
  import { redactErrorMessage, redactHead, redactTerminalResult } from "../../observability/run-terminal.js";
2
2
  import { runWithVerification, runCascade, taskNotificationDedupKey, uuidv7 } from "@sema-agent/core";
3
3
  import { heldFor } from "../../peer-seat.js";
4
- import { beatRunHeartbeat, graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, TurnAnchorCapture, HEARTBEAT_MS } from "../../runs.js";
4
+ import { beatRunHeartbeat, graftParkToolCallId, heldParkOf, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, TurnAnchorCapture, HEARTBEAT_MS } from "../../runs.js";
5
+ import { commitParkRow } from "../../park-row-commit.js";
5
6
  import { atHostBoundary, failureCodeOf, sealResultForExit, outwardPlane } from "../../terminal.js";
6
7
  import { voidVerifierPauseCard } from "../../verifier-pause-card.js";
7
8
  import { withSubject } from "../../observability/principal-context.js";
@@ -24,9 +25,10 @@ import { isReplayedOutcome, replayedOutcome, replayOfExistingRun } from "../subm
24
25
  import { httpErrorCode, sendJson, sseHeaders } from "../send.js";
25
26
  import { collectSsePreamble } from "../sse-log.js";
26
27
  import { buildApprovalPreamble } from "../../approval-card.js";
28
+ import { approvalLegOriginOf } from "../../approval-leg-origin.js";
27
29
  import { approvalPreambleReplays, declaredApprovalFrameFamilies, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
28
30
  import { buildActiveRunConflict, isActiveRunConflictBody, toDoneFrameResult } from "../active-run-conflict.js";
29
- import { commitExecutionContext } from "../execution-context.js";
31
+ import { SUBMISSION_CLAIM_FACE, commitExecutionContext, faultedAnswerOf } from "../execution-context.js";
30
32
  import { rootSessionAbsentAnswer } from "../execution-context.js";
31
33
  import { recheckClaimBeforeLaunch, startClaimHeartbeat } from "../claim-heartbeat.js";
32
34
  import { timeClaim } from "../claim-latency.js";
@@ -34,7 +36,7 @@ import { commitSessionInheritEnv } from "../session-inherit-env.js";
34
36
  import { headerStr, gatedPerson, gatedSubject, explicitOperatorOk, runIdentityOf } from "../principal-gate.js";
35
37
  import { recoveredSubject } from "../../owner-faces.js";
36
38
  import { recordFailOpen } from "../../observability/fail-open.js";
37
- import { buildSyncSubmitBody } from "../sync-submit-body.js";
39
+ import { buildSyncSubmitBody, syncSubmitBodyOfRow } from "../sync-submit-body.js";
38
40
  import { assertNever } from "../route-ctx.js";
39
41
  import * as facts from "../../capability-facts.js";
40
42
  import { persistSubmissionCtx, SUBMIT_CTX_CLAIM_LOST } from "../submit-ctx.js";
@@ -42,6 +44,7 @@ import { withModelReachScope } from "../../model-reach-scope.js";
42
44
  import { createInstructionSelectionLeg } from "../../instruction-selection.js";
43
45
  import { refusalBody } from "../refusal-body.js";
44
46
  import { heldWorkflowParkDecisions } from "../../parked-decide.js";
47
+ import { compositionLegRoot } from "../../task-cwd.js";
45
48
  import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../../session-workspace.js";
46
49
  const DISCONNECT_PARK_GRACE_MS = 10_000;
47
50
  async function mintSubmitExitResult(result, checkpoints) {
@@ -277,8 +280,14 @@ export async function handleTasks(req, res, match, ctx) {
277
280
  const runStreamSubmitLeg = async () => {
278
281
  ranLive = true;
279
282
  let finalResult;
283
+ let heldCard;
284
+ const commitSyncPark = (runStore, runId, word, parkResult, cardToken) => commitParkRow({
285
+ runStore, taskId: runId, word, result: parkResult, card: { token: cardToken, sessionId: prepared.spec.sessionId }, cards: deps.checkpointStore, leg: "sync",
286
+ legId: heldLegOf(durableLegId, runId), staleWindowMs: deps.config.runStaleSec * 1000,
287
+ });
280
288
  let runRowSettled = false;
281
289
  let durableTaskId;
290
+ let durableLegId;
282
291
  let durableHeartbeat;
283
292
  const cancelledResult = (errorMessage, cause) => mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId, startedAtMs: streamLegStartedAt, message: errorMessage, cause });
284
293
  let userMsgEntryId;
@@ -293,52 +302,60 @@ export async function handleTasks(req, res, match, ctx) {
293
302
  anchorPut = true;
294
303
  await settleResumeAnchor(() => store.put(prepared.spec.sessionId, key, entryId, principal ?? null), { leg: "stream", kind: "prompt" });
295
304
  };
296
- if (deps.runStore) {
297
- const tid = earlyDurableTid ?? uuidv7();
298
- const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
299
- if (created.ok)
300
- clearTurnActivity(tid);
301
- if (created.ok)
302
- recordResourceWindow(tid, prepared.spec.resourceSuspend);
303
- if (created.existing) {
304
- const replay = await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
305
- writeTerminalFrame(doneFrameOfOutcome(replay));
306
- return replay;
305
+ try {
306
+ if (deps.runStore) {
307
+ const tid = earlyDurableTid ?? uuidv7();
308
+ const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
309
+ if (created.ok)
310
+ clearTurnActivity(tid);
311
+ if (created.ok)
312
+ recordResourceWindow(tid, prepared.spec.resourceSuspend);
313
+ if (created.existing) {
314
+ const replay = await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
315
+ writeTerminalFrame(doneFrameOfOutcome(replay));
316
+ return replay;
317
+ }
318
+ if (created.sessionAbsent) {
319
+ const refused = rootSessionAbsentAnswer();
320
+ writeTerminalFrame(doneFrameOfOutcome(refused));
321
+ return refused;
322
+ }
323
+ if (!created.ok) {
324
+ const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
325
+ const refused = { status: 409, body: conflict };
326
+ writeTerminalFrame(doneFrameOfOutcome(refused));
327
+ return refused;
328
+ }
329
+ prepared.seat.noteOwnRun(tid);
330
+ stopClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
331
+ const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid, legId: created.legId }, prepared.execution);
332
+ if (placementReject) {
333
+ writeTerminalFrame(doneFrameOfOutcome(placementReject));
334
+ return placementReject;
335
+ }
336
+ durableTaskId = tid;
337
+ durableLegId = created.legId;
338
+ fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
307
339
  }
308
- if (created.sessionAbsent) {
309
- const refused = rootSessionAbsentAnswer();
310
- writeTerminalFrame(doneFrameOfOutcome(refused));
311
- return refused;
340
+ if (deps.checkpointStore) {
341
+ const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId, legId: heldLegOf(durableLegId, durableTaskId) } : undefined, prepared);
342
+ if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST) {
343
+ writeTerminalFrame(doneFrameOfOutcome(ctxRefusal));
344
+ return ctxRefusal;
345
+ }
312
346
  }
313
- if (!created.ok) {
314
- const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
315
- const refused = { status: 409, body: conflict };
316
- writeTerminalFrame(doneFrameOfOutcome(refused));
317
- return refused;
347
+ const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId, heldLegOf(durableLegId, durableTaskId)) : undefined;
348
+ if (lostClaim !== undefined) {
349
+ writeTerminalFrame(doneFrameOfOutcome(lostClaim));
350
+ return lostClaim;
318
351
  }
319
- prepared.seat.noteOwnRun(tid);
320
- if (detachOnDisconnect)
352
+ if (durableTaskId !== undefined && detachOnDisconnect)
321
353
  prepared.seat.markRecord();
322
- stopClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
323
- const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
324
- if (placementReject) {
325
- writeTerminalFrame(doneFrameOfOutcome(placementReject));
326
- return placementReject;
327
- }
328
- durableTaskId = tid;
329
- fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
330
- }
331
- if (deps.checkpointStore) {
332
- const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared);
333
- if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST) {
334
- writeTerminalFrame(doneFrameOfOutcome(ctxRefusal));
335
- return ctxRefusal;
336
- }
337
354
  }
338
- const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId) : undefined;
339
- if (lostClaim !== undefined) {
340
- writeTerminalFrame(doneFrameOfOutcome(lostClaim));
341
- return lostClaim;
355
+ catch (e) {
356
+ const claimFault = faultedAnswerOf(e, SUBMISSION_CLAIM_FACE.faulted);
357
+ writeTerminalFrame(doneFrameOfOutcome(claimFault));
358
+ return claimFault;
342
359
  }
343
360
  commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
344
361
  markChildrenStoppedByUserOnAbort(ac.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.subject);
@@ -407,6 +424,7 @@ export async function handleTasks(req, res, match, ctx) {
407
424
  const noticeLedger = ledgerSink;
408
425
  const unregisterEngineNotice = registerEngineNoticeLeg({
409
426
  sessionId: prepared.spec.sessionId,
427
+ ...(durableTaskId !== undefined ? { taskId: durableTaskId } : {}),
410
428
  ...(prepared.engineNotices !== undefined ? { pending: prepared.engineNotices } : {}),
411
429
  live: (row) => {
412
430
  if (res.writableEnded || res.destroyed) {
@@ -517,6 +535,7 @@ export async function handleTasks(req, res, match, ctx) {
517
535
  if (ledgerSink)
518
536
  await manifestSeat?.drain(ledgerSink.append);
519
537
  if (ev.type === "done") {
538
+ heldCard = heldParkOf(ev.result);
520
539
  finalResult = await mintSubmitExitResult(ev.result, deps.checkpointStore);
521
540
  if (durableTaskId && finalResult)
522
541
  finalResult = { ...finalResult, taskId: durableTaskId };
@@ -526,7 +545,8 @@ export async function handleTasks(req, res, match, ctx) {
526
545
  finalizeTaskResult(ev.result, principal, prepared.spec.objective);
527
546
  noteRunOutcome(finalResult);
528
547
  await putRewindAnchor();
529
- settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
548
+ if (!(durableTaskId && deps.runStore && deps.checkpointStore && heldCard !== undefined))
549
+ settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
530
550
  if (ledgerSink && finalResult) {
531
551
  if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
532
552
  const rs2 = deps.runStore;
@@ -679,7 +699,7 @@ export async function handleTasks(req, res, match, ctx) {
679
699
  owner: askOwner,
680
700
  abortSignal: ac.signal,
681
701
  sessionId: prepared.spec.sessionId,
682
- executionLane: prepared.execution.lane,
702
+ ...approvalLegOriginOf(prepared.execution),
683
703
  ...(streamApprovalOn
684
704
  ? {
685
705
  family: "approval_request",
@@ -693,12 +713,12 @@ export async function handleTasks(req, res, match, ctx) {
693
713
  if (deps.toolApproval) {
694
714
  const toolApproval = deps.toolApproval;
695
715
  prepared.spec.onAsk = unattended
696
- ? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, sessionId: prepared.spec.sessionId, executionLane: prepared.execution.lane }, unattended)
716
+ ? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, sessionId: prepared.spec.sessionId, ...approvalLegOriginOf(prepared.execution) }, unattended)
697
717
  : toolApproval.boundAsk({
698
718
  owner: askOwner,
699
719
  taskId: askTaskId,
700
720
  sessionId: prepared.spec.sessionId,
701
- executionLane: prepared.execution.lane,
721
+ ...approvalLegOriginOf(prepared.execution),
702
722
  ...(streamApprovalOn ? { legKey: "", ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
703
723
  });
704
724
  }
@@ -718,10 +738,10 @@ export async function handleTasks(req, res, match, ctx) {
718
738
  : withApproval()));
719
739
  if (durableTaskId && deps.runStore) {
720
740
  const finalPlane = finalResult ? outwardPlane(finalResult.terminal) : undefined;
721
- if (finalResult && finalPlane?.status === "suspended" && deps.checkpointStore)
722
- await deps.runStore.setSuspended(durableTaskId, finalResult);
723
- else if (finalResult && finalPlane?.status === "needs_review" && deps.checkpointStore)
724
- await deps.runStore.setNeedsReview(durableTaskId, finalResult);
741
+ if (finalResult && heldCard !== undefined && deps.checkpointStore) {
742
+ const parked = await commitSyncPark(deps.runStore, durableTaskId, heldCard.word, finalResult, heldCard.token);
743
+ settleFleet(parked.kind === "ended" ? "failed" : outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult, failureCodeOf(finalResult.terminal)));
744
+ }
725
745
  else if (finalResult && finalPlane) {
726
746
  await deps.runStore.setTerminal(durableTaskId, finalPlane.status, finalResult, finalPlane.errorMessage ?? null);
727
747
  await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
@@ -736,8 +756,8 @@ export async function handleTasks(req, res, match, ctx) {
736
756
  await ledgerSink.flush().catch(() => undefined);
737
757
  await ledgerSink.appendParked("suspended", {}).catch(() => undefined);
738
758
  }
739
- await deps.runStore.setSuspended(durableTaskId, null);
740
- settleFleet("suspended");
759
+ const parked = await commitSyncPark(deps.runStore, durableTaskId, "suspended", null, pending);
760
+ settleFleet(parked.kind === "ended" ? "failed" : "suspended");
741
761
  }
742
762
  else if (dcCause !== undefined) {
743
763
  const dcErr = "stream client disconnected before completion (run aborted)";
@@ -790,8 +810,8 @@ export async function handleTasks(req, res, match, ctx) {
790
810
  await ledgerSink.flush().catch(() => undefined);
791
811
  await ledgerSink.appendParked("suspended", {}).catch(() => undefined);
792
812
  }
793
- await deps.runStore.setSuspended(durableTaskId, null);
794
- settleFleet("suspended");
813
+ const parked = await commitSyncPark(deps.runStore, durableTaskId, "suspended", null, pending);
814
+ settleFleet(parked.kind === "ended" ? "failed" : "suspended");
795
815
  }
796
816
  else if (finalResult) {
797
817
  if (ledgerSink && !ledgerTerminal) {
@@ -881,36 +901,43 @@ export async function handleTasks(req, res, match, ctx) {
881
901
  const runSyncSubmitLeg = async () => {
882
902
  const syncLegStartedAt = Date.now();
883
903
  let durableTaskId;
904
+ let durableLegId;
884
905
  let durableHeartbeat;
885
- if (deps.runStore) {
886
- const tid = uuidv7();
887
- const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
888
- if (created.ok)
889
- clearTurnActivity(tid);
890
- if (created.ok)
891
- recordResourceWindow(tid, prepared.spec.resourceSuspend);
892
- if (created.existing)
893
- return await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
894
- if (created.sessionAbsent)
895
- return rootSessionAbsentAnswer();
896
- if (!created.ok)
897
- return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId) };
898
- prepared.seat.noteOwnRun(tid);
899
- stopSyncClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
900
- const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
901
- if (placementReject)
902
- return placementReject;
903
- durableTaskId = tid;
904
- fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
906
+ try {
907
+ if (deps.runStore) {
908
+ const tid = uuidv7();
909
+ const created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null }));
910
+ if (created.ok)
911
+ clearTurnActivity(tid);
912
+ if (created.ok)
913
+ recordResourceWindow(tid, prepared.spec.resourceSuspend);
914
+ if (created.existing)
915
+ return await replayOfExistingRun(created.existing, { subject: submitter, idem }, "sync", deps, deps.runStore);
916
+ if (created.sessionAbsent)
917
+ return rootSessionAbsentAnswer();
918
+ if (!created.ok)
919
+ return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId) };
920
+ prepared.seat.noteOwnRun(tid);
921
+ stopSyncClaimHeartbeat = startClaimHeartbeat(deps.runStore, tid, principal ?? null, deps.metrics);
922
+ const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid, legId: created.legId }, prepared.execution);
923
+ if (placementReject)
924
+ return placementReject;
925
+ durableTaskId = tid;
926
+ durableLegId = created.legId;
927
+ fillRunPreviewOnDelivery(prepared.acceptance, deps.runStore, tid);
928
+ }
929
+ if (deps.checkpointStore) {
930
+ const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId, legId: heldLegOf(durableLegId, durableTaskId) } : undefined, prepared);
931
+ if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST)
932
+ return ctxRefusal;
933
+ }
934
+ const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId, heldLegOf(durableLegId, durableTaskId)) : undefined;
935
+ if (lostClaim !== undefined)
936
+ return lostClaim;
905
937
  }
906
- if (deps.checkpointStore) {
907
- const ctxRefusal = await persistSubmissionCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared);
908
- if (ctxRefusal !== undefined && ctxRefusal !== SUBMIT_CTX_CLAIM_LOST)
909
- return ctxRefusal;
938
+ catch (e) {
939
+ return faultedAnswerOf(e, SUBMISSION_CLAIM_FACE.faulted);
910
940
  }
911
- const lostClaim = durableTaskId !== undefined && deps.runStore ? await recheckClaimBeforeLaunch(deps, deps.runStore, prepared.spec.sessionId, durableTaskId) : undefined;
912
- if (lostClaim !== undefined)
913
- return lostClaim;
914
941
  commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
915
942
  const syncCancelCtrl = createRunAbort(principal ?? null);
916
943
  markChildrenStoppedByUserOnAbort(syncCancelCtrl.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.subject);
@@ -947,8 +974,9 @@ export async function handleTasks(req, res, match, ctx) {
947
974
  counters.uncountedBillableInflight++;
948
975
  try {
949
976
  const heldDecisions = await heldWorkflowParkDecisions(deps, prepared.spec.sessionId);
950
- const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, heldDecisions);
951
- const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), heldDecisions);
977
+ const compositionInternals = { ...heldDecisions, ...compositionLegRoot(prepared.legFacts?.registeredCwd) };
978
+ const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, compositionInternals);
979
+ const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), compositionInternals);
952
980
  const plainLeg = async () => {
953
981
  const stream = prepared.runner.runTaskStream(specWithSignal, undefined, heldDecisions);
954
982
  const syncWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), prepared.legFacts?.sessionWitness);
@@ -1009,15 +1037,16 @@ export async function handleTasks(req, res, match, ctx) {
1009
1037
  }
1010
1038
  const exitResult = await mintSubmitExitResult(result, deps.checkpointStore);
1011
1039
  const syncPlane = outwardPlane(result.terminal);
1012
- if (syncPlane.status === "suspended" && deps.checkpointStore && deps.runStore && durableTaskId) {
1013
- await deps.runStore.setSuspended(durableTaskId, exitResult);
1014
- prepared.acceptance.settle(result);
1015
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "suspended" })) };
1016
- }
1017
- if (syncPlane.status === "needs_review" && deps.checkpointStore && deps.runStore && durableTaskId) {
1018
- await deps.runStore.setNeedsReview(durableTaskId, exitResult);
1040
+ const syncHeld = heldParkOf(result);
1041
+ if (syncHeld !== undefined && deps.checkpointStore && deps.runStore && durableTaskId) {
1042
+ const parked = await commitParkRow({
1043
+ runStore: deps.runStore, taskId: durableTaskId, word: syncHeld.word, result: exitResult, card: { token: syncHeld.token, sessionId: prepared.spec.sessionId }, cards: deps.checkpointStore, leg: "sync",
1044
+ legId: heldLegOf(durableLegId, durableTaskId), staleWindowMs: deps.config.runStaleSec * 1000,
1045
+ });
1019
1046
  prepared.acceptance.settle(result);
1020
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "needs_review" })) };
1047
+ if (parked.kind === "ended")
1048
+ return { status: 200, body: withSyncSubmitKeys(parked.row !== undefined ? syncSubmitBodyOfRow(parked.row) : { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "failed" }) };
1049
+ return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: syncHeld.word })) };
1021
1050
  }
1022
1051
  if (durableTaskId && deps.runStore)
1023
1052
  await deps.runStore.setTerminal(durableTaskId, syncPlane.status, exitResult, syncPlane.errorMessage ?? null);
@@ -1055,4 +1084,9 @@ export const TASKS_ROUTES = [
1055
1084
  { id: "tasks-submit", path: "/v1/tasks", billable: "submit", methods: ["POST"] },
1056
1085
  { id: "tasks-submit-stream", path: "/v1/tasks/stream", billable: "submit", methods: ["POST"] },
1057
1086
  ];
1087
+ function heldLegOf(legId, taskId) {
1088
+ if (legId === undefined)
1089
+ throw new Error(`tasks route: run ${taskId} has no record of the holding leg its createRun handed back — wiring error, nothing keyed on the leg can be written`);
1090
+ return legId;
1091
+ }
1058
1092
  //# sourceMappingURL=tasks.js.map
@@ -606,7 +606,7 @@ export interface ServiceSeamDeps {
606
606
  /** [ref] §10.2 —— 跨主体投递门(`createOrgDeliveryGate` 的产物,`boot/stage-06-runners.ts` 装配的唯一实例)。
607
607
  * `POST /v1/principal-inbox/messages` 只经它投递;缺席 = 本部署没声明收件箱消费方(`PRINCIPAL_INBOX_ASSISTANT` 未设)⇒
608
608
  * 那一口 501、能力位 `principalInboxDelivery` false(同读事实 `principalInboxDelivery`)。 */
609
- orgDeliveryGate?: import("@sema-agent/core").OrgDeliveryGate;
609
+ orgDeliveryGate?: import("../org-delivery-gate.js").ServerOrgDeliveryGate;
610
610
  /** WEB-SETUP-RECON 附B — org sessionMirror 治理态的 SERVICE 半场 = **观测面(audit),非执法面**。
611
611
  * 裁定 (c):「该镜像而未镜像」发生在数据产生端(壳)——本 server 是镜像**目标**,只看得见到达的 push;
612
612
  * 没到达的会话对 server 不存在(无客户端会话清单、无心跳契约),required 锁的真执法只能在壳(CC
@@ -659,10 +659,9 @@ export interface ServiceObservabilityDeps {
659
659
  * 缺席 = 该道门不存在(不是「默认放行的门」——两者在事故复盘里语义完全不同)。 */
660
660
  export interface ServiceGovernanceDeps {
661
661
  /** 鉴权桥(registry-core api/auth-bridge):registry 用户 JWT → principal。缺席=分支不存在
662
- * (bearer 只认 SERVICE_AUTH_TOKEN(S),现状不变)。 */
663
- webAdminJwtVerifier?: {
664
- verify: (bearer: string) => Promise<import("../auth-bridge.js").VerifyOutcome>;
665
- };
662
+ * (bearer 只认 SERVICE_AUTH_TOKEN(S),现状不变)。席上的型就是工厂 `createWebAdminJwtVerifier` 铸的那一种(含只读成员 `issuer` = 它验的 issuer):
663
+ * 与配置里的桥成对(在不在、验的是谁),`createHttpServer` 构造期判。 */
664
+ webAdminJwtVerifier?: import("../auth-bridge.js").WebAdminJwtVerifier;
666
665
  /** Per-principal rate limiter for task/run endpoints. In-memory (single replica) or TiDB-backed
667
666
  * (cross-replica soft limit) — both satisfy RateGate. */
668
667
  rateLimiter?: RateGate;
@@ -5,6 +5,7 @@ import {} from "../web-admin-client/facade.js";
5
5
  import { describeValueShape } from "@sema-agent/settings-schema";
6
6
  import { HttpError } from "../security.js";
7
7
  import { SessionDeletingError, SessionForkInProgressError } from "../execution-placement.js";
8
+ import { ORG_DELIVERY_QUOTA_UNREADABLE_SENTENCE, OrgDeliveryQuotaUnreadableError } from "../plugins/org-delivery-quota-store.js";
8
9
  import {} from "../memory-sync.js";
9
10
  import {} from "../orchestration/workflow-agent-steer.js";
10
11
  import {} from "../orchestration/workflow-completion-inbox.js";
@@ -26,7 +27,7 @@ import { sqlEngineSeatIssue } from "../sql-engine-posture.js";
26
27
  import { parkDecisionStoreRefusal } from "../orchestration/workflow-park-decision.js";
27
28
  import { CHECKPOINT_CTX_SEALING_REQUIRED } from "./checkpoint-ctx.js";
28
29
  import { PARKED_REVIVE_EXECUTION_SEAT_REQUIRED } from "../parked-decide.js";
29
- import { a2aAudienceIdentityBoundaryRefusal, operatorDeclarationRefusal } from "../config-invariants.js";
30
+ import { a2aAudienceVerifiedSourceRefusal, operatorDeclarationRefusal } from "../config-invariants.js";
30
31
  import { retiredServiceDepsRefusal } from "./retired-service-deps.js";
31
32
  import { createAdmission, MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills } from "./admission.js";
32
33
  import { createResumeLegs } from "./resume-legs.js";
@@ -37,7 +38,9 @@ import { createApprovalSweeps } from "./approval-sweeps.js";
37
38
  export { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath };
38
39
  export { MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills };
39
40
  import { explicitOperatorOk } from "./principal-gate.js";
40
- import { configuredIdentitySources } from "../identity-source.js";
41
+ import { authBridgeIssuerOf, configuredIdentitySources } from "../identity-source.js";
42
+ import { normalizeBridgeIssuer } from "../auth-bridge.js";
43
+ import { buildDisplaySafeUrl } from "../trace/redact.js";
41
44
  export { explicitOperatorOk };
42
45
  class DrainYieldingPreemptBook extends Map {
43
46
  drainingNow;
@@ -73,6 +76,12 @@ export function createHttpServer(rawDeps) {
73
76
  if (!Array.isArray(deps.deploymentMods)) {
74
77
  throw new Error("createHttpServer: the deploymentMods seat is required — it is how the server learns whether a prompt screen runs on its legs (the same registrations the Runners carry as `mods`); pass `[]` for an embedding without mods; refusing to start rather than store objective text before the screen decides");
75
78
  }
79
+ if (typeof deps.peerDesk?.lease !== "function" || typeof deps.peerDesk.declare !== "function" || typeof deps.peerDesk.seat?.answer !== "function") {
80
+ throw new Error("createHttpServer: the peerDesk seat is required — it is the one registry of the MCP / A2A credential pieces a send carries, and the submission and resume funnels open their host leases over it; pass `createPeerDesk()` (package root, zero IO — an embedding without MCP / A2A credentials passes one too), the very desk each Runner carries as `peerSeat: desk.seat`; refusing to start rather than answer every submission with a 500 at its first lease");
81
+ }
82
+ if (typeof deps.scenarioGate !== "function" || typeof deps.scenarioGate.known !== "function") {
83
+ throw new Error("createHttpServer: the scenarioGate seat is required — it is the one reading of which scenario names this deployment serves and lets a principal use, and the capability status face, the two session panels and the scenario request header all ask it; pass the gate that `createScenarioGate` (package root) mints from your config, scenario table and principal caps on its \"peek\" leg; refusing to start rather than answer those reads with a 500");
84
+ }
76
85
  {
77
86
  const retired = retiredServiceDepsRefusal(deps);
78
87
  if (retired !== undefined)
@@ -97,11 +106,23 @@ export function createHttpServer(rawDeps) {
97
106
  "the service boot builds one from that same issuer; inject a verifier for it, or remove the bridge and the center from the config, " +
98
107
  "since /health.auth, the owner gates and the one-time migrations read the bridge from the config alone; refusing to start rather than report SSO sign-in that verifies nobody");
99
108
  }
109
+ const configured = authBridgeIssuerOf(deps.config);
110
+ const verifier = deps.webAdminJwtVerifier;
111
+ if (verifier !== undefined && configured !== undefined) {
112
+ const verifies = verifier.issuer;
113
+ if (typeof verifies !== "string" || normalizeBridgeIssuer(verifies) !== normalizeBridgeIssuer(configured.issuer)) {
114
+ throw new Error(`createHttpServer: the injected webAdminJwtVerifier verifies issuer ${typeof verifies === "string" ? buildDisplaySafeUrl(verifies) : `<${describeValueShape(verifies)}>`}, ` +
115
+ `but the config's auth bridge issuer is ${buildDisplaySafeUrl(configured.issuer)} (authBridgeIssuer / AUTH_BRIDGE_ISSUER, or the center base webAdmin.baseUrl when that is unset) — ` +
116
+ "the gate would accept one issuer's tokens while /health.center.issuer reports another; the config is the only place the deployment's issuer is read, " +
117
+ "so inject a verifier whose `issuer` member (the issuer it verifies tokens for) is that one, or change the config to the issuer the verifier verifies " +
118
+ "(the values are shown display-safe: credentials, query and fragment are folded); refusing to start rather than verify tokens for an issuer this deployment does not report");
119
+ }
120
+ }
100
121
  }
101
122
  {
102
- const audienceBoundaryFailure = a2aAudienceIdentityBoundaryRefusal(deps.config.a2aServe, configuredIdentitySources(deps.config).length === 0);
103
- if (audienceBoundaryFailure !== undefined)
104
- throw new Error(audienceBoundaryFailure);
123
+ const audienceSourceFailure = a2aAudienceVerifiedSourceRefusal(deps.config.a2aServe, configuredIdentitySources(deps.config).length === 0);
124
+ if (audienceSourceFailure !== undefined)
125
+ throw new Error(audienceSourceFailure);
105
126
  }
106
127
  {
107
128
  const issue = sqlEngineSeatIssue(deps.backend, deps.sqlEngine);
@@ -227,6 +248,10 @@ export function createHttpServer(rawDeps) {
227
248
  sendError(res, 409, err.code, err.message);
228
249
  return;
229
250
  }
251
+ if (err instanceof OrgDeliveryQuotaUnreadableError) {
252
+ sendError(res, 500, "internal.org_delivery_quota_unreadable", ORG_DELIVERY_QUOTA_UNREADABLE_SENTENCE);
253
+ return;
254
+ }
230
255
  sendOpenFaceFault(res, err);
231
256
  });
232
257
  });
@@ -35,6 +35,7 @@ export declare function persistSubmitCtx(store: SubmitCtxStore, deps: {
35
35
  }, claim: {
36
36
  readonly runStore: RunStore;
37
37
  readonly taskId: string;
38
+ readonly legId: string;
38
39
  } | undefined, sessionId: string, fields: Parameters<typeof buildCheckpointCtx>[0]): Promise<SubmitCtxRefusal | typeof SUBMIT_CTX_CLAIM_LOST | undefined>;
39
40
  /**
40
41
  * 提交腿写续跑输入的入口(三个调用点同调这一只):体与标记按受理座提交时交出的那一份定(见文件头「体里的目标按哪一份写」),只写这一笔。
@@ -1,5 +1,5 @@
1
1
  import { StoreRowTooLargeError } from "../plugins/sql-errors.js";
2
- import { releaseClaimedRun } from "./claimed-run.js";
2
+ import { withdrawClaimedRun } from "./claimed-run.js";
3
3
  import { runProvenElsewhere } from "../plugins/store-contracts.js";
4
4
  import { buildCheckpointCtx, CheckpointCtxUnsealableError } from "./checkpoint-ctx.js";
5
5
  import { refusalBody } from "./refusal-body.js";
@@ -51,8 +51,7 @@ export async function persistSubmitCtx(store, deps, claim, sessionId, fields) {
51
51
  const unsealable = err instanceof CheckpointCtxUnsealableError ? err : undefined;
52
52
  const known = tooLarge ?? unsealable;
53
53
  if (claim !== undefined) {
54
- const why = known !== undefined ? known.message : `the run's resume inputs could not be stored: ${err instanceof Error ? err.message : String(err)}`;
55
- await releaseClaimedRun(claim.runStore, claim.taskId, why, (releaseErr, step) => {
54
+ await withdrawClaimedRun(claim.runStore, claim.taskId, claim.legId, (releaseErr, step) => {
56
55
  deps.logger?.warn("submit_ctx_run_release_failed", { taskId: claim.taskId, sessionId, step, err: releaseErr instanceof Error ? releaseErr.message : String(releaseErr) });
57
56
  deps.metrics?.inc("submit_ctx_run_release_failed_total", { step });
58
57
  });
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export { createBrain } from "./brain.js";
5
5
  export { createSessionStore } from "./plugins/session-store.js";
6
6
  export { createStoreBackend, type StoreBackend, type SessionCaptureRecordSource } from "./plugins/store-backend.js";
7
7
  export { RetiredSchemaPresentError } from "./plugins/schema-consistency.js";
8
+ export { LegacySkillExemptionsPresentError } from "./plugins/approval-exemption-skill-cutoff.js";
8
9
  export { LocalDataRootSchemaMismatchError, type LocalDataRootMismatch } from "./plugins/local-session-store.js";
9
10
  export { CachingSessionStore, type CachingOptions } from "./plugins/caching-session-store.js";
10
11
  export type { RunRecord, RunEvent } from "./plugins/store-contracts.js";
@@ -38,6 +39,7 @@ export { CATALOG_ENTRY_HEADER_LANES, CATALOG_ENTRY_HEADER_NAMES, type CatalogEnt
38
39
  export type { ModelRouteGap } from "./model-route-endpoint.js";
39
40
  export { judgeServedModelRoute, type ServedModelRouteView, type ServedModelRouteOptions, type ModelRouteEndpointVerdict } from "./model-route-endpoint.js";
40
41
  export type { UserInputLedgerStore, UserInputAcceptance, NewUserInputAcceptance, OpenScanCursor, OpenScanPage, SettleHow, WriterGoneEvidence } from "./user-input-ledger.js";
41
- export type { OrgDeliveryQuotaStore, OrgDeliveryQuotaPolicy } from "./plugins/org-delivery-quota-store.js";
42
+ export type { OrgDeliveryQuotaStore, OrgDeliveryQuotaPolicy, OrgDeliveryQuotaVerdict } from "./plugins/org-delivery-quota-store.js";
43
+ export type { ServerOrgDeliveryGate, ServerOrgDeliveryOutcome } from "./org-delivery-gate.js";
42
44
  export { APPROVAL_GATE_KINDS, type ApprovalGateKind } from "./approval-content-kind.js";
43
45
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export { createBrain } from "./brain.js";
5
5
  export { createSessionStore } from "./plugins/session-store.js";
6
6
  export { createStoreBackend } from "./plugins/store-backend.js";
7
7
  export { RetiredSchemaPresentError } from "./plugins/schema-consistency.js";
8
+ export { LegacySkillExemptionsPresentError } from "./plugins/approval-exemption-skill-cutoff.js";
8
9
  export { LocalDataRootSchemaMismatchError } from "./plugins/local-session-store.js";
9
10
  export { CachingSessionStore } from "./plugins/caching-session-store.js";
10
11
  export { runInBackground } from "./runs.js";
@@ -1,7 +1,7 @@
1
1
  /**
2
- * 一条腿的**部署事实**(执行车道 · run 技能名册 · 受理见证)—— server 自有的载体,**不搭引擎 spec 的车**。
2
+ * 一条腿的**部署事实**(执行车道 · run 技能名册 · 受理见证 · 登记的工作目录)—— server 自有的载体,**不搭引擎 spec 的车**。
3
3
  *
4
- * 规则:`TaskSpec` 是引擎的类型面,上面只放引擎读的成员。本仓装配器(`boot/resolve-spec.ts` 的 `createResolveSpec`)同时还判出三件
4
+ * 规则:`TaskSpec` 是引擎的类型面,上面只放引擎读的成员。本仓装配器(`boot/resolve-spec.ts` 的 `createResolveSpec`)同时还判出四件
5
5
  * 只有 server 自己读的事实 —— 它们以装配器**自己的输出对象**为键登记在这一张表里(单一铸点 {@link mintLegFacts}),由两只漏斗
6
6
  * (受理 `http/admission.ts` 的 `prepareSpec` · 续跑 `http/resume-legs.ts` 的 `resolveResumeSpec`)在拿到装配输出的**同一只对象**时
7
7
  * 读一次(唯一读口 {@link legFactsOf},读在 `stampSpecRoot` 复制之前),此后作普通值随 `PreparedTaskSubmission.legFacts` /
@@ -26,6 +26,11 @@ export interface LegFacts {
26
26
  readonly skills: readonly RunSkillEntry[];
27
27
  /** 受理时读根会话行的那一读(会话 id + 住客)。读者 = 腿的会话行记录座(`session-workspace.ts`)。 */
28
28
  readonly sessionWitness: DelegationRootWitness;
29
+ /**
30
+ * 这次提交的根会话登记的工作目录(提交体 `cwd` 经唯一写口 `setSessionCwd` 登记的那一枚;装配器在登记之后读一次)。缺席 = 没登记。
31
+ * 读者 = 三只组合入口(同步 / 后台 / 续跑腿的梯子与验证门):经 `compositionLegRoot`(`task-cwd.ts`)交给它们驱动的每一条腿当交活方的工作目录。
32
+ */
33
+ readonly registeredCwd?: string;
29
34
  }
30
35
  /**
31
36
  * 铸事实(**单一属主**:只允许 `createResolveSpec` 的出口调用)。同一只对象被第二次铸 ⇒ 当场抛 —— 两个写者是漂移的成因,
package/dist/leg-facts.js CHANGED
@@ -6,6 +6,7 @@ export function mintLegFacts(resolved, facts) {
6
6
  hands: facts.hands,
7
7
  skills: Object.freeze(facts.skills.map((e) => Object.freeze({ ...e }))),
8
8
  sessionWitness: Object.freeze({ ...facts.sessionWitness }),
9
+ ...(facts.registeredCwd !== undefined ? { registeredCwd: facts.registeredCwd } : {}),
9
10
  }));
10
11
  return resolved;
11
12
  }