@sema-agent/server 7.142.0 → 7.144.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 (301) hide show
  1. package/MIGRATION.md +608 -0
  2. package/USAGE.md +63 -36
  3. package/dist/adoption/plan.js +22 -0
  4. package/dist/approval-ask-audit-store.d.ts +7 -5
  5. package/dist/approval-ask-audit-store.js +12 -6
  6. package/dist/approval-ask-machine.d.ts +15 -7
  7. package/dist/approval-ask-machine.js +10 -4
  8. package/dist/approval-card.d.ts +155 -39
  9. package/dist/approval-card.js +111 -31
  10. package/dist/approval-queue-kind.d.ts +27 -0
  11. package/dist/approval-queue-kind.js +6 -0
  12. package/dist/approval-reconciler.d.ts +8 -8
  13. package/dist/approval-reconciler.js +3 -3
  14. package/dist/audit.js +4 -2
  15. package/dist/boot/budget-tracing.d.ts +1 -1
  16. package/dist/boot/execution-env.js +1 -1
  17. package/dist/boot/governance-seams.d.ts +26 -41
  18. package/dist/boot/governance-seams.js +61 -28
  19. package/dist/boot/late-binds.d.ts +7 -4
  20. package/dist/boot/late-binds.js +3 -1
  21. package/dist/boot/leader.js +2 -4
  22. package/dist/boot/memory-consolidation.d.ts +0 -8
  23. package/dist/boot/memory-consolidation.js +3 -3
  24. package/dist/boot/reapers.js +5 -4
  25. package/dist/boot/resolve-spec.d.ts +1 -1
  26. package/dist/boot/resolve-spec.js +8 -8
  27. package/dist/boot/runner-deps.d.ts +14 -6
  28. package/dist/boot/runner-deps.js +6 -17
  29. package/dist/boot/shutdown.d.ts +9 -0
  30. package/dist/boot/shutdown.js +18 -2
  31. package/dist/boot/stage-01-config.js +2 -0
  32. package/dist/boot/stage-02-web-admin-pull.js +3 -0
  33. package/dist/boot/stage-03-store-backend.d.ts +4 -1
  34. package/dist/boot/stage-03-store-backend.js +1 -2
  35. package/dist/boot/stage-04-stores.d.ts +5 -2
  36. package/dist/boot/stage-04-stores.js +3 -5
  37. package/dist/boot/stage-05-execution-env.d.ts +5 -2
  38. package/dist/boot/stage-06-runners.d.ts +5 -2
  39. package/dist/boot/stage-06-runners.js +1 -3
  40. package/dist/boot/stage-07-capability-layer.d.ts +5 -2
  41. package/dist/boot/stage-07-capability-layer.js +6 -2
  42. package/dist/boot/stage-08-reapers.d.ts +5 -2
  43. package/dist/boot/stage-09-leader.d.ts +5 -2
  44. package/dist/boot/stage-10-http-server.d.ts +5 -2
  45. package/dist/boot/stage-10-http-server.js +4 -1
  46. package/dist/boot/stores.d.ts +5 -2
  47. package/dist/boot/stores.js +7 -7
  48. package/dist/boot/web-admin.d.ts +5 -1
  49. package/dist/boot/web-admin.js +31 -19
  50. package/dist/capabilities/hands-lane.d.ts +9 -39
  51. package/dist/capabilities/hands-lane.js +8 -13
  52. package/dist/capabilities/mcp-probe.d.ts +3 -2
  53. package/dist/capabilities/scenarios.d.ts +23 -17
  54. package/dist/capabilities/scenarios.js +2 -2
  55. package/dist/capabilities/skills.d.ts +1 -17
  56. package/dist/capabilities/skills.js +0 -8
  57. package/dist/capability-facts.d.ts +8 -8
  58. package/dist/capability-facts.js +4 -4
  59. package/dist/card-void.d.ts +6 -9
  60. package/dist/config-catalog.js +1 -1
  61. package/dist/config-d-migration.d.ts +2 -0
  62. package/dist/config-dir-trust.js +58 -29
  63. package/dist/config-invariants.d.ts +7 -1
  64. package/dist/config-invariants.js +7 -0
  65. package/dist/config-provider.d.ts +10 -0
  66. package/dist/config-provider.js +15 -4
  67. package/dist/config-root-migration.d.ts +13 -0
  68. package/dist/config-root-migration.js +99 -0
  69. package/dist/config-types.d.ts +5 -5
  70. package/dist/config.d.ts +4 -3
  71. package/dist/config.js +1 -1
  72. package/dist/delegated-session-owner.d.ts +35 -151
  73. package/dist/delegated-session-owner.js +1 -83
  74. package/dist/device-ws-protocol.d.ts +1 -0
  75. package/dist/device-ws-protocol.js +2 -1
  76. package/dist/entry-mode-clamp-notice.d.ts +1 -1
  77. package/dist/env-model-table-gate.d.ts +53 -0
  78. package/dist/env-model-table-gate.js +53 -0
  79. package/dist/execution-placement.d.ts +7 -4
  80. package/dist/fleet/fleet-bus.d.ts +28 -52
  81. package/dist/fleet/fleet-bus.js +35 -100
  82. package/dist/fleet/fleet-reconciler.d.ts +4 -4
  83. package/dist/fleet/fleet-reconciler.js +1 -1
  84. package/dist/fleet/subagent-tail-bus.d.ts +14 -11
  85. package/dist/fleet/subagent-tail-bus.js +15 -28
  86. package/dist/hooks/classic-stations.d.ts +3 -1
  87. package/dist/hooks/classic-stations.js +2 -0
  88. package/dist/hooks/hook-runner.js +28 -7
  89. package/dist/host-decision.d.ts +54 -20
  90. package/dist/host-decision.js +42 -14
  91. package/dist/http/admission.d.ts +1 -1
  92. package/dist/http/admission.js +7 -3
  93. package/dist/http/approval-sweeps.js +11 -8
  94. package/dist/http/caller-trust.d.ts +1 -1
  95. package/dist/http/durable-run-leg.js +2 -2
  96. package/dist/http/engine-refusal.d.ts +16 -0
  97. package/dist/http/engine-refusal.js +17 -0
  98. package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
  99. package/dist/http/memory-compliance-failure-reply.js +4 -6
  100. package/dist/http/owner-access.d.ts +11 -0
  101. package/dist/http/owner-access.js +13 -0
  102. package/dist/http/principal-gate.d.ts +1 -1
  103. package/dist/http/refusal-body.d.ts +7 -3
  104. package/dist/http/refusal-body.js +1 -0
  105. package/dist/http/resume-legs.d.ts +21 -7
  106. package/dist/http/resume-legs.js +82 -53
  107. package/dist/http/resume-restatement.d.ts +39 -0
  108. package/dist/http/resume-restatement.js +25 -0
  109. package/dist/http/route-ctx.d.ts +35 -10
  110. package/dist/http/route-ctx.js +1 -1
  111. package/dist/http/routes/approvals-assistant.d.ts +9 -1
  112. package/dist/http/routes/approvals-assistant.js +143 -31
  113. package/dist/http/routes/capabilities.js +11 -2
  114. package/dist/http/routes/memory-policy.d.ts +2 -2
  115. package/dist/http/routes/memory-policy.js +1 -1
  116. package/dist/http/routes/notify-wake.js +23 -25
  117. package/dist/http/routes/rules.js +48 -13
  118. package/dist/http/routes/runs.js +9 -8
  119. package/dist/http/routes/session-memory-sync.d.ts +34 -6
  120. package/dist/http/routes/session-memory-sync.js +27 -10
  121. package/dist/http/routes/session-sync.js +13 -20
  122. package/dist/http/routes/sessions.d.ts +2 -2
  123. package/dist/http/routes/sessions.js +22 -23
  124. package/dist/http/routes/tasks.js +27 -49
  125. package/dist/http/server.d.ts +13 -7
  126. package/dist/http/server.js +2 -2
  127. package/dist/http/stored-body-replay.js +15 -4
  128. package/dist/http/wire-types.d.ts +17 -7
  129. package/dist/index.d.ts +1 -0
  130. package/dist/index.js +1 -0
  131. package/dist/lane-home-probe.d.ts +15 -0
  132. package/dist/lane-home-probe.js +4 -0
  133. package/dist/leader/leader.js +5 -2
  134. package/dist/leader/wire.d.ts +7 -1
  135. package/dist/leader/wire.js +6 -5
  136. package/dist/leg-facts.d.ts +37 -0
  137. package/dist/leg-facts.js +15 -0
  138. package/dist/memory-bundle-engine.d.ts +1 -4
  139. package/dist/memory-bundle-engine.js +2 -2
  140. package/dist/memory-operator-faces.d.ts +30 -66
  141. package/dist/memory-operator-faces.js +17 -88
  142. package/dist/memory-scope-stores.d.ts +38 -40
  143. package/dist/memory-scope-stores.js +51 -36
  144. package/dist/memory-scope.d.ts +0 -9
  145. package/dist/memory-scope.js +0 -9
  146. package/dist/memory-sync-client.js +14 -3
  147. package/dist/memory-sync.d.ts +20 -4
  148. package/dist/memory-sync.js +23 -4
  149. package/dist/model-plane-face.d.ts +13 -7
  150. package/dist/model-plane-face.js +2 -1
  151. package/dist/observability/corrupt-read-seat.d.ts +5 -9
  152. package/dist/observability/corrupt-read-seat.js +1 -2
  153. package/dist/observability/fail-open.d.ts +30 -10
  154. package/dist/observability/fail-open.js +27 -10
  155. package/dist/observability/run-terminal.d.ts +1 -1
  156. package/dist/observability/run-terminal.js +6 -2
  157. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
  158. package/dist/orchestration/workflow-completion-inbox.js +0 -12
  159. package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
  160. package/dist/orchestration/workflow-park-decision.d.ts +8 -3
  161. package/dist/orchestration/workflow-park-decision.js +5 -3
  162. package/dist/org-delivery-gate.d.ts +11 -0
  163. package/dist/org-delivery-gate.js +19 -1
  164. package/dist/parked-decide.d.ts +13 -9
  165. package/dist/parked-decide.js +7 -7
  166. package/dist/parked-revive-surface.d.ts +6 -7
  167. package/dist/parked-revive-surface.js +1 -1
  168. package/dist/peer-inbound-face.d.ts +122 -0
  169. package/dist/peer-inbound-face.js +123 -0
  170. package/dist/permission-rule-list.d.ts +13 -9
  171. package/dist/permission-rule-list.js +7 -3
  172. package/dist/plugins/approval-ask-store-file.js +18 -6
  173. package/dist/plugins/approval-ask-store-memory.js +8 -6
  174. package/dist/plugins/approval-ask-store-sql.d.ts +28 -13
  175. package/dist/plugins/approval-ask-store-sql.js +30 -11
  176. package/dist/plugins/caching-session-store.d.ts +0 -3
  177. package/dist/plugins/caching-session-store.js +0 -3
  178. package/dist/plugins/checkpoint-store-sql.d.ts +45 -38
  179. package/dist/plugins/checkpoint-store-sql.js +108 -45
  180. package/dist/plugins/file-history-store-sql.d.ts +24 -18
  181. package/dist/plugins/file-history-store-sql.js +24 -19
  182. package/dist/plugins/file-run-store.d.ts +29 -0
  183. package/dist/plugins/file-run-store.js +97 -8
  184. package/dist/plugins/fork-routing-session-store.d.ts +8 -1
  185. package/dist/plugins/fork-routing-session-store.js +6 -0
  186. package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
  187. package/dist/plugins/imported-layer-root-retirement.js +96 -0
  188. package/dist/plugins/local-checkpoint-store.d.ts +6 -8
  189. package/dist/plugins/local-checkpoint-store.js +5 -4
  190. package/dist/plugins/local-session-store.d.ts +69 -30
  191. package/dist/plugins/local-session-store.js +133 -57
  192. package/dist/plugins/local-session-window.d.ts +4 -2
  193. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
  194. package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
  195. package/dist/plugins/mailbox-store-sql.d.ts +12 -8
  196. package/dist/plugins/mailbox-store-sql.js +76 -7
  197. package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
  198. package/dist/plugins/memory-sync-store-pg.js +21 -0
  199. package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
  200. package/dist/plugins/memory-sync-store-tidb.js +13 -1
  201. package/dist/plugins/one-time-migrations.d.ts +44 -14
  202. package/dist/plugins/one-time-migrations.js +118 -15
  203. package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
  204. package/dist/plugins/org-delivery-quota-store.js +2 -12
  205. package/dist/plugins/park-commit-watch.d.ts +1 -1
  206. package/dist/plugins/permission-rule-store-file.d.ts +10 -1
  207. package/dist/plugins/permission-rule-store-file.js +15 -2
  208. package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
  209. package/dist/plugins/permission-rule-store-sql.js +35 -2
  210. package/dist/plugins/pg-session-storage.d.ts +1 -9
  211. package/dist/plugins/pg-session-storage.js +2 -19
  212. package/dist/plugins/remote-env-device.d.ts +8 -11
  213. package/dist/plugins/remote-env-device.js +6 -3
  214. package/dist/plugins/remote-env-host.d.ts +8 -4
  215. package/dist/plugins/remote-env-host.js +7 -9
  216. package/dist/plugins/remote-env-k8s.d.ts +37 -24
  217. package/dist/plugins/remote-env-k8s.js +50 -17
  218. package/dist/plugins/remote-shell.js +12 -2
  219. package/dist/plugins/retention-store-sql.d.ts +2 -2
  220. package/dist/plugins/sandbox-read-floor.d.ts +5 -7
  221. package/dist/plugins/sandbox-read-floor.js +2 -7
  222. package/dist/plugins/schema-consistency.d.ts +5 -1
  223. package/dist/plugins/session-fork.d.ts +1 -1
  224. package/dist/plugins/session-ownership.d.ts +9 -0
  225. package/dist/plugins/session-ownership.js +6 -0
  226. package/dist/plugins/session-store.d.ts +13 -16
  227. package/dist/plugins/session-store.js +9 -10
  228. package/dist/plugins/sql-errors.d.ts +10 -1
  229. package/dist/plugins/sql-errors.js +13 -0
  230. package/dist/plugins/sql-json-column.d.ts +24 -2
  231. package/dist/plugins/sql-json-column.js +38 -3
  232. package/dist/plugins/store-backend.d.ts +23 -28
  233. package/dist/plugins/store-backend.js +12 -3
  234. package/dist/plugins/store-contracts.d.ts +29 -5
  235. package/dist/plugins/store-contracts.js +4 -1
  236. package/dist/plugins/task-attachment-store.d.ts +2 -2
  237. package/dist/plugins/task-attachment-store.js +37 -52
  238. package/dist/plugins/tidb-session-store.d.ts +2 -14
  239. package/dist/plugins/tidb-session-store.js +2 -20
  240. package/dist/plugins/tool-result-store-sql.d.ts +9 -8
  241. package/dist/plugins/tool-result-store-sql.js +23 -2
  242. package/dist/plugins/wiring-section-codec.d.ts +32 -0
  243. package/dist/plugins/wiring-section-codec.js +55 -0
  244. package/dist/plugins/workspace-fill.d.ts +1 -1
  245. package/dist/rule-entry-list.d.ts +3 -2
  246. package/dist/rule-entry-list.js +5 -1
  247. package/dist/rules-consent.d.ts +28 -5
  248. package/dist/rules-consent.js +40 -28
  249. package/dist/run-local.js +11 -6
  250. package/dist/runs.d.ts +12 -8
  251. package/dist/runs.js +10 -7
  252. package/dist/runtime-governance.d.ts +1 -1
  253. package/dist/security.d.ts +0 -4
  254. package/dist/server-secret-env.d.ts +4 -0
  255. package/dist/session-error-wire.d.ts +34 -23
  256. package/dist/session-error-wire.js +8 -3
  257. package/dist/session-incarnation.d.ts +3 -3
  258. package/dist/session-notify-door.d.ts +106 -0
  259. package/dist/session-notify-door.js +97 -0
  260. package/dist/session-sync.d.ts +9 -14
  261. package/dist/session-sync.js +5 -5
  262. package/dist/session-workspace.d.ts +3 -13
  263. package/dist/session-workspace.js +0 -9
  264. package/dist/standing-answer-grant.d.ts +5 -0
  265. package/dist/standing-answer-grant.js +10 -0
  266. package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
  267. package/dist/stores-sql/session-policy-store-sql.js +3 -13
  268. package/dist/task-mcp.d.ts +1 -1
  269. package/dist/task-settings.d.ts +11 -8
  270. package/dist/task-settings.js +31 -11
  271. package/dist/tool-approval.d.ts +55 -35
  272. package/dist/tool-approval.js +112 -74
  273. package/dist/trace/core-keyset-guard.d.ts +12 -9
  274. package/dist/trace/engine-notice-wire.d.ts +1 -1
  275. package/dist/trace/engine-notice-wire.js +4 -2
  276. package/dist/trace/exit-seat.d.ts +7 -1
  277. package/dist/trace/exit-seat.js +1 -0
  278. package/dist/trace/ledger-sink.d.ts +2 -2
  279. package/dist/trace/ledger-sink.js +12 -4
  280. package/dist/trace/model-segment.d.ts +74 -25
  281. package/dist/trace/model-segment.js +141 -32
  282. package/dist/trace/project.d.ts +15 -6
  283. package/dist/trace/project.js +12 -4
  284. package/dist/trace/redact.d.ts +72 -9
  285. package/dist/trace/redact.js +1509 -471
  286. package/dist/trace/self-minted-wire.d.ts +598 -47
  287. package/dist/trace/self-minted-wire.js +190 -20
  288. package/dist/trace/wire-projection-faces.d.ts +1 -1
  289. package/dist/trace/wire-projection-faces.js +1 -1
  290. package/dist/verifier-pause-card.d.ts +33 -5
  291. package/dist/verifier-pause-card.js +15 -10
  292. package/dist/web-admin-client/apply-effective.d.ts +12 -16
  293. package/dist/web-admin-client/apply-effective.js +90 -10
  294. package/dist/workspace-space.d.ts +19 -3
  295. package/dist/workspace-space.js +8 -4
  296. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
  297. package/package.json +3 -2
  298. package/wire-changes/server@7.143.0.json +1167 -0
  299. package/wire-changes/server@7.144.0.json +291 -0
  300. package/dist/session-records-skipped-notice.d.ts +0 -21
  301. package/dist/session-records-skipped-notice.js +0 -27
