@sema-agent/server 7.52.1 → 7.54.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 (342) hide show
  1. package/USAGE.md +7 -1
  2. package/dist/adoption/plan.d.ts +3 -3
  3. package/dist/adoption/quiesce.d.ts +1 -1
  4. package/dist/adoption/sql.d.ts +2 -2
  5. package/dist/adoption/wire.d.ts +1 -1
  6. package/dist/approval-ask-machine.d.ts +2 -2
  7. package/dist/approval-card.d.ts +18 -18
  8. package/dist/approval-deny-reasons.d.ts +1 -1
  9. package/dist/approval-hmac.d.ts +2 -2
  10. package/dist/approval-reconciler.d.ts +14 -14
  11. package/dist/approval.d.ts +2 -2
  12. package/dist/audit.d.ts +4 -4
  13. package/dist/auth-keys.d.ts +6 -6
  14. package/dist/bench/l8/artifact.d.ts +6 -1
  15. package/dist/bench/l8/artifact.js +2 -27
  16. package/dist/bench/l8/escape.d.ts +3 -3
  17. package/dist/bench/l8/index.d.ts +1 -1
  18. package/dist/bench/s1/arms.d.ts +3 -3
  19. package/dist/bench/s1/oracle.d.ts +2 -2
  20. package/dist/bench/s1/reviewer.d.ts +1 -1
  21. package/dist/bench/s1/row.d.ts +5 -5
  22. package/dist/bench/s1/runner-ctx.d.ts +3 -3
  23. package/dist/boot/config-center.d.ts +14 -7
  24. package/dist/boot/config-center.js +4 -2
  25. package/dist/boot/coordinators.d.ts +4 -4
  26. package/dist/boot/crash-last.d.ts +1 -1
  27. package/dist/boot/device-lane.d.ts +3 -3
  28. package/dist/boot/engine-lease.d.ts +4 -4
  29. package/dist/boot/governance-seams.d.ts +5 -5
  30. package/dist/boot/leader.d.ts +5 -5
  31. package/dist/boot/leader.js +2 -0
  32. package/dist/boot/limit-sync.d.ts +1 -1
  33. package/dist/boot/memory-boundary.d.ts +5 -5
  34. package/dist/boot/memory-consolidation.d.ts +8 -2
  35. package/dist/boot/memory-consolidation.js +1 -0
  36. package/dist/boot/org-memory.d.ts +5 -5
  37. package/dist/boot/parked-revive-gate.d.ts +6 -6
  38. package/dist/boot/permission-rules-audit.d.ts +2 -2
  39. package/dist/boot/reapers.d.ts +8 -8
  40. package/dist/boot/resolve-spec.d.ts +4 -4
  41. package/dist/boot/resolve-spec.js +1 -3
  42. package/dist/boot/retention-lane.d.ts +1 -1
  43. package/dist/boot/runner-deps.d.ts +53 -27
  44. package/dist/boot/runner-deps.js +16 -9
  45. package/dist/boot/runtime-caps.d.ts +4 -4
  46. package/dist/boot/session-faces.d.ts +1 -1
  47. package/dist/boot/shutdown.d.ts +10 -10
  48. package/dist/boot/shutdown.js +1 -1
  49. package/dist/boot/side-query-lane.d.ts +14 -14
  50. package/dist/boot/stores.js +5 -0
  51. package/dist/boot/task-list-lane.d.ts +3 -3
  52. package/dist/boot/webfetch-summarize-lane.d.ts +9 -9
  53. package/dist/boot/workflow-orchestration.d.ts +1 -1
  54. package/dist/bounded-session-map.d.ts +1 -1
  55. package/dist/brain.d.ts +3 -3
  56. package/dist/budget.d.ts +3 -3
  57. package/dist/canonical-json.d.ts +53 -0
  58. package/dist/canonical-json.js +48 -0
  59. package/dist/capabilities/center-prompts.d.ts +13 -13
  60. package/dist/capabilities/collab-workflows.d.ts +1 -1
  61. package/dist/capabilities/hands-lane.d.ts +4 -4
  62. package/dist/capabilities/memory-notice.d.ts +4 -4
  63. package/dist/capabilities/prompt.d.ts +2 -2
  64. package/dist/capabilities/sandbox-file-send.d.ts +2 -2
  65. package/dist/capabilities/scenarios.d.ts +16 -16
  66. package/dist/capabilities/skills.d.ts +1 -1
  67. package/dist/capabilities/team.d.ts +13 -12
  68. package/dist/capabilities/tool-defer.d.ts +6 -6
  69. package/dist/config-catalog.d.ts +139 -0
  70. package/dist/config-catalog.js +556 -0
  71. package/dist/config-center/apply-effective.d.ts +42 -30
  72. package/dist/config-center/apply-effective.js +69 -62
  73. package/dist/config-center/apply-ledger.d.ts +6 -6
  74. package/dist/config-center/effective-keys.d.ts +30 -0
  75. package/dist/config-center/effective-keys.js +49 -0
  76. package/dist/config-center/facade.d.ts +6 -5
  77. package/dist/config-center/facade.js +1 -1
  78. package/dist/config-center/hot-keys-registry.d.ts +2 -2
  79. package/dist/config-center/http-client.d.ts +5 -5
  80. package/dist/config-center/mcp-revocation.d.ts +6 -4
  81. package/dist/config-center/mcp-revocation.js +2 -12
  82. package/dist/config-center/restart-signal.d.ts +11 -1
  83. package/dist/config-center/restart-signal.js +4 -10
  84. package/dist/config-center/skills-mcp.d.ts +2 -2
  85. package/dist/config-center/stage-limits.d.ts +3 -3
  86. package/dist/config-center/types.d.ts +42 -59
  87. package/dist/config-invariants.d.ts +1 -1
  88. package/dist/config-lkg.js +7 -1
  89. package/dist/config-provider.d.ts +2 -2
  90. package/dist/config-provider.js +1 -1
  91. package/dist/config-types.d.ts +140 -132
  92. package/dist/config.d.ts +22 -22
  93. package/dist/config.js +2 -1
  94. package/dist/degenerate-instrument.d.ts +1 -1
  95. package/dist/deployment-governance.d.ts +13 -13
  96. package/dist/device-enrollment.d.ts +5 -3
  97. package/dist/device-store.d.ts +17 -3
  98. package/dist/device-store.js +2 -0
  99. package/dist/device-ws-hub.d.ts +10 -5
  100. package/dist/device-ws-hub.js +25 -5
  101. package/dist/device-ws-protocol.d.ts +3 -3
  102. package/dist/digest-form.d.ts +1 -1
  103. package/dist/elicitation.d.ts +1 -1
  104. package/dist/env-facts.d.ts +7 -7
  105. package/dist/execution-lane-caps.d.ts +5 -5
  106. package/dist/fleet/fleet-bus.d.ts +53 -53
  107. package/dist/fleet/fleet-reconciler.d.ts +2 -2
  108. package/dist/fleet/fleet-terminal-window.d.ts +1 -1
  109. package/dist/fleet/subagent-tail-bus.d.ts +3 -3
  110. package/dist/fleet-client.d.ts +3 -3
  111. package/dist/fleet-lease.d.ts +1 -1
  112. package/dist/hooks/branch-transcript.d.ts +2 -2
  113. package/dist/hooks/cc-agent-hook-prompt.d.ts +2 -2
  114. package/dist/hooks/cc-stop-prompt.d.ts +2 -2
  115. package/dist/hooks/hook-llm.d.ts +1 -1
  116. package/dist/hooks/hook-runner.d.ts +5 -5
  117. package/dist/http/active-run-conflict.d.ts +31 -33
  118. package/dist/http/active-run-conflict.js +4 -2
  119. package/dist/http/route-ctx.d.ts +22 -22
  120. package/dist/http/routes/a2a-serve.d.ts +2 -2
  121. package/dist/http/routes/admin-config-refresh.d.ts +1 -1
  122. package/dist/http/routes/admin-drain.d.ts +4 -4
  123. package/dist/http/routes/admin-memory-optout.d.ts +5 -5
  124. package/dist/http/routes/adoption.d.ts +1 -1
  125. package/dist/http/routes/agents-roster.d.ts +1 -1
  126. package/dist/http/routes/approvals-assistant.d.ts +6 -6
  127. package/dist/http/routes/approvals-assistant.js +4 -1
  128. package/dist/http/routes/capabilities.d.ts +1 -1
  129. package/dist/http/routes/capabilities.js +1 -0
  130. package/dist/http/routes/config-catalog.d.ts +28 -0
  131. package/dist/http/routes/config-catalog.js +42 -0
  132. package/dist/http/routes/diagnostics.d.ts +2 -2
  133. package/dist/http/routes/fleet.d.ts +1 -1
  134. package/dist/http/routes/images.d.ts +1 -1
  135. package/dist/http/routes/leader.d.ts +1 -1
  136. package/dist/http/routes/memory-bundle.d.ts +4 -4
  137. package/dist/http/routes/memory-compliance.d.ts +7 -7
  138. package/dist/http/routes/memory-consolidation.d.ts +1 -1
  139. package/dist/http/routes/memory-origin.d.ts +9 -9
  140. package/dist/http/routes/memory-policy.d.ts +3 -3
  141. package/dist/http/routes/notify-wake.d.ts +1 -1
  142. package/dist/http/routes/observability.d.ts +1 -1
  143. package/dist/http/routes/retention-ops.d.ts +1 -1
  144. package/dist/http/routes/rules.d.ts +3 -3
  145. package/dist/http/routes/run-memory-capture.d.ts +1 -1
  146. package/dist/http/routes/runs.d.ts +3 -3
  147. package/dist/http/routes/runs.js +12 -17
  148. package/dist/http/routes/session-sync.d.ts +2 -2
  149. package/dist/http/routes/sessions-list.d.ts +1 -1
  150. package/dist/http/routes/sessions.d.ts +9 -1
  151. package/dist/http/routes/sessions.js +60 -0
  152. package/dist/http/routes/shared-memory.d.ts +1 -1
  153. package/dist/http/routes/side-query.d.ts +1 -1
  154. package/dist/http/routes/tasks.d.ts +1 -1
  155. package/dist/http/routes/trace-usage.d.ts +1 -1
  156. package/dist/http/routes/workflows.d.ts +1 -1
  157. package/dist/http/run-meta.d.ts +1 -1
  158. package/dist/http/send.d.ts +6 -6
  159. package/dist/http/server.d.ts +84 -67
  160. package/dist/http/server.js +39 -10
  161. package/dist/http/sse-lifecycle.d.ts +1 -1
  162. package/dist/http/sse-log.d.ts +6 -6
  163. package/dist/http/verify-rounds.d.ts +3 -3
  164. package/dist/http/wire-gate.d.ts +2 -2
  165. package/dist/http/wire-types.d.ts +57 -38
  166. package/dist/key-resolver.d.ts +1 -1
  167. package/dist/leader/diffout.d.ts +2 -2
  168. package/dist/leader/diffup.d.ts +1 -1
  169. package/dist/leader/endpoint.d.ts +1 -1
  170. package/dist/leader/fanout.d.ts +6 -6
  171. package/dist/leader/grader-env-factory.d.ts +1 -1
  172. package/dist/leader/leader.d.ts +12 -12
  173. package/dist/leader/merge.d.ts +3 -3
  174. package/dist/leader/planner.d.ts +5 -5
  175. package/dist/leader/repair-oracle.d.ts +1 -1
  176. package/dist/leader/wire.d.ts +21 -9
  177. package/dist/leader/wire.js +6 -5
  178. package/dist/lsp/manager.d.ts +2 -2
  179. package/dist/lsp/types.d.ts +1 -1
  180. package/dist/lsp/ws-transport.d.ts +2 -2
  181. package/dist/main.js +12 -2
  182. package/dist/mcp-content-origin.d.ts +1 -1
  183. package/dist/memory-bundle-engine.d.ts +5 -3
  184. package/dist/memory-bundle-engine.js +2 -2
  185. package/dist/memory-operator-faces.d.ts +41 -11
  186. package/dist/memory-operator-faces.js +12 -0
  187. package/dist/memory-origin-fence.d.ts +1 -1
  188. package/dist/memory-origin-fence.js +2 -13
  189. package/dist/memory-posture.d.ts +6 -6
  190. package/dist/memory-scope.d.ts +7 -7
  191. package/dist/model-select.d.ts +5 -5
  192. package/dist/observability/cost-quota.d.ts +6 -6
  193. package/dist/observability/cost-taxonomy.d.ts +2 -2
  194. package/dist/observability/fail-open.d.ts +17 -5
  195. package/dist/observability/fail-open.js +16 -4
  196. package/dist/observability/metrics.d.ts +1 -1
  197. package/dist/observability/prompt-manifest.d.ts +8 -8
  198. package/dist/observability/rate-limit.d.ts +2 -2
  199. package/dist/observability/secret-env-scrub.d.ts +1 -1
  200. package/dist/observability/tool-trace.d.ts +1 -1
  201. package/dist/orchestration/hardened-vm-runner.d.ts +6 -6
  202. package/dist/orchestration/hardened-vm-worker-runner.d.ts +1 -1
  203. package/dist/orchestration/subagent-steer.d.ts +3 -3
  204. package/dist/orchestration/workflow-agent-steer.d.ts +1 -1
  205. package/dist/orchestration/workflow-completion-inbox.d.ts +6 -6
  206. package/dist/orchestration/workflow-notify-journal.d.ts +6 -6
  207. package/dist/parent-watch.d.ts +1 -1
  208. package/dist/parked-decide.d.ts +11 -11
  209. package/dist/plan-cache-probe.d.ts +1 -1
  210. package/dist/plugins/adoption-log-sql.d.ts +4 -4
  211. package/dist/plugins/approval-ask-store-memory.d.ts +1 -1
  212. package/dist/plugins/approval-ask-store-memory.js +12 -0
  213. package/dist/plugins/approval-ask-store-sql.d.ts +39 -17
  214. package/dist/plugins/approval-ask-store-sql.js +23 -6
  215. package/dist/plugins/approval-payload-fingerprint.d.ts +23 -0
  216. package/dist/plugins/approval-payload-fingerprint.js +23 -0
  217. package/dist/plugins/background-agent-store-sql.d.ts +8 -8
  218. package/dist/plugins/background-shell-support.d.ts +12 -12
  219. package/dist/plugins/blob-backend.d.ts +3 -3
  220. package/dist/plugins/breaker-state-sql.d.ts +3 -3
  221. package/dist/plugins/caching-session-store.d.ts +6 -6
  222. package/dist/plugins/checkpoint-store-sql.d.ts +162 -66
  223. package/dist/plugins/checkpoint-store-sql.js +76 -33
  224. package/dist/plugins/device-store-sql.d.ts +4 -3
  225. package/dist/plugins/e2b-orphan-reclaim.d.ts +3 -3
  226. package/dist/plugins/file-history-store-sql.d.ts +9 -8
  227. package/dist/plugins/file-run-store.d.ts +27 -27
  228. package/dist/plugins/fork-routing-session-store.d.ts +9 -9
  229. package/dist/plugins/image-bake-store-sql.d.ts +1 -1
  230. package/dist/plugins/image-index-sql.d.ts +2 -2
  231. package/dist/plugins/k8s-bg-scripts.d.ts +1 -1
  232. package/dist/plugins/k8s-exec-protocol.d.ts +1 -1
  233. package/dist/plugins/leader-run-store-sql.d.ts +1 -1
  234. package/dist/plugins/local-checkpoint-store.d.ts +26 -17
  235. package/dist/plugins/local-checkpoint-store.js +21 -11
  236. package/dist/plugins/local-session-store.d.ts +5 -5
  237. package/dist/plugins/mailbox-store-sql.d.ts +6 -6
  238. package/dist/plugins/memory-embedder-fingerprint.d.ts +2 -2
  239. package/dist/plugins/memory-engine-pg.d.ts +1 -1
  240. package/dist/plugins/memory-engine-tidb.d.ts +1 -1
  241. package/dist/plugins/memory-key-guards.d.ts +3 -3
  242. package/dist/plugins/memory-optout-grant-store-sql.d.ts +10 -10
  243. package/dist/plugins/memory-origin-law.d.ts +13 -13
  244. package/dist/plugins/memory-run-store.d.ts +12 -12
  245. package/dist/plugins/outcome-ledger-sql.d.ts +3 -3
  246. package/dist/plugins/permission-rule-store-file.d.ts +3 -3
  247. package/dist/plugins/permission-rule-store-sql.d.ts +38 -33
  248. package/dist/plugins/permission-rule-store-sql.js +7 -12
  249. package/dist/plugins/pg-cost-quota.d.ts +2 -2
  250. package/dist/plugins/pg-pool.d.ts +29 -2
  251. package/dist/plugins/pg-pool.js +50 -2
  252. package/dist/plugins/pg-query.d.ts +1 -1
  253. package/dist/plugins/pg-rate-limiter.d.ts +2 -2
  254. package/dist/plugins/pg-session-storage.d.ts +9 -9
  255. package/dist/plugins/remote-env-adb.d.ts +1 -1
  256. package/dist/plugins/remote-env-device.d.ts +6 -4
  257. package/dist/plugins/remote-env-device.js +4 -1
  258. package/dist/plugins/remote-env-e2b.d.ts +11 -11
  259. package/dist/plugins/remote-env-file-error.d.ts +2 -2
  260. package/dist/plugins/remote-env-host.d.ts +10 -10
  261. package/dist/plugins/remote-env-k8s.d.ts +7 -7
  262. package/dist/plugins/remote-env-local-docker.d.ts +1 -1
  263. package/dist/plugins/remote-env-ssh.d.ts +9 -9
  264. package/dist/plugins/remote-scratchpad.d.ts +1 -1
  265. package/dist/plugins/resume-anchor-store-sql.d.ts +1 -1
  266. package/dist/plugins/retention-lane-store-sql.d.ts +2 -2
  267. package/dist/plugins/retention-store-sql.d.ts +11 -11
  268. package/dist/plugins/roster-store-sql.d.ts +6 -8
  269. package/dist/plugins/run-store-sql.d.ts +12 -12
  270. package/dist/plugins/scheduler-support.d.ts +1 -1
  271. package/dist/plugins/send-user-file.d.ts +1 -1
  272. package/dist/plugins/session-capture-record-store-sql.d.ts +99 -0
  273. package/dist/plugins/session-capture-record-store-sql.js +110 -0
  274. package/dist/plugins/session-placement.d.ts +1 -1
  275. package/dist/plugins/session-policy-store-sql.d.ts +2 -2
  276. package/dist/plugins/session-store.d.ts +3 -3
  277. package/dist/plugins/shared-memory-store-sql.d.ts +5 -5
  278. package/dist/plugins/sql-driver.d.ts +7 -7
  279. package/dist/plugins/sql-errors.d.ts +2 -2
  280. package/dist/plugins/sql-escape.d.ts +1 -1
  281. package/dist/plugins/sql-row-helpers.d.ts +1 -1
  282. package/dist/plugins/store-backend.d.ts +32 -19
  283. package/dist/plugins/store-backend.js +5 -1
  284. package/dist/plugins/store-contracts.d.ts +9 -9
  285. package/dist/plugins/task-list-store-sql.d.ts +3 -3
  286. package/dist/plugins/tidb-cost-quota.d.ts +3 -3
  287. package/dist/plugins/tidb-pool.d.ts +13 -0
  288. package/dist/plugins/tidb-pool.js +9 -0
  289. package/dist/plugins/tidb-rate-limiter.d.ts +2 -2
  290. package/dist/plugins/tidb-session-storage.d.ts +2 -2
  291. package/dist/plugins/tidb-session-store.d.ts +11 -11
  292. package/dist/plugins/tool-result-store-sql.d.ts +8 -8
  293. package/dist/plugins/usage-window-store-sql.d.ts +3 -3
  294. package/dist/plugins/web-search.d.ts +7 -7
  295. package/dist/plugins/workflow-journal-store-sql.d.ts +6 -6
  296. package/dist/plugins/workflow-run-store-sql.d.ts +1 -1
  297. package/dist/plugins/write-behind-counter.d.ts +6 -6
  298. package/dist/principal-jwt.d.ts +2 -2
  299. package/dist/project-memory.d.ts +1 -1
  300. package/dist/prompts-domain-validate.d.ts +8 -8
  301. package/dist/question.d.ts +3 -3
  302. package/dist/resource-suspend.d.ts +4 -4
  303. package/dist/resource-window.d.ts +3 -3
  304. package/dist/router/route-orchestration.d.ts +1 -1
  305. package/dist/rules-consent.d.ts +48 -40
  306. package/dist/run-local.d.ts +5 -5
  307. package/dist/runs.d.ts +19 -19
  308. package/dist/runtime-caps-resolver.d.ts +6 -6
  309. package/dist/runtime-governance.d.ts +11 -7
  310. package/dist/runtime-governance.js +23 -1
  311. package/dist/security.d.ts +13 -13
  312. package/dist/session-leaf-bus.d.ts +1 -1
  313. package/dist/session-sync-content.d.ts +4 -4
  314. package/dist/session-sync-kernel.d.ts +2 -2
  315. package/dist/session-sync.d.ts +13 -13
  316. package/dist/session-titler.d.ts +1 -1
  317. package/dist/session-watch.d.ts +3 -3
  318. package/dist/shared-memory-scope-authorizer.d.ts +4 -4
  319. package/dist/sighup-idle.d.ts +1 -1
  320. package/dist/spec-fields.d.ts +20 -20
  321. package/dist/ssh-host-key.d.ts +5 -5
  322. package/dist/store-live-probe.d.ts +2 -2
  323. package/dist/task-cwd.d.ts +11 -11
  324. package/dist/task-mcp.d.ts +5 -5
  325. package/dist/task-settings.d.ts +35 -35
  326. package/dist/task-workflow.d.ts +3 -3
  327. package/dist/text-bidi.d.ts +1 -1
  328. package/dist/tool-approval.d.ts +186 -182
  329. package/dist/tool-approval.js +247 -120
  330. package/dist/trace/core-keyset-guard.d.ts +19 -5
  331. package/dist/trace/engine-notice-wire.d.ts +7 -7
  332. package/dist/trace/engine-notice-wire.js +2 -0
  333. package/dist/trace/injection-tier.d.ts +11 -21
  334. package/dist/trace/injection-tier.js +3 -4
  335. package/dist/trace/ledger-events.d.ts +3 -3
  336. package/dist/trace/ledger-sink.d.ts +7 -7
  337. package/dist/trace/project.d.ts +31 -30
  338. package/dist/trace/project.js +1 -0
  339. package/dist/turn-activity.d.ts +4 -4
  340. package/dist/usage-analytics.d.ts +1 -1
  341. package/dist/wall-clock-jump-guard.d.ts +3 -3
  342. package/package.json +6 -6
