@sema-agent/server 7.138.0 → 7.140.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 (332) hide show
  1. package/MIGRATION.md +457 -7
  2. package/README.md +7 -4
  3. package/README.zh-CN.md +6 -4
  4. package/USAGE.md +91 -41
  5. package/deploy/sema-up/README.md +1 -1
  6. package/deploy/sema-up/lib/lanes.json +3 -2
  7. package/dist/adoption/runner.js +1 -1
  8. package/dist/adoption/sql.js +1 -1
  9. package/dist/adoption/wire.d.ts +3 -3
  10. package/dist/approval-card.d.ts +26 -26
  11. package/dist/bench/s1/arms.d.ts +1 -1
  12. package/dist/bench/s1/arms.js +1 -3
  13. package/dist/bench/s1/live-deps.js +3 -2
  14. package/dist/bench/s1/row.d.ts +5 -2
  15. package/dist/bench/s1/row.js +2 -22
  16. package/dist/bench/s1/run-firm.js +2 -2
  17. package/dist/boot/adoption.js +1 -1
  18. package/dist/boot/device-lane.d.ts +8 -3
  19. package/dist/boot/device-lane.js +7 -2
  20. package/dist/boot/execution-env.d.ts +4 -2
  21. package/dist/boot/execution-env.js +28 -34
  22. package/dist/boot/execution-lane.d.ts +9 -1
  23. package/dist/boot/execution-lane.js +6 -1
  24. package/dist/boot/governance-seams.d.ts +3 -2
  25. package/dist/boot/governance-seams.js +9 -11
  26. package/dist/boot/memory-boundary.d.ts +14 -51
  27. package/dist/boot/memory-boundary.js +10 -20
  28. package/dist/boot/memory-consolidation.d.ts +15 -11
  29. package/dist/boot/memory-consolidation.js +25 -14
  30. package/dist/boot/resolve-spec.d.ts +4 -6
  31. package/dist/boot/resolve-spec.js +10 -13
  32. package/dist/boot/retention-lane.d.ts +5 -5
  33. package/dist/boot/retention-lane.js +0 -6
  34. package/dist/boot/runner-deps.d.ts +6 -4
  35. package/dist/boot/runner-deps.js +3 -1
  36. package/dist/boot/session-faces.d.ts +0 -3
  37. package/dist/boot/session-faces.js +15 -8
  38. package/dist/boot/stage-02-web-admin-pull.js +2 -2
  39. package/dist/boot/stage-03-store-backend.d.ts +2 -6
  40. package/dist/boot/stage-03-store-backend.js +2 -3
  41. package/dist/boot/stage-04-stores.d.ts +2 -6
  42. package/dist/boot/stage-04-stores.js +5 -5
  43. package/dist/boot/stage-05-execution-env.d.ts +2 -6
  44. package/dist/boot/stage-05-execution-env.js +2 -2
  45. package/dist/boot/stage-06-runners.d.ts +2 -6
  46. package/dist/boot/stage-06-runners.js +2 -3
  47. package/dist/boot/stage-07-capability-layer.d.ts +2 -6
  48. package/dist/boot/stage-08-reapers.d.ts +2 -6
  49. package/dist/boot/stage-09-leader.d.ts +2 -6
  50. package/dist/boot/stage-09-leader.js +1 -2
  51. package/dist/boot/stage-10-http-server.d.ts +2 -6
  52. package/dist/boot/stage-10-http-server.js +7 -6
  53. package/dist/boot/stores.d.ts +3 -6
  54. package/dist/boot/stores.js +27 -40
  55. package/dist/boot/task-list-lane.d.ts +1 -1
  56. package/dist/boot/task-list-lane.js +1 -1
  57. package/dist/boot/web-admin.js +37 -11
  58. package/dist/capabilities/execution-lane.d.ts +2 -2
  59. package/dist/capabilities/mcp-probe.js +1 -1
  60. package/dist/capabilities/scenarios.d.ts +1 -1
  61. package/dist/capability-facts.d.ts +15 -7
  62. package/dist/capability-facts.js +8 -3
  63. package/dist/config-catalog.js +9 -8
  64. package/dist/config-invariants.d.ts +23 -3
  65. package/dist/config-invariants.js +42 -0
  66. package/dist/config-provider.d.ts +33 -37
  67. package/dist/config-provider.js +51 -30
  68. package/dist/config-types.d.ts +21 -7
  69. package/dist/config.d.ts +33 -0
  70. package/dist/config.js +46 -16
  71. package/dist/delegated-session-owner.d.ts +4 -3
  72. package/dist/delegated-session-owner.js +1 -1
  73. package/dist/deployment-shape.d.ts +10 -9
  74. package/dist/deployment-shape.js +4 -4
  75. package/dist/device-enrollment.d.ts +41 -2
  76. package/dist/device-enrollment.js +27 -12
  77. package/dist/device-store.d.ts +58 -85
  78. package/dist/device-store.js +19 -49
  79. package/dist/device-ws-hub.js +2 -1
  80. package/dist/env-name-allowlist-knobs.d.ts +5 -4
  81. package/dist/exec-cut.d.ts +60 -0
  82. package/dist/exec-cut.js +36 -0
  83. package/dist/execution-lane-caps.d.ts +115 -105
  84. package/dist/execution-lane-caps.js +76 -82
  85. package/dist/execution-placement.d.ts +259 -0
  86. package/dist/execution-placement.js +199 -0
  87. package/dist/field-conflict.d.ts +3 -2
  88. package/dist/field-conflict.js +1 -0
  89. package/dist/hosted-posture.d.ts +2 -2
  90. package/dist/http/admission.js +8 -19
  91. package/dist/http/checkpoint-ctx.d.ts +21 -12
  92. package/dist/http/checkpoint-ctx.js +4 -2
  93. package/dist/http/claimed-run.d.ts +1 -1
  94. package/dist/http/durable-run-leg.js +9 -5
  95. package/dist/http/execution-context.d.ts +218 -0
  96. package/dist/http/execution-context.js +330 -0
  97. package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
  98. package/dist/http/memory-compliance-failure-reply.js +5 -0
  99. package/dist/http/memory-layer-reply.d.ts +30 -0
  100. package/dist/http/memory-layer-reply.js +24 -0
  101. package/dist/http/resume-legs.js +63 -36
  102. package/dist/http/retired-service-deps.d.ts +1 -1
  103. package/dist/http/retired-service-deps.js +1 -1
  104. package/dist/http/route-ctx.d.ts +14 -8
  105. package/dist/http/routes/adoption.js +1 -1
  106. package/dist/http/routes/background.d.ts +29 -1
  107. package/dist/http/routes/background.js +29 -2
  108. package/dist/http/routes/devices.d.ts +13 -19
  109. package/dist/http/routes/devices.js +21 -26
  110. package/dist/http/routes/memory-bundle.js +3 -0
  111. package/dist/http/routes/memory-compliance.js +8 -1
  112. package/dist/http/routes/memory-consolidation.js +12 -1
  113. package/dist/http/routes/memory-origin.js +14 -2
  114. package/dist/http/routes/memory-policy.js +5 -0
  115. package/dist/http/routes/session-sync.js +110 -15
  116. package/dist/http/routes/sessions.d.ts +6 -0
  117. package/dist/http/routes/sessions.js +143 -22
  118. package/dist/http/routes/side-query.d.ts +12 -4
  119. package/dist/http/routes/side-query.js +4 -5
  120. package/dist/http/routes/tasks.js +41 -33
  121. package/dist/http/server.d.ts +40 -44
  122. package/dist/http/server.js +13 -2
  123. package/dist/http/session-inherit-env.d.ts +3 -4
  124. package/dist/http/session-inherit-env.js +1 -1
  125. package/dist/http/wire-types.d.ts +8 -12
  126. package/dist/identity-source.d.ts +1 -1
  127. package/dist/identity-source.js +1 -1
  128. package/dist/index.d.ts +1 -0
  129. package/dist/lane-home-probe.d.ts +68 -42
  130. package/dist/lane-home-probe.js +53 -30
  131. package/dist/leader/wire.js +5 -4
  132. package/dist/memory-bundle-engine.d.ts +16 -9
  133. package/dist/memory-bundle-engine.js +29 -6
  134. package/dist/memory-operator-faces.d.ts +85 -30
  135. package/dist/memory-operator-faces.js +136 -30
  136. package/dist/memory-project-layer.d.ts +3 -21
  137. package/dist/memory-project-layer.js +11 -8
  138. package/dist/memory-scope-stores.d.ts +73 -0
  139. package/dist/memory-scope-stores.js +86 -0
  140. package/dist/memory-scope.d.ts +29 -5
  141. package/dist/memory-scope.js +16 -4
  142. package/dist/memory-sync-client.d.ts +70 -18
  143. package/dist/memory-sync-client.js +215 -117
  144. package/dist/memory-sync.d.ts +1 -1
  145. package/dist/memory-sync.js +3 -2
  146. package/dist/observability/cost-taxonomy.d.ts +2 -2
  147. package/dist/observability/fail-open.d.ts +12 -0
  148. package/dist/observability/fail-open.js +12 -0
  149. package/dist/observability/run-terminal.js +0 -1
  150. package/dist/orchestration/workflow-notify-journal.js +4 -4
  151. package/dist/org-memory-admission.d.ts +4 -3
  152. package/dist/org-memory-admission.js +6 -6
  153. package/dist/parked-decide.d.ts +34 -9
  154. package/dist/parked-decide.js +12 -19
  155. package/dist/parked-revive-surface.d.ts +12 -15
  156. package/dist/parked-revive-surface.js +3 -6
  157. package/dist/peer-seat.d.ts +13 -7
  158. package/dist/peer-seat.js +37 -3
  159. package/dist/plugins/adoption-log-sql.js +4 -4
  160. package/dist/plugins/approval-ask-store-file.d.ts +7 -0
  161. package/dist/plugins/approval-ask-store-file.js +11 -0
  162. package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
  163. package/dist/plugins/approval-ask-store-memory.js +12 -0
  164. package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
  165. package/dist/plugins/approval-ask-store-sql.js +44 -26
  166. package/dist/plugins/approval-nonce-store.js +4 -4
  167. package/dist/plugins/blob-backend.d.ts +4 -4
  168. package/dist/plugins/blob-backend.js +7 -7
  169. package/dist/plugins/breaker-state-sql.js +2 -2
  170. package/dist/plugins/caching-session-store.d.ts +6 -2
  171. package/dist/plugins/caching-session-store.js +9 -3
  172. package/dist/plugins/checkpoint-index-columns.js +2 -2
  173. package/dist/plugins/checkpoint-store-sql.d.ts +6 -5
  174. package/dist/plugins/checkpoint-store-sql.js +21 -23
  175. package/dist/plugins/device-store-sql.d.ts +25 -51
  176. package/dist/plugins/device-store-sql.js +68 -122
  177. package/dist/plugins/ensure-index.d.ts +1 -2
  178. package/dist/plugins/execution-placement-sql.d.ts +151 -0
  179. package/dist/plugins/execution-placement-sql.js +223 -0
  180. package/dist/plugins/file-history-store-sql.d.ts +9 -8
  181. package/dist/plugins/file-history-store-sql.js +9 -9
  182. package/dist/plugins/file-run-store.d.ts +6 -1
  183. package/dist/plugins/file-run-store.js +4 -0
  184. package/dist/plugins/fork-routing-session-store.d.ts +6 -0
  185. package/dist/plugins/fork-routing-session-store.js +16 -0
  186. package/dist/plugins/image-bake-store-sql.js +9 -9
  187. package/dist/plugins/image-index-sql.js +11 -11
  188. package/dist/plugins/leader-run-store-sql.js +4 -4
  189. package/dist/plugins/local-session-store.d.ts +149 -50
  190. package/dist/plugins/local-session-store.js +382 -107
  191. package/dist/plugins/mailbox-store-sql.d.ts +2 -1
  192. package/dist/plugins/mailbox-store-sql.js +4 -4
  193. package/dist/plugins/memory-engine-tidb.js +5 -5
  194. package/dist/plugins/memory-key-guards.d.ts +4 -0
  195. package/dist/plugins/memory-key-guards.js +1 -0
  196. package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
  197. package/dist/plugins/memory-run-store.d.ts +1 -1
  198. package/dist/plugins/memory-sync-store-tidb.js +3 -3
  199. package/dist/plugins/one-time-migrations.d.ts +117 -8
  200. package/dist/plugins/one-time-migrations.js +408 -38
  201. package/dist/plugins/org-delivery-quota-store.js +2 -2
  202. package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
  203. package/dist/plugins/outcome-ledger-sql.js +2 -2
  204. package/dist/plugins/permission-rule-store-sql.d.ts +17 -19
  205. package/dist/plugins/permission-rule-store-sql.js +29 -32
  206. package/dist/plugins/pg-pool.d.ts +7 -3
  207. package/dist/plugins/pg-session-storage.d.ts +31 -20
  208. package/dist/plugins/pg-session-storage.js +120 -52
  209. package/dist/plugins/remote-env-adb.d.ts +18 -19
  210. package/dist/plugins/remote-env-adb.js +91 -66
  211. package/dist/plugins/remote-env-device.d.ts +23 -31
  212. package/dist/plugins/remote-env-device.js +19 -17
  213. package/dist/plugins/remote-env-e2b.d.ts +27 -21
  214. package/dist/plugins/remote-env-e2b.js +91 -45
  215. package/dist/plugins/remote-env-file-error.d.ts +3 -1
  216. package/dist/plugins/remote-env-file-error.js +9 -3
  217. package/dist/plugins/remote-env-host.d.ts +31 -34
  218. package/dist/plugins/remote-env-host.js +91 -72
  219. package/dist/plugins/remote-env-k8s.d.ts +13 -29
  220. package/dist/plugins/remote-env-k8s.js +63 -55
  221. package/dist/plugins/remote-env-local-docker.d.ts +24 -12
  222. package/dist/plugins/remote-env-local-docker.js +49 -61
  223. package/dist/plugins/remote-env-ssh.d.ts +11 -19
  224. package/dist/plugins/remote-env-ssh.js +74 -57
  225. package/dist/plugins/remote-shell.d.ts +100 -3
  226. package/dist/plugins/remote-shell.js +166 -2
  227. package/dist/plugins/resume-anchor-store-sql.js +2 -2
  228. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  229. package/dist/plugins/retention-lane-store-sql.js +2 -2
  230. package/dist/plugins/retention-store-sql.d.ts +10 -7
  231. package/dist/plugins/retention-store-sql.js +13 -7
  232. package/dist/plugins/run-store-sql.d.ts +13 -3
  233. package/dist/plugins/run-store-sql.js +20 -15
  234. package/dist/plugins/schema-consistency.d.ts +21 -11
  235. package/dist/plugins/schema-consistency.js +15 -9
  236. package/dist/plugins/schema-drift-sentence.d.ts +27 -0
  237. package/dist/plugins/schema-drift-sentence.js +38 -0
  238. package/dist/plugins/schema-ensure-legs.d.ts +2 -3
  239. package/dist/plugins/schema-ensure-legs.js +2 -2
  240. package/dist/plugins/schema-live-columns.d.ts +1 -1
  241. package/dist/plugins/session-capture-record-store-sql.js +1 -1
  242. package/dist/plugins/session-fork.d.ts +54 -0
  243. package/dist/plugins/session-fork.js +38 -1
  244. package/dist/plugins/session-row-sql.d.ts +22 -0
  245. package/dist/plugins/session-row-sql.js +81 -0
  246. package/dist/plugins/session-rules-column.d.ts +1 -1
  247. package/dist/plugins/session-rules-column.js +1 -1
  248. package/dist/plugins/session-store.d.ts +1 -1
  249. package/dist/plugins/session-workspace-cell.d.ts +1 -1
  250. package/dist/plugins/session-workspace-cell.js +1 -1
  251. package/dist/plugins/shared-memory-store-sql.js +2 -2
  252. package/dist/plugins/sql-driver.d.ts +10 -5
  253. package/dist/plugins/sql-driver.js +6 -6
  254. package/dist/plugins/sql-errors.js +1 -1
  255. package/dist/plugins/store-backend.d.ts +5 -7
  256. package/dist/plugins/store-backend.js +23 -11
  257. package/dist/plugins/store-contracts.d.ts +25 -5
  258. package/dist/plugins/task-list-store-sql.js +11 -11
  259. package/dist/plugins/tidb-pool.d.ts +12 -7
  260. package/dist/plugins/tidb-pool.js +13 -7
  261. package/dist/plugins/tidb-session-storage.js +4 -4
  262. package/dist/plugins/tidb-session-store.d.ts +57 -26
  263. package/dist/plugins/tidb-session-store.js +127 -59
  264. package/dist/plugins/tool-result-store-sql.d.ts +5 -4
  265. package/dist/plugins/tool-result-store-sql.js +21 -13
  266. package/dist/plugins/user-input-ledger-sql.js +2 -2
  267. package/dist/plugins/workflow-journal-store-sql.js +5 -5
  268. package/dist/plugins/workflow-run-store-sql.js +19 -19
  269. package/dist/plugins/write-behind-counter.d.ts +2 -3
  270. package/dist/plugins/write-behind-counter.js +5 -5
  271. package/dist/project-memory.d.ts +9 -15
  272. package/dist/project-memory.js +5 -4
  273. package/dist/request-key-closure.js +1 -1
  274. package/dist/request-value-closure.d.ts +6 -7
  275. package/dist/request-value-closure.js +1 -3
  276. package/dist/resource-suspend.d.ts +14 -12
  277. package/dist/resource-suspend.js +1 -1
  278. package/dist/resource-window.d.ts +4 -3
  279. package/dist/run-local.d.ts +6 -0
  280. package/dist/run-local.js +34 -35
  281. package/dist/runs.d.ts +10 -5
  282. package/dist/runs.js +52 -66
  283. package/dist/security.d.ts +38 -12
  284. package/dist/security.js +8 -2
  285. package/dist/server-secret-env.d.ts +9 -5
  286. package/dist/session-children-retire.d.ts +27 -9
  287. package/dist/session-children-retire.js +9 -5
  288. package/dist/session-incarnation.d.ts +20 -10
  289. package/dist/session-incarnation.js +5 -3
  290. package/dist/session-policy-wire.d.ts +1 -1
  291. package/dist/session-row.d.ts +114 -5
  292. package/dist/session-row.js +55 -5
  293. package/dist/session-titler.d.ts +2 -2
  294. package/dist/sql-engine-posture.d.ts +1 -1
  295. package/dist/sql-engine-posture.js +1 -1
  296. package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
  297. package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
  298. package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
  299. package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
  300. package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
  301. package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
  302. package/dist/task-a2a.d.ts +1 -1
  303. package/dist/task-a2a.js +5 -6
  304. package/dist/task-cwd.d.ts +6 -1
  305. package/dist/task-mcp.d.ts +22 -9
  306. package/dist/task-mcp.js +17 -9
  307. package/dist/terminal.d.ts +27 -0
  308. package/dist/terminal.js +6 -0
  309. package/dist/tool-approval.d.ts +6 -0
  310. package/dist/tool-approval.js +8 -1
  311. package/dist/trace/project.d.ts +1 -0
  312. package/dist/trace/project.js +1 -0
  313. package/dist/trace/redact.d.ts +3 -1
  314. package/dist/trace/redact.js +80 -28
  315. package/dist/trace/self-minted-wire.d.ts +169 -2
  316. package/dist/trace/self-minted-wire.js +54 -1
  317. package/dist/url-refusal.d.ts +1 -1
  318. package/dist/web-admin-client/apply-effective.d.ts +17 -3
  319. package/dist/web-admin-client/apply-effective.js +20 -10
  320. package/dist/web-admin-client/candidate-gate.d.ts +11 -7
  321. package/dist/web-admin-client/candidate-gate.js +1 -1
  322. package/dist/web-admin-client/http-client.d.ts +5 -4
  323. package/dist/web-admin-client/http-client.js +2 -2
  324. package/dist/web-admin-client/read-warnings.d.ts +7 -17
  325. package/dist/web-admin-client/read-warnings.js +5 -9
  326. package/dist/web-admin-client/skills-mcp.js +3 -2
  327. package/dist/web-admin-client/types.d.ts +6 -0
  328. package/package.json +3 -3
  329. package/wire-changes/server@7.139.0.json +348 -0
  330. package/wire-changes/server@7.140.0.json +184 -0
  331. package/dist/http/device-placement.d.ts +0 -175
  332. package/dist/http/device-placement.js +0 -145
