@sema-agent/server 7.151.0 → 7.152.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 (286) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +93 -64
  5. package/deploy/sema-up/README.md +5 -4
  6. package/deploy/sema-up/cluster-up.sh +6 -6
  7. package/deploy/sema-up/kube-up.sh +5 -5
  8. package/deploy/sema-up/lib/flagshape.sh +36 -8
  9. package/deploy/sema-up/machines.example.yaml +3 -1
  10. package/deploy/sema-up/sema-up.sh +22 -16
  11. package/dist/approval-ask-audit-store.d.ts +1 -1
  12. package/dist/approval-ask-machine.d.ts +4 -10
  13. package/dist/approval-ask-retention.d.ts +1 -1
  14. package/dist/approval-card.d.ts +10 -12
  15. package/dist/approval-gate-currency.d.ts +8 -8
  16. package/dist/approval-gate-currency.js +3 -4
  17. package/dist/approval-hmac.d.ts +17 -1
  18. package/dist/approval-hmac.js +7 -1
  19. package/dist/approval-queue-kind.d.ts +1 -1
  20. package/dist/approval.d.ts +2 -2
  21. package/dist/approval.js +2 -2
  22. package/dist/bind-host.d.ts +1 -3
  23. package/dist/bind-host.js +2 -3
  24. package/dist/boot/coordinators.d.ts +1 -1
  25. package/dist/boot/coordinators.js +9 -10
  26. package/dist/boot/device-lane.js +2 -0
  27. package/dist/boot/execution-env.d.ts +1 -0
  28. package/dist/boot/execution-env.js +31 -5
  29. package/dist/boot/leader.d.ts +31 -30
  30. package/dist/boot/leader.js +38 -28
  31. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  32. package/dist/boot/leg-path-adjudication.js +18 -0
  33. package/dist/boot/parked-revive-gate.js +3 -15
  34. package/dist/boot/reapers.d.ts +1 -1
  35. package/dist/boot/reapers.js +1 -1
  36. package/dist/boot/resolve-spec.js +12 -26
  37. package/dist/boot/runner-deps.d.ts +39 -35
  38. package/dist/boot/runner-deps.js +92 -89
  39. package/dist/boot/shutdown.d.ts +6 -0
  40. package/dist/boot/shutdown.js +10 -4
  41. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  42. package/dist/boot/stage-05-execution-env.js +2 -1
  43. package/dist/boot/stage-06-runners.d.ts +2 -0
  44. package/dist/boot/stage-06-runners.js +10 -4
  45. package/dist/boot/stage-07-capability-layer.d.ts +1 -0
  46. package/dist/boot/stage-07-capability-layer.js +1 -1
  47. package/dist/boot/stage-08-reapers.d.ts +1 -0
  48. package/dist/boot/stage-09-leader.d.ts +1 -0
  49. package/dist/boot/stage-09-leader.js +2 -2
  50. package/dist/boot/stage-10-http-server.d.ts +8 -0
  51. package/dist/boot/stage-10-http-server.js +11 -15
  52. package/dist/boot/stores.js +7 -4
  53. package/dist/boot/web-admin.js +2 -7
  54. package/dist/capabilities/approvals-push.d.ts +3 -3
  55. package/dist/capabilities/scenarios.d.ts +28 -13
  56. package/dist/capabilities/scenarios.js +2 -2
  57. package/dist/capability-facts.d.ts +22 -20
  58. package/dist/capability-facts.js +18 -34
  59. package/dist/card-rule-offers.d.ts +32 -0
  60. package/dist/card-rule-offers.js +130 -0
  61. package/dist/config-catalog.js +12 -11
  62. package/dist/config-dir-trust.js +4 -2
  63. package/dist/config-invariants.d.ts +18 -7
  64. package/dist/config-invariants.js +51 -8
  65. package/dist/config-lkg.d.ts +5 -19
  66. package/dist/config-lkg.js +8 -62
  67. package/dist/config-provider.d.ts +1 -1
  68. package/dist/config-root-migration.d.ts +2 -2
  69. package/dist/config-types.d.ts +28 -38
  70. package/dist/config.d.ts +7 -5
  71. package/dist/config.js +55 -16
  72. package/dist/control-socket.d.ts +51 -0
  73. package/dist/control-socket.js +115 -0
  74. package/dist/deployment-governance.d.ts +2 -1
  75. package/dist/device-ws-hub.d.ts +7 -0
  76. package/dist/device-ws-hub.js +7 -1
  77. package/dist/elicitation.js +2 -2
  78. package/dist/entry-problems.d.ts +40 -3
  79. package/dist/entry-problems.js +3 -1
  80. package/dist/execution-env-refusal.d.ts +8 -2
  81. package/dist/execution-env-refusal.js +3 -0
  82. package/dist/fleet/engine-signal.d.ts +12 -29
  83. package/dist/fleet/engine-signal.js +1 -7
  84. package/dist/fleet-client.js +2 -5
  85. package/dist/gate-settlement.d.ts +1 -8
  86. package/dist/gate-settlement.js +0 -4
  87. package/dist/history-anchor.js +1 -1
  88. package/dist/hitl-delivery.d.ts +2 -3
  89. package/dist/hitl-delivery.js +0 -2
  90. package/dist/hooks/hook-llm.js +4 -2
  91. package/dist/hooks/hook-runner.d.ts +3 -2
  92. package/dist/hooks/hook-runner.js +16 -1
  93. package/dist/host-decision.d.ts +11 -11
  94. package/dist/http/active-run-conflict.d.ts +35 -2
  95. package/dist/http/active-run-conflict.js +48 -19
  96. package/dist/http/approval-sweeps.d.ts +1 -1
  97. package/dist/http/approval-sweeps.js +5 -2
  98. package/dist/http/checkpoint-ctx.d.ts +2 -0
  99. package/dist/http/checkpoint-ctx.js +1 -0
  100. package/dist/http/dispatch.d.ts +6 -2
  101. package/dist/http/dispatch.js +25 -5
  102. package/dist/http/durable-run-leg.js +0 -1
  103. package/dist/http/health-reader.d.ts +16 -9
  104. package/dist/http/health-reader.js +2 -1
  105. package/dist/http/health-self-report.js +1 -1
  106. package/dist/http/owner-access.d.ts +2 -3
  107. package/dist/http/owner-access.js +3 -4
  108. package/dist/http/principal-gate.d.ts +49 -21
  109. package/dist/http/principal-gate.js +61 -11
  110. package/dist/http/request-channel.d.ts +23 -0
  111. package/dist/http/request-channel.js +9 -0
  112. package/dist/http/request-guards.js +17 -2
  113. package/dist/http/resume-ctx-read.js +20 -3
  114. package/dist/http/resume-legs.d.ts +2 -2
  115. package/dist/http/resume-legs.js +111 -41
  116. package/dist/http/route-ctx.d.ts +73 -7
  117. package/dist/http/route-ctx.js +17 -0
  118. package/dist/http/route-table.d.ts +4 -0
  119. package/dist/http/route-table.js +4 -0
  120. package/dist/http/routes/admin-config-refresh.js +3 -3
  121. package/dist/http/routes/admin-drain.d.ts +3 -0
  122. package/dist/http/routes/admin-drain.js +7 -7
  123. package/dist/http/routes/admin-memory-optout.js +3 -3
  124. package/dist/http/routes/adoption.js +3 -5
  125. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  126. package/dist/http/routes/approvals-assistant.js +95 -48
  127. package/dist/http/routes/capabilities.d.ts +4 -0
  128. package/dist/http/routes/capabilities.js +30 -5
  129. package/dist/http/routes/config-catalog.js +2 -2
  130. package/dist/http/routes/devices.js +1 -1
  131. package/dist/http/routes/diagnostics.d.ts +3 -3
  132. package/dist/http/routes/diagnostics.js +19 -7
  133. package/dist/http/routes/images.js +10 -10
  134. package/dist/http/routes/memory-bundle.js +3 -3
  135. package/dist/http/routes/memory-compliance.js +3 -3
  136. package/dist/http/routes/memory-consolidation.js +2 -2
  137. package/dist/http/routes/memory-origin.js +3 -3
  138. package/dist/http/routes/memory-policy.js +2 -2
  139. package/dist/http/routes/observability.js +3 -3
  140. package/dist/http/routes/retention-ops.js +3 -3
  141. package/dist/http/routes/rules.js +5 -5
  142. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  143. package/dist/http/routes/run-permission-mode.js +2 -2
  144. package/dist/http/routes/runs.d.ts +4 -9
  145. package/dist/http/routes/runs.js +73 -33
  146. package/dist/http/routes/session-sync.d.ts +18 -6
  147. package/dist/http/routes/session-sync.js +38 -36
  148. package/dist/http/routes/sessions.js +20 -9
  149. package/dist/http/routes/tasks.js +28 -37
  150. package/dist/http/routes/workflows.js +1 -1
  151. package/dist/http/server.d.ts +9 -3
  152. package/dist/http/server.js +15 -3
  153. package/dist/http/submit-ctx.d.ts +1 -1
  154. package/dist/http/submit-ctx.js +2 -0
  155. package/dist/human-facing-args.d.ts +33 -0
  156. package/dist/human-facing-args.js +33 -0
  157. package/dist/index.d.ts +1 -1
  158. package/dist/k8s-api-credentials.d.ts +29 -0
  159. package/dist/k8s-api-credentials.js +25 -0
  160. package/dist/lane-home-probe.d.ts +1 -1
  161. package/dist/lane-home-probe.js +2 -1
  162. package/dist/leader/diffup.d.ts +19 -0
  163. package/dist/leader/diffup.js +7 -0
  164. package/dist/leader/leader.d.ts +114 -10
  165. package/dist/leader/leader.js +69 -5
  166. package/dist/leader/repair-wire.js +2 -2
  167. package/dist/leader/run-entry.d.ts +2 -1
  168. package/dist/leader/run-entry.js +1 -1
  169. package/dist/leader/wire.d.ts +42 -132
  170. package/dist/leader/wire.js +81 -67
  171. package/dist/memory-scope.d.ts +20 -9
  172. package/dist/memory-scope.js +15 -3
  173. package/dist/model-entry-headers.d.ts +9 -10
  174. package/dist/model-entry-headers.js +0 -4
  175. package/dist/model-entry-refusal.d.ts +7 -4
  176. package/dist/model-entry-refusal.js +11 -5
  177. package/dist/model-plane-face.d.ts +1 -1
  178. package/dist/model-plane-face.js +3 -1
  179. package/dist/model-route-endpoint.d.ts +13 -7
  180. package/dist/model-route-endpoint.js +14 -11
  181. package/dist/model-select.d.ts +22 -0
  182. package/dist/model-select.js +9 -0
  183. package/dist/model-unreachable-notice.d.ts +11 -0
  184. package/dist/model-unreachable-notice.js +4 -4
  185. package/dist/object-store-buckets.d.ts +640 -6
  186. package/dist/object-store-buckets.js +166 -0
  187. package/dist/observability/fail-open.d.ts +20 -16
  188. package/dist/observability/fail-open.js +20 -16
  189. package/dist/observability/logger.js +3 -1
  190. package/dist/operator-roster.d.ts +68 -0
  191. package/dist/operator-roster.js +32 -0
  192. package/dist/orchestration/workflow-park-decision.d.ts +1 -1
  193. package/dist/outbound-dispatcher.d.ts +71 -8
  194. package/dist/outbound-dispatcher.js +48 -7
  195. package/dist/owner-faces.d.ts +1 -1
  196. package/dist/parked-decide.d.ts +2 -2
  197. package/dist/permission-mode-admission.d.ts +59 -26
  198. package/dist/permission-mode-admission.js +37 -10
  199. package/dist/plugins/approval-ask-store-file.d.ts +4 -0
  200. package/dist/plugins/approval-ask-store-file.js +3 -0
  201. package/dist/plugins/approval-ask-store-memory.d.ts +4 -0
  202. package/dist/plugins/approval-ask-store-memory.js +7 -1
  203. package/dist/plugins/approval-ask-store-sql.d.ts +26 -2
  204. package/dist/plugins/approval-ask-store-sql.js +12 -1
  205. package/dist/plugins/blob-backend.d.ts +83 -7
  206. package/dist/plugins/blob-backend.js +57 -6
  207. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  208. package/dist/plugins/checkpoint-index-columns.js +3 -6
  209. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  210. package/dist/plugins/checkpoint-store-face.js +134 -55
  211. package/dist/plugins/landed-attendants.d.ts +2 -2
  212. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  213. package/dist/plugins/local-checkpoint-store.js +38 -49
  214. package/dist/plugins/one-time-migrations.d.ts +51 -21
  215. package/dist/plugins/one-time-migrations.js +67 -45
  216. package/dist/plugins/pg-pool.js +11 -9
  217. package/dist/plugins/remote-env-host.d.ts +29 -10
  218. package/dist/plugins/remote-env-host.js +99 -19
  219. package/dist/plugins/remote-env-k8s.d.ts +68 -2
  220. package/dist/plugins/remote-env-k8s.js +107 -24
  221. package/dist/plugins/replica-registration.d.ts +1 -1
  222. package/dist/plugins/replica-registration.js +1 -1
  223. package/dist/plugins/s3-presign.d.ts +23 -0
  224. package/dist/plugins/s3-presign.js +37 -3
  225. package/dist/plugins/scheduler-support.d.ts +2 -2
  226. package/dist/plugins/scheduler-support.js +0 -3
  227. package/dist/plugins/schema-indexes.js +2 -0
  228. package/dist/plugins/send-file-ledger.d.ts +2 -2
  229. package/dist/plugins/send-file-ledger.js +2 -2
  230. package/dist/plugins/send-user-file.d.ts +3 -4
  231. package/dist/plugins/send-user-file.js +56 -52
  232. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  233. package/dist/plugins/session-blob-claim-token.js +20 -0
  234. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  235. package/dist/plugins/session-blob-namespace.js +116 -0
  236. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  237. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  238. package/dist/plugins/sql-json-column.d.ts +1 -1
  239. package/dist/plugins/store-backend.d.ts +44 -2
  240. package/dist/plugins/store-backend.js +75 -53
  241. package/dist/plugins/task-attachment-store.d.ts +2 -1
  242. package/dist/plugins/task-attachment-store.js +5 -1
  243. package/dist/plugins/tidb-pool.js +19 -24
  244. package/dist/plugins/workspace-custody.d.ts +4 -3
  245. package/dist/question.d.ts +2 -1
  246. package/dist/question.js +5 -13
  247. package/dist/request-form.d.ts +6 -1
  248. package/dist/request-form.js +4 -1
  249. package/dist/rule-issue-reading.d.ts +1 -1
  250. package/dist/rules-consent.d.ts +1 -1
  251. package/dist/run-local.js +8 -9
  252. package/dist/runs.d.ts +17 -8
  253. package/dist/runs.js +15 -2
  254. package/dist/runtime-governance.d.ts +2 -2
  255. package/dist/sema-config-dir.d.ts +2 -1
  256. package/dist/session-sync.d.ts +27 -11
  257. package/dist/session-sync.js +15 -7
  258. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  259. package/dist/stores-sql/blob-index-sql.js +40 -21
  260. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  261. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  262. package/dist/stores-sql/file-history-store-sql.d.ts +64 -16
  263. package/dist/stores-sql/file-history-store-sql.js +100 -28
  264. package/dist/stores-sql/retention-store-sql.js +3 -9
  265. package/dist/task-settings.d.ts +6 -5
  266. package/dist/task-settings.js +3 -3
  267. package/dist/tool-approval.d.ts +342 -518
  268. package/dist/tool-approval.js +498 -1207
  269. package/dist/trace/core-keyset-guard.d.ts +1 -1
  270. package/dist/trace/ledger-events.d.ts +3 -3
  271. package/dist/trace/project.d.ts +2 -3
  272. package/dist/trace/redact.js +3 -2
  273. package/dist/trace/self-minted-wire.d.ts +287 -157
  274. package/dist/trace/self-minted-wire.js +93 -48
  275. package/dist/web-admin-client/apply-effective.js +2 -2
  276. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  277. package/dist/web-admin-client/read-warnings.js +1 -1
  278. package/dist/web-admin-client/types.d.ts +1 -1
  279. package/dist/workspace-space.d.ts +10 -4
  280. package/dist/workspace-space.js +4 -1
  281. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +1 -1
  282. package/package.json +6 -2
  283. package/scripts/embed-minimal.mjs +3 -3
  284. package/wire-changes/server@7.152.0.json +900 -0
  285. package/dist/config-d-migration.d.ts +0 -37
  286. package/dist/config-d-migration.js +0 -60
