@sema-agent/server 7.137.0 → 7.139.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 (328) hide show
  1. package/MIGRATION.md +600 -142
  2. package/README.md +7 -3
  3. package/README.zh-CN.md +6 -3
  4. package/USAGE.md +132 -41
  5. package/deploy/sema-up/README.md +1 -1
  6. package/deploy/sema-up/lib/lanes.json +3 -2
  7. package/dist/adoption/wire.d.ts +3 -3
  8. package/dist/approval-card.d.ts +23 -16
  9. package/dist/approval-card.js +1 -0
  10. package/dist/audit.js +1 -0
  11. package/dist/background-agent-name.d.ts +5 -0
  12. package/dist/background-agent-name.js +5 -0
  13. package/dist/bench/s1/arms.d.ts +1 -1
  14. package/dist/bench/s1/arms.js +1 -3
  15. package/dist/bench/s1/run-firm.js +2 -2
  16. package/dist/boot/budget-tracing.d.ts +1 -12
  17. package/dist/boot/deployment-mods.d.ts +46 -16
  18. package/dist/boot/deployment-mods.js +82 -6
  19. package/dist/boot/device-lane.d.ts +8 -3
  20. package/dist/boot/device-lane.js +7 -2
  21. package/dist/boot/execution-env.d.ts +4 -2
  22. package/dist/boot/execution-env.js +16 -24
  23. package/dist/boot/execution-lane.d.ts +1 -1
  24. package/dist/boot/governance-seams.d.ts +12 -18
  25. package/dist/boot/governance-seams.js +10 -24
  26. package/dist/boot/leader.d.ts +3 -0
  27. package/dist/boot/leader.js +1 -0
  28. package/dist/boot/memory-consolidation.js +2 -2
  29. package/dist/boot/org-delivery.js +15 -2
  30. package/dist/boot/resolve-spec.d.ts +4 -1
  31. package/dist/boot/resolve-spec.js +29 -19
  32. package/dist/boot/retention-lane.d.ts +14 -8
  33. package/dist/boot/retention-lane.js +2 -8
  34. package/dist/boot/runner-deps.d.ts +10 -4
  35. package/dist/boot/runner-deps.js +2 -0
  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-04-stores.d.ts +1 -12
  40. package/dist/boot/stage-05-execution-env.d.ts +3 -12
  41. package/dist/boot/stage-05-execution-env.js +8 -5
  42. package/dist/boot/stage-06-runners.d.ts +3 -12
  43. package/dist/boot/stage-06-runners.js +5 -3
  44. package/dist/boot/stage-07-capability-layer.d.ts +3 -12
  45. package/dist/boot/stage-07-capability-layer.js +2 -2
  46. package/dist/boot/stage-08-reapers.d.ts +3 -12
  47. package/dist/boot/stage-09-leader.d.ts +3 -12
  48. package/dist/boot/stage-09-leader.js +2 -3
  49. package/dist/boot/stage-10-http-server.d.ts +3 -12
  50. package/dist/boot/stage-10-http-server.js +5 -3
  51. package/dist/boot/stores.js +4 -4
  52. package/dist/boot/web-admin.d.ts +5 -2
  53. package/dist/boot/web-admin.js +5 -5
  54. package/dist/brain.js +5 -5
  55. package/dist/budget.d.ts +17 -15
  56. package/dist/budget.js +2 -2
  57. package/dist/capabilities/mcp-probe.d.ts +36 -11
  58. package/dist/capabilities/mcp-probe.js +44 -5
  59. package/dist/capabilities/scenarios.d.ts +1 -1
  60. package/dist/capability-facts.d.ts +21 -7
  61. package/dist/capability-facts.js +13 -3
  62. package/dist/checkpoint-identity.d.ts +13 -6
  63. package/dist/config-catalog.js +14 -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 +19 -24
  67. package/dist/config-provider.js +27 -12
  68. package/dist/config-types.d.ts +25 -12
  69. package/dist/config.d.ts +33 -0
  70. package/dist/config.js +52 -20
  71. package/dist/delegated-session-owner.d.ts +2 -2
  72. package/dist/deployment-shape.d.ts +7 -7
  73. package/dist/device-enrollment.d.ts +41 -2
  74. package/dist/device-enrollment.js +27 -12
  75. package/dist/device-store.d.ts +58 -85
  76. package/dist/device-store.js +19 -49
  77. package/dist/device-ws-hub.js +2 -1
  78. package/dist/env-name-allowlist-knobs.d.ts +5 -4
  79. package/dist/exec-cut.d.ts +60 -0
  80. package/dist/exec-cut.js +36 -0
  81. package/dist/execution-lane-caps.d.ts +19 -0
  82. package/dist/execution-lane-caps.js +10 -0
  83. package/dist/execution-placement.d.ts +259 -0
  84. package/dist/execution-placement.js +199 -0
  85. package/dist/field-conflict.d.ts +3 -2
  86. package/dist/field-conflict.js +1 -0
  87. package/dist/gate-settlement.d.ts +71 -0
  88. package/dist/gate-settlement.js +40 -0
  89. package/dist/hooks/classic-stations.d.ts +1 -0
  90. package/dist/hooks/classic-stations.js +1 -0
  91. package/dist/hooks/command-spawn.d.ts +2 -2
  92. package/dist/hooks/hook-runner.js +14 -14
  93. package/dist/hosted-posture.d.ts +2 -2
  94. package/dist/http/admission.js +10 -19
  95. package/dist/http/checkpoint-ctx.d.ts +21 -12
  96. package/dist/http/checkpoint-ctx.js +4 -2
  97. package/dist/http/claimed-run.d.ts +1 -1
  98. package/dist/http/dispatch.d.ts +4 -0
  99. package/dist/http/dispatch.js +3 -0
  100. package/dist/http/durable-run-leg.js +12 -6
  101. package/dist/http/execution-context.d.ts +218 -0
  102. package/dist/http/execution-context.js +330 -0
  103. package/dist/http/memory-compliance-failure-reply.js +3 -0
  104. package/dist/http/resume-legs.d.ts +5 -11
  105. package/dist/http/resume-legs.js +179 -104
  106. package/dist/http/route-ctx.d.ts +44 -59
  107. package/dist/http/route-ctx.js +2 -5
  108. package/dist/http/routes/a2a-serve.js +10 -4
  109. package/dist/http/routes/agents-roster.d.ts +1 -1
  110. package/dist/http/routes/agents-roster.js +5 -1
  111. package/dist/http/routes/approvals-assistant.js +6 -6
  112. package/dist/http/routes/background.d.ts +29 -1
  113. package/dist/http/routes/background.js +29 -2
  114. package/dist/http/routes/capabilities.js +12 -10
  115. package/dist/http/routes/devices.d.ts +13 -19
  116. package/dist/http/routes/devices.js +21 -26
  117. package/dist/http/routes/mcp-reconnect.d.ts +3 -2
  118. package/dist/http/routes/mcp-reconnect.js +7 -5
  119. package/dist/http/routes/memory-consolidation.d.ts +1 -1
  120. package/dist/http/routes/memory-origin.d.ts +1 -1
  121. package/dist/http/routes/rules.js +3 -3
  122. package/dist/http/routes/runs.js +11 -7
  123. package/dist/http/routes/session-sync.js +110 -15
  124. package/dist/http/routes/sessions.d.ts +6 -0
  125. package/dist/http/routes/sessions.js +119 -13
  126. package/dist/http/routes/side-query.d.ts +12 -4
  127. package/dist/http/routes/side-query.js +6 -8
  128. package/dist/http/routes/tasks.js +800 -782
  129. package/dist/http/server.d.ts +61 -39
  130. package/dist/http/server.js +11 -0
  131. package/dist/http/session-inherit-env.d.ts +3 -4
  132. package/dist/http/session-inherit-env.js +1 -1
  133. package/dist/http/wire-types.d.ts +22 -18
  134. package/dist/identity-source.d.ts +1 -1
  135. package/dist/index.d.ts +3 -0
  136. package/dist/index.js +1 -0
  137. package/dist/leader/wire.d.ts +7 -0
  138. package/dist/leader/wire.js +5 -4
  139. package/dist/mcp-assertion-header.d.ts +51 -40
  140. package/dist/mcp-assertion-header.js +10 -11
  141. package/dist/mcp-authorization-face.d.ts +27 -0
  142. package/dist/mcp-authorization-face.js +15 -0
  143. package/dist/memory-operator-faces.d.ts +13 -4
  144. package/dist/memory-operator-faces.js +1 -17
  145. package/dist/memory-sync-client.d.ts +53 -14
  146. package/dist/memory-sync-client.js +187 -92
  147. package/dist/memory-sync.d.ts +1 -1
  148. package/dist/memory-sync.js +3 -2
  149. package/dist/model-route-gap.d.ts +6 -22
  150. package/dist/model-route-gap.js +7 -5
  151. package/dist/mods-declaration.d.ts +110 -0
  152. package/dist/mods-declaration.js +109 -0
  153. package/dist/observability/cost-taxonomy.d.ts +2 -2
  154. package/dist/observability/err-text.d.ts +5 -0
  155. package/dist/observability/err-text.js +9 -0
  156. package/dist/observability/fail-open.d.ts +17 -1
  157. package/dist/observability/fail-open.js +17 -1
  158. package/dist/observability/run-terminal.js +0 -1
  159. package/dist/observability/secret-env-scrub.d.ts +1 -1
  160. package/dist/observability/secret-env-scrub.js +1 -1
  161. package/dist/orchestration/workflow-notify-journal.js +4 -4
  162. package/dist/org-memory-admission.d.ts +4 -3
  163. package/dist/org-memory-admission.js +6 -6
  164. package/dist/parked-decide.d.ts +49 -11
  165. package/dist/parked-decide.js +25 -26
  166. package/dist/parked-revive-surface.d.ts +12 -15
  167. package/dist/parked-revive-surface.js +3 -6
  168. package/dist/peer-seat.d.ts +156 -0
  169. package/dist/peer-seat.js +273 -0
  170. package/dist/permission-rule-vocab.d.ts +7 -7
  171. package/dist/permission-rule-vocab.js +3 -3
  172. package/dist/plain-string-record.d.ts +38 -0
  173. package/dist/plain-string-record.js +38 -0
  174. package/dist/plugins/approval-ask-store-file.d.ts +7 -0
  175. package/dist/plugins/approval-ask-store-file.js +11 -0
  176. package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
  177. package/dist/plugins/approval-ask-store-memory.js +12 -0
  178. package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
  179. package/dist/plugins/approval-ask-store-sql.js +30 -12
  180. package/dist/plugins/background-agent-store-sql.js +6 -3
  181. package/dist/plugins/caching-session-store.d.ts +11 -2
  182. package/dist/plugins/caching-session-store.js +15 -3
  183. package/dist/plugins/checkpoint-store-sql.d.ts +21 -25
  184. package/dist/plugins/checkpoint-store-sql.js +13 -15
  185. package/dist/plugins/device-store-sql.d.ts +25 -51
  186. package/dist/plugins/device-store-sql.js +49 -103
  187. package/dist/plugins/execution-placement-sql.d.ts +151 -0
  188. package/dist/plugins/execution-placement-sql.js +223 -0
  189. package/dist/plugins/file-history-store-sql.d.ts +7 -6
  190. package/dist/plugins/file-history-store-sql.js +8 -7
  191. package/dist/plugins/file-run-store.d.ts +6 -1
  192. package/dist/plugins/file-run-store.js +4 -0
  193. package/dist/plugins/fork-routing-session-store.d.ts +6 -0
  194. package/dist/plugins/fork-routing-session-store.js +16 -0
  195. package/dist/plugins/k8s-pod-reaper.d.ts +2 -8
  196. package/dist/plugins/k8s-pod-reaper.js +3 -3
  197. package/dist/plugins/local-checkpoint-store.d.ts +1 -11
  198. package/dist/plugins/local-checkpoint-store.js +0 -1
  199. package/dist/plugins/local-session-store.d.ts +183 -45
  200. package/dist/plugins/local-session-store.js +412 -105
  201. package/dist/plugins/mailbox-store-sql.d.ts +11 -3
  202. package/dist/plugins/mailbox-store-sql.js +103 -15
  203. package/dist/plugins/memory-key-guards.d.ts +4 -0
  204. package/dist/plugins/memory-key-guards.js +1 -0
  205. package/dist/plugins/memory-run-store.d.ts +1 -1
  206. package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
  207. package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
  208. package/dist/plugins/one-time-migrations.d.ts +117 -6
  209. package/dist/plugins/one-time-migrations.js +383 -14
  210. package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
  211. package/dist/plugins/permission-rule-store-sql.d.ts +13 -15
  212. package/dist/plugins/permission-rule-store-sql.js +34 -29
  213. package/dist/plugins/pg-pool.d.ts +7 -3
  214. package/dist/plugins/pg-session-storage.d.ts +41 -22
  215. package/dist/plugins/pg-session-storage.js +136 -55
  216. package/dist/plugins/remote-env-adb.d.ts +22 -4
  217. package/dist/plugins/remote-env-adb.js +70 -62
  218. package/dist/plugins/remote-env-device.d.ts +32 -12
  219. package/dist/plugins/remote-env-device.js +18 -17
  220. package/dist/plugins/remote-env-e2b.d.ts +19 -3
  221. package/dist/plugins/remote-env-e2b.js +41 -42
  222. package/dist/plugins/remote-env-file-error.d.ts +2 -0
  223. package/dist/plugins/remote-env-file-error.js +1 -1
  224. package/dist/plugins/remote-env-host.d.ts +23 -8
  225. package/dist/plugins/remote-env-host.js +66 -70
  226. package/dist/plugins/remote-env-k8s.d.ts +13 -16
  227. package/dist/plugins/remote-env-k8s.js +61 -54
  228. package/dist/plugins/remote-env-local-docker.d.ts +30 -5
  229. package/dist/plugins/remote-env-local-docker.js +46 -59
  230. package/dist/plugins/remote-env-ssh.d.ts +18 -4
  231. package/dist/plugins/remote-env-ssh.js +72 -56
  232. package/dist/plugins/remote-shell.d.ts +100 -3
  233. package/dist/plugins/remote-shell.js +166 -2
  234. package/dist/plugins/retention-store-sql.d.ts +23 -8
  235. package/dist/plugins/retention-store-sql.js +13 -1
  236. package/dist/plugins/run-store-sql.d.ts +13 -3
  237. package/dist/plugins/run-store-sql.js +5 -0
  238. package/dist/plugins/schema-consistency.d.ts +15 -5
  239. package/dist/plugins/schema-consistency.js +14 -8
  240. package/dist/plugins/schema-drift-sentence.d.ts +27 -0
  241. package/dist/plugins/schema-drift-sentence.js +38 -0
  242. package/dist/plugins/session-fork.d.ts +63 -12
  243. package/dist/plugins/session-fork.js +38 -21
  244. package/dist/plugins/session-ownership.d.ts +7 -0
  245. package/dist/plugins/session-ownership.js +5 -0
  246. package/dist/plugins/session-row-sql.d.ts +22 -0
  247. package/dist/plugins/session-row-sql.js +81 -0
  248. package/dist/plugins/session-store.d.ts +1 -1
  249. package/dist/plugins/session-workspace-cell.d.ts +17 -0
  250. package/dist/plugins/session-workspace-cell.js +38 -0
  251. package/dist/plugins/store-backend.d.ts +1 -1
  252. package/dist/plugins/store-backend.js +26 -14
  253. package/dist/plugins/store-contracts.d.ts +25 -5
  254. package/dist/plugins/tidb-pool.d.ts +12 -7
  255. package/dist/plugins/tidb-pool.js +15 -3
  256. package/dist/plugins/tidb-session-store.d.ts +74 -28
  257. package/dist/plugins/tidb-session-store.js +132 -53
  258. package/dist/plugins/tool-result-store-sql.d.ts +16 -8
  259. package/dist/plugins/tool-result-store-sql.js +26 -17
  260. package/dist/plugins/worktree-isolation.d.ts +3 -2
  261. package/dist/plugins/worktree-isolation.js +1 -7
  262. package/dist/project-identity.d.ts +1 -14
  263. package/dist/project-identity.js +0 -4
  264. package/dist/project-memory.d.ts +9 -15
  265. package/dist/project-memory.js +5 -4
  266. package/dist/request-key-closure.js +1 -1
  267. package/dist/request-value-closure.d.ts +6 -7
  268. package/dist/request-value-closure.js +1 -3
  269. package/dist/rules-consent.js +6 -4
  270. package/dist/run-local.d.ts +6 -0
  271. package/dist/run-local.js +36 -26
  272. package/dist/runs.d.ts +9 -2
  273. package/dist/runs.js +9 -2
  274. package/dist/sandbox-git-plane.d.ts +2 -2
  275. package/dist/security.d.ts +38 -12
  276. package/dist/security.js +8 -2
  277. package/dist/server-secret-env.d.ts +15 -8
  278. package/dist/server-secret-env.js +4 -2
  279. package/dist/session-children-retire.d.ts +27 -9
  280. package/dist/session-children-retire.js +9 -5
  281. package/dist/session-incarnation.d.ts +19 -10
  282. package/dist/session-incarnation.js +5 -3
  283. package/dist/session-row.d.ts +114 -5
  284. package/dist/session-row.js +55 -5
  285. package/dist/session-titler.d.ts +2 -2
  286. package/dist/session-workspace.d.ts +130 -0
  287. package/dist/session-workspace.js +83 -0
  288. package/dist/spec-fields.d.ts +1 -1
  289. package/dist/standing-answer-grant.d.ts +2 -13
  290. package/dist/standing-answer-grant.js +0 -7
  291. package/dist/task-a2a.d.ts +44 -14
  292. package/dist/task-a2a.js +46 -20
  293. package/dist/task-cwd.d.ts +6 -1
  294. package/dist/task-mcp.d.ts +33 -20
  295. package/dist/task-mcp.js +46 -22
  296. package/dist/tool-approval.d.ts +38 -8
  297. package/dist/tool-approval.js +57 -13
  298. package/dist/trace/core-keyset-guard.d.ts +33 -18
  299. package/dist/trace/engine-notice-wire.d.ts +1 -1
  300. package/dist/trace/engine-notice-wire.js +2 -0
  301. package/dist/trace/exit-seat.d.ts +20 -1
  302. package/dist/trace/exit-seat.js +3 -0
  303. package/dist/trace/extension-call-face.d.ts +33 -0
  304. package/dist/trace/extension-call-face.js +39 -0
  305. package/dist/trace/project.d.ts +26 -7
  306. package/dist/trace/project.js +30 -3
  307. package/dist/trace/redact.js +42 -13
  308. package/dist/trace/self-minted-wire.d.ts +240 -12
  309. package/dist/trace/self-minted-wire.js +100 -4
  310. package/dist/trace/wire-projection-faces.d.ts +6 -6
  311. package/dist/trace/wire-projection-faces.js +6 -5
  312. package/dist/url-refusal.d.ts +1 -1
  313. package/dist/user-authored-text.d.ts +2 -2
  314. package/dist/user-authored-text.js +16 -1
  315. package/dist/web-admin-client/apply-effective.d.ts +17 -3
  316. package/dist/web-admin-client/apply-effective.js +20 -10
  317. package/dist/web-admin-client/center-request.d.ts +3 -2
  318. package/dist/web-admin-client/center-request.js +2 -3
  319. package/dist/web-admin-client/skills-mcp.d.ts +8 -4
  320. package/dist/web-admin-client/skills-mcp.js +32 -18
  321. package/dist/web-admin-client/types.d.ts +11 -0
  322. package/package.json +3 -3
  323. package/wire-changes/server@7.138.0.json +446 -0
  324. package/wire-changes/server@7.139.0.json +348 -0
  325. package/dist/http/device-placement.d.ts +0 -175
  326. package/dist/http/device-placement.js +0 -145
  327. package/dist/http/mcp-remote-text.d.ts +0 -5
  328. package/dist/http/mcp-remote-text.js +0 -7