@@ -40,7 +40,7 @@ import { type WorkflowScriptRunner, type WorkflowPrimitives } from "@sema-agent/
40
40
  * timer nor the abort listener fires → it hangs the process. The worker-isolated runner (`terminate()`)
41
41
  * pre-empts that — use it for genuinely-untrusted multi-tenant scripts where resource isolation matters.
42
42
  *
43
- * 🔴 Silent-hang class ([1818]§二, clay live incident 2026-07-26): a script whose promise graph can NEVER settle
43
+ * 🔴 Silent-hang class ([ref]§二, clay live incident 2026-07-26): a script whose promise graph can NEVER settle
44
44
  * (an un-awaited `phase(...)` whose body returns its own promise) used to burn the full totalTimeoutMs blind
45
45
  * and then blame the timeout. The quiescence detector in {@link runHardened} fail-fasts it with a diagnosis:
46
46
  * inside the membrane the bridge is the ONLY async host seam, so bridge-quiescent + both queues drained +
@@ -62,20 +62,20 @@ export interface HardenedVmLimits {
62
62
  * A script exceeding it OOMs the WORKER (killed), never the shared main process. Default 128. */
63
63
  maxHeapMb?: number;
64
64
  }
65
- /** [5434]①(clay 亲机四 run 三次恰在 600s 整点全灭):workflow 总超时默认与旋钮的**单点**。
65
+ /** [ref]①(clay 亲机四 run 三次恰在 600s 整点全灭):workflow 总超时默认与旋钮的**单点**。
66
66
  * 旧默认 600_000(10 分钟)对真实 workflow(验证 agent 逐条重跑清单/任何带审批等待的车)结构性不够——
67
67
  * 默认抬到 **1 小时**;部署经 `WORKFLOW_TOTAL_TIMEOUT_MS` 显式配,域 [60_000, 86_400_000](1 分钟..24h),
68
- * 坏值**响亮拒**(#210 立律:旋钮坏值禁静默回默认)。0/负数不是「禁用」:无界 runaway 脚本会吞掉共享
68
+ * 坏值**响亮拒**([ref] 立律:旋钮坏值禁静默回默认)。0/负数不是「禁用」:无界 runaway 脚本会吞掉共享
69
69
  * 副本的事件循环/堆,禁用臂刻意不提供——要更久就把值配大。模块加载时读一次(坏 env = boot fail-loud)。
70
- * 超时终态分型(partial vs failed,[5434]① 后半)涉 wire status 语义,与 core workflow 终态形另批对表。 */
70
+ * 超时终态分型(partial vs failed,[ref]① 后半)涉 wire status 语义,与 core workflow 终态形另批对表。 */
71
71
  export declare function workflowTotalTimeoutMsDefault(): number;