package/dist/run-local.js CHANGED
@@ -19,7 +19,7 @@ import { applyRuntimeGovernance, autonomyModeFloor, entryPermissionMode } from "
19
19
  import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
20
20
  import { taskWallClockSec } from "./task-workflow.js";
21
21
  import { applyCenterArtifact, centerSourceOnError } from "./capabilities/center-prompts.js";
22
- import { buildUnpricedCeilingNotice, loadConfig, logConfigDiagnostics, parseConfigProvider, parseNumOrFailNonNegative } from "./config.js";
22
+ import { buildUnpricedCeilingNotice, isRosterGateArmed, loadConfig, logConfigDiagnostics, parseConfigProvider, parseNumOrFailNonNegative } from "./config.js";
23
23
  import { buildStoreOpenRefusalTail } from "./plugins/store-open-refusal.js";
24
24
  import { acquireLocalBackendWithWait } from "./plugins/store-lock-wait.js";
25
25
  import { configLocalRoot, createConfigProvider } from "./config-provider.js";
@@ -28,6 +28,7 @@ import { buildUnreadConfigFileFields, buildUnreadConfigKeyFields } from "./web-a
28
28
  import { composeExecutionLane, settleHostLaneShell, warnReadDenyFloorUnkept } from "./boot/execution-lane.js";