@@ -1,3 +1,169 @@
1
1
  export const SESSION_SNAPSHOT_BUCKET_DEFAULT = "session-snapshots";
2
2
  export const WORKSPACE_SNAPSHOT_BUCKET_DEFAULT = "workspaces";
3
+ export const S3_PUBLIC_BUCKET_DEFAULT = "sema-public";
4
+ export const WORKSPACE_SNAPSHOT_PREFIX_DEFAULT = "kata";
5
+ export const LEGACY_BLOB_ROOT_DEFAULT = "blobs/";
6
+ export const FILE_HISTORY_BLOB_SEGMENT = "file-history/";
7
+ export const ATTACHMENT_BLOB_SEGMENT = "attachments/";
8
+ export const SESSION_BLOB_CLAIM_KEY = "blob-namespace-claim";
9
+ export function sessionSnapshotPrefixProblem(prefix) {
10
+ for (const segment of [FILE_HISTORY_BLOB_SEGMENT, ATTACHMENT_BLOB_SEGMENT]) {
11
+ if (prefix.endsWith(segment))
12
+ return `it ends with "${segment}", a session blob domain's own segment: the retired epoch's root is the prefix itself, so it would be another engine's ${segment} domain`;
13
+ }
14
+ return undefined;
15
+ }
16
+ export const SENDFILE_PRIVATE_PREFIX = "sendfile/";
17
+ export const SENDFILE_STAGING_SEGMENT = "staging/";
18
+ export const LEADER_DIFF_PREFIX = "leader-diff";
19
+ export const OBJECT_STORE_BUCKET_KNOBS = {
20
+ SESSION_SNAPSHOT_BUCKET: SESSION_SNAPSHOT_BUCKET_DEFAULT,
21
+ WORKSPACE_SNAPSHOT_BUCKET: WORKSPACE_SNAPSHOT_BUCKET_DEFAULT,
22
+ MINIO_BUCKET: WORKSPACE_SNAPSHOT_BUCKET_DEFAULT,
23
+ S3_PUBLIC_BUCKET: S3_PUBLIC_BUCKET_DEFAULT,
24
+ };
25
+ export const OBJECT_KEY_KNOB_SLOTS = {
26
+ workspacePrefix: { knob: "WORKSPACE_SNAPSHOT_PREFIX", unset: WORKSPACE_SNAPSHOT_PREFIX_DEFAULT },
27
+ sessionPrefix: { knob: "SESSION_SNAPSHOT_PREFIX", unset: "" },
28
+ legacyBlobRoot: { knob: "SESSION_SNAPSHOT_PREFIX", unset: LEGACY_BLOB_ROOT_DEFAULT },
29
+ };
30
+ export const OBJECT_KEY_SEGMENTS = {
31
+ sessionId: "the parked run's session id (an env without one cannot park: its `_` placeholder is outside the key segment shape, so nothing is signed)",
32
+ incarnation: "the space occupant's incarnation (the session occupant's minted id)",
33
+ snapshotId: "a snapshot id minted for one upload (carries the writer's ownership mark)",
34
+ object: "an object name read from the partition's listing",
35
+ sha256: "the blob's content address (hex sha256)",
36
+ scope: "the hashed tenant segment (`_` for a single-user deployment)",
37
+ uuid: "a uuidv7 minted per file (the capability part of a link)",
38
+ name: "the sanitized file name",
39
+ run: "the leader run's object tag (time + random)",
40
+ workerId: "the leader sub-worker id",
41
+ };
42
+ export const OBJECT_STORE_ACTION_VERBS = ["GET", "PUT", "HEAD", "DELETE", "LIST", "COPY"];
43
+ export const OBJECT_STORE_ACTION_PERMISSIONS = {
44
+ GET: ["s3:GetObject"],
45
+ PUT: ["s3:PutObject"],
46
+ HEAD: ["s3:GetObject"],
47
+ DELETE: ["s3:DeleteObject"],
48
+ LIST: ["s3:ListBucket"],
49
+ COPY: ["s3:PutObject"],
50
+ };
51
+ export const OBJECT_STORE_EXECUTORS = {
52
+ server: "the server process sends it itself (from its replica's network)",
53
+ sandbox: "the execution sandbox sends it (a k8s pod, an e2b / ssh sandbox, a leader worker env): it holds the presigned URL only, never the key",
54
+ client: "the end user's client fetches the link the server handed out",
55
+ };
56
+ export const OBJECT_STORE_DOMAINS = {
57
+ "k8s-park": "k8s lane: a parked run's workspace archive (suspend / resume) and its reclaim",
58
+ "k8s-space": "k8s lane: the workspace space (run-end snapshot, `latest` pointer, restore, prune) and its reclaim",
59
+ "boot-probe": "boot: the one bucket-presence check per bucket",
60
+ "file-history": "file-history blob bytes",
61
+ attachments: "task attachment bytes and their orphan sweep",
62
+ "blob-claim": "the session blob namespace's claim: one database per bucket × SESSION_SNAPSHOT_PREFIX (checked when the store opens)",
63
+ "legacy-blobs": "the retired snapshot epoch's blob bytes (sweep only)",
64
+ sendfile: "SendUserFile: the permanent and presigned tracks and the sandbox staging two-phase",
65
+ "leader-diff": "the leader's diff-out: a worker uploads its patch, the leader fetches it",
66
+ };
67
+ export const SIGV4_PRESIGN_MAX_SEC = 604_800;
68
+ const PARK = "{workspacePrefix}/<sessionId>/";
69
+ const SPACE = "{workspacePrefix}/<incarnation>/space/";
70
+ const K8S_TTL = { defaultSec: 600, knob: "WORKSPACE_SNAPSHOT_TTL_SEC", maxSec: 3600 };
71
+ const BLOB_TTL = { defaultSec: 3600, knob: "SESSION_SNAPSHOT_TTL_SEC" };
72
+ const FILE_HISTORY_KEY = `{sessionPrefix}${FILE_HISTORY_BLOB_SEGMENT}<sha256>`;
73
+ const ATTACHMENT_ROOT = `{sessionPrefix}${ATTACHMENT_BLOB_SEGMENT}`;
74
+ const CLAIM_KEY = `{sessionPrefix}${SESSION_BLOB_CLAIM_KEY}`;
75
+ const CLAIM_TTL = { defaultSec: 60 };
76
+ const SENDFILE_PUBLIC_KEY = "<scope>/<uuid>/<name>";
77
+ const SENDFILE_PRIVATE_KEY = `${SENDFILE_PRIVATE_PREFIX}<scope>/<uuid>/<name>`;
78
+ const SENDFILE_STAGING = { bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: `${SENDFILE_PRIVATE_PREFIX}${SENDFILE_STAGING_SEGMENT}<scope>/<uuid>` };
79
+ const SENDFILE_SERVER_TTL = { defaultSec: 60 };
80
+ const LEADER_KEY = `${LEADER_DIFF_PREFIX}/<run>/<workerId>.patch`;
81
+ const LEADER_TTL = { knob: "LEADER_TIMEOUT_MS" };
82
+ export const OBJECT_STORE_ACTIONS = [
83
+ { domain: "k8s-park", subject: "archive", action: "PUT", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${PARK}<snapshotId>.tar.gz`, executor: "sandbox", ttl: K8S_TTL },
84
+ { domain: "k8s-park", subject: "archive", action: "HEAD", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${PARK}<snapshotId>.tar.gz`, executor: "server", ttl: K8S_TTL },
85
+ { domain: "k8s-park", subject: "archive", action: "GET", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${PARK}<snapshotId>.tar.gz`, executor: "sandbox", ttl: K8S_TTL },
86
+ { domain: "k8s-park", subject: "prefix", action: "LIST", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: PARK, executor: "server", ttl: K8S_TTL },
87
+ { domain: "k8s-park", subject: "object", action: "DELETE", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${PARK}<object>`, executor: "server", ttl: K8S_TTL },
88
+ { domain: "k8s-space", subject: "archive", action: "PUT", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}<snapshotId>.tar.gz`, executor: "sandbox", ttl: K8S_TTL },
89
+ { domain: "k8s-space", subject: "archive", action: "HEAD", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}<snapshotId>.tar.gz`, executor: "server", ttl: K8S_TTL },
90
+ { domain: "k8s-space", subject: "archive", action: "GET", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}<snapshotId>.tar.gz`, executor: "sandbox", ttl: K8S_TTL },
91
+ { domain: "k8s-space", subject: "archive", action: "DELETE", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}<snapshotId>.tar.gz`, executor: "server", ttl: K8S_TTL },
92
+ { domain: "k8s-space", subject: "latest", action: "GET", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}latest`, executor: "server", ttl: K8S_TTL },
93
+ { domain: "k8s-space", subject: "latest", action: "PUT", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}latest`, executor: "server", ttl: K8S_TTL },
94
+ { domain: "k8s-space", subject: "latest", action: "DELETE", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}latest`, executor: "server", ttl: K8S_TTL },
95
+ { domain: "k8s-space", subject: "prefix", action: "LIST", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: SPACE, executor: "server", ttl: K8S_TTL },
96
+ { domain: "k8s-space", subject: "object", action: "DELETE", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: `${SPACE}<object>`, executor: "server", ttl: K8S_TTL },
97
+ { domain: "boot-probe", subject: "session", action: "LIST", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: "{legacyBlobRoot}", executor: "server", ttl: { defaultSec: 3600 } },
98
+ { domain: "boot-probe", subject: "workspace", action: "LIST", bucketKnob: "WORKSPACE_SNAPSHOT_BUCKET", key: "{workspacePrefix}/", executor: "server", ttl: { defaultSec: 3600 } },
99
+ { domain: "file-history", subject: "blob", action: "PUT", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: FILE_HISTORY_KEY, executor: "server", ttl: BLOB_TTL },
100
+ { domain: "file-history", subject: "blob", action: "GET", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: FILE_HISTORY_KEY, executor: "server", ttl: BLOB_TTL },
101
+ { domain: "file-history", subject: "blob", action: "DELETE", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: FILE_HISTORY_KEY, executor: "server", ttl: BLOB_TTL },
102
+ { domain: "attachments", subject: "blob", action: "PUT", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: `${ATTACHMENT_ROOT}<sha256>`, executor: "server", ttl: BLOB_TTL },
103
+ { domain: "attachments", subject: "blob", action: "GET", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: `${ATTACHMENT_ROOT}<sha256>`, executor: "server", ttl: BLOB_TTL },
104
+ { domain: "attachments", subject: "blob", action: "HEAD", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: `${ATTACHMENT_ROOT}<sha256>`, executor: "server", ttl: BLOB_TTL },
105
+ { domain: "attachments", subject: "blob", action: "DELETE", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: `${ATTACHMENT_ROOT}<sha256>`, executor: "server", ttl: BLOB_TTL },
106
+ { domain: "attachments", subject: "prefix", action: "LIST", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: ATTACHMENT_ROOT, executor: "server", ttl: BLOB_TTL },
107
+ { domain: "legacy-blobs", subject: "blob", action: "DELETE", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: "{legacyBlobRoot}<sha256>", executor: "server", ttl: BLOB_TTL },
108
+ { domain: "blob-claim", subject: "claim", action: "GET", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: CLAIM_KEY, executor: "server", ttl: CLAIM_TTL },
109
+ { domain: "blob-claim", subject: "claim", action: "PUT", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: CLAIM_KEY, executor: "server", ttl: CLAIM_TTL },
110
+ { domain: "sendfile", subject: "public", action: "PUT", bucketKnob: "S3_PUBLIC_BUCKET", key: SENDFILE_PUBLIC_KEY, executor: "server", ttl: { defaultSec: 600 } },
111
+ { domain: "sendfile", subject: "public", action: "COPY", bucketKnob: "S3_PUBLIC_BUCKET", key: SENDFILE_PUBLIC_KEY, executor: "server", ttl: SENDFILE_SERVER_TTL, from: SENDFILE_STAGING },
112
+ { domain: "sendfile", subject: "public", action: "HEAD", bucketKnob: "S3_PUBLIC_BUCKET", key: SENDFILE_PUBLIC_KEY, executor: "server", ttl: SENDFILE_SERVER_TTL },
113
+ { domain: "sendfile", subject: "public", action: "DELETE", bucketKnob: "S3_PUBLIC_BUCKET", key: SENDFILE_PUBLIC_KEY, executor: "server", ttl: SENDFILE_SERVER_TTL },
114
+ { domain: "sendfile", subject: "public", action: "GET", bucketKnob: "S3_PUBLIC_BUCKET", key: SENDFILE_PUBLIC_KEY, executor: "client", ttl: "unsigned" },
115
+ { domain: "sendfile", subject: "private", action: "PUT", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: SENDFILE_PRIVATE_KEY, executor: "server", ttl: { defaultSec: 600 } },
116
+ { domain: "sendfile", subject: "private", action: "COPY", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: SENDFILE_PRIVATE_KEY, executor: "server", ttl: SENDFILE_SERVER_TTL, from: SENDFILE_STAGING },
117
+ { domain: "sendfile", subject: "private", action: "HEAD", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: SENDFILE_PRIVATE_KEY, executor: "server", ttl: SENDFILE_SERVER_TTL },
118
+ { domain: "sendfile", subject: "private", action: "DELETE", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: SENDFILE_PRIVATE_KEY, executor: "server", ttl: SENDFILE_SERVER_TTL },
119
+ { domain: "sendfile", subject: "private", action: "GET", bucketKnob: "SESSION_SNAPSHOT_BUCKET", key: SENDFILE_PRIVATE_KEY, executor: "client", ttl: { knob: "SEND_USER_FILE_URL_TTL" } },
120
+ { domain: "sendfile", subject: "staging", action: "PUT", bucketKnob: SENDFILE_STAGING.bucketKnob, key: SENDFILE_STAGING.key, executor: "sandbox", ttl: { defaultSec: 120 } },
121
+ { domain: "sendfile", subject: "staging", action: "HEAD", bucketKnob: SENDFILE_STAGING.bucketKnob, key: SENDFILE_STAGING.key, executor: "server", ttl: SENDFILE_SERVER_TTL },
122
+ { domain: "sendfile", subject: "staging", action: "DELETE", bucketKnob: SENDFILE_STAGING.bucketKnob, key: SENDFILE_STAGING.key, executor: "server", ttl: SENDFILE_SERVER_TTL },
123
+ { domain: "leader-diff", subject: "patch", action: "PUT", bucketKnob: "MINIO_BUCKET", key: LEADER_KEY, executor: "sandbox", ttl: LEADER_TTL },
124
+ { domain: "leader-diff", subject: "patch", action: "GET", bucketKnob: "MINIO_BUCKET", key: LEADER_KEY, executor: "server", ttl: LEADER_TTL },
125
+ ];
126
+ export function objectStoreOpOf(row) {
127
+ return `${row.domain}/${row.subject}:${row.action}`;
128
+ }
129
+ const ROWS_BY_OP = (() => {
130
+ const byOp = new Map();
131
+ for (const row of OBJECT_STORE_ACTIONS) {
132
+ const op = objectStoreOpOf(row);
133
+ if (byOp.has(op))
134
+ throw new Error(`object-store action table: two rows share the id ${op}`);
135
+ byOp.set(op, row);
136
+ }
137
+ return byOp;
138
+ })();
139
+ export function objectStoreActionOf(op) {
140
+ const row = ROWS_BY_OP.get(op);
141
+ if (row === undefined)
142
+ throw new Error(`object-store action table: no row ${JSON.stringify(op)}`);
143
+ return row;
144
+ }
145
+ export function objectStoreRowEngineSlot(row) {
146
+ const headSlot = (key) => {
147
+ const m = /^\{([A-Za-z]+)\}/.exec(key);
148
+ return m !== null && m[1] in OBJECT_KEY_KNOB_SLOTS ? m[1] : undefined;
149
+ };
150
+ const slot = headSlot(row.key);
151
+ if (slot === undefined)
152
+ return undefined;
153
+ return row.action === "COPY" && headSlot(row.from.key) === undefined ? undefined : slot;
154
+ }
155
+ export function objectKeyGlob(key, slots = {}) {
156
+ return key
157
+ .replace(/\{([A-Za-z]+)\}/g, (_, slot) => {
158
+ if (!(slot in OBJECT_KEY_KNOB_SLOTS))
159
+ throw new Error(`object key form: unknown slot {${slot}}`);
160
+ const name = slot;
161
+ return slots[name] ?? OBJECT_KEY_KNOB_SLOTS[name].unset;
162
+ })
163
+ .replace(/<([A-Za-z0-9]+)>/g, (_, segment) => {
164
+ if (!(segment in OBJECT_KEY_SEGMENTS))
165
+ throw new Error(`object key form: unknown segment <${segment}>`);
166
+ return "*";
167
+ });
168
+ }
3
169
  //# sourceMappingURL=object-store-buckets.js.map
@@ -97,7 +97,7 @@ export declare const FAIL_OPEN_TAGS: {
97
97
  };
98
98
  readonly "server.run-store.file-active-claims-unreadable": {
99
99
  readonly cls: "P-DEBT";
100
- readonly note: "`FileRunStore.hydrate()` 的第二处 `readdirSync(runs/active/)`(claim 平面 = 单活索引)失败,且 `RUN_STORE_STRICT_HYDRATE` 关(缺省)⇒ 服务照常起动、单活索引为**空**。放行的后果两条,都不报错:① 已有 run 行仍可读(`GET /v1/runs/:id` 照常答),但此后对这些会话的审批决定在请求里同步跑完、却找不到要更新的 run 行 —— run 行停在决前的 `suspended`;② 读单活索引的各处读到「没人占用」—— `getActiveTaskId` 恒答空,例如会话同步推送前的「会话有在飞 run」检查(与 `server.run-store.file-hydrate-unreadable` 同一句错话:「证不出有占用 ⇒ 没有占用」,只是换了一个盘面);新提交不读这张索引,claim 文件完好时仍按盘上的 claim 裁定,不受影响。同一条债的另一个盘面:缺省不拒启是刻意保留的行为,所以留作 P-DEBT —— error 级启动日志(`file_run_store_active_claims_unreadable`,带 `runs/active/` 绝对路径)早已在,本计数补的是遥测轴(此前 `runs/` 臂有计数、这一臂没有)。`RUN_STORE_STRICT_HYDRATE=on` 把这一格换成 fail-closed 启动门,本计数因此只在缺省 off 档的真放行时产生(拒启那一形不记)—— 读遥测时「计数为零」也可能是部署开了拒启门、根本起不来。";
100
+ readonly note: "`FileRunStore.hydrate()` 的第二处 `readdirSync(runs/active/)`(claim 平面 = 单活索引)失败,且 `RUN_STORE_STRICT_HYDRATE` 关(缺省)⇒ 服务照常起动、单活索引为**空**。放行的后果两条,都不报错:① 已有 run 行仍可读(`GET /v1/runs/:id` 照常答),但此后对这些会话的审批决定在请求里同步跑完、却找不到要更新的 run 行 —— run 行停在决前的 `suspended`;② 读单活索引的各处读到「没人占用」—— `getActiveTaskId` 恒答空,例如会话同步推送前的「会话有在飞 run」检查、会话头探针 `GET /v1/sessions/:id/head` 的 `activeTaskId`(这一档里答 `null`,而提交照旧按盘上的 claim 文件 409)(与 `server.run-store.file-hydrate-unreadable` 同一句错话:「证不出有占用 ⇒ 没有占用」,只是换了一个盘面);新提交不读这张索引,claim 文件完好时仍按盘上的 claim 裁定,不受影响。同一条债的另一个盘面:缺省不拒启是刻意保留的行为,所以留作 P-DEBT —— error 级启动日志(`file_run_store_active_claims_unreadable`,带 `runs/active/` 绝对路径)早已在,本计数补的是遥测轴(此前 `runs/` 臂有计数、这一臂没有)。`RUN_STORE_STRICT_HYDRATE=on` 把这一格换成 fail-closed 启动门,本计数因此只在缺省 off 档的真放行时产生(拒启那一形不记)—— 读遥测时「计数为零」也可能是部署开了拒启门、根本起不来。";
101
101
  };
102
102
  readonly "server.fork-routing.placed-probe-host-error": {
103
103
  readonly cls: "F";
@@ -183,17 +183,13 @@ export declare const FAIL_OPEN_TAGS: {
183
183
  readonly cls: "F";
184
184
  readonly note: "CC 规则导入票的**认领回滚**失败(认领之后的某一步没成 ⇒ 本该把认领放回去,而这次放回本身也抛了)。放行的最坏后果 = 这张票留在已认领态、属主这一轮不能重试 —— 恰好等于加认领回滚**之前**的行为,不是新损失;票随 TTL 自然消失,属主重走一次 prepare 即可拿新票(导入按 core 的设计幂等:同一条规则再兑付只是同一个 dot 的重放)。方向上没有任何权限被放宽(规则**没有**落地才走到这条臂),故 F 类;必须留痕,否则「票为什么突然不能用了」在遥测里没有任何痕迹。";
185
185
  };
186
- readonly "server.approvals.rule-suggestions-cell-unreadable": {
187
- readonly cls: "F";
188
- readonly note: "运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint.rule_suggestions` 这一格**不是合法 JSON 文本**(手改过的行 / 未来列语义漂了 / 回滚残留)。放行的最坏后果 = **这一行**的「不再询问」候选缺席(展示/分诊材料,永不参与 resume、也不是任何判据),队列其余部分照常;不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 cell 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空)。故 F 类,但必须留痕:静默吞掉之后「候选为什么消失了」在遥测里没有任何痕迹,而本键存在的全部理由就是「缺席 = 真的没有候选」。";
189
- };
190
186
  readonly "server.approvals.risk-descriptor-cell-unreadable": {
191
187
  readonly cls: "F";
192
- readonly note: "运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint.risk_descriptor` 这一格**不是合法 JSON 文本**(手改过的行 / 回滚残留 / 列语义漂;与同一 `rows.map` 里的 `rule_suggestions` 是同族坏法,两方言都是 TEXT 列)—— 或解得出却不是一只对象;`DB_BACKEND=local` 上同一读面读存储体里门上的 `gate.riskDescriptor`,在场却不是一只对象同样计在本 tag(两孪生同一只形读者 `checkpoint-store-face.ts` 的 `readRiskDescriptorBody`,修前 local 把原值原样上 wire)。放行的最坏后果 = **这一行**的分诊 descriptor 落 null:severity 折 0 排到有 descriptor 的行之后、披露位(`allowRuleShadowed`;7.117.0 前叫 `shadowedRule`)无可脱敏、读面派生的 `governanceForced` 徽章不亮 —— 三者都是**展示/分诊**,不是执法判据(门早已 park,真按 `shellGateDoctrine` 判的 `active-run-conflict.ts` 读的是 checkpoint blob 的 `get()`,不经本读面),且 `governanceForced` 的成文语义本就是「缺席 = 没有治理来源的**证据**」。不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 cell 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空),连同其余所有行一起消失。故 F 类;tag 与候选那格**分开计**,并计会让「哪一格在坏」在遥测里读不出来。";
188
+ readonly note: "运维待批队列(`GET /v1/approvals` / `/stream`;两孪生同一只投影 `checkpoint-store-face.ts` 的 `buildQueueActionFacts`)的某一行,停驻文档门上的风险描述(引擎派生 `checkpointIndexFacts` 那一格,只在审批门上)**在场却读不成一只对象**(手改 / 带外写者写下的文档)。7.152.0 起只有这一座:描述不再落列,队列行在读时从续跑执行的同一次整行解码取(此前 SQL 孪生读 `checkpoint.risk_descriptor` 列、列文本坏也计在本 tag;那一列随一次性迁移 M54 删)。放行的最坏后果 = **这一行**的分诊 descriptor 落 null:severity 折 0 排到有 descriptor 的行之后、披露位(`allowRuleShadowed`)无可脱敏、读面派生的 `governanceForced` 徽章不亮 —— 三者都是**展示/分诊**,不是执法判据(门早已 park,真按 `shellGateDoctrine` 判的 `active-run-conflict.ts` 读的是 `get()`,不经本读面),且 `governanceForced` 的成文语义本就是「缺席 = 没有治理来源的**证据**」。不放行的代价是一行坏描述打掉整个租户的队列。故 F 类。计数口径:SQL 孪生每份字节每进程一次(动作事实按字节记忆),local 每次列表一次。";
193
189
  };