72
72
  /**
73
73
  * The realm test itself, exported so there is exactly ONE ruler for "did this rejection come from an untrusted
74
74
  * script?" in the process. A promise minted INSIDE a vm context fails `instanceof` against the HOST `Promise`
75
75
  * (different intrinsic per realm) — that is the whole judgement.
76
76
  *
77
- * 🔴 Why it is exported (A-070 二轮重扫, lifecycle-pairing, double-opus CONFIRMED): the guard below is NOT the
78
- * only `unhandledRejection` listener in a real boot. `src/boot/shutdown.ts` installs one at boot (#320① crash
77
+ * 🔴 Why it is exported ([ref] 二轮重扫, lifecycle-pairing, double-opus CONFIRMED): the guard below is NOT the
78
+ * only `unhandledRejection` listener in a real boot. `src/boot/shutdown.ts` installs one at boot ([ref]① crash
79
79
  * last words) that exits(1); Node walks EVERY listener for the event, so containment cannot be expressed by
80
80
  * one listener returning early — whoever exits wins regardless of registration order. The containment DECISION
81
81
  * therefore lives in the boot handler, and it must use this same ruler rather than minting a second one.
@@ -1,7 +1,7 @@
1
1
  import { type WorkflowScriptRunner } from "@sema-agent/core";
2
2
  import { type HardenedVmLimits } from "./hardened-vm-runner.js";
3
3
  /**
4
- * Worker-isolated S8 hard runner (design/98 v2). Runs the hardened-vm membrane inside a `worker_thread`, adding
4
+ * Worker-isolated S8 hard runner ([ref] v2). Runs the hardened-vm membrane inside a `worker_thread`, adding
5
5
  * RESOURCE isolation on top of the in-process {@link import("./hardened-vm-runner.js").createHardenedVmRunner}'s
6
6
  * BOUNDARY isolation:
7
7
  * - HEAP cap (`resourceLimits.maxOldGenerationSizeMb`): a runaway-allocation script OOMs the WORKER (an `error`
@@ -1,6 +1,6 @@
1
1
  import type { SubagentSteerHandle } from "@sema-agent/core";
2
2
  /**
3
- * C2 (core 1.219) + design/122 (core 1.225) — the SERVICE-side registry for
3
+ * C2 (core 1.219) + [ref] (core 1.225) — the SERVICE-side registry for
4
4
  * STEERING and RESUMING a Task SUB-AGENT (a sync delegation spawned by the `Agent` tool), the sibling of
5
5
  * {@link import("./workflow-agent-steer.js").WorkflowAgentRegistry} for workflow agents.
6
6
  *
@@ -10,7 +10,7 @@ import type { SubagentSteerHandle } from "@sema-agent/core";
10
10
  * Delivery is replica-local (the handle is an in-memory bridge, like `steerableRuns`); a cross-replica
11
11
  * steer/resume is an honest 409, never a silent drop.
12
12
  *
13
- * 🔴 LIFECYCLE (design/122 item ③ — the "不改必踩" change): handles are NO LONGER evicted on child settle.
13
+ * 🔴 LIFECYCLE ([ref] item ③ — the "不改必踩" change): handles are NO LONGER evicted on child settle.
14
14
  * `resume` is only legal AFTER the child settled (core rejects `steering.still_running` before), so a
15
15
  * settle-evicted registry would make resume structurally unreachable. Instead:
16
16
  * - one handle PER parentToolCallId, NEWEST WINS (core D2: each resume re-emits a FRESH handle under the
@@ -41,7 +41,7 @@ export declare class SubagentSteerRegistry {
41
41
  /** Register a child handle under its parent run. SAME parentToolCallId replaces (core D2: a resume
42
42
  * re-emits a fresh handle for the revived run — newest wins). Returns an IDENTITY-GUARDED unregister
43
43
  * thunk: it removes the entry only while it still holds THIS handle (a fresh sibling-leg registration
44
- * under the same id survives the old leg's teardown). Call it at LEG END, not on settle (design/122 ③). */
44
+ * under the same id survives the old leg's teardown). Call it at LEG END, not on settle ([ref] ③). */
45
45
  register(runId: string, handle: SubagentSteerHandle): () => void;