@@ -1,8 +1,10 @@
1
1
  import { MAX_MINTED_TOOL_RESULT_REF_CHARS, assertSafeToolResultRef, assertToolResultProvenanceMatch, normalizeToolResultProvenance } from "@sema-agent/core";
2
2
  import { pgSanitizeText } from "./pg-safe-json.js";
3
3
  import { mysqlDriver, pgDriver } from "./sql-driver.js";
4
- import { MANAGED_RETENTION } from "./retention-store-sql.js";
4
+ import { MANAGED_RETENTION, UNMANAGED_RETENTION } from "./retention-store-sql.js";
5
5
  import { ensureIndexes } from "./ensure-index.js";
6
+ import { describeProbedTableDrift, schemaWaysOut } from "./schema-drift-sentence.js";
7
+ import { isMissingColumnError } from "./sql-errors.js";
6
8
  export const PG_TOOL_RESULT_SCHEMA = [
7
9
  `CREATE TABLE IF NOT EXISTS tool_result (
8
10
  ref VARCHAR(518) COLLATE "C" NOT NULL,
@@ -28,30 +30,37 @@ export async function assertToolResultProvenanceSchema(query, dialect) {
28
30
  const width = Number(widthRow.rows[0]?.len ?? NaN);
29
31
  if (Number.isFinite(width) && width < MAX_MINTED_TOOL_RESULT_REF_CHARS) {
30
32
  throw new Error(`tool_result.ref is VARCHAR(${width}) but core 5.26.0 mints refs up to ${MAX_MINTED_TOOL_RESULT_REF_CHARS} characters ` +
31
- `(#119 made the ref injective: four \`~\`-separated segments). A truncating primary key aliases two distinct refs onto ` +
32
- `one row — one run's tool output reads back from another run's ref. This repository ships no ALTER TABLE migrations: ` +
33
- `run \`DROP TABLE tool_result;\` on the ${dialect === "pg" ? "PostgreSQL" : "MySQL-protocol"} backend and restart ` +
34
- `(the schema is recreated at boot; offloaded results are a recoverable-window cache, inline previews are unaffected).`);
33
+ `(#119 made the ref injective: four \`~\`-separated segments) — refusing to start. A truncating primary key aliases two distinct refs onto ` +
34
+ `one row — one run's tool output reads back from another run's ref. ` +
35
+ `The ${dialect === "pg" ? "PostgreSQL" : "MySQL-protocol"} database is behind this build on that key column; offloaded results are a recoverable-window cache, ` +
36
+ `inline previews in transcripts are unaffected.\n\n` +
37
+ ` table tool_result: column ref is VARCHAR(${width}); this build needs at least VARCHAR(${MAX_MINTED_TOOL_RESULT_REF_CHARS}) — the database is OLDER than this build.\n\n` +
38
+ schemaWaysOut({
39
+ when: "a key column is narrower than this build declares",
40
+ action: "run an ALTER TABLE that widens tool_result.ref to this build's definition yourself",
41
+ }).join("\n"));
35
42
  }
