@sema-agent/core 7.52.0 → 7.54.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 (357) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/LICENSE +3 -1
  3. package/README.md +3 -1
  4. package/dist/agents/cross-session-envelope.d.ts +8 -0
  5. package/dist/agents/cross-session-envelope.js +6 -0
  6. package/dist/agents/cross-session-judge.d.ts +21 -1
  7. package/dist/agents/cross-session-judge.js +8 -0
  8. package/dist/agents/cross-session-ref.d.ts +5 -0
  9. package/dist/agents/cross-session-ref.js +1 -0
  10. package/dist/agents/org-delivery-gate.d.ts +122 -0
  11. package/dist/agents/org-delivery-gate.js +69 -0
  12. package/dist/agents/peer-held-queue.d.ts +9 -4
  13. package/dist/agents/peer-held-queue.js +6 -5
  14. package/dist/agents/peer-session-drain.d.ts +35 -6
  15. package/dist/agents/peer-session-drain.js +271 -182
  16. package/dist/agents/read-inbox-tool.d.ts +7 -0
  17. package/dist/agents/read-inbox-tool.js +5 -1
  18. package/dist/agents/send-message-tool.js +3 -4
  19. package/dist/agents/subagent.d.ts +6 -5
  20. package/dist/agents/subagent.js +117 -83
  21. package/dist/agents/tool-filter.d.ts +25 -4
  22. package/dist/agents/tool-filter.js +13 -3
  23. package/dist/brain/anthropic.d.ts +6 -1
  24. package/dist/brain/anthropic.js +4 -4
  25. package/dist/brain/model-presets.js +2 -1
  26. package/dist/brain/route-adjudicator.d.ts +6 -0
  27. package/dist/brain/routing.d.ts +24 -1
  28. package/dist/brain/routing.js +54 -19
  29. package/dist/brain/timeout.js +5 -4
  30. package/dist/core/a2a.d.ts +5 -2
  31. package/dist/core/a2a.js +33 -14
  32. package/dist/core/allow-entry.d.ts +3 -1
  33. package/dist/core/allow-entry.js +3 -2
  34. package/dist/core/approval-object.d.ts +87 -0
  35. package/dist/core/approval-object.js +85 -0
  36. package/dist/core/arg-summary.d.ts +3 -2
  37. package/dist/core/arg-summary.js +17 -11
  38. package/dist/core/ask-origin.d.ts +43 -27
  39. package/dist/core/ask-origin.js +20 -11
  40. package/dist/core/ask-question.d.ts +0 -1
  41. package/dist/core/ask-question.js +4 -67
  42. package/dist/core/ask-unresolvable-notice.d.ts +3 -2
  43. package/dist/core/auto-compaction.d.ts +106 -50
  44. package/dist/core/auto-compaction.js +69 -53
  45. package/dist/core/auto-mode-prompt.d.ts +4 -2
  46. package/dist/core/auto-mode-prompt.js +4 -3
  47. package/dist/core/canonical-json.d.ts +69 -0
  48. package/dist/core/canonical-json.js +130 -8
  49. package/dist/core/checkpoint-requirements.d.ts +13 -7
  50. package/dist/core/checkpoint-requirements.js +4 -1
  51. package/dist/core/checkpoint-store.d.ts +60 -36
  52. package/dist/core/checkpoint-store.js +7 -6
  53. package/dist/core/child-clamp-seats.d.ts +45 -6
  54. package/dist/core/child-clamp-seats.js +56 -4
  55. package/dist/core/compliance.js +3 -1
  56. package/dist/core/consolidate-scope.d.ts +1 -1
  57. package/dist/core/cross-boundary-taint.d.ts +213 -0
  58. package/dist/core/cross-boundary-taint.js +196 -0
  59. package/dist/core/decision-receipt.d.ts +44 -1
  60. package/dist/core/decision-receipt.js +16 -0
  61. package/dist/core/effective-path-target.d.ts +28 -6
  62. package/dist/core/effective-path-target.js +28 -2
  63. package/dist/core/engine-notice.d.ts +47 -4
  64. package/dist/core/engine-notice.js +17 -1
  65. package/dist/core/engine-storage-backend.d.ts +73 -0
  66. package/dist/core/engine-storage-backend.js +1 -0
  67. package/dist/core/file-history-store.d.ts +6 -2
  68. package/dist/core/file-history-store.js +1 -0
  69. package/dist/core/gate-fold.js +13 -4
  70. package/dist/core/gate-lanes.js +41 -34
  71. package/dist/core/gate-outcome.d.ts +18 -9
  72. package/dist/core/governance-codes.d.ts +9 -2
  73. package/dist/core/governance-codes.js +9 -0
  74. package/dist/core/hands-band-screen.d.ts +7 -0
  75. package/dist/core/hands-band-screen.js +32 -0
  76. package/dist/core/hooks.d.ts +21 -19
  77. package/dist/core/hooks.js +6 -5
  78. package/dist/core/locked-config.d.ts +110 -31
  79. package/dist/core/locked-config.js +155 -42
  80. package/dist/core/lsp.d.ts +1 -1
  81. package/dist/core/mcp-probe.js +1 -1
  82. package/dist/core/mcp-server-spec.d.ts +152 -17
  83. package/dist/core/mcp-server-spec.js +223 -40
  84. package/dist/core/mcp.d.ts +21 -14
  85. package/dist/core/mcp.js +59 -54
  86. package/dist/core/memory-engine/engine.d.ts +14 -19
  87. package/dist/core/memory-engine/engine.js +9 -6
  88. package/dist/core/memory-engine/export-bundle.d.ts +1 -1
  89. package/dist/core/memory-engine/export-bundle.js +1 -1
  90. package/dist/core/memory-engine/file-backend.d.ts +2 -6
  91. package/dist/core/memory-engine/file-backend.js +1 -12
  92. package/dist/core/memory.d.ts +3 -3
  93. package/dist/core/mode-policy.d.ts +16 -26
  94. package/dist/core/mode-policy.js +5 -18
  95. package/dist/core/mods/kernel/dispatch.js +13 -15
  96. package/dist/core/mods/kernel/events.d.ts +9 -6
  97. package/dist/core/mods/kernel/events.js +2 -2
  98. package/dist/core/mods/kernel/receive.d.ts +41 -11
  99. package/dist/core/mods/kernel/receive.js +124 -54
  100. package/dist/core/mods/kernel/site-rules.d.ts +80 -15
  101. package/dist/core/mods/kernel/site-rules.js +232 -40
  102. package/dist/core/mods/stations.d.ts +0 -6
  103. package/dist/core/mods/stations.js +0 -7
  104. package/dist/core/mounted-mcp.d.ts +57 -0
  105. package/dist/core/mounted-mcp.js +71 -2
  106. package/dist/core/own-property-receipt.d.ts +13 -0
  107. package/dist/core/own-property-receipt.js +3 -1
  108. package/dist/core/parent-spec-seat.d.ts +12 -15
  109. package/dist/core/parent-spec-seat.js +14 -6
  110. package/dist/core/pause-registry.d.ts +35 -1
  111. package/dist/core/pause-registry.js +10 -0
  112. package/dist/core/permission-rule-consent.d.ts +18 -5
  113. package/dist/core/permission-rule-consent.js +13 -8
  114. package/dist/core/permission-rule-model.d.ts +87 -15
  115. package/dist/core/permission-rule-model.js +87 -8
  116. package/dist/core/permission-rule-org.d.ts +200 -33
  117. package/dist/core/permission-rule-org.js +217 -91
  118. package/dist/core/permission-rule-session.js +2 -2
  119. package/dist/core/permission-rule-store.d.ts +8 -0
  120. package/dist/core/permission-rule-store.js +1 -0
  121. package/dist/core/permission-rule-sync.js +3 -2
  122. package/dist/core/permission-rules.d.ts +7 -1
  123. package/dist/core/permission-rules.js +37 -8
  124. package/dist/core/read-only-shell.d.ts +1 -1
  125. package/dist/core/read-only-shell.js +30 -9
  126. package/dist/core/remote-env.d.ts +41 -1
  127. package/dist/core/remote-env.js +18 -0
  128. package/dist/core/resume-startup-cause.d.ts +18 -0
  129. package/dist/core/resume-startup-cause.js +12 -0
  130. package/dist/core/retention.js +7 -2
  131. package/dist/core/retired-keys.d.ts +8 -2
  132. package/dist/core/retired-keys.js +12 -1
  133. package/dist/core/roles.js +60 -10
  134. package/dist/core/rule-lane-reads.js +1 -1
  135. package/dist/core/runner/approval-feedback.d.ts +46 -0
  136. package/dist/core/runner/approval-feedback.js +41 -0
  137. package/dist/core/runner/compaction-call-options.d.ts +3 -3
  138. package/dist/core/runner/compaction-call-options.js +2 -2
  139. package/dist/core/runner/contracts.d.ts +34 -41
  140. package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
  141. package/dist/core/runner/cross-boundary-lane.js +190 -0
  142. package/dist/core/runner/decide-continuation.d.ts +4 -4
  143. package/dist/core/runner/decide-continuation.js +3 -1
  144. package/dist/core/runner/gate-exit.d.ts +32 -12
  145. package/dist/core/runner/gate-exit.js +77 -34
  146. package/dist/core/runner/inherited-ask-grants.js +2 -2
  147. package/dist/core/runner/mcp-redial.d.ts +52 -10
  148. package/dist/core/runner/mcp-redial.js +38 -9
  149. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  150. package/dist/core/runner/permission-rule-lanes.js +22 -10
  151. package/dist/core/runner/person-path-rows.d.ts +5 -3
  152. package/dist/core/runner/person-path-rows.js +2 -2
  153. package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
  154. package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
  155. package/dist/core/runner/prepare-ask-lane.js +3 -3
  156. package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
  157. package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
  158. package/dist/core/runner/prepare-config-doors.d.ts +58 -15
  159. package/dist/core/runner/prepare-config-doors.js +167 -146
  160. package/dist/core/runner/prepare-context-lane.js +6 -3
  161. package/dist/core/runner/prepare-defer-classify.js +4 -7
  162. package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
  163. package/dist/core/runner/prepare-delegation-surface.js +8 -7
  164. package/dist/core/runner/prepare-execution-env.d.ts +1 -2
  165. package/dist/core/runner/prepare-execution-env.js +2 -1
  166. package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
  167. package/dist/core/runner/prepare-gate-stations.js +4 -3
  168. package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
  169. package/dist/core/runner/prepare-hands-readface.js +3 -2
  170. package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
  171. package/dist/core/runner/prepare-inherited-gate.js +3 -2
  172. package/dist/core/runner/prepare-listings.d.ts +1 -1
  173. package/dist/core/runner/prepare-listings.js +4 -2
  174. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  175. package/dist/core/runner/prepare-memory-engine-session.js +19 -6
  176. package/dist/core/runner/prepare-memory.d.ts +3 -2
  177. package/dist/core/runner/prepare-memory.js +6 -2
  178. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  179. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  180. package/dist/core/runner/prepare-park-ask.d.ts +1 -1
  181. package/dist/core/runner/prepare-park-ask.js +9 -3
  182. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  183. package/dist/core/runner/prepare-policy-chain.js +14 -19
  184. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  185. package/dist/core/runner/prepare-project-context.js +6 -4
  186. package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
  187. package/dist/core/runner/prepare-prompt-assembly.js +20 -16
  188. package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
  189. package/dist/core/runner/prepare-prompt-inputs.js +6 -3
  190. package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
  191. package/dist/core/runner/prepare-protocol-tools.js +19 -12
  192. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  193. package/dist/core/runner/prepare-question-face.js +4 -3
  194. package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
  195. package/dist/core/runner/prepare-safety-scan.js +34 -27
  196. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
  197. package/dist/core/runner/prepare-suspend-saga.js +6 -2
  198. package/dist/core/runner/prepare-task.js +22 -19
  199. package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
  200. package/dist/core/runner/prepare-turn-wiring.js +14 -49
  201. package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
  202. package/dist/core/runner/prepare-wiring-manifest.js +9 -6
  203. package/dist/core/runner/prepare-workspace-restore.js +2 -2
  204. package/dist/core/runner/resume-admission.d.ts +4 -1
  205. package/dist/core/runner/resume-admission.js +16 -14
  206. package/dist/core/runner/resume-apply.js +4 -4
  207. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  208. package/dist/core/runner/resume-internals-and-config.js +3 -8
  209. package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
  210. package/dist/core/runner/resume-policy-outcome.js +18 -15
  211. package/dist/core/runner/resume-preflight.js +2 -2
  212. package/dist/core/runner/resume-review-outcome.js +3 -3
  213. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  214. package/dist/core/runner/retired-runner-deps.js +1 -4
  215. package/dist/core/runner/run-leg.js +97 -43
  216. package/dist/core/runner/run-recovery-lanes.js +5 -3
  217. package/dist/core/runner/run-settle-and-teardown.js +2 -0
  218. package/dist/core/runner/run-terminal-adoption.js +21 -9
  219. package/dist/core/runner/run-turn-boundary.js +9 -3
  220. package/dist/core/runner/runtask.js +1 -1
  221. package/dist/core/runner/session-file-state-replay.d.ts +5 -2
  222. package/dist/core/runner/session-file-state-replay.js +3 -2
  223. package/dist/core/runner/skills-seat.d.ts +15 -0
  224. package/dist/core/runner/skills-seat.js +57 -0
  225. package/dist/core/runner/stream-steer-verb.js +2 -2
  226. package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
  227. package/dist/core/runner/sub-agent-deny-lists.js +7 -5
  228. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  229. package/dist/core/runner/synthetic-tools.js +2 -12
  230. package/dist/core/runner/tool-face-overlay.d.ts +24 -6
  231. package/dist/core/runner/tool-face-overlay.js +24 -15
  232. package/dist/core/runner-deps.d.ts +37 -22
  233. package/dist/core/session-policy-store.d.ts +19 -0
  234. package/dist/core/session-policy-store.js +22 -2
  235. package/dist/core/session-store.d.ts +35 -16
  236. package/dist/core/session-store.js +20 -12
  237. package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
  238. package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
  239. package/dist/core/shell-wrapper-table.d.ts +5 -3
  240. package/dist/core/shell-wrapper-table.js +1 -1
  241. package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
  242. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  243. package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
  244. package/dist/core/store-contracts/session-store-contract.js +639 -0
  245. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
  246. package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
  247. package/dist/core/task-event.d.ts +44 -6
  248. package/dist/core/task-notification.js +2 -2
  249. package/dist/core/task-registry-agent.js +1 -0
  250. package/dist/core/task-registry-shared.d.ts +5 -0
  251. package/dist/core/task-registry.d.ts +7 -0
  252. package/dist/core/task-registry.js +17 -0
  253. package/dist/core/task-result.d.ts +1 -1
  254. package/dist/core/task-spec.d.ts +7 -7
  255. package/dist/core/tighten-task-spec.d.ts +6 -4
  256. package/dist/core/tighten-task-spec.js +2 -2
  257. package/dist/core/tool-catalog-entries.d.ts +1 -1
  258. package/dist/core/tool-catalog-entries.js +52 -52
  259. package/dist/core/tool-face-reader.d.ts +49 -0
  260. package/dist/core/tool-face-reader.js +94 -0
  261. package/dist/core/tool-face.d.ts +17 -8
  262. package/dist/core/tool-face.js +1 -0
  263. package/dist/core/tool-policy.d.ts +67 -23
  264. package/dist/core/tool-policy.js +72 -60
  265. package/dist/core/tool-roster.d.ts +46 -28
  266. package/dist/core/tool-roster.js +91 -14
  267. package/dist/core/tool-spec-members.js +2 -2
  268. package/dist/core/tool-spec.d.ts +20 -4
  269. package/dist/core/tools.js +2 -0
  270. package/dist/core/trace.d.ts +24 -2
  271. package/dist/core/types.d.ts +3 -3
  272. package/dist/core/types.js +1 -1
  273. package/dist/core/untrusted-text.d.ts +23 -0
  274. package/dist/core/untrusted-text.js +10 -10
  275. package/dist/core/user-attachment.d.ts +56 -2
  276. package/dist/core/user-attachment.js +139 -56
  277. package/dist/core/wiring-manifest.d.ts +4 -2
  278. package/dist/engine/compaction/compaction.d.ts +2 -2
  279. package/dist/engine/compaction/utils.d.ts +2 -2
  280. package/dist/engine/harness/agent-harness.js +2 -1
  281. package/dist/engine/harness/types.d.ts +10 -4
  282. package/dist/engine/llm/types.d.ts +7 -2
  283. package/dist/engine/llm/types.js +2 -1
  284. package/dist/engine/loop/agent-loop.d.ts +12 -1
  285. package/dist/engine/loop/agent-loop.js +17 -5
  286. package/dist/engine/loop/types.d.ts +7 -1
  287. package/dist/engine/session/repo-utils.d.ts +5 -0
  288. package/dist/engine/session/repo-utils.js +9 -0
  289. package/dist/engine/session/storage-base.js +2 -2
  290. package/dist/index.d.ts +37 -17
  291. package/dist/index.js +31 -14
  292. package/dist/internal/harness.d.ts +1 -0
  293. package/dist/internal/harness.js +1 -0
  294. package/dist/internal/llm.d.ts +1 -1
  295. package/dist/internal/llm.js +1 -1
  296. package/dist/orchestration/goal.d.ts +24 -1
  297. package/dist/orchestration/goal.js +3 -2
  298. package/dist/orchestration/run-workflow-tool.d.ts +3 -0
  299. package/dist/orchestration/run-workflow-tool.js +1 -0
  300. package/dist/orchestration/workflow-governance.d.ts +1 -1
  301. package/dist/orchestration/workflow.d.ts +3 -0
  302. package/dist/orchestration/workflow.js +2 -1
  303. package/dist/prompt-assembly/artifact-store.d.ts +44 -9
  304. package/dist/prompt-assembly/artifact-store.js +38 -12
  305. package/dist/prompt-assembly/artifact.d.ts +12 -11
  306. package/dist/prompt-assembly/artifact.js +52 -21
  307. package/dist/prompt-assembly/assemble.d.ts +2 -0
  308. package/dist/prompt-assembly/assemble.js +2 -1
  309. package/dist/prompt-assembly/catalog/index.js +2 -1
  310. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  311. package/dist/prompt-assembly/catalog/memory.js +6 -0
  312. package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
  313. package/dist/prompt-assembly/catalog/schema.js +3 -0
  314. package/dist/prompt-assembly/composer.d.ts +2 -0
  315. package/dist/prompt-assembly/composer.js +1 -1
  316. package/dist/prompt-assembly/overlay.d.ts +21 -11
  317. package/dist/prompt-assembly/overlay.js +57 -19
  318. package/dist/prompt-assembly/select.d.ts +21 -6
  319. package/dist/prompt-assembly/select.js +41 -4
  320. package/dist/prompts/default.d.ts +1 -12
  321. package/dist/prompts/default.js +0 -3
  322. package/dist/shell/lex.d.ts +87 -8
  323. package/dist/shell/lex.js +283 -49
  324. package/dist/stores/file/index.d.ts +8 -6
  325. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  326. package/dist/stores/file/permission-rule-store.js +2 -1
  327. package/dist/tools/artifact/artifact-tool.js +14 -3
  328. package/dist/tools/fs/bash-program-position.d.ts +3 -15
  329. package/dist/tools/fs/bash-program-position.js +3 -10
  330. package/dist/tools/fs/bash-readonly-classifier.js +2 -0
  331. package/dist/tools/fs/fs-bash.d.ts +3 -3
  332. package/dist/tools/fs/fs-bash.js +72 -101
  333. package/dist/tools/fs/fs-read.d.ts +12 -0
  334. package/dist/tools/fs/fs-read.js +10 -9
  335. package/dist/tools/fs/fs-shared.d.ts +27 -31
  336. package/dist/tools/fs/fs-shared.js +12 -15
  337. package/dist/tools/fs/fs-write.js +1 -1
  338. package/dist/tools/fs/index.js +2 -2
  339. package/dist/tools/fs/read-deny-home.d.ts +1 -1
  340. package/dist/tools/fs/read-deny-home.js +5 -4
  341. package/dist/tools/fs/read-deny.d.ts +16 -3
  342. package/dist/tools/fs/read-deny.js +12 -9
  343. package/dist/tools/fs/safety.d.ts +7 -6
  344. package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
  345. package/dist/tools/fs/shell-read-bindings.js +15 -16
  346. package/dist/tools/fs/shell-read-device.js +1 -1
  347. package/dist/tools/fs/shell-read-plan.js +36 -47
  348. package/dist/tools/fs/shell-read-word.d.ts +1 -6
  349. package/dist/tools/fs/shell-read-word.js +2 -20
  350. package/dist/tools/fs/shell-reentry-text.js +1 -1
  351. package/dist/tools/web.d.ts +2 -2
  352. package/package.json +4 -1
  353. package/test/export-surface.snapshot.json +5651 -5457
  354. package/wire-changes/core@7.53.0.json +1968 -0
  355. package/wire-changes/core@7.54.0.json +2870 -0
  356. package/dist/core/shell-scan.d.ts +0 -60
  357. package/dist/core/shell-scan.js +0 -183
