@sema-agent/server 7.148.0 → 7.149.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/MIGRATION.md +429 -0
  2. package/README.md +16 -1
  3. package/README.zh-CN.md +4 -0
  4. package/USAGE.md +89 -55
  5. package/dist/adoption/wire.d.ts +3 -3
  6. package/dist/approval-card.d.ts +32 -32
  7. package/dist/approval-leg-origin.d.ts +33 -0
  8. package/dist/approval-leg-origin.js +4 -0
  9. package/dist/auth-bridge.d.ts +9 -1
  10. package/dist/auth-bridge.js +4 -4
  11. package/dist/auth-keys.d.ts +10 -1
  12. package/dist/auth-keys.js +8 -0
  13. package/dist/boot/execution-env.js +10 -11
  14. package/dist/boot/execution-lane.d.ts +6 -4
  15. package/dist/boot/execution-lane.js +3 -1
  16. package/dist/boot/org-delivery.d.ts +3 -2
  17. package/dist/boot/resolve-spec.js +6 -4
  18. package/dist/boot/runner-deps.js +3 -1
  19. package/dist/boot/stage-01-config.d.ts +1 -0
  20. package/dist/boot/stage-01-config.js +4 -3
  21. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  22. package/dist/boot/stage-02-web-admin-pull.js +10 -2
  23. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  24. package/dist/boot/stage-03-store-backend.js +2 -2
  25. package/dist/boot/stage-04-stores.d.ts +1 -0
  26. package/dist/boot/stage-05-execution-env.d.ts +1 -0
  27. package/dist/boot/stage-06-runners.d.ts +2 -1
  28. package/dist/boot/stage-07-capability-layer.d.ts +2 -1
  29. package/dist/boot/stage-08-reapers.d.ts +2 -1
  30. package/dist/boot/stage-09-leader.d.ts +2 -1
  31. package/dist/boot/stage-10-http-server.d.ts +2 -1
  32. package/dist/boot/stores.d.ts +3 -0
  33. package/dist/boot/stores.js +22 -19
  34. package/dist/capabilities/tool-defer.d.ts +1 -1
  35. package/dist/capability-facts.d.ts +5 -4
  36. package/dist/capability-facts.js +3 -14
  37. package/dist/card-settle-stored-scope.d.ts +56 -0
  38. package/dist/card-settle-stored-scope.js +27 -0
  39. package/dist/card-void.d.ts +7 -12
  40. package/dist/card-void.js +2 -7
  41. package/dist/config-catalog.d.ts +12 -0
  42. package/dist/config-catalog.js +36 -32
  43. package/dist/config-invariants.d.ts +5 -4
  44. package/dist/config-invariants.js +4 -4
  45. package/dist/config-types.d.ts +37 -5
  46. package/dist/config.d.ts +6 -5
  47. package/dist/config.js +35 -24
  48. package/dist/context-window-notice.d.ts +31 -0
  49. package/dist/context-window-notice.js +28 -0
  50. package/dist/deployment-shape.d.ts +20 -11
  51. package/dist/deployment-shape.js +1 -0
  52. package/dist/env-name-allowlist-knobs.d.ts +6 -5
  53. package/dist/env-name-allowlist-knobs.js +5 -0
  54. package/dist/execution-lane-caps.d.ts +20 -5
  55. package/dist/execution-lane-caps.js +18 -4
  56. package/dist/hooks/command-spawn.d.ts +7 -2
  57. package/dist/hooks/command-spawn.js +13 -6
  58. package/dist/hooks/hook-runner.d.ts +5 -0
  59. package/dist/hooks/hook-runner.js +11 -7
  60. package/dist/http/admission.js +3 -3
  61. package/dist/http/approval-sweeps.js +3 -2
  62. package/dist/http/claim-heartbeat.d.ts +3 -3
  63. package/dist/http/claim-heartbeat.js +3 -3
  64. package/dist/http/claimed-run.d.ts +16 -9
  65. package/dist/http/claimed-run.js +8 -0
  66. package/dist/http/dispatch.js +5 -3
  67. package/dist/http/durable-run-leg.d.ts +8 -1
  68. package/dist/http/durable-run-leg.js +30 -11
  69. package/dist/http/execution-context.d.ts +115 -14
  70. package/dist/http/execution-context.js +130 -40
  71. package/dist/http/owner-access.d.ts +3 -2
  72. package/dist/http/owner-access.js +2 -3
  73. package/dist/http/principal-gate.d.ts +18 -11
  74. package/dist/http/principal-gate.js +3 -1
  75. package/dist/http/resume-ctx-read.d.ts +14 -3
  76. package/dist/http/resume-ctx-read.js +8 -2
  77. package/dist/http/resume-legs.d.ts +35 -3
  78. package/dist/http/resume-legs.js +244 -92
  79. package/dist/http/route-ctx.d.ts +6 -0
  80. package/dist/http/routes/a2a-serve.js +2 -0
  81. package/dist/http/routes/approvals-assistant.js +3 -2
  82. package/dist/http/routes/capabilities.js +1 -1
  83. package/dist/http/routes/diagnostics.d.ts +3 -1
  84. package/dist/http/routes/diagnostics.js +30 -5
  85. package/dist/http/routes/principal-inbox.d.ts +3 -1
  86. package/dist/http/routes/principal-inbox.js +3 -2
  87. package/dist/http/routes/runs.js +10 -7
  88. package/dist/http/routes/session-sync.d.ts +24 -5
  89. package/dist/http/routes/session-sync.js +46 -34
  90. package/dist/http/routes/sessions-list.d.ts +1 -1
  91. package/dist/http/routes/tasks.js +127 -93
  92. package/dist/http/server.d.ts +4 -5
  93. package/dist/http/server.js +30 -5
  94. package/dist/http/submit-ctx.d.ts +1 -0
  95. package/dist/http/submit-ctx.js +2 -3
  96. package/dist/index.d.ts +3 -1
  97. package/dist/index.js +1 -0
  98. package/dist/leg-facts.d.ts +7 -2
  99. package/dist/leg-facts.js +1 -0
  100. package/dist/local-store-declaration.d.ts +54 -0
  101. package/dist/local-store-declaration.js +59 -0
  102. package/dist/mcp-assertion-header.d.ts +1 -1
  103. package/dist/mcp-assertion-header.js +1 -1
  104. package/dist/memory-project-layer.js +1 -1
  105. package/dist/memory-scope.d.ts +4 -4
  106. package/dist/memory-scope.js +4 -4
  107. package/dist/memory-sync-client.js +2 -2
  108. package/dist/model-context-window.d.ts +50 -11
  109. package/dist/model-context-window.js +20 -1
  110. package/dist/model-entry-refusal.d.ts +5 -4
  111. package/dist/model-entry-refusal.js +17 -3
  112. package/dist/model-reach-scope.d.ts +2 -1
  113. package/dist/observability/fail-open.d.ts +14 -2
  114. package/dist/observability/fail-open.js +14 -2
  115. package/dist/observability/metrics.js +1 -1
  116. package/dist/observability/run-terminal.js +1 -0
  117. package/dist/observability/secret-env-scrub.d.ts +1 -1
  118. package/dist/observability/secret-env-scrub.js +1 -1
  119. package/dist/org-delivery-gate.d.ts +31 -6
  120. package/dist/org-delivery-gate.js +7 -4
  121. package/dist/owner-faces.d.ts +3 -2
  122. package/dist/park-row-commit.d.ts +67 -0
  123. package/dist/park-row-commit.js +76 -0
  124. package/dist/parked-decide.d.ts +9 -7
  125. package/dist/parked-decide.js +25 -6
  126. package/dist/peer-directory.d.ts +1 -1
  127. package/dist/plugins/adoption-log-sql.d.ts +3 -3
  128. package/dist/plugins/adoption-log-sql.js +19 -19
  129. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  130. package/dist/plugins/approval-ask-store-sql.js +3 -5
  131. package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
  132. package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
  133. package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
  134. package/dist/plugins/approval-exemption-skill-m46.js +6 -10
  135. package/dist/plugins/approval-exemption-store.d.ts +26 -1
  136. package/dist/plugins/approval-exemption-store.js +28 -19
  137. package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
  138. package/dist/plugins/ensure-schema-lock-policy.js +75 -9
  139. package/dist/plugins/file-run-store.d.ts +22 -9
  140. package/dist/plugins/file-run-store.js +50 -22
  141. package/dist/plugins/local-checkpoint-store.d.ts +4 -0
  142. package/dist/plugins/local-checkpoint-store.js +2 -1
  143. package/dist/plugins/local-data-root-admission.d.ts +52 -0
  144. package/dist/plugins/local-data-root-admission.js +100 -0
  145. package/dist/plugins/local-engine-high-water.d.ts +28 -7
  146. package/dist/plugins/local-engine-high-water.js +27 -22
  147. package/dist/plugins/local-session-store.d.ts +134 -49
  148. package/dist/plugins/local-session-store.js +149 -108
  149. package/dist/plugins/memory-run-store.d.ts +14 -9
  150. package/dist/plugins/memory-run-store.js +47 -21
  151. package/dist/plugins/one-time-migration-marker.d.ts +19 -3
  152. package/dist/plugins/one-time-migration-marker.js +7 -1
  153. package/dist/plugins/one-time-migrations.d.ts +46 -20
  154. package/dist/plugins/one-time-migrations.js +102 -79
  155. package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
  156. package/dist/plugins/org-delivery-quota-store.js +29 -14
  157. package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
  158. package/dist/plugins/permission-rule-store-sql.js +5 -9
  159. package/dist/plugins/pg-pool.d.ts +1 -1
  160. package/dist/plugins/pg-pool.js +10 -12
  161. package/dist/plugins/remote-env-device.d.ts +3 -2
  162. package/dist/plugins/remote-env-e2b.d.ts +1 -7
  163. package/dist/plugins/remote-env-e2b.js +10 -7
  164. package/dist/plugins/remote-env-host.d.ts +50 -9
  165. package/dist/plugins/remote-env-host.js +77 -20
  166. package/dist/plugins/remote-env-k8s.js +4 -2
  167. package/dist/plugins/remote-env-local-docker.d.ts +6 -3
  168. package/dist/plugins/remote-env-local-docker.js +8 -23
  169. package/dist/plugins/run-store-sql.d.ts +26 -7
  170. package/dist/plugins/run-store-sql.js +44 -16
  171. package/dist/plugins/scenario-prefix-switch-m42.d.ts +3 -1
  172. package/dist/plugins/scenario-prefix-switch-m42.js +4 -3
  173. package/dist/plugins/schema-consistency.d.ts +89 -5
  174. package/dist/plugins/schema-consistency.js +176 -7
  175. package/dist/plugins/schema-drift-sentence.d.ts +6 -5
  176. package/dist/plugins/schema-drift-sentence.js +13 -5
  177. package/dist/plugins/session-placement.d.ts +5 -4
  178. package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
  179. package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
  180. package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
  181. package/dist/plugins/stop-then-start-sentence.js +7 -0
  182. package/dist/plugins/store-backend.d.ts +22 -8
  183. package/dist/plugins/store-backend.js +58 -24
  184. package/dist/plugins/store-contracts.d.ts +33 -3
  185. package/dist/plugins/store-contracts.js +16 -0
  186. package/dist/plugins/tidb-pool.d.ts +11 -6
  187. package/dist/plugins/tidb-pool.js +18 -12
  188. package/dist/plugins/workspace-custody.d.ts +44 -0
  189. package/dist/plugins/workspace-custody.js +47 -0
  190. package/dist/project-identity.d.ts +8 -7
  191. package/dist/project-identity.js +40 -17
  192. package/dist/project-layer-key.d.ts +13 -2
  193. package/dist/project-layer-key.js +9 -1
  194. package/dist/read-deny-floor-notice.d.ts +36 -0
  195. package/dist/read-deny-floor-notice.js +40 -0
  196. package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
  197. package/dist/request-declaration-disposition.js +39 -0
  198. package/dist/run-cancel-card.d.ts +28 -0
  199. package/dist/run-cancel-card.js +19 -0
  200. package/dist/run-cancel-context.d.ts +10 -0
  201. package/dist/run-cancel-context.js +1 -0
  202. package/dist/run-local.js +28 -13
  203. package/dist/runs.d.ts +31 -7
  204. package/dist/runs.js +34 -16
  205. package/dist/security.d.ts +2 -2
  206. package/dist/server-secret-env.d.ts +34 -20
  207. package/dist/server-secret-env.js +61 -18
  208. package/dist/session-agent.d.ts +3 -2
  209. package/dist/session-children-retire.d.ts +6 -3
  210. package/dist/session-children-retire.js +2 -5
  211. package/dist/session-workspace.d.ts +3 -3
  212. package/dist/store-admission.d.ts +33 -0
  213. package/dist/store-admission.js +49 -0
  214. package/dist/store-posture.d.ts +5 -0
  215. package/dist/store-posture.js +18 -1
  216. package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
  217. package/dist/stores-sql/checkpoint-store-sql.js +3 -5
  218. package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
  219. package/dist/stores-sql/file-history-store-sql.js +3 -5
  220. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  221. package/dist/stores-sql/tool-result-store-sql.js +4 -6
  222. package/dist/task-a2a.d.ts +3 -8
  223. package/dist/task-a2a.js +25 -27
  224. package/dist/task-cwd.d.ts +23 -7
  225. package/dist/task-cwd.js +3 -0
  226. package/dist/task-mcp.d.ts +3 -3
  227. package/dist/task-mcp.js +1 -1
  228. package/dist/task-settings.js +1 -0
  229. package/dist/terminal.d.ts +2 -0
  230. package/dist/terminal.js +21 -6
  231. package/dist/tool-approval.d.ts +44 -36
  232. package/dist/tool-approval.js +66 -47
  233. package/dist/trace/engine-notice-wire.d.ts +24 -21
  234. package/dist/trace/engine-notice-wire.js +7 -3
  235. package/dist/trace/ledger-sink.d.ts +3 -1
  236. package/dist/trace/project.d.ts +4 -2
  237. package/dist/trace/project.js +8 -7
  238. package/dist/trace/redact.d.ts +12 -0
  239. package/dist/trace/redact.js +5 -1
  240. package/dist/trace/self-minted-wire.d.ts +131 -52
  241. package/dist/trace/self-minted-wire.js +71 -39
  242. package/dist/web-admin-client/apply-effective.js +22 -9
  243. package/docs/error-text-lexicon.json +317 -0
  244. package/package.json +3 -1
  245. package/scripts/embed-minimal.mjs +183 -0
  246. package/wire-changes/server@7.149.0.json +372 -0
  247. package/dist/plain-string-record.js +0 -70
