@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.
- package/USAGE.md +7 -1
- package/dist/adoption/plan.d.ts +3 -3
- package/dist/adoption/quiesce.d.ts +1 -1
- package/dist/adoption/sql.d.ts +2 -2
- package/dist/adoption/wire.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +2 -2
- package/dist/approval-card.d.ts +18 -18
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval-hmac.d.ts +2 -2
- package/dist/approval-reconciler.d.ts +14 -14
- package/dist/approval.d.ts +2 -2
- package/dist/audit.d.ts +4 -4
- package/dist/auth-keys.d.ts +6 -6
- package/dist/bench/l8/artifact.d.ts +6 -1
- package/dist/bench/l8/artifact.js +2 -27
- package/dist/bench/l8/escape.d.ts +3 -3
- package/dist/bench/l8/index.d.ts +1 -1
- package/dist/bench/s1/arms.d.ts +3 -3
- package/dist/bench/s1/oracle.d.ts +2 -2
- package/dist/bench/s1/reviewer.d.ts +1 -1
- package/dist/bench/s1/row.d.ts +5 -5
- package/dist/bench/s1/runner-ctx.d.ts +3 -3
- package/dist/boot/config-center.d.ts +14 -7
- package/dist/boot/config-center.js +4 -2
- package/dist/boot/coordinators.d.ts +4 -4
- package/dist/boot/crash-last.d.ts +1 -1
- package/dist/boot/device-lane.d.ts +3 -3
- package/dist/boot/engine-lease.d.ts +4 -4
- package/dist/boot/governance-seams.d.ts +5 -5
- package/dist/boot/leader.d.ts +5 -5
- package/dist/boot/leader.js +2 -0
- package/dist/boot/limit-sync.d.ts +1 -1
- package/dist/boot/memory-boundary.d.ts +5 -5
- package/dist/boot/memory-consolidation.d.ts +8 -2
- package/dist/boot/memory-consolidation.js +1 -0
- package/dist/boot/org-memory.d.ts +5 -5
- package/dist/boot/parked-revive-gate.d.ts +6 -6
- package/dist/boot/permission-rules-audit.d.ts +2 -2
- package/dist/boot/reapers.d.ts +8 -8
- package/dist/boot/resolve-spec.d.ts +4 -4
- package/dist/boot/resolve-spec.js +1 -3
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.d.ts +53 -27
- package/dist/boot/runner-deps.js +16 -9
- package/dist/boot/runtime-caps.d.ts +4 -4
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/shutdown.d.ts +10 -10
- package/dist/boot/shutdown.js +1 -1
- package/dist/boot/side-query-lane.d.ts +14 -14
- package/dist/boot/stores.js +5 -0
- package/dist/boot/task-list-lane.d.ts +3 -3
- package/dist/boot/webfetch-summarize-lane.d.ts +9 -9
- package/dist/boot/workflow-orchestration.d.ts +1 -1
- package/dist/bounded-session-map.d.ts +1 -1
- package/dist/brain.d.ts +3 -3
- package/dist/budget.d.ts +3 -3
- package/dist/canonical-json.d.ts +53 -0
- package/dist/canonical-json.js +48 -0
- package/dist/capabilities/center-prompts.d.ts +13 -13
- package/dist/capabilities/collab-workflows.d.ts +1 -1
- package/dist/capabilities/hands-lane.d.ts +4 -4
- package/dist/capabilities/memory-notice.d.ts +4 -4
- package/dist/capabilities/prompt.d.ts +2 -2
- package/dist/capabilities/sandbox-file-send.d.ts +2 -2
- package/dist/capabilities/scenarios.d.ts +16 -16
- package/dist/capabilities/skills.d.ts +1 -1
- package/dist/capabilities/team.d.ts +13 -12
- package/dist/capabilities/tool-defer.d.ts +6 -6
- package/dist/config-catalog.d.ts +139 -0
- package/dist/config-catalog.js +556 -0
- package/dist/config-center/apply-effective.d.ts +42 -30
- package/dist/config-center/apply-effective.js +69 -62
- package/dist/config-center/apply-ledger.d.ts +6 -6
- package/dist/config-center/effective-keys.d.ts +30 -0
- package/dist/config-center/effective-keys.js +49 -0
- package/dist/config-center/facade.d.ts +6 -5
- package/dist/config-center/facade.js +1 -1
- package/dist/config-center/hot-keys-registry.d.ts +2 -2
- package/dist/config-center/http-client.d.ts +5 -5
- package/dist/config-center/mcp-revocation.d.ts +6 -4
- package/dist/config-center/mcp-revocation.js +2 -12
- package/dist/config-center/restart-signal.d.ts +11 -1
- package/dist/config-center/restart-signal.js +4 -10
- package/dist/config-center/skills-mcp.d.ts +2 -2
- package/dist/config-center/stage-limits.d.ts +3 -3
- package/dist/config-center/types.d.ts +42 -59
- package/dist/config-invariants.d.ts +1 -1
- package/dist/config-lkg.js +7 -1
- package/dist/config-provider.d.ts +2 -2
- package/dist/config-provider.js +1 -1
- package/dist/config-types.d.ts +140 -132
- package/dist/config.d.ts +22 -22
- package/dist/config.js +2 -1
- package/dist/degenerate-instrument.d.ts +1 -1
- package/dist/deployment-governance.d.ts +13 -13
- package/dist/device-enrollment.d.ts +5 -3
- package/dist/device-store.d.ts +17 -3
- package/dist/device-store.js +2 -0
- package/dist/device-ws-hub.d.ts +10 -5
- package/dist/device-ws-hub.js +25 -5
- package/dist/device-ws-protocol.d.ts +3 -3
- package/dist/digest-form.d.ts +1 -1
- package/dist/elicitation.d.ts +1 -1
- package/dist/env-facts.d.ts +7 -7
- package/dist/execution-lane-caps.d.ts +5 -5
- package/dist/fleet/fleet-bus.d.ts +53 -53
- package/dist/fleet/fleet-reconciler.d.ts +2 -2
- package/dist/fleet/fleet-terminal-window.d.ts +1 -1
- package/dist/fleet/subagent-tail-bus.d.ts +3 -3
- package/dist/fleet-client.d.ts +3 -3
- package/dist/fleet-lease.d.ts +1 -1
- package/dist/hooks/branch-transcript.d.ts +2 -2
- package/dist/hooks/cc-agent-hook-prompt.d.ts +2 -2
- package/dist/hooks/cc-stop-prompt.d.ts +2 -2
- package/dist/hooks/hook-llm.d.ts +1 -1
- package/dist/hooks/hook-runner.d.ts +5 -5
- package/dist/http/active-run-conflict.d.ts +31 -33
- package/dist/http/active-run-conflict.js +4 -2
- package/dist/http/route-ctx.d.ts +22 -22
- package/dist/http/routes/a2a-serve.d.ts +2 -2
- package/dist/http/routes/admin-config-refresh.d.ts +1 -1
- package/dist/http/routes/admin-drain.d.ts +4 -4
- package/dist/http/routes/admin-memory-optout.d.ts +5 -5
- package/dist/http/routes/adoption.d.ts +1 -1
- package/dist/http/routes/agents-roster.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.d.ts +6 -6
- package/dist/http/routes/approvals-assistant.js +4 -1
- package/dist/http/routes/capabilities.d.ts +1 -1
- package/dist/http/routes/capabilities.js +1 -0
- package/dist/http/routes/config-catalog.d.ts +28 -0
- package/dist/http/routes/config-catalog.js +42 -0
- package/dist/http/routes/diagnostics.d.ts +2 -2
- package/dist/http/routes/fleet.d.ts +1 -1
- package/dist/http/routes/images.d.ts +1 -1
- package/dist/http/routes/leader.d.ts +1 -1
- package/dist/http/routes/memory-bundle.d.ts +4 -4
- package/dist/http/routes/memory-compliance.d.ts +7 -7
- package/dist/http/routes/memory-consolidation.d.ts +1 -1
- package/dist/http/routes/memory-origin.d.ts +9 -9
- package/dist/http/routes/memory-policy.d.ts +3 -3
- package/dist/http/routes/notify-wake.d.ts +1 -1
- package/dist/http/routes/observability.d.ts +1 -1
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/rules.d.ts +3 -3
- package/dist/http/routes/run-memory-capture.d.ts +1 -1
- package/dist/http/routes/runs.d.ts +3 -3
- package/dist/http/routes/runs.js +12 -17
- package/dist/http/routes/session-sync.d.ts +2 -2
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +9 -1
- package/dist/http/routes/sessions.js +60 -0
- package/dist/http/routes/shared-memory.d.ts +1 -1
- package/dist/http/routes/side-query.d.ts +1 -1
- package/dist/http/routes/tasks.d.ts +1 -1
- package/dist/http/routes/trace-usage.d.ts +1 -1
- package/dist/http/routes/workflows.d.ts +1 -1
- package/dist/http/run-meta.d.ts +1 -1
- package/dist/http/send.d.ts +6 -6
- package/dist/http/server.d.ts +84 -67
- package/dist/http/server.js +39 -10
- package/dist/http/sse-lifecycle.d.ts +1 -1
- package/dist/http/sse-log.d.ts +6 -6
- package/dist/http/verify-rounds.d.ts +3 -3
- package/dist/http/wire-gate.d.ts +2 -2
- package/dist/http/wire-types.d.ts +57 -38
- package/dist/key-resolver.d.ts +1 -1
- package/dist/leader/diffout.d.ts +2 -2
- package/dist/leader/diffup.d.ts +1 -1
- package/dist/leader/endpoint.d.ts +1 -1
- package/dist/leader/fanout.d.ts +6 -6
- package/dist/leader/grader-env-factory.d.ts +1 -1
- package/dist/leader/leader.d.ts +12 -12
- package/dist/leader/merge.d.ts +3 -3
- package/dist/leader/planner.d.ts +5 -5
- package/dist/leader/repair-oracle.d.ts +1 -1
- package/dist/leader/wire.d.ts +21 -9
- package/dist/leader/wire.js +6 -5
- package/dist/lsp/manager.d.ts +2 -2
- package/dist/lsp/types.d.ts +1 -1
- package/dist/lsp/ws-transport.d.ts +2 -2
- package/dist/main.js +12 -2
- package/dist/mcp-content-origin.d.ts +1 -1
- package/dist/memory-bundle-engine.d.ts +5 -3
- package/dist/memory-bundle-engine.js +2 -2
- package/dist/memory-operator-faces.d.ts +41 -11
- package/dist/memory-operator-faces.js +12 -0
- package/dist/memory-origin-fence.d.ts +1 -1
- package/dist/memory-origin-fence.js +2 -13
- package/dist/memory-posture.d.ts +6 -6
- package/dist/memory-scope.d.ts +7 -7
- package/dist/model-select.d.ts +5 -5
- package/dist/observability/cost-quota.d.ts +6 -6
- package/dist/observability/cost-taxonomy.d.ts +2 -2
- package/dist/observability/fail-open.d.ts +17 -5
- package/dist/observability/fail-open.js +16 -4
- package/dist/observability/metrics.d.ts +1 -1
- package/dist/observability/prompt-manifest.d.ts +8 -8
- package/dist/observability/rate-limit.d.ts +2 -2
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/tool-trace.d.ts +1 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +6 -6
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +1 -1
- package/dist/orchestration/subagent-steer.d.ts +3 -3
- package/dist/orchestration/workflow-agent-steer.d.ts +1 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +6 -6
- package/dist/orchestration/workflow-notify-journal.d.ts +6 -6
- package/dist/parent-watch.d.ts +1 -1
- package/dist/parked-decide.d.ts +11 -11
- package/dist/plan-cache-probe.d.ts +1 -1
- package/dist/plugins/adoption-log-sql.d.ts +4 -4
- package/dist/plugins/approval-ask-store-memory.d.ts +1 -1
- package/dist/plugins/approval-ask-store-memory.js +12 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +39 -17
- package/dist/plugins/approval-ask-store-sql.js +23 -6
- package/dist/plugins/approval-payload-fingerprint.d.ts +23 -0
- package/dist/plugins/approval-payload-fingerprint.js +23 -0
- package/dist/plugins/background-agent-store-sql.d.ts +8 -8
- package/dist/plugins/background-shell-support.d.ts +12 -12
- package/dist/plugins/blob-backend.d.ts +3 -3
- package/dist/plugins/breaker-state-sql.d.ts +3 -3
- package/dist/plugins/caching-session-store.d.ts +6 -6
- package/dist/plugins/checkpoint-store-sql.d.ts +162 -66
- package/dist/plugins/checkpoint-store-sql.js +76 -33
- package/dist/plugins/device-store-sql.d.ts +4 -3
- package/dist/plugins/e2b-orphan-reclaim.d.ts +3 -3
- package/dist/plugins/file-history-store-sql.d.ts +9 -8
- package/dist/plugins/file-run-store.d.ts +27 -27
- package/dist/plugins/fork-routing-session-store.d.ts +9 -9
- package/dist/plugins/image-bake-store-sql.d.ts +1 -1
- package/dist/plugins/image-index-sql.d.ts +2 -2
- package/dist/plugins/k8s-bg-scripts.d.ts +1 -1
- package/dist/plugins/k8s-exec-protocol.d.ts +1 -1
- package/dist/plugins/leader-run-store-sql.d.ts +1 -1
- package/dist/plugins/local-checkpoint-store.d.ts +26 -17
- package/dist/plugins/local-checkpoint-store.js +21 -11
- package/dist/plugins/local-session-store.d.ts +5 -5
- package/dist/plugins/mailbox-store-sql.d.ts +6 -6
- package/dist/plugins/memory-embedder-fingerprint.d.ts +2 -2
- package/dist/plugins/memory-engine-pg.d.ts +1 -1
- package/dist/plugins/memory-engine-tidb.d.ts +1 -1
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +10 -10
- package/dist/plugins/memory-origin-law.d.ts +13 -13
- package/dist/plugins/memory-run-store.d.ts +12 -12
- package/dist/plugins/outcome-ledger-sql.d.ts +3 -3
- package/dist/plugins/permission-rule-store-file.d.ts +3 -3
- package/dist/plugins/permission-rule-store-sql.d.ts +38 -33
- package/dist/plugins/permission-rule-store-sql.js +7 -12
- package/dist/plugins/pg-cost-quota.d.ts +2 -2
- package/dist/plugins/pg-pool.d.ts +29 -2
- package/dist/plugins/pg-pool.js +50 -2
- package/dist/plugins/pg-query.d.ts +1 -1
- package/dist/plugins/pg-rate-limiter.d.ts +2 -2
- package/dist/plugins/pg-session-storage.d.ts +9 -9
- package/dist/plugins/remote-env-adb.d.ts +1 -1
- package/dist/plugins/remote-env-device.d.ts +6 -4
- package/dist/plugins/remote-env-device.js +4 -1
- package/dist/plugins/remote-env-e2b.d.ts +11 -11
- package/dist/plugins/remote-env-file-error.d.ts +2 -2
- package/dist/plugins/remote-env-host.d.ts +10 -10
- package/dist/plugins/remote-env-k8s.d.ts +7 -7
- package/dist/plugins/remote-env-local-docker.d.ts +1 -1
- package/dist/plugins/remote-env-ssh.d.ts +9 -9
- package/dist/plugins/remote-scratchpad.d.ts +1 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.d.ts +2 -2
- package/dist/plugins/retention-store-sql.d.ts +11 -11
- package/dist/plugins/roster-store-sql.d.ts +6 -8
- package/dist/plugins/run-store-sql.d.ts +12 -12
- package/dist/plugins/scheduler-support.d.ts +1 -1
- package/dist/plugins/send-user-file.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.d.ts +99 -0
- package/dist/plugins/session-capture-record-store-sql.js +110 -0
- package/dist/plugins/session-placement.d.ts +1 -1
- package/dist/plugins/session-policy-store-sql.d.ts +2 -2
- package/dist/plugins/session-store.d.ts +3 -3
- package/dist/plugins/shared-memory-store-sql.d.ts +5 -5
- package/dist/plugins/sql-driver.d.ts +7 -7
- package/dist/plugins/sql-errors.d.ts +2 -2
- package/dist/plugins/sql-escape.d.ts +1 -1
- package/dist/plugins/sql-row-helpers.d.ts +1 -1
- package/dist/plugins/store-backend.d.ts +32 -19
- package/dist/plugins/store-backend.js +5 -1
- package/dist/plugins/store-contracts.d.ts +9 -9
- package/dist/plugins/task-list-store-sql.d.ts +3 -3
- package/dist/plugins/tidb-cost-quota.d.ts +3 -3
- package/dist/plugins/tidb-pool.d.ts +13 -0
- package/dist/plugins/tidb-pool.js +9 -0
- package/dist/plugins/tidb-rate-limiter.d.ts +2 -2
- package/dist/plugins/tidb-session-storage.d.ts +2 -2
- package/dist/plugins/tidb-session-store.d.ts +11 -11
- package/dist/plugins/tool-result-store-sql.d.ts +8 -8
- package/dist/plugins/usage-window-store-sql.d.ts +3 -3
- package/dist/plugins/web-search.d.ts +7 -7
- package/dist/plugins/workflow-journal-store-sql.d.ts +6 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +1 -1
- package/dist/plugins/write-behind-counter.d.ts +6 -6
- package/dist/principal-jwt.d.ts +2 -2
- package/dist/project-memory.d.ts +1 -1
- package/dist/prompts-domain-validate.d.ts +8 -8
- package/dist/question.d.ts +3 -3
- package/dist/resource-suspend.d.ts +4 -4
- package/dist/resource-window.d.ts +3 -3
- package/dist/router/route-orchestration.d.ts +1 -1
- package/dist/rules-consent.d.ts +48 -40
- package/dist/run-local.d.ts +5 -5
- package/dist/runs.d.ts +19 -19
- package/dist/runtime-caps-resolver.d.ts +6 -6
- package/dist/runtime-governance.d.ts +11 -7
- package/dist/runtime-governance.js +23 -1
- package/dist/security.d.ts +13 -13
- package/dist/session-leaf-bus.d.ts +1 -1
- package/dist/session-sync-content.d.ts +4 -4
- package/dist/session-sync-kernel.d.ts +2 -2
- package/dist/session-sync.d.ts +13 -13
- package/dist/session-titler.d.ts +1 -1
- package/dist/session-watch.d.ts +3 -3
- package/dist/shared-memory-scope-authorizer.d.ts +4 -4
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/spec-fields.d.ts +20 -20
- package/dist/ssh-host-key.d.ts +5 -5
- package/dist/store-live-probe.d.ts +2 -2
- package/dist/task-cwd.d.ts +11 -11
- package/dist/task-mcp.d.ts +5 -5
- package/dist/task-settings.d.ts +35 -35
- package/dist/task-workflow.d.ts +3 -3
- package/dist/text-bidi.d.ts +1 -1
- package/dist/tool-approval.d.ts +186 -182
- package/dist/tool-approval.js +247 -120
- package/dist/trace/core-keyset-guard.d.ts +19 -5
- package/dist/trace/engine-notice-wire.d.ts +7 -7
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/injection-tier.d.ts +11 -21
- package/dist/trace/injection-tier.js +3 -4
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/ledger-sink.d.ts +7 -7
- package/dist/trace/project.d.ts +31 -30
- package/dist/trace/project.js +1 -0
- package/dist/turn-activity.d.ts +4 -4
- package/dist/usage-analytics.d.ts +1 -1
- package/dist/wall-clock-jump-guard.d.ts +3 -3
- 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 ([
|
|
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
|
-
/** [
|
|
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
|
-
* 坏值**响亮拒**(
|
|
68
|
+
* 坏值**响亮拒**([ref] 立律:旋钮坏值禁静默回默认)。0/负数不是「禁用」:无界 runaway 脚本会吞掉共享
|
|
69
69
|
* 副本的事件循环/堆,禁用臂刻意不提供——要更久就把值配大。模块加载时读一次(坏 env = boot fail-loud)。
|
|
70
|
-
* 超时终态分型(partial vs failed,[
|
|
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 (
|
|
78
|
-
* only `unhandledRejection` listener in a real boot. `src/boot/shutdown.ts` installs one at boot (
|
|
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 (
|
|
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) +
|
|
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 (
|
|
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 (
|
|
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 [
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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 [
|
|
102
|
-
* (bash/monitor terminal/retain 降级)保持单周期旧键=同键第二帧吞,诚实语义。[
|
|
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([
|
|
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
|
-
*
|
|
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 ([
|
|
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 ([
|
|
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 ([
|
|
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
|
-
/** [
|
|
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
|
-
/** [
|
|
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
|
-
/** [
|
|
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
|
package/dist/parent-watch.d.ts
CHANGED
package/dist/parked-decide.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 件3d `/decide` 消费 parked 后台子代——server 半场辅件(设计稿:sema-internal
|
|
3
|
-
* server/docs/DECIDE-PARKED-DESIGN.md;黑板 [
|
|
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 同实例天然成立([
|
|
40
|
+
* subRunner/bg opts/checkpointStore 同实例天然成立([ref] 设计稿 §4)。 */
|
|
41
41
|
reviveTool: ToolSpec;
|
|
42
|
-
/** revive args 的 `subagent_type` 成员性判定集([
|
|
42
|
+
/** revive args 的 `subagent_type` 成员性判定集([ref] Q1 修正:非 roster 成员必须省略,否则
|
|
43
43
|
* unknown subagent_type 拒;字面比对 general-purpose 在 roster 撞名时会错省)。缺省空集=恒省略。 */
|
|
44
44
|
knownAgentTypes?: ReadonlySet<string>;
|
|
45
|
-
/** [
|
|
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**(
|
|
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
|
-
/**
|
|
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 执行器([
|
|
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
|
-
/**
|
|
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 赎回腿(
|
|
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}`,[
|
|
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
|
-
* ([
|
|
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
|
|
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
|
-
*
|
|
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
|
-
* 把弧锁名限定到**一个库**的键空间(
|
|
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
|
-
* 本连接所在**数据库**的名字 = 弧锁的键空间限定符(
|
|
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} 限定到本库之后的形(
|
|
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` ——
|
|
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
|
-
* 流内审批协议(
|
|
3
|
-
* (`TiDBApprovalAskStore` / `PgApprovalAskStore`,SINGLE-FILE DUAL-DIALECT,
|
|
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
|
-
* ── 方言差异(显式写在每个调用点,
|
|
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`, 因果下界)三维(
|
|
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
|
-
*
|
|
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
|
-
*
|
|
113
|
-
*
|
|
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
|
-
/**
|
|
155
|
+
/** [ref] 规则车道素材(语义与「为什么是行上的列」见 {@link AskRow.ruleCommand})。缺席 ⇒ 列 NULL ⇒
|
|
138
156
|
* 这条行上的迟到决议对 `persistRule` 响亮拒(`rule_material_absent`),绝不猜命令。 */
|
|
139
157
|
ruleCommand?: string | null;
|
|
140
|
-
/**
|
|
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` 的产出 —— 行 **+ 这一次调用到底插没插**(
|
|
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
|
-
*
|
|
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
|
-
* ── 列宽的**测量依据**(
|
|
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
|
-
*
|
|
367
|
-
*
|
|
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
|
-
* 没有这道断言,运维得不到**任何**「这次升级必须重建表」的信号 —— 正是
|
|
398
|
+
* 没有这道断言,运维得不到**任何**「这次升级必须重建表」的信号 —— 正是 [ref]「禁静默降级」要挡的形。
|
|
377
399
|
*
|
|
378
400
|
* 判据 = **能力探测**(恒空的 `WHERE 1=0` 读)+ **方言的缺列错误码**(判据属主 `sql-errors.ts` 的
|
|
379
401
|
* {@link isMissingColumnError});其余错误**原样 rethrow**,一个字都不加工 —— 一句破坏性的
|
|
380
|
-
* 「去 DROP TABLE」指路比它要挡的缺陷更贵(
|
|
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`(
|
|
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;
|
|
176
|
-
`
|
|
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,
|
|
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
|