36
43
  try {
37
44
  await query("SELECT owner_session_id, owner_task_id FROM tool_result WHERE 1=0");
38
45
  }
39
46
  catch (err) {
47
+ if (!isMissingColumnError(err, dialect))
48
+ throw err;
40
49
  throw new Error(`tool_result is missing the #119 provenance columns (owner_session_id / owner_task_id) — refusing to start. ` +
41
50
  `This release picks up @sema-agent/core 5.26.0, which changed how an offloaded tool result is addressed ` +
42
- `(the ref grew past the old VARCHAR(190) key) and made the store record who wrote each row. This repository ` +
43
- `ships no ALTER TABLE migrations, so the table must be recreated: run \`DROP TABLE tool_result;\` on the ` +
44
- `${dialect === "pg" ? "PostgreSQL" : "MySQL-protocol"} backend and restart — the schema is recreated at boot. ` +
45
- `Offloaded tool results are a recoverable-window cache (the inline previews in transcripts are unaffected), ` +
46
- `so the cost is at most the full text of results from runs still in flight. ` +
47
- `Underlying probe error: ${err instanceof Error ? err.message : String(err)}`);
51
+ `(the ref grew past the old VARCHAR(190) key) and made the store record who wrote each row. Without the columns every offload write ` +
52
+ `fails with unknown column and core's failure arm turns it into an inline placeholder — the service keeps running and the tool output is lost. ` +
53
+ `Offloaded tool results are a recoverable-window cache (the inline previews in transcripts are unaffected).\n` +
54
+ `Underlying probe error: ${err instanceof Error ? err.message : String(err)}\n\n` +
55
+ (await describeProbedTableDrift(query, dialect, ["tool_result"])));
48
56
  }
49
57
  }