@@ -0,0 +1,54 @@
1
+ /**
2
+ * **local 店对引擎的声明**(会话店顶层 · 检查点店「两半」读同一份;委派分区的声明是子代转录档位的判据,不随两半降)—— 「这台部署向谁承诺店活过替换」的唯一读者,与运维那一个词的闭集。
3
+ *
4
+ * ## 规则(一句)
5
+ * local 文件店的设计声明是「活过进程重启」(`SESSION_DURABILITY`);起服的店持久性准入(`store-admission.ts`,第 2 段、第一笔写之前)拿这句声明与数据根介质对表
6
+ * (声明 `durable` ∧ 介质 `ephemeral` ⇒ 拒启 `config.store_not_durable`;第 9 段布线审计对引擎读到的声明同判)。声明降为引擎的 `process-local` 只有两个来源,都由 {@link localStoreDeclarationOf} 一处答:
7
+ * · 运维写了 `LOCAL_STORE_DURABILITY=ephemeral`(闭集只有这一个词;缺席 = 设计声明);
8
+ * · 店落在**调用方自己的盘**上(部署形表行 `callerOwnsWorkerDisk`:host 车道 ∧ 单主)且数据根介质判 `ephemeral` —— 调用方的工作区、工具与会话史同在那块盘上,
9
+ * 部署不替他承诺他自己那块易失盘活过替换(参照实现在无卷容器里同形)。
10
+ * 两半一起降:只降会话店,引擎的 durable-park 自检读出缺口(`durableParkGapOf`:检查点活过、会话不活);只降检查点店同理。
11
+ *
12
+ * 叶模块:值导入只有部署形表(叶)与店型常量的属主;`store-posture.ts` / `store-admission.ts` / `config.ts` / local 后端各读这里,不各写一份。
13
+ */
14
+ import type { StoreDurability as EngineStoreDurability } from "@sema-agent/core";
15
+ import { type DeploymentShapeInput } from "./deployment-shape.js";
16
+ import type { StoreDurability } from "./store-posture.js";
17
+ /** `LOCAL_STORE_DURABILITY` 的词(闭集,只有「易失」一个词;缺席 = 店型的设计声明)。不给第二个放宽词 —— 声明只有「我就是易失」这一句。 */
18
+ export declare const LOCAL_STORE_DECLARATION_WORDS: readonly ["ephemeral"];
19
+ export type LocalStoreDeclarationWord = (typeof LOCAL_STORE_DECLARATION_WORDS)[number];
20
+ /**
21
+ * local 店声明的依据词(闭集;引擎声明词由 {@link engineDurabilityOfDeclarationRule} 的穷举 switch 派生 —— 加词 ⇒ 编译红):
22
+ * · `declared_ephemeral` —— 运维写了 `LOCAL_STORE_DURABILITY=ephemeral` ⇒ `process-local`(不论车道与介质:这是部署者对自己的店说的话);
23
+ * · `callers_own_volatile_disk` —— 部署形表行 `callerOwnsWorkerDisk` 成立(host 车道 ∧ 单主:店所在的盘就是调用方自己的盘 —— 他的工作区、工具与会话史同在一块盘上,
24
+ * CC 在容器里同形)且数据根介质判 `ephemeral` ⇒ `process-local`:部署不替调用方承诺他自己那块易失盘活过替换;
25
+ * · `store_design` —— 其余:local 文件店的设计声明(活过进程重启,`SESSION_DURABILITY`)。店落在调用方看不见的 worker 盘上而介质易失 ⇒ 审计拒启;
26
+ * 调用方自己的盘判 `durable` / `unknown` ⇒ 声明照旧(开发机、挂了卷的容器、非 Linux)。
27
+ */
28
+ export declare const LOCAL_STORE_DECLARATION_RULES: readonly ["declared_ephemeral", "callers_own_volatile_disk", "store_design"];
29
+ export type LocalStoreDeclarationRule = (typeof LOCAL_STORE_DECLARATION_RULES)[number];
30
+ /** 依据词 → 引擎声明词(穷举 switch)。 */
31
+ export declare function engineDurabilityOfDeclarationRule(rule: LocalStoreDeclarationRule): EngineStoreDurability;
32
+ /** local 店的声明(依据词 + 派生的引擎声明词;两半店读同一份)。 */
33
+ export interface LocalStoreDeclaration {
34
+ readonly rule: LocalStoreDeclarationRule;
35
+ readonly durability: EngineStoreDurability;
36
+ }
37
+ /** 声明读的部署事实:部署形表行 `callerOwnsWorkerDisk` 的读入形(车道 × 租户)+ 运维的词 `LOCAL_STORE_DURABILITY`(`ServiceConfig` 结构上满足)。 */
38
+ export type LocalStoreDeclarationDeployment = DeploymentShapeInput<"lane" | "principal"> & {
39
+ readonly localStoreDurability: LocalStoreDeclarationWord | undefined;
40
+ };
41
+ /**
42
+ * 🔴 「local 店对引擎声明自己活过什么」的**唯一读者**(两个调用点读同一组输入:local 后端的构造 —— 两半店的声明都从它的返回值来;起服第 2 段的店持久性准入 `store-admission.ts` —— 拒启判读同一份)。
43
+ * `dataRootMedium` = 起服第 2 段对数据根介质的判定;没有起服证据的入口(`run-local`、嵌入方直调 `createStoreBackend`)递 `unknown` —— 与装配值同一条缺证据律:
44
+ * 判不出的介质不放宽声明,只有运维的词能。
45
+ */
46
+ export declare function localStoreDeclarationOf(deployment: LocalStoreDeclarationDeployment, dataRootMedium: StoreDurability): LocalStoreDeclaration;
47
+ /** 依据词的人读形(布线审计的 warn 行与店的持久性准入的拒句用)。 */
48
+ export declare function describeLocalStoreDeclaration(d: LocalStoreDeclaration): string;
49
+ /**
50
+ * `LOCAL_STORE_DURABILITY` 的读法(配置装载调这一只):缺席 / 空串 ⇒ `undefined`(设计声明);恰为闭集里的词(去首尾空白后逐字)⇒ 那个词;
51
+ * 别的任何值 ⇒ 抛(拒启)—— 一个读不懂的声明不许被折成「持久」或「易失」中的任何一边。
52
+ */
53
+ export declare function parseLocalStoreDurabilityWord(raw: string | undefined): LocalStoreDeclarationWord | undefined;
54
+ //# sourceMappingURL=local-store-declaration.d.ts.map
@@ -0,0 +1,59 @@
1
+ import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
2
+ import { SESSION_DURABILITY } from "./plugins/session-placement.js";
3
+ export const LOCAL_STORE_DECLARATION_WORDS = ["ephemeral"];
4
+ export const LOCAL_STORE_DECLARATION_RULES = ["declared_ephemeral", "callers_own_volatile_disk", "store_design"];
5
+ export function engineDurabilityOfDeclarationRule(rule) {
6
+ switch (rule) {
7
+ case "declared_ephemeral":
8
+ case "callers_own_volatile_disk":
9
+ return "process-local";
10
+ case "store_design":
11
+ return SESSION_DURABILITY;
12
+ default: {
13
+ const unhandled = rule;
14
+ throw new Error(`store posture: no ruling for local store declaration rule ${String(unhandled)}`);
15
+ }
16
+ }
17
+ }
18
+ export function localStoreDeclarationOf(deployment, dataRootMedium) {
19
+ const of = (rule) => ({ rule, durability: engineDurabilityOfDeclarationRule(rule) });
20
+ const word = deployment.localStoreDurability;
21
+ switch (word) {
22
+ case "ephemeral":
23
+ return of("declared_ephemeral");
24
+ case undefined:
25
+ if (dataRootMedium === "ephemeral" && DEPLOYMENT_SHAPE_PREDICATES.callerOwnsWorkerDisk.holds(deployment))
26
+ return of("callers_own_volatile_disk");
27
+ return of("store_design");
28
+ default: {
29
+ const unhandled = word;
30
+ throw new Error(`unhandled LOCAL_STORE_DURABILITY word ${JSON.stringify(unhandled)}`);
31
+ }
32
+ }
33
+ }
34
+ export function describeLocalStoreDeclaration(d) {
35
+ switch (d.rule) {
36
+ case "declared_ephemeral":
37
+ return "the operator declared LOCAL_STORE_DURABILITY=ephemeral";
38
+ case "callers_own_volatile_disk":
39
+ return "the store sits on the caller's own disk (host execution lane, single owner), and that disk does not survive a container / Pod replacement";
40
+ case "store_design":
41
+ return "the local file store's own declaration";
42
+ default: {
43
+ const unhandled = d.rule;
44
+ throw new Error(`store posture: no wording for local store declaration rule ${String(unhandled)}`);
45
+ }
46
+ }
47
+ }
48
+ export function parseLocalStoreDurabilityWord(raw) {
49
+ const w = raw?.trim() ?? "";
50
+ if (w === "")
51
+ return undefined;
52
+ const word = LOCAL_STORE_DECLARATION_WORDS.find((x) => x === w);
53
+ if (word !== undefined)
54
+ return word;
55
+ throw new Error(`LOCAL_STORE_DURABILITY=${JSON.stringify(raw)} is not a recognized declaration — the only word is ${LOCAL_STORE_DECLARATION_WORDS.map((x) => `"${x}"`).join(", ")} ` +
56
+ `(the local store declares itself process-local: sessions, parked approvals and memory do not survive a container / Pod replacement). ` +
57
+ `Leave it unset for the store's own durable declaration. Refusing to boot rather than reading a declaration nobody can read as either one.`);
58
+ }
59
+ //# sourceMappingURL=local-store-declaration.js.map
@@ -5,7 +5,7 @@
5
5
  * 请求面条目的形 = 契约包的请求传输形({@link RequestMcpServerSpec}:stdio 带 `env`、http 带 `headers` / `principalHeader` / `assertionHeader`),wire 上的形由它说。
