@sema-agent/server 7.123.0 → 7.124.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/MIGRATION.md +132 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/USAGE.md +53 -51
- package/dist/approval-ask-audit-store.d.ts +27 -32
- package/dist/approval-ask-audit-store.js +10 -9
- package/dist/approval-crash-convergence.d.ts +2 -2
- package/dist/approval-crash-convergence.js +5 -5
- package/dist/approval-deny-reasons.d.ts +163 -51
- package/dist/approval-deny-reasons.js +79 -8
- package/dist/approval-policy-settlement.d.ts +4 -1
- package/dist/approval-policy-settlement.js +3 -2
- package/dist/approval-reconciler.d.ts +3 -3
- package/dist/approval-reconciler.js +10 -10
- package/dist/approval.d.ts +1 -1
- package/dist/approval.js +1 -1
- package/dist/audit.js +1 -1
- package/dist/auth-bridge.d.ts +8 -8
- package/dist/auth-bridge.js +6 -6
- package/dist/auth-keys.d.ts +2 -2
- package/dist/auto-mode-face.d.ts +1 -1
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/execution-env.js +1 -0
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-consolidation.d.ts +4 -4
- package/dist/boot/org-memory.d.ts +3 -3
- package/dist/boot/org-memory.js +5 -5
- package/dist/boot/resolve-spec.js +7 -7
- package/dist/boot/runner-deps.d.ts +1 -1
- package/dist/boot/runtime-caps.d.ts +1 -1
- package/dist/boot/runtime-caps.js +10 -10
- package/dist/boot/shutdown.d.ts +2 -2
- package/dist/boot/shutdown.js +2 -2
- package/dist/boot/side-query-lane.d.ts +3 -3
- package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
- package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
- package/dist/boot/stage-03-store-backend.d.ts +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +6 -6
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +6 -5
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -3
- package/dist/boot/stage-09-leader.js +7 -7
- package/dist/boot/stage-10-http-server.d.ts +3 -3
- package/dist/boot/stage-10-http-server.js +19 -19
- package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
- package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
- package/dist/boot/{config-center.js → web-admin.js} +38 -22
- package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
- package/dist/brain.d.ts +1 -1
- package/dist/brain.js +1 -1
- package/dist/budget.d.ts +3 -3
- package/dist/canonical-json.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/center-wiring.d.ts +12 -5
- package/dist/capabilities/center-wiring.js +11 -2
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capabilities/team.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/center-credential-renewer.d.ts +1 -1
- package/dist/center-credential-renewer.js +7 -7
- package/dist/center-credential.d.ts +9 -9
- package/dist/center-credential.js +6 -6
- package/dist/config-catalog.d.ts +7 -10
- package/dist/config-catalog.js +15 -15
- package/dist/config-d-migration.d.ts +32 -0
- package/dist/config-d-migration.js +59 -0
- package/dist/config-invariants.d.ts +14 -4
- package/dist/config-invariants.js +31 -2
- package/dist/config-lkg.d.ts +26 -6
- package/dist/config-lkg.js +43 -14
- package/dist/config-provider.d.ts +23 -19
- package/dist/config-provider.js +24 -26
- package/dist/config-types.d.ts +52 -51
- package/dist/config.d.ts +9 -46
- package/dist/config.js +33 -92
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/drain-entry.d.ts +1 -1
- package/dist/fleet/engine-signal.d.ts +8 -8
- package/dist/fleet/fleet-bus.d.ts +12 -3
- package/dist/fleet/fleet-bus.js +13 -9
- package/dist/fleet/serving-lease.d.ts +3 -3
- package/dist/fleet/serving-lease.js +1 -1
- package/dist/fleet-client.d.ts +7 -7
- package/dist/fleet-client.js +5 -4
- package/dist/fleet-lease.d.ts +3 -3
- package/dist/fleet-lease.js +2 -2
- package/dist/host-lsp-manager.d.ts +1 -1
- package/dist/hosted-posture.d.ts +4 -4
- package/dist/http/admission.js +4 -4
- package/dist/http/checkpoint-ctx.d.ts +20 -3
- package/dist/http/checkpoint-ctx.js +13 -5
- package/dist/http/dispatch.js +2 -2
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/health-self-report.d.ts +4 -4
- package/dist/http/health-self-report.js +3 -3
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +31 -18
- package/dist/http/route-ctx.d.ts +8 -0
- package/dist/http/routes/admin-config-refresh.d.ts +1 -1
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.d.ts +1 -1
- package/dist/http/routes/admin-drain.js +5 -4
- package/dist/http/routes/approvals-assistant.js +4 -4
- package/dist/http/routes/capabilities.js +5 -5
- package/dist/http/routes/config-catalog.js +2 -3
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/runs.js +8 -4
- package/dist/http/routes/sessions-list.js +2 -1
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/side-query.js +3 -3
- package/dist/http/routes/tasks.js +3 -2
- package/dist/http/run-meta.d.ts +1 -1
- package/dist/http/run-meta.js +2 -2
- package/dist/http/server.d.ts +7 -7
- package/dist/http/server.js +1 -1
- package/dist/http/stored-body-replay.js +3 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/key-resolver.d.ts +1 -1
- package/dist/leader/wire.d.ts +2 -2
- package/dist/leader/wire.js +2 -1
- package/dist/main.js +1 -1
- package/dist/mcp-tool-faces.d.ts +2 -2
- package/dist/model-entry-refusal.d.ts +3 -3
- package/dist/model-entry-refusal.js +4 -4
- package/dist/model-provider.d.ts +2 -2
- package/dist/model-route-endpoint.d.ts +1 -1
- package/dist/model-route-url.d.ts +1 -1
- package/dist/model-route-url.js +2 -1
- package/dist/model-select.d.ts +24 -21
- package/dist/model-select.js +22 -17
- package/dist/observability/metrics.d.ts +1 -1
- package/dist/org-memory-admission.d.ts +1 -1
- package/dist/plugins/approval-ask-store-file.d.ts +4 -2
- package/dist/plugins/approval-ask-store-file.js +3 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
- package/dist/plugins/approval-ask-store-memory.js +10 -4
- package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
- package/dist/plugins/approval-ask-store-sql.js +20 -13
- package/dist/plugins/caching-session-store.d.ts +0 -10
- package/dist/plugins/caching-session-store.js +0 -3
- package/dist/plugins/file-run-store.js +9 -3
- package/dist/plugins/leader-run-store-sql.d.ts +3 -2
- package/dist/plugins/leader-run-store-sql.js +3 -2
- package/dist/plugins/local-session-store.d.ts +20 -27
- package/dist/plugins/local-session-store.js +19 -17
- package/dist/plugins/memory-run-store.js +9 -3
- package/dist/plugins/one-time-migrations.js +26 -2
- package/dist/plugins/scheduler-support.d.ts +26 -7
- package/dist/plugins/scheduler-support.js +96 -53
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/store-contracts.d.ts +20 -4
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/plugins/web-search.js +2 -1
- package/dist/posture-source.d.ts +1 -1
- package/dist/read-face-posture.d.ts +3 -3
- package/dist/read-face-posture.js +1 -1
- package/dist/run-local.js +6 -3
- package/dist/runtime-caps-resolver.d.ts +4 -4
- package/dist/runtime-caps-resolver.js +2 -2
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sealed-key.d.ts +4 -4
- package/dist/sealed-key.js +3 -2
- package/dist/security.d.ts +3 -3
- package/dist/service-version.d.ts +1 -1
- package/dist/service-version.js +5 -0
- package/dist/session-titler.d.ts +0 -11
- package/dist/session-titler.js +3 -5
- package/dist/shared-memory-scope-authorizer.d.ts +4 -4
- package/dist/task-a2a.d.ts +1 -1
- package/dist/tool-approval.d.ts +43 -4
- package/dist/tool-approval.js +147 -98
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/project.d.ts +3 -3
- package/dist/trace/redact.d.ts +2 -23
- package/dist/trace/redact.js +1 -6
- package/dist/trace/self-minted-wire.d.ts +147 -3
- package/dist/trace/self-minted-wire.js +50 -9
- package/dist/url-refusal.d.ts +35 -0
- package/dist/url-refusal.js +15 -0
- package/dist/user-authored-text.d.ts +31 -0
- package/dist/user-authored-text.js +18 -0
- package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
- package/dist/{config-center → web-admin-client}/apply-effective.js +100 -119
- package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
- package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
- package/dist/{config-center → web-admin-client}/center-request.js +5 -4
- package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
- package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
- package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
- package/dist/{config-center → web-admin-client}/facade.js +2 -2
- package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
- package/dist/{config-center → web-admin-client}/http-client.js +12 -12
- package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/read-face.js +4 -4
- package/dist/{config-center → web-admin-client}/read-warnings.d.ts +23 -16
- package/dist/{config-center → web-admin-client}/read-warnings.js +33 -23
- package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
- package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
- package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
- package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
- package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
- package/dist/{config-center → web-admin-client}/types.d.ts +12 -39
- package/package.json +2 -2
- package/skills/find-skills.md +2 -2
- package/dist/url-shape.d.ts +0 -31
- package/dist/url-shape.js +0 -41
- /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
- /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
- /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/types.js +0 -0
|
@@ -35,10 +35,12 @@
|
|
|
35
35
|
* `ask` 铸造点(呈卡帧 register 后、emit 前):wire approvalId / 出处 taskId / owner /
|
|
36
36
|
* toolName / `legTracked`(出处腿是否在协调器 `runWithContext` 视野里 —— decided
|
|
37
37
|
* 臂的收敛前提,见下)/ 窗死线 / 铸造时刻。
|
|
38
|
-
* `settle` 决议点(`settle()` 公共咽喉,五臂全过):outcome(
|
|
38
|
+
* `settle` 决议点(`settle()` 公共咽喉,五臂全过):outcome({@link SETTLE_OUTCOME} 三词)+
|
|
39
39
|
* `parkRouted`(窗到期/断连等 park 路由臂如实标注 —— 该行的续命在 durable park 面,
|
|
40
|
-
* 收敛器**不**把它当孤儿)+ 宿主自报(在场才带)+
|
|
41
|
-
*
|
|
40
|
+
* 收敛器**不**把它当孤儿)+ 宿主自报(在场才带)+ **`cause`(成因闭集 {@link SettleCause},`approval-deny-reasons.ts`)**:
|
|
41
|
+
* `outcome:"expired"`(非人结局)恒带、人答(`allowed` / `denied`)恒缺席 —— 写口的联合型逼每个非人调用点点名一个;
|
|
42
|
+
* 词表外 ⇒ 计坏行、结清照认;本版之前落盘的 `expired` 行没有 `cause`(存量审计行不回填,读面缺席即缺席)。
|
|
43
|
+
* `cause:"shutdown_before_park"`(S-929)= 这次等待是被**有序关停**结束的 —— `drainForShutdown` 按断连同路收场的活卡;park 路由的那几行**等观察到 core 已处置这次调用才落**(F1:停车行提交 / 承载它的腿退场,后者恒在 `leg_closed` 之前),两者皆无就退出 ⇒ 无此行。
|
|
42
44
|
* `leg_closed` 腿闭点(`runWithContext` finally;只为铸过审计行的 taskId 落,防账本膨胀):
|
|
43
45
|
* 「决议之后腿有没有闭」是 decided 臂唯一的机械证据面 —— 没有它,「批完跑完」与
|
|
44
46
|
* 「批了、执行窗内崩」在账本字节上同形,收敛器只能二选一地撒谎。
|
|
@@ -169,7 +171,7 @@
|
|
|
169
171
|
*/
|
|
170
172
|
import type { HostDecision } from "./host-decision.js";
|
|
171
173
|
import { AppendLog } from "@sema-agent/core";
|
|
172
|
-
import
|
|
174
|
+
import { SETTLE_OUTCOME, type HolderGoneCause, type SettleCause } from "./approval-deny-reasons.js";
|
|
173
175
|
/** 数据子目录名(挂在 local 数据根下,与 `workflow-notify/` 同层同形)。 */
|
|
174
176
|
export declare const APPROVAL_ASK_AUDIT_DIR = "approval-ask-audit";
|
|
175
177
|
/** 账本文件名(目录内唯一一只;启动收敛据它判「盘上有没有前世审计证据」,见 `approval-crash-convergence.ts` 的 `openAuditEvidenceForConvergence`)。 */
|
|
@@ -194,38 +196,30 @@ export interface AuditAskInput {
|
|
|
194
196
|
expiresAtMs: number;
|
|
195
197
|
mintedAtMs: number;
|
|
196
198
|
}
|
|
197
|
-
/**
|
|
198
|
-
|
|
199
|
-
* 共用这一个词。读盘词表 = {@link AUDIT_SHUTDOWN_CAUSE_WORDS}(编译期穷举)。词表外的值(新版本写的、本二进制不认识的成因 / 手改)⇒
|
|
200
|
-
* **计坏行**(`corruptLines`,坏值响亮律 —— 不静默读成「没写成因」),但**不丢该 settle 行的结清**(F4:outcome / parkRouted 照认 ——
|
|
201
|
-
* 因为一个成因词把整条结清行丢掉,会把一张已结清的卡收成 pending 孤儿,方向比「少认一个成因」更坏)。
|
|
202
|
-
*/
|
|
203
|
-
export type AuditShutdownCause = typeof VOID_REASONS.HOLDER_SHUTDOWN;
|
|
204
|
-
/**
|
|
205
|
-
* 成因词的读盘词表(F4:`satisfies Record<AuditShutdownCause, true>` ⇒ 闭集加一个词而本表没跟 = **编译红**;判定走 `Object.hasOwn`,
|
|
206
|
-
* 原型链上的名字不算词 —— CLAUDE.md 词表律)。唯一读者 = {@link readShutdownCause}。
|
|
207
|
-
*/
|
|
208
|
-
export declare const AUDIT_SHUTDOWN_CAUSE_WORDS: {
|
|
209
|
-
readonly shutdown_before_park: true;
|
|
210
|
-
};
|
|
211
|
-
/** 收敛行 `cause` 的闭集(`GET /v1/approvals` `crashConverged[].cause`):崩溃孤儿 / 有序关停截断的腿(S-929 +1;与 `crashed_before_park` 同形)。
|
|
212
|
-
* 🔴 **词表属主 = `approval-deny-reasons.ts` 的 `VOID_REASONS`**(`HOLDER_CRASHED` / `HOLDER_SHUTDOWN`):启动收敛把同一问的问账行收成 VOID 时
|
|
213
|
-
* `deniedReason` 写的就是这两个词 —— 同一问在 `crashConverged` 与决断口 410 体上只有一个成因词(本型不再自带一份字面量)。
|
|
214
|
-
* wire 值闭集登记在 `trace/self-minted-wire.ts` 的 `crashConvergedCause`(`satisfies Record<CrashConvergedCause, …>` 双向绑定 ⇒ 加词不登记 = tsc 红,
|
|
215
|
-
* wire 变更清单从那张表 diff —— F3)。 */
|
|
216
|
-
export type CrashConvergedCause = HolderGoneReason;
|
|
217
|
-
/** 决议点入参(`settle()` 公共咽喉挂线;五臂全过,不漏窗到期/断连/取消)。 */
|
|
218
|
-
export interface AuditSettleInput {
|
|
199
|
+
/** 决议点入参共有的位(联合型的两臂都带)。 */
|
|
200
|
+
interface AuditSettleBase {
|
|
219
201
|
approvalId: string;
|
|
220
|
-
outcome: "allowed" | "denied" | "expired";
|
|
221
202
|
/** 走了 park 路由(windowRouteUnavailable)—— 该行的续命在 durable park 面,收敛器不当孤儿。 */
|
|
222
203
|
parkRouted?: boolean;
|
|
223
|
-
/** S-929:这次等待是被有序关停结束的(`ToolApprovalCoordinator.drainForShutdown`);缺席 = 别的臂。 */
|
|
224
|
-
cause?: AuditShutdownCause;
|
|
225
204
|
/** 宿主自报来源(HostSettledBy;在场才带)。收敛器不消费,纯审计。 */
|
|
226
205
|
settledBy?: string;
|
|
227
206
|
settledAtMs: number;
|
|
228
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* 决议点入参(`settle()` 公共咽喉挂线;五臂全过,不漏窗到期/断连/取消)。**判别联合**:`cause` 在场 ⇔ 非人结局(`outcome:"expired"`)——
|
|
210
|
+
* 人答(`allowed` / `denied`)不带 `cause`,非人结局不点名成因就**编译不过**(类型面上没有「`expired` 而无成因」这个值)。
|
|
211
|
+
*/
|
|
212
|
+
export type AuditSettleInput = (AuditSettleBase & {
|
|
213
|
+
outcome: typeof SETTLE_OUTCOME.ALLOWED | typeof SETTLE_OUTCOME.DENIED;
|
|
214
|
+
cause?: undefined;
|
|
215
|
+
}) | (AuditSettleBase & {
|
|
216
|
+
outcome: typeof SETTLE_OUTCOME.EXPIRED;
|
|
217
|
+
cause: SettleCause;
|
|
218
|
+
});
|
|
219
|
+
/** 收敛行 `cause` 的闭集(`GET /v1/approvals` `crashConverged[].cause`):崩溃孤儿 / 有序关停截断的腿(S-929 +1;与 `crashed_before_park` 同形)。
|
|
220
|
+
* 🔴 **词表属主 = `approval-deny-reasons.ts` 的 {@link HolderGoneCause}**(本表两词的子集):启动收敛把同一问的问账行收成 VOID 时 `denied_reason` 写的就是这两个词 ——
|
|
221
|
+
* 同一问在 `crashConverged` 与决断口 410 体上只有一个成因词。wire 值闭集登记在 `trace/self-minted-wire.ts` 的 `crashConvergedCause`
|
|
222
|
+
* (`satisfies Record<HolderGoneCause, …>` 双向绑定 ⇒ 加词不登记 = tsc 红,wire 变更清单从那张表 diff —— F3)。 */
|
|
229
223
|
/**
|
|
230
224
|
* [ref] **迟到人工结算点**入参:调用方(两条 HTTP decide 腿)只交 **checkpoint 锚 + 这次结算的事实**,
|
|
231
225
|
* `approvalId` 的反查与「算不算迟到」的判据**属主在店内**(一处成文,见 {@link FileApprovalAskAuditStore.recordLateSettle})
|
|
@@ -302,9 +296,9 @@ export interface CrashConvergedRow {
|
|
|
302
296
|
* 不是语义(改这个值会让把它当闭集判别式读的消费端整行丢弃,须与消费端同窗改)。
|
|
303
297
|
*/
|
|
304
298
|
decision: "denied";
|
|
305
|
-
/** 成因注(闭集 {@link
|
|
299
|
+
/** 成因注(闭集 {@link HolderGoneCause}):`crashed_before_park` = 进程崩了;`shutdown_before_park`(S-929)= 腿被**有序关停**截断
|
|
306
300
|
* (判据见头注「收敛行的 `cause`」)。两者的 `orphanState` / `resumeSafe` 判据相同。 */
|
|
307
|
-
cause:
|
|
301
|
+
cause: HolderGoneCause;
|
|
308
302
|
orphanState: CrashOrphanState;
|
|
309
303
|
/** decided 臂:人当时批的是 approve(这句话不许被终态同码吞掉)。 */
|
|
310
304
|
originalDecision?: "approve";
|
|
@@ -447,7 +441,7 @@ export declare class FileApprovalAskAuditStore implements ApprovalAskAuditSink,
|
|
|
447
441
|
* {@link causeOf})。前世账本里没有这只 `approvalId` 的铸造行(崩在 ask 账落行之后、本店铸造行之前,或本店那时不在)⇒ `crashed_before_park`:
|
|
448
442
|
* 没有有序关停的证据,就不说它是有序关停。判据读的是构造时冻结的前世账本 ⇒ 同一份账本跨几次启动恒得同一个词。
|
|
449
443
|
*/
|
|
450
|
-
causeFor(approvalId: string):
|
|
444
|
+
causeFor(approvalId: string): HolderGoneCause;
|
|
451
445
|
/** S-929 收敛行的成因注(判据见头注「收敛行的 `cause`」):组的最后一个事件行之后、收敛行(若已收敛)之前,有本 taskId 的
|
|
452
446
|
* 有序关停记号 ⇒ `shutdown_before_park`;否则 `crashed_before_park`。 */
|
|
453
447
|
private causeOf;
|
|
@@ -466,4 +460,5 @@ export declare class FileApprovalAskAuditStore implements ApprovalAskAuditSink,
|
|
|
466
460
|
/** 收追加口(优雅关闭腿;SIGKILL 下不跑也不丢 —— 每行已 fsync)。core `AppendLog.close()` 自己吞 `closeSync` 的错、不抛(全函数),本店不再包 catch。 */
|
|
467
461
|
close(): void;
|
|
468
462
|
}
|
|
463
|
+
export {};
|
|
469
464
|
//# sourceMappingURL=approval-ask-audit-store.d.ts.map
|
|
@@ -3,20 +3,21 @@ import { join } from "node:path";
|
|
|
3
3
|
import { AppendLog, ensureDir, isHostDecider } from "@sema-agent/core";
|
|
4
4
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
5
5
|
import { replayJsonlSkipping } from "./observability/corrupt-read-seat.js";
|
|
6
|
+
import { isSettleCause, SETTLE_OUTCOME } from "./approval-deny-reasons.js";
|
|
6
7
|
export const APPROVAL_ASK_AUDIT_DIR = "approval-ask-audit";
|
|
7
8
|
export const APPROVAL_ASK_AUDIT_LEDGER = "ledger.jsonl";
|
|
8
9
|
export const CRASH_CONVERGED_LIST_MAX = 200;
|
|
9
|
-
|
|
10
|
+
const SETTLE_OUTCOME_WORDS = new Set(Object.values(SETTLE_OUTCOME));
|
|
11
|
+
function isSettleOutcome(v) {
|
|
12
|
+
return typeof v === "string" && SETTLE_OUTCOME_WORDS.has(v);
|
|
13
|
+
}
|
|
10
14
|
export function buildCheckpointAnchorHash(token) {
|
|
11
15
|
return createHash("sha256").update(token, "utf8").digest("hex").slice(0, 16);
|
|
12
16
|
}
|
|
13
|
-
function
|
|
14
|
-
return typeof v === "string" && Object.hasOwn(AUDIT_SHUTDOWN_CAUSE_WORDS, v);
|
|
15
|
-
}
|
|
16
|
-
function readShutdownCause(v) {
|
|
17
|
+
function readSettleCause(v) {
|
|
17
18
|
if (v === undefined)
|
|
18
19
|
return { cause: undefined, outOfSet: false };
|
|
19
|
-
if (
|
|
20
|
+
if (isSettleCause(v))
|
|
20
21
|
return { cause: v, outOfSet: false };
|
|
21
22
|
return { cause: undefined, outOfSet: true };
|
|
22
23
|
}
|
|
@@ -70,11 +71,11 @@ function readLedgerRecord(u, noteOutOfSetSeat) {
|
|
|
70
71
|
const approvalId = s("approvalId");
|
|
71
72
|
const settledAtMs = num("settledAtMs");
|
|
72
73
|
const outcomeV = o.outcome;
|
|
73
|
-
const outcome = outcomeV
|
|
74
|
+
const outcome = isSettleOutcome(outcomeV) ? outcomeV : undefined;
|
|
74
75
|
if (approvalId === undefined || settledAtMs === undefined || outcome === undefined)
|
|
75
76
|
return undefined;
|
|
76
77
|
const settledBy = s("settledBy");
|
|
77
|
-
const cause =
|
|
78
|
+
const cause = readSettleCause(o.cause);
|
|
78
79
|
if (cause.outOfSet)
|
|
79
80
|
noteOutOfSetSeat();
|
|
80
81
|
return {
|
|
@@ -279,7 +280,7 @@ export class FileApprovalAskAuditStore {
|
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
indexSettle(rec) {
|
|
282
|
-
if (rec.outcome ===
|
|
283
|
+
if (rec.outcome === SETTLE_OUTCOME.EXPIRED && rec.parkRouted === true)
|
|
283
284
|
this.parkExpired.add(rec.approvalId);
|
|
284
285
|
}
|
|
285
286
|
recordAsk(input) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ApprovalAskStore } from "./plugins/approval-ask-store-sql.js";
|
|
2
2
|
import { FileApprovalAskAuditStore } from "./approval-ask-audit-store.js";
|
|
3
|
-
import { type
|
|
3
|
+
import { type HolderGoneCause } from "./approval-deny-reasons.js";
|
|
4
4
|
import { type RunStoreReader } from "./user-input-ledger.js";
|
|
5
5
|
import type { Logger } from "./observability/logger.js";
|
|
6
6
|
/** 启动收敛的读数(进启动日志)。 */
|
|
@@ -11,7 +11,7 @@ export interface CrashConvergenceReport {
|
|
|
11
11
|
readonly inconsistent: number;
|
|
12
12
|
readonly corruptLines: number;
|
|
13
13
|
/** ask 账半场:按成因词计的、本次收成 VOID 的前世 `STREAM_PENDING` 行数。 */
|
|
14
|
-
readonly asksVoided: Readonly<Record<
|
|
14
|
+
readonly asksVoided: Readonly<Record<HolderGoneCause, number>>;
|
|
15
15
|
/** 其中卡信封读不出、成因词是回落(`crashed_before_park`)的行数(同时记 fail-open tag)。 */
|
|
16
16
|
readonly causeUnreadable: number;
|
|
17
17
|
}
|
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { APPROVAL_ASK_AUDIT_DIR, APPROVAL_ASK_AUDIT_LEDGER, FileApprovalAskAuditStore } from "./approval-ask-audit-store.js";
|
|
4
4
|
import { ApprovalCardEnvelopeSchema } from "./approval-card.js";
|
|
5
|
-
import {
|
|
5
|
+
import { APPROVAL_ENDING_CAUSES } from "./approval-deny-reasons.js";
|
|
6
6
|
import { writerGoneEvidenceFor } from "./user-input-ledger.js";
|
|
7
7
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
8
8
|
const CONVERGE_PAGE = 500;
|
|
@@ -20,7 +20,7 @@ export function openAuditEvidenceForConvergence(live, localDataRoot) {
|
|
|
20
20
|
export async function convergeCrashedAsksAtBoot(input) {
|
|
21
21
|
const now = input.now ?? Date.now;
|
|
22
22
|
const audited = input.audit?.convergeCrashedAsks() ?? { pending: 0, decided: 0, inconsistent: 0, corruptLines: 0 };
|
|
23
|
-
const asksVoided = { [
|
|
23
|
+
const asksVoided = { [APPROVAL_ENDING_CAUSES.CRASHED_BEFORE_PARK]: 0, [APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK]: 0 };
|
|
24
24
|
let causeUnreadable = 0;
|
|
25
25
|
const store = input.askStore;
|
|
26
26
|
if (store !== undefined) {
|
|
@@ -34,9 +34,9 @@ export async function convergeCrashedAsksAtBoot(input) {
|
|
|
34
34
|
const envelope = ApprovalCardEnvelopeSchema.safeParse(row.cardJson);
|
|
35
35
|
if (!envelope.success) {
|
|
36
36
|
causeUnreadable += 1;
|
|
37
|
-
recordFailOpen("server.approval-crash-convergence.cause-unreadable", `ask ${row.askId} (task ${row.taskId}): card envelope unreadable — cause defaulted to ${
|
|
37
|
+
recordFailOpen("server.approval-crash-convergence.cause-unreadable", `ask ${row.askId} (task ${row.taskId}): card envelope unreadable — cause defaulted to ${APPROVAL_ENDING_CAUSES.CRASHED_BEFORE_PARK}`);
|
|
38
38
|
}
|
|
39
|
-
const reason = envelope.success && input.audit !== undefined ? input.audit.causeFor(envelope.data.approvalId) :
|
|
39
|
+
const reason = envelope.success && input.audit !== undefined ? input.audit.causeFor(envelope.data.approvalId) : APPROVAL_ENDING_CAUSES.CRASHED_BEFORE_PARK;
|
|
40
40
|
let won;
|
|
41
41
|
try {
|
|
42
42
|
won = await store.transitionAsk(row.askId, "STREAM_PENDING", "VOID", { deniedReason: reason, updatedAtMs: now() });
|
|
@@ -67,7 +67,7 @@ export async function runBootCrashConvergence(ctx) {
|
|
|
67
67
|
corruptLines: converged.corruptLines,
|
|
68
68
|
asksVoided: converged.asksVoided,
|
|
69
69
|
causeUnreadable: converged.causeUnreadable,
|
|
70
|
-
note: "approval asks left pending by the previous process were converged: each such ask is now VOID in the ask ledger (the decision endpoint answers 410 gone.ask with this cause
|
|
70
|
+
note: "approval asks left pending by the previous process were converged: each such ask is now VOID in the ask ledger (the decision endpoint answers 410 gone.ask with this cause) and is listed under GET /v1/approvals crashConverged when the audit ledger saw it (cause crashed_before_park = the process crashed; cause shutdown_before_park = an orderly shutdown cut the leg off before it closed or before its park committed)",
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
return converged;
|
|
@@ -1,69 +1,181 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* **审批席「这张卡为什么没被人答」的一只闭集** —— {@link APPROVAL_ENDING_CAUSES}。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* ## 它治的病(同一件事、四张词表、一词多义)
|
|
5
|
+
* 一张卡没被人答就结束了,今天有四个读面各说各话:审计 settle 行(`expired` 一词盖 TTL 到期 / run 取消 / run 退出清理 / 广播全灭,批内兄弟被撤卡也是同一个词)、
|
|
6
|
+
* 问账 VOID/DENIED 行(`denied_reason` 列)、晚答 404 的判别位、决断口 409 的码(多种成因借 `approval_binding_mismatch` 一个名)。壳读账写不出「已取消」,
|
|
7
|
+
* 也分不出「重取坐标再决」与「改答案再决」。收成**一张表、一个词、各面同读**:
|
|
8
|
+
* · 审计 settle 行的 `cause`(非人结局必填,人答缺席;`settle(verdict)` 判别联合逼每个非人调用点点名一个)与活卡结局帧 `tool_approval_complete` 的 additive `cause`(同一个词,同一条律);
|
|
9
|
+
* · 问账 VOID/DENIED 行的 `denied_reason` 列 → 决断口 410 `gone.ask` 体的 `cause` 与晚答 404 体的 `cause`(读同一列,经唯一读口 {@link causeOfAskRow});
|
|
10
|
+
* · `GET /v1/approvals` `crashConverged[].cause`(本表的 {@link HolderGoneCause} 两词子集);
|
|
11
|
+
* · 决断口 409 的码:`binding_changed` / `answer_invalid` / `outcome_cell_invalid` 三词各归一个码。`retriable` 不由成因说 —— 三词都出自 core 的
|
|
12
|
+
* `checkpoint.invalid_outcome`,由 `http/resume-legs.ts` 的 core 码 → 处置一张表派生(一个意思:卡仍 pending、行重新 park)。
|
|
7
13
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
14
|
+
* ## 规则
|
|
15
|
+
* · 词表属主一处(本文件);加一个成因 = 加一个词:决断类词 ⇒ 409 码表(`http/resume-legs.ts` 的 `WIRE_CODE_OF_DECISION_REFUSAL`)的穷举编译红,结局类词 ⇒ 读盘词表 {@link SETTLE_CAUSE_WORDS} 的穷举编译红。
|
|
16
|
+
* · 成因**只从事实读**:run 行 `errorCode:"cancelled"`、钟到、emit 零接收、停车行 / 问账行的列、`detail.field`;不读拒句散文。
|
|
17
|
+
* · 「停驻行的格式比本引擎新」**不是**本表的词:它只有 core 一个来源(`checkpoint.unsupported_version` + `detail.reason:"version_newer"`,原码镜像);服务层不从续跑上下文的写者版本推断成因。
|
|
18
|
+
* · **人答的结局(`allowed` / `denied`)没有 cause**:`cause` 在场 ⇔ 非人结局。
|
|
19
|
+
* · 落列面:问账行的成因写进 `approval_ask.denied_reason`(VARCHAR(64)),一列按 `state` 承载两种意思 —— VOID / DENIED 行上是**终态成因**,PARKING / PARKED 行上是
|
|
20
|
+
* **转 park 的触发成因**;读它只经 {@link causeOfAskRow}(按 state 穷举分派,两张读词表只被它读)。列名将在下一个 DDL 窗按意义改名。
|
|
13
21
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
22
|
+
* ## 为什么 `routing_failure_fail_closed` 也在表里(归因诚实性)
|
|
23
|
+
* 审计面唯一能证明「超时永不产生 denial」的东西是**终态 + 成因**的组合:人拒恒为 `DECIDED(decision=deny)`,路由失败恒为 `DENIED(routing_failure_fail_closed)`,
|
|
24
|
+
* 撤卡 / 取消 / 遗孤恒为 `VOID(<成因>)` —— 三者在 wire 与审计上全程可分。终态(问账行的 `state`)是判别位,成因词在同一张表里:一个成因只落一种终态
|
|
25
|
+
* (写点各自的类型固定了这一点:对账器的 `DENIED` 写点只收 {@link ReconcileDenyCause},`VOID` 写点只收 {@link ReconcileVoidCause})。
|
|
26
|
+
* 全仓 `DENIED` 只有**一个**写点 = 对账器判据 2 的非取消臂(`approval-reconciler.ts`);启动收敛(进程没了)落的是 VOID 不是 DENIED:状态机上
|
|
27
|
+
* `STREAM_PENDING` 没有到 DENIED 的边(DENIED 只在「已路由去 park」之后),而承载它的进程没了 = 这条腿死了 = abort 语义。
|
|
28
|
+
*/
|
|
29
|
+
import type { AskState } from "./approval-ask-machine.js";
|
|
30
|
+
/**
|
|
31
|
+
* 审计 settle 行 `outcome` 的三词 —— **全仓唯一**的定义处(wire 契约锚:`tool_approval_complete.outcome` 与审计行同三词)。
|
|
32
|
+
* `allowed` / `denied` = 一次**决议**(人答,或行上读回来的决议);`expired` = 这次等待**没有等到决议就结束了**(非人结局,恒带 {@link ApprovalEndingCause})。
|
|
21
33
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
export declare const SETTLE_OUTCOME: {
|
|
35
|
+
readonly ALLOWED: "allowed";
|
|
36
|
+
readonly DENIED: "denied";
|
|
37
|
+
readonly EXPIRED: "expired";
|
|
38
|
+
};
|
|
39
|
+
export type SettleOutcome = (typeof SETTLE_OUTCOME)[keyof typeof SETTLE_OUTCOME];
|
|
40
|
+
/** 非人结局的**穷尽**成因(每个非人 `settle` 调用点必须点名一个)。成员的语义随成员。 */
|
|
41
|
+
export declare const APPROVAL_ENDING_CAUSES: {
|
|
42
|
+
/** 窗到期:这张卡的等待窗(行上一次铸定的绝对 deadline)走完,没有人答。 */
|
|
43
|
+
readonly TTL_EXPIRED: "ttl_expired";
|
|
44
|
+
/** emit 广播全灭:两族帧都没送到任何连接(emit 返回零接收)—— 这张卡从未送达任何人。 */
|
|
45
|
+
readonly BROADCAST_LOST: "broadcast_lost";
|
|
46
|
+
/** 承载这张卡的流没了:断连强转 park(`parkOpenAsksForTask`,断连臂的事实 = 这个 wire run 的承载流断了;卡曾送达过,只是不会再有人从那条流上答它)。 */
|
|
47
|
+
readonly STREAM_DISCONNECTED: "stream_disconnected";
|
|
24
48
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* 🔴 证据是**行的终局态**(journal 的肯定证据),不是「等够久了」——约束②因此成立。
|
|
49
|
+
* 这张卡呈不出去:兜底臂(行不可用 / 身份不定 / 悬挂无行,`unattendedOutcome` 的 `persisted_row_unusable` / `ensure_indeterminate` / `unreached_no_row`)—— 持久行证不出属主或读不成,
|
|
50
|
+
* 本次登记根本没把卡呈到任何投递面;同 askId 的其余本地登记按这个词随行收场。与 `broadcast_lost`(emit 零接收)是两个事实。
|
|
28
51
|
*/
|
|
29
|
-
readonly
|
|
30
|
-
|
|
31
|
-
export type DenyReason = (typeof DENY_REASONS)[keyof typeof DENY_REASONS];
|
|
32
|
-
/** `VOID` 终态的归因闭集。 */
|
|
33
|
-
export declare const VOID_REASONS: {
|
|
34
|
-
/** 判据 2 的取消分臂(§9 C3):run `failed ∧ errorCode==="cancelled"` ⇒ 取消不是路由失败,收 VOID。 */
|
|
52
|
+
readonly UNDELIVERABLE: "undeliverable";
|
|
53
|
+
/** run 被取消:出处 run 的中止信号触发(取消动词 / 非 detach 断连),或对账器读到 run 行 `failed ∧ errorCode==="cancelled"`(判据 2 的取消分臂,§9 C3:取消不是路由失败,收 VOID)。 */
|
|
35
54
|
readonly RUN_CANCELLED: "run_cancelled";
|
|
55
|
+
/** run 结束清理:承载这张卡的那条腿的作用域退出(正常返回或抛出)时卡还挂着。 */
|
|
56
|
+
readonly RUN_EXITED: "run_exited";
|
|
36
57
|
/** 判据 2 的取消分臂之二:批行已 `ABORTED`(取消腿打过 `abortBatch`)⇒ 同 abort 语义。 */
|
|
37
58
|
readonly BATCH_ABORTED: "batch_aborted";
|
|
59
|
+
/** 批内兄弟被赢家的原子撤卡连坐(窗到期赢家把同批其余 `STREAM_PENDING` 兄弟一起撤成 VOID)的「没了」。 */
|
|
60
|
+
readonly BATCH_SIBLING_WITHDRAWN: "batch_sibling_withdrawn";
|
|
38
61
|
/**
|
|
39
|
-
* bind-once 的**落选者**(codex 交叉复审 round2 R2-3,2026-08-06 验真):批已 `ROUTING_BOUND` 且
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* 迟到行(late `ensureAsk` + `expireAsk` 不查批态,设计如此)由收敛器补判——就是这条臂。
|
|
44
|
-
* 不这么判的后果:该行滞留到 run 终局,然后被判据 2 误报成 `routing_failure_fail_closed`(归因失真)。
|
|
62
|
+
* bind-once 的**落选者**(codex 交叉复审 round2 R2-3,2026-08-06 验真):批已 `ROUTING_BOUND` 且 `bound_ask_id` 是**别人**——本行永远赢不了 `bindBatch`
|
|
63
|
+
* (谓词要求 `state='ROUTING_UNBOUND'`),却又不是路由失败(投递面好好的,只是这个决策点选了兄弟)。172 §3.0 的 bind-once 字面就是「非中选兄弟收敛 VOID」;
|
|
64
|
+
* `bindBatch` 的原子事务只连坐它当时看得见的 PARKING 兄弟,**之后**才进入 PARKING 的迟到行由收敛器补判——就是这条臂。不这么判的后果:该行滞留到 run 终局,
|
|
65
|
+
* 然后被判据 2 误报成 `routing_failure_fail_closed`(归因失真)。
|
|
45
66
|
*/
|
|
46
67
|
readonly BATCH_BOUND_ELSEWHERE: "batch_bound_elsewhere";
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
/**
|
|
69
|
+
* 收敛器判据 2:出处 run 已到**非 suspended 的终局**(completed / blocked / 非取消的 failed)而始终没有出现与本 ask 匹配的 checkpoint ⇒ 这只 ask 的投递面永远不会再出现,
|
|
70
|
+
* fail-closed 收 `DENIED`。🔴 证据是**行的终局态**(journal 的肯定证据),不是「等够久了」——「超时永不产生 denial」因此成立。
|
|
71
|
+
*/
|
|
72
|
+
readonly ROUTING_FAILURE: "routing_failure_fail_closed";
|
|
73
|
+
/**
|
|
74
|
+
* 启动收敛(`approval-crash-convergence.ts`,local 车道):**承载这一问的进程没了** —— 前世进程崩溃 / 被杀,留下的 `STREAM_PENDING` 行在下一次启动、任何卡能开始之前收成 VOID。
|
|
75
|
+
* 证据是数据根 `LOCK`(前世写者全死),不是「等够久了」。值与 `GET /v1/approvals` `crashConverged[].cause` 是**同一个词**。
|
|
76
|
+
*/
|
|
77
|
+
readonly CRASHED_BEFORE_PARK: "crashed_before_park";
|
|
78
|
+
/** 同上,但承载它的腿是被**有序关停**截断的(审计账本上有本腿的关停记号;关停收尾没能在宽限窗内把这张卡结清),或有序关停期间这张卡被改路停驻(settle 行的成因)。 */
|
|
79
|
+
readonly SHUTDOWN_BEFORE_PARK: "shutdown_before_park";
|
|
80
|
+
/** 判据 5:任何在 `STREAM_APPROVAL_ORPHAN_TTL_MS` 内仍未收敛的 `PARKING` 行(量 immutable 的 `createdAtMs`,§9 C5)—— 遗孤最终可判的最后兜底,带一条 warn。 */
|
|
53
81
|
readonly ORPHAN_TTL_EXCEEDED: "orphan_ttl_exceeded";
|
|
54
82
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* 🔴 值与 `GET /v1/approvals` `crashConverged[].cause` 是**同一个词**(审计店的 `CrashConvergedCause` 从本表取型):
|
|
58
|
-
* 同一问在两个读面上只有一个成因词。
|
|
83
|
+
* 判据 4:adhoc 腿(`sessionId === taskId` ∧ `getRun` 无行)窗过 + 宽限 —— 该腿形**结构上**没有 durable 对账域(一次性 taskId 不进 runStore,park 目的地不可寻址),流死即 abort 语义。
|
|
84
|
+
* 🔴 落 VOID 不落 DENIED:VOID 不是 denial,「超时永不产生 denial」不被触碰。
|
|
59
85
|
*/
|
|
60
|
-
readonly
|
|
61
|
-
/**
|
|
62
|
-
readonly
|
|
86
|
+
readonly ADHOC_LEG_NO_DURABLE_DOMAIN: "adhoc_leg_no_durable_domain";
|
|
87
|
+
/** 决议绑的动作 / 输入被换了(core `detail.field` ∈ `boundCallId` / `boundInputHash`,不论写者版本 —— 绑定值由写者引擎铸进卡帧、调用方原样回传、core 等值比较):重取 pending 列表换坐标再决。 */
|
|
88
|
+
readonly BINDING_CHANGED: "binding_changed";
|
|
89
|
+
/** 决议体里的 `answer` 不合法(core `detail.field` = `answer`):把答案改对再决。 */
|
|
90
|
+
readonly ANSWER_INVALID: "answer_invalid";
|
|
91
|
+
/** 决议体里某一格不合法(`hostDecision` / `approver` / `boundGrantDigest`,或 plan / dry-run 审阅门上 editedPlan / reason 的内容净化被拒):把那一格改对再决。 */
|
|
92
|
+
readonly OUTCOME_CELL_INVALID: "outcome_cell_invalid";
|
|
63
93
|
};
|
|
64
|
-
export type
|
|
65
|
-
/**
|
|
66
|
-
export
|
|
67
|
-
/**
|
|
68
|
-
|
|
94
|
+
export type ApprovalEndingCause = (typeof APPROVAL_ENDING_CAUSES)[keyof typeof APPROVAL_ENDING_CAUSES];
|
|
95
|
+
/** 全部成因词(机器判据用:值域互不相同 + 列宽 ≤ 64 的钉子在 test/approval-reconciler.test.ts)。 */
|
|
96
|
+
export declare const ALL_APPROVAL_ENDING_CAUSES: readonly ApprovalEndingCause[];
|
|
97
|
+
/**
|
|
98
|
+
* 审计 settle 行 `cause` 的读盘词表(S-929 形):{@link SettleCause} 的穷举,`satisfies Record<SettleCause, true>` ⇒ 闭集加一个非决断类的词而本表没跟 = **编译红**(多一个词同样红);
|
|
99
|
+
* 判定走 `Object.hasOwn`,原型链上的名字不算词。决断类三词({@link DecisionRefusalCause})拒一次决议、不结束一张卡 ⇒ 不是 settle 行的成因,读到它们照词表外处置(计坏行)。
|
|
100
|
+
* 唯一读者 = {@link isSettleCause}。
|
|
101
|
+
*/
|
|
102
|
+
export declare const SETTLE_CAUSE_WORDS: {
|
|
103
|
+
readonly ttl_expired: true;
|
|
104
|
+
readonly broadcast_lost: true;
|
|
105
|
+
readonly stream_disconnected: true;
|
|
106
|
+
readonly undeliverable: true;
|
|
107
|
+
readonly run_cancelled: true;
|
|
108
|
+
readonly run_exited: true;
|
|
109
|
+
readonly batch_aborted: true;
|
|
110
|
+
readonly batch_sibling_withdrawn: true;
|
|
111
|
+
readonly batch_bound_elsewhere: true;
|
|
112
|
+
readonly routing_failure_fail_closed: true;
|
|
113
|
+
readonly crashed_before_park: true;
|
|
114
|
+
readonly shutdown_before_park: true;
|
|
115
|
+
readonly orphan_ttl_exceeded: true;
|
|
116
|
+
readonly adhoc_leg_no_durable_domain: true;
|
|
117
|
+
};
|
|
118
|
+
/** 一个值是不是非人结局的成因词(审计账读盘用这一只判词)。 */
|
|
119
|
+
export declare function isSettleCause(v: unknown): v is SettleCause;
|
|
120
|
+
/** 「承载这一问的进程没了」的两个成因词(启动收敛写进问账行 `denied_reason`,审计收敛行 `cause` 读同一型)。 */
|
|
121
|
+
export type HolderGoneCause = typeof APPROVAL_ENDING_CAUSES.CRASHED_BEFORE_PARK | typeof APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK;
|
|
122
|
+
/** 对账器 `DENIED` 终态的成因(单员:全仓 DENIED 只有一个写点)。 */
|
|
123
|
+
export type ReconcileDenyCause = typeof APPROVAL_ENDING_CAUSES.ROUTING_FAILURE;
|
|
124
|
+
/** 对账器 `VOID` 终态的成因(判据 2 取消分臂 / 批已 ABORTED / bind-once 落选者 / 判据 4 adhoc / 判据 5 遗孤 TTL)。 */
|
|
125
|
+
export type ReconcileVoidCause = typeof APPROVAL_ENDING_CAUSES.RUN_CANCELLED | typeof APPROVAL_ENDING_CAUSES.BATCH_ABORTED | typeof APPROVAL_ENDING_CAUSES.BATCH_BOUND_ELSEWHERE | typeof APPROVAL_ENDING_CAUSES.ADHOC_LEG_NO_DURABLE_DOMAIN | typeof APPROVAL_ENDING_CAUSES.ORPHAN_TTL_EXCEEDED;
|
|
126
|
+
/**
|
|
127
|
+
* 问账行(`approval_ask`)上**终态成因**能落的词(决断口 410 `gone.ask` 体与晚答 404 体的 `cause` 的值域):对账器的 DENIED / VOID 写点 + 启动收敛 + 店内的 VOID 写点
|
|
128
|
+
* (取消赢下 VOID ⇒ `run_cancelled` / `run_exited`,兄弟被撤卡 ⇒ `batch_sibling_withdrawn`)。窗到期 / 广播全灭 / 决断类的词只落审计 settle 行或 409 码,不落这一列。
|
|
129
|
+
*/
|
|
130
|
+
export type AskRowEndingCause = ReconcileDenyCause | ReconcileVoidCause | HolderGoneCause | typeof APPROVAL_ENDING_CAUSES.RUN_EXITED | typeof APPROVAL_ENDING_CAUSES.BATCH_SIBLING_WITHDRAWN;
|
|
131
|
+
/** 问账行 `denied_reason` 列在 VOID / DENIED 行上的读词表({@link AskRowEndingCause} 的穷举,`satisfies` ⇒ 子集加词而本表没跟 = 编译红)。唯一读者 = {@link causeOfAskRow}。 */
|
|
132
|
+
export declare const ASK_ROW_ENDING_CAUSE_WORDS: {
|
|
133
|
+
readonly routing_failure_fail_closed: true;
|
|
134
|
+
readonly run_cancelled: true;
|
|
135
|
+
readonly run_exited: true;
|
|
136
|
+
readonly batch_aborted: true;
|
|
137
|
+
readonly batch_sibling_withdrawn: true;
|
|
138
|
+
readonly batch_bound_elsewhere: true;
|
|
139
|
+
readonly adhoc_leg_no_durable_domain: true;
|
|
140
|
+
readonly orphan_ttl_exceeded: true;
|
|
141
|
+
readonly crashed_before_park: true;
|
|
142
|
+
readonly shutdown_before_park: true;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* `expire` 终局 claim(窗到期 / 广播全灭 / 有序关停把一张卡转投递面 = `PARKING`)赢下时写进这一行 `denied_reason` 的**触发成因**:这一行此后若走到 `DENIED` / `VOID`,终态成因会覆盖它
|
|
146
|
+
* ({@link AskRowEndingCause});`PARKED` 行的这一格就是「它为什么被转 park」。跨副本的读者(另一进程的悬挂腿轮询、CAS 败方读数)读到 `PARKING` / `PARKED` 时靠它归因,
|
|
147
|
+
* 不替没写的行猜一个词。
|
|
148
|
+
*/
|
|
149
|
+
export type ParkTriggerCause = typeof APPROVAL_ENDING_CAUSES.TTL_EXPIRED | typeof APPROVAL_ENDING_CAUSES.BROADCAST_LOST | typeof APPROVAL_ENDING_CAUSES.STREAM_DISCONNECTED | typeof APPROVAL_ENDING_CAUSES.UNDELIVERABLE | typeof APPROVAL_ENDING_CAUSES.SHUTDOWN_BEFORE_PARK;
|
|
150
|
+
/** 问账行 `denied_reason` 在 `PARKING` / `PARKED` 行上的读词表({@link ParkTriggerCause} 的穷举)。唯一读者 = {@link causeOfAskRow}。 */
|
|
151
|
+
export declare const PARK_TRIGGER_CAUSE_WORDS: {
|
|
152
|
+
readonly ttl_expired: true;
|
|
153
|
+
readonly broadcast_lost: true;
|
|
154
|
+
readonly stream_disconnected: true;
|
|
155
|
+
readonly undeliverable: true;
|
|
156
|
+
readonly shutdown_before_park: true;
|
|
157
|
+
};
|
|
158
|
+
/** 问账行成因的读数:`kind` 说这一个词在这一行上是哪种意思(终态成因 / 转 park 的触发成因)。 */
|
|
159
|
+
export type AskRowCause = {
|
|
160
|
+
readonly kind: "ending";
|
|
161
|
+
readonly cause: AskRowEndingCause;
|
|
162
|
+
} | {
|
|
163
|
+
readonly kind: "park_trigger";
|
|
164
|
+
readonly cause: ParkTriggerCause;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* 🔴 **问账行成因的唯一读口**:`denied_reason` 一列按 `state` 承载两种意思,本函数按 `state` 穷举分派(加状态 ⇒ 这里编译红),读者不自己先判 state 再查表:
|
|
168
|
+
* · `VOID` / `DENIED` ⇒ 终态成因({@link AskRowEndingCause};决断口 410、晚答 404、CAS 败方读数、悬挂腿的轮询读这一种);
|
|
169
|
+
* · `PARKING` / `PARKED` ⇒ 转 park 的触发成因({@link ParkTriggerCause};跨副本的悬挂腿与 CAS 败方读这一种);
|
|
170
|
+
* · `DECIDED` / `STREAM_PENDING` / `absent`(败方读数的「行不在」)⇒ 无成因。
|
|
171
|
+
* 列值 `null` / 键缺席(没写归因的存量行)或与 state 不配的词(手改 / 将来版本写的词)⇒ `undefined`(读面缺席即缺席,不替没写的行编一个成因)。返回纯数据。
|
|
172
|
+
*/
|
|
173
|
+
export declare function causeOfAskRow(row: {
|
|
174
|
+
readonly state: AskState | "absent";
|
|
175
|
+
readonly deniedReason?: string | null;
|
|
176
|
+
}): AskRowCause | undefined;
|
|
177
|
+
/** 非人**结局**的成因(审计 settle 行 `cause`、活卡结局帧 `tool_approval_complete.cause`):闭集去掉决断口 409 的三个词({@link DecisionRefusalCause})—— 那三个词不结束一张卡,只拒一次决议。 */
|
|
178
|
+
export type SettleCause = Exclude<ApprovalEndingCause, DecisionRefusalCause>;
|
|
179
|
+
/** 决断口 409 的成因子集(core 的 `detail.field` → 码;每词一个码,见 `http/resume-legs.ts`)。 */
|
|
180
|
+
export type DecisionRefusalCause = typeof APPROVAL_ENDING_CAUSES.BINDING_CHANGED | typeof APPROVAL_ENDING_CAUSES.ANSWER_INVALID | typeof APPROVAL_ENDING_CAUSES.OUTCOME_CELL_INVALID;
|
|
69
181
|
//# sourceMappingURL=approval-deny-reasons.d.ts.map
|
|
@@ -1,14 +1,85 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export const SETTLE_OUTCOME = { ALLOWED: "allowed", DENIED: "denied", EXPIRED: "expired" };
|
|
2
|
+
export const APPROVAL_ENDING_CAUSES = {
|
|
3
|
+
TTL_EXPIRED: "ttl_expired",
|
|
4
|
+
BROADCAST_LOST: "broadcast_lost",
|
|
5
|
+
STREAM_DISCONNECTED: "stream_disconnected",
|
|
6
|
+
UNDELIVERABLE: "undeliverable",
|
|
5
7
|
RUN_CANCELLED: "run_cancelled",
|
|
8
|
+
RUN_EXITED: "run_exited",
|
|
6
9
|
BATCH_ABORTED: "batch_aborted",
|
|
10
|
+
BATCH_SIBLING_WITHDRAWN: "batch_sibling_withdrawn",
|
|
7
11
|
BATCH_BOUND_ELSEWHERE: "batch_bound_elsewhere",
|
|
8
|
-
|
|
12
|
+
ROUTING_FAILURE: "routing_failure_fail_closed",
|
|
13
|
+
CRASHED_BEFORE_PARK: "crashed_before_park",
|
|
14
|
+
SHUTDOWN_BEFORE_PARK: "shutdown_before_park",
|
|
9
15
|
ORPHAN_TTL_EXCEEDED: "orphan_ttl_exceeded",
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
ADHOC_LEG_NO_DURABLE_DOMAIN: "adhoc_leg_no_durable_domain",
|
|
17
|
+
BINDING_CHANGED: "binding_changed",
|
|
18
|
+
ANSWER_INVALID: "answer_invalid",
|
|
19
|
+
OUTCOME_CELL_INVALID: "outcome_cell_invalid",
|
|
20
|
+
};
|
|
21
|
+
export const ALL_APPROVAL_ENDING_CAUSES = Object.values(APPROVAL_ENDING_CAUSES);
|
|
22
|
+
export const SETTLE_CAUSE_WORDS = {
|
|
23
|
+
ttl_expired: true,
|
|
24
|
+
broadcast_lost: true,
|
|
25
|
+
stream_disconnected: true,
|
|
26
|
+
undeliverable: true,
|
|
27
|
+
run_cancelled: true,
|
|
28
|
+
run_exited: true,
|
|
29
|
+
batch_aborted: true,
|
|
30
|
+
batch_sibling_withdrawn: true,
|
|
31
|
+
batch_bound_elsewhere: true,
|
|
32
|
+
routing_failure_fail_closed: true,
|
|
33
|
+
crashed_before_park: true,
|
|
34
|
+
shutdown_before_park: true,
|
|
35
|
+
orphan_ttl_exceeded: true,
|
|
36
|
+
adhoc_leg_no_durable_domain: true,
|
|
37
|
+
};
|
|
38
|
+
export function isSettleCause(v) {
|
|
39
|
+
return typeof v === "string" && Object.hasOwn(SETTLE_CAUSE_WORDS, v);
|
|
40
|
+
}
|
|
41
|
+
export const ASK_ROW_ENDING_CAUSE_WORDS = {
|
|
42
|
+
routing_failure_fail_closed: true,
|
|
43
|
+
run_cancelled: true,
|
|
44
|
+
run_exited: true,
|
|
45
|
+
batch_aborted: true,
|
|
46
|
+
batch_sibling_withdrawn: true,
|
|
47
|
+
batch_bound_elsewhere: true,
|
|
48
|
+
adhoc_leg_no_durable_domain: true,
|
|
49
|
+
orphan_ttl_exceeded: true,
|
|
50
|
+
crashed_before_park: true,
|
|
51
|
+
shutdown_before_park: true,
|
|
52
|
+
};
|
|
53
|
+
function isAskRowEndingCause(v) {
|
|
54
|
+
return Object.hasOwn(ASK_ROW_ENDING_CAUSE_WORDS, v);
|
|
55
|
+
}
|
|
56
|
+
export const PARK_TRIGGER_CAUSE_WORDS = {
|
|
57
|
+
ttl_expired: true,
|
|
58
|
+
broadcast_lost: true,
|
|
59
|
+
stream_disconnected: true,
|
|
60
|
+
undeliverable: true,
|
|
61
|
+
shutdown_before_park: true,
|
|
12
62
|
};
|
|
13
|
-
|
|
63
|
+
function isParkTriggerCause(v) {
|
|
64
|
+
return Object.hasOwn(PARK_TRIGGER_CAUSE_WORDS, v);
|
|
65
|
+
}
|
|
66
|
+
export function causeOfAskRow(row) {
|
|
67
|
+
const stored = row.deniedReason;
|
|
68
|
+
switch (row.state) {
|
|
69
|
+
case "VOID":
|
|
70
|
+
case "DENIED":
|
|
71
|
+
return stored !== null && stored !== undefined && isAskRowEndingCause(stored) ? { kind: "ending", cause: stored } : undefined;
|
|
72
|
+
case "PARKING":
|
|
73
|
+
case "PARKED":
|
|
74
|
+
return stored !== null && stored !== undefined && isParkTriggerCause(stored) ? { kind: "park_trigger", cause: stored } : undefined;
|
|
75
|
+
case "DECIDED":
|
|
76
|
+
case "STREAM_PENDING":
|
|
77
|
+
case "absent":
|
|
78
|
+
return undefined;
|
|
79
|
+
default: {
|
|
80
|
+
const unhandled = row.state;
|
|
81
|
+
throw new Error(`causeOfAskRow: unhandled ask row state ${String(unhandled)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
14
85
|
//# sourceMappingURL=approval-deny-reasons.js.map
|
|
@@ -23,9 +23,12 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import type { ApprovalAskStore, AskRow, AskTerminalClaimOutcome } from "./plugins/approval-ask-store-sql.js";
|
|
25
25
|
import type { UnattendedApprovalPolicy } from "./tool-approval.js";
|
|
26
|
+
import type { ParkTriggerCause } from "./approval-deny-reasons.js";
|
|
26
27
|
/**
|
|
27
28
|
* 按部署政策给这一只 ask 行打原子终局 claim(见文件头:四个调用点、两个意图、答案自足)。`row` 只取 scope 两维 ——
|
|
28
29
|
* `batchId` 必须是**行上**的批(幂等命中的存量行可能是别的政策 / 旧版本铸的整腿批,错 scope 的 claim 如实 `absent`)。
|
|
29
30
|
*/
|
|
30
|
-
export declare function settleByPolicy(store: Pick<ApprovalAskStore, "claimTerminal">, row: Pick<AskRow, "askId" | "batchId">, policy: UnattendedApprovalPolicy
|
|
31
|
+
export declare function settleByPolicy(store: Pick<ApprovalAskStore, "claimTerminal">, row: Pick<AskRow, "askId" | "batchId">, policy: UnattendedApprovalPolicy,
|
|
32
|
+
/** 转 park 的触发成因(窗到期 / 广播全灭 / 有序关停):`park` 政策的 `expire` 赢下 PARKING 时随同一步写进行(`denied_reason`),跨副本的读者据它归因;`deny` 政策落的是一条决议,不带。 */
|
|
33
|
+
cause: ParkTriggerCause): Promise<AskTerminalClaimOutcome>;
|
|
31
34
|
//# sourceMappingURL=approval-policy-settlement.d.ts.map
|
|
@@ -10,7 +10,8 @@ function unattendedClaimIntent(policy) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
export function settleByPolicy(store, row, policy) {
|
|
14
|
-
|
|
13
|
+
export function settleByPolicy(store, row, policy, cause) {
|
|
14
|
+
const intent = unattendedClaimIntent(policy);
|
|
15
|
+
return store.claimTerminal(row.askId, row.batchId, intent, intent === "expire" ? { cause } : undefined);
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=approval-policy-settlement.js.map
|
|
@@ -5,7 +5,7 @@ import type { CheckpointAskCandidate } from "./plugins/checkpoint-store-sql.js";
|
|
|
5
5
|
import { type RunRecord } from "./plugins/store-contracts.js";
|
|
6
6
|
import type { Logger } from "./observability/logger.js";
|
|
7
7
|
import type { Metrics } from "./observability/metrics.js";
|
|
8
|
-
import { type
|
|
8
|
+
import { type ReconcileDenyCause, type ReconcileVoidCause } from "./approval-deny-reasons.js";
|
|
9
9
|
import { type ApprovalRevokeFrame } from "./approval-card.js";
|
|
10
10
|
import type { ParkCommitWatch } from "./plugins/park-commit-watch.js";
|
|
11
11
|
/** 判据表 v2 的一次判定结果(纯数据;执行器按 kind 分派到店面的一次 CAS)。 */
|
|
@@ -18,10 +18,10 @@ export type ReconcileAction = {
|
|
|
18
18
|
};
|
|
19
19
|
} | {
|
|
20
20
|
kind: "deny";
|
|
21
|
-
reason:
|
|
21
|
+
reason: ReconcileDenyCause;
|
|
22
22
|
} | {
|
|
23
23
|
kind: "void";
|
|
24
|
-
reason:
|
|
24
|
+
reason: ReconcileVoidCause;
|
|
25
25
|
} | {
|
|
26
26
|
kind: "hold";
|
|
27
27
|
};
|