@@ -1,7 +1,7 @@
1
1
  import { CATCH_BUDGET_MS, createSelfBudget, POST_ABORT_GRACE_MS, RUNAWAY_AFTER_MS, unrefTimer, watchRunaway } from "./budget.js";
2
2
  import { expandModPattern, isModEventName, MOD_SEATS, nextToRefusal, stationOn } from "./events.js";
3
3
  import { ENGINE_ORIGIN, modsInvalid, screenModSeats, } from "./registration.js";
4
- import { answerUpward, answerViolation, detachedCopy, matcherMatches, matcherViolation, methodAnswerViolation, NEXT_IN_FLIGHT, pinnedKeyChanged, receiveAnswer, receivePayload, } from "./site-rules.js";
4
+ import { answerUpward, answerViolation, detachedCopy, engineObjectsOnce, handedOn, matcherMatches, matcherViolation, methodAnswerViolation, NEXT_IN_FLIGHT, receiveAnswer, receiveEvent, receivePayload, } from "./site-rules.js";
5
5
  const TIER_RANK = { prepend: 0, user: 1, append: 2, builtin: 3, core: 4 };
6
6
  const bypassed = (floors, tier) => floors.some((f) => TIER_RANK[f.from] < TIER_RANK[tier] && TIER_RANK[tier] < TIER_RANK[f.to]);