6
6
  * 交给引擎的声明不带件值:引擎的声明收据对带 `headers` / `env` 的声明整条拒,件由部署的对端座在发送时作答。所以每条条目按它那一臂的处置表
7
7
  * ({@link MCP_STDIO_TRANSPORT_DISPOSITION} / {@link MCP_HTTP_TRANSPORT_DISPOSITION})拆成草稿:`env` / `headers` 进草稿的件,`assertionHeader` 承载不发送,其余进声明。
8
- * 拆法只有 `plain-string-record.ts` 的 `splitDeclaration` 一只、键的去处只有表一处说;两张表各带三道编译格(请求臂加 / 减键、引擎臂加键、引擎臂删键都编译红)。
8
+ * 拆法只有 `request-declaration-disposition.ts` 的 `splitDeclaration` 一只、键的去处只有表一处说;两张表各带三道编译格(请求臂加 / 减键、引擎臂加键、引擎臂删键都编译红)。
9
9
  * 草稿只有胜出者(部署同名者赢,`task-mcp.ts` 的 `mergeRequestMcp`)才经对端座的唯一铸点(`peer-seat.ts` 的 `mintDeclaration`)登记,登记换来的引用放进声明的传输臂。
10
10
  *
11
11
  * ## `assertionHeader`:一条律,一个键一种读法
@@ -1,4 +1,4 @@
1
- import { splitDeclaration } from "./plain-string-record.js";
1
+ import { splitDeclaration } from "./request-declaration-disposition.js";
2
2
  export const MCP_STDIO_TRANSPORT_DISPOSITION = { args: "engine", command: "engine", env: "seat", kind: "engine" };
3
3
  export const MCP_HTTP_TRANSPORT_DISPOSITION = { assertionHeader: "withheld", headers: "seat", kind: "engine", principalHeader: "engine", url: "engine" };
