@sema-agent/server 7.145.0 → 7.147.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 (526) hide show
  1. package/MIGRATION.md +876 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +374 -99
  5. package/deploy/facts/CHANGES.json +25 -0
  6. package/deploy/facts/README.md +57 -0
  7. package/deploy/facts/lanes.json +61 -0
  8. package/deploy/facts/lanes.schema.json +57 -0
  9. package/deploy/facts/sandbox-rbac.json +113 -0
  10. package/deploy/facts/sandbox-rbac.schema.json +74 -0
  11. package/deploy/facts/sealed-key.json +9 -0
  12. package/deploy/facts/sealed-key.schema.json +52 -0
  13. package/deploy/sema-up/README.md +2 -2
  14. package/deploy/sema-up/chart/templates/_helpers.tpl +41 -0
  15. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
  16. package/deploy/sema-up/chart/templates/server-v4pro.yaml +9 -4
  17. package/deploy/sema-up/chart/templates/server.yaml +9 -4
  18. package/deploy/sema-up/chart/values.yaml +8 -1
  19. package/deploy/sema-up/cluster-up.sh +2 -1
  20. package/deploy/sema-up/lib/flagshape.sh +4 -0
  21. package/deploy/sema-up/lib/lanes.json +2 -5
  22. package/deploy/sema-up/sema-up.sh +12 -9
  23. package/deploy/sema-up/stack/compose.yaml +5 -4
  24. package/deploy/sema-up/stack/sema-stack-cluster.yaml +34 -17
  25. package/dist/adoption/import-limits.d.ts +6 -0
  26. package/dist/adoption/import-limits.js +7 -0
  27. package/dist/adoption/import.d.ts +62 -0
  28. package/dist/adoption/import.js +107 -0
  29. package/dist/adoption/wire.d.ts +52 -0
  30. package/dist/adoption/wire.js +9 -0
  31. package/dist/approval-ask-machine.d.ts +2 -2
  32. package/dist/approval-card.d.ts +7 -16
  33. package/dist/approval-card.js +0 -4
  34. package/dist/approval-gate-currency.d.ts +1 -1
  35. package/dist/approval-gate-currency.js +1 -1
  36. package/dist/approval-reconciler.d.ts +1 -1
  37. package/dist/approval.d.ts +3 -3
  38. package/dist/audit.js +2 -2
  39. package/dist/bench/s1/live-deps.js +3 -1
  40. package/dist/boot/crash-last.js +2 -1
  41. package/dist/boot/deployment-mods.d.ts +11 -1
  42. package/dist/boot/deployment-mods.js +15 -2
  43. package/dist/boot/device-lane.js +7 -5
  44. package/dist/boot/engine-lease.d.ts +195 -22
  45. package/dist/boot/engine-lease.js +146 -20
  46. package/dist/boot/execution-env.d.ts +5 -0
  47. package/dist/boot/execution-env.js +57 -33
  48. package/dist/boot/execution-lane.d.ts +37 -9
  49. package/dist/boot/execution-lane.js +74 -20
  50. package/dist/boot/exit-boundary.d.ts +50 -0
  51. package/dist/boot/exit-boundary.js +32 -0
  52. package/dist/boot/exit-last.d.ts +20 -4
  53. package/dist/boot/exit-last.js +23 -5
  54. package/dist/boot/governance-seams.d.ts +2 -2
  55. package/dist/boot/governance-seams.js +1 -0
  56. package/dist/boot/leader.js +1 -1
  57. package/dist/boot/memory-boundary.d.ts +11 -11
  58. package/dist/boot/memory-boundary.js +3 -3
  59. package/dist/boot/memory-consolidation.d.ts +42 -41
  60. package/dist/boot/memory-consolidation.js +26 -28
  61. package/dist/boot/org-memory.js +3 -2
  62. package/dist/boot/parked-revive-gate.d.ts +1 -1
  63. package/dist/boot/parked-revive-gate.js +1 -1
  64. package/dist/boot/reapers.d.ts +12 -4
  65. package/dist/boot/reapers.js +40 -16
  66. package/dist/boot/resolve-spec.d.ts +2 -0
  67. package/dist/boot/resolve-spec.js +126 -123
  68. package/dist/boot/retention-lane.d.ts +4 -42
  69. package/dist/boot/runner-deps.js +1 -1
  70. package/dist/boot/session-faces.d.ts +1 -0
  71. package/dist/boot/session-faces.js +11 -3
  72. package/dist/boot/shutdown.js +27 -9
  73. package/dist/boot/stage-01-config.d.ts +1 -1
  74. package/dist/boot/stage-01-config.js +7 -3
  75. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
  76. package/dist/boot/stage-02-web-admin-pull.js +10 -8
  77. package/dist/boot/stage-03-store-backend.d.ts +2 -1
  78. package/dist/boot/stage-03-store-backend.js +2 -2
  79. package/dist/boot/stage-04-stores.d.ts +2 -1
  80. package/dist/boot/stage-05-execution-env.d.ts +4 -1
  81. package/dist/boot/stage-05-execution-env.js +6 -6
  82. package/dist/boot/stage-06-runners.d.ts +5 -2
  83. package/dist/boot/stage-06-runners.js +12 -13
  84. package/dist/boot/stage-07-capability-layer.d.ts +5 -2
  85. package/dist/boot/stage-07-capability-layer.js +7 -7
  86. package/dist/boot/stage-08-reapers.d.ts +5 -2
  87. package/dist/boot/stage-08-reapers.js +3 -3
  88. package/dist/boot/stage-09-leader.d.ts +6 -2
  89. package/dist/boot/stage-10-http-server.d.ts +6 -2
  90. package/dist/boot/stage-10-http-server.js +5 -3
  91. package/dist/boot/stores.d.ts +10 -0
  92. package/dist/boot/stores.js +53 -26
  93. package/dist/boot/web-admin.js +3 -3
  94. package/dist/boot/workflow-orchestration.d.ts +1 -1
  95. package/dist/boot/workflow-orchestration.js +2 -1
  96. package/dist/capabilities/center-plugins.d.ts +2 -0
  97. package/dist/capabilities/center-plugins.js +6 -2
  98. package/dist/capabilities/composite-members.d.ts +4 -1
  99. package/dist/capabilities/composite-members.js +4 -1
  100. package/dist/capabilities/execution-lane.d.ts +7 -7
  101. package/dist/capabilities/execution-lane.js +2 -2
  102. package/dist/capabilities/hands-lane.d.ts +1 -1
  103. package/dist/capabilities/scenarios.d.ts +34 -20
  104. package/dist/capabilities/scenarios.js +13 -9
  105. package/dist/capabilities/settings-contract.d.ts +29 -0
  106. package/dist/capabilities/settings-contract.js +14 -0
  107. package/dist/capabilities/skills.d.ts +5 -5
  108. package/dist/capability-facts.d.ts +56 -1
  109. package/dist/capability-facts.js +59 -8
  110. package/dist/center-credential-renewer.js +3 -2
  111. package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
  112. package/dist/config-catalog.js +19 -9
  113. package/dist/config-invariants.d.ts +18 -3
  114. package/dist/config-invariants.js +36 -19
  115. package/dist/config-lkg.d.ts +1 -1
  116. package/dist/config-lkg.js +5 -6
  117. package/dist/config-provider.d.ts +2 -2
  118. package/dist/config-provider.js +2 -0
  119. package/dist/config-types.d.ts +228 -185
  120. package/dist/config.d.ts +74 -6
  121. package/dist/config.js +146 -64
  122. package/dist/degenerate-instrument.js +1 -1
  123. package/dist/deleted-session-ids.d.ts +19 -0
  124. package/dist/deleted-session-ids.js +26 -0
  125. package/dist/deploy-facts.d.ts +155 -0
  126. package/dist/deploy-facts.js +95 -0
  127. package/dist/deployment-shape.d.ts +21 -12
  128. package/dist/deployment-shape.js +24 -6
  129. package/dist/device-ws-hub.d.ts +48 -3
  130. package/dist/device-ws-hub.js +48 -2
  131. package/dist/env-facts.d.ts +7 -5
  132. package/dist/env-facts.js +10 -6
  133. package/dist/error-code-family.d.ts +35 -0
  134. package/dist/error-code-family.js +26 -0
  135. package/dist/execution-config-root.d.ts +5 -5
  136. package/dist/execution-config-root.js +5 -5
  137. package/dist/execution-env-purpose.d.ts +14 -0
  138. package/dist/execution-env-purpose.js +29 -0
  139. package/dist/execution-lane-caps.d.ts +49 -86
  140. package/dist/execution-lane-caps.js +52 -62
  141. package/dist/execution-placement.d.ts +18 -2
  142. package/dist/execution-placement.js +19 -0
  143. package/dist/file-history-disclosure.d.ts +2 -2
  144. package/dist/fleet/drain-entry.d.ts +46 -3
  145. package/dist/fleet/drain-entry.js +6 -0
  146. package/dist/fleet/fleet-bus.d.ts +2 -1
  147. package/dist/fleet/serving-lease.js +3 -4
  148. package/dist/history-anchor.d.ts +22 -0
  149. package/dist/history-anchor.js +14 -0
  150. package/dist/hooks/branch-transcript.d.ts +1 -1
  151. package/dist/hooks/branch-transcript.js +1 -0
  152. package/dist/hooks/classic-stations.d.ts +25 -8
  153. package/dist/hooks/classic-stations.js +29 -3
  154. package/dist/hooks/command-spawn.d.ts +1 -4
  155. package/dist/hooks/command-spawn.js +0 -11
  156. package/dist/hooks/hook-runner.d.ts +85 -24
  157. package/dist/hooks/hook-runner.js +326 -109
  158. package/dist/hooks/hook-source.d.ts +14 -2
  159. package/dist/hooks/hook-source.js +8 -0
  160. package/dist/http/active-run-conflict.d.ts +1 -1
  161. package/dist/http/active-run-conflict.js +1 -1
  162. package/dist/http/admission.js +11 -1
  163. package/dist/http/approval-sweeps.d.ts +2 -5
  164. package/dist/http/approval-sweeps.js +3 -2
  165. package/dist/http/checkpoint-ctx.d.ts +76 -71
  166. package/dist/http/checkpoint-ctx.js +40 -40
  167. package/dist/http/claim-latency.d.ts +10 -0
  168. package/dist/http/claim-latency.js +12 -0
  169. package/dist/http/dispatch.js +19 -3
  170. package/dist/http/durable-run-leg.d.ts +5 -0
  171. package/dist/http/durable-run-leg.js +3 -1
  172. package/dist/http/execution-context.d.ts +7 -1
  173. package/dist/http/execution-context.js +13 -0
  174. package/dist/http/health-self-report.d.ts +6 -2
  175. package/dist/http/health-self-report.js +3 -2
  176. package/dist/http/memory-compliance-failure-reply.d.ts +2 -2
  177. package/dist/http/memory-compliance-failure-reply.js +5 -15
  178. package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
  179. package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
  180. package/dist/http/memory-store-refusal-reply.d.ts +3 -3
  181. package/dist/http/memory-store-refusal-reply.js +3 -0
  182. package/dist/http/owner-access.d.ts +11 -0
  183. package/dist/http/owner-access.js +7 -4
  184. package/dist/http/principal-gate.d.ts +28 -16
  185. package/dist/http/principal-gate.js +10 -19
  186. package/dist/http/request-guards.d.ts +2 -2
  187. package/dist/http/request-guards.js +5 -5
  188. package/dist/http/resume-legs.d.ts +29 -10
  189. package/dist/http/resume-legs.js +94 -56
  190. package/dist/http/rewind-files-reply.d.ts +34 -0
  191. package/dist/http/rewind-files-reply.js +36 -0
  192. package/dist/http/route-ctx.d.ts +43 -26
  193. package/dist/http/route-table.js +4 -0
  194. package/dist/http/routes/adoption.d.ts +11 -0
  195. package/dist/http/routes/adoption.js +80 -6
  196. package/dist/http/routes/agents-roster.js +1 -0
  197. package/dist/http/routes/approvals-assistant.js +7 -26
  198. package/dist/http/routes/background.js +1 -0
  199. package/dist/http/routes/capabilities.js +12 -3
  200. package/dist/http/routes/devices.js +1 -1
  201. package/dist/http/routes/diagnostics.d.ts +9 -14
  202. package/dist/http/routes/diagnostics.js +10 -20
  203. package/dist/http/routes/engine.d.ts +31 -0
  204. package/dist/http/routes/engine.js +81 -0
  205. package/dist/http/routes/memory-bundle.js +3 -0
  206. package/dist/http/routes/memory-consolidation.js +3 -5
  207. package/dist/http/routes/memory-origin.d.ts +2 -2
  208. package/dist/http/routes/memory-origin.js +2 -4
  209. package/dist/http/routes/memory-policy.js +5 -1
  210. package/dist/http/routes/notify-wake.js +2 -1
  211. package/dist/http/routes/observability.js +3 -6
  212. package/dist/http/routes/projects.d.ts +70 -0
  213. package/dist/http/routes/projects.js +86 -0
  214. package/dist/http/routes/rules.js +30 -2
  215. package/dist/http/routes/runs.js +15 -11
  216. package/dist/http/routes/session-sync.js +39 -35
  217. package/dist/http/routes/sessions-list.d.ts +1 -1
  218. package/dist/http/routes/sessions.d.ts +7 -1
  219. package/dist/http/routes/sessions.js +108 -2
  220. package/dist/http/routes/tasks.js +32 -8
  221. package/dist/http/routes/trace-usage.js +1 -1
  222. package/dist/http/run-concurrency-cap.d.ts +86 -0
  223. package/dist/http/run-concurrency-cap.js +54 -0
  224. package/dist/http/server.d.ts +31 -14
  225. package/dist/http/server.js +29 -3
  226. package/dist/http/stored-body-replay.d.ts +12 -7
  227. package/dist/http/stored-body-replay.js +28 -5
  228. package/dist/http/wire-types.d.ts +27 -13
  229. package/dist/index.d.ts +2 -2
  230. package/dist/index.js +1 -1
  231. package/dist/instruction-source-notice.d.ts +1 -1
  232. package/dist/json-body-limit.d.ts +8 -0
  233. package/dist/json-body-limit.js +2 -0
  234. package/dist/leader/diffout.d.ts +1 -1
  235. package/dist/local-data-root.d.ts +2 -2
  236. package/dist/memory-embedder-reembed.d.ts +38 -0
  237. package/dist/memory-embedder-reembed.js +20 -0
  238. package/dist/memory-incident-sink.d.ts +0 -28
  239. package/dist/memory-incident-sink.js +5 -0
  240. package/dist/memory-operator-faces.d.ts +9 -4
  241. package/dist/memory-scope-stores.d.ts +9 -7
  242. package/dist/memory-scope-stores.js +3 -14
  243. package/dist/memory-scope.d.ts +38 -2
  244. package/dist/memory-scope.js +33 -2
  245. package/dist/memory-store-refusal.d.ts +17 -4
  246. package/dist/memory-store-refusal.js +1 -1
  247. package/dist/memory-sync-client.d.ts +2 -0
  248. package/dist/memory-sync-client.js +13 -11
  249. package/dist/memory-sync.js +1 -1
  250. package/dist/model-compat.d.ts +35 -21
  251. package/dist/model-compat.js +49 -21
  252. package/dist/model-entry-refusal.d.ts +11 -1
  253. package/dist/model-entry-refusal.js +7 -0
  254. package/dist/namespaced-rule-name.d.ts +18 -1
  255. package/dist/namespaced-rule-name.js +12 -0
  256. package/dist/net-address.d.ts +53 -0
  257. package/dist/net-address.js +111 -0
  258. package/dist/observability/fail-open.d.ts +29 -17
  259. package/dist/observability/fail-open.js +29 -17
  260. package/dist/observability/metrics.d.ts +2 -0
  261. package/dist/observability/metrics.js +2 -0
  262. package/dist/observability/secret-env-scrub.d.ts +30 -4
  263. package/dist/observability/secret-env-scrub.js +15 -3
  264. package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
  265. package/dist/orchestration/workflow-agent-session-index.js +1 -6
  266. package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
  267. package/dist/orchestration/workflow-completion-inbox.js +63 -45
  268. package/dist/orchestration/workflow-notify-journal.js +2 -3
  269. package/dist/org-delivery-gate.js +1 -1
  270. package/dist/org-memory-admission.d.ts +5 -2
  271. package/dist/org-memory-admission.js +25 -10
  272. package/dist/parked-decide.d.ts +33 -26
  273. package/dist/parked-decide.js +36 -44
  274. package/dist/peer-directory.d.ts +6 -12
  275. package/dist/peer-directory.js +5 -1
  276. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  277. package/dist/plugins/approval-ask-store-file.js +37 -4
  278. package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
  279. package/dist/plugins/approval-ask-store-memory.js +11 -2
  280. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  281. package/dist/plugins/approval-ask-store-sql.js +3 -1
  282. package/dist/plugins/blob-backend.d.ts +38 -195
  283. package/dist/plugins/blob-backend.js +33 -229
  284. package/dist/plugins/caching-session-store.d.ts +12 -5
  285. package/dist/plugins/caching-session-store.js +3 -0
  286. package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
  287. package/dist/plugins/checkpoint-index-columns.js +3 -2
  288. package/dist/plugins/checkpoint-store-face.d.ts +426 -0
  289. package/dist/plugins/checkpoint-store-face.js +152 -0
  290. package/dist/plugins/device-store-sql.d.ts +2 -2
  291. package/dist/plugins/device-store-sql.js +5 -10
  292. package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
  293. package/dist/plugins/execution-lane-rename-m40.js +10 -0
  294. package/dist/plugins/execution-placement-sql.d.ts +63 -88
  295. package/dist/plugins/execution-placement-sql.js +94 -54
  296. package/dist/plugins/file-run-store.d.ts +26 -18
  297. package/dist/plugins/file-run-store.js +64 -75
  298. package/dist/plugins/fork-routing-session-store.d.ts +6 -2
  299. package/dist/plugins/fork-routing-session-store.js +2 -2
  300. package/dist/plugins/imported-layer-root-retirement.d.ts +22 -11
  301. package/dist/plugins/imported-layer-root-retirement.js +4 -8
  302. package/dist/plugins/inbox-payload-column.d.ts +14 -0
  303. package/dist/plugins/inbox-payload-column.js +13 -0
  304. package/dist/plugins/local-checkpoint-store.d.ts +7 -2
  305. package/dist/plugins/local-checkpoint-store.js +13 -8
  306. package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
  307. package/dist/plugins/local-data-dir-modes-m39.js +182 -0
  308. package/dist/plugins/local-engine-high-water.d.ts +11 -0
  309. package/dist/plugins/local-engine-high-water.js +59 -0
  310. package/dist/plugins/local-session-store.d.ts +119 -30
  311. package/dist/plugins/local-session-store.js +156 -53
  312. package/dist/plugins/local-task-attachment-store.d.ts +2 -0
  313. package/dist/plugins/local-task-attachment-store.js +10 -11
  314. package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
  315. package/dist/plugins/memory-embedder-fingerprint.js +52 -12
  316. package/dist/plugins/memory-embedder.d.ts +1 -1
  317. package/dist/plugins/memory-embedder.js +2 -2
  318. package/dist/plugins/memory-engine-pg.d.ts +30 -6
  319. package/dist/plugins/memory-engine-pg.js +96 -214
  320. package/dist/plugins/memory-engine-sql-apply.d.ts +130 -0
  321. package/dist/plugins/memory-engine-sql-apply.js +358 -0
  322. package/dist/plugins/memory-engine-tidb.d.ts +38 -9
  323. package/dist/plugins/memory-engine-tidb.js +99 -230
  324. package/dist/plugins/memory-key-guards.d.ts +1 -1
  325. package/dist/plugins/memory-origin-law.d.ts +3 -3
  326. package/dist/plugins/one-time-migrations.d.ts +169 -83
  327. package/dist/plugins/one-time-migrations.js +295 -235
  328. package/dist/plugins/owner-only-file-mode.d.ts +29 -0
  329. package/dist/plugins/owner-only-file-mode.js +141 -0
  330. package/dist/plugins/permission-rule-store-file.d.ts +17 -3
  331. package/dist/plugins/permission-rule-store-file.js +20 -1
  332. package/dist/plugins/pg-pool.d.ts +2 -1
  333. package/dist/plugins/pg-pool.js +12 -5
  334. package/dist/plugins/release-version.d.ts +20 -0
  335. package/dist/plugins/release-version.js +28 -0
  336. package/dist/plugins/remote-env-adb.d.ts +20 -4
  337. package/dist/plugins/remote-env-adb.js +39 -11
  338. package/dist/plugins/remote-env-e2b.d.ts +12 -3
  339. package/dist/plugins/remote-env-e2b.js +6 -4
  340. package/dist/plugins/remote-env-host.d.ts +9 -1
  341. package/dist/plugins/remote-env-host.js +6 -5
  342. package/dist/plugins/remote-env-k8s.d.ts +5 -2
  343. package/dist/plugins/remote-env-k8s.js +15 -4
  344. package/dist/plugins/remote-env-local-docker.d.ts +4 -1
  345. package/dist/plugins/remote-env-local-docker.js +3 -3
  346. package/dist/plugins/remote-env-ssh.d.ts +8 -2
  347. package/dist/plugins/remote-env-ssh.js +26 -24
  348. package/dist/plugins/remote-shell.d.ts +59 -30
  349. package/dist/plugins/remote-shell.js +175 -62
  350. package/dist/plugins/retention-declaration.d.ts +37 -0
  351. package/dist/plugins/retention-declaration.js +9 -0
  352. package/dist/plugins/retention-deployment.d.ts +126 -0
  353. package/dist/plugins/retention-deployment.js +88 -0
  354. package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
  355. package/dist/plugins/retention-lane-store-sql.js +103 -1
  356. package/dist/plugins/retention-sql.d.ts +29 -0
  357. package/dist/plugins/retention-sql.js +8 -0
  358. package/dist/plugins/run-store-sql.js +2 -2
  359. package/dist/plugins/schema-consistency.d.ts +0 -6
  360. package/dist/plugins/schema-consistency.js +1 -2
  361. package/dist/plugins/schema-ensure-legs.d.ts +1 -1
  362. package/dist/plugins/schema-ensure-legs.js +13 -3
  363. package/dist/plugins/session-ext-table.d.ts +74 -0
  364. package/dist/plugins/session-ext-table.js +121 -0
  365. package/dist/plugins/session-fork.d.ts +31 -9
  366. package/dist/plugins/session-fork.js +3 -2
  367. package/dist/plugins/session-placement.d.ts +4 -2
  368. package/dist/plugins/session-row-sql.d.ts +8 -7
  369. package/dist/plugins/session-row-sql.js +15 -7
  370. package/dist/plugins/session-store-sql.d.ts +131 -0
  371. package/dist/plugins/session-store-sql.js +298 -0
  372. package/dist/plugins/session-workspace-cell.d.ts +2 -2
  373. package/dist/plugins/session-workspace-cell.js +2 -2
  374. package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
  375. package/dist/plugins/shared-memory-store-sql.js +13 -13
  376. package/dist/plugins/snapshot-bucket-presence.js +1 -1
  377. package/dist/plugins/sql-driver.d.ts +23 -7
  378. package/dist/plugins/sql-driver.js +41 -8
  379. package/dist/plugins/sql-errors.d.ts +5 -2
  380. package/dist/plugins/sql-errors.js +4 -0
  381. package/dist/plugins/sql-json-column.d.ts +5 -1
  382. package/dist/plugins/store-backend.d.ts +46 -16
  383. package/dist/plugins/store-backend.js +192 -69
  384. package/dist/plugins/store-contracts.d.ts +10 -13
  385. package/dist/plugins/store-contracts.js +1 -9
  386. package/dist/plugins/store-sweep.d.ts +63 -0
  387. package/dist/plugins/store-sweep.js +48 -0
  388. package/dist/plugins/task-attachment-store.d.ts +6 -8
  389. package/dist/plugins/task-attachment-store.js +15 -10
  390. package/dist/plugins/task-list-store-sql.d.ts +1 -1
  391. package/dist/plugins/text-column-capacity.d.ts +21 -0
  392. package/dist/plugins/text-column-capacity.js +5 -0
  393. package/dist/plugins/tidb-pool.d.ts +3 -2
  394. package/dist/plugins/tidb-pool.js +20 -32
  395. package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
  396. package/dist/prompt-screen.d.ts +6 -9
  397. package/dist/prompt-screen.js +2 -5
  398. package/dist/read-face-posture.d.ts +6 -6
  399. package/dist/read-face-posture.js +2 -2
  400. package/dist/request-value-closure.d.ts +5 -5
  401. package/dist/request-value-closure.js +1 -1
  402. package/dist/rules-consent.d.ts +48 -27
  403. package/dist/rules-consent.js +147 -23
  404. package/dist/run-cancel-context.d.ts +4 -1
  405. package/dist/run-cancel-context.js +2 -1
  406. package/dist/run-local.js +17 -13
  407. package/dist/runs.d.ts +48 -30
  408. package/dist/runs.js +27 -17
  409. package/dist/runtime-caps-resolver.d.ts +15 -8
  410. package/dist/runtime-caps-resolver.js +14 -10
  411. package/dist/sandbox-egress-policy.js +6 -11
  412. package/dist/sandbox-rbac-rules.d.ts +88 -0
  413. package/dist/sandbox-rbac-rules.js +80 -0
  414. package/dist/sealed-key-layout.d.ts +16 -0
  415. package/dist/sealed-key-layout.js +3 -0
  416. package/dist/sealed-key.js +8 -6
  417. package/dist/security.d.ts +43 -9
  418. package/dist/security.js +9 -2
  419. package/dist/sema-config-dir.js +2 -2
  420. package/dist/server-secret-env.d.ts +2 -0
  421. package/dist/service-version.d.ts +2 -1
  422. package/dist/service-version.js +2 -2
  423. package/dist/session-error-wire.d.ts +1 -1
  424. package/dist/session-incarnation.d.ts +8 -5
  425. package/dist/session-notify-door.d.ts +5 -3
  426. package/dist/session-resident-background.d.ts +110 -0
  427. package/dist/session-resident-background.js +88 -0
  428. package/dist/session-row.d.ts +1 -1
  429. package/dist/session-sync-kernel.d.ts +53 -14
  430. package/dist/session-sync-kernel.js +70 -1
  431. package/dist/session-sync.d.ts +5 -3
  432. package/dist/session-workspace.d.ts +12 -2
  433. package/dist/session-workspace.js +6 -0
  434. package/dist/sighup-idle.d.ts +9 -7
  435. package/dist/sighup-idle.js +4 -5
  436. package/dist/spec-fields.d.ts +16 -0
  437. package/dist/spec-fields.js +7 -0
  438. package/dist/store-posture.d.ts +2 -1
  439. package/dist/stored-request-env-credentials-m38.d.ts +3 -0
  440. package/dist/stored-request-env-credentials-m38.js +8 -0
  441. package/dist/stored-request-hooks-m20.d.ts +3 -2
  442. package/dist/stored-request-hooks-m20.js +19 -14
  443. package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
  444. package/dist/stores-sql/blob-index-sql.d.ts +148 -0
  445. package/dist/stores-sql/blob-index-sql.js +154 -0
  446. package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +14 -428
  447. package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +43 -220
  448. package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
  449. package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
  450. package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
  451. package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
  452. package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +27 -67
  453. package/dist/{plugins → stores-sql}/pg-session-storage.js +82 -207
  454. package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
  455. package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
  456. package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
  457. package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
  458. package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
  459. package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
  460. package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
  461. package/dist/stores-sql/session-write-hooks.d.ts +59 -0
  462. package/dist/stores-sql/session-write-hooks.js +2 -0
  463. package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
  464. package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
  465. package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +35 -112
  466. package/dist/{plugins → stores-sql}/tidb-session-store.js +73 -169
  467. package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +3 -3
  468. package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
  469. package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
  470. package/dist/stores-sql/windowed-session-storage.js +61 -0
  471. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
  472. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
  473. package/dist/task-a2a.d.ts +7 -1
  474. package/dist/task-a2a.js +15 -14
  475. package/dist/task-cwd.d.ts +11 -3
  476. package/dist/task-cwd.js +17 -1
  477. package/dist/task-mcp.d.ts +10 -2
  478. package/dist/task-mcp.js +13 -16
  479. package/dist/task-settings.d.ts +68 -8
  480. package/dist/task-settings.js +63 -6
  481. package/dist/tool-approval.d.ts +23 -10
  482. package/dist/tool-approval.js +10 -6
  483. package/dist/trace/core-keyset-guard.d.ts +17 -10
  484. package/dist/trace/engine-notice-wire.d.ts +1 -1
  485. package/dist/trace/engine-notice-wire.js +4 -0
  486. package/dist/trace/exit-seat.d.ts +29 -1
  487. package/dist/trace/exit-seat.js +4 -0
  488. package/dist/trace/project.d.ts +33 -16
  489. package/dist/trace/project.js +21 -9
  490. package/dist/trace/redact.d.ts +13 -2
  491. package/dist/trace/redact.js +347 -78
  492. package/dist/trace/self-minted-wire.d.ts +587 -16
  493. package/dist/trace/self-minted-wire.js +215 -9
  494. package/dist/trace/sema-provenance.d.ts +45 -41
  495. package/dist/trace/sema-provenance.js +81 -10
  496. package/dist/trace/task-notification-facets.d.ts +70 -2
  497. package/dist/trace/task-notification-facets.js +71 -1
  498. package/dist/trace/wire-projection-faces.d.ts +39 -3
  499. package/dist/trace/wire-projection-faces.js +27 -2
  500. package/dist/unread-request-members.d.ts +66 -0
  501. package/dist/unread-request-members.js +41 -0
  502. package/dist/usage-analytics.d.ts +4 -0
  503. package/dist/user-input-ledger.d.ts +2 -2
  504. package/dist/web-admin-client/apply-effective.js +22 -26
  505. package/dist/web-admin-client/candidate-gate.d.ts +35 -3
  506. package/dist/web-admin-client/candidate-gate.js +53 -5
  507. package/dist/web-admin-client/center-request.d.ts +4 -1
  508. package/dist/web-admin-client/center-request.js +2 -1
  509. package/dist/web-admin-client/effective-keys.js +0 -1
  510. package/dist/web-admin-client/facade.d.ts +1 -1
  511. package/dist/web-admin-client/http-client.d.ts +1 -0
  512. package/dist/web-admin-client/http-client.js +17 -9
  513. package/dist/web-admin-client/restart-signal.js +5 -2
  514. package/dist/web-admin-client/skills-mcp.d.ts +20 -6
  515. package/dist/web-admin-client/skills-mcp.js +26 -21
  516. package/dist/web-admin-client/types.d.ts +34 -49
  517. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
  518. package/package.json +22 -13
  519. package/scripts/drain-check-local.mjs +8 -55
  520. package/scripts/drain-check.mysql.sql +3 -40
  521. package/scripts/drain-check.pg.sql +3 -40
  522. package/skills/update-config.md +1 -1
  523. package/wire-changes/server@7.146.0.json +3221 -0
  524. package/wire-changes/server@7.147.0.json +813 -0
  525. package/dist/approval-batch-census.d.ts +0 -27
  526. package/dist/approval-batch-census.js +0 -27