194
190
  readonly "server.approvals.park-row-blob-unreadable": {
195
191
  readonly cls: "F";
196
- readonly note: "S-700(`stores-sql/checkpoint-store-sql.ts` 的 `readParkRowActionCell`):运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint` 列里寄存行的 **`pendingAction` 子树**(NP-3 / 7.100.0 起引擎内只取这一棵、整只快照不出库;只为 park 行事实 `requiresRealApproval` / `ruleOffersAbsence` / `mandated`(S-663 二段,core #1079)/ `mandate`(S-721)/ `origin`(S-755)而读 —— 事实位的真源是 `approval-card.ts` 的 `ParkRowFacts`)**在场却不是一只对象**(JSON `null` 字面 / 串 / 数 —— 手改 / 迁移脚本改过)。子树**缺席**(SQL NULL:成员不在,或整只文档不是对象 —— 后者 `get()` 照旧拒;MariaDB 文本承载上的非 JSON 字节同样答 SQL NULL)⇒ 事实缺席、不计数。放行的最坏后果 = **这一行**的 park 行事实(`ParkRowFacts` 各位)缺席(展示/分诊材料;core 定性 display metadata,resume 的带子读 gate 自己的位),队列其余部分照常 —— 而这一行本来就 resume 不了(`get()` 对同一格拒)。不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 blob 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空),与同一 `rows.map` 里 `rule_suggestions` / `risk_descriptor` 两格同族同判。故 F 类;tag 与那两格**分开计**(哪一格在坏要读得出来)。计数非零 = 这一行的 decide 同样读不动(`get()` 对同一格拒),去按 session 查那一行。 7.144.0 起同 tag 另有一座:停驻行的**整行读**(`readStoredRow`;按快照摘要记忆,未命中才读)—— 运维队列行的判决 `rowVerdict` 与技能卡两位、7.145.0 起还有收件箱 / 任务视图 `listByScope` 的行投影,同经这一只读法、同一失败方向(行级隔离):整行解不出 ⇒ 判官对读回的原样值作答(恒 `damaged`),行照列、带判决;体是对象但 core 摘要读不动(`{}` / 缺 `state` 等手改行)⇒ 判官对这只对象作答;两形都只丢摘要派生的位(队列行的技能卡两位 / 收件箱行的摘要键,收件箱行退回列组事实),逐次计、不进记忆,一行坏体在子树与整行两读上各计一次。修前收件箱对同一行整张拒(500 / 503)。 (`member=gate` 那第二座随 core 7.55.0 #1468 P1 阶段二退役:队列行的卡与到期分法改读 `approval_card` / `gate_kind` 两列 —— 写口与 M29 回填同一只派生落下的格 —— 本读面不再读 blob 的 `gate` 子树。)(S-2076 的 `readParkedSkillCardFacts` 两座已由上面那次 `projectStoredRow` 整行读取代,树上零命中。)";
192
+ readonly note: "运维待批队列(`GET /v1/approvals` / `/stream`)、收件箱 / 任务视图(`listByScope`)与按会话读口的某一行,停驻行的**整行读**(`stores-sql/checkpoint-store-sql.ts` 的 `readStoredRow`;队列行的全部动作事实 —— 工具名、绑定、入参、卡、描述、候选、bidi 位、park 行事实、`checkpointId`、技能卡两位、判决 —— 都出自这一次解码,两孪生同一只投影 `buildQueueActionFacts`)读不动:字节解不出 ⇒ 判官对读回的原样值作答(恒 `damaged`);体是对象但 core 摘要读不动(`{}` / 缺 `state` 等手改行)或 core 的投影自己抛 ⇒ 判官对这只对象作答。行照列、带判决,动作事实 `null` / 缺席(与 local 孪生同形),逐次计、不进记忆。放行的最坏后果 = **这一行**少了动作事实(这样的行续跑同样读不动它 —— `get()` 对同一份字节拒),队列其余部分照常;不放行的代价是一行坏字节打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远停在旧帧)。故 F 类。7.152.0 起不再有「`pendingAction` 子树」那一座(引擎内的成员提取退役,同一份文档只有一只 parser)。计数非零 = 这一行的 decide 同样读不动,去按 session 查那一行。";
197
193
  };