46
46
  /** Resolve `runId` + `target` to its handle on this replica. Exact `parentToolCallId` match wins (unique —
47
47
  * newest-per-id by construction → count is 0|1); otherwise match by `agentName` (count may be >1 →
@@ -34,7 +34,7 @@ export declare class WorkflowAgentRegistry {
34
34
  * · **「被截断过」仍有信号**:超界时正文段尾出现 `…`(未超界时不出现)⇒ 消费方能判断"这不是全文";
35
35
  * · **「截了多少」不再披露**:`[+N chars]` 在**所有**档位都没有了(实测 +1 / +10 / +100 / +5000 / +50000
36
36
  * 全部无披露,输出长度恒 4103)。所以一个超出 5 万字符的输入与只超 1 个字符的输入,**外观完全相同**。
37
- * ⚠️ core [1707]⑤ 的措辞是「**刚过界**的输入现在是裸 `…` 结尾」,而实测是**全档位**都没有披露 —— 范围比
37
+ * ⚠️ core [ref]⑤ 的措辞是「**刚过界**的输入现在是裸 `…` 结尾」,而实测是**全档位**都没有披露 —— 范围比
38
38
  * 它描述的宽。已带实测数据上黑板问 core 这是否是有意的(可能只是描述省略,也可能是它没注意到)。
39
39
  * 在得到答复前**不改行为**:core 的截断器是它那侧的安全件,server 不该自己在外面补一层"+N chars"去顶
40
40
  * ——那会变成两处各说一套。 */
@@ -69,7 +69,7 @@ export declare const PURGE_FENCE_MS: number;
69
69
  * to swallow any realistic notify lag incl. a boot-recovery re-fire racing a fresh poll; per-runId scoped, so
70
70
  * it can never starve a DIFFERENT workflow's push. In-memory only (see {@link PURGE_FENCE_MS} rationale). */
71
71
  export declare const SERVED_FENCE_MS: number;
72
- /** design/144 §4 server 折叠键:`JSON([域, taskId, RAW status])[#seq]`。域=external 帧独立 lane(task_id 是
72
+ /** [ref] §4 server 折叠键:`JSON([域, taskId, RAW status])[#seq]`。域=external 帧独立 lane(task_id 是
73
73
  * 调用方自由串,不分域可预占内部帧键把真实子代 settle 帧吞掉)/其余内部帧统一 "task" 域。
74
74
  *
75
75
  * 三路复审修1(MED):status 保留 RAW,不再归一 completed/failed —— 归一让同 id 无 seq 的两条 external
@@ -91,15 +91,15 @@ export declare function taskNotificationFoldKey(n: {
91
91
  status: string;
92
92
  seq?: number;
93
93
  }): string;
94
- /** design/144 stream 侧去重键(core [784]④a + codex 1.189 前双审 F2)= `域:taskId:status[#seq]`。
94
+ /** [ref] stream 侧去重键(core [ref]④a + codex 1.189 前双审 F2)= `域:taskId:status[#seq]`。
95
95
  * 与 {@link taskNotificationFoldKey} 同族,域二分也一致(codex F2 HIGH:external 通知的 task_id 是
96
96
  * POST /v1/sessions/:id/notify 调用方自由串——同一条腿上,drain 出的 external 帧可与内部任务帧同形
97
97
  * `task_id:status:seq` 撞键互吞,per-leg 键集并不豁免这个面,旧注释「没有跨调用方预占面」判错);
98
98
  * 仍与 fold key 有意不同的一点:status 保留 RAW(killed/cancelled/event 不归一 failed)——归一会让同
99
99
  * task 的 Monitor event 批与 failed 终态在一条腿上互吞;wire 去重要的是逐帧身份,不是 inbox 的双终态列。
100
100
  * `seq` 折入 = 停→唤→停的第二周期同 status 帧各自成键(core 1.283 起 background_agent 四腿 notify 铸
101
- * cycleSeq;缺 seq 时旧键曾把二周期 completed 帧在 observer 臂反向吞掉——core [784]④a);无 seq 的帧
102
- * (bash/monitor terminal/retain 降级)保持单周期旧键=同键第二帧吞,诚实语义。[2373]B-10:core 4.0.0 起
101
+ * cycleSeq;缺 seq 时旧键曾把二周期 completed 帧在 observer 臂反向吞掉——core [ref]④a);无 seq 的帧
102
+ * (bash/monitor terminal/retain 降级)保持单周期旧键=同键第二帧吞,诚实语义。[ref]B-10:core 4.0.0 起
103
103
  * task_type 是必填闭合枚举——`task_type?` 可选性**不再对应旧 core 帧**,它活着只为家族前缀构造
104
104
  * (server.ts fleet 腿 `taskNotificationFoldKey({task_id,status})` 同款用法);缺席归 "task" 域的语义
105
105
  * 只在前缀用途下生效。external 帧三来源齐备(notify 端点 core 铸 / inbox entry extras 存 / drain 帧
@@ -257,7 +257,7 @@ export declare function taskNotificationInboxEntry(sessionId: string, owner: str
257
257
  edits: number;
258
258
  }>;
259
259
  resumable?: boolean;
260
- /** core 1.353([1412]):诊断槽(journal 坐标+教句,引擎值单源)——park 透传,drain 帧原样带。 */
260
+ /** core 1.353([ref]):诊断槽(journal 坐标+教句,引擎值单源)——park 透传,drain 帧原样带。 */
261
261
  diagnostics?: string;
262
262
  }, enqueuedAt: number,
263
263
  /** lead-b (dual-ID audit): the PARENT run's durable taskId (the uuid the shell's footer rows
@@ -265,7 +265,7 @@ export declare function taskNotificationInboxEntry(sessionId: string, owner: str
265
265
  * parent row without a side lookup. */
266
266
  parentTaskId?: string,
267
267
  /**
268
- * design/373 §3.6(core 5.61.0,#366 / codex R1[high]):core 在 `onTaskNotification` 的**第二参**上报的
268
+ * [ref] §3.6(core 5.61.0,[ref] / codex R1[high]):core 在 `onTaskNotification` 的**第二参**上报的
269
269
  * 投递档位。park 是**跨 run** 的那条投递路径 —— 不带过去,档位就在最常走的一条路上恒缺席。
270
270
  *
271
271
  * 🔴 只在 core **真的给了**档位时传:缺席原样缺席(与 live 投影同一条「缺席≠later」纪律)。
@@ -152,7 +152,7 @@ export declare class WorkflowNotifyGate {
152
152
  *
153
153
  * BOTH abandoned arms (boot-orphan + stale-past-grace) flip the DURABLE row to `failed` FIRST (CAS on rev),
154
154
  * so the run store, the fleet panel and the delivered notify give ONE answer — previously the notify said
155
- * `failed` while `/workflows` kept saying `running` forever ([2999]: republishing without finalizing would
155
+ * `failed` while `/workflows` kept saying `running` forever ([ref]: republishing without finalizing would
156
156
  * have turned "panel empty" into "panel shows a row that never moves"). A lost CAS means the run moved under
157
157
  * the sweep (e.g. its real terminal landed concurrently) — skip this pass; the entry stays pending and the
158
158
  * next sweep handles the NEW state.
@@ -175,14 +175,14 @@ export declare class WorkflowNotifyGate {
175
175
  /** Replica-local (File/in-memory) journal ONLY: a pending entry recorded BEFORE this timestamp belongs to
176
176
  * a previous incarnation of THIS process — workflow executors are in-process, so they died with it and a
177
177
  * still-`running` run is a boot-orphan: finalize it NOW instead of leaving the user's "Waiting for
178
- * workflow" pointed at a run that can never finish for the whole grace window ([2995] 顺带①/[3000]§二).
178
+ * workflow" pointed at a run that can never finish for the whole grace window ([ref] 顺带①/[ref]§二).
179
179
  * NEVER pass this for a cross-replica (SQL) journal — there a pending running run may be genuinely alive
180
180
  * on another replica, and age (`orphanGraceMs`) is the only sound orphan proxy.
181
181
  * ⚠️ This wall-clock cutoff is a NECESSARY, not sufficient, condition — {@link recordedThisIncarnation}
182
182
  * is the authoritative one (a clock rollback after boot would otherwise stamp THIS process's own new
183
183
  * entries below the cutoff and finalize live runs). */
184
184
  finalizeStartedBeforeMs?: number;
185
- /** Retire a fleet row for a run this sweep just finalized ([2995]/[2999]): called ONLY with a TERMINAL run,
185
+ /** Retire a fleet row for a run this sweep just finalized ([ref]/[ref]): called ONLY with a TERMINAL run,
186
186
  * so the {@link JournalingWorkflowRunStore} projection publishes the final frame and then removes the row —
187
187
  * the store, the panel and the notify end up saying the same thing. Never called with a `running` run (see
188
188
  * the single-writer invariant above). Late-bound because the wrapper is constructed after this gate. */
@@ -264,7 +264,7 @@ export declare class InMemoryWorkflowNotifyJournalStore implements WorkflowNotif
264
264
  */
