@sema-agent/server 7.51.0 → 7.52.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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +83 -20
- package/dist/adoption/plan.d.ts +4 -4
- package/dist/adoption/plan.js +11 -0
- package/dist/approval-card.d.ts +26 -2
- package/dist/approval-card.js +9 -0
- package/dist/approval-hmac.d.ts +1 -1
- package/dist/approval-reconciler.d.ts +2 -2
- package/dist/approval-reconciler.js +1 -1
- package/dist/bench/l8/artifact.d.ts +1 -1
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/live-deps.d.ts +1 -1
- package/dist/bench/s1/oracle.d.ts +1 -1
- package/dist/bench/s1/row.d.ts +1 -1
- package/dist/boot/budget-tracing.d.ts +1 -1
- package/dist/boot/budget-tracing.js +2 -5
- package/dist/boot/coordinators.js +3 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +1 -1
- package/dist/boot/engine-lease.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-consolidation.d.ts +6 -6
- package/dist/boot/org-memory.d.ts +1 -1
- package/dist/boot/parked-revive-gate.d.ts +3 -3
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/reapers.js +17 -4
- package/dist/boot/resolve-spec.d.ts +12 -0
- package/dist/boot/resolve-spec.js +29 -7
- package/dist/boot/retention-lane.d.ts +2 -2
- package/dist/boot/runner-deps.d.ts +17 -7
- package/dist/boot/runner-deps.js +4 -2
- package/dist/boot/runtime-caps.d.ts +23 -0
- package/dist/boot/runtime-caps.js +24 -2
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +14 -3
- package/dist/boot/stores.js +31 -1
- package/dist/boot/task-list-lane.d.ts +2 -2
- package/dist/brain.js +51 -31
- package/dist/budget.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/collab-workflows.d.ts +1 -1
- package/dist/capabilities/hands-lane.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +3 -3
- package/dist/capabilities/skills.d.ts +1 -1
- package/dist/config-center/hot-keys-registry.js +5 -0
- package/dist/config-center/http-client.d.ts +2 -2
- package/dist/config-center/read-face.d.ts +1 -1
- package/dist/config-center/restart-signal.d.ts +1 -1
- package/dist/config-types.d.ts +78 -18
- package/dist/config.js +45 -10
- package/dist/deployment-governance.d.ts +1 -1
- package/dist/device-enrollment.d.ts +2 -2
- package/dist/device-store.d.ts +3 -3
- package/dist/device-ws-protocol.d.ts +2 -2
- package/dist/env-facts.d.ts +1 -1
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/fleet-bus.d.ts +1 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/fleet-terminal-window.d.ts +1 -1
- package/dist/http/active-run-conflict.d.ts +2 -2
- package/dist/http/principal-gate.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +24 -4
- package/dist/http/routes/admin-memory-optout.d.ts +48 -0
- package/dist/http/routes/admin-memory-optout.js +75 -0
- package/dist/http/routes/agents-roster.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.js +21 -21
- package/dist/http/routes/capabilities.js +20 -9
- package/dist/http/routes/diagnostics.d.ts +1 -1
- package/dist/http/routes/leader.d.ts +1 -1
- package/dist/http/routes/memory-bundle.d.ts +1 -1
- package/dist/http/routes/memory-bundle.js +3 -1
- package/dist/http/routes/memory-compliance.d.ts +4 -4
- package/dist/http/routes/memory-origin.d.ts +4 -4
- package/dist/http/routes/memory-origin.js +3 -1
- package/dist/http/routes/memory-policy.js +6 -2
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/rules.d.ts +5 -2
- package/dist/http/routes/rules.js +84 -5
- package/dist/http/routes/run-memory-capture.d.ts +34 -0
- package/dist/http/routes/run-memory-capture.js +97 -0
- package/dist/http/routes/runs.d.ts +1 -0
- package/dist/http/routes/runs.js +212 -6
- package/dist/http/routes/session-sync.d.ts +4 -6
- package/dist/http/routes/session-sync.js +60 -47
- package/dist/http/routes/sessions.js +61 -188
- package/dist/http/routes/shared-memory.d.ts +1 -1
- package/dist/http/routes/tasks.js +1 -1
- package/dist/http/routes/workflows.js +19 -0
- package/dist/http/server.d.ts +35 -13
- package/dist/http/server.js +105 -12
- package/dist/http/verify-rounds.d.ts +1 -1
- package/dist/http/wire-types.d.ts +41 -8
- package/dist/leader/endpoint.d.ts +1 -1
- package/dist/leader/leader.d.ts +1 -1
- package/dist/leader/repair-oracle.d.ts +2 -2
- package/dist/leader/repair-oracle.js +1 -1
- package/dist/main.js +13 -6
- package/dist/memory-bundle-engine.d.ts +1 -1
- package/dist/memory-operator-faces.d.ts +5 -5
- package/dist/memory-origin-fence.d.ts +50 -0
- package/dist/memory-origin-fence.js +15 -0
- package/dist/memory-posture.d.ts +13 -1
- package/dist/memory-posture.js +1 -0
- package/dist/memory-scope.d.ts +6 -1
- package/dist/memory-scope.js +3 -2
- package/dist/model-select.d.ts +2 -2
- package/dist/observability/fail-open.d.ts +17 -5
- package/dist/observability/fail-open.js +17 -5
- package/dist/orchestration/hardened-vm-runner.d.ts +2 -2
- package/dist/orchestration/workflow-completion-inbox.d.ts +2 -2
- package/dist/plugins/background-shell-support.d.ts +2 -2
- package/dist/plugins/blob-backend.d.ts +7 -2
- package/dist/plugins/blob-backend.js +22 -18
- package/dist/plugins/caching-session-store.d.ts +7 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.d.ts +170 -0
- package/dist/plugins/file-history-store-sql.js +827 -0
- package/dist/plugins/file-run-store.d.ts +44 -5
- package/dist/plugins/file-run-store.js +85 -13
- package/dist/plugins/fork-routing-session-store.d.ts +1 -1
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/leader-run-store-sql.d.ts +1 -1
- package/dist/plugins/local-session-store.d.ts +9 -1
- package/dist/plugins/memory-embedder-fingerprint.d.ts +1 -1
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +139 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +157 -0
- package/dist/plugins/memory-origin-law.d.ts +2 -2
- package/dist/plugins/memory-run-store.d.ts +4 -3
- package/dist/plugins/memory-run-store.js +2 -1
- package/dist/plugins/permission-rule-store-file.d.ts +16 -6
- package/dist/plugins/permission-rule-store-file.js +77 -13
- package/dist/plugins/permission-rule-store-sql.d.ts +156 -8
- package/dist/plugins/permission-rule-store-sql.js +123 -21
- package/dist/plugins/pg-pool.js +59 -0
- package/dist/plugins/pg-safe-json.d.ts +1 -1
- package/dist/plugins/remote-env-device.d.ts +1 -1
- package/dist/plugins/remote-env-k8s.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.d.ts +3 -3
- package/dist/plugins/retention-store-sql.d.ts +7 -7
- package/dist/plugins/retention-store-sql.js +6 -0
- package/dist/plugins/run-store-sql.d.ts +9 -3
- package/dist/plugins/run-store-sql.js +2 -2
- package/dist/plugins/send-user-file.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +1 -1
- package/dist/plugins/sql-errors.d.ts +1 -1
- package/dist/plugins/store-backend.d.ts +59 -29
- package/dist/plugins/store-backend.js +75 -15
- package/dist/plugins/store-contracts.d.ts +5 -3
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/tidb-pool.js +59 -0
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/prompts-domain-validate.js +1 -1
- package/dist/resource-suspend.d.ts +1 -1
- package/dist/resource-window.d.ts +3 -3
- package/dist/rules-consent.d.ts +231 -9
- package/dist/rules-consent.js +411 -13
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +15 -1
- package/dist/runs.js +19 -0
- package/dist/runtime-caps-resolver.d.ts +36 -1
- package/dist/runtime-caps-resolver.js +25 -0
- package/dist/runtime-governance.d.ts +1 -1
- package/dist/security.d.ts +5 -5
- package/dist/security.js +1 -1
- package/dist/session-sync.d.ts +52 -37
- package/dist/session-sync.js +19 -16
- package/dist/shared-memory-scope-authorizer.d.ts +1 -1
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/spec-fields.d.ts +22 -1
- package/dist/spec-fields.js +11 -0
- package/dist/store-live-probe.d.ts +2 -2
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-settings.d.ts +3 -3
- package/dist/task-workflow.d.ts +1 -1
- package/dist/text-bidi.d.ts +2 -2
- package/dist/tool-approval.d.ts +191 -9
- package/dist/tool-approval.js +248 -29
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/engine-notice-wire.d.ts +6 -4
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/ledger-events.d.ts +1 -1
- package/dist/trace/ledger-sink.d.ts +2 -2
- package/dist/trace/project.d.ts +3 -2
- package/dist/trace/project.js +1 -0
- package/dist/turn-activity.d.ts +1 -1
- package/dist/wall-clock-jump-guard.d.ts +3 -3
- package/package.json +2 -2
- package/dist/http/tar.d.ts +0 -17
- package/dist/http/tar.js +0 -53
- package/dist/http/workspace-content.d.ts +0 -11
- package/dist/http/workspace-content.js +0 -20
- package/dist/plugins/file-snapshot-store-sql.d.ts +0 -170
- package/dist/plugins/file-snapshot-store-sql.js +0 -213
package/dist/tool-approval.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { IncomingMessage } from "node:http";
|
|
2
2
|
import { type AskRequest, type AskOutcome, type RuleOffer } from "@sema-agent/core";
|
|
3
3
|
import { type CardRulePersisted, type RuleConsentLane } from "./rules-consent.js";
|
|
4
|
-
import { type ApprovalRequestFrame, type ApprovalRevokeFrame, type RuleEvidenceProjection } from "./approval-card.js";
|
|
4
|
+
import { type RuleOffersAbsence, type ApprovalRequestFrame, type ApprovalRevokeFrame, type RuleEvidenceProjection } from "./approval-card.js";
|
|
5
5
|
import type { ApprovalAskStore } from "./plugins/approval-ask-store-sql.js";
|
|
6
6
|
import { type GovernanceAskMarks } from "./governance-ask-marks.js";
|
|
7
7
|
/** A-002.1:审批 gate kind 闭集(core gateMatch 的 `human`/`irreversible_ask` ↔ outcome.gate "policy_ask")。
|
|
@@ -13,6 +13,27 @@ export type ApprovalGateKind = (typeof APPROVAL_GATE_KINDS)[number];
|
|
|
13
13
|
export declare function isApprovalGateKind(k: string | undefined): k is ApprovalGateKind;
|
|
14
14
|
/** 两方言同形的 SQL IN 片段(值为闭集常量字面,无注入面)。 */
|
|
15
15
|
export declare const APPROVAL_GATE_KINDS_SQL_IN: string;
|
|
16
|
+
/**
|
|
17
|
+
* 🔴 S-43(案A)追记 F6 —— durable 回决口(`POST /v1/tasks/:taskId/asks/:askId/decision`)的 **200 体
|
|
18
|
+
* additive 判别位**:这次决议在**本副本**上有没有被一条活着的腿消费掉。
|
|
19
|
+
*
|
|
20
|
+
* 值只有一个词(`"absent"`),因为只有 absent 这一面需要披露:在场 = 「行判了,但本机没有任何东西
|
|
21
|
+
* 因此续跑」。反面(真被消费)不铸键 —— additive 只记真,与 `updatedInputForwarded`/`decisionNote`
|
|
22
|
+
* 的先例逐字同族。**缺席禁读作「有消费者」的证明**:老版本 server 从不发这个键。
|
|
23
|
+
*
|
|
24
|
+
* 成因三形(S-43 复审件3 补第三形):①持有悬挂 promise 的是**另一个副本**;②本副本重启后本地窗已空;
|
|
25
|
+
* ③**弃单墓碑守卫把素批准翻成 park**({@link ToolApprovalCoordinator.guardRowDerivedApprove}:本地腿
|
|
26
|
+
* 在场,但没有一条把这次 approve 当**放行**消费 —— 它们全部收成 park,人须经 durable 门再兑)。
|
|
27
|
+
* 三形的处置同一句:壳读 run 面判续跑没有,绝不把 200 无键当成「run 已续跑」的证明。
|
|
28
|
+
*
|
|
29
|
+
* 为什么不是 409/410(施工时的二选一,裁定写在这里):409/410 说的是「你的请求没有生效」,而这次决议
|
|
30
|
+
* **确实生效了**(行是 DECIDED,幂等回放读得到、审计面记得住)——把它渲成错误会让壳把一次成功的
|
|
31
|
+
* 人类决议当成失败去重试,而重试只会撞回幂等回放。200 + 机读披露是唯一同时诚实的形。
|
|
32
|
+
*
|
|
33
|
+
* 语义边界(禁扩读):它答的是「本副本此刻有没有活体消费者」,**不是**「这条 run 还活着吗」——持有
|
|
34
|
+
* 悬挂 promise 的可能是另一个副本(F4 的轮询腿会在它自己的下一拍续跑)。run 的生死读 run 面。
|
|
35
|
+
*/
|
|
36
|
+
export declare const ASK_DECISION_CONSUMER_ABSENT = "absent";
|
|
16
37
|
/**
|
|
17
38
|
* #329 §三 PARKED 臂:把一条已 park 的 ask 的决议交给**既有赎回腿**所需的全部材料。
|
|
18
39
|
*
|
|
@@ -68,7 +89,7 @@ export interface ToolApprovalFrame {
|
|
|
68
89
|
* 接线)兜底按在场性渲染归属标仍然正确。 */
|
|
69
90
|
sourceTaskId?: string;
|
|
70
91
|
/** [1550] RB-39②:core 1.378 显式判别键——委派子代 gate 发起的 ask 恒带 `true`,受信 internals 事实
|
|
71
|
-
* (worker
|
|
92
|
+
* (worker 不可自造/不可抑制)。取代 [1546] MED-1 的「在场 ∧ ≠ 宿主 sessionId」权宜判别式。 */
|
|
72
93
|
fromSubagent?: true;
|
|
73
94
|
/** [1550] 展示身份(子代 agent 名)——UNTRUSTED-for-display(core 未做秘密脱敏)→ redactSecrets 后渲。
|
|
74
95
|
* 仅子代 ask 上可能在场(core 未必总能解析出名字)。 */
|
|
@@ -180,6 +201,15 @@ export interface ToolApprovalFrame {
|
|
|
180
201
|
* 是 wire 谎言(判据逐字见 `trace/core-keyset-guard.ts` ④ 面本键那一段)。
|
|
181
202
|
*/
|
|
182
203
|
ruleOffers?: readonly RuleOffer[];
|
|
204
|
+
/**
|
|
205
|
+
* S-15 第五单(core #490 修②;**ADDITIVE**,`"tool_approval"` only)—— `ruleOffers` 的**缺席因由**:
|
|
206
|
+
* 规则车道在场却无可给时,引擎点名哪扇门关了(闭三词集 `mandated`/`shadowed`/`lane_cannot_speak`,
|
|
207
|
+
* 引擎侧与 `ruleOffers` 互斥)。壳据它把「为什么没有不再询问」渲成对应文案(`mandated` 臂**不得**
|
|
208
|
+
* 指向写规则)。ADVISORY 展示元数据、永不是裁决输入;**缺席不是断言**(covers「有 offers」与三扇
|
|
209
|
+
* 结构门)。值经 `approval-card.ts` 的 `readRuleOffersAbsence` 窄读(闭集校验;与 `card_json`
|
|
210
|
+
* **同一个**函数 ⇒ 两面同值),词表外的值=形不合=不铸键(#157 闭集纪律,绝不透传未知词)。
|
|
211
|
+
*/
|
|
212
|
+
ruleOffersAbsence?: RuleOffersAbsence;
|
|
183
213
|
/**
|
|
184
214
|
* #253 件 G1(core 5.33.0 backlog #239,判据帖 [3930] G1;**ADDITIVE**,`"tool_approval"` only)——
|
|
185
215
|
* 这次 ask **为什么**被收紧的**结构化**因由(`AskRequest.probeCause`:工具的 `reversibilityProbe`
|
|
@@ -281,6 +311,14 @@ export interface LivePendingRow {
|
|
|
281
311
|
governanceForced?: true;
|
|
282
312
|
/** 发起者为委派子代(originTaskId 在场)。 */
|
|
283
313
|
fromSubagent?: true;
|
|
314
|
+
/** S-52 C2(additive):委派子代的 **canonical taskId**。值域精确成文(codex R1-F3 问询后按 core dist
|
|
315
|
+
* 亲证):值 = `AskRequest.sourceTaskId` = 发起 task 的 sessionId(core prepare-task `askSourceIdentity`);
|
|
316
|
+
* 而 core 的 canonical taskId = `spec.taskId ?? sessionId`(runtask.js `runSourceTaskId`),Runner 铸的
|
|
317
|
+
* 委派子代 spec **不带** taskId ⇒ 子代 canonical taskId ≡ 子代 sessionId ≡ 本键 ≡
|
|
318
|
+
* `task_progress.taskId`(同一 `runSourceTaskId` 铸)—— 关联 join 在本键存在的唯一面(`fromSubagent`
|
|
319
|
+
* 子代 ask)上恒等成立。缺席 = 顶层 ask。`fromSubagent` 保留不动(byte-compat:先于本键的消费方仍按
|
|
320
|
+
* 它判别)。 */
|
|
321
|
+
originTaskId?: string;
|
|
284
322
|
}
|
|
285
323
|
export interface ToolApprovalRunContext {
|
|
286
324
|
taskId: string;
|
|
@@ -314,7 +352,7 @@ export interface ToolApprovalRunContext {
|
|
|
314
352
|
* 于是 wire 上确实是一条面、两种帧。
|
|
315
353
|
*
|
|
316
354
|
* 缺席 ⇒ 本连接不收呈卡帧(旧壳照常靠 `tool_approval` 工作);`askId` 未确认落盘时**也不发**
|
|
317
|
-
* (设计稿 §2.2(b) 硬条款一:无持久身份不发新帧)
|
|
355
|
+
* (设计稿 §2.2(b) 硬条款一:无持久身份不发新帧)。发射序锚定在 `tool_approval` **之后**(§4.2)。
|
|
318
356
|
*/
|
|
319
357
|
emitCard?: (frame: ApprovalRequestFrame) => void | Promise<void>;
|
|
320
358
|
abortSignal?: AbortSignal;
|
|
@@ -493,13 +531,18 @@ export declare function resolveStreamApprovalGate(input: StreamApprovalGateInput
|
|
|
493
531
|
* 三源(§8.3)里本仓可执行的是后两源;第一源 `forceDurableGate` 在 HTTP 装配时刻不可解析(§14 §12-5
|
|
494
532
|
* 亲裁:不可读则该源不做,core `prepare-task.js:3330` 结构性兜底),故不在本函数内。
|
|
495
533
|
*
|
|
496
|
-
* **`windowZero` 的两件事必须同时做**(调用方契约):不包 ALS
|
|
497
|
-
*
|
|
498
|
-
*
|
|
534
|
+
* **`windowZero` 的两件事必须同时做**(调用方契约):不包 ALS **且**注入 immediate-unavailable 闭包。
|
|
535
|
+
* 只做一件另一条路仍会呈卡。⚠️ S-52 起**三腿都有** per-task `spec.onAsk` 装配点(sync=routes/tasks.ts,
|
|
536
|
+
* bg=runs.ts,resume=server.ts driveResumeLeg),windowZero 的第二件在三腿都是显式闭包 —— 旧文「bg/
|
|
537
|
+
* resume 无装配点,不包 ALS 即等价」的缺席论证已退役,别再据它推断「少装一件也行」。
|
|
499
538
|
*/
|
|
500
539
|
export interface ApprovalLegAssembly {
|
|
501
540
|
/** 协议在本腿上是否上场。false ⇒ **既不包 ALS、也不接** `emitCard`/`emitRevoke`/`legKey`/
|
|
502
|
-
* `legDeadlineMonotonic` ——
|
|
541
|
+
* `legDeadlineMonotonic` —— **协议件**逐字保持协议之前的行为。
|
|
542
|
+
* ⚠️ S-52 门职分离(codex R1-F1 随修):本位**不再兼职**「审批席在场性」—— `spec.onAsk = boundAsk`
|
|
543
|
+
* 三腿恒装(判据 = 协调器在场,即 `TOOL_APPROVAL_ENABLED`),协议关时 bg/resume 腿的 ask 也能命中
|
|
544
|
+
* 同 (owner, session) 活流呈活卡(sync 腿 [1535] 起本就如此;bg/resume 的这条行为差 = S-52 CHANGELOG
|
|
545
|
+
* 披露的行为面变更)。旧文「本腿逐字保持协议之前的行为」只对协议件成立,别再把它读成「协议关 = 零呈卡」。 */
|
|
503
546
|
active: boolean;
|
|
504
547
|
/** §8.3 窗=0 恒 park。`active` 为假时恒 false(协议都没上场,谈不上关窗)。 */
|
|
505
548
|
windowZero: boolean;
|
|
@@ -583,6 +626,10 @@ export declare class ToolApprovalCoordinator {
|
|
|
583
626
|
* 收 dismiss 通知(见 askBroadcast)。 */
|
|
584
627
|
private readonly streams;
|
|
585
628
|
private readonly ttlMs;
|
|
629
|
+
/** S-43(案A §3.4):**零活流铸造**的 ask 的窗(`UNREACHED_ASK_TTL_MS`,缺省
|
|
630
|
+
* {@link DEFAULT_UNREACHED_ASK_TTL_MS} = 1h,域 [60s, 24h] 由 config 守)。只作用于
|
|
631
|
+
* `AskReachability === "unreached"` 的那一支;有活流的 ask 恒用 {@link ttlMs}。 */
|
|
632
|
+
private readonly unreachedTtlMs;
|
|
586
633
|
/** #151 车2(design/172 §7 协调器半场,D1):可选持久层——缺席 ⇒ 每一条现行为逐字不变(in-memory
|
|
587
634
|
* promise 机械即契约);在场 ⇒ 四竞争者(回决/窗到期/取消/emit 全灭)的终局多一道持久 CAS 记账。
|
|
588
635
|
* additive 改造,不是替换——settle 闭包/pending map/TTL/broker 全保留,CAS 只决定「谁有权 settle
|
|
@@ -599,6 +646,17 @@ export declare class ToolApprovalCoordinator {
|
|
|
599
646
|
* 一群 ask 全部越过门。 */
|
|
600
647
|
private readonly admitByTask;
|
|
601
648
|
private readonly admitByOwner;
|
|
649
|
+
/** S-43 F4:悬挂决议轮询腿的**轮转游标**(整数偏移,与集合成员无关 —— 理由见
|
|
650
|
+
* `pollSuspendedDecisions` 里那段:按 askId 记的形会在「上一拍最后碰的那条被结算掉」时塌回队首,
|
|
651
|
+
* 构造出永久饥饿的前缀)。只回答「上一拍扫到第几个」,单调推进、按当前长度取模。 */
|
|
652
|
+
private suspendedPollOffset;
|
|
653
|
+
/** S-43 + codex R3-[critical]:askId → **此刻正带着 `updatedInput` 决它的请求数**(见
|
|
654
|
+
* {@link markEditedDecisionInFlight} 顶注)。只在 `decideAsk` 那一次调用期间非空,故天然有界。 */
|
|
655
|
+
private readonly editedDecisionsInFlight;
|
|
656
|
+
/** S-43 + codex R6-[critical]:askId → **弃单墓碑**到期时刻。看门狗放弃一枚在飞编辑标记时落一条,
|
|
657
|
+
* 此后行派生的 approve 对这只 ask 改走 park 路由(理由见 {@link notifyExternalDecision} 里那段)。
|
|
658
|
+
* 有界两道:条目自带 TTL(惰性过期)+ 表大小 FIFO 上限,同 park 墓碑表的纪律。 */
|
|
659
|
+
private readonly abandonedEditedDecisions;
|
|
602
660
|
/** #151 车2(D5 一次性 warn 节流):同实例只报第一次,后续只计数(避免 store 抖动期间刷屏)。 */
|
|
603
661
|
private storeErrorWarned;
|
|
604
662
|
private storeErrorTally;
|
|
@@ -635,6 +693,9 @@ export declare class ToolApprovalCoordinator {
|
|
|
635
693
|
private readonly parkedRedeem;
|
|
636
694
|
constructor(opts?: {
|
|
637
695
|
ttlMs?: number;
|
|
696
|
+
/** S-43(案A):零活流铸造的 ask 的窗(见 {@link unreachedTtlMs})。装配点在协议**上场**时才传
|
|
697
|
+
* (与 `ttlMs` 同条件、同理由:悬挂的三条发现通道全长在 ask 行上);缺席 ⇒ 1h 代码默认。 */
|
|
698
|
+
unreachedTtlMs?: number;
|
|
638
699
|
askStore?: ApprovalAskStore;
|
|
639
700
|
windowMarginMs?: number;
|
|
640
701
|
admitMaxPerTask?: number;
|
|
@@ -826,7 +887,7 @@ export declare class ToolApprovalCoordinator {
|
|
|
826
887
|
* `card.governanceForced` 一个位 —— 行处于 `DECIDED=deny`(人已明确拒过这只调用)时照样回 `true`,
|
|
827
888
|
* 一揽子放行把一次**已落盘的人类拒绝**在重入 / failover / deny-后到 三形里翻成放行(帧 0、行不变、
|
|
828
889
|
* 无 recordFailOpen ⇒ 遥测零痕迹)。
|
|
829
|
-
* · **codex
|
|
890
|
+
* · **codex 交叉复审**(A-057.1 同批,验真后采纳):只补终态判据仍漏「卡还在别处挂着」——
|
|
830
891
|
* STREAM_PENDING 行意味着已有一张卡在等人,凭 grant 抢跑会让行上的终局与真实执行长期矛盾
|
|
831
892
|
* (那张卡随后可被人/另一副本决成相反答案,或 TTL 到点被收敛成幻影 gate)。
|
|
832
893
|
* 三次都不是各自独立的 bug,是同一句话没说全,故最终判据收成一条而不是三个分支。
|
|
@@ -845,6 +906,14 @@ export declare class ToolApprovalCoordinator {
|
|
|
845
906
|
* **park 路由**收尾 —— 行已 PARKING,它们看的是同一条行,终局必须与赢家同形(`unattendedPolicy`
|
|
846
907
|
* 由各自的闭包读同一个口,deny 部署上一起是 deny)。赢家自己此刻已 settle 过、已从集合里摘除,
|
|
847
908
|
* 故对它重复调用天然无操作。 */
|
|
909
|
+
/**
|
|
910
|
+
* S-43(案A)+ codex R2-[high]:同一条 askId 下,除 `self` 之外**是否还有悬挂登记在候**。
|
|
911
|
+
*
|
|
912
|
+
* 唯一消费者 = 投递面坍塌的两条臂(取消/断连的 `runCancel`、emit 全灭)。它们的语义是「这条连接没了」,
|
|
913
|
+
* 而悬挂登记的可达性从不建立在任何连接上 —— 判据与理由全文写在 `runCancel` 的调用点注里(单一属主)。
|
|
914
|
+
* 只看 `suspended === true` 且未结算的条目:两条**都有连接**的登记之间的旧语义不在本判据射程内。
|
|
915
|
+
*/
|
|
916
|
+
private hasOtherSuspendedOwner;
|
|
848
917
|
private settleSameAskIdParkRoute;
|
|
849
918
|
/** #329:落一条 park 墓碑(容量帽按**插入序**逐出最旧,与 `allowAllSessions` 同款有界纪律)。
|
|
850
919
|
* 调用点唯一 = `settle` 里的 park 路由支(见那处注);真终局绝不调它。
|
|
@@ -1084,11 +1153,124 @@ export declare class ToolApprovalCoordinator {
|
|
|
1084
1153
|
* 的唯一数据源。纯读投影,零锁/零结算语义;行键集刻意窄(**input/args 不上列表**,不开第二个脱敏
|
|
1085
1154
|
* 面;详情走流帧)。`scope` 与 durable 面同一表达式:`undefined` = operator 全量(含 owner null 的
|
|
1086
1155
|
* 条目),串 = 只见 `owner === scope` 的条目(null-owner 行对 principal 不可见,fail-closed——
|
|
1087
|
-
*
|
|
1156
|
+
* 宁少列不超范围;`"__none__"` 未鉴权哨兵自然恒空)。行的 `approvalId` 就是 `respond()` 收的 id
|
|
1088
1157
|
* (同源可达,A-058 判据);`expiresAtMs` 照抄登记时单点铸定的窗死线(#288 三键同一个数)。 */
|
|
1089
1158
|
listLivePending(scope: string | undefined): LivePendingRow[];
|
|
1159
|
+
/**
|
|
1160
|
+
* 🔴 S-43(案A)追记 F4 —— **跨副本决议的执行通知**(悬挂行的一次终态轮询)。
|
|
1161
|
+
*
|
|
1162
|
+
* ## 缺口的准确形状(别照抄第一版叙述)
|
|
1163
|
+
* 案A 的**发现**路径经 durable 腿本就跨副本可达:悬挂 ask 落的是共享店里的 `STREAM_PENDING` 行,
|
|
1164
|
+
* `GET /v1/approvals` 的 durable 段、壳队列、任一副本的 decide 端点都读得到它(codex 那句「另一副本
|
|
1165
|
+
* 列不出」经亲验为错述 —— 那说的是 `listLivePending`,它只是 live 腿)。真缺口在**执行**侧:兑现这次
|
|
1166
|
+
* 决议的 promise 是**进程内**的,只活在铸卡的那个副本里。人的决议打到副本 B ⇒ 行被 CAS 成 `DECIDED`,
|
|
1167
|
+
* 而副本 A 上那条悬挂 promise 没有任何本地事件会驱动它 —— 挂到窗满(1h)才收场,人已经批了。
|
|
1168
|
+
*
|
|
1169
|
+
* ## 二选一的取舍(设计稿追记 F4 要求写死)
|
|
1170
|
+
* 候选①**副本亲和路由**(把 decide 请求转发到持有 promise 的副本):需要一张「谁持有哪只 ask」的跨副本
|
|
1171
|
+
* 注册表 + 它自己的过期/裂脑收敛,而那张表的真源仍然是这张 ask 行 —— 等于为一个通知问题引入第二套一致性
|
|
1172
|
+
* 问题;且亲和一旦失效(副本刚死),决议就**没有**回落路径。
|
|
1173
|
+
* 候选②**原副本轮询唤醒**(本实现):不新开任何定时器族,搭 reaper 既有节拍(`boot/reapers.ts` 的
|
|
1174
|
+
* tick,与对账收敛器同一拍);读的是**行本身**这一个真源;副本死了就没有 promise 可唤醒,那与「run
|
|
1175
|
+
* 已经死了」是同一件事,不需要额外语义。**裁定 = ②**,理由一句话:通知面不该比它通知的那件事更复杂。
|
|
1176
|
+
* 代价如实记:唤醒延迟上界 = 一个 reaper tick(默认 `REAP_INTERVAL_SEC`),不是毫秒级 —— 悬挂 ask 的
|
|
1177
|
+
* 时间尺度是分钟到小时,这个上界在语义上是免费的;真要秒级,那是亲和路由的活,登记为后续件。
|
|
1178
|
+
*
|
|
1179
|
+
* ## 判据(逐条窄)
|
|
1180
|
+
* · **只轮询悬挂条目**(`suspended === true` ∧ 有 `askId` ∧ 未结算):有活流的 ask 有自己的
|
|
1181
|
+
* emit/respond/窗三条路,轮询它们只会在既有竞争者之外多加一个写者;
|
|
1182
|
+
* · **只读不写**:一次 `getAsk` 点读(带墙钟 deadline),读失败 ⇒ 记账 + 本轮跳过(下轮再来),
|
|
1183
|
+
* 绝不因为读不出来就替它编终局;
|
|
1184
|
+
* · **行仍 `STREAM_PENDING` ⇒ 什么都不做**(那是悬挂的**期望态**,不是异常);
|
|
1185
|
+
* · 终态映射复用 {@link replayTerminalAskRow}(不造第二套):`DECIDED` ⇒ 真决议经
|
|
1186
|
+
* {@link notifyExternalDecision}(它对已结算条目天然幂等);`PARKING|PARKED` ⇒ park 路由口
|
|
1187
|
+
* {@link settleSameAskIdParkRoute};`DENIED|VOID` ⇒ 裸 deny(同 {@link settleVoidedSiblings} 的形)。
|
|
1188
|
+
* · 同一 askId 只读一次(多条本地注册共享一次点读)。
|
|
1189
|
+
*
|
|
1190
|
+
* 返回 `{ polled, settled }` —— `polled` = 本轮真去店里点读的 askId 数,`settled` = 被唤醒的**本地条目**数。
|
|
1191
|
+
*/
|
|
1192
|
+
pollSuspendedDecisions(): Promise<{
|
|
1193
|
+
polled: number;
|
|
1194
|
+
settled: number;
|
|
1195
|
+
backlog: number;
|
|
1196
|
+
truncated: boolean;
|
|
1197
|
+
}>;
|
|
1198
|
+
/**
|
|
1199
|
+
* S-43(案A)+ codex [critical] 的**前置门读口**:本副本对这条持久 askId 还有几条**未结算**的活体登记。
|
|
1200
|
+
*
|
|
1201
|
+
* 唯一消费者 = durable 回决口(`routes/runs.ts`)在 CAS **之前**判「这次带来的 `updatedInput` 交得出去
|
|
1202
|
+
* 吗」—— 交不出去就响亮拒,绝不静默把编辑降级成不带编辑的批准(判据与理由全文在那个调用点)。
|
|
1203
|
+
* 返回 0 的两种成因(**刻意不分**):等待的 promise 在**别的副本**,或那条 run 已经死了(重启后本地窗空)。
|
|
1204
|
+
* 两者的处置相同(这次编辑在这里都落不了地),而分辨它们需要读 run 面 —— 那不是本口能回答的问题。
|
|
1205
|
+
*/
|
|
1206
|
+
liveConsumerCount(askId: string): number;
|
|
1207
|
+
/**
|
|
1208
|
+
* 🔴 S-43 + codex R3-[critical](真缺陷,红先复现器在 `test/case-a-reachability-queue.test.ts` 同名格)
|
|
1209
|
+
* —— **带编辑的决议在飞期间,观察者不结算**。
|
|
1210
|
+
*
|
|
1211
|
+
* 病灶:`decideAsk` 是「提交 → **另起**一次回读」的形。带 `updatedInput` 的请求 W 赢下 CAS 之后、
|
|
1212
|
+
* 回读返回**之前**,任何并发请求 R 看到的就是一条 `DECIDED` 行 —— 它经 `syncLiveFromDecidedRow` 用
|
|
1213
|
+
* **行派生**的裸 `true` 把本地等待腿结算掉(那条腿从此消失);W 的回读回来要转发编辑时 `settled` 已是 0。
|
|
1214
|
+
* 人批的是改好的命令,跑的是原来那条 —— 与 census 第 31 行同一种伤害,只是成因是**进程内的竞态**。
|
|
1215
|
+
*
|
|
1216
|
+
* 为什么进程内可解(这决定了它归本车而不是归那条店语义级欠账):这场竞态**恒在同一副本内** ——
|
|
1217
|
+
* W 能过决议口 CAS 前那道门,前提就是「本副本有活体等待腿」;R 要真伤到人,也必须结算**同一条**本地腿。
|
|
1218
|
+
*
|
|
1219
|
+
* 形:**只让路,不猜载荷**。在飞标记只回答「此刻有没有另一次请求正带着编辑决这只 ask」;观察者据它
|
|
1220
|
+
* **跳过结算**(把结算权留给持有编辑的那一次),绝不去替它转发一份自己没见过的载荷 —— 猜载荷就会在
|
|
1221
|
+
* 「两个并发 approve、一个带编辑一个不带」的形上执行一个**不是赢家**的决议。
|
|
1222
|
+
* 让路是安全的:标记的持有者在 `decideAsk` 返回后**必定**走两条路之一(赢 ⇒ 带编辑结算;输 ⇒ 经
|
|
1223
|
+
* `syncLiveFromDecidedRow` 按行结算),而那时标记已经释放 ⇒ 不存在「谁都不结算」的窗口。
|
|
1224
|
+
*
|
|
1225
|
+
* 生命周期硬条款:`mark` 与它返回的 `release` 必须**只包住 `decideAsk` 这一次调用**(try/finally),
|
|
1226
|
+
* 不包住调用之后的结算与响应 —— 包多了就把自己的结算路也让掉,那才是真的挂死。
|
|
1227
|
+
*/
|
|
1228
|
+
markEditedDecisionInFlight(askId: string): () => void;
|
|
1229
|
+
/** {@link markEditedDecisionInFlight} 的**并发计数**读口:此刻有几次请求正带着编辑决这只 ask。
|
|
1230
|
+
* 提交歧义臂的认领判据要它 —— 见 `routes/runs.ts` 那段注:`> 1` 时「谁的载荷是赢家」无从证明。 */
|
|
1231
|
+
editedDecisionInFlightCount(askId: string): number;
|
|
1232
|
+
/** {@link markEditedDecisionInFlight} 的读口:此刻有没有**别的**请求正带着编辑决这只 ask。 */
|
|
1233
|
+
editedDecisionInFlight(askId: string): boolean;
|
|
1234
|
+
/**
|
|
1235
|
+
* 弃单墓碑的读口(**惰性过期**:读到过期即删,不另起定时器 —— 同 park 墓碑表的姿势)。
|
|
1236
|
+
* 在场 = 这只 ask 曾有一次带编辑的决议在飞而看门狗放弃了它 ⇒ **行派生**的 approve 一律改走 park 路由。
|
|
1237
|
+
*
|
|
1238
|
+
* 🔴 **过期/逐出必须 fail-closed**(codex R7-[high],验真后采纳):首版是「到点就删」——而它保护的是
|
|
1239
|
+
* 一条**仍然挂着**的本地等待腿。店退化到十分钟以上、或并发弃单超过表帽时,墓碑先消失、腿还在,下一次
|
|
1240
|
+
* 行派生 approve 照样把原始命令放出去,正好复活它要防的那件事。判据改成:**丢墓碑之前先把它保护的
|
|
1241
|
+
* 消费者收掉**(park 路由,可逆可再批)。收完之后再删就是安全的 —— 没有腿可被误放行了。
|
|
1242
|
+
*/
|
|
1243
|
+
private abandonedEditedDecisionPending;
|
|
1244
|
+
/**
|
|
1245
|
+
* 🔴 **行派生 approve 的统一守卫**(codex R7-[critical],验真后修)。
|
|
1246
|
+
*
|
|
1247
|
+
* R6 把弃单墓碑的兑现点收在 {@link notifyExternalDecision} 上,并自称「公共咽喉」—— 那句话**不成立**:
|
|
1248
|
+
* 树上还有三处**直接** `settle(true, …)` / 直接把 `true` 交回 core 的行派生回放(`convergeFromDurableState`
|
|
1249
|
+
* 的收敛臂、`ensureAsk` 幂等命中终局行的回放、窗到期报错臂的 `readDecidedForRecovery`),它们跳过那个
|
|
1250
|
+
* 口。于是弃单之后从这三条路上仍能放出原始命令。
|
|
1251
|
+
*
|
|
1252
|
+
* 收口形 = **一个判据函数、五处消费**(上面三处 + 轮询 + HTTP 观察者):把「行说 approve」这件事
|
|
1253
|
+
* 在弃单墓碑在场时翻译成 `"unavailable"`(park 路由,可逆可再批),其余取值逐字透传。
|
|
1254
|
+
* 判据只认**行派生**的放行 —— 人的当次决议带着 `updatedInput` 走的是另一条路,不经本函数。
|
|
1255
|
+
*/
|
|
1256
|
+
private guardRowDerivedApprove;
|
|
1257
|
+
/** 丢一枚弃单墓碑的**唯一**口(过期 / 容量逐出共用):先把它还在保护的本地消费者按 park 路由收掉,
|
|
1258
|
+
* 再删表项 —— 顺序是硬的(先删表再收人 = 中间那一瞬正是可被误放行的窗口)。 */
|
|
1259
|
+
private dropAbandonedEditTombstone;
|
|
1260
|
+
/** 判据钩子:把「看门狗那一拍」显式地跑一次(留弃单墓碑 + 让在飞标记归零)。
|
|
1261
|
+
* 存在理由 = 那条臂的真实触发要等 {@link EDITED_DECISION_MARK_CAP_MS} 的墙钟,而本仓禁固定睡眠钉
|
|
1262
|
+
* (fixed-sleep 棘轮);把**语义**开一个口比让判据去睡 10 秒诚实得多。生产路径不调它。 */
|
|
1263
|
+
expireEditedDecisionMarkForTest(askId: string): void;
|
|
1264
|
+
/** 判据钩子:把一枚弃单墓碑**拨到已过期**并当场走它的丢弃路(= 真实 TTL 到点那一拍的语义)。
|
|
1265
|
+
* 同上理由:真触发要等 {@link ABANDONED_EDIT_TOMBSTONE_TTL_MS} 的墙钟。生产路径不调它。 */
|
|
1266
|
+
forceAbandonedEditTombstoneExpiryForTest(askId: string): void;
|
|
1267
|
+
/** 判据钩子:把一枚弃单墓碑的到期时刻**改写**成给定值(不触发惰性过期口本身)。用来构造
|
|
1268
|
+
* 「墓碑已过期、但还没有任何人来读过它」这一拍 —— 那正是「触发过期的那次调用还护不护」的判据点。 */
|
|
1269
|
+
setAbandonedEditTombstoneDeadlineForTest(askId: string, atMs: number): void;
|
|
1090
1270
|
/** Test/observability hooks. */
|
|
1091
1271
|
pendingCount(): number;
|
|
1272
|
+
/** S-43:当前挂着的**悬挂**条目数(零投递集合铸的那一类)——运维/判据读它证「悬挂队列有多长」。 */
|
|
1273
|
+
suspendedCount(): number;
|
|
1092
1274
|
sessionAllowedCount(): number;
|
|
1093
1275
|
/** #329:当前在场的 park 墓碑数(有界性的可观测面 —— 判据据它证「帽是硬的、过期会被清」)。 */
|
|
1094
1276
|
parkTombstoneCount(): number;
|