29
29
  import { judgeConsolidationValve } from "./boot/memory-consolidation.js";
30
30
  import { logConfigDirMigration, migrateLocalConfigDirectory } from "./config-d-migration.js";
31
+ import { logEnvModelsMigration, runEnvModelsMigration } from "./config-root-migration.js";
31
32
  import { assertLocalConfigDirTrusted, ConfigDirUntrustedError } from "./config-dir-trust.js";
32
33
  import { applyEffective, applyCenterReadFace, applySkillsManifest, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./web-admin-client/facade.js";
33
34
  import { hostExecutionEnvFactory } from "./plugins/remote-env-host.js";
@@ -42,7 +43,7 @@ import { createTaskListLane } from "./boot/task-list-lane.js";
42
43
  import { pickHandsRunner, withoutHands } from "./capabilities/hands-lane.js";
43
44
  import { HttpError, sessionIdShapeIssue } from "./security.js";
44
45
  import { createMemoryEngineIncidentSink } from "./memory-incident-sink.js";
45
- import { fileMemoryEngineRoot, memoryEngineBackendFor, memoryLayersNamedBy, memorySpecForRequest } from "./memory-scope.js";
46
+ import { fileMemoryEngineRoot, memoryEngineBackendFor, memorySpecForRequest } from "./memory-scope.js";
46
47
  import { createMemoryScopeStores } from "./memory-scope-stores.js";
47
48
  import { createMemoryProjectLayers } from "./memory-project-layer.js";
48
49
  import { assertProjectLayerOwnable } from "./project-identity.js";
@@ -50,9 +51,9 @@ import { declaredCredential } from "./model-route-gap.js";
50
51
  import { judgeServedModelRoute } from "./model-route-endpoint.js";
51
52
  import { startMemorySyncRunner } from "./memory-sync-client.js";
52
53
  import { buildPricing, cappedCeiling, createTracer } from "./budget.js";
53
- import { createSharedRunnerDeps } from "./boot/runner-deps.js";
54
+ import { createSharedRunnerDeps, installDefaultEngineNoticeSeat } from "./boot/runner-deps.js";
54
55
  import { createPeerDesk } from "./peer-seat.js";
55
- import { createGovernanceSeams } from "./boot/governance-seams.js";
56
+ import { assertGovernanceAssemblable, createGovernanceSeams } from "./boot/governance-seams.js";
56
57
  import { assertRetentionLaneWirable } from "./boot/retention-lane.js";
57
58
  import { createOrgMemoryAdmissionWiring } from "./boot/org-memory.js";
58
59
  import { assembleDeploymentMods } from "./boot/deployment-mods.js";
@@ -351,6 +352,7 @@ export async function runLocal(argv, deps = {}) {
351
352
  const metrics = createMetrics();
352
353
  const memoryEngineIncident = createMemoryEngineIncidentSink({ logger, metrics });
353
354
  installSecretEnvScrubRecorder({ logger, metrics });
355
+ installDefaultEngineNoticeSeat(logger, metrics);
354
356
  logConfigDiagnostics(logger);
355
357
  provisionSemaConfigDir(config, logger);
356
358
  installOutboundDispatcher(logger);
@@ -362,6 +364,8 @@ export async function runLocal(argv, deps = {}) {
362
364
  printErr(err instanceof Error ? err.message : String(err));
363
365
  return 2;
364
366
  }
367
+ const envModelsMigration = { root, env: process.env, envTableIsPlaceholder: isRosterGateArmed(config.webAdmin) };
368
+ logEnvModelsMigration(logger, envModelsMigration, await runEnvModelsMigration(envModelsMigration));
365
369
  logConfigDirMigration(logger, await migrateLocalConfigDirectory(root));
366
370
  try {
367
371
  await composeExecutionLane(config, { configSource: "local", localRoot: root, logger, drivesFromFile: ["host"] });
@@ -393,7 +397,7 @@ export async function runLocal(argv, deps = {}) {
393
397
  for (const d of r.droppedEntries ?? [])
394
398
  logger.warn("config_entry_dropped", { domain: d.domain, entry: d.entry, reasonCode: d.reasonCode, error: d.error, version: r.effective.version, phase: "boot", note: "this one entry failed its domain schema and was dropped on its own — the rest of the candidate applies (per-entry tolerance); fix the named entry to bring it back" });
395
399
  applying = true;
396
- applyEffective(config, r.effective, logger, { leg: "boot" });
400
+ applyEffective(config, r.effective, logger, { leg: "boot", catalogSource: r.catalogSource });
397
401
  effective = r.effective;
398
402
  candidatePrompts = verdict.prompts;
399
403
  if (effective?.mcp)
@@ -487,7 +491,7 @@ export async function runLocal(argv, deps = {}) {
487
491
  const engineDataRoot = fileMemoryEngineRoot(config, root);
488
492
  const fileEngine = memoryEngineBackendFor(config, root, memoryEngineIncident);
489
493
  const memoryEngine = fileEngine !== undefined
490
- ? createMemoryScopeStores({ backend: fileEngine.backend, root: engineDataRoot, namedLayers: () => memoryLayersNamedBy({ ...config, memoryScope: args.user ?? "local" }), onIncident: memoryEngineIncident })
494
+ ? createMemoryScopeStores({ backend: fileEngine.backend, root: engineDataRoot, onIncident: memoryEngineIncident })
491
495
  : undefined;
492
496
  try {
493
497
  judgeConsolidationValve({ config, memoryEngine });
@@ -582,6 +586,7 @@ export async function runLocal(argv, deps = {}) {
582
586
  ],
583
587
  retentionExecutor: null,
584
588
  });
589
+ assertGovernanceAssemblable(config);
585
590
  const { registrations: deploymentMods } = await assembleDeploymentMods({ metrics, brandIdentity: true, declaration: config.modsDeclaration, logger });
586
591
  const sharedRunnerDeps = createSharedRunnerDeps({
587
592
  metrics,
package/dist/runs.d.ts CHANGED
@@ -4,6 +4,7 @@ import { type EntryProblem } from "./entry-problems.js";
4
4
  import type { SendUserFileEmitter } from "./capabilities/send-user-file-tool.js";
5
5
  import type { RunStore } from "./plugins/store-backend.js";
6
6
  import type { Metrics } from "./observability/metrics.js";
7
+ import type { RunSkillEntry } from "./capabilities/skills.js";
7
8
  import { type RunAbort } from "./run-cancel-context.js";
8
9
  import type { ModelUsageTracker, PromptManifestTracker } from "./budget.js";
9
10
  import type { ElicitationCoordinator } from "./elicitation.js";
@@ -39,16 +40,15 @@ import type { UserInputLedger } from "./user-input-ledger.js";
39
40
  * first-marker-wins guards live inside the seam.
40
41
  */
41
42
  /** [ref]③(b) + codex R2: the bg agent-handle OUTPUT read, kind-gated BEFORE any poll. `pollTask` is the
42
- * generic registry face and polling is NOT side-effect-free for other kinds — a terminal workflow poll
43
- * fires `onServedTerminal` (acknowledges the completion as served → suppresses its notification) and a
44
- * bash poll advances the output cursor. `getAccessibleTask` is a pure lookup: resolve + access-check +
43
+ * generic registry face and polling is NOT side-effect-free for other kinds — a bash poll advances the
44
+ * output cursor (and a workflow's read face is its journal, not this one). `getAccessibleTask` is a pure lookup: resolve + access-check +
45
45
  * type-check FIRST; only a `background_agent` row is ever polled (non-blocking). Everything else returns
46
46
  * the registry's own not_found shape, indistinguishable from an unknown handle (the route 404s it).
47
47
  *
48
48
  * 1.250 durable arm (core 1.364, [ref] follow-up delivered): a FULL in-process miss (`!row`) falls
49
49
  * through to `pollTask(…, { agentStore })` — core's durable arm only fires for `a*`-shaped handles
50
50
  * (DURABLE_AGENT_HANDLE_RE) behind `canAccessAgentRecord`, and with NO in-process handle the live
51
- * workflow/bash branches are unreachable, so the kind-gate's reason (onServedTerminal / cursor advance)
51
+ * workflow/bash branches are unreachable, so the kind-gate's reason (cursor advance / the journal owning workflow reads)
52
52
  * cannot trigger. Terminal rows serve the durable snapshot cross-instance/post-restart; a foreign-writer
53
53
  * running row answers the honest "outcome unknown here"; anything else is core's own not_found (byte-same
54
54
  * route 404 as today). A row that IS in-process but of the wrong type stays a hard 404 — the process
@@ -372,9 +372,8 @@ approval?: {
372
372
  executionLane: import("./execution-lane-caps.js").ExecutionLane;
373
373
  },
374
374
  /** 本腿结算用的 checkpoint 店(`deps.checkpointStore`),两件事:①[ref] park 投影腿的读口 —— 在场时 durable park 的
375
- * `suspended` 事件带 `toolCallId`(graft 见 {@link parkToolCallId});②验证门结算时作废验证器自己的停驻卡
376
- * ({@link voidVerifierPauseCard}:本服务兑现不了的卡不留在待决面上);③停驻没落定就以失败收场时作废手里那张卡({@link voidHeldParkCard})。
377
- * 缺席 ⇒ ①旧字节逐字不变;②③带凭据的停驻响亮留痕、卡由兜底收割。 */
375
+ * `suspended` 事件带 `toolCallId`(graft 见 {@link parkToolCallId});②停驻没落定就以失败收场时作废手里那张卡({@link voidHeldParkCard})。
376
+ * 缺席 ⇒ ①旧字节逐字不变;②带凭据的停驻响亮留痕、卡由兜底收割。(验证器自己的停驻卡不经本店:结算时交本腿的 Runner 动词,见 {@link voidVerifierPauseCard}。) */
378
377
  checkpointCards?: ParkCheckpointReader & CardVoidPort,
379
378
  /** [ref]:装配期(`prepareSpec` → `resolveSpec`)铸下的用户面通告 —— 那一刻本腿的通告口还没开,
380
379
  * 所以由本腿在 `registerEngineNoticeLeg` 那一拍连同 `pending` 一起投(投递单点仍是 `route()`)。
@@ -412,7 +411,12 @@ acceptance?: RunAcceptance,
412
411
  * 会话行的位置与项目那一格的记录座(`session-workspace.ts`;唯一写者):普通流形逐帧喂(这条腿自己的 `workspace_changed` 排一次写),
413
412
  * `done` 时等写落定再落终局。只回结果的 verify / cascade 形宿主手里没有流 ⇒ 不记。缺席 ⇒ 不记行(与本参数存在之前逐字相同)。
414
413
  */
415
- workspaceRecorder?: SessionWorkspaceRecorder): Promise<void>;
414
+ workspaceRecorder?: SessionWorkspaceRecorder,
415
+ /**
416
+ * 这条 run 交给引擎的技能名册(`wiring_manifest.skills` 段;部署事实 `LegFacts.skills`,`leg-facts.ts`:受理漏斗在复制之前读出)。
417
+ * 缺席 = 嵌入方自带的装配器没铸 ⇒ 账本行不带技能段。
418
+ */
419
+ runSkills?: readonly RunSkillEntry[]): Promise<void>;
416
420
  /** How often a running instance refreshes its run's updated_at (liveness, independent of events).
417
421
  * Must stay strictly below `runStaleSec` (asserted at startup AND on every hot config candidate) or the
418
422
  * reaper would race live runs. [ref]:数值的单源是 `config-invariants.ts`(那条不变量的属主),两个消费面
package/dist/runs.js CHANGED
@@ -9,7 +9,6 @@ import { isSessionErrorCode, sessionErrorHttp } from "./session-error-wire.js";
9
9
  import { redactErrorMessage } from "./observability/run-terminal.js";
10
10
  import { withPrincipal } from "./observability/principal-context.js";
11
11
  import { withModelReachScope } from "./model-reach-scope.js";
12
- import { runSkillsOf } from "./capabilities/skills.js";
13
12
  import { createInstructionSelectionLeg } from "./instruction-selection.js";
14
13
  import { redactSecrets } from "./trace/redact.js";
15
14
  import { taskNotificationEventData, appendModelUsageDelta, appendPromptManifest, attachModelUsage } from "./trace/project.js";
@@ -18,7 +17,7 @@ import { registerEngineNoticeLeg } from "./trace/engine-notice-wire.js";
18
17
  import { recordTurnActivity } from "./turn-activity.js";
19
18
  import { buildCancelledLedgerRow, CANCELLED_CODE, createRunAbort, mintCancelledResult } from "./run-cancel-context.js";
20
19
  import { createApprovalCardEmitter, resolveApprovalLeg } from "./tool-approval.js";
21
- import { fleetRunResiduals, isFleetAgentTerminalNotification } from "./fleet/fleet-bus.js";
20
+ import { fleetRunResiduals } from "./fleet/fleet-bus.js";
22
21
  import { defaultSubagentTailBus } from "./fleet/subagent-tail-bus.js";
23
22
  import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationStreamKeyOf, NotifiedKeys } from "./orchestration/workflow-completion-inbox.js";
24
23
  import { isParkLedgerEventType } from "./trace/ledger-events.js";
@@ -70,6 +69,9 @@ export function markChildrenStoppedByUserOnAbort(signal, taskId, principal) {
70
69
  }
71
70
  signal.addEventListener("abort", mark, { once: true });
72
71
  }
72
+ const EXECUTION_ENV_REFUSAL_HTTP_STATUS = {
73
+ "env.home_unconfirmed": 409,
74
+ };
73
75
  const PREPARE_REFUSAL_HTTP_STATUS = {
74
76
  "resume.session_not_found": 404,
75
77
  "rewind_snapshot.unresolvable": 422,
@@ -93,6 +95,8 @@ const PREPARE_REFUSAL_HTTP_STATUS = {
93
95
  "config.memory_project_marker": 409,
94
96
  "config.memory_project_marker_nested": 409,
95
97
  "config.read_deny_floor_unkept": 409,
98
+ "config.mcp_server_name_collision": 409,
99
+ ...EXECUTION_ENV_REFUSAL_HTTP_STATUS,
96
100
  };
97
101
  export function resumeAtHttpStatus(result) {
98
102
  const code = failureCodeOf(result.terminal);
@@ -277,7 +281,7 @@ export async function voidHeldParkCard(held, hostSessionId, cards, leg) {
277
281
  return;
278
282
  await voidPendingCard({ token: held.terminal.token, sessionId: hostSessionId }, cards, "server.park.held-card-void-failed", `leg=${leg}`);
279
283
  }
280
- export async function runInBackground(runner, spec, runStore, taskId, metrics, principal, verify, cascade, instrumentDegenerate, planCacheProbe, persistThinking = false, inflight, preemptable, steerable, modelUsage, elicitation, elicitOwner, captureTurnAnchor, fleetPublisher, captureUserMessageAnchor, question, workflowCompletionInbox, subagentSteer, completionDiagLog, sendUserFile, promptManifests, approval, checkpointCards, pendingEngineNotices, trustedInternals, userInputLedger, acceptance, workspaceRecorder) {
284
+ export async function runInBackground(runner, spec, runStore, taskId, metrics, principal, verify, cascade, instrumentDegenerate, planCacheProbe, persistThinking = false, inflight, preemptable, steerable, modelUsage, elicitation, elicitOwner, captureTurnAnchor, fleetPublisher, captureUserMessageAnchor, question, workflowCompletionInbox, subagentSteer, completionDiagLog, sendUserFile, promptManifests, approval, checkpointCards, pendingEngineNotices, trustedInternals, userInputLedger, acceptance, workspaceRecorder, runSkills) {
281
285
  const startedAt = Date.now();
282
286
  metrics?.addGauge("runs_active", 1);
283
287
  fleetPublisher?.onStart();
@@ -375,7 +379,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
375
379
  acceptance?.settle(safe);
376
380
  };
377
381
  const instructionLeg = createInstructionSelectionLeg();
378
- const sink = createLedgerSink({ appendEvent: (seq, type, data) => runStore.appendEvent(taskId, seq, type, data), persistThinking, notifiedKeys, onActivity: (kind, statusData) => recordTurnActivity(taskId, kind, statusData), legSections: () => ({ instructions: instructionLeg.segment(), skills: runSkillsOf(spec) }), usage: { modelUsage, taskId } });
382
+ const sink = createLedgerSink({ appendEvent: (seq, type, data) => runStore.appendEvent(taskId, seq, type, data), persistThinking, notifiedKeys, onActivity: (kind, statusData) => recordTurnActivity(taskId, kind, statusData), legSections: () => ({ instructions: instructionLeg.segment(), skills: runSkills }), usage: { modelUsage, taskId } });
379
383
  const append = (type, data) => sink.append(type, data);
380
384
  const flush = () => sink.flush();
381
385
  const flushModelUsage = () => appendModelUsageDelta(append, modelUsage, taskId);
@@ -430,9 +434,8 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
430
434
  if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
431
435
  defaultSubagentTailBus.publish(n.task_id, { type: "task_settled", taskId: n.task_id, status: n.status, ...(typeof n.seq === "number" ? { seq: n.seq } : {}), ...(n.summary ? { summary: redactSecrets(n.summary) } : {}) });
432
436
  }
433
- const hadRow = isFleetAgentTerminalNotification(n) ? (fleetPublisher?.onChildTerminal(n.sessionId ?? n.task_id, n.status, n.task_id, n.toolUseId) ?? false) : false;
434
437
  const parked = !legLive && Boolean(workflowCompletionInbox && spec.sessionId);
435
- completionDiagLog?.("task_notification_observed", { route: "bg-run-start", taskId: n.task_id, taskType: n.task_type, status: n.status, hadFleetRow: hadRow, legLive, parkedDurable: parked });
438
+ completionDiagLog?.("task_notification_observed", { route: "bg-run-start", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive, parkedDurable: parked });
436
439
  if (parked) {
437
440
  void workflowCompletionInbox.enqueue(taskNotificationInboxEntry(spec.sessionId, elicitOwner ?? owner, n, Date.now(), taskId, opts?.priority)).catch((err) => completionDiagLog?.("park_enqueue_failed", { route: "bg-run-start", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
438
441
  }
@@ -467,7 +470,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
467
470
  const result = await compositeLeg();
468
471
  observedDone = result;
469
472
  causeAtDone = cancelCtrl.cause();
470
- await voidVerifierPauseCard(result, checkpointCards);
473
+ await voidVerifierPauseCard(result, runner);
471
474
  await flush();
472
475
  await flushPromptManifest();
473
476
  await settleLegResult(result);
@@ -230,7 +230,7 @@ export interface GovernancePosture {
230
230
  * (checkpoint → ask)今天**没有读口**:两条 list 读口都硬过滤 `state='STREAM_PENDING'`,而 park 完的行是
231
231
  * `PARKED`;唯一精确的连接键是 ask 行上的 `gate_token`,要按它反查得给店加一个新读口(SQL 面 = 双库集成
232
232
  * 门)。派生 `deriveAskId(...)` 也不行:它吃 `legKey`(= 上一腿 resume token 的摘要)、`parentToolCallId` 与这一问的
233
- * 类集([ref]);前两维从 checkpoint 行推不出来,类集在 park 行上老行缺席、续跑不补 —— 二腿/子代/老行形上会算出一个
233
+ * 类集([ref])与展示的动作(工具名 + 入参摘要,7.143.0);前两维从 checkpoint 行推不出来,类集在 park 行上老行缺席、续跑不补 —— 二腿/子代/老行形上会算出一个
234
234
  * **错**的 id —— 在「等的谁」这条通道上,错 id 比缺席坏得多(`http/active-run-conflict.ts` 的 `resumeEntryForGate` 的 default 臂是同一条纪律)。故诚实缺席。
235
235
  */
236
236
  export declare function governanceOriginOf(gate: {
@@ -8,7 +8,6 @@ import type { ClientSessionRowWrite, ReplaySessionRowWrite, ReplaySessionRowWrit
8
8
  import type { ExecutionPlacementSeat } from "./execution-placement.js";
9
9
  import type { SessionUnreadable } from "./session-error-wire.js";
10
10
  import type { ForkTarget, ForkToOutcome } from "./plugins/session-fork.js";
11
- import { type OwnerlessClaim } from "./delegated-session-owner.js";
12
11
  /** One row of the session-list projection (CC /resume picker) — the durable session abstraction's enumeration
13
12
  * output (§0.5). Mirrors {@link RunStore}'s shipped `SessionSummary` shape so the wire response is unchanged. */
14
13
  export interface SessionListItem {
@@ -183,9 +182,6 @@ export declare function legacyUnownedAmnestyOpen(deployment: DeploymentShapeInpu
183
182
  export type OwnerAwareSessionStore = SessionStore & {
184
183
  /** 属主登记(core `SessionStore.register` 的契约:对没有行的 id 建行并记下属主,首写赢;对已有的行什么都不做)。读回走 `headOf`。 */
185
184
  register?: (sessionId: string, owner: string | null) => Promise<void>;
186
- /** [ref] 委派继承律的**认领口** —— 只在记录委派树的店上(三只持久会话店,只命中 placed 行;不记委派树的店没有):判断时读到的那一位住客仍是无主的 placed 行 ⇒ 写 `owner`,
187
- * 返回是否写成(只 CAS 子行自己)。唯一调用方 = 停驻挂点的 `settleDelegatedOwner`(`delegated-session-owner.ts`;M23 走同一句 SQL);规则写在那个模块。 */
188
- claimOwnerless?: OwnerlessClaim;
189
185
  /** [ref] placed 分区的元组读口(店的既有读口,一行 PK 读;`undefined` = 普通会话或无此行)。店不交它 = 不实现 placement = 没有 placed 行(无 repo 的内存店)。两个读者:
190
186
  * ① 会话面的属主门只在属主为 NULL 时读它一次(无主的 placed 行不是公共行,`http/principal-gate.ts` 的 `sessionOwnerCellOf`);
191
187
  * ② 会话视图读它投影体顶层 `agent` 键(`audit.ts` 的 `sessionAgentOf`,只在视图读上付):店没有这一面 ⇒ 键缺席,读面不凭别处另铸子代身份。 */
@@ -76,6 +76,10 @@ export declare function serverCredentialValueSources(modelApiKeyEnv?: ModelApiKe
76
76
  * `holdOwnCredentialValues` 同一姿势:不收 + 说一次),经留痕座结构化点名那个变量一次 —— `warn` 行 `own_credential_value_not_withheld { name, reason }`
77
77
  * ({@link recordOwnCredentialValueNotWithheld};`reason` 是引擎拒句原文,从不回显值;起服第一步还没有 logger 时当拍经进程默认的 JSON 行日志器写 stderr,不缓冲),能力位 `inherit_env.own_credential_values_withheld`
78
78
  * 因此答 false(位真 ⇔ 值臂真扣)。引擎拒一个值时声明保持上一份,所以逐个交表的中间态都是上一份的超集。
79
+ * 🔴 **这一行是本服务唯一的写者**:值是网关密钥(`MODEL_API_KEY` / `ANTHROPIC_API_KEY`)时,进程输出里另有一行**引擎**的裸 `console.warn`(`a credential the engine was handed is …`)——
80
+ * 它写在 `createOpenAIBrain` / `createAnthropicBrain` 的收值口,那个口没有通告席(适配器配置没有 `onNotice`;`holdOwnCredentialValues` 不在 core 根导出),core 把这一形记为已知限制。
81
+ * 本仓不在引擎外面吞 console、也不拿声明口去抢引擎的「每进程每值说一次」账(下游不改上游座的语义);等 core 给席或让声明口的拒收记作已说。读数与翻面条件:
82
+ * `test/own-credential-value-boot-lines.test.ts`(真主进程;零裸行的期望以 `it.fails` 立着,core 改形那天转红再翻成常规钉)。
79
83
  * 返回声明的名单(只名、不值)。
80
84
  */
81
85
  export declare function declareServerWithheldEnv(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
@@ -9,30 +9,25 @@
9
9
  * owner 已知时同步口是 200 + failed 体、并照常走计费收尾)。
10
10
  *
11
11
  * ## 为什么多一个 `face` 参数(而不是单参)
12
- * core 的 `invalid_session` 是**同词两义**(亲读 dist:`engine/session/import-validate.js` 的导入门拒调用方交来的
13
- * 日志,`engine/session/storage-base.js` / `parent-chain-guard.js` 的建树 / 走根拒**已存**日志的结构 —— 叶子或父不在日志里、
14
- * 条目是自己的祖先〔自指 / 成环〕)。前者是调用方的日志没过校验(import 面 422),后者是这只会话**存着的**日志坏了(open 面 500,
15
- * 调用方没做错任何事)。单参签名装不下这件事:要么打开面的每个消费点都写一句 `code === "invalid_session"` 特判,要么把已存日志坏了
16
- * 说成「你交的日志坏了」。⇒ 面是映射的一维,写进属主,不散在消费点。
12
+ * 三个 core 词只在一面上有自己的答复:`invalid_session`(导入门拒调用方交来的日志,亲读 dist:`engine/session/import-validate.js` 与
13
+ * `core/session-log-transfer.js` 的暂存腿)、`placement_refused`、`conflict`(各自在 import 面只有一个来源,见逐词)—— 在 open 面上它们要么从不出现,
14
+ * 要么是 run 的终局码(引擎词汇,原样随 failed 体走)。单参签名装不下「一面有答复、另一面留白」:要么每个消费点写一句按码特判,要么把 import 面的
15
+ * 答复漏到 open 面(把「存着的会话坏了」说成「你交的日志坏了」)。⇒ 面是映射的一维,写进属主,不散在消费点。
17
16
  * · `"open"` —— 为某只会话**打开它已存的日志**(提交各腿的引擎 prepare、鉴权门的归属探针、直接读会话的口);
18
17
  * · `"import"` —— 校验 / 写入**调用方交来的**日志(2c session-sync 的暂存导入)。
19
18
  *
20
19
  * ## 逐词(`undefined` = 登记过的留白:这个词在这一面上没有自己的 wire 答复,站点的既有处置照旧)
21
- * · `corrupt_session` —— 两面同答 **500 `corrupt_session`**。这只会话的存档读不出、唤不醒。不是 4xx:调用方没做错
20
+ * · `corrupt_session` —— 两面同答 **500 `corrupt_session`**。这只会话的存档读不出、唤不醒;core 7.62.0([ref])起也含「读得出、走不成一棵树」那一形
21
+ * (悬空父而回放没丢记录 / 自指 / 成环 / 叶子缺席 / 分叉走链 —— 7.137.0–7.143.0 那一形是 `invalid_session`,见下一词)。不是 4xx:调用方没做错
22
22
  * 任何事;不是 503:重试改不了判(修复在运维手里)—— 与会话规则店的 `corrupt` 同一档同一理由。码不另铸(core 的词
23
23
  * 原样上 wire,契约既有立场:不为上游码铸孪生码)。三种会话后端同词:文件店由 core 铸,两只 SQL 店由
24
24
  * `plugins/session-event-payload.ts` 铸(坏的 `session_event.payload` 行)。
25
- * · `invalid_session` —— `import` 面 **422 `invalid_entries`**(修前 session-sync 的那一行,码位 / 状态逐字不变);
26
- * `open` 面 **500 `invalid_session`**:这只会话已存的日志结构坏了(悬空父 / 自指 / 成环 / 叶子缺席),打得开存档、走不通分支。
27
- * 句子发 core 的原句(点名条目 id,不含盘上路径),过既有脱敏。
28
- * · **为什么是 500、不是 4xx / 503**:坏的是存着的数据,调用方没做错任何事;重试改不了判(修复在运维手里)—— 与 `corrupt_session` 同一档同一理由。
29
- * · **为什么码是 `invalid_session`、不是 `corrupt_session`**:码不另铸、也不把一个 core 词改名成另一个 core 词。两个词说的是两件事
30
- * (`corrupt_session` = 存档读不出;`invalid_session` = 读得出、结构走不通),而 run 终局上它本来就是引擎词(`terminal.code`,同步口 4xx / 5xx 体的
31
- * `errorCode` 取终局码原样):读口答 `corrupt_session`、提交口答 `invalid_session` 就是同一件事两个名字。所以映射只有一格,
32
- * 读口与提交口的 run 终局分诊({@link sessionErrorHttp} 的 open 面,`resumeAtHttpStatus` 读它)同一只、同码同状态。
33
- * · **没有 `reason` 机读位**:core 的 `SessionError` 只带 `code` 与句子;悬空父与叶子缺席是同一句 `Entry <id> not found`,自指与成环是同一句
34
- * `is its own ancestor` —— 本仓分出 {parent_missing, parent_self, parent_cycle} 只有解析句子或再写一只判官两条路(会话视图自己的走链器已在 core 7.54.0 提货时退役:
35
- * 视图读的就是引擎读的那条分支,见 `plugins/local-session-window.ts` 头注)。要分,请求 core 把种类放进错误(同 `placement_kind` 的先例),不在这里猜。
25
+ * · `invalid_session` —— `import` 面 **422 `invalid_entries`**(修前 session-sync 的那一行,码位 / 状态逐字不变);`open` 面**留白**:core 7.62.0
26
+ * ([ref] / [ref])起它只是导入门的词,打开已存日志从不抛它 —— 走不成一棵树的已存日志是 `corrupt_session`(上一词);回放丢了记录的悬空父不再失败,
27
+ * run 从断点续上并在流上说 `session.lineage_rerooted`。7.137.0–7.143.0 本表在 open 面给过它一格 500 `invalid_session`(那时 core 用它说已存日志的结构坏),
28
+ * 随 core 改判退役(一个词一个意思,[ref];零双读:open 面不再认它,真来了也是通用 500,不替它猜成 `corrupt_session`)。
29
+ * · **没有 `reason` 机读位**(两种结构坏同一个 `corrupt_session`):core 的 `SessionError` 只带 `code` 与句子 —— 要分成因,请求 core 把种类放进错误
30
+ * (同 `placement_kind` 的先例),不在这里解析句子。
36
31
  * · `not_found` —— 留白:每一面各有自己的「不存在」答法(404 `not_found.session` / 同步口的 `resume.session_not_found` /
37
32
  * 列表里的缺席),码位各不相同,不由本表统一。
38
33
  * · `placement_refused` —— `import` 面 **409 `conflict.session_placed`**(机读位 `detail.placement_kind`,固定句);`open` 面留白。
@@ -40,7 +35,7 @@
40
35
  * (三只持久会话店的整段换装 / 暂存提交门:目标 id 的 `placement_kind` 在场 ⇒ 不适用),调用方没做错格式、是**目标**不收这种写;
41
36
  * open 面上同一个词还含「声明了分区的创建撞上了分区外 / 异组的行」两形(core `TtlSessionStore.assertPlacementAdmission` 的后两条),
42
37
  * 那不是「目标是分区会话」。而 run 终局上它是引擎词汇(`terminal.code`),原样随 failed 体走 —— 若在这里分诊成 409,
43
- * 体上的 `errorCode` 仍是引擎词 `placement_refused`,一个状态两个名字。所以 open 面留白,`invalid_session` 是同形先例。
38
+ * 体上的 `errorCode` 仍是引擎词 `placement_refused`,一个状态两个名字。所以 open 面留白。
44
39
  * 409 的语义:目标会话**状态**不收这种写(重试同一个 id 同一结果;换一个会话 id 推)—— 与 `conflict.session_ownerless` / `conflict.session_children_alive` 同族。
45
40
  * `detail.placement_kind` 是**常量**,不是从错误里读的:core 的 `SessionError` 只带 `code` 与句子,不带种类;今天分区种类闭集只有
46
41
  * `"subagent"` 一个词,所以常量就是事实。core 给 `SessionPlacementRecord["kind"]` 加第二个词 ⇒ 下面的守卫编译红,由人裁定种类从哪儿读
@@ -50,9 +45,12 @@
50
45
  * · `conflict` —— `import` 面 **409 `conflict`**(固定句 {@link STAGED_IMPORT_OWNER_CHANGED_SENTENCE});`open` 面留白。按码映射时 import 面上这个词只有一个来源:
51
46
  * 暂存提交的属主 CAS(`session-sync-kernel.ts` 的 `StagedCommitOwnerChangedError`,三家店在提交事务里比「此刻的属主格 = 这次导入的门判过的那一格」,
52
47
  * 不等 ⇒ 回滚)—— 码位与同族的提交期同步冲突(`SyncConflictError` ⇒ 409 `conflict`「sync conflict」)同一个,出路也相同:从第一阶段重来(重新过门)。
53
- * 本服务自铸的同码具名拒 {@link StampedSessionArchiveError}(local 店:存档仍带更早版本写下的属主戳)不按码映射 —— 出路不同(重来照样撞),
54
- * 由 {@link sessionErrorWireOf} 按**型**先认:两面同答 409 `conflict` + 固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}。
48
+ * 本服务自铸的同码具名拒 {@link StampedSessionArchiveError}(local 店:存档仍带更早版本写下的属主戳)不按码映射 —— 出路不同(重来照样撞),它有**自己的 wire 码**:
49
+ * 由 {@link sessionErrorWireOf} 按**型**先认:两面同答 409 `conflict.session_archive_stamped` + 固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}(与上一句的属主变更拒同状态、不同码:
50
+ * 两件事的出路相反 —— 属主变更从第一阶段重来,带戳存档删掉会话再推 —— 机读方按码分支,不读句子)。
55
51
  * open 面上它是 run 的写撞上真并发写,落成那条 run 的 `failed` 终局(`terminal.code: "conflict"`),提交腿不另作处置。
52
+ * 带戳存档的具名拒在提交里排在一切同步冲突判之前(`local-session-store.ts` 的 `assertArchiveAnonymousHeld`):改日志的推送的每一形(干净追加 / 载荷分叉 / fork / stale,带同意与否)都答它的这一句 ——
53
+ * 带戳存档的日志换不了,同步冲突的出路(带同意重来)无从谈起。
56
54
  * · `storage` / `unknown` —— 留白:故障类,通用 500 就是它们今天的应答。
57
55
  *
58
56
  * core 给闭集加一个词 ⇒ 下面的 `switch` 编译红,由人裁定它在两面上的答复,而不是让它静默落进某个恰好存在的臂
@@ -95,14 +93,27 @@ export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated a
95
93
  export declare const STAGED_IMPORT_OWNER_CHANGED_SENTENCE = "session owner changed while the import streamed; nothing was imported \u2014 start the sync again";
96
94
  /**
97
95
  * local 店的具名拒(唯一铸点 `plugins/local-session-store.ts`):这只会话的引擎存档仍带更早版本写下的属主戳(一次性迁移 M33 改写不了它,或数据根跳过了带这次迁移的版本)
98
- * ⇒ 不在它上面造新存档(fork),也不原地换它的日志(改日志的推送);零写。码是 core 闭集的 `conflict`(码不另铸);句子(给运维日志,点名会话 id)归本错,
99
- * wire 上发固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}(两面同一句;映射 {@link sessionErrorWireOf})。
96
+ * ⇒ 不在它上面造新存档(fork),也不原地换它的日志(改日志的推送);零写。`SessionError.code` 是 core 闭集的 `conflict`;句子(给运维日志,点名会话 id)归本错,
97
+ * wire 上发自己的码 `conflict.session_archive_stamped` + 固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}(两面同一码同一句;映射 {@link sessionErrorWireOf}):
98
+ * 同一个 core 词 `conflict` 在 import 面上还有属主变更那一件事(出路相反),机读方要能按码把两件事分开。
100
99
  */
101
100
  export declare class StampedSessionArchiveError extends SessionError {
102
101
  readonly sessionId: string;
103
102
  constructor(sessionId: string);
104
103
  }
105
- /** {@link StampedSessionArchiveError} 的 wire 固定句(fork 与改日志的推送同一句;不点名会话 id;出路在句里 —— 从头再同步照样撞)。 */
104
+ /**
105
+ * local 店的具名拒(唯一铸点 `plugins/local-session-store.ts` 的 `metaRead`):这只会话的**属主读不出**。会话的行事实(属主 / 化身)只住在会话元数据边档的那一格;
106
+ * 7.104.0 之前写下、此后从没被读过的会话没有这一格,要从存档补铸它(第一次读时的惯例),存档又用不了(会话头坏 / 截断 / 日志结构走不通)——
107
+ * 于是没有任何一位调用方能被判成它的属主。要读它的行事实的店方法(`headOf` / 执行席的读 / 会话元数据读口)抛本错。
108
+ *
109
+ * 码与句子**就是**那只存档故障的(`cause` = 它;码不另铸 —— 只会是 `corrupt_session`,读不出而说不出在不在的 I/O 级故障不换型):
110
+ * 不认识本型的站点看到的与此前逐字相同(`sessionErrorHttp` 按码映射,wire 与运维日志不变)。认识本型的站点 —— 会话读面的属主读
111
+ * (`http/owner-access.ts` 的 `foldOwnerUnreadable`)—— 把它读成「没有这一行」:与对非属主、对不存在的会话同一只 404,原故障进运维日志。
112
+ */
113
+ export declare class SessionOwnerUnreadableError extends SessionError {
114
+ constructor(fault: SessionError);
115
+ }
116
+ /** {@link StampedSessionArchiveError} 的 wire 固定句(fork 与改日志的推送〔每一形〕同一句;不点名会话 id;出路在句里 —— 从头再同步照样撞)。 */
106
117
  export declare const STAMPED_SESSION_ARCHIVE_SENTENCE = "this session's stored archive still carries an owner stamp written by an earlier server version, so it cannot be forked or have its log replaced; nothing was written \u2014 delete the session and push it again";
107
118
  /**
108
119
  * 一只 `SessionError` 在一面上的 wire 答复 —— 下发点({@link sendSessionError} 的唯一读法)经这里:本服务自铸的同码具名拒先按型认(它的出路与同码的
@@ -13,13 +13,18 @@ export class StampedSessionArchiveError extends SessionError {
13
13
  this.name = "StampedSessionArchiveError";
14
14
  }
15
15
  }
16
+ export class SessionOwnerUnreadableError extends SessionError {
17
+ constructor(fault) {
18
+ super("corrupt_session", fault.message, fault);
19
+ this.name = "SessionOwnerUnreadableError";
20
+ }
21
+ }
16
22
  export const STAMPED_SESSION_ARCHIVE_SENTENCE = "this session's stored archive still carries an owner stamp written by an earlier server version, so it cannot be forked or have its log replaced; nothing was written — delete the session and push it again";
17
23
  const CORRUPT_SESSION = { status: 500, errorCode: "corrupt_session" };
18
- const STORED_LOG_INVALID = { status: 500, errorCode: "invalid_session" };
19
24
  const INVALID_ENTRIES = { status: 422, errorCode: "invalid_entries", sentence: STAGED_IMPORT_INVALID_SENTENCE };
20
25
  const SESSION_PLACED = { status: 409, errorCode: "conflict.session_placed", sentence: PLACED_SESSION_SENTENCE, detail: { placement_kind: PLACEMENT_KIND } };
21
26
  const STAGED_IMPORT_OWNER_CHANGED = { status: 409, errorCode: "conflict", sentence: STAGED_IMPORT_OWNER_CHANGED_SENTENCE };
22
- const STAMPED_SESSION_ARCHIVE = { status: 409, errorCode: "conflict", sentence: STAMPED_SESSION_ARCHIVE_SENTENCE };
27
+ const STAMPED_SESSION_ARCHIVE = { status: 409, errorCode: "conflict.session_archive_stamped", sentence: STAMPED_SESSION_ARCHIVE_SENTENCE };
23
28
  export function sessionErrorWireOf(e, face) {
24
29
  return e instanceof StampedSessionArchiveError ? STAMPED_SESSION_ARCHIVE : sessionErrorHttp(e.code, face);
25
30
  }
@@ -35,7 +40,7 @@ export function sessionErrorHttp(code, face) {
35
40
  case "corrupt_session":
36
41
  return CORRUPT_SESSION;
37
42
  case "invalid_session":
38
- return face === "import" ? INVALID_ENTRIES : STORED_LOG_INVALID;
43
+ return face === "import" ? INVALID_ENTRIES : undefined;
39
44
  case "placement_refused":
40
45
  return face === "import" ? SESSION_PLACED : undefined;
41
46
  case "conflict":
@@ -11,7 +11,7 @@
11
11
  * 所以化身与属主不是同一条律(读法分三种,见下「两读」)。删除随行消失,同 id 重新登记铸新的。
12
12
  * · **两读(住客的三种问法,各读各的格,不混用)**:
13
13
  * K1 **住客自己的记录**(工作区、记忆、空间分区……按「这一位住客」落的东西)只按化身绑 —— 同一位住客的属主换代(推送重戳 / 认领)不换住客,记录照落;
14
- * K2 **以「这一行的这一代」为条件的写**(执行放置的换绑 / 收回、执行上下文的复核)比属主与化身整对,判官 = core 的行期望判官 `sessionRowMatches`
14
+ * K2 **以「这一行的这一代」为条件的写**(执行放置的换绑 / 收回、执行上下文的复核、会话通知门投递前的复核 —— 条目按属主排空)比属主与化身整对,判官 = core 的行期望判官 `sessionRowMatches`
15
15
  * (`execution-placement.ts` 的 `sameOccupant`,SQL `incarnation = ? AND owner <=> ?` 的对位)—— 读与写之间属主换了一代 ⇒ 不是判过的那一行;
16
16
  * K0 **只问属主的门**(授权门、暂存提交的属主 CAS)只读属主那一格。三种都读会话**行**;local 店的行 = 会话元数据边档那一格(引擎仓里的存档是匿名内容仓,
17
17
  * 存档头上的属主不是行事实 —— `plugins/local-session-store.ts` 头注)。
@@ -91,7 +91,7 @@ export type EmptyIncarnationReading = "refuse" | "absent";
91
91
  export declare function incarnationFromCell(sessionId: string, cell: unknown, empty?: "refuse"): string;
92
92
  export declare function incarnationFromCell(sessionId: string, cell: unknown, empty: "absent"): string | undefined;
93
93
  /** 一行原始列 → {@link SessionFace}(属主 + 一只令牌)的唯一口:化身那一格经 {@link incarnationFromCell} 的 `refuse` 读法(空 ⇒ 响亮拒)。
94
- * 按 id 的读者经 {@link sessionFaceOfHead};批量来源读(委派继承律)与 staged 换装的回读直接从行列经它。 */
94
+ * 按 id 的读者经 {@link sessionFaceOfHead};批量来源读(一次性迁移 M23 窗内的回填扫描)与 staged 换装的回读直接从行列经它。 */
95
95
  export declare function sessionFaceFromRow(sessionId: string, owner: string | null, incarnation: unknown): SessionFace;
96
96
  /**
97
97
  * 头的叶子那一格读不出 —— 会话**内容**读不出时的那只故障(local 店:会话存档读不出,例如存档首行的会话头坏了;行上的属主与住客照样读得出)。
@@ -122,7 +122,7 @@ export declare function sessionFaceOfHead(sessionId: string, head: SessionHead):
122
122
  export declare function sessionFaceOfHead(sessionId: string, head: SessionHead | undefined): SessionFace | undefined;
123
123
  /**
124
124
  * 「这只会话店有没有按 id 读(`headOf`)」—— 全仓**只判这一处**:授权口、各路由的属主门、能力位、起服门、k8s 工作区空间的每 run 读与
125
- * 委派继承律读的都是这一只返回值。缺席 = 店没有实装 `headOf`(读不出属主 / 住客 / 叶子,调用方各按自己的 fail-closed 臂处置)。
125
+ * 一次性迁移 M23(窗内)的回填读的都是这一只返回值。缺席 = 店没有实装 `headOf`(读不出属主 / 住客 / 叶子,调用方各按自己的 fail-closed 臂处置)。
126
126
  */
127
127
  export declare function headReadOf(store: object | undefined): HeadRead | undefined;
128
128
  /** 换装沿用的行格(化身 + fork 键):{@link carriedRowCells} 的答案。`forkKey: null` = 没有可沿用的键(新建行 / 行上本来没有)。 */
@@ -0,0 +1,106 @@
1
+ /**
2
+ * 🔴 **会话通知门 —— 一只会话外的事件进一只会话,只有这一处,两臂**。
3
+ *
4
+ * ## 门
5
+ * · **目标** = 会话 + 调用方判过的那一位住客(那一次头读的属主与化身令牌)+ 那一位无主时条目盖谁。门**不**替调用方判授权(属主门在调用方);门只保证交到的是那一位。
6
+ * · **活**:这只会话在本副本有活流 —— 判据一读:`runStore.getActiveTaskId(会话)` 交回的 run 在本副本的活流登记簿里(`steerableRuns`,属主是 HTTP 服务)
7
+ * ⇒ core `TaskStream.notify(事件, { priority: "next" })`。core 铸 `task_type: "external"`(外来的事件穿不上引擎内部车道的类型),载荷校验 / 消毒 / 围栏全在
8
+ * core;档位**写死** `"next"`(最早边界投递;core 的无参缺省是收官座 `"later"`,不写就静默推迟到 run 收尾)。core 的明确拒(码以 `notify.` 开头)原样交回;
9
+ * 别的抛 = 活流刚收尾的竞态 ⇒ 落空闲臂。
10
+ * · **空闲**:这只会话的完成收件箱(`externalNotificationInboxEntry`,external 键域;脱敏 / 限长在入箱口内)⇒ 下次开流排空成 `task_notification` 帧。
11
+ * 部署没有收件箱 ⇒ 如实交回 `no_inbox`(调用方各自答:HTTP 门 501,引擎完成告警)。
12
+ * · **复核住客**:两臂的投递动作(注入 / 入箱)之前**紧邻**一次头读,与目标的住客比 —— 判官是仓里那一只 `sameOccupant`(`execution-placement.ts`:属主 ∧ 化身,
13
+ * 写口与执行上下文解析器判的也是它):不在 ⇒ `withdrawn: gone`;两样里任一样变了 ⇒ `withdrawn: replaced`。会话店不铸化身(嵌入方自建的店)时两侧都没有令牌,
14
+ * 判官只剩属主那一半:属主没变 ⇒ 投,变了 ⇒ 撤回。这一读是动作之前的最后一次让出:判活读(及活臂刚收尾时的那次注入)都在它前面 ——
15
+ * 令牌永不复用,此刻还是那一位 ⇒ 判活读那一刻也是那一位 ⇒ 判出的 run 是它的 run。
16
+ * · **条目属主** = 目标住客的属主(调用方判过的那一读;复核放行 ⇒ 与这一读的属主逐字相等);那一位无主 ⇒ `ownerlessEntryOwner`(调用方交)。
17
+ *
18
+ * ## 竞态(两个调用方同一句话,只写在这里)
19
+ * · 判活之后、注入之前活流收尾:core 对已收尾的 run 不抛,按会话暂存、本进程同一会话的下一个 run 开轮时投递(core `notify` 契约);抛了 ⇒ 空闲臂(入箱前再复核一次)。
20
+ * · 判空闲之后、入箱之前同一会话开了新流:新腿开流那一拍的排空可能已读过收件箱 ⇒ 这一条在**再下一次**开流排空(至少一次,晚一次开流)。
21
+ * · 跨副本:活流在别的副本 ⇒ 本副本判空闲 ⇒ 入箱(收件箱随 run 店同一后端,哪个副本开流都排得到)。
22
+ * · 复核之后、入箱写落库之前别的副本删了这只会话并同 id 重新登记:条目带的是判过那一位的属主 —— 排空时按属主比开流者,另一位属主排不到;
23
+ * 同一属主重新登记的那一只会排到它(余窗 = 一次入箱写的时长;这一形不再收窄)。
24
+ *
25
+ * ## 调用方(两只,都经 {@link SessionNotifyDoor.deliver},不各写一份臂)
26
+ * · `POST /v1/sessions/:id/notify`(`http/routes/notify-wake.ts`):入站鉴权、验型、属主门在路由;属主 = 会话行的属主。
27
+ * · **Runner 之外的后台子代完成**({@link createBackgroundCompletionRelay}):停驻赎回腿的复活、操作员 `handle.resume` —— 这些续跑不是哪一次 run 内的调用,
28
+ * 没有调用车道(`ToolExecuteContext.onTaskNotification`),引擎把完成交给委派工具挂载期的 `background.notify`;那只 sink 在 `capabilities/scenarios.ts` 接一次,
29
+ * 交到委派树根会话的这只门。Runner 之内的调用照旧走调用车道(引擎 `resolveCompletionSink` = 调用 ?? 挂载),这只门不经手。
30
+ */
31
+ import type { ExternalNotificationInput, SessionHead, SubagentToolOptions, TaskStream } from "@sema-agent/core";
32
+ import { type WorkflowCompletionInbox } from "./orchestration/workflow-completion-inbox.js";
33
+ import type { DelegationRootWitness } from "./delegated-session-owner.js";
34
+ import type { HeadRead } from "./session-incarnation.js";
35
+ import type { Logger } from "./observability/logger.js";
36
+ /** 门的一次投递结局(闭集;调用方 `switch` 穷尽)。 */
37
+ export type SessionNotifyOutcome = {
38
+ readonly delivery: "live";
39
+ } | {
40
+ readonly delivery: "parked";
41
+ }
42
+ /** core 的明确拒(`notify.invalid_payload` 等):码与句原样。 */
43
+ | {
44
+ readonly delivery: "refused";
45
+ readonly code: string;
46
+ readonly message: string;
47
+ }
48
+ /** 会话空闲而部署没有收件箱:这一条无处可放。 */
49
+ | {
50
+ readonly delivery: "no_inbox";
51
+ }
52
+ /** 投递动作之前的复核:会话不在(`gone`)/ 住客不是目标那一位(`replaced`)⇒ 没交。 */
53
+ | {
54
+ readonly delivery: "withdrawn";
55
+ readonly reason: "gone" | "replaced";
56
+ };
57
+ /** 投递目标。 */
58
+ export interface SessionNotifyTarget {
59
+ readonly sessionId: string;
60
+ /** 调用方判过的那一位住客:那一次头读的属主与化身令牌(化身缺席 = 那一读里没有令牌;复核见头注)。它的属主也是收件箱条目的属主(排空时与开流者比对)。 */
61
+ readonly occupant: Pick<SessionHead, "owner" | "incarnation">;
62
+ /** 那一位无主(`occupant.owner === null`)时条目盖的属主(`null` = 无主条目,谁开流都排)。 */
63
+ readonly ownerlessEntryOwner: string | null;
64
+ }
65
+ export interface SessionNotifyDoor {
66
+ deliver(target: SessionNotifyTarget, event: ExternalNotificationInput): Promise<SessionNotifyOutcome>;
67
+ }
68
+ /** 门要读的四样(都由 HTTP 服务交:活流登记簿是它的,run 店、会话店与收件箱是它的依赖)。 */
69
+ export interface SessionNotifyDoorIo {
70
+ /** 会话 → 它的在飞 run(run 店的单活认领读)。部署没有 run 店 ⇒ 交 `undefined` ⇒ 恒判空闲。读失败按空闲(F 类兜底:门留痕 `server.session-notify.active-run-read-failed`)。 */
71
+ readonly activeTaskIdOf: (sessionId: string) => Promise<string | null | undefined>;
72
+ /** 本副本持活 core 流的腿(taskId → 流)。 */
73
+ readonly liveRuns: ReadonlyMap<string, Pick<TaskStream, "notify">>;
74
+ readonly inbox: WorkflowCompletionInbox | undefined;
75
+ /** 会话店的按 id 头读(复核住客的那一读)。店没有 ⇒ `undefined`:调用方先判(路由 501;后台完成 relay 照交,门响亮抛 ⇒ relay 告警)。 */
76
+ readonly headOf: HeadRead | undefined;
77
+ }
78
+ export declare function createSessionNotifyDoor(io: SessionNotifyDoorIo): SessionNotifyDoor;
79
+ /** 委派工具挂载期的完成 sink 的型(取自 core 的选项型,不手抄)。 */
80
+ export type BackgroundCompletionSink = NonNullable<NonNullable<SubagentToolOptions["background"]>["notify"]>;
81
+ /** 把一只委派树根见证变成挂载期 sink 的工厂(`ScenarioDeps.backgroundCompletionSinkFor` 的型)。 */
82
+ export type BackgroundCompletionSinkFor = (root: DelegationRootWitness) => BackgroundCompletionSink;
83
+ export interface BackgroundCompletionRelayIo {
84
+ /** 会话通知门。门的属主是 HTTP 服务、场景层先于它装配 ⇒ 晚绑取值;未绑 ⇒ 交不出去(告警)。 */
85
+ readonly door: () => SessionNotifyDoor | undefined;
86
+ /** 交不出去的那一行告警写到这里(本仓的 `Logger`:写口自己吞掉输出故障、不抛 —— relay 的收尾臂依赖这一条)。 */
87
+ readonly logger: Pick<Logger, "warn">;
88
+ }
89
+ /** 交不出去的成因(闭集;告警 `background_completion_undelivered` 的 `reason`)。 */
90
+ export type BackgroundCompletionUndelivered = "root_gone" | "root_replaced" | "door_unbound" | "refused" | "no_inbox" | "relay_failed";
91
+ /**
92
+ * **Runner 之外的后台子代完成 → 委派树根会话的会话通知门**(挂载期 `background.notify` 的唯一实现)。
93
+ *
94
+ * · **地址** = 场景层交出的委派树根见证(`ScenarioContext.delegationRoot`:会话 id + 判断那一刻的根住客)—— 停驻赎回面按行上的 `rootSessionId`
95
+ * 与赎回腿写口放行的那一位住客交,请求腿按本请求会话与受理时那一读交;不读完成帧上的任何键定址。一层行的根就是父会话;更深的行(孙代)报给根 ——
96
+ * 委派终态的受众是整棵委派树的根会话(孙代的父是一只没人开流的委派会话,交给它等于没交)。
97
+ * · **目标住客 = 见证的那一位**(属主与化身,见证铸点那一读):门在投递动作之前紧邻地复核(头注「复核住客」)—— 不在 ⇒ 不交(`root_gone`);
98
+ * 不是见证的那一位(删了、同 id 被重新登记、属主变了)⇒ 不交(`root_replaced`):这棵树的结果不交给同 id 的下一位住客。条目属主 = 见证的属主;
99
+ * 根无主 ⇒ 无主条目(relay 不是谁的请求,没有请求主体可落)。见证那一读里根行不在(化身 `null`)⇒ 目标住客 = 「无主、无令牌」,只有不铸化身的店上
100
+ * 此刻也无主的根与它同(铸化身的店上它恒不同 ⇒ 不交)。
101
+ * · **事件** = 完成帧的 `task_id` / `status` / `summary` / `result` / `seq`(后台子代的 `seq` = 停驻周期号,同一只子代两次复活的完成在收件箱折叠键上不相撞)。
102
+ * 帧上别的键不过门:门的事件型只有这几位(活臂 core 铸 external,空闲臂入箱同一形),两臂一个形。
103
+ * · 交不出去一律一行 warn(`background_completion_undelivered`,带成因),不抛回引擎(sink 是 fire-and-forget)。
104
+ */
105
+ export declare function createBackgroundCompletionRelay(io: BackgroundCompletionRelayIo): BackgroundCompletionSinkFor;
106
+ //# sourceMappingURL=session-notify-door.d.ts.map