@@ -1,5 +1,5 @@
1
1
  import { REDACTION_MARK, displayUrlOf, stripFormatCharacters } from "@sema-agent/core";
2
- import { CONTROL_AND_BIDI_CHARS, CREDENTIAL_PARAM_NAMES, isHierarchicalUrl } from "@sema-agent/settings-schema";
2
+ import { CONTROL_AND_BIDI_CHARS, CREDENTIAL_PARAM_NAMES, credentialParamWordOf, isHierarchicalUrl } from "@sema-agent/settings-schema";
3
3
  import { recordFailOpen } from "../observability/fail-open.js";
4
4
  const normalizeForRedaction = stripFormatCharacters;
5
5
  export function mapNormalizedToOriginal(text, normalized) {
@@ -1062,7 +1062,7 @@ function undecidedKeywordStart(text, t) {
1062
1062
  }
1063
1063
  const CREDENTIAL_NAME_ANCHORS = {
1064
1064
  api_key: "declarative", apikey: "declarative", "api-key": "declarative", key: "structure-only",
1065
- token: "structure-only", access_token: "declarative", refresh_token: "declarative", id_token: "declarative",
1065
+ token: "assignment", access_token: "declarative", refresh_token: "declarative", id_token: "declarative",
1066
1066
  auth: "structure-only", authorization: "auth-scheme", "proxy-authorization": "auth-scheme",
1067
1067
  password: "declarative", passwd: "any-form", pwd: "any-form",
1068
1068
  secret: "declarative", client_secret: "declarative", private_key: "declarative",
@@ -1070,14 +1070,9 @@ const CREDENTIAL_NAME_ANCHORS = {
1070
1070
  "x-amz-signature": "declarative", "x-amz-security-token": "declarative", "x-amz-credential": "declarative",
1071
1071
  sas: "structure-only",
1072
1072
  };
1073
- const CREDENTIAL_NAME_ALT = (() => {
1074
- for (const w of CREDENTIAL_PARAM_NAMES) {
1075
- if (!/^[a-z][a-z0-9_-]*$/.test(w))
1076
- throw new Error(`redact: credential name ${JSON.stringify(w)} must be lowercase [a-z0-9_-] (the alternation is built without escaping)`);
1077
- }
1078
- return [...CREDENTIAL_PARAM_NAMES].sort((a, b) => b.length - a.length || (a < b ? -1 : 1)).join("|");
1079
- })();
1080
1073
  const CREDENTIAL_NAME_MAX = Math.max(...CREDENTIAL_PARAM_NAMES.map((w) => w.length));
1074
+ const JSON_FIELD_NAME_CLASS = "[A-Za-z0-9_.-]";
1075
+ const isJsonFieldNameCode = (c) => isAsciiAlnumCode(c) || c === CH_UNDERSCORE || c === CH_MINUS || c === CH_DOT;
1081
1076
  const JSON_FIELD_QUOTE_FORMS = ['"', '\\"', '\\\\\\"'];
1082
1077
  for (let d = 0; d < JSON_FIELD_QUOTE_FORMS.length; d++) {
1083
1078
  if (JSON_FIELD_QUOTE_FORMS[d] !== "\\".repeat(2 ** d - 1) + '"')
@@ -1096,15 +1091,53 @@ function buildJsonSecretFieldSource() {
1096
1091
  q = b + q;
1097
1092
  b = b + b;
1098
1093
  }
1099
- alts.push(String.raw `(${q}(?:${CREDENTIAL_NAME_ALT})${q}\s*:\s*)${q}(?:${o}|${l}|${b}(?:${o}|${b}|${q}))*${q}`);
1094
+ alts.push(String.raw `(${q}(${JSON_FIELD_NAME_CLASS}+)${q}\s*:\s*)${q}(?:${o}|${l}|${b}(?:${o}|${b}|${q}))*${q}`);
1100
1095
  }
1101
1096
  return alts.join("|");
1102
1097
  }
1103
1098
  const asciiLower = (s) => s.replace(/[A-Z]/g, (c) => c.toLowerCase());
1104
1099
  function credentialNameAnchor(name) {
1105
- return CREDENTIAL_ANCHOR_OF.get(asciiLower(name));
1100
+ let word = CREDENTIAL_WORD_MEMO.get(name);
1101
+ if (word === undefined) {
1102
+ word = credentialParamWordOf(name) ?? null;
1103
+ if (name.length <= CREDENTIAL_WORD_MEMO_NAME_MAX) {
1104
+ if (CREDENTIAL_WORD_MEMO.size >= CREDENTIAL_WORD_MEMO_SIZE)
1105
+ CREDENTIAL_WORD_MEMO.clear();
1106
+ CREDENTIAL_WORD_MEMO.set(name, word);
1107
+ }
1108
+ }
1109
+ return word === null ? undefined : CREDENTIAL_NAME_ANCHORS[word];
1110
+ }
1111
+ const CREDENTIAL_WORD_MEMO = new Map();
1112
+ const CREDENTIAL_WORD_MEMO_SIZE = 1024;
1113
+ const CREDENTIAL_WORD_MEMO_NAME_MAX = 64;
1114
+ const BARE_WORD_READINGS = {
1115
+ null: "absent-or-boolean", nil: "absent-or-boolean", none: "absent-or-boolean", undefined: "absent-or-boolean",
1116
+ true: "absent-or-boolean", false: "absent-or-boolean", yes: "absent-or-boolean", no: "absent-or-boolean",
1117
+ str: "type-name", string: "type-name", bytes: "type-name", int: "type-name", integer: "type-name", float: "type-name", number: "type-name",
1118
+ bool: "type-name", boolean: "type-name", any: "type-name", object: "type-name", array: "type-name", secretstr: "type-name",
1119
+ };
1120
+ for (const w of Object.keys(BARE_WORD_READINGS)) {
1121
+ if (!/^[a-z]+$/.test(w))
1122
+ throw new Error(`redact: bare value word ${JSON.stringify(w)} must be lowercase ASCII letters (values are ASCII-lowercased before the lookup)`);
1123
+ }
1124
+ const BARE_WORD_OF = new Map(Object.entries(BARE_WORD_READINGS));
1125
+ const BARE_WORD_MAX = Math.max(...Object.keys(BARE_WORD_READINGS).map((w) => w.length));
1126
+ function bareWordIsValue(reading, bare) {
1127
+ switch (reading) {
1128
+ case "absent-or-boolean":
1129
+ return false;
1130
+ case "type-name":
1131
+ return bare === "declared";
1132
+ default: {
1133
+ const unhandled = reading;
1134
+ throw new Error(`redact: unhandled bare value word reading ${String(unhandled)}`);
1135
+ }
1136
+ }
1137
+ }
1138
+ export function lineKeyTypeNamesForTest() {
1139
+ return Object.entries(BARE_WORD_READINGS).filter(([, r]) => r === "type-name").map(([w]) => w);
1106
1140
  }
1107
- const CREDENTIAL_ANCHOR_OF = new Map(Object.entries(CREDENTIAL_NAME_ANCHORS));
1108
1141
  const STRUCTURAL_SECRET_PATTERNS = [
1109
1142
  [/-----BEGIN(?:[^-](?:[^-](?:[^-]|-(?!-))*)?)?PRIVATE KEY(?: BLOCK)?-----[\s\S]{0,8192}?-----END(?:[^-](?:[^-](?:[^-]|-(?!-))*)?)?PRIVATE KEY(?: BLOCK)?-----/g, "«redacted:private-key»"],
1110
1143
  [/---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----[\s\S]{0,8192}?---- END SSH2 ENCRYPTED PRIVATE KEY ----/g, "«redacted:private-key»"],
@@ -1855,46 +1888,26 @@ const isRegexSpace = (c) => c === 32 || (c >= 9 && c <= 13) || c === 0xa0 || c =
1855
1888
  const isLineTerminator = (c) => c === 10 || c === 13 || c === 0x2028 || c === 0x2029;
1856
1889
  const isControlCode = (c) => c < 0x20 || c === 0x7f;
1857
1890
  const TOKEN_UNIT_Y = new RegExp(REDACTION_TOKEN_RE_SRC, "y");
1858
- const CREDENTIAL_NAME_SCAN_MAX = CREDENTIAL_NAME_MAX * 3 + 1;
1859
- function decodeAsciiName(name) {
1860
- let out = "";
1861
- for (let i = 0; i < name.length; i++) {
1862
- const c = name.charCodeAt(i);
1863
- if (c !== 37) {
1864
- out += name[i];
1865
- continue;
1866
- }
1867
- const hex = name.slice(i + 1, i + 3);
1868
- if (hex.length !== 2 || !/^[0-9A-Fa-f]{2}$/.test(hex))
1869
- return undefined;
1870
- const b = Number.parseInt(hex, 16);
1871
- if (b >= 0x80)
1872
- return undefined;
1873
- out += String.fromCharCode(b);
1874
- i += 2;
1875
- }
1876
- return out;
1877
- }
1878
- function credentialParamValueStart(text, p) {
1879
- const limit = Math.min(text.length, p + CREDENTIAL_NAME_SCAN_MAX);
1880
- let hasPct = false;
1881
- for (let i = p; i < limit; i++) {
1891
+ function credentialParamValueStart(text, p, json) {
1892
+ let encoded = false;
1893
+ for (let i = p; i < text.length; i++) {
1882
1894
  const c = text.charCodeAt(i);
1883
- if (c === 37) {
1884
- hasPct = true;
1885
- continue;
1886
- }
1887
1895
  if (c === CH_EQ) {
1888
1896
  if (i === p)
1889
1897
  return -1;
1890
- const name = hasPct ? decodeAsciiName(text.slice(p, i)) : text.slice(p, i);
1891
- return name !== undefined && credentialNameAnchor(name) !== undefined ? i + 1 : -1;
1898
+ const raw = text.slice(p, i);
1899
+ return credentialNameAnchor(encoded ? receiverParamName(raw) : raw) !== undefined ? i + 1 : -1;
1892
1900
  }
1893
- if (!(isAsciiAlnumCode(c) || c === CH_UNDERSCORE || c === CH_MINUS))
1901
+ if (c === 63 || c === 38 || c === 35 || isRegexSpace(c) || isControlCode(c) || (json && c === 34))
1894
1902
  return -1;
1903
+ if (c === 37 || c === 43)
1904
+ encoded = true;
1895
1905
  }
1896
1906
  return -1;
1897
1907
  }
1908
+ function receiverParamName(raw) {
1909
+ return new URLSearchParams(`${raw}=`).keys().next().value ?? raw;
1910
+ }
1898
1911
  function tokenUnitEnd(text, p) {
1899
1912
  TOKEN_UNIT_Y.lastIndex = p;
1900
1913
  return TOKEN_UNIT_Y.test(text) ? TOKEN_UNIT_Y.lastIndex : -1;
@@ -2948,7 +2961,7 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
2948
2961
  const c = text.charCodeAt(i);
2949
2962
  if (c !== 63 && c !== 38 && c !== 35)
2950
2963
  continue;
2951
- const valueStart = credentialParamValueStart(text, i + 1);
2964
+ const valueStart = credentialParamValueStart(text, i + 1, json);
2952
2965
  if (valueStart < 0)
2953
2966
  continue;
2954
2967
  while (qc < ppn && pp[qc] < i)
@@ -2997,7 +3010,7 @@ function collectUrlCredentialSpans(scan, text, json, span, isHead) {
2997
3010
  scan.footHi = armHi;
2998
3011
  }
2999
3012
  const JSON_FIELD_ANCHOR = '"';
3000
- const JSON_FIELD_BACK = Math.max(...JSON_FIELD_QUOTE_FORMS.map((f) => f.length));
3013
+ const JSON_FIELD_HEAD_MAX = Math.max(...JSON_FIELD_QUOTE_FORMS.map((f) => f.length));
3001
3014
  function jsonSecretFieldValueQuoteAt(text, p, depth) {
3002
3015
  const form = JSON_FIELD_QUOTE_FORMS[depth];
3003
3016
  const n = text.length;
@@ -3005,10 +3018,8 @@ function jsonSecretFieldValueQuoteAt(text, p, depth) {
3005
3018
  let i = nameFrom;
3006
3019
  for (; i < n; i++) {
3007
3020
  const c = text.charCodeAt(i);
3008
- if (!(isAsciiAlnumCode(c) || c === CH_UNDERSCORE || c === CH_MINUS))
3021
+ if (!isJsonFieldNameCode(c))
3009
3022
  break;
3010
- if (i - nameFrom >= CREDENTIAL_NAME_MAX)
3011
- return -1;
3012
3023
  }
3013
3024
  if (i === nameFrom || !text.startsWith(form, i) || credentialNameAnchor(text.slice(nameFrom, i)) === undefined)
3014
3025
  return -1;
@@ -3092,7 +3103,7 @@ function collectJsonSecretFieldSpans(text, span, isHead) {
3092
3103
  let from = 0;
3093
3104
  for (let p = text.indexOf(JSON_FIELD_ANCHOR); p >= 0;) {
3094
3105
  let run = 0;
3095
- while (run < JSON_FIELD_BACK - 1 && p - run - 1 >= from && text.charCodeAt(p - run - 1) === CH_BACKSLASH)
3106
+ while (run < JSON_FIELD_HEAD_MAX - 1 && p - run - 1 >= from && text.charCodeAt(p - run - 1) === CH_BACKSLASH)
3096
3107
  run += 1;
3097
3108
  let next = -1;
3098
3109
  for (let d = JSON_FIELD_QUOTE_FORMS.length - 1; d >= 0 && next < 0; d--) {
@@ -3107,7 +3118,7 @@ function collectJsonSecretFieldSpans(text, span, isHead) {
3107
3118
  const open = found === STRING_OPEN;
3108
3119
  const end = open ? text.length : found;
3109
3120
  span(q, end, q, open ? NOT_CLOSED : end - form.length, open, JSON_FIELD_VALUE_REPLS[d]);
3110
- from = scanResumeAfterHit(start, end, JSON_FIELD_BACK);
3121
+ from = scanResumeAfterHit(start, end, end - q);
3111
3122
  next = text.indexOf(JSON_FIELD_ANCHOR, from);
3112
3123
  if (next < 0)
3113
3124
  return;
@@ -3126,8 +3137,6 @@ function isEngineMarkedCandidate(text, start, end, repl) {
3126
3137
  return end - start === lead.length + REDACTION_MARK.length + trail.length && text.startsWith(lead, start) && text.startsWith(REDACTION_MARK, start + lead.length) && text.startsWith(trail, end - trail.length);
3127
3138
  }
3128
3139
  const STRONG_AUTH_SCHEME_MAX = Math.max(...[...STRONG_AUTH_SCHEMES].map((w) => w.length));
3129
- const ABSENT_OR_BOOLEAN_WORDS = new Set(["null", "nil", "none", "undefined", "true", "false", "yes", "no"]);
3130
- const ABSENT_OR_BOOLEAN_MAX = Math.max(...[...ABSENT_OR_BOOLEAN_WORDS].map((w) => w.length));
3131
3140
  const CH_GRAVE = 96, CH_APOS = 39, CH_DOT = 46, CH_COMMA = 44, CH_SEMI = 59, CH_DOLLAR = 36;
3132
3141
  const CH_LPAREN = 40, CH_RPAREN = 41, CH_RBRACKET = 93, CH_LBRACE = 123, CH_RBRACE = 125, CH_LT = 60, CH_GT = 62;
3133
3142
  const CH_QMARK = 63, CH_AMP = 38, CH_HASH = 35;
@@ -3154,6 +3163,9 @@ const unitChOf = (unit) => (unit >> 3) - 1;
3154
3163
  const unitLenOf = (unit) => unit & 7;
3155
3164
  function readAnchorUnit(text, i, json) {
3156
3165
  anchoredScanUnits += 1;
3166
+ return readTextUnit(text, i, json);
3167
+ }
3168
+ function readTextUnit(text, i, json) {
3157
3169
  const c = text.charCodeAt(i);
3158
3170
  if (!json)
3159
3171
  return packUnit(c, 1);
@@ -3217,16 +3229,13 @@ function anchorHeadAt(scan, text, op, json) {
3217
3229
  i -= quoteLen;
3218
3230
  }
3219
3231
  const nameEnd = i + 1;
3220
- const floor = Math.max(-1, i - (CREDENTIAL_NAME_MAX + 2));
3221
3232
  let j = i;
3222
- while (j > floor && isIdentCode(text.charCodeAt(j)))
3233
+ while (j >= 0 && isIdentCode(text.charCodeAt(j)))
3223
3234
  j -= 1;
3224
3235
  anchoredScanUnits += nameEnd - (j + 1);
3225
3236
  const bound = j + 1 < nameEnd ? nameBoundAt(scan, Math.max(j, 0), nameEnd) : -1;
3226
3237
  if (bound > j)
3227
3238
  j = bound - 1;
3228
- else if (j === floor && j >= 0 && isIdentCode(text.charCodeAt(j)))
3229
- return undefined;
3230
3239
  let nameStart = j + 1;
3231
3240
  let afterEscape = false;
3232
3241
  if (j >= 0 && text.charCodeAt(j) === CH_BACKSLASH && escapedAt(text, j + 1)) {
@@ -3269,7 +3278,7 @@ function anchorHeadAt(scan, text, op, json) {
3269
3278
  const left = k >= 0 ? text.charCodeAt(k) : 0;
3270
3279
  listSep = left === CH_QMARK || left === CH_AMP || left === CH_HASH ? CH_AMP : left === CH_SEMI ? CH_SEMI : left === CH_COMMA || left === CH_LPAREN || left === CH_LBRACKET || left === CH_LBRACE ? CH_COMMA : 0;
3271
3280
  }
3272
- return { strength, quotedName: quote !== 0, spacedLeft, listSep };
3281
+ return { strength, quotedName: quote !== 0, spacedLeft, listSep, runStart };
3273
3282
  }
3274
3283
  function quotedValueEnd(text, cs, quote, json, isHead) {
3275
3284
  const n = text.length;
@@ -3382,7 +3391,7 @@ function bareValueEnd(text, s, json, listSep, memo) {
3382
3391
  }
3383
3392
  return e;
3384
3393
  }
3385
- function literalValueAt(text, s, json, declaredIfBare, listSep, isHead, memo) {
3394
+ function literalValueAt(text, s, json, bare, listSep, isHead, memo) {
3386
3395
  const n = text.length;
3387
3396
  if (s >= n)
3388
3397
  return undefined;
@@ -3403,8 +3412,21 @@ function literalValueAt(text, s, json, declaredIfBare, listSep, isHead, memo) {
3403
3412
  }
3404
3413
  else if (!isAsciiAlnumCode(first))
3405
3414
  return undefined;
3406
- if (!declaredIfBare)
3407
- return undefined;
3415
+ let lineKey;
3416
+ switch (bare) {
3417
+ case "never":
3418
+ return undefined;
3419
+ case "declared":
3420
+ lineKey = false;
3421
+ break;
3422
+ case "line-key":
3423
+ lineKey = true;
3424
+ break;
3425
+ default: {
3426
+ const unhandled = bare;
3427
+ throw new Error(`redact: unhandled bare literal form ${String(unhandled)}`);
3428
+ }
3429
+ }
3408
3430
  if (isProgramIdentStartCode(text.charCodeAt(vs))) {
3409
3431
  let k = vs;
3410
3432
  while (k < n && isProgramIdentCode(text.charCodeAt(k)))
@@ -3417,10 +3439,92 @@ function literalValueAt(text, s, json, declaredIfBare, listSep, isHead, memo) {
3417
3439
  const e = bareValueEnd(text, vs, json, listSep, memo);
3418
3440
  if (e <= vs)
3419
3441
  return undefined;
3420
- if (e - vs <= ABSENT_OR_BOOLEAN_MAX && ABSENT_OR_BOOLEAN_WORDS.has(text.slice(vs, e).toLowerCase()))
3421
- return undefined;
3442
+ if (e - vs <= BARE_WORD_MAX) {
3443
+ const reading = BARE_WORD_OF.get(asciiLower(text.slice(vs, e)));
3444
+ if (reading !== undefined && !bareWordIsValue(reading, lineKey ? "line-key" : "declared"))
3445
+ return undefined;
3446
+ }
3447
+ if (lineKey) {
3448
+ const rest = lineKeyRestAt(text, e, json, isHead);
3449
+ switch (rest) {
3450
+ case "ends":
3451
+ break;
3452
+ case "goes-on":
3453
+ return undefined;
3454
+ case "undecided":
3455
+ return { start: vs, end: text.length, quoted: false, open: true };
3456
+ default: {
3457
+ const unhandled = rest;
3458
+ throw new Error(`redact: unhandled line-key rest ${String(unhandled)}`);
3459
+ }
3460
+ }
3461
+ }
3422
3462
  return { start: vs, end: e, quoted: false };
3423
3463
  }
3464
+ function lineKeyRestAt(text, e, json, isHead) {
3465
+ const n = text.length;
3466
+ let i = e;
3467
+ while (i < n) {
3468
+ const unit = readAnchorUnit(text, i, json);
3469
+ const ch = unitChOf(unit);
3470
+ if (isInlineSpaceUnit(ch) || (ch >= 0 && INVISIBLE_UNIT_CLASS[ch] === 1)) {
3471
+ i += unitLenOf(unit);
3472
+ continue;
3473
+ }
3474
+ return ch === JSON_STRING_END || isLineTerminator(ch) || ch === CH_HASH ? "ends" : "goes-on";
3475
+ }
3476
+ return isHead ? "undecided" : "ends";
3477
+ }
3478
+ function unitEndingAt(text, end, json) {
3479
+ const c = text.charCodeAt(end - 1);
3480
+ anchoredScanUnits += 1;
3481
+ if (!json)
3482
+ return packUnit(c, 1);
3483
+ if (end >= 6 && text.charCodeAt(end - 6) === CH_BACKSLASH && text.charCodeAt(end - 5) === CH_u && !escapedAt(text, end - 6)) {
3484
+ const h0 = hexDigitValue(text.charCodeAt(end - 4));
3485
+ const h1 = hexDigitValue(text.charCodeAt(end - 3));
3486
+ const h2 = hexDigitValue(text.charCodeAt(end - 2));
3487
+ const h3 = hexDigitValue(text.charCodeAt(end - 1));
3488
+ if (h0 >= 0 && h1 >= 0 && h2 >= 0 && h3 >= 0)
3489
+ return packUnit((h0 << 12) | (h1 << 8) | (h2 << 4) | h3, 6);
3490
+ }
3491
+ if (end >= 2 && text.charCodeAt(end - 2) === CH_BACKSLASH && escapedAt(text, end - 1)) {
3492
+ const two = readTextUnit(text, end - 2, true);
3493
+ if (unitLenOf(two) === 2)
3494
+ return two;
3495
+ }
3496
+ return c === CH_QUOTE ? packUnit(JSON_STRING_END, 1) : packUnit(c, 1);
3497
+ }
3498
+ function lineHeadBefore(text, at, json) {
3499
+ let i = at;
3500
+ let blank = false;
3501
+ for (;;) {
3502
+ if (i <= 0)
3503
+ return true;
3504
+ const unit = unitEndingAt(text, i, json);
3505
+ const ch = unitChOf(unit);
3506
+ if (isInlineSpaceUnit(ch)) {
3507
+ i -= unitLenOf(unit);
3508
+ blank = true;
3509
+ continue;
3510
+ }
3511
+ if (ch >= 0 && INVISIBLE_UNIT_CLASS[ch] === 1) {
3512
+ i -= unitLenOf(unit);
3513
+ continue;
3514
+ }
3515
+ if (ch === CH_MINUS && blank) {
3516
+ i -= unitLenOf(unit);
3517
+ blank = false;
3518
+ continue;
3519
+ }
3520
+ return isLineTerminator(ch) || ch === JSON_STRING_END;
3521
+ }
3522
+ }
3523
+ function declarativeBareAt(text, head, spacedRight, json) {
3524
+ if (head.quotedName || (!head.spacedLeft && !spacedRight))
3525
+ return "declared";
3526
+ return spacedRight && lineHeadBefore(text, head.runStart, json) ? "line-key" : "never";
3527
+ }
3424
3528
  function schemeValueAt(text, s, json) {
3425
3529
  const n = text.length;
3426
3530
  let i = s;
@@ -3504,11 +3608,16 @@ function anchoredValueAt(scan, text, op, json, span, isHead, memo) {
3504
3608
  case "auth-scheme":
3505
3609
  v = schemeValueAt(text, s, json);
3506
3610
  break;
3611
+ case "assignment":
3612
+ if (text.charCodeAt(op) !== CH_EQ || head.quotedName || head.spacedLeft || spacedRight)
3613
+ return;
3614
+ v = literalValueAt(text, s, json, "declared", head.listSep, isHead, memo);
3615
+ break;
3507
3616
  case "declarative":
3508
- v = literalValueAt(text, s, json, head.quotedName || (!head.spacedLeft && !spacedRight), head.listSep, isHead, memo);
3617
+ v = literalValueAt(text, s, json, declarativeBareAt(text, head, spacedRight, json), head.listSep, isHead, memo);
3509
3618
  break;
3510
3619
  case "any-form":
3511
- v = literalValueAt(text, s, json, true, head.listSep, isHead, memo);
3620
+ v = literalValueAt(text, s, json, "declared", head.listSep, isHead, memo);
3512
3621
  break;
3513
3622
  default: {
3514
3623
  const unhandled = head.strength;
@@ -3592,6 +3701,149 @@ function collectAnchoredValueSpans(scan, text, json, span, isHead) {
3592
3701
  scan.footLo = armLo;
3593
3702
  scan.footHi = armHi;
3594
3703
  }
3704
+ const isRegexWordCode = (c) => isAsciiAlnumCode(c) || c === CH_UNDERSCORE;
3705
+ const isDiagnosticNameCode = (c) => isRegexWordCode(c) || c === CH_MINUS;
3706
+ const isDiagnosticValueUnit = (ch) => ch !== JSON_STRING_END && !isRegexSpace(ch) && ch !== CH_QUOTE && ch !== CH_APOS && ch !== CH_COMMA && ch !== CH_RBRACE;
3707
+ const isAsciiLetterCode = (ch) => (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a);
3708
+ const isDiagnosticSchemeValueUnit = (ch) => isAsciiAlnumCode(ch) || ch === CH_DOT || ch === CH_UNDERSCORE || ch === CH_TILDE || ch === CH_PLUS || ch === CH_SLASH || ch === CH_EQ || ch === CH_MINUS;
3709
+ function diagnosticNameSlot(tier) {
3710
+ switch (tier) {
3711
+ case "assignment":
3712
+ case "declarative":
3713
+ case "any-form":
3714
+ case "auth-scheme":
3715
+ return true;
3716
+ case "structure-only":
3717
+ return false;
3718
+ default: {
3719
+ const unhandled = tier;
3720
+ throw new Error(`redact: unhandled free-text anchor strength ${String(unhandled)}`);
3721
+ }
3722
+ }
3723
+ }
3724
+ const DIAGNOSTIC_SCHEME_RE = new RegExp([...STRONG_AUTH_SCHEMES].sort((a, b) => b.length - a.length).join("|"), "gi");
3725
+ let diagnosticScanUnits = 0;
3726
+ export function diagnosticScanUnitsForTest() {
3727
+ return diagnosticScanUnits;
3728
+ }
3729
+ export function resetDiagnosticScanUnitsForTest() {
3730
+ diagnosticScanUnits = 0;
3731
+ }
3732
+ function collectDiagnosticValueSpans(text, json, span, isHead, deletedAt) {
3733
+ const n = text.length;
3734
+ const readRun = (from, isValue) => {
3735
+ let i = from;
3736
+ while (i < n) {
3737
+ const unit = readTextUnit(text, i, json);
3738
+ diagnosticScanUnits += 1;
3739
+ if (!isValue(unitChOf(unit)))
3740
+ break;
3741
+ i += unitLenOf(unit);
3742
+ }
3743
+ return i;
3744
+ };
3745
+ const skipBlank = (from) => readRun(from, isRegexSpace);
3746
+ let valueEnd = 0;
3747
+ let plainEnd = 0;
3748
+ let nextEq = text.indexOf("=");
3749
+ let nextColon = text.indexOf(":");
3750
+ while (nextEq >= 0 || nextColon >= 0) {
3751
+ let op;
3752
+ if (nextColon < 0 || (nextEq >= 0 && nextEq < nextColon)) {
3753
+ op = nextEq;
3754
+ nextEq = text.indexOf("=", op + 1);
3755
+ }
3756
+ else {
3757
+ op = nextColon;
3758
+ nextColon = text.indexOf(":", op + 1);
3759
+ }
3760
+ const inValue = op + 1 < plainEnd;
3761
+ let e = op;
3762
+ while (e > 0 && isRegexSpace(text.charCodeAt(e - 1)))
3763
+ e -= 1;
3764
+ diagnosticScanUnits += op - e;
3765
+ if (e === 0 || !isRegexWordCode(text.charCodeAt(e - 1)))
3766
+ continue;
3767
+ let runStart = e;
3768
+ while (runStart > 0 && isDiagnosticNameCode(text.charCodeAt(runStart - 1)))
3769
+ runStart -= 1;
3770
+ diagnosticScanUnits += e - runStart;
3771
+ let nameStart = -1;
3772
+ let nameTier;
3773
+ for (let q = runStart; q < e && nameStart < 0; q = q === runStart ? Math.max(runStart + 1, e - CREDENTIAL_NAME_MAX) : q + 1) {
3774
+ if (!isRegexWordCode(text.charCodeAt(q)))
3775
+ continue;
3776
+ const bounded = q === runStart || text.charCodeAt(q - 1) === CH_MINUS || deletedAt(q) !== "none";
3777
+ const tier = bounded ? credentialNameAnchor(text.slice(q, e)) : undefined;
3778
+ if (tier !== undefined && diagnosticNameSlot(tier)) {
3779
+ nameStart = q;
3780
+ nameTier = tier;
3781
+ }
3782
+ }
3783
+ if (nameStart < 0)
3784
+ continue;
3785
+ let s;
3786
+ let end;
3787
+ if (inValue) {
3788
+ s = op + 1;
3789
+ end = plainEnd;
3790
+ }
3791
+ else {
3792
+ s = skipBlank(op + 1);
3793
+ if (s < n) {
3794
+ const unit = readTextUnit(text, s, json);
3795
+ if (unitChOf(unit) === CH_QUOTE)
3796
+ s += unitLenOf(unit);
3797
+ }
3798
+ if (s >= n) {
3799
+ if (isHead)
3800
+ span(nameStart, n, op, NOT_CLOSED, true);
3801
+ continue;
3802
+ }
3803
+ end = readRun(s, isDiagnosticValueUnit);
3804
+ plainEnd = end;
3805
+ }
3806
+ if (end > s && nameTier === "auth-scheme" && readRun(s, isAsciiLetterCode) === end) {
3807
+ const k = skipBlank(end);
3808
+ if (k > end && k >= n && isHead) {
3809
+ span(nameStart, n, op, NOT_CLOSED, true);
3810
+ continue;
3811
+ }
3812
+ if (k > end && k < n) {
3813
+ const credEnd = readRun(k, isDiagnosticSchemeValueUnit);
3814
+ if (credEnd > k)
3815
+ end = credEnd;
3816
+ }
3817
+ }
3818
+ if (end > s && end > valueEnd) {
3819
+ span(s, end, op, NOT_CLOSED);
3820
+ valueEnd = end;
3821
+ }
3822
+ }
3823
+ let schemeEnd = 0;
3824
+ DIAGNOSTIC_SCHEME_RE.lastIndex = 0;
3825
+ for (let m = DIAGNOSTIC_SCHEME_RE.exec(text); m !== null; m = DIAGNOSTIC_SCHEME_RE.exec(text)) {
3826
+ const at = m.index;
3827
+ const q = at + m[0].length;
3828
+ if (q < schemeEnd)
3829
+ continue;
3830
+ if (at > 0 && isRegexWordCode(text.charCodeAt(at - 1)) && deletedAt(at) === "none")
3831
+ continue;
3832
+ const k = skipBlank(q);
3833
+ if (k === q && deletedAt(q) !== "blank")
3834
+ continue;
3835
+ if (k >= n) {
3836
+ if (isHead)
3837
+ span(at, n, at, NOT_CLOSED, true);
3838
+ continue;
3839
+ }
3840
+ const end = readRun(k, isDiagnosticSchemeValueUnit);
3841
+ if (end > k) {
3842
+ span(k, end, at, NOT_CLOSED);
3843
+ schemeEnd = end;
3844
+ }
3845
+ }
3846
+ }
3595
3847
  export function structuralScannerForTest(arm) {
3596
3848
  const collect = (scan) => (text) => {
3597
3849
  const out = [];
@@ -3750,6 +4002,7 @@ const armPool = (() => {
3750
4002
  order,
3751
4003
  phase: 1,
3752
4004
  lexical: LEXICAL_KEYWORD_ARMS.has(re),
4005
+ diagnosticOnly: false,
3753
4006
  collect: (text, _json, _eat, out, isHead) => {
3754
4007
  if (boundary === undefined)
3755
4008
  collectRegexSpans(arm, text, out);
@@ -3769,16 +4022,16 @@ const armPool = (() => {
3769
4022
  prior: { kind: "bounded", gap: keywordTail === undefined ? NO_GAP : (c) => keywordTail.isSeparator(String.fromCharCode(c)) },
3770
4023
  };
3771
4024
  };
3772
- const scannerMember = (token, order, arm, reach, family, prior) => {
4025
+ const scannerMember = (token, order, arm, reach, family, prior, rank = ARM_RANK.structural, lexical = false, diagnosticOnly = false) => {
3773
4026
  const repl = spanRepl(token);
3774
- const rank = ARM_RANK.structural;
3775
4027
  return {
3776
4028
  token,
3777
4029
  rank,
3778
4030
  order,
3779
4031
  phase: 1,
3780
- lexical: false,
3781
- collect: (text, json, eat, out, isHead) => arm(text, json, eat, (start, end, anchor, closeAt, undecided, r = repl) => out.push(undecided === true ? { start, end, repl: r, rank, order, undecided, anchor, closeAt } : { start, end, repl: r, rank, order, anchor, closeAt }), isHead),
4032
+ lexical,
4033
+ diagnosticOnly,
4034
+ collect: (text, json, eat, out, isHead, deletedAt) => arm(text, json, eat, (start, end, anchor, closeAt, undecided, r = repl) => out.push(undecided === true ? { start, end, repl: r, rank, order, undecided, anchor, closeAt } : { start, end, repl: r, rank, order, anchor, closeAt }), isHead, deletedAt),
3782
4035
  retry: undefined,
3783
4036
  headSrc: undefined,
3784
4037
  headFirst: undefined,
@@ -3795,6 +4048,7 @@ const armPool = (() => {
3795
4048
  order,
3796
4049
  phase: 2,
3797
4050
  lexical,
4051
+ diagnosticOnly: false,
3798
4052
  collect: (scan, text, json, eat, out, isHead) => arm(scan, text, json, eat, (start, end, anchor, closeAt, undecided, r = repl) => out.push(undecided === true ? { start, end, repl: r, rank, order, undecided, anchor, closeAt } : { start, end, repl: r, rank, order, anchor, closeAt }), isHead),
3799
4053
  retry: undefined,
3800
4054
  headSrc: undefined,
@@ -3813,7 +4067,7 @@ const armPool = (() => {
3813
4067
  if (row === URL_CREDENTIAL_PATTERN)
3814
4068
  return forensicMember(row[1], order, (scan, text, json, _eat, span, isHead) => collectUrlCredentialSpans(scan, text, json, span, isHead), "://".length, "url", { kind: "bounded", gap: NO_GAP });
3815
4069
  if (row === JSON_SECRET_FIELD_PATTERN)
3816
- return scannerMember(row[1], order, (text, _json, _eat, span, isHead) => collectJsonSecretFieldSpans(text, span, isHead), JSON_FIELD_BACK, "json-field", { kind: "bounded", gap: isRegexSpace });
4070
+ return scannerMember(row[1], order, (text, _json, _eat, span, isHead) => collectJsonSecretFieldSpans(text, span, isHead), JSON_FIELD_HEAD_MAX, "json-field", { kind: "bounded", gap: isRegexSpace });
3817
4071
  throw new Error(`redact: structural row /${row[0].source}/ has no hand-written scanner — structural grammars are declared as regexes but never executed as one (S-102 / S-265)`);
3818
4072
  };
3819
4073
  const members = [];
@@ -3822,13 +4076,14 @@ const armPool = (() => {
3822
4076
  members.push(forensicMember(PPK_CONTAINER_TOKEN, members.length, (scan, text, _json, eat, span, isHead) => collectPpkContainerSpans(scan, text, eat, span, isHead), PPK_FILE_HEAD.length, "putty-ppk", { kind: "anchored", anchors: [PPK_FILE_HEAD] }));
3823
4077
  members.push(forensicMember(PEM_FRAGMENT_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectPemFragmentSpans(scan, text, json, span, isHead), PEM_FENCE_OPEN.length, "pem-armor", { kind: "anchored", anchors: [PEM_FENCE_OPEN, PEM_END_OPEN] }));
3824
4078
  members.push(forensicMember(HEADLESS_PPK_TOKEN, members.length, (scan, text, _json, _eat, span, isHead) => collectHeadlessPpkSpans(scan, text, span, isHead), PPK_LINES_FIELD.length, "putty-ppk", { kind: "anchored", anchors: [PPK_LINES_FIELD] }));
3825
- members.push(forensicMember(ANCHORED_VALUE_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectAnchoredValueSpans(scan, text, json, span, isHead), Math.max(BEARER_VALUE_MIN, ABSENT_OR_BOOLEAN_MAX + 1, STRONG_AUTH_SCHEME_MAX + 1), "anchor", { kind: "bounded", gap: (c) => isInlineSpaceUnit(c) || isSchemeDelimiterCode(c) }, ARM_RANK.keyword, true));
4079
+ members.push(forensicMember(ANCHORED_VALUE_TOKEN, members.length, (scan, text, json, _eat, span, isHead) => collectAnchoredValueSpans(scan, text, json, span, isHead), Math.max(BEARER_VALUE_MIN, BARE_WORD_MAX + 1, STRONG_AUTH_SCHEME_MAX + 1), "anchor", { kind: "bounded", gap: (c) => isInlineSpaceUnit(c) || isSchemeDelimiterCode(c) }, ARM_RANK.keyword, true));
3826
4080
  for (const row of KEYWORD_SECRET_PATTERNS)
3827
4081
  members.push(regexMember(row, ARM_RANK.keyword, members.length));
3828
4082
  for (const row of SHAPE_SECRET_PATTERNS)
3829
4083
  members.push(regexMember(row, ARM_RANK.shape, members.length));
3830
4084
  for (const row of FRAGMENT_SECRET_PATTERNS)
3831
4085
  members.push(regexMember(row, ARM_RANK.fragment, members.length));
4086
+ members.push(scannerMember(ANCHORED_VALUE_TOKEN, members.length, (text, json, _eat, span, isHead, deletedAt) => collectDiagnosticValueSpans(text, json, span, isHead, deletedAt), Math.max(CREDENTIAL_NAME_MAX, STRONG_AUTH_SCHEME_MAX) + 2, "prose", { kind: "bounded", gap: isRegexSpace }, ARM_RANK.keyword, true, true));
3832
4087
  for (const [re] of KEYWORD_SECRET_PATTERNS) {
3833
4088
  if (!LEXICAL_KEYWORD_ARMS.has(re))
3834
4089
  throw new Error(`redact: keyword arm /${re.source}/ is not registered as lexical — build it with keywordArm() so the bounded-unit scope can exclude it`);
@@ -3840,8 +4095,9 @@ const armPool = (() => {
3840
4095
  const laneOf = (scope) => {
3841
4096
  const inScope = (m) => {
3842
4097
  switch (scope) {
3843
- case "free-text": return true;
3844
- case "bounded-unit": return !m.lexical;
4098
+ case "free-text": return !m.diagnosticOnly;
4099
+ case "bounded-unit": return !m.lexical && !m.diagnosticOnly;
4100
+ case "diagnostic": return true;
3845
4101
  }
3846
4102
  };
3847
4103
  return {
@@ -3853,13 +4109,14 @@ const armPool = (() => {
3853
4109
  const LANES = {
3854
4110
  "free-text": laneOf("free-text"),
3855
4111
  "bounded-unit": laneOf("bounded-unit"),
4112
+ diagnostic: laneOf("diagnostic"),
3856
4113
  };
3857
4114
  const headScreen = new RegExp(`(?:${retryMembers.map((m) => m.headSrc).join("|")})`, "y");
3858
4115
  const headFirstUnit = unionMembers(retryMembers.map((m) => m.headFirst)) ?? new Uint32Array(0x10000 >>> 5).fill(0xffffffff);
3859
4116
  poolArmCount = members.length;
3860
4117
  poolBoundaryArmCount = retryMembers.length;
3861
4118
  const reaches = members.map((m) => ({ token: m.token, order: m.order, reach: m.reach }));
3862
- const run = (text, wantCount, json, eat, scope, reach, engineMarked) => {
4119
+ const run = (text, wantCount, json, eat, scope, reach, engineMarked, deletedAt) => {
3863
4120
  readings += 1;
3864
4121
  const isHead = reach !== undefined;
3865
4122
  const lane = LANES[scope];
@@ -3914,7 +4171,7 @@ const armPool = (() => {
3914
4171
  }
3915
4172
  };
3916
4173
  for (const m of lane.phase1)
3917
- m.collect(text, json, eat, spans, isHead);
4174
+ m.collect(text, json, eat, spans, isHead, deletedAt);
3918
4175
  closeCoveragePositions(0);
3919
4176
  if (lane.phase2.length > 0) {
3920
4177
  const scan = buildForensicScan(tokenUnits(text), buildEvidenceRows(text), lane.phase2.length);
@@ -3999,8 +4256,8 @@ let onRedaction;
3999
4256
  export function setRedactionObserver(fn) {
4000
4257
  onRedaction = fn;
4001
4258
  }
4002
- function applyRules(text, wantCount, json, eat, scope, reach, engineMarked) {
4003
- return armPool(text, wantCount, json, eat, scope, reach, engineMarked);
4259
+ function applyRules(text, wantCount, json, eat, scope, reach, engineMarked, deletedAt) {
4260
+ return armPool(text, wantCount, json, eat, scope, reach, engineMarked, deletedAt);
4004
4261
  }
4005
4262
  function reportHits(hits) {
4006
4263
  if (onRedaction === undefined)
@@ -4072,7 +4329,19 @@ function runRedaction(text, observe, json, wantHits, scope, layout, extent, obse
4072
4329
  const toOriginal = createViewToOriginal(layers);
4073
4330
  const reach = extent.kind === "head" ? (viewStart) => toOriginal.start(viewStart) < extent.emitEnd : undefined;
4074
4331
  const engineMarked = (viewStart, viewEnd, repl) => isEngineMarkedCandidate(text, toOriginal.start(viewStart), toOriginal.start(viewEnd - 1) + 1, repl);
4075
- const r = applyRules(view, wantCount, json, eat, scope, reach, engineMarked);
4332
+ const deletedAt = (viewIndex) => {
4333
+ if (viewIndex <= 0 || viewIndex > view.length)
4334
+ return "none";
4335
+ const lo = toOriginal.start(viewIndex - 1) + 1;
4336
+ const hi = viewIndex === view.length ? text.length : toOriginal.start(viewIndex);
4337
+ if (hi <= lo)
4338
+ return "none";
4339
+ for (let k = lo; k < hi; k++)
4340
+ if (isRegexSpace(text.charCodeAt(k)))
4341
+ return "blank";
4342
+ return "invisible";
4343
+ };
4344
+ const r = applyRules(view, wantCount, json, eat, scope, reach, engineMarked, deletedAt);
4076
4345
  forgetEscapedSeparatorTails();
4077
4346
  readsSoFar += 1;
4078
4347
  if (readsSoFar === 1) {
@@ -4154,7 +4423,7 @@ export function redactSecretsWithArms(text, opts) {
4154
4423
  return { text: r.text, arms: new Set(r.hits.map((h) => h.arm)) };
4155
4424
  }
4156
4425
  export function redactionSpansForTest(text, opts) {
4157
- const r = runRedaction(text, false, opts?.json === true, false, "free-text", "multi-line", WHOLE_EXTENT);
4426
+ const r = runRedaction(text, false, opts?.json === true, false, opts?.scope ?? "free-text", "multi-line", WHOLE_EXTENT);
4158
4427
  return { text: r.text, spans: r.spans.map((sp) => ({ start: sp.start, end: sp.end })) };
4159
4428
  }
4160
4429
  export function proposeRedactionSpans(text, scope, layout, extent) {