7
7
  export async function admitMods(input) {
@@ -202,7 +202,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
202
202
  hasHandlers: (event, participant) => mounted.some((h) => h.events.has(event) && admits(participant, h)),
203
203
  dispatch: (event, e, options) => {
204
204
  const st = stationOn(event, side);
205
- const received = st === undefined ? { refusal: `${event} is not raised on the ${side} bus` } : receivePayload(e);
205
+ const received = st === undefined ? { refusal: `${event} is not raised on the ${side} bus` } : receiveEvent(e);
206
206
  if (st === undefined || "refusal" in received) {
207
207
  const reason = `${event}: ${"refusal" in received ? received.refusal : "not raised"}`;
208
208
  report(new Error(`engine: ${reason} — the dispatch was not run`));
@@ -237,7 +237,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
237
237
  throw new Error(`${caller.origin.plugin}: $.${event}: not raised on the ${side} bus`);
238
238
  let e0 = args;
239
239
  if (seat.enter !== undefined) {
240
- const shaped = receivePayload(seat.enter(args), undefined, isProxy);
240
+ const shaped = receivePayload(seat.enter(args), isProxy, engineObjectsOnce(args)());
241
241
  if ("refusal" in shaped)
242
242
  throw new TypeError(`${caller.origin.plugin}: $.${event}: ${shaped.refusal}`);
243
243
  e0 = shaped.payload;
@@ -263,7 +263,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
263
263
  throw new Error(`${caller.origin.plugin}: $.${event}: ${deny}`);
264
264
  return typeof answer === "object" && answer !== null ? Reflect.get(answer, "value") : undefined;
265
265
  }
266
- function dollarFor(reg, frames, budget, signal) {
266
+ function dollarFor(reg, frames, budget, signal, engines) {
267
267
  const origin = Object.freeze({ plugin: reg.name, tier: reg.tier });
268
268
  const callerFrames = Object.freeze([...frames, Object.freeze({ kind: "dollar", plugin: reg.name })]);
269
269
  const namespaces = new Map();
@@ -273,7 +273,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
273
273
  ns[m.method] = async (args) => {
274
274
  if (!reg.callsBound.has(m.event))
275
275
  throw new Error(`${reg.name}: $.${m.event}: not declared in uses.calls`);
276
- const received = receivePayload(args === undefined ? {} : args, undefined, isProxy);
276
+ const received = receivePayload(args === undefined ? {} : args, isProxy, engines());
277
277
  if ("refusal" in received)
278
278
  throw new TypeError(`${reg.name}: $.${m.event}: takes one object — ${received.refusal}`);
279
279
  if (m.pauses)
@@ -347,19 +347,17 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
347
347
  const drop = () => void pendingRuns.delete(run);
348
348
  run.then(drop, drop);
349
349
  };
350
+ const engines = engineObjectsOnce(e0);
350
351
  const handOn = (passed) => {
351
352
  if (passed === e0)
352
353
  return { snap: e0 };
353
- const received = receivePayload(passed, e0, isProxy);
354
- if ("refusal" in received)
355
- return { violation: `next() takes the event object: ${received.refusal}` };
356
- const k = pinnedKeyChanged(st.pinned, e0, received.payload);
357
- return k === undefined ? { snap: received.payload } : { violation: `next() changed the pinned key "${k}"` };
354
+ const handed = handedOn(st.pinned, e0, passed, engines(), isProxy);
355
+ return "violation" in handed ? handed : { snap: handed.payload };
358
356
  };
359
357
  const takeAnswer = (answer, s, e, h) => {
360
358
  let taken = answer;
361
359
  if (!s.answers.some((a) => Object.is(a, answer))) {
362
- const received = receiveAnswer(answer, isProxy);
360
+ const received = receiveAnswer(answer, engines(), isProxy);
363
361
  if ("refusal" in received)
364
362
  return { violation: received.refusal };
365
363
  taken = received.answer;
@@ -472,7 +470,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
472
470
  }
473
471
  else {
474
472
  const next = makeNext({ budget, signal: ac.signal, trace: () => Object.freeze([...state.below]) }, (x) => descend(x, floors), to);
475
- const $ = dollarFor(h.reg, myFrames, budget, ac.signal);
473
+ const $ = dollarFor(h.reg, myFrames, budget, ac.signal, engines);
476
474
  handlerP = invokeNow(() => h.fn($, e, next));
477
475
  try {
478
476
  const raced = await Promise.race([handlerP, budget.expired]);
@@ -578,7 +576,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
578
576
  return why !== undefined ? Promise.reject(new Error(`${h.reg.name}: ${why}`)) : replay(x, [...floors, { from: h.reg.tier, to: tier }]);
579
577
  }, { error, called: state.called });
580
578
  try {
581
- const raced = await Promise.race([invokeNow(() => onCatch(dollarFor(h.reg, myFrames, budget, ac.signal), e, next)), budget.expired]);
579
+ const raced = await Promise.race([invokeNow(() => onCatch(dollarFor(h.reg, myFrames, budget, ac.signal, engines), e, next)), budget.expired]);
582
580
  if (raced === "expired" && budget.isExpired())
583
581
  return { problem: `its .catch ran past its ${CATCH_BUDGET_MS}ms budget` };
584
582
  if (violated !== undefined)
@@ -610,7 +608,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
610
608
  report(new Error(`${name}: ${event}: an observe handler returned a verdict — not adopted; an observe handler answers undefined`), "observational-hook-verdict-ignored");
611
609
  };
612
610
  try {
613
- const raced = await Promise.race([invokeNow(() => h.fn(dollarFor(h.reg, myFrames, budget, ac.signal), detachedCopy(e0), next)), budget.expired]);
611
+ const raced = await Promise.race([invokeNow(() => h.fn(dollarFor(h.reg, myFrames, budget, ac.signal, engines), detachedCopy(e0), next)), budget.expired]);
614
612
  if (raced === "expired" && budget.isExpired())
615
613
  throw new Error(`ran past its ${h.reg.budgetMs}ms budget`);
616
614
  verdict(raced);
@@ -631,7 +629,7 @@ function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
631
629
  called: false,
632
630
  });
633
631
  try {
634
- const caught = await Promise.race([invokeNow(() => onCatch(dollarFor(h.reg, myFrames, catchBudget, cac.signal), detachedCopy(e0), cnext)), catchBudget.expired]);
632
+ const caught = await Promise.race([invokeNow(() => onCatch(dollarFor(h.reg, myFrames, catchBudget, cac.signal, engines), detachedCopy(e0), cnext)), catchBudget.expired]);
635
633
  if (!(caught === "expired" && catchBudget.isExpired()))
636
634
  verdict(caught);
637
635
  }
@@ -8,12 +8,14 @@
8
8
  */
9
9
  /**
10
10
  * The kernel CONTRACT number — a monotonic integer, independent of the package version (the package is
11
- * cut with core every release; this number is not). Every party that loads a kernel copy compares it for
12
- * EQUALITY. It is raised when, and only when, one of four things changes: the chain semantics (`next`,
13
- * `next.to`, origin, trace, re-entry frames), the registration form (`ModRegistration`, `on`, `uses`),
14
- * the event closed set (names and their `side`), or the failure columns (failure, abort, pinned keys).
11
+ * cut with core every release; this number is not). It is exported for a host that loads a kernel copy
12
+ * beside another one to compare for EQUALITY; nothing in this folder or in the engine reads it, so two
13
+ * copies that differ are not detected here. It is raised when, and only when, one of four things changes:
14
+ * the chain semantics (`next`, `next.to`, origin, trace, re-entry frames), the registration form (`ModRegistration`, `on`, `uses`),
15
+ * the event closed set (names and their `side`), or the failure columns (failure, abort, pinned keys — which keys,
16
+ * and how a pinned key is judged: by value since 2).
15
17
  */
16
- export declare const KERNEL_CONTRACT_VERSION = 1;
18
+ export declare const KERNEL_CONTRACT_VERSION = 2;
17
19
  /** The five tiers in run order (CC names). `builtin` and `core` are the engine's own. */
18
20
  export declare const MOD_TIERS: readonly ["prepend", "user", "append", "builtin", "core"];
19
21
  export type ModTier = (typeof MOD_TIERS)[number];
@@ -58,7 +60,8 @@ export declare const SEAT_TIER_TABLE: Readonly<{
58
60
  export interface ModStation {
59
61
  readonly failure: ModFailureAnswer;
60
62
  readonly abort: ModAbortPosture;
61
- /** Keys a handler may not change when it passes `e` on through `next`. */
63
+ /** Keys a handler may not change when it passes `e` on through `next` — compared by value: the engine's fact handed on,
64
+ * or a copy of it (a spread, a structured clone, a JSON round trip), is not a change; a different value is. */
62
65
  readonly pinned: readonly string[];
63
66
  readonly method?: {
64
67
  readonly pausesCallerBudget: boolean;
@@ -1,4 +1,4 @@
1
- export const KERNEL_CONTRACT_VERSION = 1;
1
+ export const KERNEL_CONTRACT_VERSION = 2;
2
2
  export const MOD_TIERS = Object.freeze(["prepend", "user", "append", "builtin", "core"]);
3
3
  export const MOD_SEATS = Object.freeze(["deployment", "task"]);
4
4
  export const MOD_EVENT_SIDES = Object.freeze(["engine", "surface", "both"]);
@@ -87,7 +87,7 @@ export const MOD_EVENT_TABLE = Object.freeze({
87
87
  "prompt.context": engine(),
88
88
  "prompt.attachment": engine(),
89
89
  "prompt.mention": surface,
90
- "prompt.compose": engine(station("skip", "grace", ["model"])),
90
+ "prompt.compose": engine(station("skip", "grace", ["model", "catalog", "selectors"])),
91
91
  "tool.describe": engine(),
92
92
  "command.run": surface,
93
93
  "command.describe": surface,
@@ -8,8 +8,11 @@
8
8
  * ordinary array — within `depth` levels is copied member by member off its own property descriptors, captured in
9
9
  * one call before any of the caller's code can run; each member lands as an enumerable data property of the copy (a
10
10
  * defined property, never an assignment, so an own `__proto__` key stays a plain key). Anything else — a function, an
11
- * object of another prototype, a container past `depth` — is handed as it is or refused, by `others`, which also
12
- * says whether cycles and shared references keep their shape or are refused / walked again.
11
+ * object of another prototype, a container past `depth` — is handed as it is, refused, or (an object of another
12
+ * prototype under `copy`) copied off its own members like a record, by `others`, which also says whether cycles and
13
+ * shared references keep their shape or are refused / walked again. A refusal refuses the whole receipt, or — under
14
+ * `contain` — only the member it was met in. The walk keeps its own stack (one frame per container being copied), so
15
+ * neither how deep a value nests nor how deep its caller already stands decides a verdict: only `depth` does.
13
16
  *
14
17
  * Zero-dependency on purpose (this folder compiles on its own): a Proxy cannot be recognised from here, so the
15
18
  * host passes its probe (`isProxy`); with a probe, a Proxy is refused before anything is asked of it.
@@ -18,9 +21,11 @@
18
21
  export interface ReceiptMode {
19
22
  /**
20
23
  * `call-once`: every own string-keyed member is read — a data property's value, or an accessor's getter called exactly
21
- * once on the object (a getter that throws refuses the receipt; one that moves the object's prototype refuses it).
24
+ * once on the object (a getter that throws refuses the receipt; one that moves the object's prototype refuses it, but
25
+ * under `others: "copy"`).
22
26
  * `refuse`: only own enumerable string-keyed DATA properties are members; an accessor, a non-enumerable property or
23
- * a symbol-keyed one refuses the receipt (no getter ever runs).
27
+ * a symbol-keyed one refuses the receipt (no getter ever runs) — under `contain`, each is a member left out and reported
28
+ * (a symbol-keyed one at its container's path and its `String(symbol)`), its container received.
24
29
  */
25
30
  readonly accessors: "call-once" | "refuse";
26
31
  /** How many levels of containers are copied (`Infinity` = every level). */
@@ -28,14 +33,34 @@ export interface ReceiptMode {
28
33
  /** What a value that is not copied is (a function, another prototype, a container past `depth`, a symbol or a
29
34
  * bigint): handed as it is, or a refusal of the receipt. Shared references keep their shape in the copy (one copy
30
35
  * each); under `as-is` a cycle does too, under `refuse` a cycle is refused and a shared reference must fit `depth`
31
- * where it sits each time it is met. */
32
- readonly others: "as-is" | "refuse";
36
+ * where it sits each time it is met. `copy` is `refuse`, except that an object of another prototype within `depth`
37
+ * — a class instance, another realm's object or array, an array of a subclass — is copied as an ordinary record (an
38
+ * array as an ordinary array) off its OWN members: its prototype is not kept and no code of the prototype runs, so a
39
+ * prototype's getters and a built-in's internal state (a `Date`'s time, a `Map`'s entries) are not members and are
40
+ * not copied, while every own data member is (and an own accessor is read as `accessors` says; one that moves the
41
+ * object's prototype changes nothing the copy holds). A Proxy and a cycle are still refused. */
42
+ readonly others: "as-is" | "refuse" | "copy";
43
+ /** `refuse`: a container (an ordinary record or array) past `depth` refuses the receipt (`too-deep`) even where
44
+ * `others` hands other values as they are — a value of another kind there is still what `others` says — and a shared
45
+ * reference must fit `depth` where it sits each time it is met, by the height its first walk found (a walk that ran
46
+ * into a container still being walked — a cycle — counts that container as one level, and so does an object the
47
+ * reader holds, met directly or in what holds it): `depth` is a bound, never a copy depth. Absent ⇒ a container past
48
+ * `depth` is what `others` says. */
49
+ readonly past?: "refuse";
50
+ /** A fault met in a member — its getter threw, it is a value the receipt refuses, it holds a cycle, it runs too deep,
51
+ * or it could not be copied at all (`uncopyable`) — leaves THAT member out of its container's copy and is reported in the
52
+ * receipt's `faults` (where it was met); the walk goes on with the next member. A container refused where it was met
53
+ * is refused again wherever else it is met (never read twice). Only a fault of the received value itself refuses the
54
+ * receipt. Absent ⇒ the first fault refuses the receipt. */
55
+ readonly contain?: true;
33
56
  /** Every container the copy makes is frozen (a received value cannot be changed after it was received). */
34
57
  readonly freeze?: boolean;
35
58
  /** The host's Proxy probe. */
36
59
  readonly isProxy?: (value: object) => boolean;
37
60
  }
38
- /** Why a receipt was refused. */
61
+ /** Why a receipt was refused. `uncopyable` has two causes, and depth is neither (the walk keeps its own stack): reading
62
+ * the value threw where none of its getters runs — a Proxy's trap, on a receipt given no Proxy probe; what it threw is
63
+ * never read — or the value holds more objects than one receipt can index. */
39
64
  export declare const RECEIPT_FAULTS: readonly ["proxy", "accessor", "hidden", "getter-threw", "prototype-moved", "not-data", "cycle", "too-deep", "uncopyable"];
40
65
  export type ReceiptFaultKind = (typeof RECEIPT_FAULTS)[number];
41
66
  /** A refusal and where in the value it was met (member names from the top). */
@@ -43,9 +68,11 @@ export interface ReceiptFault {
43
68
  readonly kind: ReceiptFaultKind;
44
69
  readonly path: readonly string[];
45
70
  }
71
+ /** A receipt: the copy (with, under `contain`, every fault a member was left out for), or the refusal. */
46
72
  export type Receipt = {
47
73
  readonly ok: true;
48
74
  readonly value: unknown;
75
+ readonly faults?: readonly ReceiptFault[];
49
76
  } | {
50
77
  readonly ok: false;
51
78
  readonly fault: ReceiptFault;
@@ -53,13 +80,16 @@ export type Receipt = {
53
80
  /** Whether `v` is an ordinary record: an object whose prototype is `Object.prototype` or none (an array is not one). */
54
81
  export declare function isPlainRecord(v: unknown): v is Record<string, unknown>;
55
82
  /**
56
- * Receive `value` by `mode`. `held` names objects the reader already owns: met in the walk, each is kept as itself
57
- * (not received again) — so a member handed back unchanged keeps its identity.
83
+ * Receive `value` by `mode`. `held` names objects the reader already owns: met in the walk, each is kept as itself — not
84
+ * received again, never walked — so a member handed back unchanged keeps its identity. The set is consulted as it is,
85
+ * never copied, so one set serves every receipt of the same owner.
58
86
  */
59
- export declare function receive(value: unknown, mode: ReceiptMode, held?: Iterable<unknown>): Receipt;
87
+ export declare function receive(value: unknown, mode: ReceiptMode, held?: ReadonlySet<object>): Receipt;
60
88
  /** The mods bus's mode: a payload and an answer received whole — no accessor runs, no depth limit, cycles and shared
61
89
  * references kept, a function or a class instance handed as it is, every copied container frozen (so a member the
62
- * bus holds cannot be changed under it by a handler that holds it too). */
90
+ * bus holds cannot be changed under it by a handler that holds it too). The engine's own event is received in it as it
91
+ * is; what a handler gives the bus — a payload, an answer, a `$` call's arguments — in it held to the bus's one depth
92
+ * (the site rules set `depth` and `past: "refuse"`). */
63
93
  export declare const MODS_PAYLOAD_MODE: ReceiptMode;
64
94
  /** One clause naming a fault for a sentence ("an accessor at input.deep.x"). */
65
95
  export declare function describeFault(fault: ReceiptFault): string;
@@ -10,91 +10,161 @@ function isOrdinaryArray(v) {
10
10
  }
11
11
  export function receive(value, mode, held) {
12
12
  const seen = new Map();
13
- if (held !== undefined)
14
- for (const h of held)
15
- if (typeof h === "object" && h !== null)
16
- seen.set(h, h);
17
13
  const path = [];
18
14
  const open = new Set();
19
15
  const heights = new Map();
16
+ const faults = [];
17
+ const refusedAt = new Map();
18
+ const stack = [];
19
+ const refusals = new Set();
20
20
  const refuse = (kind) => {
21
- throw { refused: Object.freeze({ kind, path: Object.freeze([...path]) }) };
21
+ const fault = Object.freeze({ kind, path: Object.freeze([...path]) });
22
+ refusals.add(fault);
23
+ throw fault;
22
24
  };
25
+ const faultOf = (err) => typeof err === "object" && err !== null && refusals.has(err) ? err : Object.freeze({ kind: "uncopyable", path: Object.freeze([...path]) });
23
26
  const other = (v, kind) => (mode.others === "as-is" ? v : refuse(kind));
24
- const walk = (v, level) => {
27
+ const refuseContainer = (v, kind) => {
28
+ if (mode.contain === true) {
29
+ refusedAt.set(v, kind);
30
+ open.delete(v);
31
+ }
32
+ return refuse(kind);
33
+ };
34
+ const memberOf = (v, d) => {
35
+ if (Object.hasOwn(d, "value")) {
36
+ if (mode.accessors === "refuse" && d.enumerable !== true)
37
+ refuse("hidden");
38
+ return d.value;
39
+ }
40
+ if (mode.accessors === "refuse")
41
+ refuse("accessor");
42
+ const get = Object.hasOwn(d, "get") ? d.get : undefined;
43
+ try {
44
+ return get === undefined ? undefined : Reflect.apply(get, v, []);
45
+ }
46
+ catch {
47
+ return refuse("getter-threw");
48
+ }
49
+ };
50
+ const measured = mode.past === "refuse" || mode.others !== "as-is";
51
+ const heightOf = (v) => heights.get(v) ?? (open.has(v) || (held?.has(v) === true && mode.isProxy?.(v) !== true && (isOrdinaryArray(v) || isPlainRecord(v))) ? 1 : 0);
52
+ const pastDepth = (v, level) => measured && level + heightOf(v) > mode.depth;
53
+ const meet = (v, level) => {
25
54
  if (v === null || v === undefined || typeof v === "string" || typeof v === "number" || typeof v === "boolean")
26
55
  return v;
27
56
  if (typeof v !== "object")
28
57
  return other(v, "not-data");
58
+ if (held?.has(v) === true)
59
+ return pastDepth(v, level) ? refuse("too-deep") : v;
29
60
  if (seen.has(v)) {
30
- if (open.has(v))
31
- return mode.others === "refuse" ? refuse("cycle") : seen.get(v);
32
- if (mode.others === "refuse" && level + (heights.get(v) ?? 1) > mode.depth)
61
+ if (refusedAt.has(v))
62
+ return refuse(refusedAt.get(v));
63
+ if (open.has(v) && mode.others !== "as-is")
64
+ return refuse("cycle");
65
+ return pastDepth(v, level) ? refuse("too-deep") : seen.get(v);
66
+ }
67
+ if (level >= mode.depth && mode.past === "refuse") {
68
+ if (mode.isProxy?.(v) === true)
69
+ return refuse("proxy");
70
+ if (isOrdinaryArray(v) || isPlainRecord(v))
33
71
  return refuse("too-deep");
34
- return seen.get(v);
35
72
  }
36
73
  if (level >= mode.depth)
37
74
  return other(v, "too-deep");
38
75
  if (mode.isProxy?.(v) === true)
39
76
  return refuse("proxy");
40
- const list = isOrdinaryArray(v);
41
- if (!list && !isPlainRecord(v))
77
+ const list = isOrdinaryArray(v) || (mode.others === "copy" && Array.isArray(v));
78
+ if (!list && !isPlainRecord(v) && mode.others !== "copy")
42
79
  return other(v, "not-data");
43
80
  const proto = Object.getPrototypeOf(v);
44
81
  const captured = Object.getOwnPropertyDescriptors(v);
45
82
  const out = list ? [] : {};
46
83
  seen.set(v, out);
47
84
  open.add(v);
48
- let height = 1;
49
- if (mode.accessors === "refuse" && Object.getOwnPropertySymbols(captured).length > 0)
50
- refuse("hidden");
51
- for (const key of Object.getOwnPropertyNames(captured)) {
52
- if (list && key === "length")
53
- continue;
54
- const d = captured[key];
55
- path.push(key);
56
- let member;
57
- if (Object.hasOwn(d, "value")) {
58
- if (mode.accessors === "refuse" && d.enumerable !== true)
59
- refuse("hidden");
60
- member = d.value;
61
- }
62
- else {
63
- if (mode.accessors === "refuse")
64
- refuse("accessor");
65
- const get = Object.hasOwn(d, "get") ? d.get : undefined;
66
- try {
67
- member = get === undefined ? undefined : get.call(v);
68
- }
69
- catch {
70
- return refuse("getter-threw");
71
- }
72
- }
73
- Object.defineProperty(out, key, { value: walk(member, level + 1), enumerable: true, writable: true, configurable: true });
74
- if (typeof member === "object" && member !== null)
75
- height = Math.max(height, (heights.get(member) ?? 0) + 1);
76
- path.pop();
85
+ if (mode.accessors === "refuse") {
86
+ const symbols = Object.getOwnPropertySymbols(captured);
87
+ if (symbols.length > 0 && mode.contain !== true)
88
+ refuseContainer(v, "hidden");
89
+ for (const s of symbols)
90
+ faults.push(Object.freeze({ kind: "hidden", path: Object.freeze([...path, String(s)]) }));
77
91
  }
78
- heights.set(v, height);
79
- if (mode.accessors === "call-once" && Object.getPrototypeOf(v) !== proto)
80
- refuse("prototype-moved");
81
- if (Array.isArray(out)) {
82
- const length = captured["length"]?.value;
92
+ stack.push({ v, out, list, proto, captured, keys: Object.getOwnPropertyNames(captured), level, next: 0, height: 1, key: "", member: undefined });
93
+ return out;
94
+ };
95
+ const land = (f, key, copy, member) => {
96
+ if (measured && typeof member === "object" && member !== null)
97
+ f.height = Math.max(f.height, heightOf(member) + 1);
98
+ Object.defineProperty(f.out, key, { value: copy, enumerable: true, writable: true, configurable: true });
99
+ path.length = f.level;
100
+ };
101
+ const finish = (f) => {
102
+ heights.set(f.v, f.height);
103
+ if (mode.accessors === "call-once" && mode.others !== "copy" && Object.getPrototypeOf(f.v) !== f.proto)
104
+ refuseContainer(f.v, "prototype-moved");
105
+ if (Array.isArray(f.out)) {
106
+ const length = f.captured["length"]?.value;
83
107
  if (typeof length === "number")
84
- out.length = length;
108
+ f.out.length = length;
85
109
  }
86
110
  if (mode.freeze === true)
87
- Object.freeze(out);
88
- open.delete(v);
89
- return out;
111
+ Object.freeze(f.out);
112
+ open.delete(f.v);
113
+ return f.out;
90
114
  };
115
+ const received = (copy) => (mode.contain === true ? { ok: true, value: copy, faults: Object.freeze(faults) } : { ok: true, value: copy });
91
116
  try {
92
- return { ok: true, value: walk(value, 0) };
117
+ const copy = meet(value, 0);
118
+ if (stack.length === 0)
119
+ return received(copy);
93
120
  }
94
121
  catch (err) {
95
- if (typeof err === "object" && err !== null && "refused" in err)
96
- return { ok: false, fault: err.refused };
97
- return { ok: false, fault: Object.freeze({ kind: "uncopyable", path: Object.freeze([...path]) }) };
122
+ return { ok: false, fault: faultOf(err) };
123
+ }
124
+ for (;;) {
125
+ const f = stack[stack.length - 1];
126
+ if (f.next < f.keys.length) {
127
+ const key = f.keys[f.next++];
128
+ if (f.list && key === "length")
129
+ continue;
130
+ path.push(key);
131
+ try {
132
+ const member = memberOf(f.v, f.captured[key]);
133
+ const frames = stack.length;
134
+ const copy = meet(member, f.level + 1);
135
+ if (stack.length > frames) {
136
+ f.key = key;
137
+ f.member = member;
138
+ }
139
+ else
140
+ land(f, key, copy, member);
141
+ }
142
+ catch (err) {
143
+ if (mode.contain !== true)
144
+ return { ok: false, fault: faultOf(err) };
145
+ faults.push(faultOf(err));
146
+ path.length = f.level;
147
+ }
148
+ continue;
149
+ }
150
+ let copy;
151
+ try {
152
+ copy = finish(f);
153
+ }
154
+ catch (err) {
155
+ stack.pop();
156
+ const holder = stack[stack.length - 1];
157
+ if (mode.contain !== true || holder === undefined)
158
+ return { ok: false, fault: faultOf(err) };
159
+ faults.push(faultOf(err));
160
+ path.length = holder.level;
161
+ continue;
162
+ }
163
+ stack.pop();
164
+ const holder = stack[stack.length - 1];
165
+ if (holder === undefined)
166
+ return received(copy);
167
+ land(holder, holder.key, copy, holder.member);
98
168
  }
99
169
  }
100
170
  export const MODS_PAYLOAD_MODE = Object.freeze({ accessors: "refuse", depth: Infinity, others: "as-is", freeze: true });
@@ -7,6 +7,19 @@ import { type ModSeat, type ModTier } from "./events.js";
7
7
  /** The host's Proxy probe (this folder cannot recognise a Proxy on its own): with one, a handler's Proxy is refused
8
8
  * before any of its traps runs; without one, it is read like any object. */
9
9
  export type ProxyProbe = (value: object) => boolean;
10
+ /**
11
+ * The one depth the bus holds a handler's values to: how many container levels a value may have below a payload member
12
+ * or an answer's top (1 = the member itself). Every value a handler gives the bus — what it hands to `next`, a `$`
13
+ * call's arguments, its answer — is received in a mode bounded by it (a shared reference measured again where it sits
14
+ * each time it is met), so a value nested deeper is refused by the first walk that meets it before that
15
+ * walk goes any deeper. Every walk keeps its own stack, so neither the platform nor the caller's stack depth decides.
16
+ * The pinned-key comparison is held to the same depth. A container is one level wherever it is met, so the verdict
17
+ * does not depend on member order for a value without a cycle; through a cycle, depth is measured on the walk's way (a
18
+ * container still being walked counts as one level where it is met again). The engine's own event is received at any
19
+ * depth, and its objects — handed back anywhere in what a handler hands on, answers or passes to a `$` call — are taken
20
+ * as themselves, never walked: one of its containers is one level where it sits, whatever it holds.
21
+ */
22
+ export declare const MODS_VALUE_DEPTH = 1000;
10
23
  /** Why a handler did not answer for itself: it threw, it ran past its budget, it broke the site's contract, or it was
11
24
  * not run because the dispatch re-entered a frame it is part of (its `.catch` answers for it — CC 296 form, (cli296.js:242947) "hasCatch"). */
12
25
  export declare const MOD_FAILURE_CAUSES: readonly ["threw", "timeout", "violation", "reentry"];
@@ -35,8 +48,50 @@ export declare const NEXT_IN_FLIGHT: Readonly<{
35
48
  export type ModAnswerCheck = (answer: unknown, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[]) => string | undefined;
36
49
  /** A matcher: top-level fields of `e` that must equal these values exactly. */
37
50
  export type ModMatcher = Readonly<Record<string, string | number | boolean>>;
38
- /** The first pinned key `next` changed, or undefined. Identity comparison: a pinned value is handed on as is. */
39
- export declare function pinnedKeyChanged(pinned: readonly string[], received: ModEventPayload, passed: ModEventPayload): string | undefined;
51
+ /** Why a pinned key of what a handler handed on is not taken: it holds another value, or it is a copy the comparison
52
+ * could not walk to the end (`unproven` says why) — refused all the same, since only a copy proven the same is taken. */
53
+ export interface PinnedKeyBreak {
54
+ readonly key: string;
55
+ readonly unproven?: string;
56
+ }
57
+ /**
58
+ * The first pinned key `next` did not hand on as the engine's fact, or undefined. A pinned value is compared by value
59
+ * ({@link sameModValue}): the engine's own fact handed on as is, or a copy of it, is not a change.
60
+ */
61
+ export declare function pinnedKeyChanged(pinned: readonly string[], received: ModEventPayload, passed: ModEventPayload): PinnedKeyBreak | undefined;
62
+ /** {@link engineObjects} of a dispatch's own event, found the first time it is asked and the same set every time after:
63
+ * the event is frozen, so one finding serves every receipt of the dispatch. */
64
+ export declare function engineObjectsOnce(held: ModEventPayload): () => ReadonlySet<object>;
65
+ /**
66
+ * What the next handler reads when a handler hands `passed` to `next` (not the dispatch's own e): `passed` received
67
+ * whole in the mode held to {@link MODS_VALUE_DEPTH} (every object of the dispatch's own e in it — `engines`, found once
68
+ * per dispatch by {@link engineObjectsOnce} — kept as itself), then {@link pinnedHandOn}. A value nested past the depth
69
+ * is refused by the receipt, before any deeper walk — under a pinned key in the comparison's own words (too deep to
70
+ * compare), under any other member as the payload holding it.
71
+ */
72
+ export declare function handedOn(pinned: readonly string[], held: ModEventPayload, passed: unknown, engines: ReadonlySet<object>, isProxy?: ProxyProbe): {
73
+ readonly payload: ModEventPayload;
74
+ } | {
75
+ readonly violation: string;
76
+ };
77
+ /**
78
+ * What the next handler reads when a handler hands on `passed` (already received whole): the payload with every
79
+ * pinned key the engine's own member — the same object `held` carries, or no member where `held` has none — so a
80
+ * handler below a copy-forwarder reads the engine's fact, not the copy's shape (a member that is `undefined`, a
81
+ * member order, a −0 the comparison does not count). A pinned key the copy did not hand on as the engine's fact
82
+ * ({@link pinnedKeyChanged}) breaks the site instead. The comparison decides only whether to refuse; what travels down
83
+ * for a pinned key is the engine's member, always. The payload keeps the shape it was received in: a reference inside
84
+ * it to the payload itself is a reference to what is handed on (a cycle stays a cycle), and one to any object inside
85
+ * what the handler handed on under a pinned key — the copy itself, a member of it, an element of one of its lists, at
86
+ * any depth — is a reference to the engine's object it was proven the same as (a shared reference stays shared; an
87
+ * object of the copy standing for two of the engine's goes to the one the comparison met first). `engines`: every
88
+ * object of `held` (found here when not given).
89
+ */
90
+ export declare function pinnedHandOn(pinned: readonly string[], held: ModEventPayload, passed: ModEventPayload, engines?: ReadonlySet<object>): {
91
+ readonly payload: ModEventPayload;
92
+ } | {
93
+ readonly violation: string;
94
+ };
40
95
  /** Why a handler's answer breaks the site, or undefined. No answer at all is never an answer. */
41
96
  export declare function answerViolation(answer: unknown, check: ModAnswerCheck | undefined, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[]): string | undefined;
42
97
  /**
@@ -52,14 +107,18 @@ export declare function methodAnswerViolation(answer: unknown, _e?: ModEventPayl
52
107
  export declare function matcherViolation(m: unknown): string | undefined;
53
108
  /** Whether every matcher field equals `e`'s own top-level field exactly. */
54
109
  export declare function matcherMatches(m: ModMatcher | undefined, e: ModEventPayload): boolean;
55
- /**
56
- * What a payload hands on, received by the one receipt in the mods mode: a plain record, copied whole at every depth
57
- * (cycles and shared references kept, a function or a class instance handed as it is), its top level frozen. A member
58
- * the reader already holds (`held`: the dispatch's own members) is kept as itself, so a pinned value handed back
59
- * unchanged is the same value. An accessor anywhere is refused (a getter is never run), and a payload that cannot be
60
- * copied whole is refused — never handed on shorter than it was given.
61
- */
62
- export declare function receivePayload(v: unknown, held?: ModEventPayload, isProxy?: ProxyProbe): {
110
+ /** A record a handler gives the bus other than through `next` — a `$` call's arguments, and a method's `enter` shaping
111
+ * of them — received held to {@link MODS_VALUE_DEPTH}; an object of `held` ({@link engineObjectsOnce} of what the bus
112
+ * already holds: the dispatch the handler runs in, or the call's received arguments) is kept as itself, never walked. */
113
+ export declare function receivePayload(v: unknown, isProxy?: ProxyProbe, held?: ReadonlySet<object>): {
114
+ readonly payload: ModEventPayload;
115
+ } | {
116
+ readonly refusal: string;
117
+ };
118
+ /** The engine's own event at a dispatch's entry, received whole at any depth (one the receipt cannot copy whole —
119
+ * reading it threw where none of its getters runs, or it holds more objects than one receipt can index — is refused,
120
+ * never handed on shorter). */
121
+ export declare function receiveEvent(e: unknown): {
63
122
  readonly payload: ModEventPayload;
64
123
  } | {
65
124
  readonly refusal: string;
@@ -70,15 +129,21 @@ export declare function receivePayload(v: unknown, held?: ModEventPayload, isPro
70
129
  * copied once and frozen; an answer already frozen (an engine sentinel) or not a plain container is itself.
71
130
  */
72
131
  export declare function answerUpward(v: unknown): unknown;
73
- /** A handler's answer, received by the same receipt and mode (an answer need not be a record; a primitive is itself). */
74
- export declare function receiveAnswer(answer: unknown, isProxy?: ProxyProbe): {
132
+ /** A handler's answer, received by the same receipt held to {@link MODS_VALUE_DEPTH} (an answer need not be a record; a
133
+ * primitive is itself); an object of the dispatch's own event in it (`engines`, {@link engineObjectsOnce}) is kept as
134
+ * itself, never walked. */
135
+ export declare function receiveAnswer(answer: unknown, engines: ReadonlySet<object>, isProxy?: ProxyProbe): {
75
136
  readonly answer: unknown;
76
137
  } | {
77
138
  readonly refusal: string;
78
139
  };
79
140
  /**
80
- * A copy for an observe handler: every data container (a plain object, an array) detached at whatever depth, a
81
- * leaf the structured clone refuses (a function, a handle, a class instance holding one) handed as is. An
82
- * uncloneable leaf therefore never leaves the data beside it — at the top or nested — aliased.
141
+ * A copy for an observe handler, made by the one receipt (its own stack, so no depth of the event decides whether an
142
+ * observer runs — the event it observes was received at any depth too): every data container (a plain object, an
143
+ * ordinary array) detached at any depth; then every other object the copy holds — a tool result's `Map`, `Date` or
144
+ * typed array — detached by a structured clone of that object alone (one clone per object, so a shared one stays shared),
145
+ * and one the clone refuses (a function, a handle, a class instance holding one) handed as is. The engine's own event
146
+ * holds data properties only, so the copy is whole; a receipt that could not make it (a Proxy whose trap throws, on a bus
147
+ * given no probe) is the observer's failure, reported like any other.
83
148
  */
84
149
  export declare function detachedCopy(e: ModEventPayload): Record<string, unknown>;