4
4
  const MCP_REQUEST_TRANSPORT_ARMS = {
@@ -29,7 +29,7 @@ export function createMemoryProjectLayers(deps) {
29
29
  };
30
30
  return {
31
31
  async prepare(config, scope, taskRoot) {
32
- const layer = memoryProjectLayerFor(config, scope, taskRoot);
32
+ const layer = await memoryProjectLayerFor(config, scope, taskRoot);
33
33
  const current = layer?.key.scope;
34
34
  if (layer === undefined || current === undefined)
35
35
  return layer?.key;
@@ -62,8 +62,8 @@ export declare function memoryScopeFor(config: ServiceConfig, principal?: string
62
62
  * 读不到(根在沙箱/设备盘上,或 host 车道会话没登记 cwd、spec 期还不知道根)⇒ 调用方传 `undefined` ⇒ `{ absent: "unreadable" }`,
63
63
  * core 铸 operator 通知 `memory.project_scope_absent`,写照常落全局层 —— **响亮**,不是静默落 `local`。
64
64
  *
65
- * 🔴 [ref] 键形:项目层 = **全局层的属主 × 项目身份**,`userrepo:<属主段>/<档>.<摘要>`(文法 `project-layer-key.ts`,身份 `project-identity.ts`);
66
- * 属主 = `projectLayerOwnerOf(scope)`。
65
+ * 🔴 [ref] 键形:项目层 = **全局层的属主 × 项目身份**,`userrepo:<属主段>/<档>.<摘要>`(文法 `project-layer-key.ts`,身份 `project-identity.ts`
66
+ * —— 检出带 `.sema/project` 记号 ⇒ 记号档,读法与引擎判官同一只;没有记号 ⇒ git 根回落);属主 = `projectLayerOwnerOf(scope)`。
67
67
  *
68
68
  * 🔴 **写家只落复制路径覆盖得到的层**(7.98.0 合并复审 F1,主会话裁「统一规则,不做特判」):写家 = 读列表里、本部署
69
69
  * **每一条已配置的复制路径都覆盖到**的最具体的一层。项目层不在覆盖面里 ⇒ 本任务**不按项目键控**,写家落全局层 —— 否则开了
@@ -77,9 +77,9 @@ export declare function memoryScopeFor(config: ServiceConfig, principal?: string
77
77
  * · 记忆面暗(`scope` 缺席)—— 没有 spec 可铸,也就不读盘;
78
78
  * · 本任务的项目层不在复制覆盖面里(见上)—— 让位给全局层。
79
79
  */
80
- export declare function memoryProjectKeyFor(config: Pick<ServiceConfig, "requirePrincipal" | "memorySync">, scope: string | undefined, taskRoot: string | undefined): MemoryProjectKey | undefined;
80
+ export declare function memoryProjectKeyFor(config: Pick<ServiceConfig, "requirePrincipal" | "memorySync">, scope: string | undefined, taskRoot: string | undefined): Promise<MemoryProjectKey | undefined>;
81
81
  /** {@link memoryProjectKeyFor} 的同一条规则,带上本 checkout 要折进当前层的旧层(`memory-project-layer.ts` 读它)。 */
82
- export declare function memoryProjectLayerFor(config: Pick<ServiceConfig, "requirePrincipal" | "memorySync">, scope: string | undefined, taskRoot: string | undefined): ProjectLayerOfTask | undefined;
82
+ export declare function memoryProjectLayerFor(config: Pick<ServiceConfig, "requirePrincipal" | "memorySync">, scope: string | undefined, taskRoot: string | undefined): Promise<ProjectLayerOfTask | undefined>;
83
83
  /**
84
84
  * 本部署记忆的**复制覆盖面** —— 唯一属主(7.98.0 合并复审 F1)。「复制路径」= 把某一层记忆搬出本机的腿;今天只有一条:
85
85
  * TOC 同步客户端腿(`MEMORY_SYNC_*`,`memory-sync-client.ts`)。🔴 [ref]:一条复制路径复制**它那一层**(`config.memorySync.scope`)
@@ -34,13 +34,13 @@ export function memoryScopeFor(config, principal, projectId) {
34
34
  }
35
35
  return config.memoryScope;
36
36
  }
37
- export function memoryProjectKeyFor(config, scope, taskRoot) {
38
- return memoryProjectLayerFor(config, scope, taskRoot)?.key;
37
+ export async function memoryProjectKeyFor(config, scope, taskRoot) {
38
+ return (await memoryProjectLayerFor(config, scope, taskRoot))?.key;
39
39
  }
40
- export function memoryProjectLayerFor(config, scope, taskRoot) {
40
+ export async function memoryProjectLayerFor(config, scope, taskRoot) {
41
41
  if (config.requirePrincipal === true || scope === undefined)
42
42
  return undefined;
43
- const layer = projectLayerForTaskRoot(taskRoot, projectLayerOwnerOf(scope));
43
+ const layer = await projectLayerForTaskRoot(taskRoot, projectLayerOwnerOf(scope));
44
44
  if (layer.key.scope !== undefined && !replicationCovers(memoryReplicationCoverage(config), layer.key.scope))
45
45
  return undefined;
46
46
  return layer;
@@ -3,7 +3,7 @@ import { readFile, readdir, rename, rmdir, stat } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  import { carriesCredential, ensureDir, syncMemoryScope, } from "@sema-agent/core";
5
5
  import { replicationCovers } from "./memory-scope.js";
6
- import { parseProjectLayerKey } from "./project-layer-key.js";
6
+ import { compareProjectLayersForSync, parseProjectLayerKey } from "./project-layer-key.js";
7
7
  import { atomicWriteFileAsync } from "./plugins/owner-only-file-mode.js";
8
8
  import { ONE_TIME_MIGRATIONS, migrationWindowOpen } from "./plugins/one-time-migrations.js";
9
9
  import { buildMemorySyncIdentityBootRefusal, readMemorySyncIdentity } from "./memory-sync-identity.js";
@@ -272,7 +272,7 @@ export function createMemorySyncRunner(opts) {
272
272
  opts.log.warn("memory_sync_layer_enumeration_unsupported", { scope: opts.scope, reason: local.reason, note: "only the sync layer and tracked project layers are synced" });
273
273
  }
274
274
  const projectLayers = new Set([...(local.supported ? local.scopes : []), ...tracked].filter(isCoveredProjectLayer));
275
- return [opts.scope, ...[...projectLayers].sort()];
275
+ return [opts.scope, ...[...projectLayers].sort(compareProjectLayersForSync)];
276
276
  };
277
277
  const syncLayer = async (scope, reason, calls) => {
278
278
  const cursorPath = memorySyncCursorPath(memoryEngineDir, scope);
@@ -1,18 +1,57 @@
1
1
  /**
2
- * The window this server ASSUMES for a model whose context window nobody declared — ONE spelling of the number.
2
+ * A model's context window: ONE resolver, ONE spelling of the assumed number, ONE word for where the window came from.
3
3
  *
4
- * Three readers fall back to it and nothing else may carry a copy: the env leg (`config.ts`: `MODEL_CONTEXT_WINDOW` unset ⇒ this value,
5
- * and the `MODEL_MAX_TOKENS` default `min(32000, window)` reads the SAME resolved window), the center leg (`web-admin-client/apply-effective.ts`:
6
- * `entry.contextWindow ?? env model's window ?? this value`) and the config catalog's default note (`config-catalog.ts`). A literal copied
7
- * into any of them is a second source that drifts the day the assumption changes — a center roster would then assume one window while
8
- * the env model assumes another, and the operator-facing default note would name a third.
4
+ * ## The rule
5
+ * A window is either **declared** — someone along the model's inheritance chain wrote a number: the catalog entry's `contextWindow`,
6
+ * the deployment's `MODEL_CONTEXT_WINDOW` (inherited by every catalog entry that writes none, BL-8), or `MODEL_CHEAP_CONTEXT_WINDOW`
7
+ * (the cheap slot; unset ⇒ it inherits the main slot's resolution) — or **assumed**: nobody along the chain wrote one, and this server
8
+ * fills {@link ASSUMED_CONTEXT_WINDOW}. {@link resolveContextWindow} is the only place that decides; it hands back the number AND its
9
+ * source as one value, and an inheriting reader passes the parent's resolution down whole — so the source travels with the number and
10
+ * no reader re-derives "was it declared?" on its own.
9
11
  *
10
- * This is a conservative CEILING GUESS, not a measurement: the engine needs a window to size its compaction trigger and the tool-schema
11
- * defer threshold, and an undeclared window must never be read optimistically — so every model that reaches the engine carries SOME window,
12
- * declared or this one (a catalog entry may omit `contextWindow`; the readers above fill it). Whether the value is conservative for a
13
- * given model is a per-model question this constant does not answer.
12
+ * Readers: the env leg (`config.ts`: main slot, cheap slot inheriting the main resolution), the center leg (`web-admin-client/apply-effective.ts`:
13
+ * entry → env main resolution), and the config catalog's default note (`config-catalog.ts`, which describes the assumed arm and so names the constant).
14
+ * The source is disclosed twice and read from the same per-model table both times (`ServiceConfig.contextWindowSources`): the `GET /v1/models`
15
+ * row key `contextWindowSource`, and the operator line {@link buildContextWindowAssumedNotice} (once per served model whose window is assumed; the one
16
+ * emitter is `context-window-notice.ts`, run after the served table settles).
17
+ *
18
+ * ## The assumed number
19
+ * A conservative guess, not a measurement: the engine needs a window to size its compaction trigger and the tool-schema defer
20
+ * threshold, and an undeclared window must never be read optimistically — so every model that reaches the engine carries SOME window,
21
+ * declared or this one. "Conservative" has one meaning here: the number is no larger than the smallest real window any model family in
22
+ * this stack's own deployments is known to declare, so an undeclared window errs toward "compaction and tool-schema deferral start
23
+ * earlier than the model needs", not toward "the model reaches its limit before compaction starts". It is ONE number, not a table keyed
24
+ * by model family — a per-family table would be a second source for the same fact. A model whose real window is larger declares it
25
+ * (catalog entry `contextWindow` / `MODEL_CONTEXT_WINDOW`); the disclosure above is how an operator / client learns which rows still
26
+ * ride on this number.
14
27
  *
15
28
  * Pure leaf: no imports.
16
29
  */
17
- export declare const ASSUMED_CONTEXT_WINDOW = 262144;
30
+ export declare const ASSUMED_CONTEXT_WINDOW = 131072;
31
+ /** Where a model's window came from — closed set; consumers switch exhaustively. */
32
+ export declare const CONTEXT_WINDOW_SOURCES: readonly ["declared", "assumed"];
33
+ export type ContextWindowSource = (typeof CONTEXT_WINDOW_SOURCES)[number];
34
+ /** A resolved window: the number the engine gets and where it came from (one value — never split across two reads). */
35
+ export interface ResolvedContextWindow {
36
+ readonly window: number;
37
+ readonly source: ContextWindowSource;
38
+ }
39
+ /**
40
+ * The one resolver. `declared` = the number this level of the chain wrote (`undefined` = wrote none); `inherited` = the parent level's
41
+ * resolution (omitted at the root ⇒ the assumed arm). Declared ⇒ that number, `declared`; otherwise the parent's resolution unchanged —
42
+ * a catalog entry that writes no window under a deployment that declared `MODEL_CONTEXT_WINDOW` is declared, under one that did not it is assumed.
43
+ */
44
+ export declare function resolveContextWindow(declared: number | undefined, inherited?: ResolvedContextWindow): ResolvedContextWindow;
45
+ /**
46
+ * The operator line for one served model whose window is assumed (plain data; both legs emit this shape, the event name lives here only).
47
+ * `declareAt` names where the operator writes the number to make it declared (the env knob for an env slot, the catalog entry otherwise).
48
+ */
49
+ export declare function buildContextWindowAssumedNotice(row: {
50
+ readonly model: string;
51
+ readonly window: number;
52
+ readonly declareAt: string;
53
+ }): {
54
+ readonly event: "model_context_window_assumed";
55
+ readonly fields: Record<string, string>;
56
+ };
18
57
  //# sourceMappingURL=model-context-window.d.ts.map
@@ -1,2 +1,21 @@
1
- export const ASSUMED_CONTEXT_WINDOW = 262144;
1
+ export const ASSUMED_CONTEXT_WINDOW = 131072;
2
+ export const CONTEXT_WINDOW_SOURCES = ["declared", "assumed"];
3
+ const ASSUMED = Object.freeze({ window: ASSUMED_CONTEXT_WINDOW, source: "assumed" });
4
+ export function resolveContextWindow(declared, inherited = ASSUMED) {
5
+ return declared !== undefined ? { window: declared, source: "declared" } : inherited;
6
+ }
7
+ export function buildContextWindowAssumedNotice(row) {
8
+ return {
9
+ event: "model_context_window_assumed",
10
+ fields: {
11
+ model: row.model,
12
+ contextWindow: String(row.window),
13
+ declareAt: row.declareAt,
14
+ note: `no context window is declared for model "${row.model}" — this server assumes ${row.window} tokens (a conservative guess, not a measurement): ` +
15
+ `the engine sizes its compaction trigger on it, so a model whose real window is smaller reaches its limit before compaction starts, ` +
16
+ `and a model whose real window is larger compacts earlier than it needs to. ` +
17
+ `GET /v1/models marks this row contextWindowSource:"assumed". Declare the real window at ${row.declareAt} — said once per model.`,
18
+ },
19
+ };
20
+ }
2
21
  //# sourceMappingURL=model-context-window.js.map
@@ -58,7 +58,7 @@ export type CatalogEntryVerdict = {
58
58
  };
59
59
  /**
60
60
  * **逐条判据**:`ok` = 本部署能完整服务它(连同判出它的那一份读数)。判序即语义:先形(不合形的条目谈不上走哪条腿),再腿。
61
- * 形分两段、同一个码(`config.model_entry_invalid`):settings-schema 的 `ModelEntry`,再是 [ref] 的 `headers`(白名单 + 线路 + 值形,
61
+ * 形分三段、同一个码(`config.model_entry_invalid`):settings-schema 的 `ModelEntry`,再是 [ref] 的名字(凭据形的名不收,见 {@link credentialNameRefusal}),再是 [ref] 的 `headers`(白名单 + 线路 + 值形,
62
62
  * 判据单属主 `model-entry-headers.ts`;settings-schema 6.3.0 的 `ModelEntry` 还没有这个键 —— 候裁加字段,届时词表不另抄)。
63
63
  *
64
64
  * 形判的属主是 settings-schema 的 `ModelEntry`(两条读腿用的就是它)—— 本仓不手抄任何一条字段规则;这里在第二道边界(绕过读腿的
@@ -114,9 +114,9 @@ export interface ModelRefusalVerdict {
114
114
  /**
115
115
  * [ref] —— 判决 → `/health.modelRefusals` 与 fleet 心跳 `modelRefusals` 的 wire 形(settings-schema `ModelRefusalsSignal`,纯投影):
116
116
  * 名 → 码,**值只码**(拒因事实里的上游 id / provider 词 / 坏字段键 / 出路句都不上 wire —— `entry_invalid` 行是没人验过的行,id / provider
117
- * 可能就是坏行原样;句子是给本机运维的散文,不是契约)。**名筛在这里、只在这里**:键过 settings-schema `isReportableRefusalName`(唯一判据,
118
- * import 不复制;6.3.0 起 = 标识符白名单 ∧ 无密钥形 ∧ 无 URL userinfo)—— 秘密形 / 空串 / `__proto__` / 不是标识符的串这类出不了门的名不进键、
119
- * 不计数;引擎内部的判决不受影响;本机日志 / 拒因句里的写名同样先问这一只([ref],{@link disclosableRefusalName}:不可披露的名只写码)。
117
+ * 可能就是坏行原样;句子是给本机运维的散文,不是契约)。**名筛在这里、只在这里**:键过 {@link disclosableRefusalName}([ref] 起 wire 出口与日志 / 拒因句同一个口:
118
+ * settings-schema `isReportableRefusalName`〔6.3.0 起 = 标识符白名单 ∧ 无密钥形 ∧ 无 URL userinfo,import 不复制〕∧ 脱敏器的强证据臂不认它是凭据)—— 秘密形 /
119
+ * 空串 / `__proto__` / 不是标识符的串这类出不了门的名不进键、不计数;引擎内部的判决不受影响;本机日志 / 拒因句里的写名同样先问这一个口([ref]:不可披露的名只写码)。
120
120
  * 逐条空且无组拒 ⇒ `undefined`(键缺席:「没有」只有一种拼法)。
121
121
  */
122
122
  export declare function buildModelRefusalsSignal(v: ModelRefusalVerdict | undefined): ModelRefusalsSignal | undefined;
@@ -144,6 +144,7 @@ export declare function echoModelRef(ref: string): string;
144
144
  * hook 选模型的失败文案 —— 各处同一句)。`field` = 调用方的通道名(`model` / `compactionModel` / `agents[0].model` /
145
145
  * `@-mention`),`requested` = 调用方发来的**原形**(name 或 id;本函数回显它时过 {@link echoModelRef},调用方不预先截)。
146
146
  * 别名段(`(catalog entry …)`)的判断读原形:ref 与条目名逐字相同 ⇒ 不带,不因回显截短而误判成「另有条目」。
147
+ * 别名段里的条目名过 {@link nameSlot}([ref]):调用方按上游 id 点中一条名字是凭据形的条目时,名字是**配置里的字**、不是调用方写的字,不可披露的名不原样回给他。
147
148
  */
148
149
  export declare function modelUnavailableMessage(field: string, requested: string, name: string, r: ModelEntryRefusal): string;
149
150
  /**
@@ -4,6 +4,7 @@ import { catalogBrainLane } from "./model-provider.js";
4
4
  import { readCatalogEntryHeaders } from "./model-entry-headers.js";
5
5
  import { DroppedCatalogEntryRow, describeSchemaIssueFields, describeSchemaIssues } from "./web-admin-client/read-warnings.js";
6
6
  import { echoCallerText } from "./caller-text-echo.js";
7
+ import { isCredentialShapedUnit } from "./trace/redact.js";
7
8
  import { DEFAULT_MODEL_REF } from "./model-select.js";
8
9
  export const ENTRY_REFUSAL_REASON_OF = {
9
10
  "config.model_no_brain": "no_brain",
@@ -29,6 +30,8 @@ export function judgeCatalogEntry(m, ctx) {
29
30
  return { ok: false, refusal: entryInvalidRefusal(typeof m.id === "string" ? m.id : "", typeof m.provider === "string" ? m.provider : "", fields, describeSchemaIssues(shape.error) ?? fields.join(", ")) };
30
31
  }
31
32
  const e = shape.data;
33
+ if (isCredentialShapedUnit(e.name))
34
+ return { ok: false, refusal: credentialNameRefusal(e.id, e.provider) };
32
35
  const headers = readCatalogEntryHeaders(e.headers, e.api);
33
36
  if (!headers.ok)
34
37
  return { ok: false, refusal: entryInvalidRefusal(e.id, e.provider, headers.fields, headers.issue) };
@@ -74,6 +77,17 @@ function entryInvalidRefusal(id, provider, fields, issues) {
74
77
  "deployment's catalog on its own (the other entries keep serving) instead of being served with a value nothing validated; fix the entry to bring it back",
75
78
  };
76
79
  }
80
+ function credentialNameRefusal(id, provider) {
81
+ return {
82
+ ...refusalCause("config.model_entry_invalid"),
83
+ id,
84
+ provider,
85
+ fields: ["name"],
86
+ detail: "the catalog entry's name field is credential-shaped (the engine's secret scanner reads it as a credential) — an entry name is returned verbatim by GET /v1/models " +
87
+ "and serves as the @-mention handle, so the entry is not served rather than served under a name that every log line has to mask; rename the entry to a plain identifier " +
88
+ "to bring it back, and treat the credential as exposed if the name was pasted from a real one",
89
+ };
90
+ }
77
91
  function droppedRowEnabled(row) {
78
92
  return row.identity?.enabled !== false;
79
93
  }
@@ -116,13 +130,13 @@ export function judgeCatalogEntries(enabled, ctx, dropped) {
116
130
  export function buildModelRefusalsSignal(v) {
117
131
  if (v === undefined)
118
132
  return undefined;
119
- const entries = Object.fromEntries(Object.entries(v.entries).flatMap(([name, r]) => (isReportableRefusalName(name) ? [[name, r.code]] : [])));
133
+ const entries = Object.fromEntries(Object.entries(v.entries).flatMap(([name, r]) => (disclosableRefusalName(name) !== undefined ? [[name, r.code]] : [])));
120
134
  if (Object.keys(entries).length === 0 && v.plane === undefined)
121
135
  return undefined;
122
136
  return v.plane === undefined ? { entries } : { entries, plane: v.plane };
123
137
  }
124
138
  function disclosableRefusalName(name) {
125
- return isReportableRefusalName(name) ? name : undefined;
139
+ return isReportableRefusalName(name) && !isCredentialShapedUnit(name) ? name : undefined;
126
140
  }
127
141
  export function refusedNameLogField(key, name) {
128
142
  const shown = disclosableRefusalName(name);
@@ -159,7 +173,7 @@ export function echoModelRef(ref) {
159
173
  return echoCallerText(ref, { maxChars: MODEL_REF_ECHO_CHARS });
160
174
  }
161
175
  export function modelUnavailableMessage(field, requested, name, r) {
162
- const alias = requested === name ? "" : ` (catalog entry "${name}")`;
176
+ const alias = requested === name ? "" : ` (catalog entry ${nameSlot(name)})`;
163
177
  return `${field} "${echoModelRef(requested)}"${alias} is published in the catalog but unavailable on this deployment [${r.code}] — ${r.detail}`;
164
178
  }
165
179
  export function modelNotAllowedMessage(field, requested, resolved) {
@@ -4,7 +4,8 @@
4
4
  * 两层,一只 `AsyncLocalStorage`:
5
5
  * · **腿层**(`withModelReachScope`,三条带用户面投递口的 run 腿各包一次:流式 `POST /v1/tasks/stream`、后台 `POST /v1/runs`、续跑):
6
6
  * 带着这条腿的两枚身份 —— `sessionId`(通告归属键)与 `taskId`(这条腿的 run 资源 id,= 本腿交给引擎的 `spec.taskId`;7.121.0)——
7
- * 与本腿已经说过的目标集合(去重单位 = 每腿每目标一次);
7
+ * 与本腿已经说过的目标集合(去重单位 = 每腿每目标一次);腿层的 `sessionId` 同时是读拒字节地板通告的归属键
8
+ * (`read-deny-floor-notice.ts` 的 `presentEngineNotice`:腿派出去的 run —— cascade 的级、验证器、子代 —— 的那一帧落在这条腿的流上);
8
9
  * · **调用层**(`createModelReachBrain` 每次模型调用包一次):一只可变的 {@link ModelCallReach},出网观察者
9
10
  * (`outbound-dispatcher.ts` 的 undici 诊断通道订阅)把这次调用发出的每一条请求的**结局**记在上面 —— 最后一条是
10
11
  * 「连上了、有了回答」还是「建连就失败了」。
@@ -303,6 +303,10 @@ export declare const FAIL_OPEN_TAGS: {
303
303
  readonly cls: "F";
304
304
  readonly note: "`memory-incident-sink.ts` 的 `createMemoryEngineIncidentSink`(两只宿主 `onError` 的 `memory` 相共用的落点):记忆相上到达店形拒族(`STORE_FORM_REFUSAL_CODES`,按族读;引擎 7.65.0 起含控制面所在文件系统不能建硬链接的 `memory.control_plane_links_unsupported`)的码 ⇒ 引擎的一步记忆活被店拒、会话照跑:mount 时开店被拒 ⇒ 这一跑记忆面读作 `memoryless`(`mount-failed`);mount 之后的整理 / 收割撞上 ⇒ 那一步没做(席只认码与相,不分哪一步 —— 是哪一步看同一行 `memory_engine_incident` 的句子)。放行的最坏后果 = 这一跑没有记忆或少做一步记忆活(不召回、不采集、不收割、不整理)—— 少做,不是错做:不开门、不放宽任何判据,模型读不到的是记忆不是别的;不放行的代价是记忆盘一个挂载面的形不对就让每一跑都失败。留痕是因为「这台部署的记忆从来没挂上」与「会话里本来没东西可记」在外部同形:逐次计数 + 探针 + 每进程一次 warn,detail `code=<店形拒码>`(运维行 `memory_engine_incident` 另带码与经出口座的句子);出路 = 把记忆控制面放到支持硬链接的卷上(或按码修挂载形)后重启。";
305
305
  };
306
+ readonly "server.memory.project-marker-unreadable": {
307
+ readonly cls: "F";
308
+ readonly note: "单用户记忆项目层的身份(`project-identity.ts` 的 `markerFact`,唯一读者 `projectLayerIdentityOf`;装配期每个任务读一次):检出的 `.sema/project` 记号**读不出** —— 坏记号(`config.memory_project_marker`)、嵌套在仓根之下的记号(`config.memory_project_marker_nested`)、存在性查询或读本身失败 ⇒ 这一任务**没有项目层**(声明席 `{ absent: \"unreadable\" }`):写家落全局层,引擎同拍铸 operator 通知 `memory.project_scope_absent`,并在每条腿上自己报一次记号的错(`onError`,相 `config`)。**不**退回 git 根档 —— 那会在记号读得出之后静默换键。放行的最坏后果 = 这一任务的项目记忆写进全局层(同一用户的其它项目也读得到,单用户部署内,不越属主),记号修好之后 git 根档折进记号档、全局层里这段时间写下的条目不回项目层;不是门、不是凭据、不改任何裁决。反方向(拒整条 run)为一只坏记号打死用户的任务,且引擎自己对不消费项目身份的腿也照跑。detail = `code=<引擎的记号码 | ->`(句子与路径在引擎那一行里)。计数持续非零 = 有检出带着坏 / 嵌套记号,去修记号。";
309
+ };
306
310
  readonly "server.memory.locked-layer-probe-partial": {
307
311
  readonly cls: "F";
308
312
  readonly note: "O2(7.101.0 合并复审,`memory-layer-legacy-lock.ts announceLockedLegacyMemoryLayers`,boot 期锁住记忆层探测;detail 只报 `unreadable=<条数>`):挂载面或某个层里的目录**读不出**(EACCES 之类 —— 不是 ≤7.30.x 引擎的锁形,那种 0555 目录可读)⇒ 那棵子树看不全,照常起服。放行的最坏后果 = 一个锁住的层在 boot 日志里没被点名 —— 探测是**披露**面,不参与任何门 / 裁决;core 在真正失败的那一次删除上仍给出自己的 `chmod -R u+w` 补救句。不放行的代价严重不对称:为一条 warn 打死起服(混跑窗里能服务的副本)。计数让「这台部署的记忆树有读不出的目录」显形。";
@@ -409,7 +413,7 @@ export declare const FAIL_OPEN_TAGS: {
409
413
  };
410
414
  readonly "server.runs.terminal-ledger-write-failed": {
411
415
  readonly cls: "F";
412
- readonly note: "S-107(全量门 silent-degradation 棘轮抓出的五处静默 `catch {}`):run 终局链里**账本腿**(flush 缓冲 text/reasoning、append `failed` 行)与终态翻转(setTerminal)已不共命运——账本 INSERT 抛不再让 run 卡 running 到 reaper;但那条抛掉的账本行之前是**静默**吞的。detail `arm=` 四臂(flush-clean-cancel / append-clean-cancel / flush-catch / append-thrown-cancel / append-failed);S-947 起续跑腿(`http/resume-legs.ts`)两座同 tag:resume-append-resume-aborted / resume-append-thrown-cancel(取消抛出两臂的 `failed` 行,修前那两臂根本不落账本终局行):缺的是 run_events 尾巴(缓冲文本或 failed 事件),run 行本身仍是 durable truth,读面/reaper 容忍缺失,故 F 类;计数=多少次终局账本写失败。";
416
+ readonly note: "S-107(全量门 silent-degradation 棘轮抓出的五处静默 `catch {}`):run 终局链里**账本腿**(flush 缓冲 text/reasoning、append `failed` 行)与终态翻转(setTerminal)已不共命运——账本 INSERT 抛不再让 run 卡 running 到 reaper;但那条抛掉的账本行之前是**静默**吞的。detail `arm=` 四臂(flush-clean-cancel / append-clean-cancel / flush-catch / append-thrown-cancel / append-failed);S-947 起续跑腿(`http/resume-legs.ts`)两座同 tag:resume-append-resume-aborted / resume-append-thrown-cancel(取消抛出两臂的 `failed` 行,修前那两臂根本不落账本终局行);停驻帧同一条律(卡已提交之后,停驻的账本投影写不下不改判词,行的停驻写是唯一提交点 —— `park-row-commit.ts`):park-usage / park-row(park 行唯一写口 `trace/project.ts` 的 `appendParkRow`,三条腿同经)、park-held(后台腿停驻结果到手之后、进停驻臂之前一笔簿记写抛 ⇒ 照常停驻)、resume-park-projection(续跑 verify 臂停驻形的清单 / 用量 / 停驻帧那一段)、resume-park-held(续跑腿再停结果到手之后一笔簿记写抛 ⇒ 本腿照常再停,detail 带那一抛的原句):缺的是 run_events 尾巴(缓冲文本、failed 事件或停驻帧),run 行本身仍是 durable truth,读面/reaper 容忍缺失,故 F 类;计数=多少次状态帧(终局 / 停驻)账本写失败。";
413
417
  };
414
418
  readonly "server.live-text.hold-diverged": {
415
419
  readonly cls: "P-DEBT";
@@ -657,7 +661,15 @@ export declare const FAIL_OPEN_TAGS: {
657
661
  };
658
662
  readonly "server.park.held-card-void-failed": {
659
663
  readonly cls: "F";
660
- readonly note: "停驻没落定就以失败收场的腿(`runs.ts` 的 `voidHeldParkCard`;两处:后台腿 catch 的失败臂 `leg=bg`、续跑腿 catch 放认领的取消 / 普通异常两臂 `leg=resume`):手里的结果是宿主层停驻(引擎交回之前已把卡落进 checkpoint 店,卡在本 run 的会话上),而停驻行 / 用量行 / 结果到手之后的账本写抛 ⇒ 腿以 `failed` 收场、放认领;放认领之前先按卡自己的 scope 店级 `expire` 作废那张卡(动词 = `card-void.ts` 的结算作废)。作废没做成 —— 店读 / 作废抛错(`store_error`)、卡的会话与本 run 的会话对不上(`card_mismatch`,只作废那一张,对不上就不动)、本部署没接 checkpoint 店(`no_checkpoint_store`)—— 照样以 `failed` 收场、放认领,每次记一次。放行的最坏后果 = 那张卡回到修前的形:留在待决面上,兑现它的 run 已经 `failed`、认领已放,决定口照样受理、续跑在没有认领的会话上驱动(`resume-legs.ts` 认领缺席成因 ②),由审批兜底收割收走;前提是停驻簿记写失败,并且这张卡没作废成(三个 reason 任一:checkpoint 店这一笔也失败 / 卡与本 run 的会话对不上 / 没接店 —— 后两者不需要第二次写失败)。不是门、不是凭据、不改 run 的判词。计数非零 = 有一次停驻没落定的失败收场留下了一张卡:按 reason 看 —— `store_error` = checkpoint 店在同一拍也出错,`card_mismatch` = 结果里的卡与本 run 的会话对不上,`no_checkpoint_store` = 这台部署没接 checkpoint 店;去看那只会话。detail = `reason=<词> leg=<bg|resume> [err=<原句>]`(不含凭据)。";
664
+ readonly note: "卡已提交(引擎交回停驻之前已把卡落进 checkpoint 店,卡在本 run 的会话上)而兑现它的 run 不再等它,本服务按卡自己的 scope 店级 `expire` 作废那张卡(动词 = `card-void.ts` 的结算作废)—— 两个产地:① 手里握着停驻结果、却以终局收场的腿(`runs.ts` 的 `voidHeldParkCard`:后台腿 catch 的失败臂 `leg=bg` —— 取消落在结果到手之后、或结果不是停驻词;续跑腿 catch 放认领的取消 / 普通异常两臂 `leg=resume`),卡的命运先于认领释放;② 停驻的唯一提交点(`park-row-commit.ts` 的 `commitParkRow`,`leg=bg|resume|sync`,detail 多一位 `at=<park_commit_refused|park_commit_cancelled>`):行的停驻写被店答出「不」而读到的行不在或已终局(被收割 / 别处终结 / 接手腿收场)⇒ `park_commit_refused`,卡跟着行作废;读到行归本腿、在跑、挂着取消请求 ⇒ `park_commit_cancelled`,先作废卡、再落取消终局。停驻簿记(账本帧 / 用量差)写不下与行的停驻写撞店故障**都不是**产地(前者只留痕、后者续写,见 `server.park.row-commit-deferred`)。作废没做成 —— 店读 / 作废抛错(`store_error`)、卡的会话与本 run 的会话对不上(`card_mismatch`,只作废那一张,对不上就不动)、本部署没接 checkpoint 店(`no_checkpoint_store`)—— 收场照走,每次记一次。放行的最坏后果 = 那张卡留在待决面上,兑现它的 run 已经终局、认领已放:决定口照样受理、续跑在没有认领的会话上驱动(`resume-legs.ts` 认领缺席成因),由审批兜底收割按卡的截止收走。不是门、不是凭据、不改 run 的判词。计数非零 = 留下了一张兑现不了的卡:按 reason 看 —— `store_error` = checkpoint 店在同一拍也出错,`card_mismatch` = 卡与本 run 的会话对不上,`no_checkpoint_store` = 这台部署没接 checkpoint 店;去看那只会话。detail = `reason=<词> leg=<bg|resume|sync>[ at=<park_commit_refused|park_commit_cancelled>][ err=<原句>]`(不含凭据)。";
665
+ };
666
+ readonly "server.park.row-commit-deferred": {
667
+ readonly cls: "F";
668
+ readonly note: "停驻的唯一提交点(`park-row-commit.ts` 的 `commitParkRow`;三条腿同经:后台腿 `leg=bg`、续跑腿的再停 / 重开 / 放回 `leg=resume`、同步 detach 腿 `leg=sync`):卡已提交之后 run 行的停驻写(`setSuspended` / `setNeedsReview`)撞店故障(抛:连接 / 超时 / 程序错)。规则「店的故障不是答案」⇒ 不收场:行不落 failed、卡不作废、认领留着,同一笔停驻再提交 —— 当拍一次,仍没答出 ⇒ 按心跳节拍续,店答出即收。停驻写的 CAS = 行仍归本腿(持有腿 `leg_id`,认领铸、交给本腿)∧ 在跑(或已停在本词上)∧ 没挂取消请求;第一笔与每一次再提交是同一个形(一笔抛了的写结局未知,同词重写幂等):写,店答出「不」⇒ 读行、由行答 —— 行不在 / 已终局 ⇒ 卡跟着作废;归别的腿、还活着 ⇒ 接手腿已接走,不再写;归本腿、停在本词上 ⇒ 停驻成立;归本腿、在跑、挂着取消请求 ⇒ 先作废卡、再落取消终局(码 `cancelled`;作废见 `server.park.held-card-void-failed`)。上界 = 两个判活窗(`REAP_RUN_STALE_SEC`);到上界仍没答 ⇒ 停手、交既有出路:行由失联收割按判活窗收成 failed 并放认领,卡由审批兜底收割按它的截止 / 绝对兜底时刻作废。放行的最坏后果 = 续写期间行停在 `running`(没有心跳):这一窗里决定那张卡答 409 `conflict.not_resumable`(行还没落到停驻词),落下之后同一决定照常受理;进程在续写期间退出 ⇒ 直接交既有出路(行被失联收割、卡由兜底收割)。不是门、不是凭据。detail = `leg=<bg|resume|sync> step=<first|again|retry|gave_up> err=<原句>`(不含凭据);计数 = 停驻提交失败的次数(第一笔写 / 再提交的读、写、取消终局写),`gave_up` 非零 = 有一次停驻交给了既有出路,去看那只会话与店。";
669
+ };
670
+ readonly "server.park.row-commit-contradicted": {
671
+ readonly cls: "F";
672
+ readonly note: "停驻的唯一提交点(`park-row-commit.ts` 的 `commitParkRow`,`leg=bg|resume|sync`)的拒后判之外的那一格:停驻写被店答出「不」,随后读到的行却归本腿、在跑、没挂取消请求 —— CAS 的三件(持有腿 · 在跑或已停在本词上 · 没挂取消)读来都成立而写被拒,店自相矛盾,是不变量破,不是店抖动。本格不猜:当一次店故障处置(不收场、不作废卡、认领留着),交同一条再提交路(当拍一次、心跳节拍续、上界两个判活窗,`server.park.row-commit-deferred` 同计),店答出别的读数即按拒后判收场;一直矛盾 ⇒ 到上界停手、交既有出路(失联收割收行、审批兜底收割收卡)。放行的最坏后果 = 行在续写期间停在 `running`、卡待决到上界。不是门、不是凭据。计数非零 = 本库对同一行的 UPDATE 与 SELECT 答得不一致(读到的不是写判的那一份:读副本 / 隔离级别 / 店的缺陷),去查那只库。detail = `leg=<bg|resume|sync> taskId=<id> word=<suspended|needs_review> status=<读到的词> holder=self cancel=false`(不含凭据)。";
661
673
  };
662
674
  readonly "server.verifier-pause.card-void-failed": {
663
675
  readonly cls: "F";
@@ -284,6 +284,10 @@ export const FAIL_OPEN_TAGS = {
284
284
  cls: "F",
285
285
  note: "`memory-incident-sink.ts` 的 `createMemoryEngineIncidentSink`(两只宿主 `onError` 的 `memory` 相共用的落点):记忆相上到达店形拒族(`STORE_FORM_REFUSAL_CODES`,按族读;引擎 7.65.0 起含控制面所在文件系统不能建硬链接的 `memory.control_plane_links_unsupported`)的码 ⇒ 引擎的一步记忆活被店拒、会话照跑:mount 时开店被拒 ⇒ 这一跑记忆面读作 `memoryless`(`mount-failed`);mount 之后的整理 / 收割撞上 ⇒ 那一步没做(席只认码与相,不分哪一步 —— 是哪一步看同一行 `memory_engine_incident` 的句子)。放行的最坏后果 = 这一跑没有记忆或少做一步记忆活(不召回、不采集、不收割、不整理)—— 少做,不是错做:不开门、不放宽任何判据,模型读不到的是记忆不是别的;不放行的代价是记忆盘一个挂载面的形不对就让每一跑都失败。留痕是因为「这台部署的记忆从来没挂上」与「会话里本来没东西可记」在外部同形:逐次计数 + 探针 + 每进程一次 warn,detail `code=<店形拒码>`(运维行 `memory_engine_incident` 另带码与经出口座的句子);出路 = 把记忆控制面放到支持硬链接的卷上(或按码修挂载形)后重启。",
286
286
  },
287
+ "server.memory.project-marker-unreadable": {
288
+ cls: "F",
289
+ note: "单用户记忆项目层的身份(`project-identity.ts` 的 `markerFact`,唯一读者 `projectLayerIdentityOf`;装配期每个任务读一次):检出的 `.sema/project` 记号**读不出** —— 坏记号(`config.memory_project_marker`)、嵌套在仓根之下的记号(`config.memory_project_marker_nested`)、存在性查询或读本身失败 ⇒ 这一任务**没有项目层**(声明席 `{ absent: \"unreadable\" }`):写家落全局层,引擎同拍铸 operator 通知 `memory.project_scope_absent`,并在每条腿上自己报一次记号的错(`onError`,相 `config`)。**不**退回 git 根档 —— 那会在记号读得出之后静默换键。放行的最坏后果 = 这一任务的项目记忆写进全局层(同一用户的其它项目也读得到,单用户部署内,不越属主),记号修好之后 git 根档折进记号档、全局层里这段时间写下的条目不回项目层;不是门、不是凭据、不改任何裁决。反方向(拒整条 run)为一只坏记号打死用户的任务,且引擎自己对不消费项目身份的腿也照跑。detail = `code=<引擎的记号码 | ->`(句子与路径在引擎那一行里)。计数持续非零 = 有检出带着坏 / 嵌套记号,去修记号。",
290
+ },
287
291
  "server.memory.locked-layer-probe-partial": {
288
292
  cls: "F",
289
293
  note: "O2(7.101.0 合并复审,`memory-layer-legacy-lock.ts announceLockedLegacyMemoryLayers`,boot 期锁住记忆层探测;detail 只报 `unreadable=<条数>`):挂载面或某个层里的目录**读不出**(EACCES 之类 —— 不是 ≤7.30.x 引擎的锁形,那种 0555 目录可读)⇒ 那棵子树看不全,照常起服。放行的最坏后果 = 一个锁住的层在 boot 日志里没被点名 —— 探测是**披露**面,不参与任何门 / 裁决;core 在真正失败的那一次删除上仍给出自己的 `chmod -R u+w` 补救句。不放行的代价严重不对称:为一条 warn 打死起服(混跑窗里能服务的副本)。计数让「这台部署的记忆树有读不出的目录」显形。",
@@ -373,7 +377,7 @@ export const FAIL_OPEN_TAGS = {
373
377
  "server.run-terminal.diag-capped": { cls: "F", note: "S-107:诊断文本座(merge details/measure/grader trace、leader 日志座、planner 样本、journal 预览、workflow_run error cut)长度 > DIAG_INPUT_CAP(256KB)⇒ 整段换 «redacted:oversized-diagnostic» [len=N](fail-closed 取证丢弃;固定窗不 fail-closed 故不开窗);计数=多少段诊断文本被整段丢弃" },
374
378
  "server.run-terminal.output-truncated": { cls: "F", note: "S-107:持久 error 脱后 UTF-8 字节 > 65,000(TiDB TEXT 65,535 字节)⇒ 脱后切并带标记(切在占位里不是泄漏);计数=多少条终态文案被字节封顶截断" },
375
379
  "server.runs.abort-cause-missing": { cls: "F", note: "S-947 候裁 ⑤(主会话裁:默认值保留,miss 臂必须响):续跑腿 `http/resume-legs.ts` 的 `checkpoint.resume_aborted` 臂 —— core 只在本腿递进去的信号**已中止**时铸该码,而那只信号唯一的写者是取消动词(快路 / 耐久旗轮询,句柄登记 `cancel_verb`),所以**只有 core 契约外的形**(桩 / 非 core Runner 直接抛该码,本腿句柄从未中止)才到得了「句柄上读不到成因」这一臂。取消终局照铸,成因取本腿唯一的中止词 `cancel_verb`(取消终局恒带成因由铸点签名保证,不让它缺);detail `task=<taskId>`;计数 = 多少次取消成因是默认值而不是句柄登记的。生产上恒零是证据,不归零 = 有一条不走 core 契约的 Runner 在跑续跑腿。" },
376
- "server.runs.terminal-ledger-write-failed": { cls: "F", note: "S-107(全量门 silent-degradation 棘轮抓出的五处静默 `catch {}`):run 终局链里**账本腿**(flush 缓冲 text/reasoning、append `failed` 行)与终态翻转(setTerminal)已不共命运——账本 INSERT 抛不再让 run 卡 running 到 reaper;但那条抛掉的账本行之前是**静默**吞的。detail `arm=` 四臂(flush-clean-cancel / append-clean-cancel / flush-catch / append-thrown-cancel / append-failed);S-947 起续跑腿(`http/resume-legs.ts`)两座同 tag:resume-append-resume-aborted / resume-append-thrown-cancel(取消抛出两臂的 `failed` 行,修前那两臂根本不落账本终局行):缺的是 run_events 尾巴(缓冲文本或 failed 事件),run 行本身仍是 durable truth,读面/reaper 容忍缺失,故 F 类;计数=多少次终局账本写失败。" },
380
+ "server.runs.terminal-ledger-write-failed": { cls: "F", note: "S-107(全量门 silent-degradation 棘轮抓出的五处静默 `catch {}`):run 终局链里**账本腿**(flush 缓冲 text/reasoning、append `failed` 行)与终态翻转(setTerminal)已不共命运——账本 INSERT 抛不再让 run 卡 running 到 reaper;但那条抛掉的账本行之前是**静默**吞的。detail `arm=` 四臂(flush-clean-cancel / append-clean-cancel / flush-catch / append-thrown-cancel / append-failed);S-947 起续跑腿(`http/resume-legs.ts`)两座同 tag:resume-append-resume-aborted / resume-append-thrown-cancel(取消抛出两臂的 `failed` 行,修前那两臂根本不落账本终局行);停驻帧同一条律(卡已提交之后,停驻的账本投影写不下不改判词,行的停驻写是唯一提交点 —— `park-row-commit.ts`):park-usage / park-row(park 行唯一写口 `trace/project.ts` 的 `appendParkRow`,三条腿同经)、park-held(后台腿停驻结果到手之后、进停驻臂之前一笔簿记写抛 ⇒ 照常停驻)、resume-park-projection(续跑 verify 臂停驻形的清单 / 用量 / 停驻帧那一段)、resume-park-held(续跑腿再停结果到手之后一笔簿记写抛 ⇒ 本腿照常再停,detail 带那一抛的原句):缺的是 run_events 尾巴(缓冲文本、failed 事件或停驻帧),run 行本身仍是 durable truth,读面/reaper 容忍缺失,故 F 类;计数=多少次状态帧(终局 / 停驻)账本写失败。" },
377
381
  "server.live-text.hold-diverged": {
378
382
  cls: "P-DEBT",
379
383
  note: "live 面模型文本的流式口(`trace/model-segment.ts` 的 `createLiveModelText`,三条 live 腿共用;流式口 = `trace/redact.ts` 的 `createRedactionStream`:喂入 / 取已判定前缀 / 收尾冲刷):一段冲刷时,已取出去的逐块字节与整段读法在那一截上的渲染对不上,或有一条整段读法的跨度横跨放行位 —— 流式口的律被打破(某条判定读到了文本之后才定的东西,却没被读口闭集算作开着 —— 交出点 = 读口闭集的交出点,`trace/redact.ts` 的 `FRONTIER_TERMS`)。处置:余下的字节照整段读法出(横跨放行位的跨度整枚换记号,不再出它的原文字节),段末帧照发整段脱敏的正文、消费端按它整段替换;但**已经出门**的那几块收不回 —— 其中可能有整段读法会遮的字节(这就是 P 族的理由)。债:编译期管不到的两处 —— 扫描器「每次尝试的头上都设一次寄存器」靠人审(一次都没设的那一形另记 `server.redact.scan-view-unattributed`),取证级数封顶从整条臂的足迹包络起补遮(另记 `server.redact.forensic-level-cap`)。钉 = 基线语料全前缀两块喂入 + 逐条按块流过流式口拼接 = 整段脱敏 + 判定距离最远的几形逐码元。detail `family=<text|reasoning> len=<段长>`;计数 = 多少段的律被打破(期望恒 0)。",
@@ -608,7 +612,15 @@ export const FAIL_OPEN_TAGS = {
608
612
  },
609
613
  "server.park.held-card-void-failed": {
610
614
  cls: "F",
611
- note: "停驻没落定就以失败收场的腿(`runs.ts` 的 `voidHeldParkCard`;两处:后台腿 catch 的失败臂 `leg=bg`、续跑腿 catch 放认领的取消 / 普通异常两臂 `leg=resume`):手里的结果是宿主层停驻(引擎交回之前已把卡落进 checkpoint 店,卡在本 run 的会话上),而停驻行 / 用量行 / 结果到手之后的账本写抛 ⇒ 腿以 `failed` 收场、放认领;放认领之前先按卡自己的 scope 店级 `expire` 作废那张卡(动词 = `card-void.ts` 的结算作废)。作废没做成 —— 店读 / 作废抛错(`store_error`)、卡的会话与本 run 的会话对不上(`card_mismatch`,只作废那一张,对不上就不动)、本部署没接 checkpoint 店(`no_checkpoint_store`)—— 照样以 `failed` 收场、放认领,每次记一次。放行的最坏后果 = 那张卡回到修前的形:留在待决面上,兑现它的 run 已经 `failed`、认领已放,决定口照样受理、续跑在没有认领的会话上驱动(`resume-legs.ts` 认领缺席成因 ②),由审批兜底收割收走;前提是停驻簿记写失败,并且这张卡没作废成(三个 reason 任一:checkpoint 店这一笔也失败 / 卡与本 run 的会话对不上 / 没接店 —— 后两者不需要第二次写失败)。不是门、不是凭据、不改 run 的判词。计数非零 = 有一次停驻没落定的失败收场留下了一张卡:按 reason 看 —— `store_error` = checkpoint 店在同一拍也出错,`card_mismatch` = 结果里的卡与本 run 的会话对不上,`no_checkpoint_store` = 这台部署没接 checkpoint 店;去看那只会话。detail = `reason=<词> leg=<bg|resume> [err=<原句>]`(不含凭据)。",
615
+ note: "卡已提交(引擎交回停驻之前已把卡落进 checkpoint 店,卡在本 run 的会话上)而兑现它的 run 不再等它,本服务按卡自己的 scope 店级 `expire` 作废那张卡(动词 = `card-void.ts` 的结算作废)—— 两个产地:① 手里握着停驻结果、却以终局收场的腿(`runs.ts` 的 `voidHeldParkCard`:后台腿 catch 的失败臂 `leg=bg` —— 取消落在结果到手之后、或结果不是停驻词;续跑腿 catch 放认领的取消 / 普通异常两臂 `leg=resume`),卡的命运先于认领释放;② 停驻的唯一提交点(`park-row-commit.ts` 的 `commitParkRow`,`leg=bg|resume|sync`,detail 多一位 `at=<park_commit_refused|park_commit_cancelled>`):行的停驻写被店答出「不」而读到的行不在或已终局(被收割 / 别处终结 / 接手腿收场)⇒ `park_commit_refused`,卡跟着行作废;读到行归本腿、在跑、挂着取消请求 ⇒ `park_commit_cancelled`,先作废卡、再落取消终局。停驻簿记(账本帧 / 用量差)写不下与行的停驻写撞店故障**都不是**产地(前者只留痕、后者续写,见 `server.park.row-commit-deferred`)。作废没做成 —— 店读 / 作废抛错(`store_error`)、卡的会话与本 run 的会话对不上(`card_mismatch`,只作废那一张,对不上就不动)、本部署没接 checkpoint 店(`no_checkpoint_store`)—— 收场照走,每次记一次。放行的最坏后果 = 那张卡留在待决面上,兑现它的 run 已经终局、认领已放:决定口照样受理、续跑在没有认领的会话上驱动(`resume-legs.ts` 认领缺席成因),由审批兜底收割按卡的截止收走。不是门、不是凭据、不改 run 的判词。计数非零 = 留下了一张兑现不了的卡:按 reason 看 —— `store_error` = checkpoint 店在同一拍也出错,`card_mismatch` = 卡与本 run 的会话对不上,`no_checkpoint_store` = 这台部署没接 checkpoint 店;去看那只会话。detail = `reason=<词> leg=<bg|resume|sync>[ at=<park_commit_refused|park_commit_cancelled>][ err=<原句>]`(不含凭据)。",
616
+ },
617
+ "server.park.row-commit-deferred": {
618
+ cls: "F",
619
+ note: "停驻的唯一提交点(`park-row-commit.ts` 的 `commitParkRow`;三条腿同经:后台腿 `leg=bg`、续跑腿的再停 / 重开 / 放回 `leg=resume`、同步 detach 腿 `leg=sync`):卡已提交之后 run 行的停驻写(`setSuspended` / `setNeedsReview`)撞店故障(抛:连接 / 超时 / 程序错)。规则「店的故障不是答案」⇒ 不收场:行不落 failed、卡不作废、认领留着,同一笔停驻再提交 —— 当拍一次,仍没答出 ⇒ 按心跳节拍续,店答出即收。停驻写的 CAS = 行仍归本腿(持有腿 `leg_id`,认领铸、交给本腿)∧ 在跑(或已停在本词上)∧ 没挂取消请求;第一笔与每一次再提交是同一个形(一笔抛了的写结局未知,同词重写幂等):写,店答出「不」⇒ 读行、由行答 —— 行不在 / 已终局 ⇒ 卡跟着作废;归别的腿、还活着 ⇒ 接手腿已接走,不再写;归本腿、停在本词上 ⇒ 停驻成立;归本腿、在跑、挂着取消请求 ⇒ 先作废卡、再落取消终局(码 `cancelled`;作废见 `server.park.held-card-void-failed`)。上界 = 两个判活窗(`REAP_RUN_STALE_SEC`);到上界仍没答 ⇒ 停手、交既有出路:行由失联收割按判活窗收成 failed 并放认领,卡由审批兜底收割按它的截止 / 绝对兜底时刻作废。放行的最坏后果 = 续写期间行停在 `running`(没有心跳):这一窗里决定那张卡答 409 `conflict.not_resumable`(行还没落到停驻词),落下之后同一决定照常受理;进程在续写期间退出 ⇒ 直接交既有出路(行被失联收割、卡由兜底收割)。不是门、不是凭据。detail = `leg=<bg|resume|sync> step=<first|again|retry|gave_up> err=<原句>`(不含凭据);计数 = 停驻提交失败的次数(第一笔写 / 再提交的读、写、取消终局写),`gave_up` 非零 = 有一次停驻交给了既有出路,去看那只会话与店。",
620
+ },
621
+ "server.park.row-commit-contradicted": {
622
+ cls: "F",
623
+ note: "停驻的唯一提交点(`park-row-commit.ts` 的 `commitParkRow`,`leg=bg|resume|sync`)的拒后判之外的那一格:停驻写被店答出「不」,随后读到的行却归本腿、在跑、没挂取消请求 —— CAS 的三件(持有腿 · 在跑或已停在本词上 · 没挂取消)读来都成立而写被拒,店自相矛盾,是不变量破,不是店抖动。本格不猜:当一次店故障处置(不收场、不作废卡、认领留着),交同一条再提交路(当拍一次、心跳节拍续、上界两个判活窗,`server.park.row-commit-deferred` 同计),店答出别的读数即按拒后判收场;一直矛盾 ⇒ 到上界停手、交既有出路(失联收割收行、审批兜底收割收卡)。放行的最坏后果 = 行在续写期间停在 `running`、卡待决到上界。不是门、不是凭据。计数非零 = 本库对同一行的 UPDATE 与 SELECT 答得不一致(读到的不是写判的那一份:读副本 / 隔离级别 / 店的缺陷),去查那只库。detail = `leg=<bg|resume|sync> taskId=<id> word=<suspended|needs_review> status=<读到的词> holder=self cancel=false`(不含凭据)。",
612
624
  },
613
625
  "server.verifier-pause.card-void-failed": {
614
626
  cls: "F",
@@ -239,7 +239,7 @@ export function createMetrics() {
239
239
  m.counter("cost_quota_rejected_total", "Tasks refused because the principal is over its cumulative cost quota");
240
240
  m.counter("deny_sweep_resume_blocked_total", "SLA deny-sweep resumes the resume leg refused (every attempt; the deny_sweep_resume_blocked warn is logged once per row and refusal)");
241
241
  m.counter("deny_sweep_policy_blocked_expired_total", "approvals the SLA deny-sweep expired because the resume leg refused them for an admission-policy reason (resume_blocked_by_policy: the stored request is refused in this version for good, so the model-continuing deny cannot be delivered; counted once per card, only when this sweep won the settle)");
242
- m.counter("submit_ctx_run_release_failed_total", "Submissions whose resume-input write failed AND whose just-claimed run could not be released, by step (terminal|idem_key); the session stays held until REAP_RUN_STALE_SEC (one submit_ctx_run_release_failed warn per failure)");
242
+ m.counter("submit_ctx_run_release_failed_total", "Submissions whose resume-input write failed AND whose just-claimed run could not be withdrawn (step=withdraw: the store did not delete the run this submission minted); the session stays held until REAP_RUN_STALE_SEC (one submit_ctx_run_release_failed warn per failure)");
243
243
  m.counter("deny_sweep_list_failed_total", "SLA deny-sweep ticks whose read of the expired approvals failed (that tick denies nothing; one deny_sweep_list_failed warn per failure)");
244
244
  m.counter("deny_sweep_row_failed_total", "SLA deny-sweep rows whose stored request could not be read this tick (a projection-drift throw); that row is not resumed this tick, the rest of the page is swept (one deny_sweep_row_failed warn per failure)");
245
245
  m.counter("degraded_total", "Tasks degraded to a cheaper model (1.40), by reason (budget/rate_limit/breaker_open)");
@@ -175,6 +175,7 @@ export const RESULT_TEXT_LEAVES = {
175
175
  "cancelContext.lastEventKind": "verbatim",
176
176
  "cancelContext.lastBrainStatus.phase": "verbatim",
177
177
  "cancelContext.lastBrainStatus.errClass": "verbatim",
178
+ "readDenyFloor.message": "verbatim",
178
179
  };
179
180
  const DROP_LEAF = Symbol("drop-leaf");
180
181
  function textLeafAct(treatment) {
@@ -90,7 +90,7 @@ export declare const SECRET_ENV_SCRUB_SITES: {
90
90
  };
91
91
  readonly "server.hooks.spawn-env": {
92
92
  readonly told: "log";
93
- readonly note: "settings hooks 的命令腿(请求带来的命令跑在宿主上)的 env —— 严格名单(`PATH` / `HOME` / 终端 / locale 等十二名)经引擎的 `hostChildEnv` 组合:名单外一律不交,本服务自有凭据任何情况都不交;请求的有效环境层(`settings.env`)作授予叠在上面;请求给工具 shell 的继承词对它不作用";
93
+ readonly note: "settings hooks 的命令腿(请求带来的命令跑在宿主上)的 env —— 严格名单(`PATH` / `HOME` / 终端 / locale 等十二名)∪ 部署方 `HOOK_ENV_ALLOW` 点名放回的变量,经引擎的 `hostChildEnv` 组合:其余一律不交,本服务自有凭据(名与值副本)任何情况都不交;请求的有效环境层(`settings.env`)作授予叠在上面;请求给工具 shell 的继承词对它不作用";
94
94
  readonly remedy: null;
95
95
  };
96
96
  readonly "server.project-memory.git-subprocess": {
@@ -20,7 +20,7 @@ export const SECRET_ENV_SCRUB_SITES = {
20
20
  },
21
21
  "server.hooks.spawn-env": {
22
22
  told: "log",
23
- note: "settings hooks 的命令腿(请求带来的命令跑在宿主上)的 env —— 严格名单(`PATH` / `HOME` / 终端 / locale 等十二名)经引擎的 `hostChildEnv` 组合:名单外一律不交,本服务自有凭据任何情况都不交;请求的有效环境层(`settings.env`)作授予叠在上面;请求给工具 shell 的继承词对它不作用",
23
+ note: "settings hooks 的命令腿(请求带来的命令跑在宿主上)的 env —— 严格名单(`PATH` / `HOME` / 终端 / locale 等十二名)∪ 部署方 `HOOK_ENV_ALLOW` 点名放回的变量,经引擎的 `hostChildEnv` 组合:其余一律不交,本服务自有凭据(名与值副本)任何情况都不交;请求的有效环境层(`settings.env`)作授予叠在上面;请求给工具 shell 的继承词对它不作用",
24
24
  remedy: null,
25
25
  },
26
26
  "server.project-memory.git-subprocess": {