@sema-agent/server 7.117.0 → 7.118.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 +97 -0
- package/USAGE.md +37 -18
- package/dist/approval-card.d.ts +40 -10
- package/dist/approval-card.js +11 -1
- package/dist/approval.d.ts +4 -12
- package/dist/approval.js +4 -26
- package/dist/boot/parked-revive-gate.d.ts +1 -7
- package/dist/boot/parked-revive-gate.js +2 -12
- package/dist/boot/resolve-spec.js +8 -13
- package/dist/boot/runner-deps.js +2 -2
- package/dist/boot/stage-07-capability-layer.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +25 -0
- package/dist/capabilities/hands-lane.js +1 -1
- package/dist/capabilities/mcp-probe.d.ts +2 -2
- package/dist/config.d.ts +14 -18
- package/dist/config.js +13 -24
- package/dist/deployment-governance.d.ts +2 -7
- package/dist/deployment-governance.js +3 -5
- package/dist/host-decision.d.ts +83 -25
- package/dist/host-decision.js +31 -1
- package/dist/http/admission.js +7 -1
- package/dist/http/approval-sweeps.js +1 -1
- package/dist/http/mcp-dial-deadline.d.ts +35 -0
- package/dist/http/mcp-dial-deadline.js +21 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +11 -5
- package/dist/http/memory-compliance-failure-reply.js +17 -8
- package/dist/http/memory-store-refusal-reply.d.ts +14 -11
- package/dist/http/memory-store-refusal-reply.js +16 -5
- package/dist/http/resume-legs.js +7 -3
- package/dist/http/routes/approvals-assistant.js +21 -24
- package/dist/http/routes/capabilities.js +2 -0
- package/dist/http/routes/mcp-reconnect.d.ts +17 -0
- package/dist/http/routes/mcp-reconnect.js +6 -1
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/runs.js +41 -33
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +3 -6
- package/dist/http/routes/workflows.js +2 -0
- package/dist/http/wire-types.d.ts +6 -1
- package/dist/memory-store-refusal.d.ts +42 -17
- package/dist/memory-store-refusal.js +25 -6
- package/dist/model-unreachable-notice.d.ts +1 -1
- package/dist/namespaced-rule-name.d.ts +45 -41
- package/dist/namespaced-rule-name.js +36 -22
- package/dist/observability/corrupt-read-seat.d.ts +4 -0
- package/dist/observability/corrupt-read-seat.js +1 -0
- package/dist/observability/fail-open.d.ts +14 -2
- package/dist/observability/fail-open.js +14 -2
- package/dist/operator-ask.d.ts +4 -1
- package/dist/orchestration/workflow-agent-session-index.d.ts +82 -59
- package/dist/orchestration/workflow-agent-session-index.js +80 -14
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -0
- package/dist/orchestration/workflow-completion-inbox.js +39 -17
- package/dist/orchestration/workflow-notify-journal.d.ts +1 -1
- package/dist/orchestration/workflow-notify-journal.js +7 -2
- package/dist/outbound-dispatcher.d.ts +29 -20
- package/dist/outbound-dispatcher.js +105 -16
- package/dist/parked-decide.d.ts +43 -48
- package/dist/parked-decide.js +54 -16
- package/dist/permission-rule-vocab.d.ts +4 -3
- package/dist/permission-rule-vocab.js +1 -1
- package/dist/plugins/approval-ask-store-sql.d.ts +17 -20
- package/dist/plugins/approval-ask-store-sql.js +0 -3
- package/dist/plugins/one-time-migrations.d.ts +5 -0
- package/dist/plugins/one-time-migrations.js +110 -4
- package/dist/plugins/pg-pool.js +1 -1
- package/dist/plugins/tidb-pool.js +1 -1
- package/dist/plugins/web-search.d.ts +20 -1
- package/dist/plugins/web-search.js +39 -10
- package/dist/plugins/workflow-run-store-sql.d.ts +7 -6
- package/dist/plugins/workflow-run-store-sql.js +5 -7
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +1 -1
- package/dist/rule-entry-list.d.ts +35 -46
- package/dist/rule-entry-list.js +17 -25
- package/dist/rules-consent.js +3 -0
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +1 -1
- package/dist/session-policy-wire.d.ts +13 -12
- package/dist/session-policy-wire.js +11 -6
- package/dist/spec-fields.d.ts +7 -9
- package/dist/spec-fields.js +4 -7
- package/dist/standing-answer-grant.d.ts +14 -2
- package/dist/standing-answer-grant.js +8 -1
- package/dist/task-settings.js +8 -4
- package/dist/tool-approval.d.ts +53 -112
- package/dist/tool-approval.js +75 -55
- package/dist/trace/core-keyset-guard.d.ts +5 -5
- package/dist/trace/self-minted-wire.d.ts +16 -2
- package/dist/trace/self-minted-wire.js +7 -0
- package/dist/user-input-ledger.d.ts +24 -12
- package/dist/user-input-ledger.js +33 -14
- package/package.json +2 -2
- package/scripts/drain-check-local.mjs +74 -3
- package/scripts/drain-check.mysql.sql +43 -17
- package/scripts/drain-check.pg.sql +46 -20
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* ·
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
2
|
+
* 规则里的工具名**够不够得着**一只挂载工具 —— 本仓唯一的一问(判官 + 句子各一只),其余全是引擎判官 `judgeRuleToolName` 的判词。
|
|
3
|
+
*
|
|
4
|
+
* 一个名字永远匹配不到工具的成因,判官是谁:
|
|
5
|
+
* · 退役名 / 无协议前缀的 `__` 短名 / **协议名的对端段引擎铸不出**(`mcp__github.com__*`、`mcp__*`、`mcp____x`、`mcp__`)—— 引擎判官
|
|
6
|
+
* (`retired` / `unprefixed_namespace` / `unmintable_segment`,带 `guidance` 与 1:1 `currentName`)。本仓不再拿 `mintNamespacePrefix` 自比对端段:
|
|
7
|
+
* 那是同一问的第二个读者(core 7.43.0 #1355 (b) 起引擎自己给这个判词)。
|
|
8
|
+
* · **工具段为空的协议名**(`mcp__srv__`)—— 引擎判官答 `current`、规则文法收下、allow 条目读成一条精确名行,而它一只工具都够不着
|
|
9
|
+
* (引擎自己的两种拆法 —— 精确名 `ns.parse`、覆盖形 `isNamespacedCoveringRuleName` —— 都不认它)。这是引擎读不到的一形,本仓在下面点名的那些面上
|
|
10
|
+
* 拒它({@link emptyToolSegmentOf}),句子在这里({@link describeEmptyToolSegment})。翻转条件:引擎判官给这一形一个判词 ⇒ 本文件整只退役。
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
12
|
+
* **调它的面**(点名,不是「每个面」;判官一问与本仓这一问同调):
|
|
13
|
+
* · 运维三张名表(`APPROVAL_REQUIRE` / `DENY` / `NEVER_AUTO`)与中心下发的同名表、请求 `settings.permissions.{ask,deny}`(经 `config.ts` 的 `unmatchableToolNamesRefusal`);
|
|
14
|
+
* · 会话规则写口(`session-policy-wire.ts`)与 SQL 会话规则店的写口(`assertSessionRuleNamesReachable`);
|
|
15
|
+
* · 引擎 allow 层的条目表:请求的 `settings.permissions.allow`、运维的 `APPROVAL_GRANT`、技能的两只清单 `allowedTools` / `disallowedTools`(顶层 `skills[]` 与子代
|
|
16
|
+
* `agents[].skills[]` 两处受理口)—— 经 `rule-entry-list.ts` 的 `emptyToolSegmentEntryOf`(本仓这一问;退役名 / 铸不出的判词那一半由引擎 `compileAllowList` 给)。
|
|
17
|
+
* **不调它的面**(如实,未接):`/v1/rules` 的持久规则写口与 `cc-import` 导入口(`http/routes/rules.ts`、`rules-consent.ts` 与两只持久规则店零判官调用)、子代的工具名表
|
|
18
|
+
* `agents[].allowTools` / `denyTools`(`spec-fields.ts` 只判形与条数)。在这两处写铸不出的服务器段、工具段为空的协议名仍被收下、永不命中。把这些面接上判官 = 另一件事
|
|
19
|
+
* (本版不做,也不在本文件里加特例;`unmatchableRuleNameOf` 就是现成的那一只)。
|
|
20
|
+
* **精确名的工具段归一不在这里判**:包根没有导出工具段的铸法,不手抄 —— 精确名的工具段按字面收,本仓每张表上都不判它。
|
|
20
21
|
*
|
|
21
|
-
*
|
|
22
|
-
* 只有 current / retired / unprefixed_namespace,亲核),等上游;到货那天本仓这只对照整只退役(连同会话规则写口这一问的码由 `request.field_invalid`
|
|
23
|
-
* 归回 `rules.legacy_tool_name`)。
|
|
22
|
+
* 规则文本里「工具名那一段」怎么取也只有一种读法:{@link ruleEntryToolName}(配置表与技能清单同读)。
|
|
24
23
|
*/
|
|
25
|
-
import { type ProtocolNamespace } from "@sema-agent/core";
|
|
24
|
+
import { type ProtocolNamespace, type RuleToolNameVerdict } from "@sema-agent/core";
|
|
26
25
|
/**
|
|
27
26
|
* 一条**规则文本**里的工具名那一段(判官与旧名判据的主语)= core 包根 `parsePermissionRule` 的 `toolName`,原样 —— 引擎的技能编译器
|
|
28
27
|
* (`compileSkillGrant`)与规则编译器读条目用的就是这一只:`Bash(npm:*)` ⇒ `Bash`;`mcp__srv(*)` / `mcp__srv()` / 带首尾空格的 `mcp__srv ` ⇒ 光杆名 `mcp__srv`。
|
|
@@ -31,26 +30,31 @@ import { type ProtocolNamespace } from "@sema-agent/core";
|
|
|
31
30
|
* `unsupported.mcp_paren`),拒由引擎的文法那一问说(配置表的判据链里它排在本判官之前),本判官不抢答。
|
|
32
31
|
*/
|
|
33
32
|
export declare function ruleEntryToolName(entry: string): string;
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
| {
|
|
43
|
-
readonly kind: "
|
|
44
|
-
readonly ns: ProtocolNamespace;
|
|
45
|
-
readonly minted: string;
|
|
46
|
-
}
|
|
47
|
-
/** 对端段里带 `*`:写的是通配,而服务器 / 对端名不支持通配(规则对这一段逐字比)。 */
|
|
48
|
-
| {
|
|
49
|
-
readonly kind: "wildcard_peer";
|
|
33
|
+
/**
|
|
34
|
+
* 判官的名册:本仓的配置表 / 请求表 / 会话规则写口都不声明「部署在退役名下挂了自有工具」(本仓没有这样的工具;boot / 请求期也没有哪一跑的名册可看)
|
|
35
|
+
* ⇒ 恒为空集。引擎判官、`compileAllowList` 的第三参、会话规则店同读这一只。
|
|
36
|
+
*/
|
|
37
|
+
export declare const NO_DECLARED_TOOL_NAMES: ReadonlySet<string>;
|
|
38
|
+
/** 一个规则名永远匹配不到工具的判词(闭集):引擎判官的三种非现行判词 ∪ 引擎读不到的那一形。 */
|
|
39
|
+
export type UnmatchableRuleName = Exclude<RuleToolNameVerdict, {
|
|
40
|
+
kind: "current";
|
|
41
|
+
}> | {
|
|
42
|
+
readonly kind: "empty_tool_segment";
|
|
50
43
|
readonly ns: ProtocolNamespace;
|
|
51
44
|
};
|
|
52
|
-
/**
|
|
53
|
-
export declare function
|
|
54
|
-
/**
|
|
55
|
-
|
|
45
|
+
/** 判:引擎判官先答(非 `current` ⇒ 原样交回),判官放行的再问引擎读不到的那一形;都过 ⇒ `undefined`。 */
|
|
46
|
+
export declare function unmatchableRuleNameOf(name: string): UnmatchableRuleName | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* 判词 → 「为什么永远匹配不到 + 怎么写」(不复述条目本身 —— 调用方的句子已点名它)。引擎判词的 `guidance` 原样带出,是改法指引的**唯一**一句
|
|
49
|
+
* (本仓不在后面追加 1:1 现名:通配名上那个现名是摘要名或更窄的写法,照写不生效;现名过境给机器读的位,如会话规则拒体顶层的 `currentName`);
|
|
50
|
+
* 无前缀短名的出路从 core 的 `PROTOCOL_TABLE` 派生。闭集穷尽:判词加一种 ⇒ 编译红。
|
|
51
|
+
*/
|
|
52
|
+
export declare function describeUnmatchableRuleName(v: UnmatchableRuleName, name: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* 工具段为空的协议名(`<ns>__<peer>__`)⇒ 交回它的协议;别的名字 ⇒ `undefined`。判据只读引擎:判官答 `current`(对端段为空 / 铸不出的那些 ——
|
|
55
|
+
* `mcp__`、`mcp____x` —— 是判官自己的判词,不在这里),而引擎自己的两种拆法(精确名 `ns.parse`、覆盖形 `isNamespacedCoveringRuleName`)都不认它。纯字符串运算。
|
|
56
|
+
*/
|
|
57
|
+
export declare function emptyToolSegmentOf(name: string): ProtocolNamespace | undefined;
|
|
58
|
+
/** {@link emptyToolSegmentOf} 的句子(「为什么永远匹配不到 + 怎么写」;不复述条目本身 —— 调用方的句子已点名它)。 */
|
|
59
|
+
export declare function describeEmptyToolSegment(ns: ProtocolNamespace): string;
|
|
56
60
|
//# sourceMappingURL=namespaced-rule-name.d.ts.map
|
|
@@ -1,33 +1,47 @@
|
|
|
1
|
-
import { isNamespacedCoveringRuleName,
|
|
1
|
+
import { PROTOCOL_TABLE, isNamespacedCoveringRuleName, judgeRuleToolName, parsePermissionRule, protocolOf } from "@sema-agent/core";
|
|
2
|
+
import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
|
|
2
3
|
export function ruleEntryToolName(entry) {
|
|
3
4
|
return parsePermissionRule(entry).toolName;
|
|
4
5
|
}
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (peer.includes("*"))
|
|
13
|
-
return { kind: "wildcard_peer", ns };
|
|
14
|
-
const minted = mintNamespacePrefix(ns, peer);
|
|
15
|
-
return minted === `${ns.prefix}${peer}__` ? undefined : { kind: "unminted_peer", ns, minted };
|
|
6
|
+
export const NO_DECLARED_TOOL_NAMES = new Set();
|
|
7
|
+
export function unmatchableRuleNameOf(name) {
|
|
8
|
+
const verdict = judgeRuleToolName(name, NO_DECLARED_TOOL_NAMES);
|
|
9
|
+
if (verdict.kind !== "current")
|
|
10
|
+
return verdict;
|
|
11
|
+
const ns = emptyToolSegmentOf(name);
|
|
12
|
+
return ns === undefined ? undefined : { kind: "empty_tool_segment", ns };
|
|
16
13
|
}
|
|
17
|
-
|
|
14
|
+
function presentName(name) {
|
|
15
|
+
const clean = name.replace(CONTROL_AND_BIDI_STRIP_RE, "");
|
|
16
|
+
return clean.length <= 160 ? clean : `${clean.slice(0, 160)}…(${name.length} chars)`;
|
|
17
|
+
}
|
|
18
|
+
export function describeUnmatchableRuleName(v, name) {
|
|
18
19
|
switch (v.kind) {
|
|
19
|
-
case "
|
|
20
|
-
return
|
|
21
|
-
case "
|
|
22
|
-
return
|
|
23
|
-
case "
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
case "retired":
|
|
21
|
+
return v.guidance;
|
|
22
|
+
case "unmintable_segment":
|
|
23
|
+
return v.guidance;
|
|
24
|
+
case "unprefixed_namespace":
|
|
25
|
+
return `pre-prefix short form — the live name carries a protocol prefix: ${PROTOCOL_TABLE.map((e) => `${e.prefix}${presentName(name)}`).join(" or ")}`;
|
|
26
|
+
case "empty_tool_segment":
|
|
27
|
+
return describeEmptyToolSegment(v.ns);
|
|
27
28
|
default: {
|
|
28
29
|
const unhandled = v;
|
|
29
|
-
throw new Error(`unhandled
|
|
30
|
+
throw new Error(`unhandled rule name verdict: ${JSON.stringify(unhandled)}`);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
export function emptyToolSegmentOf(name) {
|
|
35
|
+
const ns = protocolOf(name);
|
|
36
|
+
if (ns === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (judgeRuleToolName(name, NO_DECLARED_TOOL_NAMES).kind !== "current")
|
|
39
|
+
return undefined;
|
|
40
|
+
if (ns.parse(name) !== undefined || isNamespacedCoveringRuleName(name))
|
|
41
|
+
return undefined;
|
|
42
|
+
return ns;
|
|
43
|
+
}
|
|
44
|
+
export function describeEmptyToolSegment(ns) {
|
|
45
|
+
return `incomplete ${ns.id} name — the live form is ${ns.prefix}<server>__<tool>, or ${ns.prefix}<server> / ${ns.prefix}<server>__* to cover every tool on that server`;
|
|
46
|
+
}
|
|
33
47
|
//# sourceMappingURL=namespaced-rule-name.js.map
|
|
@@ -148,6 +148,10 @@ export declare const JSONL_REPLAY_SEATS: {
|
|
|
148
148
|
readonly direction: "fail-open";
|
|
149
149
|
readonly tag: "server.workflow-agent-session-index.corrupt-record-skipped";
|
|
150
150
|
};
|
|
151
|
+
readonly "workflow-completion-inbox": {
|
|
152
|
+
readonly direction: "fail-open";
|
|
153
|
+
readonly tag: "server.workflow-completion-inbox.corrupt-record-skipped";
|
|
154
|
+
};
|
|
151
155
|
readonly "user-input-ledger": {
|
|
152
156
|
readonly direction: "fail-open";
|
|
153
157
|
readonly tag: "server.user-input-ledger.corrupt-record-skipped";
|
|
@@ -133,6 +133,7 @@ export const JSONL_REPLAY_SEATS = {
|
|
|
133
133
|
"approval-ask-audit": { direction: "fail-open", tag: "server.approval-ask-audit.corrupt-record-skipped" },
|
|
134
134
|
"workflow-notify-journal": { direction: "fail-open", tag: "server.workflow-notify-journal.corrupt-record-skipped" },
|
|
135
135
|
"workflow-agent-session-index": { direction: "fail-open", tag: "server.workflow-agent-session-index.corrupt-record-skipped" },
|
|
136
|
+
"workflow-completion-inbox": { direction: "fail-open", tag: "server.workflow-completion-inbox.corrupt-record-skipped" },
|
|
136
137
|
"user-input-ledger": { direction: "fail-open", tag: "server.user-input-ledger.corrupt-record-skipped" },
|
|
137
138
|
};
|
|
138
139
|
function corruptRefusalSentence(seat, path, reason) {
|
|
@@ -24,7 +24,11 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
24
24
|
};
|
|
25
25
|
readonly "server.workflow-park-index.sync-failed": {
|
|
26
26
|
readonly cls: "P-DEBT";
|
|
27
|
-
readonly note: "S-185 车CM(codex r1-F2 [high],验真后登记):workflow 出身 park 的 join 索引(`workflow_agent_session` / local 账本)在**一次成功的 run 写之后**同步失败 ⇒ 该次同步被吞,重试要等这条 run 的**下一次**写。而 park 恰好常常是这条 run 的**最后**一次写(park = run 终局 `failed`)⇒ 那条 park 可能永久 join
|
|
27
|
+
readonly note: "S-185 车CM(codex r1-F2 [high],验真后登记):workflow 出身 park 的 join 索引(`workflow_agent_session` / local 账本)在**一次成功的 run 写之后**同步失败 ⇒ 该次同步被吞,重试要等这条 run 的**下一次**写。而 park 恰好常常是这条 run 的**最后**一次写(park = run 终局 `failed`)⇒ 那条 park 可能永久 join 不到。**多数情形**是诚实 miss:这张卡没有别的指针 ⇒ `/decide` 结构性退回本批之前的行为(409 `conflict.resume_context_unavailable`),不误配、不伪造、不放行,丢的是「人能不能把这条批准送出去」这个能力。**7.118.0 起不止于此**:路由把指针候选当持有者的全集读,并有分叉门(两条同代次持有者 ⇒ 409 `decide.workflow_park_forked`);同一张卡上一枚**竞争**指针没写上(本臂的写失败,或写记录与写指针之间进程崩溃 —— 后者不经本臂、不计数)⇒ 分叉被判成唯一持有者 ⇒ 决定投给幸存的那一支(它确实持有这张卡,但另一支同样站在上面,引擎把这种形交给消费方拒)。归 P 类的理由:缺指针决定**车道选择**(缺行 ⇒ 选中 legacy 腿),且能让分叉门失效;归 DEBT 的理由是真正的解要一条**按子代 checkpoint 键的耐久决议回执 + 重启期回填**(与 codex r1-F3 同一件欠账,另车),分叉门失效那一形另有设计票。计数非零 = 有 park 可能决不掉、或这张卡的分叉门可能失效,运维要按 detail 里的 runId 去查那条 run 的续跑链。";
|
|
28
|
+
};
|
|
29
|
+
readonly "server.workflow-park-index.parks-unreadable": {
|
|
30
|
+
readonly cls: "F";
|
|
31
|
+
readonly note: "S-1173(`workflow-notify-journal.ts` 的 `syncAgentSessionIndex`,与上一条 `sync-failed` 同一个写点、另一臂):workflow run 记录的 `parks[]` **读不出**(在场却不是列表 / 某条目身份位或持有者两位形坏;读者 = `workflow-agent-session-index.ts` 的 `readRunParks`,整档成败制)⇒ 这一份指针投影派生不出来 ⇒ 写者**不动**这条 run 已有的指针(上一份已知良好的投影留着)。修前这一臂静默 `return`。**`parks` 缺席不进这一臂**:那是引擎契约里的合法形(更早引擎写的记录 / 准入没走完的续跑记录),读者答 `[]`(没有条目),写者照常收敛成空指针集,不计。**与 `sync-failed` 分家的理由(后果不同句,不并成一个 tag)**:`sync-failed` 是索引**写**挂了、丢的是一份已知良好的投影(park 常常是 run 的最后一次写 ⇒ 永久 join 不到,归 P-DEBT);本臂没有丢任何一份已知良好的投影 —— 读不出的是**记录本身**,引擎对条目形坏的记录整条拒续跑(`park_binding_broken`),读口对已有指针的 run 据记录响亮拒(`unproven/unreadable`),所以无需「重试这次写」,要的是查那条记录为什么读不出(投影把它写坏 / 手改)。放行的最坏后果:这条 run 的指针不被刷新(从没写过则没有指针 ⇒ 这张卡没有别的指针时 `/decide` 落 legacy 腿、409 响亮拒),多数情形方向是 fail-closed,不误配、不放行任何东西;例外与上一条同形 —— 首写就读不出的这一支没有指针,同一张卡上另一支的指针在时分叉门判不出、决定投给那一支(引擎从不写坏形,要这一支在首写之前就被写坏,比上一条的写失败更罕见);derived cache 没更新、真源读口自带响亮拒 ⇒ F 类。detail = `runId=`;计数非零 = 有记录的 `parks[]` 读不出,按 runId 去查记录。";
|
|
28
32
|
};
|
|
29
33
|
readonly "server.trace.gate-outcome-defective": {
|
|
30
34
|
readonly cls: "F";
|
|
@@ -296,7 +300,7 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
296
300
|
};
|
|
297
301
|
readonly "server.approval-card.closed-word-out-of-set": {
|
|
298
302
|
readonly cls: "F";
|
|
299
|
-
readonly note: "S-249(`approval-card.ts` 的边界窄读族;今天三个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` 判别是哪一座):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。";
|
|
303
|
+
readonly note: "S-249(`approval-card.ts` 的边界窄读族;今天三个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛)、S-1170 起的 `classifierNoRuling`(core 7.43.0 #1353 的成因词,活卡帧读 `AskRequest.classifierNoRuling`,闭集筛 = core `isAutoModeFallbackCause`)与 `differs`(core 7.44.0 #1374,载体是 `runs.ts` 的 409 `steering.duplicate_input_id` 体读的引擎拒错 `detail.differs`,闭集筛 = core `STEER_REPLAY_FACETS` 的非空子集;集外成员 / 空 / 非数组 ⇒ 不铸 `detail`,码仍是契约);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` / `classifierNoRuling=` / `differs=` 判别是哪一座):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。";
|
|
300
304
|
};
|
|
301
305
|
readonly "server.pg-pool.idle-client-error": {
|
|
302
306
|
readonly cls: "F";
|
|
@@ -334,6 +338,10 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
334
338
|
readonly cls: "F";
|
|
335
339
|
readonly note: "S-977(`orchestration/workflow-agent-session-index.ts`,local 车道 workflow 出身 park 的 join 索引账本的 boot 重放;登记名 `workflow-agent-session-index`):账本**中间**一行读不出形(`42` / 数组 / 缺 `runId`·`rows` / 任一行成员缺身份位 / 半截 JSON;撕尾不走本 tag)⇒ **整行**跳过,那条 run 保留上一份已知良好的快照(不做「丢坏成员、留好成员」—— 那会铸出比真相少几条 park 的行集)。最坏后果 = 该 run 的 park 在索引里缺行 ⇒ `/decide` 找不到它、退回 legacy 腿(409 `conflict.resume_context_unavailable`):诚实 miss,不是错配 —— 赎回键由记录上的 `parks[]` 逐字比对,不读本索引。索引不开门 ⇒ F。修前:形不对的整行响亮(`workflow_agent_session_ledger_line_rejected`,同事件名保留)但**无 tag**,带换行的半截 JSON 静默 `continue`。";
|
|
336
340
|
};
|
|
341
|
+
readonly "server.workflow-completion-inbox.corrupt-record-skipped": {
|
|
342
|
+
readonly cls: "F";
|
|
343
|
+
readonly note: "S-978(`orchestration/workflow-completion-inbox.ts`,local 车道 File 完成信箱的 boot 重放;登记名 `workflow-completion-inbox`):账本**中间**一行读不出形(`42` / `null` / 数组 / 缺 `op` 或 `op` 词表外 / `enqueue` 缺 `entry.sessionId`·`entry.runId` / `ack` 缺 `sessionId`·`runId` / `drain` 缺 `sessionId` / 半截 JSON;撕尾不走本 tag)⇒ 跳过它继续。最坏后果按行种:丢 `enqueue` ⇒ 那条完成推送不进信箱(`WorkflowStatus` 轮询地板照旧兜住);丢 `ack` ⇒ 一条已送达的完成在重启后再投一次(壳按 runId 去重,至少一次的既有语义);丢 `drain`(会话清除墓碑)⇒ 被删会话里尚未送达的条目复活 —— 出帧前仍过 owner 二道闸(`emitPendingWorkflowCompletions`:条目盖的 owner 与本次调用方不符 ⇒ ack 丢弃、不出帧),同属主重领同一 sessionId 只会多收一条按 runId 去重的推送。信箱不开门、不改任何 run 的执行或授权 ⇒ F。修前:解析失败 `continue`(静默),而解析成功的 `null` 行在读 `rec.op` 时抛 TypeError ⇒ `new FileWorkflowCompletionInbox` 抛(构造点无 catch ⇒ 这一面起不来),其余非对象 / 缺键形静默忽略。boot 压实随后从内存活集重写账本 ⇒ 坏行的字节压实后不留盘,披露是它唯一的记录。";
|
|
344
|
+
};
|
|
337
345
|
readonly "server.user-input-ledger.append-failed": {
|
|
338
346
|
readonly cls: "F";
|
|
339
347
|
readonly note: "S-928(`src/user-input-ledger.ts`):200 承诺**之后**的一次账本写失败 —— detail 的 `op=` 点名是哪一种:`settle`(腿在本进程收场)/ `withdraw`(引擎没收下这次 steer)/ `converge`(收敛器判孤儿)/ `announce`(通告已投出,记「告知过」)。放行的最坏后果逐个说清:settle / withdraw 漏写 ⇒ 这次受理在账上仍是 open —— 本进程下一次收敛扫描补结清(本进程写的、已不在活腿上 ⇒ leg_over);进程在那之前就崩了 ⇒ 下一次 boot 的收敛读 run 店判(S-969 L8 起两车道同一只判词:承载它的 run 正常翻面 / 已 park ⇒ leg_over 补结清、不告知;落款死亡判决或写者已死仍 running ⇒ crashed)—— 仍会多说一句的只剩两形:withdraw 漏写后那条腿崩了(一次没变成 200 的受理被告知一次);settle 漏写后本进程续跑了同一条 run、续跑腿崩了(run 行说的是同一 taskId 上**最新**那条腿)。方向都是多说,不漏;converge 漏写 ⇒ 留在 open,下一次扫描再判(延迟,不丢);announce 漏写 ⇒ 下一条 run 再说一遍(至多一次退化成至少一次)。都是**告知面**的偏差,不开任何门、不改任何 run 的执行 ⇒ F。计数非零 = 这台机器的账本写不动了(local:数据根盘满 / 只读;SQL:库不可达),steer 此刻多半也在回 503。";
|
|
@@ -374,6 +382,10 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
374
382
|
readonly cls: "F";
|
|
375
383
|
readonly note: "7.116.0 修复轮(`approval-crash-convergence.ts` 的 `convergeCrashedAsksAtBoot`;local 车道启动收敛):前世留下的一条 `STREAM_PENDING` 问行,它的卡信封(`card_json`)读不出 ⇒ 读不出 wire `approvalId`、无从向审计账要成因词 ⇒ 成因**回落**成 `crashed_before_park`。行照样收 VOID(决断口照样 410 —— 可决性 fail-closed,不受影响);最坏后果 = 一张其实是被有序关停截断的卡,在 410 体的 `deniedReason` 上说成「进程崩了」(`crashConverged` 读面若有它的审计组,那里的成因仍按审计账判,两处可能不同词)。计数非零 = 问账里有读不出卡信封的行(位腐 / 手改 / 版本错位),去看探针 detail 点名的 askId。读数另在启动日志 `approval_ask_audit_crash_converged` 的 `causeUnreadable` 格单列。";
|
|
376
384
|
};
|
|
385
|
+
readonly "server.outbound.hop-member-unreadable": {
|
|
386
|
+
readonly cls: "F";
|
|
387
|
+
readonly note: "出网代理那一跳建连失败的 wire 投影(`outbound-dispatcher.ts` `projectHopFailure`):按 core 连接失败分类器的读法复制错误图时,某个成员的访问器抛了(或对象不可 toString)。读法与分类器同一把,所以抛了当缺席;最坏后果 = 副本上少一个成员,分类器把这一次失败读成 unclassified(终局句只剩 `via outbound proxy` 一句、不带码),不影响重试阶梯的方向。只在怪形错误对象上触发,计数即可。";
|
|
388
|
+
};
|
|
377
389
|
readonly "server.outbound.connect-observer-threw": {
|
|
378
390
|
readonly cls: "F";
|
|
379
391
|
readonly note: "S-925(`outbound-dispatcher.ts` 的 undici 诊断通道订阅者:`undici:request:create` / `:headers` / `:error`):一只订阅回调抛了。通道在发布方的调用栈里同步回调订阅者,抛出去在 Node 上是未捕获异常(整进程倒),所以每只回调整体 try、落本 tag。最坏后果 = 这一条请求的建连失败没被记下:少一行 `outbound_connect_failed`、诊断段 `outbound.lastConnectFailure` 不更新、那次模型调用不铸 `server.model_unreachable` 用户通告 —— 请求本身、它的错误、run 的终态一个字节不受影响(观察只读)。计数恒零是证据;非零 = undici 通道载荷的形变了,去看 detail 的 site。";
|
|
@@ -18,7 +18,11 @@ export const FAIL_OPEN_TAGS = {
|
|
|
18
18
|
},
|
|
19
19
|
"server.workflow-park-index.sync-failed": {
|
|
20
20
|
cls: "P-DEBT",
|
|
21
|
-
note: "S-185 车CM(codex r1-F2 [high],验真后登记):workflow 出身 park 的 join 索引(`workflow_agent_session` / local 账本)在**一次成功的 run 写之后**同步失败 ⇒ 该次同步被吞,重试要等这条 run 的**下一次**写。而 park 恰好常常是这条 run 的**最后**一次写(park = run 终局 `failed`)⇒ 那条 park 可能永久 join
|
|
21
|
+
note: "S-185 车CM(codex r1-F2 [high],验真后登记):workflow 出身 park 的 join 索引(`workflow_agent_session` / local 账本)在**一次成功的 run 写之后**同步失败 ⇒ 该次同步被吞,重试要等这条 run 的**下一次**写。而 park 恰好常常是这条 run 的**最后**一次写(park = run 终局 `failed`)⇒ 那条 park 可能永久 join 不到。**多数情形**是诚实 miss:这张卡没有别的指针 ⇒ `/decide` 结构性退回本批之前的行为(409 `conflict.resume_context_unavailable`),不误配、不伪造、不放行,丢的是「人能不能把这条批准送出去」这个能力。**7.118.0 起不止于此**:路由把指针候选当持有者的全集读,并有分叉门(两条同代次持有者 ⇒ 409 `decide.workflow_park_forked`);同一张卡上一枚**竞争**指针没写上(本臂的写失败,或写记录与写指针之间进程崩溃 —— 后者不经本臂、不计数)⇒ 分叉被判成唯一持有者 ⇒ 决定投给幸存的那一支(它确实持有这张卡,但另一支同样站在上面,引擎把这种形交给消费方拒)。归 P 类的理由:缺指针决定**车道选择**(缺行 ⇒ 选中 legacy 腿),且能让分叉门失效;归 DEBT 的理由是真正的解要一条**按子代 checkpoint 键的耐久决议回执 + 重启期回填**(与 codex r1-F3 同一件欠账,另车),分叉门失效那一形另有设计票。计数非零 = 有 park 可能决不掉、或这张卡的分叉门可能失效,运维要按 detail 里的 runId 去查那条 run 的续跑链。",
|
|
22
|
+
},
|
|
23
|
+
"server.workflow-park-index.parks-unreadable": {
|
|
24
|
+
cls: "F",
|
|
25
|
+
note: "S-1173(`workflow-notify-journal.ts` 的 `syncAgentSessionIndex`,与上一条 `sync-failed` 同一个写点、另一臂):workflow run 记录的 `parks[]` **读不出**(在场却不是列表 / 某条目身份位或持有者两位形坏;读者 = `workflow-agent-session-index.ts` 的 `readRunParks`,整档成败制)⇒ 这一份指针投影派生不出来 ⇒ 写者**不动**这条 run 已有的指针(上一份已知良好的投影留着)。修前这一臂静默 `return`。**`parks` 缺席不进这一臂**:那是引擎契约里的合法形(更早引擎写的记录 / 准入没走完的续跑记录),读者答 `[]`(没有条目),写者照常收敛成空指针集,不计。**与 `sync-failed` 分家的理由(后果不同句,不并成一个 tag)**:`sync-failed` 是索引**写**挂了、丢的是一份已知良好的投影(park 常常是 run 的最后一次写 ⇒ 永久 join 不到,归 P-DEBT);本臂没有丢任何一份已知良好的投影 —— 读不出的是**记录本身**,引擎对条目形坏的记录整条拒续跑(`park_binding_broken`),读口对已有指针的 run 据记录响亮拒(`unproven/unreadable`),所以无需「重试这次写」,要的是查那条记录为什么读不出(投影把它写坏 / 手改)。放行的最坏后果:这条 run 的指针不被刷新(从没写过则没有指针 ⇒ 这张卡没有别的指针时 `/decide` 落 legacy 腿、409 响亮拒),多数情形方向是 fail-closed,不误配、不放行任何东西;例外与上一条同形 —— 首写就读不出的这一支没有指针,同一张卡上另一支的指针在时分叉门判不出、决定投给那一支(引擎从不写坏形,要这一支在首写之前就被写坏,比上一条的写失败更罕见);derived cache 没更新、真源读口自带响亮拒 ⇒ F 类。detail = `runId=`;计数非零 = 有记录的 `parks[]` 读不出,按 runId 去查记录。",
|
|
22
26
|
},
|
|
23
27
|
"server.trace.gate-outcome-defective": {
|
|
24
28
|
cls: "F",
|
|
@@ -269,7 +273,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
269
273
|
"server.redact.ppk-eat-to-end": { cls: "F", note: "S-107 第三十二轮重扫:PuTTY .ppk 容器扫描器(redact.ts redactPpkContainers)在「无合格终止 / 收口后同容器范围再见私钥字段 / 收口后到下一版本头之间夹非空白」三形下从头**吃到输入末尾**(fail-closed 取证丢弃)——终态 errorMessage 座上=整条错误文案变成 «redacted:private-key»,与 redactions_applied_total{private-key} 的诚实替换同形不可分,故要有自己的计数/探针;影子扫不计;计数=多少次整段吃尾。" },
|
|
270
274
|
"server.approval-card.closed-word-out-of-set": {
|
|
271
275
|
cls: "F",
|
|
272
|
-
note: "S-249(`approval-card.ts` 的边界窄读族;今天三个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` 判别是哪一座):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。",
|
|
276
|
+
note: "S-249(`approval-card.ts` 的边界窄读族;今天三个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛)、S-1170 起的 `classifierNoRuling`(core 7.43.0 #1353 的成因词,活卡帧读 `AskRequest.classifierNoRuling`,闭集筛 = core `isAutoModeFallbackCause`)与 `differs`(core 7.44.0 #1374,载体是 `runs.ts` 的 409 `steering.duplicate_input_id` 体读的引擎拒错 `detail.differs`,闭集筛 = core `STEER_REPLAY_FACETS` 的非空子集;集外成员 / 空 / 非数组 ⇒ 不铸 `detail`,码仍是契约);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` / `classifierNoRuling=` / `differs=` 判别是哪一座):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。",
|
|
273
277
|
},
|
|
274
278
|
"server.pg-pool.idle-client-error": {
|
|
275
279
|
cls: "F",
|
|
@@ -307,6 +311,10 @@ export const FAIL_OPEN_TAGS = {
|
|
|
307
311
|
cls: "F",
|
|
308
312
|
note: "S-977(`orchestration/workflow-agent-session-index.ts`,local 车道 workflow 出身 park 的 join 索引账本的 boot 重放;登记名 `workflow-agent-session-index`):账本**中间**一行读不出形(`42` / 数组 / 缺 `runId`·`rows` / 任一行成员缺身份位 / 半截 JSON;撕尾不走本 tag)⇒ **整行**跳过,那条 run 保留上一份已知良好的快照(不做「丢坏成员、留好成员」—— 那会铸出比真相少几条 park 的行集)。最坏后果 = 该 run 的 park 在索引里缺行 ⇒ `/decide` 找不到它、退回 legacy 腿(409 `conflict.resume_context_unavailable`):诚实 miss,不是错配 —— 赎回键由记录上的 `parks[]` 逐字比对,不读本索引。索引不开门 ⇒ F。修前:形不对的整行响亮(`workflow_agent_session_ledger_line_rejected`,同事件名保留)但**无 tag**,带换行的半截 JSON 静默 `continue`。",
|
|
309
313
|
},
|
|
314
|
+
"server.workflow-completion-inbox.corrupt-record-skipped": {
|
|
315
|
+
cls: "F",
|
|
316
|
+
note: "S-978(`orchestration/workflow-completion-inbox.ts`,local 车道 File 完成信箱的 boot 重放;登记名 `workflow-completion-inbox`):账本**中间**一行读不出形(`42` / `null` / 数组 / 缺 `op` 或 `op` 词表外 / `enqueue` 缺 `entry.sessionId`·`entry.runId` / `ack` 缺 `sessionId`·`runId` / `drain` 缺 `sessionId` / 半截 JSON;撕尾不走本 tag)⇒ 跳过它继续。最坏后果按行种:丢 `enqueue` ⇒ 那条完成推送不进信箱(`WorkflowStatus` 轮询地板照旧兜住);丢 `ack` ⇒ 一条已送达的完成在重启后再投一次(壳按 runId 去重,至少一次的既有语义);丢 `drain`(会话清除墓碑)⇒ 被删会话里尚未送达的条目复活 —— 出帧前仍过 owner 二道闸(`emitPendingWorkflowCompletions`:条目盖的 owner 与本次调用方不符 ⇒ ack 丢弃、不出帧),同属主重领同一 sessionId 只会多收一条按 runId 去重的推送。信箱不开门、不改任何 run 的执行或授权 ⇒ F。修前:解析失败 `continue`(静默),而解析成功的 `null` 行在读 `rec.op` 时抛 TypeError ⇒ `new FileWorkflowCompletionInbox` 抛(构造点无 catch ⇒ 这一面起不来),其余非对象 / 缺键形静默忽略。boot 压实随后从内存活集重写账本 ⇒ 坏行的字节压实后不留盘,披露是它唯一的记录。",
|
|
317
|
+
},
|
|
310
318
|
"server.user-input-ledger.append-failed": {
|
|
311
319
|
cls: "F",
|
|
312
320
|
note: "S-928(`src/user-input-ledger.ts`):200 承诺**之后**的一次账本写失败 —— detail 的 `op=` 点名是哪一种:`settle`(腿在本进程收场)/ `withdraw`(引擎没收下这次 steer)/ `converge`(收敛器判孤儿)/ `announce`(通告已投出,记「告知过」)。放行的最坏后果逐个说清:settle / withdraw 漏写 ⇒ 这次受理在账上仍是 open —— 本进程下一次收敛扫描补结清(本进程写的、已不在活腿上 ⇒ leg_over);进程在那之前就崩了 ⇒ 下一次 boot 的收敛读 run 店判(S-969 L8 起两车道同一只判词:承载它的 run 正常翻面 / 已 park ⇒ leg_over 补结清、不告知;落款死亡判决或写者已死仍 running ⇒ crashed)—— 仍会多说一句的只剩两形:withdraw 漏写后那条腿崩了(一次没变成 200 的受理被告知一次);settle 漏写后本进程续跑了同一条 run、续跑腿崩了(run 行说的是同一 taskId 上**最新**那条腿)。方向都是多说,不漏;converge 漏写 ⇒ 留在 open,下一次扫描再判(延迟,不丢);announce 漏写 ⇒ 下一条 run 再说一遍(至多一次退化成至少一次)。都是**告知面**的偏差,不开任何门、不改任何 run 的执行 ⇒ F。计数非零 = 这台机器的账本写不动了(local:数据根盘满 / 只读;SQL:库不可达),steer 此刻多半也在回 503。",
|
|
@@ -347,6 +355,10 @@ export const FAIL_OPEN_TAGS = {
|
|
|
347
355
|
cls: "F",
|
|
348
356
|
note: "7.116.0 修复轮(`approval-crash-convergence.ts` 的 `convergeCrashedAsksAtBoot`;local 车道启动收敛):前世留下的一条 `STREAM_PENDING` 问行,它的卡信封(`card_json`)读不出 ⇒ 读不出 wire `approvalId`、无从向审计账要成因词 ⇒ 成因**回落**成 `crashed_before_park`。行照样收 VOID(决断口照样 410 —— 可决性 fail-closed,不受影响);最坏后果 = 一张其实是被有序关停截断的卡,在 410 体的 `deniedReason` 上说成「进程崩了」(`crashConverged` 读面若有它的审计组,那里的成因仍按审计账判,两处可能不同词)。计数非零 = 问账里有读不出卡信封的行(位腐 / 手改 / 版本错位),去看探针 detail 点名的 askId。读数另在启动日志 `approval_ask_audit_crash_converged` 的 `causeUnreadable` 格单列。",
|
|
349
357
|
},
|
|
358
|
+
"server.outbound.hop-member-unreadable": {
|
|
359
|
+
cls: "F",
|
|
360
|
+
note: "出网代理那一跳建连失败的 wire 投影(`outbound-dispatcher.ts` `projectHopFailure`):按 core 连接失败分类器的读法复制错误图时,某个成员的访问器抛了(或对象不可 toString)。读法与分类器同一把,所以抛了当缺席;最坏后果 = 副本上少一个成员,分类器把这一次失败读成 unclassified(终局句只剩 `via outbound proxy` 一句、不带码),不影响重试阶梯的方向。只在怪形错误对象上触发,计数即可。",
|
|
361
|
+
},
|
|
350
362
|
"server.outbound.connect-observer-threw": {
|
|
351
363
|
cls: "F",
|
|
352
364
|
note: "S-925(`outbound-dispatcher.ts` 的 undici 诊断通道订阅者:`undici:request:create` / `:headers` / `:error`):一只订阅回调抛了。通道在发布方的调用栈里同步回调订阅者,抛出去在 Node 上是未捕获异常(整进程倒),所以每只回调整体 try、落本 tag。最坏后果 = 这一条请求的建连失败没被记下:少一行 `outbound_connect_failed`、诊断段 `outbound.lastConnectFailure` 不更新、那次模型调用不铸 `server.model_unreachable` 用户通告 —— 请求本身、它的错误、run 的终态一个字节不受影响(观察只读)。计数恒零是证据;非零 = undici 通道载荷的形变了,去看 detail 的 site。",
|
package/dist/operator-ask.d.ts
CHANGED
|
@@ -59,7 +59,10 @@ export declare function operatorAsk(rule: string, message: string): OperatorAskR
|
|
|
59
59
|
* 席的同一只判据按 `mandated` 挡住它,耐久 `/decide` 腿的可记性(park 行 `mandated` 孪生位)同判 ⇒ 回执 `rememberApplied:false`。
|
|
60
60
|
* live 腿修前这里本就是个洞(进程内 `allow_session` 授权可退役 neverAuto 卡),随类收掉。
|
|
61
61
|
*
|
|
62
|
-
* ⚠️ **只**这两类:普通 `APPROVAL_REQUIRE` 仍只经 {@link operatorAsk}(
|
|
62
|
+
* ⚠️ **只**这两类:普通 `APPROVAL_REQUIRE` 仍只经 {@link operatorAsk}(不盖出身)。它的问带 `matchedAskRule` ⇒ 引擎类 `ask_rule`;站着的答案
|
|
63
|
+
* (「本会话放行」、耐久豁免行)清不清得掉它,出处是引擎类表 `foldArbitrationRow(classes).ruleMayClear` —— `ask_rule` 那一行说清不掉
|
|
64
|
+
* (`tool-approval.ts` 的 `standingAnswerMayRetire` 与它同读)。所以在「站着的答案清不掉」这一问上它与「恒问人」两类同答;不同在出身位
|
|
65
|
+
* (只这两类盖部署出身 ⇒ core 读 `operator_forced`、盖 `mandated`),其余各列按引擎类表各读各的行。
|
|
63
66
|
*/
|
|
64
67
|
export declare function operatorAlwaysHumanAsk(rule: string, message: string): OperatorAskResult;
|
|
65
68
|
/**
|
|
@@ -1,83 +1,104 @@
|
|
|
1
1
|
import { type WorkflowRun } from "@sema-agent/core";
|
|
2
|
-
/**
|
|
2
|
+
/** 一条索引行 = 一枚**指针**:记录 `runId` 的 `parks[]` 点名过子会话 `sessionId`。主键 = (子会话, run)—— 一条续跑链 / 一次分叉上
|
|
3
|
+
* 同一个子会话可以被好几条记录点名,判决要看到它们全部(见 {@link routeWorkflowPark})。 */
|
|
3
4
|
export interface WorkflowAgentSessionRow {
|
|
4
|
-
/**
|
|
5
|
+
/** 那只 workflow 子代自己的会话 id(= 条目的 `sessionId` = 那条 checkpoint 行的 `sessionId`;
|
|
5
6
|
* **不是** `sourceTaskId` —— 后者在 core 契约上是 ECHO-ONLY、明令不可作门输入)。 */
|
|
6
7
|
sessionId: string;
|
|
7
|
-
/**
|
|
8
|
+
/** 点名它的 workflow run(`w*`)。 */
|
|
8
9
|
runId: string;
|
|
9
|
-
/**
|
|
10
|
+
/** 该条目的稳定顺位身份(条目的 `callKey`)—— 行自描述用,判决以记录上的条目为准。 */
|
|
10
11
|
agentKey: string;
|
|
11
12
|
/** run 的租户键(`WorkflowRun.scope`)。 */
|
|
12
13
|
scope: string;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
|
-
* 索引面的两个动词。**写者只有一个**(见文件头)
|
|
16
|
+
* 索引面的两个动词。**写者只有一个**(见文件头),读者是判别式。
|
|
16
17
|
*
|
|
17
|
-
* `syncRun` 语义 = 「这条 run
|
|
18
|
-
*
|
|
18
|
+
* `syncRun` 语义 = 「这条 run 当前的指针集**就是** rows」:多出来的旧行删,rows 里的行 upsert。幂等、可重放、与 run 的一次成功写同拍。
|
|
19
|
+
* `listByAgentSession` = 点名这个子会话的**全部**指针(各 run 一行;顺序不承重)。
|
|
19
20
|
*/
|
|
20
21
|
export interface WorkflowAgentSessionIndex {
|
|
21
22
|
syncRun(runId: string, rows: readonly WorkflowAgentSessionRow[]): Promise<void>;
|
|
22
|
-
|
|
23
|
+
listByAgentSession(sessionId: string): Promise<WorkflowAgentSessionRow[]>;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
|
-
* 🔴 **park
|
|
26
|
+
* 🔴 **park 身份的单一真源**(core 7.17.0 [ref];持有者两成员 core 7.44.0 #1319)—— 引擎写在记录上的 `parks[]` 的元素形。
|
|
26
27
|
*
|
|
27
|
-
* 型从 core 的那一位取、不在本仓复述:core 往元素上加一位 ⇒ `trace/core-keyset-guard.ts` 的 ⑬b
|
|
28
|
-
* 与下面那只读者的构造式**同时**红,加键的人二选一,没有第三条静默的路。
|
|
28
|
+
* 型从 core 的那一位取、不在本仓复述:core 往元素上加一位 ⇒ `trace/core-keyset-guard.ts` 的 ⑬b 成员门与下面那只读者的构造式**同时**红。
|
|
29
29
|
*/
|
|
30
30
|
export type WorkflowRunParkKey = NonNullable<WorkflowRun["parks"]>[number];
|
|
31
31
|
/**
|
|
32
|
-
* 盘上 run blob → `parks[]` 的**唯一读者**(宪法 [ref] §2:进程外字节禁裸 `as`
|
|
33
|
-
* {@link
|
|
32
|
+
* 盘上 run blob → `parks[]` 的**唯一读者**(宪法 [ref] §2:进程外字节禁裸 `as` 铸形)。路由({@link routeWorkflowPark})与写者
|
|
33
|
+
* ({@link buildParkSessionRows})都经它读,「缺席」与「读不出」的边界只在这里划一次。
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
* ·
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* ·
|
|
43
|
-
*
|
|
44
|
-
* 而这只读者的消费面正是 park 的赎回路由。
|
|
45
|
-
*
|
|
46
|
-
* ⚠️ 「读不出来」与「读得出来、只是空的」是**两个状态**:后者 = 这条 run 不负责任何 park(诚实 miss),
|
|
47
|
-
* 前者 = 证不了,两者的处置相反 ⇒ 缺席永远不折成 `[]`。
|
|
35
|
+
* 判据:
|
|
36
|
+
* · 这一位**缺席** ⇒ `[]`:没有条目,持有不了任何东西。缺席是引擎契约里的合法形 —— core 7.17.0 之前写下的记录没有它,core 7.44.0
|
|
37
|
+
* 准入没走完的续跑记录(`resumeAdmissionIncomplete`)也没有它;引擎续跑这样的记录时自己从 journal 派生,走到停驻时写下带持有者位的新条目;
|
|
38
|
+
* · 这一位**在场却不是数组** ⇒ 读不出(`undefined`):记录说了话、说的不是一份列表;
|
|
39
|
+
* · 每条四个身份位必须是非空串;`originUnconfirmed` 只认字面 `true`(core 从不写 `false`);
|
|
40
|
+
* · **持有者两成员同进同出**(core 7.44.0 逐字:both or neither):`parkedBy` 非空串、`generation` 非负安全整数;只有其一、或任一形坏
|
|
41
|
+
* ⇒ 坏条目。两者皆无 = 旧引擎写的条目(证不了持有者),照读;
|
|
42
|
+
* · **任一条目形坏 ⇒ 整只读不出来**(整档成败制):core 对同一形整条拒 resume(`park_binding_broken`);「丢掉坏的、留下好的」会静默
|
|
43
|
+
* 铸出一份**比真相少几条 park** 的集合,而这只读者的消费面正是 park 的路由与赎回。
|
|
48
44
|
*/
|
|
49
45
|
export declare function readRunParks(run: unknown): WorkflowRunParkKey[] | undefined;
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
|
|
46
|
+
/**
|
|
47
|
+
* 🔴 **「这条记录的 run 持有这条停驻」的唯一读法**(core 7.44.0 #1319 逐字):`entry.parkedBy === record.id`。
|
|
48
|
+
* 继承来、本跑还没走到的条目带上一跑的 id;旧引擎写的条目两成员皆无 —— 两者都不是本记录持有的。
|
|
49
|
+
*/
|
|
50
|
+
export declare function heldParksOf(recordId: string, parks: readonly WorkflowRunParkKey[]): WorkflowRunParkKey[];
|
|
51
|
+
/**
|
|
52
|
+
* 派生的**唯一属主**:一只 `WorkflowRun` 的指针行 = 它 `parks[]` 里点名的每一个子会话(一个子会话一行)。`parks` 缺席 ⇒ 零条
|
|
53
|
+
* ({@link readRunParks}:没有条目)⇒ 写者按「这条 run 的指针集就是这一份」清掉它已有的指针。
|
|
54
|
+
* `parks[]` 读不出 ⇒ `undefined`(**派生不出来**,不是「零条」):写者据此不动这条 run 已有的指针(文件头「单写者」段)。
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildParkSessionRows(runId: string, run: {
|
|
57
|
+
scope: string;
|
|
58
|
+
parks?: unknown;
|
|
59
|
+
}): WorkflowAgentSessionRow[] | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* 一次路由的判决(闭集):
|
|
62
|
+
* · `held` —— 持有这个子会话的记录里最高代次**恰一条**:`park` = 它持有的那一条条目(赎回键在条目上);
|
|
63
|
+
* · `forked` —— 最高代次上不止一条记录(同一条 run 先后被续跑两次,两支都走到了这里):`runIds` 升序;
|
|
64
|
+
* · `unproven` —— 没有任何记录持有它,而这件事证不了:`unreadable` = 某一条候选记录的 `parks[]` 读不出(它可能就是持有者);
|
|
65
|
+
* `older_engine` = 点名它的条目没有持有者位(写于不带这两位的旧引擎);`runId` = 去续跑的那一条(`unreadable` 时是读不出的那条里 id 最小的);
|
|
66
|
+
* `readableHolderRunId` 只在 `unreadable` 上可能在场 —— **其余可读候选里**持有它的最高代次**恰一条**记录(规则 ②,与 `held` 同一只判);没有 / 并列 ⇒ 缺席。
|
|
67
|
+
* 它不改判决(任一读不出 ⇒ 整卡拒不变),只让拒体多给一条线索:读不出的那条引擎往往恰拒续跑,而健康的持有者就在旁边(工作可从它续上;
|
|
68
|
+
* 读不出的那条的指针仍在候选里,续跑它之后这张卡照旧整卡拒,直到那条记录被修好);
|
|
69
|
+
* · `none` —— 没有任何记录持有它,且候选全部读得出、条目都带持有者位 ⇒ 诚实 miss。
|
|
70
|
+
*/
|
|
71
|
+
export type WorkflowParkRoute = {
|
|
72
|
+
readonly kind: "held";
|
|
73
|
+
readonly runId: string;
|
|
74
|
+
readonly run: WorkflowRun;
|
|
75
|
+
readonly park: WorkflowRunParkKey;
|
|
76
|
+
} | {
|
|
77
|
+
readonly kind: "forked";
|
|
78
|
+
readonly runIds: readonly string[];
|
|
79
|
+
} | {
|
|
80
|
+
readonly kind: "unproven";
|
|
81
|
+
readonly cause: "unreadable" | "older_engine";
|
|
82
|
+
readonly runId: string;
|
|
83
|
+
readonly run: WorkflowRun;
|
|
84
|
+
readonly readableHolderRunId?: string;
|
|
85
|
+
} | {
|
|
86
|
+
readonly kind: "none";
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* 🔴 **路由与赎回的唯一判决**(纯函数;输入 = 点名这个子会话的每一条记录,读不到的记录 —— 已被收割 —— 由调用方先剔掉)。
|
|
60
90
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* `persist("update")` 打在 append **之前**。⇒ 那条判据会在 append 失败(以及 append 前的那一拍)上把
|
|
69
|
-
* 真正持有**新 token** 的那一跑整只排除,而上一跑的记录里只有**旧** token ⇒ 这条审批再也送不出去。
|
|
91
|
+
* 一条规则,按序:
|
|
92
|
+
* ① 任一候选的 `parks[]` 读不出 ⇒ `unproven/unreadable`(它可能正是最高代次的持有者;宁可不投,绝不投错 —— 引擎对条目形坏的记录整条拒续跑);
|
|
93
|
+
* 其余可读候选按下一条判出的持有者(恰一条)带进 `readableHolderRunId`(只给出路,不改判决);
|
|
94
|
+
* ② 其余候选里,持有这个子会话({@link heldParksOf})的条目取最高 `generation`:恰一条记录 ⇒ `held`;多于一条 ⇒ `forked`;
|
|
95
|
+
* ③ 没有持有者:有条目两成员皆无(旧引擎写的)⇒ `unproven/older_engine`,`runId` = 这类记录里最晚建的那条(续跑它,新引擎走到这张停驻时
|
|
96
|
+
* 写下自己的代次 0 行);否则 `none`。
|
|
97
|
+
* 判决不看写序、不看 `agents[]`、不看 `originRunId`(core:那一位说的是「材料在哪条 run 的 journal 里」,不是「谁站在上面」)。
|
|
70
98
|
*
|
|
71
|
-
*
|
|
72
|
-
|
|
73
|
-
export declare function
|
|
74
|
-
scope: string;
|
|
75
|
-
agents?: ReadonlyArray<{
|
|
76
|
-
status?: unknown;
|
|
77
|
-
sessionId?: unknown;
|
|
78
|
-
callKey?: unknown;
|
|
79
|
-
}>;
|
|
80
|
-
}): WorkflowAgentSessionRow[];
|
|
99
|
+
* 🔴 **窗与删码**:规则 ③ 的 `older_engine` 读臂是一次性迁移 M9 的读侧半场(升级那一刻还停驻着的存量记录)。窗口与删码清单见 `plugins/one-time-migrations.ts` 登记表 M9 一行,随 M9 一起删;这里不写第二份窗。
|
|
100
|
+
*/
|
|
101
|
+
export declare function routeWorkflowPark(sessionId: string, candidates: readonly WorkflowRun[]): WorkflowParkRoute;
|
|
81
102
|
/** 两处(装饰器的变更检测、local 后端的重放)共用的行集等值判据 —— 顺序无关的集合比较,单一属主。 */
|
|
82
103
|
export declare function sameAgentSessionRows(a: readonly WorkflowAgentSessionRow[], b: readonly WorkflowAgentSessionRow[]): boolean;
|
|
83
104
|
/** 账本一行的**内域形**:一次 `syncRun` 的整份行集快照(`{runId, rows}`)。 */
|
|
@@ -88,7 +109,7 @@ export interface WorkflowAgentSessionLedgerLine {
|
|
|
88
109
|
/**
|
|
89
110
|
* 盘上账本行 → 内域形的**唯一读者**(宪法 [ref] §2:进程外字节禁裸 `as` 铸形)。
|
|
90
111
|
*
|
|
91
|
-
* 姿态与 SQL 孪生逐字同源:那边 `
|
|
112
|
+
* 姿态与 SQL 孪生逐字同源:那边 `listByAgentSession` 逐字段收窄(`String(r.session_id)` …),这边逐字段
|
|
92
113
|
* 判形 —— 一张索引面、两个后端、**一种**入域姿态。
|
|
93
114
|
*
|
|
94
115
|
* **整行成败制**(与既有的撕裂行臂同一条规则):一行 = 一次 syncRun 的**整份**快照,任一位读不出来就说明
|
|
@@ -109,18 +130,20 @@ export declare function readAgentSessionLedgerLine(v: unknown): WorkflowAgentSes
|
|
|
109
130
|
* 追加 / 重放走本仓 JSONL 店的**共用口**(S-977;此前 ctor 里自写 `truncateTornTail` + 手写 `split("\n") + JSON.parse` 重放):
|
|
110
131
|
* 追加 = core `AppendLog`(惰性打开、撕尾在**打开与每次追加前**修 —— 修前只在 boot 修,运行期半写后的下一次成功写仍会被粘进残尾),
|
|
111
132
|
* 重放 = `replayJsonlSkipping`(登记座 `workflow-agent-session-index`:中间坏行 —— 含半截 JSON 与形不对的整行 —— 跳过 + 逐条披露 + F tag;
|
|
112
|
-
* 撕尾不计、不披露)。盘上字节 / 0o600 账本 / 0o700
|
|
133
|
+
* 撕尾不计、不披露)。盘上字节 / 0o600 账本 / 0o700 目录与修前逐字同,升级零迁移:一行仍是「这条 run 的指针集」,旧账本行就是旧记录的指针
|
|
134
|
+
* (判决从记录读,指针本身没有新旧两种读法)。
|
|
113
135
|
*/
|
|
114
136
|
export declare class LocalWorkflowAgentSessionIndex implements WorkflowAgentSessionIndex {
|
|
115
137
|
private readonly fsyncEnabled;
|
|
116
138
|
private readonly ledgerPath;
|
|
117
139
|
private readonly byRun;
|
|
140
|
+
/** 子会话 → (run → 指针)。一个子会话可以被好几条记录点名(续跑链 / 分叉),全部留着 —— 判决看全集。 */
|
|
118
141
|
private readonly bySession;
|
|
119
142
|
private log;
|
|
120
143
|
constructor(root?: string, fsyncEnabled?: boolean);
|
|
121
|
-
/** 内存两张表的收敛(重放与写路径共用一份逻辑)
|
|
144
|
+
/** 内存两张表的收敛(重放与写路径共用一份逻辑):先摘这条 run 的旧指针,再挂新的。 */
|
|
122
145
|
private apply;
|
|
123
146
|
syncRun(runId: string, rows: readonly WorkflowAgentSessionRow[]): Promise<void>;
|
|
124
|
-
|
|
147
|
+
listByAgentSession(sessionId: string): Promise<WorkflowAgentSessionRow[]>;
|
|
125
148
|
}
|
|
126
149
|
//# sourceMappingURL=workflow-agent-session-index.d.ts.map
|