265
265
  export declare class JournalingWorkflowRunStore implements WorkflowRunStore {
266
266
  private readonly inner;
267
- /** [1262] optional since the fleet decoupling: undefined ⇒ no start-time journal (ephemeral memory
267
+ /** [ref] optional since the fleet decoupling: undefined ⇒ no start-time journal (ephemeral memory
268
268
  * backend has nothing to recover), the FLEET half still publishes — the panel is replica-local UI
269
269
  * state and must not be gated on the durable-notify machinery (the regression that emptied clay's
270
270
  * workflow panel on memory-backend deployments). */
@@ -273,7 +273,7 @@ export declare class JournalingWorkflowRunStore implements WorkflowRunStore {
273
273
  * point as the notify journal). Optional — undefined ⇒ no fleet publish. */
274
274
  private readonly fleetBus?;
275
275
  constructor(inner: WorkflowRunStore,
276
- /** [1262] optional since the fleet decoupling: undefined ⇒ no start-time journal (ephemeral memory
276
+ /** [ref] optional since the fleet decoupling: undefined ⇒ no start-time journal (ephemeral memory
277
277
  * backend has nothing to recover), the FLEET half still publishes — the panel is replica-local UI
278
278
  * state and must not be gated on the durable-notify machinery (the regression that emptied clay's
279
279
  * workflow panel on memory-backend deployments). */
@@ -284,7 +284,7 @@ export declare class JournalingWorkflowRunStore implements WorkflowRunStore {
284
284
  /** Derive + publish the MF-Fleet workflow row from a WorkflowRun (doneCount/totalCount from agents, tokens from
285
285
  * stats); a terminal workflow LEAVES the fleet (publish terminal then remove), a running one stays/updates. */
286
286
  private publishFleet;
287
- /** [2995] recovery projection seam: the same fleet projection as the put/update observation points, exposed so
287
+ /** [ref] recovery projection seam: the same fleet projection as the put/update observation points, exposed so
288
288
  * the recovery sweep can RETIRE a row for a run it just finalized (terminal input ⇒ final frame, then remove).
289
289
  * Wire it as `recover`'s `publishTerminalFleetRow` hook — and only ever hand it a TERMINAL run: a `running`
290
290
  * row published from outside the wrapper's own write path has no guaranteed retirement (see the invariant on
@@ -1,5 +1,5 @@
1
1
  /**
2
- * #219(黑板 [3617]):引擎 **parent 监视**。
2
+ * [ref](黑板 [ref]):引擎 **parent 监视**。
3
3
  *
4
4
  * ## 防的是什么
5
5
  *
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * 件3d `/decide` 消费 parked 后台子代——server 半场辅件(设计稿:sema-internal
3
- * server/docs/DECIDE-PARKED-DESIGN.md;黑板 [1587];core 裁定 [1574]/[1584])。
3
+ * server/docs/DECIDE-PARKED-DESIGN.md;黑板 [ref];core 裁定 [ref]/[ref])。
4
4
  *
5
5
  * 本模块先落判别器:`POST /v1/approvals/:sessionId/decide` 路由在既有 session→token 映射拿到
6
6
  * pending checkpoint 后,用它判定该 cp 是否属于一个 parked 后台子代——命中则走 claim →
@@ -37,18 +37,18 @@ export interface ParkedDecideDeps {
37
37
  /** 与 reaper/scenarios 同一个 registry(claim/rollback 的 CAS 与 in-memory handle 收敛在同处)。 */
38
38
  registry: Pick<TaskRegistry, "claimParkedAgent" | "rollbackParkedClaim">;
39
39
  /** boot 期从生产装配(buildScenarios)取的裸 Agent ToolSpec——与 spawn 用同一装配路径,
40
- * subRunner/bg opts/checkpointStore 同实例天然成立([1587] 设计稿 §4)。 */
40
+ * subRunner/bg opts/checkpointStore 同实例天然成立([ref] 设计稿 §4)。 */
41
41
  reviveTool: ToolSpec;
42
- /** revive args 的 `subagent_type` 成员性判定集([1588] Q1 修正:非 roster 成员必须省略,否则
42
+ /** revive args 的 `subagent_type` 成员性判定集([ref] Q1 修正:非 roster 成员必须省略,否则
43
43
  * unknown subagent_type 拒;字面比对 general-purpose 在 roster 撞名时会错省)。缺省空集=恒省略。 */
44
44
  knownAgentTypes?: ReadonlySet<string>;
45
- /** [1596]/[1597] 跨进程父约束重供席:按部署配置**重建的同语义**父策略链工厂(host 任务的 toolPolicy
45
+ /** [ref]/[ref] 跨进程父约束重供席:按部署配置**重建的同语义**父策略链工厂(host 任务的 toolPolicy
46
46
  * 解析槽一条,单层链;exempt 探针锚= row.rootSessionId,与 remember grant 锚同键)。core 1.396 起
47
47
  * `parkedResume.inheritedGate` 席位把它透传进 resume 的官方重供通道——不供 = 重启后带
48
48
  * requiresParentConstraint 的 checkpoint 恒被 pre-CAS 门拒(retryable 假话,永不可赎回)。链长形状
49
49
  * 校验在 core(fail-closed,供错链长照拒)。
50
50
  *
51
- * ⚠️ **async**(A-010.1):重建条目的第三位决议链元数据 `autoModeArmed` 与 `durableMandate` 的
51
+ * ⚠️ **async**([ref]):重建条目的第三位决议链元数据 `autoModeArmed` 与 `durableMandate` 的
52
52
  * `forceDurableGate` 项都要按**本行的 principal** 现解 entitlement(`RunnerDeps.runtimeCapsResolver`
53
53
  * 本身就是 sync-or-async 的座),理由全在 `boot/parked-revive-gate.ts`。本腿一直就在 async 里,
54
54
  * 「席位必须同步」是那个文件此前自设的约束、不是结构事实。 */
@@ -64,7 +64,7 @@ export interface ParkedDecideRequest {
64
64
  /** cp.pendingAction 原样(outcome 铸造的 persisted 回落源,与 legacy 腿 D-1 姿势逐字同形)。 */
65
65
  pendingAction: unknown;
66
66
  decision: "approve" | "deny";
67
- /** #204 件6③ core `ApprovalSettledBy`:**这次结算的出处**,由调用方命名(必填,理由与 legacy 腿
67
+ /** [ref] 件6③ core `ApprovalSettledBy`:**这次结算的出处**,由调用方命名(必填,理由与 legacy 腿
68
68
  * `resumeCheckpoint` 的同名参数逐字同源 —— 本函数分辨不出谁在叫它,漏报要是编译错而不是假出处)。
69
69
  * 今天唯一的调用方是 `server.ts` 的人为 `/decide`(那道门写着 `req !== undefined`,而内部 D-D SLA
70
70
  * deny-sweep 恰是 req 缺席的那条腿,它对 parked 行另有静默跳过臂)⇒ 恒 `"human"`。 */
@@ -77,14 +77,14 @@ export interface ParkedDecideRequest {
77
77
  boundInputHash?: string;
78
78
  updatedInput?: unknown;
79
79
  };
80
- /** body 带了 `remember:"session"` 时路由传入的 grant 执行器([1591] 候裁② 的 server 侧修,经两轮
80
+ /** body 带了 `remember:"session"` 时路由传入的 grant 执行器([ref] 候裁② 的 server 侧修,经两轮
81
81
  * 行为探针实证):豁免必须锚在**行的 root/host 会话 id**——部署侧三个豁免探针(policy 层/fs-write
82
82
  * 门/workflow 门)的闭包统一捕获 host 会话键且签名不携身份(1.393 seam 亲读:`sourceTaskId` 只在
83
83
  * onAsk 层的 AskRequest,durable 车道无 onAsk),grant 落子代会话则键永不相交(G-F4 原案);落
84
84
  * root 会话则宿主键闭包立即命中,复活子代的后续同工具 ask 被短路(探针 v2 实证),语义与同步车道/
85
85
  * 宿主任务的「本会话不再询问」一致(= host 会话树全域)。行无 root 锚(病态形)⇒ claim 前诚实 400。 */
86
86
  grantRemember?: (rootSessionId: string) => Promise<void>;
87
- /** RB-459(core 5.7.0,F6 翻案):AskUserQuestion 的 approve 携操作员答案——原样透传进
87
+ /** [ref](core 5.7.0,F6 翻案):AskUserQuestion 的 approve 携操作员答案——原样透传进
88
88
  * `ResumeOutcome.answer`(形状校验在路由层 isQuestionAnswer;header 逐字匹配等语义校验在 core,
89
89
  * server 不预判)。core 拒绝形:同步腿 409 invalid_outcome field:"answer",parked 腿经 drive 失败
90
90
  * 面 422 parked_resume.startup_failed。 */
@@ -98,16 +98,16 @@ export interface ParkedDecideResult {
98
98
  body: Record<string, unknown>;
99
99
  }
100
100
  /**
101
- * `/decide` parked 赎回腿(design/153 件3d server 半场;[1574]/[1584]/[1588] core 裁定形)。
101
+ * `/decide` parked 赎回腿([ref] 件3d server 半场;[ref]/[ref]/[ref] core 裁定形)。
102
102
  *
103
103
  * 返回 `undefined` = 该 pending checkpoint 不属于任何 parked 后台子代——调用方走既有任务级
104
104
  * resumeCheckpoint 腿(零回归);返回结果对象 = 赎回腿已受理/已拒,调用方直接回 HTTP。
105
105
  *
106
106
  * 链:判别(findParkedAgentForCheckpoint)→ `claimParkedAgent`(access = 行镜像双轴
107
- * `{scope: row.scope, owner: row.owner}`,[1588] Q3)→ outcome 铸造(D-1 echo/persisted 回落)
107
+ * `{scope: row.scope, owner: row.owner}`,[ref] Q3)→ outcome 铸造(D-1 echo/persisted 回落)
108
108
  * → 裸 `reviveTool.execute(args, ctx.reviveClaim)`。execute 一旦发起 drive,rollback 全在 core 内
109
109
  * (driveParkedResume);server 只在「claim 成功但 drive 从未发起」窗口补 `rollbackParkedClaim`
110
- * ([1588] Q2:isError 入参级早退 + throw 两形,已核幂等/双滚=无害 lost)。
110
+ * ([ref] Q2:isError 入参级早退 + throw 两形,已核幂等/双滚=无害 lost)。
111
111
  *
112
112
  * 200 是**受理**语义(drive 是 core 内 fire-and-forget):失败经行/notification 面 + REOPENED
113
113
  * re-park 诚实可见,操作员可再决。
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Plan-cache recurrence probe — INSTRUMENT-FIRST (search AI → service, 团队/给service-AI.md [1];
3
- * core design/42). Zero-LLM, zero-dependency, pure in-memory.
3
+ * core [ref]). Zero-LLM, zero-dependency, pure in-memory.
4
4
  *
5
5
  * Measures the **per-scope recurrence rate of task objectives**: the unproven "省钱" premise behind a
6
6
  * proposed core *plan-caching* feature (store a successful run's generalized plan → a similar new task
@@ -1,5 +1,5 @@
1
1
  /**
2
- * design/183 I2(form b 位)—— **SQL 收编日志**:phase 真源与被迁的行**同库**。
2
+ * [ref] I2(form b 位)—— **SQL 收编日志**:phase 真源与被迁的行**同库**。
3
3
  *
4
4
  * 🔴 为什么 phase 必须住 SQL 而不是一个 sidecar 文件(183 r3 按 codex r2-F2):发起收编的那个 pod 在两条
5
5
  * 腿之间被摧毁时,进程本地的标记会与已经半迁移的 SQL 状态**分家** —— 接棒副本读不到「迁到哪了」。
@@ -118,7 +118,7 @@ export declare function ensurePgAdoptionLogSchema(q: (text: string, params?: unk
118
118
  */
119
119
  export declare function adoptionLockName(fromPrincipal: string): string;
120
120
  /**
121
- * 把弧锁名限定到**一个库**的键空间(A-010.13,验真后修)。
121
+ * 把弧锁名限定到**一个库**的键空间([ref],验真后修)。
122
122
  *
123
123
  * 🔴 病:两条腿的锁键空间**不等价**。MySQL/TiDB 的 `GET_LOCK` 名字是**服务器实例全局**的
124
124
  * (`performance_schema.metadata_locks` 里就是一个进程级命名空间,与你连的是哪个 schema 无关);
@@ -199,7 +199,7 @@ export declare class SqlAdoptionLogStore implements AdoptionLogStore {
199
199
  /** 目的地冲突 ⇒ rejected 终态(源/目的地两侧字节零变更;phase 停在 INTENT)。 */
200
200
  finalizeRejected(adoptionId: string, code: AdoptionRejectCode, detail: string, nowMs: number, exec?: SqlExec): Promise<boolean>;
201
201
  /**
202
- * 本连接所在**数据库**的名字 = 弧锁的键空间限定符(A-010.13,理由见 {@link qualifyAdoptionLockName})。
202
+ * 本连接所在**数据库**的名字 = 弧锁的键空间限定符([ref],理由见 {@link qualifyAdoptionLockName})。
203
203
  *
204
204
  * 在**交出来的那条连接**上问(不向池要第二条 —— 弧全程单连接,见 `AdoptionLogStore.getById` 的注),
205
205
  * 结果缓存在店上:库名在一条驱动的生命周期里不会变,而每次取锁多打一个往返是白付的。
@@ -217,7 +217,7 @@ export declare class SqlAdoptionLogStore implements AdoptionLogStore {
217
217
  * 返回 `undefined`,调用方按「在飞」应答 —— **不假装成功,也不无限等**。
218
218
  *
219
219
  * 🔴 入参 `name` 是**逻辑**锁名(`adoptionLockName(fromPrincipal)`);真正发给引擎的是它被
220
- * {@link qualifyAdoptionLockName} 限定到本库之后的形(A-010.13:两方言键空间不等价)。限定发生在
220
+ * {@link qualifyAdoptionLockName} 限定到本库之后的形([ref]:两方言键空间不等价)。限定发生在
221
221
  * **这里**而不是调用方,因为「键空间是每库还是每实例」是**存储层**的知识,协议层(runner)不该知道。
222
222
  */
223
223
  withLock<T>(name: string, fn: (conn: SqlTxConn) => Promise<T>, attempts?: number, sleepMs?: number): Promise<T | undefined>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `InMemoryApprovalAskStore` —— #151 车1,`ApprovalAskStore` 的语义真源(twin 对拆基准)+ LOCAL
2
+ * `InMemoryApprovalAskStore` —— [ref] 车1,`ApprovalAskStore` 的语义真源(twin 对拆基准)+ LOCAL
3
3
  * 车道占位(File 形不在本车,见设计定稿 §7)。单进程内两个 `Map`,方法体全同步(不含 `await` 中断点)——
4
4
  * Node 单线程下这就是天然原子:`Promise.all` 发起的并发调用不会在方法体内部交错执行,与
5
5
  * `approval-ask-store-sql.ts` 的 CAS UPDATE 语义逐字段一致(SQL twin 对拆套件的基准就是这份实现)。
@@ -105,12 +105,24 @@ export class InMemoryApprovalAskStore {
105
105
  }
106
106
  }
107
107
  }
108
+ let encodedUpdatedInput;
109
+ if (decision.updatedInput !== undefined) {
110
+ const text = JSON.stringify(decision.updatedInput);
111
+ if (text === undefined)
112
+ throw new Error("approval-ask-store(memory): updatedInput is not JSON-encodable (encodes to nothing) — the SQL twin cannot hold it either");
113
+ const decoded = JSON.parse(text);
114
+ encodedUpdatedInput = decoded;
115
+ }
108
116
  batch.rev += 1;
109
117
  batch.updatedAtMs = now;
110
118
  ask.state = "DECIDED";
111
119
  ask.decision = decision.decision;
112
120
  ask.decisionActor = decision.decisionActor ?? null;
113
121
  ask.decisionNote = decision.decisionNote ?? null;
122
+ if (decision.updatedInput === undefined)
123
+ delete ask.updatedInput;
124
+ else
125
+ ask.updatedInput = encodedUpdatedInput;
114
126
  ask.decidedAtMs = now;
115
127
  ask.idempotencyKey = decision.idempotencyKey ?? null;
116
128
  ask.rev += 1;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * 流内审批协议(design/172 v3.1 §3.0/§3.1/§3.2)持久层 —— #151 车1,`ApprovalAskStore` 双方言实现
3
- * (`TiDBApprovalAskStore` / `PgApprovalAskStore`,SINGLE-FILE DUAL-DIALECT,design/158 A12 形——照
2
+ * 流内审批协议([ref] v3.1 §3.0/§3.1/§3.2)持久层 —— [ref] 车1,`ApprovalAskStore` 双方言实现
3
+ * (`TiDBApprovalAskStore` / `PgApprovalAskStore`,SINGLE-FILE DUAL-DIALECT,[ref] A12 形——照
4
4
  * checkpoint-store-sql.ts:一个 `SqlApprovalAskStore` 类接 `SqlDriver`,两个薄 ctor 子类落方言绑定)。
5
5
  *
6
6
  * 两张表:`approval_ask`(每个流内工具调用一行,ask 级 6 态状态机)+ `approval_batch`(同一决策点的
@@ -19,7 +19,7 @@
19
19
  * 对被更新行本身恒是 current read,不受 REPEATABLE READ 快照影响),所以走普通 `begin()`,不需要
20
20
  * `beginPessimistic()`。
21
21
  *
22
- * ── 方言差异(显式写在每个调用点,design/158 A12 doctrine)──────────────────────────────────────────
22
+ * ── 方言差异(显式写在每个调用点,[ref] A12 doctrine)──────────────────────────────────────────
23
23
  * - `?` 占位符(位置序)vs `$n`(显式编号)——动态列清单(`transitionAsk`/`resolveProvisional`,列集合
24
24
  * 依 patch 内容变化)靠 `ph(dialect, n)` 生成两种占位符文本,与 background-agent-store-sql.ts 的
25
25
  * `updateIf` guard 占位符构造同精神(那里也是「列集合动态、占位符文本仍显式按方言生成」)。
@@ -60,7 +60,7 @@ export interface AskRow {
60
60
  * 与下面 PARKED 坐标里的 `gateBoundInputHash` 是**两件不同的东西**,别混:
61
61
  * - `boundInputHash`(本列)= ask **铸行时**的入参摘要,一次写定永不改;对账收敛器判据 1 用它跟
62
62
  * checkpoint 行的同名列做**硬相等**——它是**身份三元组之外的第二道等式**,身份本身是
63
- * (`sourceTaskId`, `toolCallId`, 因果下界)三维(#168 件1 换轴,判据属主 = `approval-reconciler.ts`
63
+ * (`sourceTaskId`, `toolCallId`, 因果下界)三维([ref] 件1 换轴,判据属主 = `approval-reconciler.ts`
64
64
  * 的 `classifyGateMatch`;本注上一版写的「identity 四元组」是换轴前的旧口径,`sessionId` 从来不是
65
65
  * 内存判据维)。任一侧缺席 ⇒ 判据 1 **不命中**;归因看走到哪一层:身份先判(候选集非空却没有同身份
66
66
  * 的一条 ⇒ `identity_miss`),身份这层还够得着时缺席才记 `single_mint`(禁「能取到时才比」的可选谓词
@@ -78,6 +78,24 @@ export interface AskRow {
78
78
  /** 171 ActorAssertion JSON(车4 才消费,列先在——JSON.parse 后的裸值,类型未知)。 */
79
79
  decisionActor: unknown | null;
80
80
  decisionNote: string | null;
81
+ /**
82
+ * [ref]([ref] / [ref] 收口):人批准时带的 **ctrl+g 编辑实参**(wire `updatedInput`),与决议**同一条
83
+ * UPDATE** 原子落列 `updated_input`。语义三态,读法**严格**:
84
+ * · `undefined`(列 NULL)= 这次决议**没带**编辑 —— 回放腿交裸 `true`,core 按原始实参执行;
85
+ * · 任何其它值(**含 `null`**,列存 JSON 文本 `"null"`)= 带了编辑的**字面值**,回放腿交
86
+ * `{ allow: true, updatedInput }`,core 按它执行。「编辑成 null」与「没编辑」在 wire 上是两回事
87
+ * (`hasUpdatedInput` 读的是键在场),店面照此分家;消费端**禁**用 `?? ` / `== null` 折叠。
88
+ * · deny 行恒 `undefined`:deny 带 `updatedInput` 的成文语义是「宽收后忽略」,写口不落。
89
+ *
90
+ * 为什么必须是行上的一列(census 第 31 行 P-DEBT 的终局件):行派生的 approve 回放(幂等重入 / 收敛臂 /
91
+ * 店报错臂 / 迟到受理 / 悬挂轮询 / HTTP 观察者,六站点)此前只能交裸 `true` ⇒ core 的
92
+ * `d.updatedInput === undefined` 分支落回**原始未改写**实参执行 —— 人批的是改写后的命令、真跑的是原
93
+ * 命令 = 执行面宽于人所批准。列在,行即真源,六站点从行上读同一份编辑。
94
+ *
95
+ * 🔴 LONGTEXT/TEXT 存 JSON 文本(与同表 `decision_actor` / `card_json` 同款,`dialectJsonEncoder` 编码、
96
+ * `parseJsonColumn` 读回):编辑实参是整只工具入参,与 `card_json` 同量级,VARCHAR 会造静默截断面。
97
+ */
98
+ updatedInput?: unknown;
81
99
  decidedAtMs: number | null;
82
100
  deniedReason: string | null;
83
101
  /** PARKED 坐标三件。 */
@@ -95,7 +113,7 @@ export interface AskRow {
95
113
  /** 重放腿的帧载荷(args 已帽已洗后的投影)。 */
96
114
  cardJson: unknown;
97
115
  /**
98
- * #363 —— **规则车道素材**两列之一:这只 ask 被裁决的**命令**(已过基础脱敏,见 `tool-approval.ts`
116
+ * [ref] —— **规则车道素材**两列之一:这只 ask 被裁决的**命令**(已过基础脱敏,见 `tool-approval.ts`
99
117
  * 的落盘点)。`null` = 这只 ask 从没进过规则车道(治理档 / 无属主 / 引擎没铸候选 / args 读不出命令),
100
118
  * 或它由**加这两列之前**的构建落的行。
101
119
  *
@@ -109,8 +127,8 @@ export interface AskRow {
109
127
  */
110
128
  ruleCommand: string | null;
111
129
  /**
112
- * #363 —— 规则车道素材两列之二:**授权发生地**的 project root(`ruleScopeRootFor` 在**铸卡时**咨询
113
- * 的那一份,#295 F-1 的快照语义)。`null` = 解析不出 root ⇒ 兑付时**不铸 scope**,core 落 global
130
+ * [ref] —— 规则车道素材两列之二:**授权发生地**的 project root(`ruleScopeRootFor` 在**铸卡时**咨询
131
+ * 的那一份,[ref] F-1 的快照语义)。`null` = 解析不出 root ⇒ 兑付时**不铸 scope**,core 落 global
114
132
  * (= live 腿逐字同形;绝不在坐标系不明时编一个 root)。
115
133
  */
116
134
  ruleScopeRoot: string | null;
@@ -134,17 +152,17 @@ export interface NewAskRow {
134
152
  /** 车5 §9 C2 的对账 join 键(语义见 `AskRow.boundInputHash`)。缺席 ⇒ 该行结构上永不满足判据 1。 */
135
153
  boundInputHash?: string | null;
136
154
  cardJson: unknown;
137
- /** #363 规则车道素材(语义与「为什么是行上的列」见 {@link AskRow.ruleCommand})。缺席 ⇒ 列 NULL ⇒
155
+ /** [ref] 规则车道素材(语义与「为什么是行上的列」见 {@link AskRow.ruleCommand})。缺席 ⇒ 列 NULL ⇒
138
156
  * 这条行上的迟到决议对 `persistRule` 响亮拒(`rule_material_absent`),绝不猜命令。 */
139
157
  ruleCommand?: string | null;
140
- /** #363 授权发生地(语义见 {@link AskRow.ruleScopeRoot})。 */
158
+ /** [ref] 授权发生地(语义见 {@link AskRow.ruleScopeRoot})。 */
141
159
  ruleScopeRoot?: string | null;
142
160
  schemaVersion: number;
143
161
  expiresAtMs: number;
144
162
  createdAtMs: number;
145
163
  }
146
164
  /**
147
- * `ensureAsk` 的产出 —— 行 **+ 这一次调用到底插没插**(#168 件2)。
165
+ * `ensureAsk` 的产出 —— 行 **+ 这一次调用到底插没插**([ref] 件2)。
148
166
  *
149
167
  * 🔴 为什么判别位必须由**店**给:`ensureAsk` 是幂等 upsert(`askId` 是确定性派生,重试 / failover /
150
168
  * 闭包再入天然指向同一行),所以「拿到一条 STREAM_PENDING 行」有两种成因 —— 本次插的,或幂等命中了
@@ -180,6 +198,10 @@ export interface DecideAskInput {
180
198
  decisionNote?: string | null;
181
199
  /** 车4 §12-E:回决幂等键,赢 CAS 时随决议一起落列(见 `AskRow.idempotencyKey`)。缺席 ⇒ 列保持 NULL。 */
182
200
  idempotencyKey?: string | null;
201
+ /** [ref]:ctrl+g 编辑实参,与决议同一条 UPDATE 落列(语义三态见 {@link AskRow.updatedInput})。
202
+ * 缺席 / `undefined` ⇒ 列 NULL(没带编辑);**`null` 是值**(编辑成 null),照存 JSON `"null"`。
203
+ * 调用方纪律:deny 不传(店不替调用方判决议方向,写什么存什么)。 */
204
+ updatedInput?: unknown;
183
205
  }
184
206
  /**
185
207
  * `idempotency_conflict`(车4 §12-E):同一 (task_id, idempotency_key) 已被**另一条** ask 的回决占用。
@@ -206,7 +228,7 @@ export type DecideResult = {
206
228
  */
207
229
  export declare function assertIdempotencyKeyShape(key: string): void;
208
230
  /**
209
- * #151 车3 刀 3b(§14.2 遗留记账):两条**重放读口**被调用方的 deadline 掐断时抛的具名错误。
231
+ * [ref] 车3 刀 3b(§14.2 遗留记账):两条**重放读口**被调用方的 deadline 掐断时抛的具名错误。
210
232
  *
211
233
  * 具名类而不是「按 message 文本判别」:错误文案是给人看的,拿它当控制流 = 上游改一句人话下游静默失效
212
234
  * (#90 工程规范 v3 门②)。调用方(开流 preamble)对它的处置与其余读错误一样 —— fail-open、零卡、一次
@@ -323,7 +345,7 @@ export declare const APPROVAL_BATCH_TABLE = "approval_batch";
323
345
  * SCHEMA POLICY 同 `tidb-pool.ts` 头注:纯 CREATE,禁 ALTER 增量 seam,改列直接改这里 + 重建库
324
346
  * (`docs/schema/baseline-mysql.sql` 是由这些文本机器录制出的**产物**,永不手改)。
325
347
  *
326
- * ── 列宽的**测量依据**(#192 A10;U2 逐列取证在档)──────────────────────────────────────────────────
348
+ * ── 列宽的**测量依据**([ref] A10;U2 逐列取证在档)──────────────────────────────────────────────────
327
349
  * 本表家族原先一律 VARCHAR(255),是"先建表后想"的产物。按"每列的值到底由谁铸、有没有入口上限"重新裁:
328
350
  *
329
351
  * 收窄(有硬上限背书,证据即上限本身):
@@ -363,8 +385,8 @@ export declare const TIDB_APPROVAL_ASK_STATEMENTS: readonly string[];
363
385
  export declare function ensureTiDBApprovalAskSchema(pool: MySqlPool): Promise<void>;
364
386
  export declare function ensurePgApprovalAskSchema(q: PgQueryFn): Promise<void>;
365
387
  /**
366
- * #363 升级前置断言 —— **拒启**,不是 warn(形照 #340 的 `assertPermissionRuleApprovalSchema` /
367
- * #119 的 `assertToolResultProvenanceSchema` 两条先例)。
388
+ * [ref] 升级前置断言 —— **拒启**,不是 warn(形照 [ref] 的 `assertPermissionRuleApprovalSchema` /
389
+ * [ref] 的 `assertToolResultProvenanceSchema` 两条先例)。
368
390
  *
369
391
  * 病:本仓不发 `ALTER TABLE`(SCHEMA POLICY:改列就改 CREATE + 删库重建)。于是一台**没删表**就升上来
370
392
  * 的部署,`CREATE TABLE IF NOT EXISTS` 对存量 `approval_ask` 是空操作 —— 本车新加的
@@ -373,11 +395,11 @@ export declare function ensurePgApprovalAskSchema(q: PgQueryFn): Promise<void>;
373
395
  * · 每一只 ask 的 `ensureAsk` 撞 unknown column ⇒ 被 `noteStoreError` 吞掉 ⇒ 整只 ask 退回 park 路由
374
396
  * (卡不落库、`GET /v1/approvals` 的重放面恒空、迟到决议腿恒 404);
375
397
  * · 而 `/v1/capabilities` 的 `streamApproval` 仍然报 active ⇒「says yes ⟺ route works」整句为假。
376
- * 没有这道断言,运维得不到**任何**「这次升级必须重建表」的信号 —— 正是 #157「禁静默降级」要挡的形。
398
+ * 没有这道断言,运维得不到**任何**「这次升级必须重建表」的信号 —— 正是 [ref]「禁静默降级」要挡的形。
377
399
  *
378
400
  * 判据 = **能力探测**(恒空的 `WHERE 1=0` 读)+ **方言的缺列错误码**(判据属主 `sql-errors.ts` 的
379
401
  * {@link isMissingColumnError});其余错误**原样 rethrow**,一个字都不加工 —— 一句破坏性的
380
- * 「去 DROP TABLE」指路比它要挡的缺陷更贵(#340 那两轮收窄的结论逐字继承)。
402
+ * 「去 DROP TABLE」指路比它要挡的缺陷更贵([ref] 那两轮收窄的结论逐字继承)。
381
403
  *
382
404
  * 🔴 位置与两条先例同款:**不在** `ensureSchema` 里(那条通道的契约是「只发 CREATE」,有运行时门看着),
383
405
  * 放在 DDL 之后、任何路由装配之前;且**只在流内审批协议真会上场时**跑(判据 = 与协调器同一个符号
@@ -392,7 +414,7 @@ export declare class SqlApprovalAskStore implements ApprovalAskStore {
392
414
  constructor(db: SqlDriver);
393
415
  private q;
394
416
  private json;
395
- /** 唯一键冲突判别 —— 判据属主 = `sql-errors.ts`(A-032 P1-①)。`decideAsk` 用它把 `(task_id,
417
+ /** 唯一键冲突判别 —— 判据属主 = `sql-errors.ts`([ref] P1-①)。`decideAsk` 用它把 `(task_id,
396
418
  * idempotency_key)` 撞键翻成 typed 的 `idempotency_conflict` 臂,不让驱动错误对象漏给消费层;
397
419
  * 旧形 tidb 臂只认 errno,只带 `code` 的驱动错误会漏判成"真障碍"。 */
398
420
  private isDupKey;
@@ -71,6 +71,10 @@ export const TIDB_APPROVAL_ASK_STATEMENTS = [
71
71
  decision VARCHAR(16) NULL,
72
72
  decision_actor TEXT NULL,
73
73
  decision_note TEXT NULL,
74
+ -- updated_input(S-26 / #304,A-054.15 收口):人批准时带的 ctrl+g 编辑实参,JSON 文本,与决议同一条
75
+ -- UPDATE 原子落列;NULL = 没带编辑(与 JSON "null" = 编辑成 null 分家)。LONGTEXT 照 card_json 先例:
76
+ -- 编辑实参是整只工具入参,VARCHAR/TEXT 会造静默截断面。语义三态与读法见 AskRow.updatedInput 顶注。
77
+ updated_input LONGTEXT NULL,
74
78
  decided_at_ms BIGINT NULL,
75
79
  denied_reason VARCHAR(64) NULL,
76
80
  gate_token VARCHAR(120) NULL,
@@ -140,6 +144,8 @@ export async function ensurePgApprovalAskSchema(q) {
140
144
  decision VARCHAR(16) COLLATE "C",
141
145
  decision_actor TEXT COLLATE "C",
142
146
  decision_note TEXT COLLATE "C",
147
+ -- updated_input(S-26 / #304)—— MySQL 孪生逐字同形(语义/类型理由见那侧行内注;PG TEXT 无长度上限)。
148
+ updated_input TEXT COLLATE "C",
143
149
  decided_at_ms BIGINT,
144
150
  denied_reason VARCHAR(64) COLLATE "C",
145
151
  gate_token VARCHAR(120) COLLATE "C",
@@ -165,15 +171,16 @@ export async function ensurePgApprovalAskSchema(q) {
165
171
  }
166
172
  export async function assertApprovalAskRuleMaterialSchema(query, dialect) {
167
173
  try {
168
- await query(`SELECT rule_command, rule_scope_root FROM ${APPROVAL_ASK_TABLE} WHERE 1=0`);
174
+ await query(`SELECT rule_command, rule_scope_root, updated_input FROM ${APPROVAL_ASK_TABLE} WHERE 1=0`);
169
175
  }
170
176
  catch (err) {
171
177
  if (!isMissingColumnError(err, dialect))
172
178
  throw err;
173
- throw new Error(`${APPROVAL_ASK_TABLE} is missing the #363 rule-material columns (rule_command / rule_scope_root) — refusing to start. ` +
179
+ throw new Error(`${APPROVAL_ASK_TABLE} is missing the #363 rule-material columns (rule_command / rule_scope_root) and/or the S-26 edited-input column (updated_input) — refusing to start. ` +
174
180
  `A parked approval's late decision can now carry \`persistRule\` ("don't ask again"), and the row is where the ` +
175
- `adjudicated command and the project root of the authorization site live; every ask-row write and read names ` +
176
- `both columns unconditionally, so on this table the whole in-stream approval protocol degrades silently (no card ` +
181
+ `adjudicated command and the project root of the authorization site live; a decision's edited input (ctrl+g) is ` +
182
+ `persisted on the row too, so a replica that does not hold the waiting leg replays the approved bytes; every ask-row ` +
183
+ `write and read names these columns unconditionally, so on this table the whole in-stream approval protocol degrades silently (no card ` +
177
184
  `is persisted, the replay list stays empty, late decisions 404) while /v1/capabilities still reports it active. ` +
178
185
  `This repository ships no ALTER TABLE migrations, so the table must be recreated: run ` +
179
186
  `\`DROP TABLE ${APPROVAL_ASK_TABLE}; DROP TABLE ${APPROVAL_BATCH_TABLE};\` on the ` +
@@ -185,7 +192,7 @@ export async function assertApprovalAskRuleMaterialSchema(query, dialect) {
185
192
  }
186
193
  }
187
194
  const ASK_COLS = "ask_id, task_id, source_task_id, session_id, owner, batch_id, tool_call_id, leg_key, parent_tool_call_id, bound_input_hash, state, " +
188
- "provisional, rev, decision, decision_actor, decision_note, decided_at_ms, denied_reason, gate_token, " +
195
+ "provisional, rev, decision, decision_actor, decision_note, updated_input, decided_at_ms, denied_reason, gate_token, " +
189
196
  "gate_bound_call_id, gate_bound_input_hash, idempotency_key, card_json, rule_command, rule_scope_root, schema_version, expires_at_ms, " +
190
197
  "created_at_ms, updated_at_ms";
191
198
  const BATCH_COLS = "batch_id, task_id, state, bound_ask_id, rev, created_at_ms, updated_at_ms";
@@ -219,6 +226,7 @@ function mapAskRow(r) {
219
226
  decision: strOrNull(r.decision) ?? null,
220
227
  decisionActor: r.decision_actor == null ? null : parseJsonColumn(r.decision_actor),
221
228
  decisionNote: strOrNull(r.decision_note),
229
+ ...(r.updated_input == null ? {} : { updatedInput: parseJsonColumn(r.updated_input) }),
222
230
  decidedAtMs: numOrNull(r.decided_at_ms),
223
231
  deniedReason: strOrNull(r.denied_reason),
224
232
  gateToken: strOrNull(r.gate_token),
@@ -368,7 +376,16 @@ export class SqlApprovalAskStore {
368
376
  }
369
377
  let askRes;
370
378
  try {
371
- askRes = await conn.query(this.q(`UPDATE ${APPROVAL_ASK_TABLE} SET state='DECIDED', decision=?, decision_actor=?, decision_note=?, decided_at_ms=?, idempotency_key=?, rev=rev+1, updated_at_ms=? WHERE ask_id=? AND state='STREAM_PENDING'`, `UPDATE ${APPROVAL_ASK_TABLE} SET state='DECIDED', decision=$1, decision_actor=$2, decision_note=$3, decided_at_ms=$4, idempotency_key=$5, rev=rev+1, updated_at_ms=$6 WHERE ask_id=$7 AND state='STREAM_PENDING'`), [decision.decision, decision.decisionActor == null ? null : this.json(decision.decisionActor), decision.decisionNote ?? null, now, decision.idempotencyKey ?? null, now, askId]);
379
+ askRes = await conn.query(this.q(`UPDATE ${APPROVAL_ASK_TABLE} SET state='DECIDED', decision=?, decision_actor=?, decision_note=?, updated_input=?, decided_at_ms=?, idempotency_key=?, rev=rev+1, updated_at_ms=? WHERE ask_id=? AND state='STREAM_PENDING'`, `UPDATE ${APPROVAL_ASK_TABLE} SET state='DECIDED', decision=$1, decision_actor=$2, decision_note=$3, updated_input=$4, decided_at_ms=$5, idempotency_key=$6, rev=rev+1, updated_at_ms=$7 WHERE ask_id=$8 AND state='STREAM_PENDING'`), [
380
+ decision.decision,
381
+ decision.decisionActor == null ? null : this.json(decision.decisionActor),
382
+ decision.decisionNote ?? null,
383
+ decision.updatedInput === undefined ? null : this.json(decision.updatedInput),
384
+ now,
385
+ decision.idempotencyKey ?? null,
386
+ now,
387
+ askId,
388
+ ]);
372
389
  }
373
390
  catch (err) {
374
391
  if (this.isDupKey(err)) {
@@ -0,0 +1,23 @@
1
+ /**
2
+ * [ref] 件1(codex R2-[high] 一)—— 决议载荷的比对指纹:`[updatedInput, answer, reason]` 三件的规范串。
3
+ *
4
+ * 为什么是指纹而不是把三件原样交出来:`updatedInput` 可能携人写的命令原文/密钥形字节,而本读口的
5
+ * 契约是「窄读、非凭据面」—— 交指纹够比对,也不给任何调用点把它误投上 wire 的机会。
6
+ *
7
+ * 🔴 **必须是 canonical(键序无关)**,不是裸 `JSON.stringify`(codex R3-[high] 二,验真后修):行侧那份
8
+ * 载荷是从 `JSON`/`JSONB` 列**回读**的,而 **PG 的 jsonb 不保留输入键序**(它按自己的规则重排)⇒ 客户端
9
+ * 逐字重发原 body 时,请求侧按原键序、行侧按库的键序,裸 stringify 出来的两串不等 ⇒ 一次**合法重试**
10
+ * 被误拒成 404。方向虽保守(不是谎报成功),但那正是本件要修的那个场景,所以指纹按**递归键排序 +
11
+ * 数组保序**铸(见 {@link canonicalFingerprintJson})。
12
+ *
13
+ * 缺席一律折 `null` 哨兵(不是省位):`{updatedInput: undefined}` 与「没有这个键」在本比对里是同一件事。
14
+ * ⚠️ 调用方**必须**按 outcome 铸点的在场规则喂参(`updatedInput` 只在 approve 上、`reason` 走真值判)——
15
+ * 铸点丢掉的字节行上就没有,请求侧多喂一件会把一次合法重试误判成「不同的决议」。
16
+ * 序列化失败(循环引用/BigInt 等)⇒ `null` = 判别不出,调用方据此拒绝回放(fail-closed)。
17
+ */
18
+ export declare function approvalPayloadFingerprint(v: {
19
+ updatedInput?: unknown;
20
+ answer?: unknown;
21
+ reason?: string;
22
+ }): string | null;
23
+ //# sourceMappingURL=approval-payload-fingerprint.d.ts.map