198
194
  readonly "server.approvals.queue-row-agent-unreadable": {
199
195
  readonly cls: "F";
@@ -293,7 +289,7 @@ export declare const FAIL_OPEN_TAGS: {
293
289
  };
294
290
  readonly "server.approvals.active-run-conflict-material-unavailable": {
295
291
  readonly cls: "F";
296
- readonly note: "A-057.47:`buildActiveRunConflict` 的材料装配段(getRun / turnActivity / peekPendingScope / findPendingTokenBySession / checkpoint `get`)任一失败 ⇒ 整段退化成裸 409(只剩 error + errorCode + activeTaskId),`activeTaskStatus` / `msSinceLastActivity` / `pendingGate`(kind·decidePath·governanceForced·checkpointId)全部蒸发。放行的最坏后果 = **展示/分诊**面缺料:壳画不出「这条 run 卡在哪道门、去哪儿决」,人退回 `POST /v1/runs/{activeTaskId}/cancel` 这条保底真路 —— 不参与任何门/CAS/resume 判定(执法面读的是 checkpoint blob 的 `get()`,不经本材料;与 census 第 21 行同一条判据),故 F 类。方向刻意不改:本材料是 best-effort 增强,让它抛会把一次 store 抖动变成整个 409 路径的 500(顶注第 11 行逐字成文「store 面任何失败都不得挡 409 本体」)。必须留痕的理由:本文件零 logger 席、pool 层无 per-query 错误日志、调用侧(tasks.ts / runs.ts / server.ts 五处)因本函数恒不 reject 结构上拿不到信号 ⇒ 「approval 出路材料系统性丢失」此前在遥测里与「一切正常」同形;滚动升级期 `checkpoint-store-sql.ts` 的 version-too-new throw 与 strict parseJson 也一并被吞在这里。";
292
+ readonly note: "A-057.47:409 `conflict.session_active_run` 的材料读失败,分两层(7.152.0 起):① 持有者那一行读不出(`refusalOccupantOf` 的 getRun —— 提交 / 续跑面的 `buildActiveRunConflict`、删除口、run 外回退口三处同调)⇒ 体只剩 error + errorCode + activeTaskId,`activeTaskStatus` / `msSinceLastActivity` / `pendingGate` 不在;② 持有者行读到了而出路材料读不出(turnActivity / peekPendingScope / findPendingTokenBySession / checkpoint `get`)⇒ 占用两键照留,只少 `msSinceLastActivity` 或 `pendingGate`(kind·decidePath·governanceForced·checkpointId)。放行的最坏后果 = **展示/分诊**面缺料:壳画不出「这条 run 卡在哪道门、去哪儿决」,人退回 `POST /v1/runs/{activeTaskId}/cancel` 这条保底真路 —— 不参与任何门/CAS/resume 判定(执法面读的是 checkpoint blob 的 `get()`,不经本材料;与 census 第 21 行同一条判据),故 F 类。方向刻意不改:本材料是 best-effort 增强,让它抛会把一次 store 抖动变成整个 409 路径的 500(顶注第 11 行逐字成文「store 面任何失败都不得挡 409 本体」)。必须留痕的理由:本文件零 logger 席、pool 层无 per-query 错误日志、调用侧(tasks.ts / runs.ts / server.ts 五处)因本函数恒不 reject 结构上拿不到信号 ⇒ 「approval 出路材料系统性丢失」此前在遥测里与「一切正常」同形;滚动升级期 `checkpoint-store-sql.ts` 的 version-too-new throw 与 strict parseJson 也一并被吞在这里。";
297
293
  };
298
294
  readonly "server.engine-notice.durable-append-failed": {
299
295
  readonly cls: "F";
@@ -347,10 +343,6 @@ export declare const FAIL_OPEN_TAGS: {
347
343
  readonly cls: "P-DEBT";
348
344
  readonly note: "#296(A-052.2,clay 裁定 C-R21):`REMOTE_EXEC=ssh` 且**两只主机密钥旋钮都缺席**(`SSH_HOST_FINGERPRINT` / `SSH_KNOWN_HOSTS`)⇒ 本次连接接受**任何**主机密钥,等价 `ssh -o StrictHostKeyChecking=no`。放行的最坏后果:一次中间人拿到这条会话的**全部命令、全部产物、以及 agent 在那台机器上的全部动作**(私钥仍在控制面手里、拿不走,design/61 §5 #2)。⇒ 保护型欠账,不是体验回退。**方向是裁定的、不是遗漏**:本 lane 的既有部署形是「AI 编排批量部署到一批 SSH 可达的机器」,那些机器的指纹通常不在任何 known_hosts 里,默认拒连 = 一次静默的可用性断裂;C-R21 裁「在场即严格,缺席即响亮」。补偿三件:①**每连接**一条 `ssh_host_key_unverified` warn(不是每进程一次 —— 一条长期裸连的 lane 必须在每条连接上都看得见);②本计数(遥测里「有多少条连接是裸连」是一个可观测的数,曲线应当只降不升);③两旋钮任一在场即**严格校验、不符拒连**(拒因带两半指纹 + `ssh-keyscan` 指路)。终局 = 部署把旋钮配上(那时本计数归零);旋钮不配而想收紧的部署级开关(「无旋钮即拒启」)是下一件,不在 C-R21 射程。";
349
345
  };
350
- readonly "server.approval.park-redemption-cap-refused": {
351
- readonly cls: "F";
352
- readonly note: "#329 / #343(黑板 [5100] Q3):停驻行迟到决议的**受理回执表**(本副本对「200 丢包后重试」的幂等承诺 + 重叠请求的单飞句柄;键 = 行的键 askId,只在一次赎回真开飞时开格;容量帽只数受理之后留下的回执,在飞的单飞句柄永不被逐)**拒留一张回执**。放行的最坏后果 = 这**一次**受理(照旧生效)没有本副本的回执可依:200 丢包后的重试会再进一次赎回腿、拿到那条腿的 409(那张 checkpoint 已被消费)而不是幂等 200 回放(终局恒由赎回腿的 gate CAS 定,不会错兑也不会双兑);迟到受理本身、`GET /v1/approvals` 列表与 `/v1/approvals/:sessionId/decide` 一个字节不动 ⇒ F 类。为什么方向是「拒新」而不是 FIFO 挤最旧:那个形让**甲的用量决定乙的可用性**(已鉴权租户量产受理即可把别家回执挤出,merge-rescan 744 confirmed 的同一病形)。必须留痕:「表被别人打满」与「这一次本来就没有回执」在 wire 上同形。detail 带 owner(判「压力来自谁」的第一手线索)。臂只有一条:全局回执帽满、本 principal 未到子帽、表里没有过期回执可收 ⇒ 拒留(detail 带 owner)。本 principal 到了子帽的常态臂逐自己最旧的一张回执(量产者自伤,设计内有界表纪律),不走本 tag;在飞的单飞句柄不占帽、永不被逐。";
353
- };
354
346
  readonly "server.approval.parked-decision-not-recorded": {
355
347
  readonly cls: "F";
356
348
  readonly note: "S-1054 α(`tool-approval.ts` 的 `recordParkedOutcome`,停驻赎回那一飞的落行步):停驻门**已经受理**了这次决定(续跑已开始),而把它的记录(决议向 · 署名 · 理由 · 回决幂等键 · 出处)落到仍 `PARKED` 的问行上没成 —— 店错 / 超时 / 行出了门判过的属主域 / 这把键已被同 task 另一只问占着(detail 带 `reason`)。放行的最坏后果 = 这一问在耐久决断口上的**同键回放**读不到这把键:同键重发得到 `409 conflict.ask_decided`(回显门上站着的那次决定,决议向 / 时刻 / 理由取自门,无署名),而不是 200 回放;审计面少一份署名。决定本身零影响(终局恒在停驻门上,门已决);不改判、不重赎、不双兑。计数非零 = 问账店在受理之后写不动了,运维要去看店。";
@@ -359,6 +351,10 @@ export declare const FAIL_OPEN_TAGS: {
359
351
  readonly cls: "F";
360
352
  readonly note: "S-02 codex R1-[medium](验真后修):decide 的 409 `approval_stale` 臂对**调用方回显的旧 token** 做归属判定(`cs.get(binding.checkpointToken)`),那次读**抛了**(store 抖动 / 坏 checkpoint 行 / 行恰被清理)。修前这里是静默 `catch(()=>null)`,「读不出」被折成「确认不在库」——叠上 S-02 的 404 收口后,一次 store 抖动就会把合法旧 token 的 409+terminal 谎报成 404「没有这条审批」。修后:unreadable ⇒ **保持 409**(`terminal` 不披露——证不出归属就不说,与 2026-07-26 纪律同向;404 折叠只在读成功且未命中时走,探测方无法自控 store 故障 ⇒ 谕示封闭不破)。放行的最坏后果 = 该次拒体 `terminal` 诚实缺席(`currentPending` 由它自己的读口与属主复核另判,不受本臂牵连),壳退回重拉列表,judgment 面 fail-safe,故 F 类。留痕理由:这次读是 terminal 披露与 404 折叠两个判定的输入,长期抖动必须在遥测显形。";
361
353
  };
354
+ readonly "server.resume.cancel-answer-row-unreadable": {
355
+ readonly cls: "F";
356
+ readonly note: "续跑腿(`http/resume-legs.ts` 的 `landedTerminalRow`)两只本腿铸取消终局的取消臂(`checkpoint.resume_aborted` 臂 / 交给引擎之后抛出的取消臂):驱行终局之后读回那一行,200 体的词 / 码 / 句读行上落下的那一份(run 店终局写先到者得,先到的可以是收割 / 判死),那一读抛。放行 = 体读本腿铸的那一份取消终局(读回之前的形);最坏后果 = 先到者不是本腿时体上的码 / 句与 `GET /v1/runs/:id` 不同 —— 行、账本、读面一个字节不受它管,门 / 裁决不读这只体 ⇒ F 类。detail `task=<taskId> arm=<resume-aborted|thrown-cancel> err=<原句>`;计数 = 多少次答复没读到行。";
357
+ };
362
358
  readonly "server.resume.reopen-confirm-unreadable": {
363
359
  readonly cls: "F";
364
360
  readonly note: "S-447(#60 M2 自查项,`http/resume-legs.ts` 的 `confirmCheckpointReopened`):续跑腿交回一条没 park 的失败结果后(7.129.0 起每一条都问,不再只在三个重开码上问)按 **token** 复核「这张 checkpoint 是不是又 pending 了」,这一读抛(库拖/版本太新/店不可达)。**方向本来就是 fail-closed**:读不出 ⇒ `return true` ⇒ 「不写任何终局、重新 park」(`:1206-1212` 头注已把取舍与有界代价写死:错 park 由 `reapSuspended` 兑,错终局会孤儿化一张活 park 到 TTL)—— 所以这条腿不是 P 类,缺的只是**留痕**。放行的最坏后果 = 多一次多余的 re-park(一张已经被决掉的卡重新挂到 reaper 窗里),人面上是「这条续跑没动」而不是谁被放行了。必须登记的理由是 **uniformity**:同文件三只同形读(`:249` `server.approvals.stale-echoed-token-unreadable` · `:288` `server.approvals.stale-current-pending-unreadable` · 本腿)中只有它是黑的,于是「店一直读不出所以每条续跑都在白白 re-park」与「一切正常」在遥测上同形。计数非零 = 这台机器的 checkpoint 店在拖,运维要去看库。";
@@ -569,6 +565,10 @@ export declare const FAIL_OPEN_TAGS: {
569
565
  readonly cls: "F";
570
566
  readonly note: "S-1195(7.119.0;`plugins/snapshot-bucket-presence.ts` 的 `ensureSnapshotBucket`,boot 期核一次快照桶 `SESSION_SNAPSHOT_BUCKET`;S-2021〔7.136.0〕起同一只探针、同一条规则、同一个 tag 也核 k8s 车道的工作区快照桶 `WORKSPACE_SNAPSHOT_BUCKET`——detail 里的 `bucket=` 就是被核的那只桶名;detail = `bucket=… endpoint=<buildDisplaySafeUrl 的显示形> <HTTP 状态 | request failed: 错类>`):presigned 列举对 `MINIO_ENDPOINT` **连不上 / 403 / 5xx / 没有 NoSuchBucket 的 404**,或探针到窗尾一次都没答过(detail 写 `probe still pending when the window ended`)⇒ **证明不了桶缺**,不拒启、照常起服(只有 404 + `NoSuchBucket` 才是「缺」,那一形窗内重试、到窗拒启,不走本 tag)。三问:①错误落到哪 —— 本 tag 的计数 / 探针行 / 记录器的一次性 warn,detail 带端点显示形与状态或错类;②谁受害 —— 桶其实不存在、或凭据不能列举的部署:之后每一次快照 offload 写与 SendUserFile 私有 presigned 请求会答 404 / 403,孤儿 sweep 每分钟一条失败,运维读到的是一串失败请求而不是「桶没建」(与 7.118.x 的既有形状同形,不是新损失);工作区快照桶则是每条 run 读 `latest` 得 404/403——404 + NoSuchBucket 在运行期由 `workspace_snapshot_bucket_missing` 响亮拒绝,403/5xx 走既有的非 404 读失败臂(同样响亮);③缺席倒向哪边 —— 倒向**放行起服**:没有证据既不拒启、也不伪造「桶在场」或「桶缺」,不是门 / 权限 / 凭证。最坏后果 = 缺桶的部署晚一步才暴露;不放行的代价是对象存储一次抖动 / 一次 403 就让整只服务起不来。计数非零 = 这台部署启动时没能确认快照桶,按 detail 的端点与状态去核对网络 / 凭据 / 桶。";
571
567
  };
568
+ readonly "server.session-blob-namespace.claim-unproven": {
569
+ readonly cls: "F";
570
+ readonly note: "`plugins/session-blob-namespace.ts` 的 `establish`(开店时对会话 blob 命名空间认领一次:`plugins/store-backend.ts` `openStoreBackendWithFallback` 在 SQL 店开好之后调,一次尝试、不在 `STORE_LOCK_WAIT_MS` 窗里重试,每个请求的上界与快照桶探针同一只常量 `SNAPSHOT_BUCKET_PROBE_TIMEOUT_MS`;detail = `bucket=… prefix=<SESSION_SNAPSHOT_PREFIX 的显示形 | unset> endpoint=<buildDisplaySafeUrl 的显示形> <claim read answered HTTP <状态> | claim write answered HTTP <状态> | the claim just written does not read back | claim request failed: 错类>`):认领物件 `{SESSION_SNAPSHOT_PREFIX}blob-namespace-claim` **读不动 / 写不进 / 连不上 / 写了读不回** ⇒ 证明不了这只命名空间是不是本库的,不拒启、照常起服(只有读到别的库的认领才是「不是」,那一形开店即拒、不走本 tag)。三问:①错误落到哪 —— 本 tag 的计数 / 探针行 / 记录器的一次性 warn;数据轴不随之放开:之后每一次删除(附件孤儿清扫、附件释放、文件历史清扫、退役 blob 清扫)各自重读认领,读不成本库的就拒删,抛出点名桶、前缀旋钮与该授权限的拒句(响亮;那是 fail-closed,不计本 tag);②谁受害 —— 引擎的键缺认领物件 GetObject / PutObject 权限的最小权限部署,或起服那一刻对象存储不通的部署:附件与文件历史的字节不再被回收(桶只涨不减),直到权限补齐或存储答复 —— 恢复后的第一次删除当场认领(缺 ⇒ create-only 写、回读相符)再删,读到别的库的认领 ⇒ 拒删、不改写;③缺席倒向哪边 —— 倒向**放行起服**:没有证据既不拒启,也不当作「是本库的」去删任何字节,不是门 / 权限 / 凭证。最坏后果 = 回收停摆到权限补齐(存储成本,不是数据丢失);不放行的代价是对象存储一次抖动 / 一条缺的权限就让整只服务起不来。计数非零 = 这台部署启动时没能确认命名空间的归属,按 detail 的端点与原因去核对网络 / 凭据 / 认领物件的权限。";
571
+ };
572
572
  readonly "server.fleet.serving-lease-unconfirmed": {
573
573
  readonly cls: "R";
574
574
  readonly ruling: "C-R296";
@@ -611,7 +611,11 @@ export declare const FAIL_OPEN_TAGS: {
611
611
  };
612
612
  readonly "server.sandbox-egress.policy-gap": {
613
613
  readonly cls: "P-DEBT";
614
- readonly note: "k8s 车道沙箱出网的起服自检(`plugins/remote-env-k8s.ts` `checkSandboxEgressPolicy` 读节点表与沙箱 ns 的 NetworkPolicy,判法 `sandbox-egress-policy.ts` `sandboxEgressGaps`;起服一次、不挡起服)读出一个缺口 —— 某节点的 InternalIP / ExternalIP 落在一条放行 ipBlock 内(`kind=node_address_open`)、没有策略以 Egress 选中沙箱 pod(`kind=policy_absent`)、pod 保留 IPv6 而策略层担保不了 v6(`kind=ipv6_enabled`)、节点表或策略表读不到(`kind=unreadable what=nodes|networkpolicies`)⇒ 车道**照常起**,每个缺口一行 `sandbox_egress_policy_gap`(带后果句与去哪改)。归 P 类:出网策略是保护面,缺口意味着沙箱里的代码可能够到节点上的服务;归 DEBT 的理由:修法都在集群配置里(节点地址点名、kubelet 放行 v6 sysctl、CNI 的 v6 执行、RBAC),本服务改不了,而拒起车道会让缺省单节点装法(恒有 `ipv6_enabled`)升级即停摆沙箱执行 —— 车道自己的隔离(VM 边界、零 SA token)仍在。放行的最坏后果 = 读出缺口的那一面照旧可达,直到运维按行里的后果句改配置。计数非零 = 这台部署的沙箱出网面有读得出的缺口。读不出的面(宿主 DNAT 发布端口、「pod 所在节点恒放行」的实现差异、CNI 根本不执行策略)不在本 tag 的射程里。";
614
+ readonly note: "k8s 车道沙箱出网的起服自检(`plugins/remote-env-k8s.ts` `checkSandboxEgressPolicy` 读节点表与沙箱 ns 的 NetworkPolicy,判法 `sandbox-egress-policy.ts` `sandboxEgressGaps`;起服一次、不挡起服)读出一个缺口 —— 某节点的 InternalIP / ExternalIP 落在一条放行 ipBlock 内(`kind=node_address_open`)、没有策略以 Egress 选中沙箱 pod(`kind=policy_absent`)、pod 保留 IPv6 而策略层担保不了 v6(`kind=ipv6_enabled`)、节点表或策略表读不到(`kind=unreadable what=nodes|networkpolicies`:RBAC 缺 / API 不可达 / 答体不成形;**集群 API 凭据缺不在其内** —— 凭据缺是起服拒 `config.k8s_api_credentials_missing`,自检不发、不记入本 tag,这一臂已退役)⇒ 车道**照常起**,每个缺口一行 `sandbox_egress_policy_gap`(带后果句与去哪改)。归 P 类:出网策略是保护面,缺口意味着沙箱里的代码可能够到节点上的服务;归 DEBT 的理由:修法都在集群配置里(节点地址点名、kubelet 放行 v6 sysctl、CNI 的 v6 执行、RBAC),本服务改不了,而拒起车道会让缺省单节点装法(恒有 `ipv6_enabled`)升级即停摆沙箱执行 —— 车道自己的隔离(VM 边界、零 SA token)仍在。放行的最坏后果 = 读出缺口的那一面照旧可达,直到运维按行里的后果句改配置。计数非零 = 这台部署的沙箱出网面有读得出的缺口。读不出的面(宿主 DNAT 发布端口、「pod 所在节点恒放行」的实现差异、CNI 根本不执行策略)不在本 tag 的射程里。";
615
+ };
616
+ readonly "server.sandbox-credentials.probe-unanswered": {
617
+ readonly cls: "F";
618
+ readonly note: "k8s 车道每条 run 铸环境之前读一次集群 API 凭据(`boot/execution-env.ts` `createK8sRunEnvFactory` ← `plugins/remote-env-k8s.ts` `apiCredentialReading`:判官说缺 ⇒ 拒;一次 SelfSubjectAccessReview 答 401 ⇒ 拒;答 2xx ⇒ 放行),而这一次探问**没有证出结论**(HTTP 403 / 5xx / 其余非 2xx 非 401、请求抛 / 超时;detail = `namespace=<ns> HTTP <状态> | <错误句>`)⇒ 这条 run 的环境照铸,凭据到底行不行由车道自己的连接答(pod 创建被 401 / 403 拒 ⇒ 响亮的 `shell_unavailable`、瞬时的 API 抖动在车道自己的重试界内重来)。只有正面证据才拒 —— 为一次没答的探问拒 run,会把每次 API 抖动变成失败的 run,把没给已认证调用方留 SSAR 权限的集群变成永远起不了 run。最坏后果 = 凭据真已失效而探问恰好没答的那条 run,落回修前的形(每条 Bash `shell_unavailable`、run `completed`)—— 可用性 / 可见性,不是门 / 凭据的放宽(没有沙箱、没有执行、没有凭据被多给一份)。归 F。计数持续非零 = 这台部署的服务账号问不了 SelfSubjectAccessReview 或 API 常不可达,按 detail 核。";
615
619
  };
616
620
  readonly "server.fleet.announce-reply-unreadable": {
617
621
  readonly cls: "P-DEBT";
@@ -645,7 +649,7 @@ export declare const FAIL_OPEN_TAGS: {
645
649
  };
646
650
  readonly "server.store-durability.evidence-unreadable": {
647
651
  readonly cls: "F";
648
- readonly note: "店的持久性起服取证(`store-posture.ts` `captureStoreEvidence`,起服第 2 段段首一次):`/proc/self/mountinfo` 读不出(`why=mountinfo_unreadable err=<码>`)/ 有读不懂的行(`why=mountinfo_malformed lines=<n>`)/ 一根的路径展不平成物理路径(`why=path_unresolvable err=<码> path=<路径>`)/ 挂载表读得出、却找不到走那条路径看见的那一只挂载(`why=mount_unresolved path=<路径>`:空表、同父同点的影子挂载)⇒ 那几根(读不出挂载表时是三根全部)判 `unknown`。只影响自报:能力位 `store.durability`、`/health.store.durability`、诊断 `storeDurability.roots` 如实说 `unknown`,起服布线审计对 `unknown` 只 warn、不拒启。放行的最坏后果 = 一只真落在易失介质(容器可写层 / emptyDir)上的 local 数据根因证据读不到而报 `unknown`、照常起服 —— 与本版之前「按后端种类恒报持久」同向且更诚实,不开门、不碰凭据。计数非零 = 本进程读不到 / 读不懂自己的挂载表(受限 procfs、挂载形不常见)或路径上有权限竞态。";
652
+ readonly note: "店的持久性起服取证(`store-posture.ts` `captureStoreEvidence`,起服第 2 段段首一次):`/proc/self/mountinfo` 读不出(`why=mountinfo_unreadable err=<码>`)/ 有读不懂的行(`why=mountinfo_malformed lines=<n>`)/ 一根的路径展不平成物理路径(`why=path_unresolvable err=<码> path=<路径>`)/ 挂载表读得出、却找不到走那条路径看见的那一只挂载(`why=mount_unresolved path=<路径>`:空表、同父同点的影子挂载)⇒ 那几根(读不出挂载表时是三根全部)判 `unknown`。只影响自报:能力位 `store.durability`、`/health.store.durability`、诊断 `storeDurability.roots` 如实说 `unknown`,起服布线审计对 `unknown` 只 warn、不拒启。放行的最坏后果 = 一只真落在易失介质(容器可写层 / emptyDir)上的 local 数据根因证据读不到而报 `unknown`、照常起服 —— 与本版之前「按后端种类恒报持久」同向且更诚实,不开门、不碰凭据。计数非零 = 本进程读不到 / 读不懂自己的挂载表(受限 procfs、挂载形不常见)或路径上有读不出的段(没有搜索权限 / 链接成环 —— 规范形读不出即抛,不当成「还不存在」)/ 权限竞态。";
649
653
  };
650
654
  readonly "server.remote-write.staging-dir-left": {
651
655
  readonly cls: "F";
@@ -653,11 +657,11 @@ export declare const FAIL_OPEN_TAGS: {
653
657
  };
654
658
  readonly "server.resume-anchor.capture-failed": {
655
659
  readonly cls: "F";
656
- readonly note: "回退锚(`resumeAt` 的提示词 / 助手文本手柄)写入失败 —— 四条腿同一只写法 `runs.ts` 的 `settleResumeAnchor`:流式腿(`POST /v1/tasks/stream`,done 帧之前 / 断连收尾时 await)、同步腿(非流式 `POST /v1/tasks` 的 plain 形,200 应答之前 await)、后台腿(`POST /v1/runs`)、续跑腿。锚店写抛(库抖 / 表缺 / 盘满),或单行店操作期限(`BASELINE_IO_DEADLINE_MS`,2 s;与项目指令基线读写同一只数、同一只 `withinIoDeadline`)内没落定(锚店挂住:锚店的写口自己不带期限)⇒ 这一次提示词(或这一轮助手文本)此刻没有回退手柄,run 照常收尾、终帧照发、不改任何终局;到期只放手不取消,那次写照常在飞、迟到落定的锚照样可用(迟到的失败被吞,不重复计数)。放行的最坏后果 = 用户拿这次 run 的 taskId 去 `resumeAt` 得 404 `resume_at.unknown_event`、会话视图里那条用户消息行不带 `taskId` 手柄(用户面的读数只有这一处真源,本臂不另铸第二份);不是门、不是凭据。不放行(抛)的代价是让一次锚写失败把整条已经跑完的 run 判成失败。计数持续非零 = 锚店写不进(去看库)。计数里 `reason=timeout` 占多数 = 锚店慢到秒级(去看库的锁 / 连接池)。detail = `leg=<stream|sync|bg|resume> kind=<prompt|turn> reason=error error=<写口的错误句>` 或 `… reason=timeout boundMs=<期限>`。";
660
+ readonly note: "回退锚(`resumeAt` 的提示词 / 助手文本手柄)写入失败 —— 四条腿同一只写法 `runs.ts` 的 `settleResumeAnchor`,经同一只 `TurnAnchorCapture` 在决定这只锚的那一帧到手时 await(流式腿 `POST /v1/tasks/stream`、同步腿非流式 `POST /v1/tasks` 的 plain 形、后台腿 `POST /v1/runs`、续跑腿;提示锚在开场提示的提交上,早于终帧;要关窗校正的那一形同一把键写两次,后一笔等前一笔落定再发 —— 提示锚至多两个期限;后台 / 续跑腿另有每个可锚的助手文本轮各一个)。锚店写抛(库抖 / 表缺 / 盘满),或单行店操作期限(`BASELINE_IO_DEADLINE_MS`,2 s;与项目指令基线读写同一只数、同一只 `withinIoDeadline`)内没落定(锚店挂住:锚店的写口自己不带期限)⇒ 这一次提示词(或这一轮助手文本)此刻没有回退手柄,run 照常收尾、终帧照发、不改任何终局;到期只放手不取消,那次写照常在飞、迟到落定的锚照样可用(迟到的失败被吞,不重复计数)。放行的最坏后果 = 用户拿这次 run 的 taskId 去 `resumeAt` 得 404 `resume_at.unknown_event`、会话视图里那条用户消息行不带 `taskId` 手柄(用户面的读数只有这一处真源,本臂不另铸第二份);不是门、不是凭据。不放行(抛)的代价是让一次锚写失败把整条已经跑完的 run 判成失败。计数持续非零 = 锚店写不进(去看库)。计数里 `reason=timeout` 占多数 = 锚店慢到秒级(去看库的锁 / 连接池)。detail = `leg=<stream|sync|bg|resume> kind=<prompt|turn> reason=error error=<写口的错误句>` 或 `… reason=timeout boundMs=<期限>`。";
657
661
  };
658
662
  readonly "server.resume-anchor.cause-read-failed": {
659
663
  readonly cls: "F";
660
- readonly note: "未知回退手柄的 404 成因半句(`history-anchor.ts` 的唯一组句器;提交体 `resumeAt` / `rewindFilesTo` 与 run 外回退口 `to` 三处同调):锚店里没有这只手柄 ⇒ 经属主存取器读一次 run 行(嵌套可选读,看不见 ≡ 没有)、同会话 ⇒ 按这条提问自己的属主键再问一次锚店,只为选句(调用方看得见的本会话提问、它自己也没落锚 ⇒ 「没有锚的提问」并点名带附件不落锚那一类;否则只说没有锚)。这两读任一抛(库抖 / 表缺)⇒ 404 的码与状态照旧,句子退回只说没有锚。放行的最坏后果 = 一条真实存在、没有锚的提问,其 404 少了那半句说明(调用方可能当成手柄写错);不影响任何判定、不放行任何请求。";
664
+ readonly note: "未知回退手柄的 404 成因半句(`history-anchor.ts` 的唯一组句器;提交体 `resumeAt` / `rewindFilesTo` 与 run 外回退口 `to` 三处同调):锚店里没有这只手柄 ⇒ 经属主存取器读一次 run 行(嵌套可选读,看不见 ≡ 没有)、同会话 ⇒ 按这条提问自己的属主键再问一次锚店,只为选句(调用方看得见的本会话提问、它自己也没落锚 ⇒ 「没有锚的提问」,只陈述这一事实、不点名成因;否则只说没有锚)。这两读任一抛(库抖 / 表缺)⇒ 404 的码与状态照旧,句子退回只说没有锚。放行的最坏后果 = 一条真实存在、没有锚的提问,其 404 少了那半句说明(调用方可能当成手柄写错);不影响任何判定、不放行任何请求。";
661
665
  };
662
666
  readonly "server.remote-write.stage-seal-fallback": {
663
667
  readonly cls: "F";
@@ -78,7 +78,7 @@ export const FAIL_OPEN_TAGS = {
78
78
  },
79
79
  "server.run-store.file-active-claims-unreadable": {
80
80
  cls: "P-DEBT",
81
- note: "`FileRunStore.hydrate()` 的第二处 `readdirSync(runs/active/)`(claim 平面 = 单活索引)失败,且 `RUN_STORE_STRICT_HYDRATE` 关(缺省)⇒ 服务照常起动、单活索引为**空**。放行的后果两条,都不报错:① 已有 run 行仍可读(`GET /v1/runs/:id` 照常答),但此后对这些会话的审批决定在请求里同步跑完、却找不到要更新的 run 行 —— run 行停在决前的 `suspended`;② 读单活索引的各处读到「没人占用」—— `getActiveTaskId` 恒答空,例如会话同步推送前的「会话有在飞 run」检查(与 `server.run-store.file-hydrate-unreadable` 同一句错话:「证不出有占用 ⇒ 没有占用」,只是换了一个盘面);新提交不读这张索引,claim 文件完好时仍按盘上的 claim 裁定,不受影响。同一条债的另一个盘面:缺省不拒启是刻意保留的行为,所以留作 P-DEBT —— error 级启动日志(`file_run_store_active_claims_unreadable`,带 `runs/active/` 绝对路径)早已在,本计数补的是遥测轴(此前 `runs/` 臂有计数、这一臂没有)。`RUN_STORE_STRICT_HYDRATE=on` 把这一格换成 fail-closed 启动门,本计数因此只在缺省 off 档的真放行时产生(拒启那一形不记)—— 读遥测时「计数为零」也可能是部署开了拒启门、根本起不来。",
81
+ note: "`FileRunStore.hydrate()` 的第二处 `readdirSync(runs/active/)`(claim 平面 = 单活索引)失败,且 `RUN_STORE_STRICT_HYDRATE` 关(缺省)⇒ 服务照常起动、单活索引为**空**。放行的后果两条,都不报错:① 已有 run 行仍可读(`GET /v1/runs/:id` 照常答),但此后对这些会话的审批决定在请求里同步跑完、却找不到要更新的 run 行 —— run 行停在决前的 `suspended`;② 读单活索引的各处读到「没人占用」—— `getActiveTaskId` 恒答空,例如会话同步推送前的「会话有在飞 run」检查、会话头探针 `GET /v1/sessions/:id/head` 的 `activeTaskId`(这一档里答 `null`,而提交照旧按盘上的 claim 文件 409)(与 `server.run-store.file-hydrate-unreadable` 同一句错话:「证不出有占用 ⇒ 没有占用」,只是换了一个盘面);新提交不读这张索引,claim 文件完好时仍按盘上的 claim 裁定,不受影响。同一条债的另一个盘面:缺省不拒启是刻意保留的行为,所以留作 P-DEBT —— error 级启动日志(`file_run_store_active_claims_unreadable`,带 `runs/active/` 绝对路径)早已在,本计数补的是遥测轴(此前 `runs/` 臂有计数、这一臂没有)。`RUN_STORE_STRICT_HYDRATE=on` 把这一格换成 fail-closed 启动门,本计数因此只在缺省 off 档的真放行时产生(拒启那一形不记)—— 读遥测时「计数为零」也可能是部署开了拒启门、根本起不来。",
82
82
  },
83
83
  "server.fork-routing.placed-probe-host-error": {
84
84
  cls: "F",
@@ -164,17 +164,13 @@ export const FAIL_OPEN_TAGS = {
164
164
  cls: "F",
165
165
  note: "CC 规则导入票的**认领回滚**失败(认领之后的某一步没成 ⇒ 本该把认领放回去,而这次放回本身也抛了)。放行的最坏后果 = 这张票留在已认领态、属主这一轮不能重试 —— 恰好等于加认领回滚**之前**的行为,不是新损失;票随 TTL 自然消失,属主重走一次 prepare 即可拿新票(导入按 core 的设计幂等:同一条规则再兑付只是同一个 dot 的重放)。方向上没有任何权限被放宽(规则**没有**落地才走到这条臂),故 F 类;必须留痕,否则「票为什么突然不能用了」在遥测里没有任何痕迹。",
166
166
  },
167
- "server.approvals.rule-suggestions-cell-unreadable": {
168
- cls: "F",
169
- note: "运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint.rule_suggestions` 这一格**不是合法 JSON 文本**(手改过的行 / 未来列语义漂了 / 回滚残留)。放行的最坏后果 = **这一行**的「不再询问」候选缺席(展示/分诊材料,永不参与 resume、也不是任何判据),队列其余部分照常;不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 cell 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空)。故 F 类,但必须留痕:静默吞掉之后「候选为什么消失了」在遥测里没有任何痕迹,而本键存在的全部理由就是「缺席 = 真的没有候选」。",
170
- },
171
167
  "server.approvals.risk-descriptor-cell-unreadable": {
172
168
  cls: "F",
173
- note: "运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint.risk_descriptor` 这一格**不是合法 JSON 文本**(手改过的行 / 回滚残留 / 列语义漂;与同一 `rows.map` 里的 `rule_suggestions` 是同族坏法,两方言都是 TEXT 列)—— 或解得出却不是一只对象;`DB_BACKEND=local` 上同一读面读存储体里门上的 `gate.riskDescriptor`,在场却不是一只对象同样计在本 tag(两孪生同一只形读者 `checkpoint-store-face.ts` 的 `readRiskDescriptorBody`,修前 local 把原值原样上 wire)。放行的最坏后果 = **这一行**的分诊 descriptor 落 null:severity 折 0 排到有 descriptor 的行之后、披露位(`allowRuleShadowed`;7.117.0 前叫 `shadowedRule`)无可脱敏、读面派生的 `governanceForced` 徽章不亮 —— 三者都是**展示/分诊**,不是执法判据(门早已 park,真按 `shellGateDoctrine` 判的 `active-run-conflict.ts` 读的是 checkpoint blob 的 `get()`,不经本读面),且 `governanceForced` 的成文语义本就是「缺席 = 没有治理来源的**证据**」。不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 cell 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空),连同其余所有行一起消失。故 F 类;tag 与候选那格**分开计**,并计会让「哪一格在坏」在遥测里读不出来。",
169
+ note: "运维待批队列(`GET /v1/approvals` / `/stream`;两孪生同一只投影 `checkpoint-store-face.ts` 的 `buildQueueActionFacts`)的某一行,停驻文档门上的风险描述(引擎派生 `checkpointIndexFacts` 那一格,只在审批门上)**在场却读不成一只对象**(手改 / 带外写者写下的文档)。7.152.0 起只有这一座:描述不再落列,队列行在读时从续跑执行的同一次整行解码取(此前 SQL 孪生读 `checkpoint.risk_descriptor` 列、列文本坏也计在本 tag;那一列随一次性迁移 M54 删)。放行的最坏后果 = **这一行**的分诊 descriptor 落 null:severity 折 0 排到有 descriptor 的行之后、披露位(`allowRuleShadowed`)无可脱敏、读面派生的 `governanceForced` 徽章不亮 —— 三者都是**展示/分诊**,不是执法判据(门早已 park,真按 `shellGateDoctrine` 判的 `active-run-conflict.ts` 读的是 `get()`,不经本读面),且 `governanceForced` 的成文语义本就是「缺席 = 没有治理来源的**证据**」。不放行的代价是一行坏描述打掉整个租户的队列。故 F 类。计数口径:SQL 孪生每份字节每进程一次(动作事实按字节记忆),local 每次列表一次。",
174
170
  },
175
171
  "server.approvals.park-row-blob-unreadable": {
176
172
  cls: "F",
177
- note: "S-700(`stores-sql/checkpoint-store-sql.ts` 的 `readParkRowActionCell`):运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint` 列里寄存行的 **`pendingAction` 子树**(NP-3 / 7.100.0 起引擎内只取这一棵、整只快照不出库;只为 park 行事实 `requiresRealApproval` / `ruleOffersAbsence` / `mandated`(S-663 二段,core #1079)/ `mandate`(S-721)/ `origin`(S-755)而读 —— 事实位的真源是 `approval-card.ts` 的 `ParkRowFacts`)**在场却不是一只对象**(JSON `null` 字面 / 串 / 数 —— 手改 / 迁移脚本改过)。子树**缺席**(SQL NULL:成员不在,或整只文档不是对象 —— 后者 `get()` 照旧拒;MariaDB 文本承载上的非 JSON 字节同样答 SQL NULL)⇒ 事实缺席、不计数。放行的最坏后果 = **这一行**的 park 行事实(`ParkRowFacts` 各位)缺席(展示/分诊材料;core 定性 display metadata,resume 的带子读 gate 自己的位),队列其余部分照常 —— 而这一行本来就 resume 不了(`get()` 对同一格拒)。不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 blob 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空),与同一 `rows.map` 里 `rule_suggestions` / `risk_descriptor` 两格同族同判。故 F 类;tag 与那两格**分开计**(哪一格在坏要读得出来)。计数非零 = 这一行的 decide 同样读不动(`get()` 对同一格拒),去按 session 查那一行。 7.144.0 起同 tag 另有一座:停驻行的**整行读**(`readStoredRow`;按快照摘要记忆,未命中才读)—— 运维队列行的判决 `rowVerdict` 与技能卡两位、7.145.0 起还有收件箱 / 任务视图 `listByScope` 的行投影,同经这一只读法、同一失败方向(行级隔离):整行解不出 ⇒ 判官对读回的原样值作答(恒 `damaged`),行照列、带判决;体是对象但 core 摘要读不动(`{}` / 缺 `state` 等手改行)⇒ 判官对这只对象作答;两形都只丢摘要派生的位(队列行的技能卡两位 / 收件箱行的摘要键,收件箱行退回列组事实),逐次计、不进记忆,一行坏体在子树与整行两读上各计一次。修前收件箱对同一行整张拒(500 / 503)。 (`member=gate` 那第二座随 core 7.55.0 #1468 P1 阶段二退役:队列行的卡与到期分法改读 `approval_card` / `gate_kind` 两列 —— 写口与 M29 回填同一只派生落下的格 —— 本读面不再读 blob 的 `gate` 子树。)(S-2076 的 `readParkedSkillCardFacts` 两座已由上面那次 `projectStoredRow` 整行读取代,树上零命中。)",
173
+ note: "运维待批队列(`GET /v1/approvals` / `/stream`)、收件箱 / 任务视图(`listByScope`)与按会话读口的某一行,停驻行的**整行读**(`stores-sql/checkpoint-store-sql.ts` 的 `readStoredRow`;队列行的全部动作事实 —— 工具名、绑定、入参、卡、描述、候选、bidi 位、park 行事实、`checkpointId`、技能卡两位、判决 —— 都出自这一次解码,两孪生同一只投影 `buildQueueActionFacts`)读不动:字节解不出 ⇒ 判官对读回的原样值作答(恒 `damaged`);体是对象但 core 摘要读不动(`{}` / 缺 `state` 等手改行)或 core 的投影自己抛 ⇒ 判官对这只对象作答。行照列、带判决,动作事实 `null` / 缺席(与 local 孪生同形),逐次计、不进记忆。放行的最坏后果 = **这一行**少了动作事实(这样的行续跑同样读不动它 —— `get()` 对同一份字节拒),队列其余部分照常;不放行的代价是一行坏字节打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远停在旧帧)。故 F 类。7.152.0 起不再有「`pendingAction` 子树」那一座(引擎内的成员提取退役,同一份文档只有一只 parser)。计数非零 = 这一行的 decide 同样读不动,去按 session 查那一行。",
178
174
  },
179
175
  "server.approvals.queue-row-agent-unreadable": {
180
176
  cls: "F",
@@ -274,7 +270,7 @@ export const FAIL_OPEN_TAGS = {
274
270
  },
275
271
  "server.approvals.active-run-conflict-material-unavailable": {
276
272
  cls: "F",
277
- note: "A-057.47:`buildActiveRunConflict` 的材料装配段(getRun / turnActivity / peekPendingScope / findPendingTokenBySession / checkpoint `get`)任一失败 ⇒ 整段退化成裸 409(只剩 error + errorCode + activeTaskId),`activeTaskStatus` / `msSinceLastActivity` / `pendingGate`(kind·decidePath·governanceForced·checkpointId)全部蒸发。放行的最坏后果 = **展示/分诊**面缺料:壳画不出「这条 run 卡在哪道门、去哪儿决」,人退回 `POST /v1/runs/{activeTaskId}/cancel` 这条保底真路 —— 不参与任何门/CAS/resume 判定(执法面读的是 checkpoint blob 的 `get()`,不经本材料;与 census 第 21 行同一条判据),故 F 类。方向刻意不改:本材料是 best-effort 增强,让它抛会把一次 store 抖动变成整个 409 路径的 500(顶注第 11 行逐字成文「store 面任何失败都不得挡 409 本体」)。必须留痕的理由:本文件零 logger 席、pool 层无 per-query 错误日志、调用侧(tasks.ts / runs.ts / server.ts 五处)因本函数恒不 reject 结构上拿不到信号 ⇒ 「approval 出路材料系统性丢失」此前在遥测里与「一切正常」同形;滚动升级期 `checkpoint-store-sql.ts` 的 version-too-new throw 与 strict parseJson 也一并被吞在这里。",
273
+ note: "A-057.47:409 `conflict.session_active_run` 的材料读失败,分两层(7.152.0 起):① 持有者那一行读不出(`refusalOccupantOf` 的 getRun —— 提交 / 续跑面的 `buildActiveRunConflict`、删除口、run 外回退口三处同调)⇒ 体只剩 error + errorCode + activeTaskId,`activeTaskStatus` / `msSinceLastActivity` / `pendingGate` 不在;② 持有者行读到了而出路材料读不出(turnActivity / peekPendingScope / findPendingTokenBySession / checkpoint `get`)⇒ 占用两键照留,只少 `msSinceLastActivity` 或 `pendingGate`(kind·decidePath·governanceForced·checkpointId)。放行的最坏后果 = **展示/分诊**面缺料:壳画不出「这条 run 卡在哪道门、去哪儿决」,人退回 `POST /v1/runs/{activeTaskId}/cancel` 这条保底真路 —— 不参与任何门/CAS/resume 判定(执法面读的是 checkpoint blob 的 `get()`,不经本材料;与 census 第 21 行同一条判据),故 F 类。方向刻意不改:本材料是 best-effort 增强,让它抛会把一次 store 抖动变成整个 409 路径的 500(顶注第 11 行逐字成文「store 面任何失败都不得挡 409 本体」)。必须留痕的理由:本文件零 logger 席、pool 层无 per-query 错误日志、调用侧(tasks.ts / runs.ts / server.ts 五处)因本函数恒不 reject 结构上拿不到信号 ⇒ 「approval 出路材料系统性丢失」此前在遥测里与「一切正常」同形;滚动升级期 `checkpoint-store-sql.ts` 的 version-too-new throw 与 strict parseJson 也一并被吞在这里。",
278
274
  },
279
275
  "server.engine-notice.durable-append-failed": {
280
276
  cls: "F",
@@ -328,10 +324,6 @@ export const FAIL_OPEN_TAGS = {
328
324
  cls: "P-DEBT",
329
325
  note: "#296(A-052.2,clay 裁定 C-R21):`REMOTE_EXEC=ssh` 且**两只主机密钥旋钮都缺席**(`SSH_HOST_FINGERPRINT` / `SSH_KNOWN_HOSTS`)⇒ 本次连接接受**任何**主机密钥,等价 `ssh -o StrictHostKeyChecking=no`。放行的最坏后果:一次中间人拿到这条会话的**全部命令、全部产物、以及 agent 在那台机器上的全部动作**(私钥仍在控制面手里、拿不走,design/61 §5 #2)。⇒ 保护型欠账,不是体验回退。**方向是裁定的、不是遗漏**:本 lane 的既有部署形是「AI 编排批量部署到一批 SSH 可达的机器」,那些机器的指纹通常不在任何 known_hosts 里,默认拒连 = 一次静默的可用性断裂;C-R21 裁「在场即严格,缺席即响亮」。补偿三件:①**每连接**一条 `ssh_host_key_unverified` warn(不是每进程一次 —— 一条长期裸连的 lane 必须在每条连接上都看得见);②本计数(遥测里「有多少条连接是裸连」是一个可观测的数,曲线应当只降不升);③两旋钮任一在场即**严格校验、不符拒连**(拒因带两半指纹 + `ssh-keyscan` 指路)。终局 = 部署把旋钮配上(那时本计数归零);旋钮不配而想收紧的部署级开关(「无旋钮即拒启」)是下一件,不在 C-R21 射程。",
330
326
  },
331
- "server.approval.park-redemption-cap-refused": {
332
- cls: "F",
333
- note: "#329 / #343(黑板 [5100] Q3):停驻行迟到决议的**受理回执表**(本副本对「200 丢包后重试」的幂等承诺 + 重叠请求的单飞句柄;键 = 行的键 askId,只在一次赎回真开飞时开格;容量帽只数受理之后留下的回执,在飞的单飞句柄永不被逐)**拒留一张回执**。放行的最坏后果 = 这**一次**受理(照旧生效)没有本副本的回执可依:200 丢包后的重试会再进一次赎回腿、拿到那条腿的 409(那张 checkpoint 已被消费)而不是幂等 200 回放(终局恒由赎回腿的 gate CAS 定,不会错兑也不会双兑);迟到受理本身、`GET /v1/approvals` 列表与 `/v1/approvals/:sessionId/decide` 一个字节不动 ⇒ F 类。为什么方向是「拒新」而不是 FIFO 挤最旧:那个形让**甲的用量决定乙的可用性**(已鉴权租户量产受理即可把别家回执挤出,merge-rescan 744 confirmed 的同一病形)。必须留痕:「表被别人打满」与「这一次本来就没有回执」在 wire 上同形。detail 带 owner(判「压力来自谁」的第一手线索)。臂只有一条:全局回执帽满、本 principal 未到子帽、表里没有过期回执可收 ⇒ 拒留(detail 带 owner)。本 principal 到了子帽的常态臂逐自己最旧的一张回执(量产者自伤,设计内有界表纪律),不走本 tag;在飞的单飞句柄不占帽、永不被逐。",
334
- },
335
327
  "server.approval.parked-decision-not-recorded": {
336
328
  cls: "F",
337
329
  note: "S-1054 α(`tool-approval.ts` 的 `recordParkedOutcome`,停驻赎回那一飞的落行步):停驻门**已经受理**了这次决定(续跑已开始),而把它的记录(决议向 · 署名 · 理由 · 回决幂等键 · 出处)落到仍 `PARKED` 的问行上没成 —— 店错 / 超时 / 行出了门判过的属主域 / 这把键已被同 task 另一只问占着(detail 带 `reason`)。放行的最坏后果 = 这一问在耐久决断口上的**同键回放**读不到这把键:同键重发得到 `409 conflict.ask_decided`(回显门上站着的那次决定,决议向 / 时刻 / 理由取自门,无署名),而不是 200 回放;审计面少一份署名。决定本身零影响(终局恒在停驻门上,门已决);不改判、不重赎、不双兑。计数非零 = 问账店在受理之后写不动了,运维要去看店。",
@@ -340,6 +332,10 @@ export const FAIL_OPEN_TAGS = {
340
332
  cls: "F",
341
333
  note: "S-02 codex R1-[medium](验真后修):decide 的 409 `approval_stale` 臂对**调用方回显的旧 token** 做归属判定(`cs.get(binding.checkpointToken)`),那次读**抛了**(store 抖动 / 坏 checkpoint 行 / 行恰被清理)。修前这里是静默 `catch(()=>null)`,「读不出」被折成「确认不在库」——叠上 S-02 的 404 收口后,一次 store 抖动就会把合法旧 token 的 409+terminal 谎报成 404「没有这条审批」。修后:unreadable ⇒ **保持 409**(`terminal` 不披露——证不出归属就不说,与 2026-07-26 纪律同向;404 折叠只在读成功且未命中时走,探测方无法自控 store 故障 ⇒ 谕示封闭不破)。放行的最坏后果 = 该次拒体 `terminal` 诚实缺席(`currentPending` 由它自己的读口与属主复核另判,不受本臂牵连),壳退回重拉列表,judgment 面 fail-safe,故 F 类。留痕理由:这次读是 terminal 披露与 404 折叠两个判定的输入,长期抖动必须在遥测显形。",
342
334
  },
335
+ "server.resume.cancel-answer-row-unreadable": {
336
+ cls: "F",
337
+ note: "续跑腿(`http/resume-legs.ts` 的 `landedTerminalRow`)两只本腿铸取消终局的取消臂(`checkpoint.resume_aborted` 臂 / 交给引擎之后抛出的取消臂):驱行终局之后读回那一行,200 体的词 / 码 / 句读行上落下的那一份(run 店终局写先到者得,先到的可以是收割 / 判死),那一读抛。放行 = 体读本腿铸的那一份取消终局(读回之前的形);最坏后果 = 先到者不是本腿时体上的码 / 句与 `GET /v1/runs/:id` 不同 —— 行、账本、读面一个字节不受它管,门 / 裁决不读这只体 ⇒ F 类。detail `task=<taskId> arm=<resume-aborted|thrown-cancel> err=<原句>`;计数 = 多少次答复没读到行。",
338
+ },
343
339
  "server.resume.reopen-confirm-unreadable": {
344
340
  cls: "F",
345
341
  note: "S-447(#60 M2 自查项,`http/resume-legs.ts` 的 `confirmCheckpointReopened`):续跑腿交回一条没 park 的失败结果后(7.129.0 起每一条都问,不再只在三个重开码上问)按 **token** 复核「这张 checkpoint 是不是又 pending 了」,这一读抛(库拖/版本太新/店不可达)。**方向本来就是 fail-closed**:读不出 ⇒ `return true` ⇒ 「不写任何终局、重新 park」(`:1206-1212` 头注已把取舍与有界代价写死:错 park 由 `reapSuspended` 兑,错终局会孤儿化一张活 park 到 TTL)—— 所以这条腿不是 P 类,缺的只是**留痕**。放行的最坏后果 = 多一次多余的 re-park(一张已经被决掉的卡重新挂到 reaper 窗里),人面上是「这条续跑没动」而不是谁被放行了。必须登记的理由是 **uniformity**:同文件三只同形读(`:249` `server.approvals.stale-echoed-token-unreadable` · `:288` `server.approvals.stale-current-pending-unreadable` · 本腿)中只有它是黑的,于是「店一直读不出所以每条续跑都在白白 re-park」与「一切正常」在遥测上同形。计数非零 = 这台机器的 checkpoint 店在拖,运维要去看库。",
@@ -520,6 +516,10 @@ export const FAIL_OPEN_TAGS = {
520
516
  cls: "F",
521
517
  note: "S-1195(7.119.0;`plugins/snapshot-bucket-presence.ts` 的 `ensureSnapshotBucket`,boot 期核一次快照桶 `SESSION_SNAPSHOT_BUCKET`;S-2021〔7.136.0〕起同一只探针、同一条规则、同一个 tag 也核 k8s 车道的工作区快照桶 `WORKSPACE_SNAPSHOT_BUCKET`——detail 里的 `bucket=` 就是被核的那只桶名;detail = `bucket=… endpoint=<buildDisplaySafeUrl 的显示形> <HTTP 状态 | request failed: 错类>`):presigned 列举对 `MINIO_ENDPOINT` **连不上 / 403 / 5xx / 没有 NoSuchBucket 的 404**,或探针到窗尾一次都没答过(detail 写 `probe still pending when the window ended`)⇒ **证明不了桶缺**,不拒启、照常起服(只有 404 + `NoSuchBucket` 才是「缺」,那一形窗内重试、到窗拒启,不走本 tag)。三问:①错误落到哪 —— 本 tag 的计数 / 探针行 / 记录器的一次性 warn,detail 带端点显示形与状态或错类;②谁受害 —— 桶其实不存在、或凭据不能列举的部署:之后每一次快照 offload 写与 SendUserFile 私有 presigned 请求会答 404 / 403,孤儿 sweep 每分钟一条失败,运维读到的是一串失败请求而不是「桶没建」(与 7.118.x 的既有形状同形,不是新损失);工作区快照桶则是每条 run 读 `latest` 得 404/403——404 + NoSuchBucket 在运行期由 `workspace_snapshot_bucket_missing` 响亮拒绝,403/5xx 走既有的非 404 读失败臂(同样响亮);③缺席倒向哪边 —— 倒向**放行起服**:没有证据既不拒启、也不伪造「桶在场」或「桶缺」,不是门 / 权限 / 凭证。最坏后果 = 缺桶的部署晚一步才暴露;不放行的代价是对象存储一次抖动 / 一次 403 就让整只服务起不来。计数非零 = 这台部署启动时没能确认快照桶,按 detail 的端点与状态去核对网络 / 凭据 / 桶。",
522
518
  },
519
+ "server.session-blob-namespace.claim-unproven": {
520
+ cls: "F",
521
+ note: "`plugins/session-blob-namespace.ts` 的 `establish`(开店时对会话 blob 命名空间认领一次:`plugins/store-backend.ts` `openStoreBackendWithFallback` 在 SQL 店开好之后调,一次尝试、不在 `STORE_LOCK_WAIT_MS` 窗里重试,每个请求的上界与快照桶探针同一只常量 `SNAPSHOT_BUCKET_PROBE_TIMEOUT_MS`;detail = `bucket=… prefix=<SESSION_SNAPSHOT_PREFIX 的显示形 | unset> endpoint=<buildDisplaySafeUrl 的显示形> <claim read answered HTTP <状态> | claim write answered HTTP <状态> | the claim just written does not read back | claim request failed: 错类>`):认领物件 `{SESSION_SNAPSHOT_PREFIX}blob-namespace-claim` **读不动 / 写不进 / 连不上 / 写了读不回** ⇒ 证明不了这只命名空间是不是本库的,不拒启、照常起服(只有读到别的库的认领才是「不是」,那一形开店即拒、不走本 tag)。三问:①错误落到哪 —— 本 tag 的计数 / 探针行 / 记录器的一次性 warn;数据轴不随之放开:之后每一次删除(附件孤儿清扫、附件释放、文件历史清扫、退役 blob 清扫)各自重读认领,读不成本库的就拒删,抛出点名桶、前缀旋钮与该授权限的拒句(响亮;那是 fail-closed,不计本 tag);②谁受害 —— 引擎的键缺认领物件 GetObject / PutObject 权限的最小权限部署,或起服那一刻对象存储不通的部署:附件与文件历史的字节不再被回收(桶只涨不减),直到权限补齐或存储答复 —— 恢复后的第一次删除当场认领(缺 ⇒ create-only 写、回读相符)再删,读到别的库的认领 ⇒ 拒删、不改写;③缺席倒向哪边 —— 倒向**放行起服**:没有证据既不拒启,也不当作「是本库的」去删任何字节,不是门 / 权限 / 凭证。最坏后果 = 回收停摆到权限补齐(存储成本,不是数据丢失);不放行的代价是对象存储一次抖动 / 一条缺的权限就让整只服务起不来。计数非零 = 这台部署启动时没能确认命名空间的归属,按 detail 的端点与原因去核对网络 / 凭据 / 认领物件的权限。",
522
+ },
523
523
  "server.fleet.serving-lease-unconfirmed": {
524
524
  cls: "R",
525
525
  ruling: "C-R296",
@@ -562,7 +562,11 @@ export const FAIL_OPEN_TAGS = {
562
562
  },
563
563
  "server.sandbox-egress.policy-gap": {
564
564
  cls: "P-DEBT",
565
- note: "k8s 车道沙箱出网的起服自检(`plugins/remote-env-k8s.ts` `checkSandboxEgressPolicy` 读节点表与沙箱 ns 的 NetworkPolicy,判法 `sandbox-egress-policy.ts` `sandboxEgressGaps`;起服一次、不挡起服)读出一个缺口 —— 某节点的 InternalIP / ExternalIP 落在一条放行 ipBlock 内(`kind=node_address_open`)、没有策略以 Egress 选中沙箱 pod(`kind=policy_absent`)、pod 保留 IPv6 而策略层担保不了 v6(`kind=ipv6_enabled`)、节点表或策略表读不到(`kind=unreadable what=nodes|networkpolicies`)⇒ 车道**照常起**,每个缺口一行 `sandbox_egress_policy_gap`(带后果句与去哪改)。归 P 类:出网策略是保护面,缺口意味着沙箱里的代码可能够到节点上的服务;归 DEBT 的理由:修法都在集群配置里(节点地址点名、kubelet 放行 v6 sysctl、CNI 的 v6 执行、RBAC),本服务改不了,而拒起车道会让缺省单节点装法(恒有 `ipv6_enabled`)升级即停摆沙箱执行 —— 车道自己的隔离(VM 边界、零 SA token)仍在。放行的最坏后果 = 读出缺口的那一面照旧可达,直到运维按行里的后果句改配置。计数非零 = 这台部署的沙箱出网面有读得出的缺口。读不出的面(宿主 DNAT 发布端口、「pod 所在节点恒放行」的实现差异、CNI 根本不执行策略)不在本 tag 的射程里。",
565
+ note: "k8s 车道沙箱出网的起服自检(`plugins/remote-env-k8s.ts` `checkSandboxEgressPolicy` 读节点表与沙箱 ns 的 NetworkPolicy,判法 `sandbox-egress-policy.ts` `sandboxEgressGaps`;起服一次、不挡起服)读出一个缺口 —— 某节点的 InternalIP / ExternalIP 落在一条放行 ipBlock 内(`kind=node_address_open`)、没有策略以 Egress 选中沙箱 pod(`kind=policy_absent`)、pod 保留 IPv6 而策略层担保不了 v6(`kind=ipv6_enabled`)、节点表或策略表读不到(`kind=unreadable what=nodes|networkpolicies`:RBAC 缺 / API 不可达 / 答体不成形;**集群 API 凭据缺不在其内** —— 凭据缺是起服拒 `config.k8s_api_credentials_missing`,自检不发、不记入本 tag,这一臂已退役)⇒ 车道**照常起**,每个缺口一行 `sandbox_egress_policy_gap`(带后果句与去哪改)。归 P 类:出网策略是保护面,缺口意味着沙箱里的代码可能够到节点上的服务;归 DEBT 的理由:修法都在集群配置里(节点地址点名、kubelet 放行 v6 sysctl、CNI 的 v6 执行、RBAC),本服务改不了,而拒起车道会让缺省单节点装法(恒有 `ipv6_enabled`)升级即停摆沙箱执行 —— 车道自己的隔离(VM 边界、零 SA token)仍在。放行的最坏后果 = 读出缺口的那一面照旧可达,直到运维按行里的后果句改配置。计数非零 = 这台部署的沙箱出网面有读得出的缺口。读不出的面(宿主 DNAT 发布端口、「pod 所在节点恒放行」的实现差异、CNI 根本不执行策略)不在本 tag 的射程里。",
566
+ },
567
+ "server.sandbox-credentials.probe-unanswered": {
568
+ cls: "F",
569
+ note: "k8s 车道每条 run 铸环境之前读一次集群 API 凭据(`boot/execution-env.ts` `createK8sRunEnvFactory` ← `plugins/remote-env-k8s.ts` `apiCredentialReading`:判官说缺 ⇒ 拒;一次 SelfSubjectAccessReview 答 401 ⇒ 拒;答 2xx ⇒ 放行),而这一次探问**没有证出结论**(HTTP 403 / 5xx / 其余非 2xx 非 401、请求抛 / 超时;detail = `namespace=<ns> HTTP <状态> | <错误句>`)⇒ 这条 run 的环境照铸,凭据到底行不行由车道自己的连接答(pod 创建被 401 / 403 拒 ⇒ 响亮的 `shell_unavailable`、瞬时的 API 抖动在车道自己的重试界内重来)。只有正面证据才拒 —— 为一次没答的探问拒 run,会把每次 API 抖动变成失败的 run,把没给已认证调用方留 SSAR 权限的集群变成永远起不了 run。最坏后果 = 凭据真已失效而探问恰好没答的那条 run,落回修前的形(每条 Bash `shell_unavailable`、run `completed`)—— 可用性 / 可见性,不是门 / 凭据的放宽(没有沙箱、没有执行、没有凭据被多给一份)。归 F。计数持续非零 = 这台部署的服务账号问不了 SelfSubjectAccessReview 或 API 常不可达,按 detail 核。",
566
570
  },
567
571
  "server.fleet.announce-reply-unreadable": {
568
572
  cls: "P-DEBT",
@@ -596,7 +600,7 @@ export const FAIL_OPEN_TAGS = {
596
600
  },
597
601
  "server.store-durability.evidence-unreadable": {
598
602
  cls: "F",
599
- note: "店的持久性起服取证(`store-posture.ts` `captureStoreEvidence`,起服第 2 段段首一次):`/proc/self/mountinfo` 读不出(`why=mountinfo_unreadable err=<码>`)/ 有读不懂的行(`why=mountinfo_malformed lines=<n>`)/ 一根的路径展不平成物理路径(`why=path_unresolvable err=<码> path=<路径>`)/ 挂载表读得出、却找不到走那条路径看见的那一只挂载(`why=mount_unresolved path=<路径>`:空表、同父同点的影子挂载)⇒ 那几根(读不出挂载表时是三根全部)判 `unknown`。只影响自报:能力位 `store.durability`、`/health.store.durability`、诊断 `storeDurability.roots` 如实说 `unknown`,起服布线审计对 `unknown` 只 warn、不拒启。放行的最坏后果 = 一只真落在易失介质(容器可写层 / emptyDir)上的 local 数据根因证据读不到而报 `unknown`、照常起服 —— 与本版之前「按后端种类恒报持久」同向且更诚实,不开门、不碰凭据。计数非零 = 本进程读不到 / 读不懂自己的挂载表(受限 procfs、挂载形不常见)或路径上有权限竞态。",
603
+ note: "店的持久性起服取证(`store-posture.ts` `captureStoreEvidence`,起服第 2 段段首一次):`/proc/self/mountinfo` 读不出(`why=mountinfo_unreadable err=<码>`)/ 有读不懂的行(`why=mountinfo_malformed lines=<n>`)/ 一根的路径展不平成物理路径(`why=path_unresolvable err=<码> path=<路径>`)/ 挂载表读得出、却找不到走那条路径看见的那一只挂载(`why=mount_unresolved path=<路径>`:空表、同父同点的影子挂载)⇒ 那几根(读不出挂载表时是三根全部)判 `unknown`。只影响自报:能力位 `store.durability`、`/health.store.durability`、诊断 `storeDurability.roots` 如实说 `unknown`,起服布线审计对 `unknown` 只 warn、不拒启。放行的最坏后果 = 一只真落在易失介质(容器可写层 / emptyDir)上的 local 数据根因证据读不到而报 `unknown`、照常起服 —— 与本版之前「按后端种类恒报持久」同向且更诚实,不开门、不碰凭据。计数非零 = 本进程读不到 / 读不懂自己的挂载表(受限 procfs、挂载形不常见)或路径上有读不出的段(没有搜索权限 / 链接成环 —— 规范形读不出即抛,不当成「还不存在」)/ 权限竞态。",
600
604
  },
601
605
  "server.remote-write.staging-dir-left": {
602
606
  cls: "F",
@@ -604,11 +608,11 @@ export const FAIL_OPEN_TAGS = {
604
608
  },
605
609
  "server.resume-anchor.capture-failed": {
606
610
  cls: "F",
607
- note: "回退锚(`resumeAt` 的提示词 / 助手文本手柄)写入失败 —— 四条腿同一只写法 `runs.ts` 的 `settleResumeAnchor`:流式腿(`POST /v1/tasks/stream`,done 帧之前 / 断连收尾时 await)、同步腿(非流式 `POST /v1/tasks` 的 plain 形,200 应答之前 await)、后台腿(`POST /v1/runs`)、续跑腿。锚店写抛(库抖 / 表缺 / 盘满),或单行店操作期限(`BASELINE_IO_DEADLINE_MS`,2 s;与项目指令基线读写同一只数、同一只 `withinIoDeadline`)内没落定(锚店挂住:锚店的写口自己不带期限)⇒ 这一次提示词(或这一轮助手文本)此刻没有回退手柄,run 照常收尾、终帧照发、不改任何终局;到期只放手不取消,那次写照常在飞、迟到落定的锚照样可用(迟到的失败被吞,不重复计数)。放行的最坏后果 = 用户拿这次 run 的 taskId 去 `resumeAt` 得 404 `resume_at.unknown_event`、会话视图里那条用户消息行不带 `taskId` 手柄(用户面的读数只有这一处真源,本臂不另铸第二份);不是门、不是凭据。不放行(抛)的代价是让一次锚写失败把整条已经跑完的 run 判成失败。计数持续非零 = 锚店写不进(去看库)。计数里 `reason=timeout` 占多数 = 锚店慢到秒级(去看库的锁 / 连接池)。detail = `leg=<stream|sync|bg|resume> kind=<prompt|turn> reason=error error=<写口的错误句>` 或 `… reason=timeout boundMs=<期限>`。",
611
+ note: "回退锚(`resumeAt` 的提示词 / 助手文本手柄)写入失败 —— 四条腿同一只写法 `runs.ts` 的 `settleResumeAnchor`,经同一只 `TurnAnchorCapture` 在决定这只锚的那一帧到手时 await(流式腿 `POST /v1/tasks/stream`、同步腿非流式 `POST /v1/tasks` 的 plain 形、后台腿 `POST /v1/runs`、续跑腿;提示锚在开场提示的提交上,早于终帧;要关窗校正的那一形同一把键写两次,后一笔等前一笔落定再发 —— 提示锚至多两个期限;后台 / 续跑腿另有每个可锚的助手文本轮各一个)。锚店写抛(库抖 / 表缺 / 盘满),或单行店操作期限(`BASELINE_IO_DEADLINE_MS`,2 s;与项目指令基线读写同一只数、同一只 `withinIoDeadline`)内没落定(锚店挂住:锚店的写口自己不带期限)⇒ 这一次提示词(或这一轮助手文本)此刻没有回退手柄,run 照常收尾、终帧照发、不改任何终局;到期只放手不取消,那次写照常在飞、迟到落定的锚照样可用(迟到的失败被吞,不重复计数)。放行的最坏后果 = 用户拿这次 run 的 taskId 去 `resumeAt` 得 404 `resume_at.unknown_event`、会话视图里那条用户消息行不带 `taskId` 手柄(用户面的读数只有这一处真源,本臂不另铸第二份);不是门、不是凭据。不放行(抛)的代价是让一次锚写失败把整条已经跑完的 run 判成失败。计数持续非零 = 锚店写不进(去看库)。计数里 `reason=timeout` 占多数 = 锚店慢到秒级(去看库的锁 / 连接池)。detail = `leg=<stream|sync|bg|resume> kind=<prompt|turn> reason=error error=<写口的错误句>` 或 `… reason=timeout boundMs=<期限>`。",
608
612
  },
609
613
  "server.resume-anchor.cause-read-failed": {
610
614
  cls: "F",
611
- note: "未知回退手柄的 404 成因半句(`history-anchor.ts` 的唯一组句器;提交体 `resumeAt` / `rewindFilesTo` 与 run 外回退口 `to` 三处同调):锚店里没有这只手柄 ⇒ 经属主存取器读一次 run 行(嵌套可选读,看不见 ≡ 没有)、同会话 ⇒ 按这条提问自己的属主键再问一次锚店,只为选句(调用方看得见的本会话提问、它自己也没落锚 ⇒ 「没有锚的提问」并点名带附件不落锚那一类;否则只说没有锚)。这两读任一抛(库抖 / 表缺)⇒ 404 的码与状态照旧,句子退回只说没有锚。放行的最坏后果 = 一条真实存在、没有锚的提问,其 404 少了那半句说明(调用方可能当成手柄写错);不影响任何判定、不放行任何请求。",
615
+ note: "未知回退手柄的 404 成因半句(`history-anchor.ts` 的唯一组句器;提交体 `resumeAt` / `rewindFilesTo` 与 run 外回退口 `to` 三处同调):锚店里没有这只手柄 ⇒ 经属主存取器读一次 run 行(嵌套可选读,看不见 ≡ 没有)、同会话 ⇒ 按这条提问自己的属主键再问一次锚店,只为选句(调用方看得见的本会话提问、它自己也没落锚 ⇒ 「没有锚的提问」,只陈述这一事实、不点名成因;否则只说没有锚)。这两读任一抛(库抖 / 表缺)⇒ 404 的码与状态照旧,句子退回只说没有锚。放行的最坏后果 = 一条真实存在、没有锚的提问,其 404 少了那半句说明(调用方可能当成手柄写错);不影响任何判定、不放行任何请求。",
612
616
  },
613
617
  "server.remote-write.stage-seal-fallback": {
614
618
  cls: "F",
@@ -49,7 +49,9 @@ function screenJsonLine(line, withheld) {
49
49
  }
50
50
  function serializeEntry(head, fields) {
51
51
  try {
52
- return JSON.stringify({ ...head, ...fields });
52
+ const record = { ...head, ...fields, ...head };
53
+ Reflect.deleteProperty(record, "toJSON");
54
+ return JSON.stringify(record);
53
55
  }
54
56
  catch (err) {
55
57
  return JSON.stringify({ ...head, [FIELDS_WITHHELD]: errorKindOf(err) });