@@ -2,7 +2,13 @@ export const LANE_HOME_PROBE_MARKER = "sema-lane-home=";
2
2
  export const LANE_HOME_PROBE_COMMAND = `printf '\\n${LANE_HOME_PROBE_MARKER}%s\\n' "$HOME"`;
3
3
  const SHOWN_MAX = 256;
4
4
  const shown = (raw) => JSON.stringify(raw.length > SHOWN_MAX ? `${raw.slice(0, SHOWN_MAX)}…` : raw);
5
- const comparable = (p) => (p.length > 1 ? p.replace(/\/+$/, "") : p);
5
+ const isAbsoluteHome = (p, paths) => (paths === "win32" ? /^[A-Za-z]:[\\/]/.test(p) || /^[\\/]{2}[^\\/]/.test(p) : p.startsWith("/"));
6
+ const comparable = (p, paths) => {
7
+ if (paths === "posix")
8
+ return p.length > 1 ? p.replace(/\/+$/, "") : p;
9
+ const q = p.replace(/\//g, "\\").toLowerCase();
10
+ return /^[a-z]:\\$/.test(q) ? q : q.replace(/\\+$/, "");
11
+ };
6
12
  function markedHome(stdout) {
7
13
  const lines = stdout.split("\n").map((l) => l.replace(/\r$/, ""));
8
14
  const marked = lines.flatMap((l, i) => (l.startsWith(LANE_HOME_PROBE_MARKER) ? [i] : []));
@@ -13,34 +19,45 @@ function markedHome(stdout) {
13
19
  return { why: "the probe output holds more than one home line or text after it, so it cannot be read as one path" };
14
20
  return { home: lines[at].slice(LANE_HOME_PROBE_MARKER.length) };
15
21
  }
16
- function readLaneHome(probe) {
22
+ function readLaneHome(probe, paths) {
17
23
  if (!probe.ok)
18
24
  return { kind: "unread", reason: probe.reason };
19
- const marked = markedHome(probe.stdout);
20
- if ("why" in marked)
21
- return { kind: "unread", reason: marked.why };
22
- return marked.home.startsWith("/") ? { kind: "home", home: marked.home } : { kind: "not_absolute", value: marked.home };
25
+ let home;
26
+ if ("value" in probe)
27
+ home = probe.value;
28
+ else {
29
+ const marked = markedHome(probe.stdout);
30
+ if ("why" in marked)
31
+ return { kind: "unread", reason: marked.why };
32
+ home = marked.home;
33
+ }
34
+ return isAbsoluteHome(home, paths) ? { kind: "home", home } : { kind: "not_absolute", value: home };
23
35
  }
24
- export function judgeLaneHome(lane, declared, probe) {
25
- const head = `REMOTE_EXEC_HOME_DIR=${shown(declared)} is the home "~/" permission rules and the engine's home-anchored read-deny rows are placed under on the ${lane} execution lane`;
26
- const reading = readLaneHome(probe);
36
+ export function judgeLaneHome(lane, claim, probe, paths = "posix") {
37
+ const declared = claim.source === "declared";
38
+ const head = declared
39
+ ? `REMOTE_EXEC_HOME_DIR=${shown(claim.home)} is the home "~/" permission rules and the engine's home-anchored read-deny rows are placed under on the ${lane} execution lane`
40
+ : `${shown(claim.home)} — the ${lane} execution lane's own home, used because REMOTE_EXEC_HOME_DIR is unset — is the home "~/" permission rules and the engine's home-anchored read-deny rows are placed under`;
41
+ const unconfirmed = declared ? "the declaration cannot be confirmed" : "that home cannot be confirmed";
42
+ const reading = readLaneHome(probe, paths);
27
43
  if (reading.kind === "unread") {
28
44
  return {
29
- refusal: `${head}, but the home of this execution environment could not be read (${reading.reason}) — the declaration cannot be confirmed, so this environment is not started. Fix the lane, or unset REMOTE_EXEC_HOME_DIR (home-relative rules are then refused at submission instead).`,
45
+ refusal: `${head}, but the home of this execution environment could not be read (${reading.reason}) — ${unconfirmed}, so this environment is not started. ${declared ? "Fix the lane, or unset REMOTE_EXEC_HOME_DIR." : "Fix the lane so the environment answers its $HOME."}`,
30
46
  answered: false,
31
47
  };
32
48
  }
33
49
  if (reading.kind === "not_absolute") {
34
50
  return {
35
- refusal: `${head}, but this execution environment reports HOME=${shown(reading.value)}, not an absolute path — the declaration cannot be confirmed, so this environment is not started. Give the environment's user a home (HOME), or unset REMOTE_EXEC_HOME_DIR.`,
51
+ refusal: `${head}, but this execution environment reports HOME=${shown(reading.value)}, not an absolute path — ${unconfirmed}, so this environment is not started. ${declared ? "Give the environment's user a home (HOME), or unset REMOTE_EXEC_HOME_DIR." : "Give the environment's user a home (HOME)."}`,
36
52
  answered: true,
37
53
  };
38
54
  }
39
- if (comparable(reading.home) === comparable(declared))
55
+ if (comparable(reading.home, paths) === comparable(claim.home, paths))
40
56
  return undefined;
57
+ const measured = shown(reading.home);
41
58
  return {
42
- refusal: `${head}, but its commands run with HOME=${shown(reading.home)} — rules would guard ${shown(declared)} while ${shown(reading.home)} stays readable and writable, ` +
43
- `so this environment is not started. Set REMOTE_EXEC_HOME_DIR to ${shown(reading.home)}, or run the environment as the user whose home is ${shown(declared)}.`,
59
+ refusal: `${head}, but its commands run with HOME=${measured} — rules would guard ${shown(claim.home)} while ${measured} stays readable and writable, ` +
60
+ `so this environment is not started. Set REMOTE_EXEC_HOME_DIR to ${measured}${declared ? " or remove it" : ""}, or make the environment's HOME read ${shown(claim.home)}.`,
44
61
  answered: true,
45
62
  };
46
63
  }
@@ -52,37 +69,43 @@ export function buildHomeAbsentNote(lane, cause, remedy) {
52
69
  }
53
70
  const DECLARE_ARG = "REMOTE_EXEC_HOME_DIR=<the absolute path the environment's $HOME reads>";
54
71
  export const DECLARE_HOME_REMEDY = `Declare the home: ${DECLARE_ARG}`;
72
+ export const LANE_HOME_UNMEASURED_EVENT = "execution_lane_home_unmeasured";
73
+ export function buildHomeUnmeasuredNote(lane, declared) {
74
+ return (`the ${lane} lane cannot read its execution environment's home, so REMOTE_EXEC_HOME_DIR=${shown(declared)} is taken as declared, not measured: ` +
75
+ `"~/" permission rules and the engine's home-anchored read-deny rows are placed under it. If the environment's $HOME is another directory, those rules guard ${shown(declared)} ` +
76
+ `while the real home stays readable and writable — keep REMOTE_EXEC_HOME_DIR equal to the $HOME the environment's commands see.`);
77
+ }
55
78
  export class LaneHomeSeat {
56
79
  measured;
57
80
  lane;
58
- declared;
59
- verifiesDeclared;
81
+ claim;
60
82
  onAbsent;
61
- constructor(options) {
62
- this.lane = options.lane;
63
- this.declared = options.declared;
64
- this.verifiesDeclared = options.verifiesDeclared;
65
- this.onAbsent = options.onAbsent;
83
+ paths;
84
+ constructor(lane, config, paths = "posix") {
85
+ this.lane = lane;
86
+ this.paths = paths;
87
+ this.claim = config.homeDir === undefined ? undefined : { home: config.homeDir, source: config.homeDirSource ?? "declared" };
88
+ this.onAbsent = config.onHomeAbsent;
66
89
  }
67
90
  get home() {
68
- return this.declared ?? this.measured;
91
+ return this.claim?.home ?? this.measured;
69
92
  }
70
93
  get asks() {
71
- return this.declared === undefined ? this.measured === undefined : this.verifiesDeclared;
94
+ return this.claim !== undefined || this.measured === undefined;
72
95
  }
73
96
  settle(probe) {
74
- if (this.declared !== undefined)
75
- return this.verifiesDeclared ? judgeLaneHome(this.lane, this.declared, probe) : undefined;
76
- const reading = readLaneHome(probe);
97
+ if (this.claim !== undefined)
98
+ return judgeLaneHome(this.lane, this.claim, probe, this.paths);
99
+ const reading = readLaneHome(probe, this.paths);
77
100
  if (reading.kind === "home") {
78
101
  this.measured = reading.home;
79
102
  return undefined;
80
103
  }
81
104
  const because = reading.kind === "unread" ? `could not be read (${reading.reason})` : `reads ${shown(reading.value)}, not an absolute path`;
82
- const remedy = this.verifiesDeclared
83
- ? "Give the environment's user an absolute HOME (a declared REMOTE_EXEC_HOME_DIR is checked against it, so declaring cannot stand in for it)."
84
- : `Give the environment's user an absolute HOME, or declare it: ${DECLARE_ARG}.`;
85
- this.onAbsent?.({ provider: this.lane, note: buildHomeAbsentNote(this.lane, `REMOTE_EXEC_HOME_DIR is unset and the environment's own $HOME ${because}`, remedy) });
105
+ this.onAbsent?.({
106
+ provider: this.lane,
107
+ note: buildHomeAbsentNote(this.lane, `REMOTE_EXEC_HOME_DIR is unset and the environment's own $HOME ${because}`, "Give the environment's user an absolute HOME (a declared REMOTE_EXEC_HOME_DIR is checked against it, so declaring cannot stand in for it)."),
108
+ });
86
109
  return undefined;
87
110
  }
88
111
  }
@@ -9,7 +9,8 @@ import { leaderEntryRefusal, leaderRunEntry } from "./run-entry.js";
9
9
  import { buildCheckpointCtx } from "../http/checkpoint-ctx.js";
10
10
  import { serviceVersion } from "../service-version.js";
11
11
  import { RemoteContainerExecutionEnv } from "../plugins/remote-env-e2b.js";
12
- import { E2B_SANDBOX_HOME } from "../execution-lane-caps.js";
12
+ import { buildLaneHomeClaim } from "../execution-lane-caps.js";
13
+ const e2bBaseTemplateHomeSeat = buildLaneHomeClaim({ remoteExec: { provider: "e2b" } });
13
14
  import { createDurableAskPolicy } from "../approval.js";
14
15
  import { gitSubprocessEnv } from "../server-secret-env.js";
15
16
  import { presignS3Url } from "../plugins/s3-presign.js";
@@ -366,7 +367,7 @@ export function createLeaderRunner(cfg) {
366
367
  }
367
368
  if (!cfg.e2bApiKey)
368
369
  throw new Error("leader wire: no envFactory+s3 (factory mode) and no e2bApiKey (static mode)");
369
- const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, homeDir: E2B_SANDBOX_HOME });
370
+ const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, ...e2bBaseTemplateHomeSeat });
370
371
  if (!(await env.connect()).ok)
371
372
  throw new Error(`connect failed for ${sub.workerId}`);
372
373
  await sh(env)(`${body.seedCmd}; cd ${repo}; git checkout -q -b ${sub.branch}`);
@@ -399,7 +400,7 @@ export function createLeaderRunner(cfg) {
399
400
  }
400
401
  if (!cfg.e2bApiKey)
401
402
  throw new Error("leader wire: no envFactory and no e2bApiKey");
402
- const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, homeDir: E2B_SANDBOX_HOME });
403
+ const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, ...e2bBaseTemplateHomeSeat });
403
404
  if (!(await env.connect()).ok) {
404
405
  await env.destroy().catch(() => { });
405
406
  throw new Error("integ connect failed");
@@ -439,7 +440,7 @@ export function createLeaderRunner(cfg) {
439
440
  else {
440
441
  if (!cfg.e2bApiKey)
441
442
  throw new Error("leader wire: repair-loop grader needs an envFactory or e2bApiKey");
442
- const e2b = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, homeDir: E2B_SANDBOX_HOME });
443
+ const e2b = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, ...e2bBaseTemplateHomeSeat });
443
444
  if (!(await e2b.connect()).ok) {
444
445
  await e2b.destroy().catch(() => { });
445
446
  throw new Error("repair-loop grader connect failed");
@@ -4,11 +4,18 @@
4
4
  * ## 为什么需要这个模块(而不是在 main.ts 里直接 new)
5
5
  *
6
6
  * 本仓**没有**一个长命的 `MemoryEngine` 实例:`boot/stores.ts` 装配出来的 `memoryEngine` 是
7
- * `{ backend, root }` 二元组,真正的引擎由 **core 的 Runner 每任务现构**
7
+ * 记忆作用域店(`memory-scope-stores.ts`:部署的店 + 引擎根 + 「一层住哪只店」的唯一读者),真正的引擎由 **core 的 Runner 每任务现构**
8
8
  * (`core/runner/prepare-memory.js`),而且构出来的 `memoryDir` 是**按任务的 scope 平面**决定的
9
9
  * (personal / project / dual-root 三形,还要看仓根、项目标记、pinned 目录)。
10
10
  * 也就是说「这个部署的那一个记忆引擎」这个东西**在本仓不存在** —— HTTP 面若要一个引擎,必须自己构。
11
11
  *
12
+ * ## 引擎建在哪只店上:包点名的层住的那只
13
+ * 导出按请求的 `scopes` 定店,导入按包自己的 `bundle.scopes` 定店(core 的整包判决保证包里每一条的层都在 `bundle.scopes` 里 —— 自洽是它的校验项);
14
+ * 几层分住两只店 ⇒ 拒(`request.memory_layer`):一只包是**一只店**单锁复合面里的一个 epoch,两只店封不出一只包。规则唯一属主
15
+ * `memory-scope-stores.ts` 的 {@link memoryStoreForRequest}。`bundle.scopes` 读不成「非空的非空串数组」的包,本来就过不了 core 的整包判决
16
+ * (结构项第一条),交部署的店那只引擎去判 —— 拒是包本身的函数,哪只引擎判都一样,什么都不落。
17
+ * 修前两面都在部署的店上建引擎:目录钉住的部署上,类型化个人层的条目在个人挂载上的另一只店里 —— 导出的包里没有会话写的条目,导入的落在会话不读的店。
18
+ *
12
19
  * ## 为什么自己构是安全的:这两个面是 **backend-scoped**,不碰 `memoryDir`
13
20
  *
14
21
  * 亲读 core 5.40.0 的 `memory-engine/engine.js`(不信 JSDoc,读实现):
@@ -41,7 +48,9 @@
41
48
  * `memory.export_incomplete` —— 那是诚实的运行期拒,附录 A 单列一条。绝不在这里回落到「用通用读面拼
42
49
  * 一个包」:core 明写那正是它拒绝生产的形(a governance-less export is the laundering shape)。
43
50
  */
44
- import { type MemoryBackend, type MemoryExportBundle, type MemoryImportReport, type SessionCaptureRecordStore } from "@sema-agent/core";
51
+ import { type MemoryExportBundle, type MemoryImportReport } from "@sema-agent/core";
52
+ import { type MemoryScopeStores } from "./memory-scope-stores.js";
53
+ import type { SessionCaptureRecordSource } from "./plugins/store-backend.js";
45
54
  /** 两口 HTTP 面消费的窄能力面(`ServiceDeps.memoryBundle{Export,Import}` 的实参来源)。 */
46
55
  export interface MemoryBundleFaces {
47
56
  exportScopes: (scopes: readonly string[]) => Promise<MemoryExportBundle>;
@@ -51,17 +60,15 @@ export interface MemoryBundleFaces {
51
60
  }) => Promise<MemoryImportReport>;
52
61
  }