50
58
  export class SqlToolResultStore {
51
59
  db;
52
- retention = MANAGED_RETENTION;
53
- constructor(db) {
60
+ retention;
61
+ constructor(db, opts = {}) {
54
62
  this.db = db;
63
+ this.retention = opts.retention ?? UNMANAGED_RETENTION;
55
64
  }
56
65
  q(tidb, pg) {
57
66
  return this.db.dialect === "tidb" ? tidb : pg;
@@ -128,13 +137,13 @@ export class SqlToolResultStore {
128
137
  }
129
138
  }
130
139
  export class TiDBToolResultStore extends SqlToolResultStore {
131
- constructor(pool) {
132
- super(mysqlDriver(pool));
140
+ constructor(pool, opts) {
141
+ super(mysqlDriver(pool), opts);
133
142
  }
134
143
  }
135
144
  export class PgToolResultStore extends SqlToolResultStore {
136
- constructor(pool) {
137
- super(pgDriver(pool));
145
+ constructor(pool, opts) {
146
+ super(pgDriver(pool), opts);
138
147
  }
139
148
  }
140
149
  //# sourceMappingURL=tool-result-store-sql.js.map
@@ -54,8 +54,9 @@ export declare function withWorktreeIsolation(baseFactory: ExecutionEnvFactory,
54
54
  * post-kill Runner hook). NEVER throws (a prune failure is logged, never fatal).
55
55
  *
56
56
  * NOTE: `git worktree prune` only deregisters worktrees whose DIRECTORY is missing. A crashed run that left
57
- * the dir intact is NOT reaped by prune alone — that is acceptable for v1 (the worktree lives under the known
58
- * `.sema-worktrees/` parent and is human-/script-reapable; a stricter age-based sweep is a follow-on).
57
+ * the dir intact is NOT reaped by prune alone — that is acceptable for v1 (the worktree lives under core's known
58
+ * managed parent `<repoRoot>/<WORKTREE_PARENT>/` on its own `sema/<name>` branch and is human-/script-reapable;
59
+ * a stricter age-based sweep is a follow-on).
59
60
  */
60
61
  export declare function reapOrphanWorktrees(baseEnvForGit: ExecutionEnv, repoRoot: string, logger?: WorktreeIsolationLogger): Promise<void>;
61
62
  //# sourceMappingURL=worktree-isolation.d.ts.map
@@ -31,7 +31,7 @@ export function withWorktreeIsolation(baseFactory, opts) {
31
31
  return baseFactory(ctx);
32
32
  }
33
33
  let innerDestroy;
34
- const { env, worktreeDir } = await serialize(() => addWorktree(opts.baseEnvForGit, {
34
+ const { env, worktreeDir, baseSha } = await serialize(() => addWorktree(opts.baseEnvForGit, {
35
35
  repoRoot,
36
36
  sessionId: ctx.sessionId,
37
37
  rootEnvAt: async (dir) => {
@@ -43,12 +43,6 @@ export function withWorktreeIsolation(baseFactory, opts) {
43
43
  },
44
44
  ...(opts.commit ? { commit: opts.commit } : {}),
45
45
  }));
46
- let baseSha;
47
- {
48
- const r = await opts.baseEnvForGit.exec("git rev-parse HEAD", { cwd: worktreeDir });
49
- if (r.ok && r.value.exitCode === 0)
50
- baseSha = r.value.stdout.trim();
51
- }
52
46
  const isChanged = async () => {
53
47
  const status = await opts.baseEnvForGit.exec("git status --porcelain", { cwd: worktreeDir });
54
48
  if (!status.ok || status.value.exitCode !== 0)
@@ -4,19 +4,6 @@ import { type ProjectLayerIdentity } from "./project-layer-key.js";
4
4
  export type { MemoryProjectKey };
5
5
  /** 本仓会说的缺席词。`not_git` 刻意排除:裁 D 起非 git 目录按目录键控,不是缺席(core 闭集仍收它,本仓不铸)。 */
6
6
  export type ProjectIdentityAbsentReason = Exclude<MemoryProjectKeyAbsentReason, "not_git">;
7
- /** 一个任务根的项目身份:canonical 项目根,或说得出理由的缺席。 */
8
- export type ProjectIdentity = {
9
- readonly root: string;
10
- } | {
11
- readonly absent: ProjectIdentityAbsentReason;
12
- };
13
- /**
14
- * 任务根 → 项目身份([ref] 四例;见文件头)。纯文件系统读,零子进程。
15
- * `taskRoot` 必须是**本进程读得到**的路径(调用方按车道判:根在沙箱/设备盘上就别调,直接给 `unreadable`)。
16
- *
17
- * 一次向上走,规则三条按优先序:最近的 `.git`(① ② ③)> 链上最近的裸仓布局(④ bare)> 非 git 按目录键控(④)。
18
- */
19
- export declare function resolveProjectIdentity(taskRoot: string): ProjectIdentity;
20
7
  /**
21
8
  * 退役 `repo:` 键的**唯一**铸点([ref] ①:`repo:` + sha256 hex 前 24;`root` 为 realpath 字符串,不加尾斜杠、不折大小写)。
22
9
  * [ref] 起它只是一次性迁移的来源(`memory-project-layer.ts` 把这一层的条目折进新键;窗见 `plugins/one-time-migrations.ts` 登记表)。
@@ -39,7 +26,7 @@ export declare function assertProjectLayerOwnable(scope: string, envName: string
39
26
  export declare function normalizeGitRemoteUrl(url: string): string | undefined;
40
27
  /**
41
28
  * 任务根 → 项目层身份([ref]):当前档(`r` 优先,没有 origin 退 `p`)+ 本 checkout 的低档(`r` 档时 = 它的 `p` 档)。
42
- * 缺席形与 {@link resolveProjectIdentity} 同;git 配置在而读不了 ⇒ `unreadable`。
29
+ * 缺席形 = 找根的缺席词(`bare` / `unreadable`);git 配置在而读不了 ⇒ `unreadable`。
43
30
  */
44
31
  export declare function projectLayerIdentityOf(taskRoot: string): {
45
32
  readonly root: string;
@@ -87,10 +87,6 @@ function canonicalTaskRoot(taskRoot) {
87
87
  p = parent;
88
88
  }
89
89
  }
90
- export function resolveProjectIdentity(taskRoot) {
91
- const located = locateProject(taskRoot);
92
- return "root" in located ? { root: located.root } : located;
93
- }
94
90
  function locateProject(taskRoot) {
95
91
  const root = canonicalTaskRoot(taskRoot);
96
92
  if (root === "unreadable")
@@ -1,14 +1,8 @@
1
1
  import { type PlatformPath } from "node:path";
2
- import type { ProjectMemoryLoad } from "@sema-agent/core";
2
+ import type { ProjectMemoryLoad, RunnerDeps } from "@sema-agent/core";
3
3
  import { type InstructionSourceSeat } from "./instruction-source-notice.js";
4
- interface ProjectMemoryCtx {
5
- cwd: string;
6
- handsEnabled: boolean;
7
- isSubagent: boolean;
8
- agentName?: string;
9
- sessionId?: string;
10
- phase?: "fresh" | "resume" | "post-compact" | "post-clear";
11
- }
4
+ /** The engine's loader ctx, read from its seat type (one source: a hand-copied twin kept a phase word the engine had retired). */
5
+ type ProjectMemoryCtx = Parameters<NonNullable<RunnerDeps["loadProjectMemory"]>>[0];
12
6
  /** The instruction-file name chain: the CLAUDE family first, the AGENTS family only when no CLAUDE file is
13
7
  * present. The FIRST hit is the single declared instruction source.
14
8
  *
@@ -37,17 +31,17 @@ export declare function instructionChainCoordinates(absPath: string, p?: Platfor
37
31
  rel: InstructionChainMember;
38
32
  } | null;
39
33
  /**
40
- * Build a `loadProjectMemory` for the host lane. Returns null (skip) unless hands are enabled AND cwd is a local
41
- * directory. Reads the instruction-file chain (CLAUDE.md → .claude/CLAUDE.md → AGENTS.md → .claude/AGENTS.md, [ref]) + (non-subagent)
34
+ * Build a `loadProjectMemory` for the host lane. Answers `{ content: null }` (skip) unless hands are enabled AND cwd is a
35
+ * local directory — every answer is a `ProjectMemoryLoad`, the one form the engine reads. Reads the instruction-file chain (CLAUDE.md → .claude/CLAUDE.md → AGENTS.md → .claude/AGENTS.md, [ref]) + (non-subagent)
42
36
  * `git log -5` / `git status`, redacts secrets, and caps the total. A subagent gets a trimmed instruction file and
43
- * no git narrative (cost control, H7). When an instruction file is hit the return is a `ProjectMemoryLoad`
44
- * declaring it in `instructionSources` (path + sha256 over the raw bounded-read window) so core's
37
+ * no git narrative (cost control, H7). When an instruction file is hit the answer also declares it in
38
+ * `instructionSources` (path + sha256 over the raw bounded-read window) so core's
45
39
  * instructions-change lane can probe it mid-run.
46
40
  *
47
41
  * Session snapshot cache (S-2): keyed on ctx.sessionId — a session keeps ONE stable instruction snapshot
48
42
  * (mid-run file edits surface via the probe as tail attachments, never a silently re-rendered prefix).
49
43
  * `phase: "post-compact"` forces a re-read (core re-renders the prefix there anyway). No entry for
50
- * sessionless one-shot runs. (post-clear never arrives from core — [ref] — so it is not a cache key here.)
44
+ * sessionless one-shot runs.
51
45
  *
52
46
  * [ref] — source-change notice: with `instructionSource` wired, every prepare of a non-subagent session that WALKED the
53
47
  * instruction chain hands the chain member it selected (`null` = none) to {@link announceInstructionSource}, which
@@ -72,7 +66,7 @@ export declare function makeLoadProjectMemory(opts: {
72
66
  cacheMax?: number;
73
67
  /** [ref]: the baseline store + notice exit. Absent ⇒ no source-change notice (the session store has no baseline face). */
74
68
  instructionSource?: InstructionSourceSeat;
75
- }): (ctx: ProjectMemoryCtx) => Promise<string | null | ProjectMemoryLoad>;
69
+ }): (ctx: ProjectMemoryCtx) => Promise<ProjectMemoryLoad>;
76
70
  /**
77
71
  * ② The `RunnerDeps.probeInstructionSources` seam: re-fingerprint the declared instruction files mid-run so
78
72
  * core's instructions-change lane can append a tail attachment when one changes. Same read posture as the
@@ -42,7 +42,8 @@ function instructionHash(raw) {
42
42
  return `hmac-sha256:${createHmac("sha256", INSTRUCTION_HASH_KEY).update(raw).digest("hex")}`;
43
43
  }
44
44
  const ABSENT_HASH = null;
45
- const NOT_APPLICABLE = { walked: false, answer: null };
45
+ const NOTHING_TO_INJECT = Object.freeze({ content: null });
46
+ const NOT_APPLICABLE = { walked: false, answer: NOTHING_TO_INJECT };
46
47
  export function instructionChainCoordinates(absPath, p = hostPath) {
47
48
  const candidates = INSTRUCTION_FILE_CHAIN.filter((rel) => absPath.endsWith(p.sep + rel.split("/").join(p.sep))).sort((a, b) => b.length - a.length);
48
49
  for (const rel of candidates) {
@@ -218,12 +219,12 @@ export function makeLoadProjectMemory(opts) {
218
219
  if (gitNarrative)
219
220
  sections.push(gitNarrative);
220
221
  if (sections.length === 0)
221
- return { walked: true, answer: null, instructionFile };
222
+ return { walked: true, answer: NOTHING_TO_INJECT, instructionFile };
222
223
  const redacted = redactSecrets(sections.join("\n\n"));
223
224
  const capped = capUtf8(redacted, totalCap);
224
225
  opts.logger?.debug?.("project_memory_loaded", { cwd: root, bytes: Buffer.byteLength(capped, "utf8"), isSubagent: ctx.isSubagent, gitOk, ...(gitDropReason ? { gitDropReason } : {}), claudeTruncated, ...(hitFile ? { instructionFile: hitFile } : {}), ...(ctx.phase ? { phase: ctx.phase } : {}), cacheSize: cache.size });
225
226
  if (!capped)
226
- return { walked: true, answer: null, instructionFile };
227
+ return { walked: true, answer: NOTHING_TO_INJECT, instructionFile };
227
228
  if (hitFile && hitHash) {
228
229
  return {
229
230
  walked: true,
@@ -237,7 +238,7 @@ export function makeLoadProjectMemory(opts) {
237
238
  instructionFile,
238
239
  };
239
240
  }
240
- return { walked: true, answer: capped, instructionFile };
241
+ return { walked: true, answer: { content: capped }, instructionFile };
241
242
  }
242
243
  }
243
244
  export function makeProbeInstructionSources() {
@@ -28,7 +28,7 @@ const TASK_BODY_DECLARED_KEYS = [
28
28
  "maxTokens", "mcpServers", "memory", "memoryCapture", "memoryWrite", "model", "objective", "oneShot", "outputRetries", "outputStyle",
29
29
  "outputSchema", "permissionMode", "projectId", "projectMemory", "promptLean", "reasoningEffort", "requireExistingSession",
30
30
  "resilience", "restoreFiles", "resumeAt", "resumeAtMode", "retainBackgroundProcesses", "retainSubagentSessions",
31
- "rewindFiles", "rewindFilesTo", "sandboxImageProfile", "scenario", "scratchpadDir", "selfOrchestration",
31
+ "rewindFilesTo", "sandboxImageProfile", "scenario", "scratchpadDir", "selfOrchestration",
32
32
  "sessionId", "settings", "skills", "suggestNextPrompts", "systemPrompt", "taskId", "toolMaterializeStrategy",
33
33
  "userAttachments", "userInvokedSkills", "verify", "verifyRounds",
34
34
  ];
@@ -67,18 +67,17 @@ export declare const PROJECT_MEMORY_OFF_SPELLING_MESSAGE = "projectMemory must b
67
67
  * 判据:{@link fileHistoryRestoreConflict}。**只在 fresh 受理门**(`http/admission.ts`);续跑腿不过这道门(RESUME 重放不过受理门,
68
68
  * 同律 —— 且续跑腿重建时整族剥掉一次性历史动作,矛盾在盘上的体里本就留不下来)。wire 可见、字节冻结。
69
69
  */
70
- export declare const FILE_HISTORY_DISABLED_NO_RESTORE = "fileHistory: 'disabled' cannot ride with a file restore (restoreFiles, rewindFilesTo, or the retired rewindFiles) \u2014 the request turns this run's file history off and asks to restore files from it in the same breath; the engine would refuse it (rewind.capture_disabled) only after the session had already been branched at resumeAt, which it does not undo, so it is refused here, before any side effect. Drop fileHistory to restore, or drop the restore to run without file history";
70
+ export declare const FILE_HISTORY_DISABLED_NO_RESTORE = "fileHistory: 'disabled' cannot ride with a file restore (restoreFiles or rewindFilesTo) \u2014 the request turns this run's file history off and asks to restore files from it in the same breath; the engine would refuse it (rewind.capture_disabled) only after the session had already been branched at resumeAt, which it does not undo, so it is refused here, before any side effect. Drop fileHistory to restore, or drop the restore to run without file history";
71
71
  /**
72
- * 「关断词 ∧ 还原」这一对的判据(纯函数,只看体)。还原 = 三个键里任一个在请求:`restoreFiles: true`、非空串 `rewindFilesTo`
73
- * (与 `boot/resolve-spec.ts` 的读法同:空串 / 非串按缺席)、退役拼法 `rewindFiles: true`(restore 义要一次还原;capture 义要的
74
- * 正是这个词关掉的记录 —— 两义都与关断词矛盾)。调用前值形已由上面的单成员表与既有布尔门判过。
72
+ * 「关断词 ∧ 还原」这一对的判据(纯函数,只看体)。还原 = 两个键里任一个在请求:`restoreFiles: true`、非空串 `rewindFilesTo`
73
+ * (与 `boot/resolve-spec.ts` 的读法同:空串 / 非串按缺席)。调用前值形已由上面的单成员表与既有布尔门判过。
75
74
  */
76
- export declare function fileHistoryRestoreConflict(body: Pick<TaskRequestBody, "fileHistory" | "restoreFiles" | "rewindFiles" | "rewindFilesTo">): boolean;
75
+ export declare function fileHistoryRestoreConflict(body: Pick<TaskRequestBody, "fileHistory" | "restoreFiles" | "rewindFilesTo">): boolean;
77
76
  /**
78
- * 还原键里请求**真带了的**那几个(顺序固定:`restoreFiles` · `rewindFilesTo` · 退役的 `rewindFiles`)。{@link fileHistoryRestoreConflict} 的「还原」一半就是它非空 ——
77
+ * 还原键里请求**真带了的**那几个(顺序固定:`restoreFiles` · `rewindFilesTo`)。{@link fileHistoryRestoreConflict} 的「还原」一半就是它非空 ——
79
78
  * 判据只有这一份,拒体的 `detail.fields` 点名的也是它(判与点名不会各读各的)。
80
79
  */
81
- export declare function fileHistoryRestoreKeysInBody(body: Pick<TaskRequestBody, "restoreFiles" | "rewindFiles" | "rewindFilesTo">): Array<"restoreFiles" | "rewindFilesTo" | "rewindFiles">;
80
+ export declare function fileHistoryRestoreKeysInBody(body: Pick<TaskRequestBody, "restoreFiles" | "rewindFilesTo">): Array<"restoreFiles" | "rewindFilesTo">;
82
81
  /**
83
82
  * **单成员闭集键表** —— 每键合法值只有它自己那一个关断词(`word`),缺席=照常,没有「开」的拼法。
84
83
  *
@@ -2,7 +2,7 @@ export const MEMORY_CAPTURE_SPELLING_MESSAGE = "memoryCapture must be the string
2
2
  export const MEMORY_OFF_SPELLING_MESSAGE = "memory must be the string 'off' when present (the request-level declaration that this run mounts no memory face at all; absent = memory as usual — there is no 'on' spelling; to keep memory mounted but stop this session's content from entering long-term memory, send memoryCapture: 'off' instead)";
3
3
  export const FILE_HISTORY_OFF_SPELLING_MESSAGE = "fileHistory must be the string 'disabled' when present (the request-level declaration that this run records no file history — no backup of an edited file, and no file restore in the same request; absent = the deployment's setting — there is no 'enabled' spelling)";
4
4
  export const PROJECT_MEMORY_OFF_SPELLING_MESSAGE = "projectMemory must be the string 'disabled' when present (the request-level declaration that this run reads none of the deployment's project context — no project instruction files and no project layer; absent = the deployment's project context as usual — there is no 'on' spelling)";
5
- export const FILE_HISTORY_DISABLED_NO_RESTORE = "fileHistory: 'disabled' cannot ride with a file restore (restoreFiles, rewindFilesTo, or the retired rewindFiles) — the request turns this run's file history off and asks to restore files from it in the same breath; the engine would refuse it (rewind.capture_disabled) only after the session had already been branched at resumeAt, which it does not undo, so it is refused here, before any side effect. Drop fileHistory to restore, or drop the restore to run without file history";
5
+ export const FILE_HISTORY_DISABLED_NO_RESTORE = "fileHistory: 'disabled' cannot ride with a file restore (restoreFiles or rewindFilesTo) — the request turns this run's file history off and asks to restore files from it in the same breath; the engine would refuse it (rewind.capture_disabled) only after the session had already been branched at resumeAt, which it does not undo, so it is refused here, before any side effect. Drop fileHistory to restore, or drop the restore to run without file history";
6
6
  export function fileHistoryRestoreConflict(body) {
7
7
  return body.fileHistory === "disabled" && fileHistoryRestoreKeysInBody(body).length > 0;
8
8
  }
@@ -12,8 +12,6 @@ export function fileHistoryRestoreKeysInBody(body) {
12
12
  out.push("restoreFiles");
13
13
  if (typeof body.rewindFilesTo === "string" && body.rewindFilesTo.length > 0)
14
14
  out.push("rewindFilesTo");
15
- if (body.rewindFiles === true)
16
- out.push("rewindFiles");
17
15
  return out;
18
16
  }
19
17
  const SINGLE_MEMBER_OFF_FIELDS = [
@@ -5,7 +5,7 @@ import { createLogger } from "./observability/logger.js";
5
5
  import { ABSOLUTE_HOST_PATH_MAX, hasControlOrBidi } from "@sema-agent/settings-schema";
6
6
  import { isDirectWritableRuleBehavior } from "./permission-rule-vocab.js";
7
7
  import { hasBidiControls } from "./text-bidi.js";
8
- import { confirmRuleApproval, RULE_BEHAVIORS, parseRuleText, ruleReachesProgramRun, ruleToolGrammarOf, precheckEditedRuleText, prepareCardApproval, prepareCcImport, redeemRuleBatch, redeemRuleTicket, addPersistedRule, removePersistedRule, isValidDurableScope, effectiveOrThrow, readRowBehavior, readRuleOwner, } from "@sema-agent/core";
8
+ import { confirmRuleApproval, RULE_BEHAVIORS, parseRuleText, ruleReachesProgramRun, precheckEditedRuleText, prepareCardApproval, prepareCcImport, redeemRuleBatch, redeemRuleTicket, addPersistedRule, removePersistedRule, isValidDurableScope, effectiveOrThrow, readRowBehavior, readRuleOwner, } from "@sema-agent/core";
9
9
  import { buildRulePayloadHash } from "./plugins/permission-rule-store-sql.js";
10
10
  export const RULE_IMPORT_TICKET_TTL_MS = 10 * 60_000;
11
11
  export const RULE_IMPORT_RETRY_AFTER_SEC = 2;
@@ -87,7 +87,7 @@ function storeForBucket(provider, ref) {
87
87
  }
88
88
  }
89
89
  }
90
- function isSupportedRuleMatch(match) {
90
+ function isCommandRuleMatch(match) {
91
91
  switch (match) {
92
92
  case "exact":
93
93
  case "prefix":
@@ -104,6 +104,8 @@ function isSupportedRuleMatch(match) {
104
104
  case "host":
105
105
  case "subdomain":
106
106
  return false;
107
+ case "tool":
108
+ return false;
107
109
  default: {
108
110
  const unknown = match;
109
111
  void unknown;
@@ -205,7 +207,7 @@ function screenLocalImportRow(row) {
205
207
  const written = parseRuleText(row.rule, row.behavior);
206
208
  if ("reject" in written)
207
209
  return { reason: "rule_rejected", detail: `${written.reject.code}: ${written.reject.message}` };
208
- if (ruleToolGrammarOf(written.rule.tool) !== "command")
210
+ if (!isCommandRuleMatch(written.rule.match))
209
211
  return consistent(written.rule);
210
212
  if (written.rule.behavior !== "allow") {
211
213
  if (!ruleReachesProgramRun(written.rule, row.command)) {
@@ -354,7 +356,7 @@ export function createRuleConsentLane(stores, opts) {
354
356
  if ("reject" in canonical) {
355
357
  return { ok: false, reason: "edit-rejected", detail: `the canonical spelling the engine minted does not re-parse: ${canonical.reject.message}` };
356
358
  }
357
- if (!isSupportedRuleMatch(canonical.rule.match)) {
359
+ if (!isCommandRuleMatch(canonical.rule.match)) {
358
360
  return { ok: false, reason: "edit-rejected", detail: `the edited rule resolves to an unsupported match form (${String(canonical.rule.match)})` };
359
361
  }
360
362
  ticket = minted.ticket;
@@ -196,6 +196,12 @@ export declare function promptYesNoOnTty(prompt: string, signal?: AbortSignal, s
196
196
  * or whose approval no person could answer, see {@link unfinishedStopOf} — / a fatal error, 2 = bad usage / unmet env). Pure of
197
197
  * `process.exit` so a test can assert the code; `main()` applies it.
198
198
  */
199
+ /**
200
+ * 本入口拒 `CONFIG_PROVIDER=remote` 的那一句(配置源的词要么兑现、要么拒)。本入口只装本地配置源:中心拉取的那一套 —— 凭据续签、托管模型钥解封、
201
+ * 名册门、LKG —— 只在 HTTP 服务里装配。修前它在 remote 的词下照读本地 `config.d`(判官对「没递中心」回落 local),零句。
202
+ * 配没配中心地址都是这一句:出路(不设词 / 写 `local` / 改跑 HTTP 服务)在本入口照做都兑现得了。
203
+ */
204
+ export declare const RUN_LOCAL_CONFIG_SOURCE_REFUSAL: string;
199
205
  export declare function runLocal(argv: string[], deps?: RunLocalDeps): Promise<number>;
200
206
  /** {@link installRunLocalExitBoundary} 的把手(同进程内反复装配的调用方=测试必须用它收尾)。 */
201
207
  export interface RunLocalExitBoundary {
package/dist/run-local.js CHANGED
@@ -19,10 +19,10 @@ import { applyRuntimeGovernance, autonomyModeFloor, entryPermissionMode } from "
19
19
  import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
20
20
  import { taskWallClockSec } from "./task-workflow.js";
21
21
  import { applyCenterArtifact, centerSourceOnError } from "./capabilities/center-prompts.js";
22
- import { buildUnpricedCeilingNotice, loadConfig, logConfigDiagnostics, parseNumOrFailNonNegative } from "./config.js";
22
+ import { buildUnpricedCeilingNotice, loadConfig, logConfigDiagnostics, parseConfigProvider, parseNumOrFailNonNegative } from "./config.js";
23
23
  import { buildStoreOpenRefusalTail } from "./plugins/store-open-refusal.js";
24
24
  import { acquireLocalBackendWithWait } from "./plugins/store-lock-wait.js";
25
- import { configLocalRoot, configProviderKind, createConfigProvider } from "./config-provider.js";
25
+ import { configLocalRoot, createConfigProvider } from "./config-provider.js";
26
26
  import { CONFIG_DOMAIN_INVALID_NOTE, buildCandidateRejectedFields, judgeConfigCandidate } from "./web-admin-client/candidate-gate.js";
27
27
  import { buildUnreadConfigFileFields, buildUnreadConfigKeyFields } from "./web-admin-client/read-warnings.js";
28
28
  import { composeExecutionLane, settleHostLaneShell } from "./boot/execution-lane.js";
@@ -45,14 +45,16 @@ import { createMemoryEngineIncidentSink } from "./memory-incident-sink.js";
45
45
  import { fileMemoryEngineRoot, memoryEngineBackendFor, memorySpecForRequest } from "./memory-scope.js";
46
46
  import { createMemoryProjectLayers } from "./memory-project-layer.js";
47
47
  import { assertProjectLayerOwnable } from "./project-identity.js";
48
+ import { declaredCredential } from "./model-route-gap.js";
48
49
  import { judgeServedModelRoute } from "./model-route-endpoint.js";
49
- import { createMemorySyncRunner, createMemorySyncTransport } from "./memory-sync-client.js";
50
+ import { buildMemorySyncEnabledFields, createMemorySyncRunner, createMemorySyncTransport } from "./memory-sync-client.js";
50
51
  import { buildPricing, cappedCeiling, createTracer } from "./budget.js";
51
52
  import { createSharedRunnerDeps } from "./boot/runner-deps.js";
53
+ import { createPeerDesk } from "./peer-seat.js";
52
54
  import { createGovernanceSeams } from "./boot/governance-seams.js";
53
55
  import { assertRetentionLaneWirable } from "./boot/retention-lane.js";
54
56
  import { createOrgMemoryAdmissionWiring } from "./boot/org-memory.js";
55
- import { assertDeploymentModsAdmitted, createDeploymentMods } from "./boot/deployment-mods.js";
57
+ import { assembleDeploymentMods } from "./boot/deployment-mods.js";
56
58
  import { createKeyResolver } from "./key-resolver.js";
57
59
  import { createLogger } from "./observability/logger.js";
58
60
  import { fatalExit } from "./boot/fatal-exit.js";
@@ -60,7 +62,6 @@ import { installProcessExitBoundary } from "./boot/exit-boundary.js";
60
62
  import { createMetrics } from "./observability/metrics.js";
61
63
  import { installSecretEnvScrubRecorder } from "./observability/secret-env-scrub.js";
62
64
  import { createHostLspManager } from "./host-lsp-manager.js";
63
- import { buildDisplaySafeUrl } from "./trace/redact.js";
64
65
  import { installOutboundDispatcher } from "./outbound-dispatcher.js";
65
66
  import { provisionSemaConfigDir } from "./sema-config-dir.js";
66
67
  import { bindOwnCredentialsConfig, declareServerWithheldEnv } from "./server-secret-env.js";
@@ -121,7 +122,7 @@ export function missingGatewayRequirements(config) {
121
122
  if (config.gatewayBaseUrl === undefined)
122
123
  return missing;
123
124
  const perModelEnvs = Object.values(config.modelApiKeyEnv ?? {});
124
- const haveGatewayKey = !!config.gatewayApiKey;
125
+ const haveGatewayKey = declaredCredential(config.gatewayApiKey) !== undefined;
125
126
  const catalogModelNames = new Set(Object.values(config.models ?? {}).map((m) => m.name));
126
127
  const allModelsHaveOwnKey = catalogModelNames.size > 0 &&
127
128
  [...catalogModelNames].every((n) => {
@@ -164,6 +165,7 @@ export const NO_TTY_ASK_CLASS_ROW = {
164
165
  shell_floor: { remedy: "shell_gate", autoBudgetReleases: false },
165
166
  target_unresolved: { remedy: "terminal_only", autoBudgetReleases: false },
166
167
  probe: { remedy: "terminal_only", autoBudgetReleases: false },
168
+ write_protection_on_disk: { remedy: "terminal_only", autoBudgetReleases: false },
167
169
  write_protection: { remedy: "terminal_only", autoBudgetReleases: false },
168
170
  tool_marks_mcp: { remedy: "terminal_only", autoBudgetReleases: false },
169
171
  tool_marks_a2a: { remedy: "terminal_only", autoBudgetReleases: false },
@@ -312,6 +314,9 @@ function buildUnfinishedStopFooter(stop, sessionId) {
312
314
  }
313
315
  }
314
316
  }
317
+ export const RUN_LOCAL_CONFIG_SOURCE_REFUSAL = "CONFIG_PROVIDER=remote: run-local reads its configuration from the local config directory only — it does not pull a web-admin center " +
318
+ "(center credential renewal, sealed model keys and the roster gate are assembled by the HTTP service). Unset CONFIG_PROVIDER or set " +
319
+ "CONFIG_PROVIDER=local for this command, or run the HTTP service to use the center.";
315
320
  export async function runLocal(argv, deps = {}) {
316
321
  const print = deps.print ?? ((l) => console.log(l));
317
322
  const printErr = deps.printErr ?? ((l) => console.error(l));
@@ -326,7 +331,12 @@ export async function runLocal(argv, deps = {}) {
326
331
  }
327
332
  throw err;
328
333
  }
329
- if (!process.env.CONFIG_PROVIDER)
334
+ const configWord = parseConfigProvider();
335
+ if (configWord === "remote") {
336
+ printErr(RUN_LOCAL_CONFIG_SOURCE_REFUSAL);
337
+ return 2;
338
+ }
339
+ if (configWord === undefined)
330
340
  process.env.CONFIG_PROVIDER = "local";
331
341
  process.env.SESSION_BACKEND = "memory";
332
342
  process.env.REQUIRE_PRINCIPAL = "false";
@@ -343,26 +353,25 @@ export async function runLocal(argv, deps = {}) {
343
353
  logConfigDiagnostics(logger);
344
354
  provisionSemaConfigDir(config, logger);
345
355
  installOutboundDispatcher(logger);
346
- const providerInput = { provider: config.configProvider ?? "local", localDir: root, localOwnerUid: config.configLocalOwnerUid };
347
- const configSource = configProviderKind(providerInput);
348
- if (configSource === "local") {
349
- try {
350
- await assertLocalConfigDirTrusted({ root, declaredOwnerUid: config.configLocalOwnerUid });
351
- }
352
- catch (err) {
353
- printErr(err instanceof Error ? err.message : String(err));
354
- return 2;
355
- }
356
- logConfigDirMigration(logger, await migrateLocalConfigDirectory(root));
356
+ const providerInput = { provider: "local", localDir: root, localOwnerUid: config.configLocalOwnerUid };
357
+ try {
358
+ await assertLocalConfigDirTrusted({ root, declaredOwnerUid: config.configLocalOwnerUid });
359
+ }
360
+ catch (err) {
361
+ printErr(err instanceof Error ? err.message : String(err));
362
+ return 2;
357
363
  }
364
+ logConfigDirMigration(logger, await migrateLocalConfigDirectory(root));
358
365
  try {
359
- await composeExecutionLane(config, { configSource, localRoot: root, logger, drivesFromFile: ["host"] });
366
+ await composeExecutionLane(config, { configSource: "local", localRoot: root, logger, drivesFromFile: ["host"] });
360
367
  }
361
368
  catch (err) {
362
369
  printErr(err instanceof Error ? err.message : String(err));
363
370
  return 2;
364
371
  }
365
372
  const configProvider = createConfigProvider(providerInput);
373
+ const peerDesk = createPeerDesk({ log: logger });
374
+ const rosterLease = peerDesk.lease("roster");
366
375
  let effective;
367
376
  let candidatePrompts;
368
377
  let applying = false;
@@ -387,9 +396,9 @@ export async function runLocal(argv, deps = {}) {
387
396
  effective = r.effective;
388
397
  candidatePrompts = verdict.prompts;
389
398
  if (effective?.mcp)
390
- config.mcpServers = resolveMcpServers(effective.mcp, logger);
399
+ config.mcpServers = resolveMcpServers(effective.mcp, peerDesk, rosterLease, logger);
391
400
  if (effective?.a2a)
392
- config.a2aPeers = resolveA2aPeers(effective.a2a, logger);
401
+ config.a2aPeers = resolveA2aPeers(effective.a2a, peerDesk, rosterLease, logger);
393
402
  applyCenterReadFace(config, r.effective, logger, { phase: "boot" });
394
403
  logger.info("config_loaded", { source: configProvider.kind, version: r.effective.version });
395
404
  }
@@ -485,16 +494,17 @@ export async function runLocal(argv, deps = {}) {
485
494
  }
486
495
  let memorySync;
487
496
  if (config.memorySync && memoryEngine) {
497
+ const transport = createMemorySyncTransport({ url: config.memorySync.url, token: config.memorySync.token });
488
498
  memorySync = createMemorySyncRunner({
489
499
  backend: memoryEngine.backend,
490
500
  scope: config.memorySync.scope,
491
501
  memoryRoot: memoryEngine.root,
492
- transport: createMemorySyncTransport({ url: config.memorySync.url, token: config.memorySync.token }),
502
+ transport,
493
503
  log: logger,
494
504
  ...(config.memorySync.maxPushEntries !== undefined ? { maxPushEntries: config.memorySync.maxPushEntries } : {}),
495
505
  ...(config.memorySync.maxPullEntries !== undefined ? { maxPullEntries: config.memorySync.maxPullEntries } : {}),
496
506
  });
497
- logger.info("memory_sync_enabled", { url: buildDisplaySafeUrl(config.memorySync.url), scope: config.memorySync.scope, cursorPath: memorySync.cursorPathFor(config.memorySync.scope) });
507
+ logger.info("memory_sync_enabled", buildMemorySyncEnabledFields(transport.peer, config.memorySync.scope, memorySync.cursorPathFor(config.memorySync.scope)));
498
508
  memorySync.trigger("boot");
499
509
  }
500
510
  else if (config.memorySync) {
@@ -559,7 +569,6 @@ export async function runLocal(argv, deps = {}) {
559
569
  }
560
570
  assertRetentionLaneWirable({
561
571
  intervalSec: config.retentionSweep.intervalSec,
562
- policy: config.retentionPolicy,
563
572
  executor: undefined,
564
573
  stores: [
565
574
  { name: "sessionStore", store: sessionStore },
@@ -576,9 +585,9 @@ export async function runLocal(argv, deps = {}) {
576
585
  { name: "checkpointStore", store: fileBackend.checkpointStore },
577
586
  { name: "toolResultStore", store: fileBackend.toolResultStore },
578
587
  ],
588
+ retentionExecutor: null,
579
589
  });
580
- const deploymentMods = createDeploymentMods({ metrics, brandIdentity: true });
581
- await assertDeploymentModsAdmitted(deploymentMods);
590
+ const { registrations: deploymentMods } = await assembleDeploymentMods({ metrics, brandIdentity: true, declaration: config.modsDeclaration, logger });
582
591
  const sharedRunnerDeps = createSharedRunnerDeps({
583
592
  metrics,
584
593
  config,
@@ -603,6 +612,7 @@ export async function runLocal(argv, deps = {}) {
603
612
  orgMemoryAdmission,
604
613
  sharedMemoryStores: undefined,
605
614
  mcpRevocations: undefined,
615
+ peerDesk,
606
616
  });
607
617
  const runnerDeps = {
608
618
  ...sharedRunnerDeps,
package/dist/runs.d.ts CHANGED
@@ -11,6 +11,7 @@ import { type ApprovalFrameFamily, type ToolApprovalCoordinator } from "./tool-a
11
11
  import { type FleetRunPublisher } from "./fleet/fleet-bus.js";
12
12
  import { type WorkflowCompletionInbox } from "./orchestration/workflow-completion-inbox.js";
13
13
  import type { RunAcceptance } from "./run-acceptance.js";
14
+ import type { SessionWorkspaceRecorder } from "./session-workspace.js";
14
15
  import type { VerifyRoundsSpec } from "./http/verify-rounds.js";
15
16
  import type { UserInputLedger } from "./user-input-ledger.js";
16
17
  /**
@@ -331,7 +332,8 @@ approval?: {
331
332
  streamApprovalOn: boolean;
332
333
  windowMs: number | undefined;
333
334
  windowMarginMs: number;
334
- declaredFamilies: ReadonlySet<ApprovalFrameFamily>;
335
+ declaredFamilies: ReadonlySet<ApprovalFrameFamily>; /** 出处带车道:这条执行上下文的车道(装配点 `durable-run-leg.ts` 写 `ctx.lane`)。 */
336
+ executionLane: import("./execution-lane-caps.js").ExecutionLane;
335
337
  },
336
338
  /** [ref]:park 投影腿的 checkpoint 读口(`deps.checkpointStore`)。在场时,durable park 的
337
339
  * `suspended` 事件带 `toolCallId`(graft 见 {@link parkToolCallId});缺席=旧字节逐字不变。 */
@@ -374,7 +376,12 @@ userInputLedger?: UserInputLedger,
374
376
  * 这次提交的受理座(`src/run-acceptance.ts`):标题器只在引擎受理之后起。普通流形逐帧喂;只回结果的 verify / cascade 形(以及终局写口的
375
377
  * 重试腿)终局落行之后收尾一次。缺席 ⇒ 不起标题(起标题此前由路由层在建行时做)。
376
378
  */
377
- acceptance?: RunAcceptance): Promise<void>;
379
+ acceptance?: RunAcceptance,
380
+ /**
381
+ * 会话行的位置与项目那一格的记录座(`session-workspace.ts`;唯一写者):普通流形逐帧喂(这条腿自己的 `workspace_changed` 排一次写),
382
+ * `done` 时等写落定再落终局。只回结果的 verify / cascade 形宿主手里没有流 ⇒ 不记。缺席 ⇒ 不记行(与本参数存在之前逐字相同)。
383
+ */
384
+ workspaceRecorder?: SessionWorkspaceRecorder): Promise<void>;
378
385
  /** How often a running instance refreshes its run's updated_at (liveness, independent of events).
379
386
  * Must stay strictly below `runStaleSec` (asserted at startup AND on every hot config candidate) or the
380
387
  * reaper would race live runs. [ref]:数值的单源是 `config-invariants.ts`(那条不变量的属主),两个消费面
package/dist/runs.js CHANGED
@@ -84,6 +84,10 @@ const PREPARE_REFUSAL_HTTP_STATUS = {
84
84
  "config.legacy_tool_name": 400,
85
85
  "config.memory_capture_unsupported": 409,
86
86
  "prompt.assembled_role_refused": 400,
87
+ "config.project_id_invalid": 400,
88
+ "config.project_identity_mismatch": 409,
89
+ "config.memory_project_marker": 409,
90
+ "config.memory_project_marker_nested": 409,
87
91
  };
88
92
  export function resumeAtHttpStatus(result) {
89
93
  const code = failureCodeOf(result.terminal);
@@ -253,7 +257,7 @@ export async function graftParkToolCallId(result, cs) {
253
257
  const id = await parkToolCallId(result, cs);
254
258
  return id === undefined ? result : { ...result, toolCallId: id };
255
259
  }
256
- export async function runInBackground(runner, spec, runStore, taskId, metrics, principal, verify, cascade, instrumentDegenerate, planCacheProbe, persistThinking = false, inflight, preemptable, steerable, modelUsage, elicitation, elicitOwner, captureTurnAnchor, fleetPublisher, captureUserMessageAnchor, question, workflowCompletionInbox, subagentSteer, completionDiagLog, sendUserFile, promptManifests, approval, parkCheckpointReader, pendingEngineNotices, trustedInternals, userInputLedger, acceptance) {
260
+ export async function runInBackground(runner, spec, runStore, taskId, metrics, principal, verify, cascade, instrumentDegenerate, planCacheProbe, persistThinking = false, inflight, preemptable, steerable, modelUsage, elicitation, elicitOwner, captureTurnAnchor, fleetPublisher, captureUserMessageAnchor, question, workflowCompletionInbox, subagentSteer, completionDiagLog, sendUserFile, promptManifests, approval, parkCheckpointReader, pendingEngineNotices, trustedInternals, userInputLedger, acceptance, workspaceRecorder) {
257
261
  const startedAt = Date.now();
258
262
  metrics?.addGauge("runs_active", 1);
259
263
  fleetPublisher?.onStart();
@@ -292,11 +296,12 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
292
296
  if (approval) {
293
297
  const coordinator = approval.coordinator;
294
298
  spec.onAsk = approvalLeg.unattended
295
- ? coordinator.boundUnattendedAsk({ owner: elicitOwner ?? owner, taskId, ...(spec.sessionId ? { sessionId: spec.sessionId } : {}) }, approvalLeg.unattended)
299
+ ? coordinator.boundUnattendedAsk({ owner: elicitOwner ?? owner, taskId, ...(spec.sessionId ? { sessionId: spec.sessionId } : {}), executionLane: approval.executionLane }, approvalLeg.unattended)
296
300
  : coordinator.boundAsk({
297
301
  owner: elicitOwner ?? owner,
298
302
  taskId,
299
303
  ...(spec.sessionId ? { sessionId: spec.sessionId } : {}),
304
+ executionLane: approval.executionLane,
300
305
  ...(approvalLeg.active ? { legKey: "", ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
301
306
  });
302
307
  }
@@ -453,6 +458,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
453
458
  fleetPublisher?.onEvent(ev);
454
459
  await userInputLedger?.observeLegEvent(stream, ev);
455
460
  acceptance?.observe(ev);
461
+ await workspaceRecorder?.observe(ev);
456
462
  await flushPromptManifest();
457
463
  switch (ev.type) {
458
464
  case "text_delta":
@@ -526,6 +532,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
526
532
  owner: elicitOwner ?? owner,
527
533
  abortSignal: cancelCtrl.signal,
528
534
  ...(spec.sessionId ? { sessionId: spec.sessionId } : {}),
535
+ executionLane: approval.executionLane,
529
536
  emitCard: createApprovalCardEmitter({ appendDurable: (f) => approvalEmit(f) }),
530
537
  emitRevoke: (f) => approvalEmit(f),
531
538
  legKey: "",