53
62
  /**
54
- * 在**已装配的记忆后端**上建 bundle 两面。命名照 CLAUDE.md 工厂律:返回的是带行为的活对象 ⇒ `create*`。
63
+ * 在**记忆作用域店**上建 bundle 两面。命名照 CLAUDE.md 工厂律:返回的是带行为的活对象 ⇒ `create*`。
55
64
  *
56
- * `memoryDir` = 引擎的**挂载平面**(`memoryMountRootOf(backend, root)` 单铸点;全仓自构引擎同一条规则,
65
+ * 店:见文件头「引擎建在哪只店上」;一只店一只引擎。
66
+ * `memoryDir` = 那只店的**挂载平面**(`memoryMountRootOf(store, root)` 单铸点;全仓自构引擎同一条规则,
57
67
  * 由 `test/memory-layout-plane.test.ts` 的归一门咬住)。见文件头:这两条路径**不读它**(机器钉在
58
68
  * `test/memory-bundle-engine.test.ts`:给一个不存在的 `memoryDir` 也照样工作),传对的那一只是为了
59
69
  * 万一 core 日后真用上时,它拿到的是本部署真正的挂载平面,而不是高一层的配置根。
60
70
  */
61
- export declare function createMemoryBundleFaces(store: {
62
- backend: MemoryBackend;
63
- root: string;
64
- }, opts?: {
65
- captureRecordStore?: SessionCaptureRecordStore;
71
+ export declare function createMemoryBundleFaces(stores: MemoryScopeStores, opts?: {
72
+ captureRecords?: SessionCaptureRecordSource;
66
73
  }): MemoryBundleFaces | undefined;
67
74
  //# sourceMappingURL=memory-bundle-engine.d.ts.map
@@ -1,13 +1,36 @@
1
1
  import { MemoryEngine } from "@sema-agent/core";
2
2
  import { memoryMountRootOf } from "./memory-scope.js";
3
- export function createMemoryBundleFaces(store, opts) {
4
- const b = store.backend;
5
- if (typeof b.exportSnapshotOf !== "function" || typeof b.importBundleCommit !== "function")
3
+ import { memoryStoreForRequest } from "./memory-scope-stores.js";
4
+ import { captureRecordStoreOf } from "./memory-operator-faces.js";
5
+ export function createMemoryBundleFaces(stores, opts) {
6
+ if (!carriesBundleComposite(stores.backend))
6
7
  return undefined;
7
- const engine = new MemoryEngine({ backend: store.backend, memoryDir: memoryMountRootOf(store.backend, store.root), ...(opts?.captureRecordStore !== undefined ? { captureRecordStore: opts.captureRecordStore } : {}) });
8
+ const engines = new Map();
9
+ const engineOf = (store) => {
10
+ const known = engines.get(store);
11
+ if (known !== undefined)
12
+ return known;
13
+ if (!carriesBundleComposite(store))
14
+ throw new Error("the memory store that holds these layers implements no v2-c bundle composite (exportSnapshotOf / importBundleCommit) — a bundle is never assembled outside one");
15
+ const records = captureRecordStoreOf(opts?.captureRecords, store);
16
+ const engine = new MemoryEngine({ backend: store, memoryDir: memoryMountRootOf(store, stores.root), ...(records !== undefined ? { captureRecordStore: records } : {}) });
17
+ engines.set(store, engine);
18
+ return engine;
19
+ };
8
20
  return {
9
- exportScopes: (scopes) => engine.exportMemoryScopes(scopes),
10
- importBundle: (bundle, opts) => engine.importMemoryBundle(bundle, opts),
21
+ exportScopes: async (scopes) => engineOf(memoryStoreForRequest(stores, scopes)).exportMemoryScopes(scopes),
22
+ importBundle: async (bundle, opts) => {
23
+ const layers = bundleLayersOf(bundle);
24
+ return engineOf(layers.length > 0 ? memoryStoreForRequest(stores, layers) : stores.backend).importMemoryBundle(bundle, opts);
25
+ },
11
26
  };
12
27
  }
28
+ function carriesBundleComposite(store) {
29
+ const b = store;
30
+ return typeof b.exportSnapshotOf === "function" && typeof b.importBundleCommit === "function";
31
+ }
32
+ function bundleLayersOf(bundle) {
33
+ const scopes = typeof bundle === "object" && bundle !== null ? bundle.scopes : undefined;
34
+ return Array.isArray(scopes) && scopes.length > 0 && scopes.every((s) => typeof s === "string" && s.length > 0) ? scopes : [];
35
+ }
13
36
  //# sourceMappingURL=memory-bundle-engine.js.map
@@ -5,9 +5,26 @@
5
5
  * ## 为什么是一个模块而不是 main.ts 里直接 new
6
6
  *
7
7
  * 同 `memory-bundle-engine.ts` 的那句话:本仓**没有**一个长命的 `MemoryEngine` 实例 —— `boot/stores.ts`
8
- * 装配出来的 `memoryEngine` 是 `{ backend, root }` 二元组,真引擎由 core 的 Runner **每任务现构**
9
- * (按任务的 scope 平面决定 `memoryDir`)。HTTP 面若要一个引擎,必须自己构;构的判断写在这里,main.ts
10
- * 只调用与转接。
8
+ * 装配出来的 `memoryEngine` 是记忆作用域店(`memory-scope-stores.ts`:部署的店 + 引擎根 + 「一层住哪只店」的唯一读者),
9
+ * 真引擎由 core 的 Runner **每任务现构**(按任务的 scope 平面决定店与 `memoryDir`)。HTTP 面若要一个引擎,必须自己构;构的判断写在这里,
10
+ * main.ts 只调用与转接。
11
+ *
12
+ * ## 引擎建在哪只店上:动词点名的层住的那只(一层的店只问记忆作用域店)
13
+ * 每个动词先定店,再在那只店上建(或复用)一只引擎 —— 一只店一只引擎,`memoryDir` = 那只店的挂载平面、控制面 = 那只店自带的。
14
+ * 店怎么定只有一条规则({@link memoryStoreForRequest}):请求点名的层(`select.scope`、`expectedScopes`、外源列表的 `scopes`、
15
+ * 不点名层的动词的层座 `{ layer }`)共住的那一只;不点名层 ⇒ 本部署点名的层与部署的店共处的那一只,分住两只就拒(`request.memory_layer`)。
16
+ * 修前三只工厂各在**部署的店**上建一只引擎 —— 目录钉住的部署上,类型化个人层(`user:` / `userproj:` / `org:`)的会话条目在个人挂载上的
17
+ * 另一只店里,擦的、查的、清标的都是会话不读的那只店。
18
+ *
19
+ * 会话 id 的两只动词不点名层(会话的写家在哪只店由它各条腿的任务根定,服务端没有存;一只会话可以跨两只店):
20
+ * · 会话记忆状态读**本部署的每一只店**(`memoryStoresOfDeployment`,至多两只),逐店的答案按 {@link foldPlaneStatuses} 折成一份;
21
+ * · 按会话抹除(`{ sessionId }` 选择子)落部署的店,见下一节的护栏。
22
+ *
23
+ * ## 抹除只在部署的店上执行({@link MemoryErasureStoreUnjudged})
24
+ * 抹除 `requestId` 的幂等判(重放收敛、同 id 换了选择子 ⇒ `memory.erasure_selector_mismatch`)记在**每只店自己的**证据链上,引擎今天没有
25
+ * 跨店的请求身份、也没有按 `requestId` 读锚的公开面;本层不另记一本请求账(第二真源)。所以本服务只在**一只**店上执行抹除 —— 部署的店,
26
+ * 它的证据链就是本部署唯一的判官:请求落到别的店(点名的层住在个人挂载那只店),或按会话抹除而这只会话在别的店里有贡献(或那只店的账读不出)
27
+ * ⇒ 409 拒,什么都不删。🚧 引擎给出部署级的抹除请求身份后,这条护栏删除、各店照常执行(钉在 `test/memory-project-scope.test.ts` ⑩)。
11
28
  *
12
29
  * ## 控制面归属:为什么 `controlPlaneRoot` 缺席就整口不挂(F-9 裁)
13
30
  *
@@ -46,6 +63,8 @@
46
63
  * 不是一回事(附录 A 两条分列)。
47
64
  */
48
65
  import { type EntryProvenanceAccount, type MemoryBackend, type MemoryEntryOrigin, type MemoryErasureAttestation, type OriginClearanceRow, type SessionCaptureRecordStore, type SessionMemoryStatus } from "@sema-agent/core";
66
+ import { type MemoryScopeStores } from "./memory-scope-stores.js";
67
+ import type { SessionCaptureRecordSource } from "./plugins/store-backend.js";
49
68
  /**
50
69
  * 控制面归属判据 —— 三个记忆操作面(合规两口 / 外源标记三口 / consolidation 阀门的 D1 拒启门)共用的
51
70
  * **同一只**谓词:backend 的面上带**非空** `controlPlaneRoot` 才算归属在案。空串与缺席同判「不归属」:
@@ -54,11 +73,22 @@ import { type EntryProvenanceAccount, type MemoryBackend, type MemoryEntryOrigin
54
73
  * 「逐字同源」成为结构事实而不是手抄承诺(merge-rescan 746 C-1:main.ts 手抄版漏了空串臂)。
55
74
  */
56
75
  export declare function backendOwnsControlPlane(backend: unknown): boolean;
76
+ /**
77
+ * 一只店的 capture opt-out 记录店 —— 按**这只店的控制面**向记录源取(`StoreBackend.sessionCaptureRecords()` 的按平面取用;
78
+ * 会话装配向同一只源问的也是它那只平面的控制面,core `prepare-memory` 的 `memoryCaptureRecordStore({ controlDir })`)。
79
+ * 店带控制面归属 ⇒ 问那一只控制面(个人店 ⇒ 个人平面的记录,部署的店 ⇒ 部署那一只);不带(SQL 孪生)⇒ 不指名(SQL 源本就不按平面分)。
80
+ * 修前操作面引擎一律拿部署平面那一只:个人店上的整理会读错名册(看不见只在个人平面登记 opt-out 的会话)。
81
+ */
82
+ export declare function captureRecordStoreOf(source: SessionCaptureRecordSource | undefined, store: MemoryBackend): SessionCaptureRecordStore | undefined;
83
+ /** 不点名层的动词(条目 id / 会话 id / 店级账本)的**层座**:点名一层 ⇒ 动词答在这一层住的那只店上(这一层只用来定店)。 */
84
+ export interface MemoryLayerSeat {
85
+ readonly layer: string;
86
+ }
57
87
  /** 两口 HTTP 面消费的窄能力面(`ServiceDeps.memoryCompliance` 的实参来源)。 */
58
88
  export interface MemoryComplianceFaces {
59
89
  /** 单条出处账。core 的失败姿态原样穿过:控制面损坏 ⇒ `ControlPlaneCorruptError`(fail-closed,
60
90
  * 绝不在一个完整性未知的账上拼一个答案);能力缺席 ⇒ 三值 `capability-absent`,**不是**抛。 */
61
- provenanceOf: (entryId: string) => Promise<EntryProvenanceAccount>;
91
+ provenanceOf: (entryId: string, at?: MemoryLayerSeat) => Promise<EntryProvenanceAccount>;
62
92
  /**
63
93
  * 抹除。入参 `unknown`:调用方递交的是未校验的对象,三选一选择子的整体判决归 core
64
94
  * (`erasureRequestInvalid` 是它的单一属主面)—— 在本层抄一遍就是第二真源。
@@ -69,14 +99,23 @@ export interface MemoryComplianceFaces {
69
99
  * 都得是集内成员,判在解析之后、店锁之内;违者整单拒 `config.memory_erasure_scope`,拒句不带数、不带 id、不带 scope(集外 id
70
100
  * 与从没存在过的 id 同句,不是存在性神谕)。本层不另设信封:一只只读得到 `{ scope }` 选择子字面量的信封判不了 `ids` /
71
101
  * `sessionId` 两腿、只能整拒,而且让「哪些 scope 能删」有两个答者。集随**入参**走(与 `requestId` / `select` 同一个对象),
72
- * 本面没有第二个形参。
102
+ * 授权集也是定店的那一只读数之一(选择子不点名 scope 时,集里的层共住的那只店;见文件头「引擎建在哪只店上」)。
73
103
  *
74
104
  * 今天谁传集:operator 面原样递交调用方的体(调用方自己写的 `expectedScopes` = 它自己收窄自己);路由不替 operator 铸集 ——
75
105
  * 本仓没有任何授权源能对一个 operator 说「你只能动这些 scope」(`routes/memory-policy.ts` 的 `gateMemoryScope`:operator 支在查
76
106
  * 目录之前就 allow;`org-memory-admission.ts`:v1 不中央收窄 operator 声明的 scope)。拿 org 目录的 grant 集去凑一个集就是在本层
77
107
  * 发明第二套授权语义,与 `gateMemoryScope` 对同一个身份给出相反答案。会话自助面的选择子由路径铸,不带集。
78
108
  */
79
- erase: (input: unknown) => Promise<MemoryErasureAttestation>;
109
+ erase: (input: unknown, at?: MemoryLayerSeat) => Promise<MemoryErasureAttestation>;
110
+ }
111
+ /**
112
+ * 本服务的「这次抹除不在本版受理的那只店上」拒(409 `memory.erasure_store_unjudged`):请求本身合法,是本部署此刻判不了同一个 `requestId`
113
+ * 跨店的幂等(见文件头「抹除只在部署的店上执行」)。什么都没删、什么都没记。句子不带层键、路径或任何值(两受众同一句;会话所有者受众另有固定句)。
114
+ * 🚧 引擎的部署级抹除请求身份到货后,本类连同抛它的两处删除。
115
+ */
116
+ export declare class MemoryErasureStoreUnjudged extends Error {
117
+ readonly code: "memory.erasure_store_unjudged";
118
+ constructor();
80
119
  }
81
120
  /**
82
121
  * **选择子替身**的拦截谓词(codex 交叉复审 [critical],亲验复现后修 —— 复现器与结论逐条在
@@ -111,10 +150,11 @@ export interface MemoryComplianceFaces {
111
150
  */
112
151
  export declare function erasureInputSmugglesPrototypeKey(input: unknown): boolean;
113
152
  /**
114
- * 在**已装配的记忆后端**上建合规两面。命名照 CLAUDE.md 工厂律:返回的是带行为的活对象 ⇒ `create*`。
153
+ * 在**记忆作用域店**上建合规两面。命名照 CLAUDE.md 工厂律:返回的是带行为的活对象 ⇒ `create*`。
115
154
  *
116
- * `memoryDir` = 引擎的**挂载平面**(`memoryMountRootOf(backend, root)` 单铸点:后端钉了 `directoryRoot`
117
- * 就是它 —— file 腿 = `<配置根>/memory`;两只 SQL 孪生不钉 ⇒ 回到配置根,读数逐字节不变)。
155
+ * 店:出处按层座定;抹除按选择子的 `scope` / `expectedScopes` 定(会话自助面由路径铸选择子,用层座)—— 见文件头。
156
+ * `memoryDir` = 那只店的**挂载平面**(`memoryMountRootOf(store, root)` 单铸点:店钉了 `directoryRoot`
157
+ * 就是它 —— file 腿 = `<配置根>/memory`,个人店 = 个人挂载;两只 SQL 孪生不钉 ⇒ 回到配置根,读数逐字节不变)。
118
158
  *
119
159
  * 🔴 **不是 `memoryEngine.root`**(2026 提货批订正,亲读 core 推翻旧注):旧注写着「这两条路径不读它」,
120
160
  * 而实装里 `erase` 的派生索引清扫(`engine.js` 的 `sweepErasedIndexLines`)与 `clearEntryOrigin` 的
@@ -123,10 +163,7 @@ export declare function erasureInputSmugglesPrototypeKey(input: unknown): boolea
123
163
  * **静默**:扫一棵不存在的树 ⇒ ENOENT ⇒ 跳过 ⇒ 零残留可报,而真正的 `MEMORY.md` 里还留着被抹条目的
124
164
  * 名字,收执却显示干净。机器钉:`test/memory-operator-faces.test.ts` 的「[ref] 提货」两格。
125
165
  */
126
- export declare function createMemoryComplianceFaces(store: {
127
- backend: MemoryBackend;
128
- root: string;
129
- },
166
+ export declare function createMemoryComplianceFaces(stores: MemoryScopeStores,
130
167
  /**
131
168
  * 引擎的 **advisory incident 座**(core `MemoryEngineOptions.onIncident`)。接它不是锦上添花:
132
169
  * 抹除腿上有一条**只走这个座**的码 —— `memory.erasure_index_residue`(engine.js)。它说的是
@@ -143,7 +180,7 @@ opts?: {
143
180
  onIncident?: (err: Error & {
144
181
  code?: string;
145
182
  }) => void;
146
- captureRecordStore?: SessionCaptureRecordStore;
183
+ captureRecords?: SessionCaptureRecordSource;
147
184
  }): MemoryComplianceFaces | undefined;
148
185
  /** 件② 三口 HTTP 面消费的窄能力面(`ServiceDeps.memoryOriginFace` 的实参来源)。 */
149
186
  export interface MemoryOriginFaces {
@@ -164,12 +201,12 @@ export interface MemoryOriginFaces {
164
201
  }>>;
165
202
  /** §13-4② 读半场:清标审计账(**同步** —— core 的 `listOriginClearances` 就是一次严格 sidecar 读;
166
203
  * 账本损坏 ⇒ `ControlPlaneCorruptError`,fail-closed,绝不回半张表)。 */
167
- listClearances: () => OriginClearanceRow[];
204
+ listClearances: (at?: MemoryLayerSeat) => OriginClearanceRow[];
168
205
  /** §13-4② 写半场:审计化的 UN-MARK 阀门。拒因族是 core 的**闭集码**,本层零翻译原样上抛。 */
169
206
  clear: (entryId: string, input: {
170
207
  requestId: string;
171
208
  reason: string;
172
- }) => Promise<{
209
+ }, at?: MemoryLayerSeat) => Promise<{
173
210
  entryId: string;
174
211
  clearanceId: string;
175
212
  origin: MemoryEntryOrigin;
@@ -208,10 +245,7 @@ export interface MemoryOriginFaces {
208
245
  * ⚠️ **不在 seam 里翻译拒因码**:core 的 origin-clear 族是**闭集**,翻译点只有一个(路由的 switch),
209
246
  * 在这里再翻一遍就是第二真源。seam 原样抛,路由逐码字面量转发。
210
247
  */
211
- export declare function createMemoryOriginFaces(store: {
212
- backend: MemoryBackend;
213
- root: string;
214
- },
248
+ export declare function createMemoryOriginFaces(stores: MemoryScopeStores,
215
249
  /**
216
250
  * 引擎的 advisory incident 座(core `MemoryEngineOptions.onIncident`)。
217
251
  * 🔴 与合规面的同名座**理由不同,如实写**:亲读 core 5.59.0 的这三条动词路径(engine.js)
@@ -223,12 +257,34 @@ opts?: {
223
257
  onIncident?: (err: Error & {
224
258
  code?: string;
225
259
  }) => void;
226
- captureRecordStore?: SessionCaptureRecordStore;
260
+ captureRecords?: SessionCaptureRecordSource;
227
261
  }): MemoryOriginFaces | undefined;
228
262
  /** [ref] seam① 的窄能力面(`ServiceDeps.sessionMemoryStatus` 的实参来源)。 */
229
263
  export interface SessionMemoryStatusFace {
264
+ /**
265
+ * 这次状态请求读的店:层座点名 ⇒ 那一层住的那一只;不带 ⇒ 本部署的每一只店(部署的店在前,至多两只;单店部署恰一只)——
266
+ * 路由逐店读,再按 {@link foldPlaneStatuses} 折成一份(会话 id 不点名层,一只会话可以跨两只店,见文件头)。每次请求都现定 ——
267
+ * 登记簿热换当场生效,路由的短窗缓存只缓存逐店的扫描,不缓存定店。唯一的拒:点名的层 / 本部署点名的层引擎读不出 ⇒ 同步抛 `request.memory_layer`。
268
+ */
269
+ storesAt: (at?: MemoryLayerSeat) => readonly SessionMemoryStatusStore[];
270
+ }
271
+ /** 一只店上的会话记忆状态读。 */
272
+ export interface SessionMemoryStatusStore {
273
+ /** 这只店的控制面根(引擎自己的读数)—— 状态读扫的就是它;路由的短窗缓存按(会话, 它)分:落同一只店的层键别名是同一格。 */
274
+ readonly controlPlane: string;
230
275
  status: (sessionId: string) => Promise<SessionMemoryStatus>;
231
276
  }
277
+ /** 状态面上 wire 的五键(引擎答案里其余的键不上 wire,也就不折)。 */
278
+ export type FoldedSessionMemoryStatus = Pick<SessionMemoryStatus, "captureOptedOut" | "committedCount" | "foldedCount" | "optOutSource" | "lastCaptureAt">;
279
+ /**
280
+ * 逐店的会话记忆状态 → 一份(**折叠律在代码里只写这一处**;契约 §9 开头同句)。每只店的答案都来自引擎,本函数只按键合,不补任何替身值:
281
+ * · `committedCount` / `foldedCount`:各店相加;任一店缺席(那只店的账读不出)⇒ 缺席。
282
+ * · `lastCaptureAt`:各店取最大;任一店的 `committedCount` 缺席(同一次账读失败)⇒ 缺席;都没有贡献 ⇒ 缺席(与引擎单店同义)。
283
+ * · `captureOptedOut` / `optOutSource`:任一店有记录 ⇒ `true`,带那只店的 `optOutSource`(引擎恒是 `"record"`;一只店上的单向记录就是这只会话的记录);否则全部店答 `false` ⇒ `false`;
284
+ * 否则(有店故障)⇒ `captureOptedOut` 缺席,有店说 `"fault"` 就带 `optOutSource: "fault"`。
285
+ * 一只店 ⇒ 逐键与那只店的答案同(单店部署的应答字节不变)。🚧 引擎的部署级会话记忆状态到货后,本函数删除、路由直接投那一份。
286
+ */
287
+ export declare function foldPlaneStatuses(statuses: readonly SessionMemoryStatus[]): FoldedSessionMemoryStatus;
232
288
  /**
233
289
  * [ref] seam①([ref] §S-7,core 7.0.2 [ref] 件1)—— `GET /v1/sessions/:id/memory-status` 的引擎面。
234
290
  * 命名照 CLAUDE.md 工厂律:返回带行为的活对象 ⇒ `create*`。
@@ -240,17 +296,16 @@ export interface SessionMemoryStatusFace {
240
296
  * 那是**说谎的 0**,比缺席更坏(S-7 的诚实键律:可读零必须是真零)。⇒ 归属缺席 ⇒ 工厂返 undefined,
241
297
  * HTTP 面诚实 501,与 erase/origin 同码同分支。
242
298
  *
243
- * `captureRecordStore` = [ref]② 的 SQL 载体(main.ts 单实例,与 Runner/其余引擎同源 —— 全站同批注入律,
244
- * 机器钉 capture-optout-lane ②):`captureOptedOut` / `optOutSource` 两键经它读,多副本部署上答的才是
245
- * 跨副本的真记录。[ref] 起 local 车道在引擎接线时也供(core 文件三腿,同一只控制面,单机字节不变);缺席 ⇒ 记忆面暗。
299
+ * `captureRecords` = [ref]② 的按平面取用源(main.ts 取一次,与 Runner/其余引擎同源 —— 全站同批注入律,
300
+ * 机器钉 capture-optout-lane ②;引擎按它那只店的控制面取,{@link captureRecordStoreOf}):`captureOptedOut` / `optOutSource`
301
+ * 两键经它读,多副本部署上答的才是跨副本的真记录。[ref] 起 local 车道在引擎接线时也供(core 文件三腿);缺席 ⇒ 记忆面暗。
246
302
  *
247
- * 面**不抛**(core 契约:sessionMemoryStatus never throws —— 每个事实源各自 catch 折缺席键);
303
+ * 引擎**不抛**(core 契约:sessionMemoryStatus never throws —— 每个事实源各自 catch 折缺席键);面唯一的拒是定店那一步的
304
+ * `request.memory_layer`(点名的层 / 本部署点名的层读不出)。不点名层 ⇒ 读本部署的每一只店、路由按 {@link foldPlaneStatuses} 折
305
+ * (只读一只店而它不装这只会话,答出来的就是一个说谎的 0)。
248
306
  * 不接 onIncident:这条只读路径上今天零 sink 站点,而且缺席键本身就是它的披露形。
249
307
  */
250
- export declare function createSessionMemoryStatusFace(store: {
251
- backend: MemoryBackend;
252
- root: string;
253
- }, opts?: {
254
- captureRecordStore?: SessionCaptureRecordStore;
308
+ export declare function createSessionMemoryStatusFace(stores: MemoryScopeStores, opts?: {
309
+ captureRecords?: SessionCaptureRecordSource;
255
310
  }): SessionMemoryStatusFace | undefined;
256
311
  //# sourceMappingURL=memory-operator-faces.d.ts.map