@crouton-kit/crouter 0.3.33 → 0.3.35

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 (617) hide show
  1. package/README.md +2 -2
  2. package/dist/build-root.js +3 -6
  3. package/dist/builtin-memory/crouter-development/marketplaces.md +6 -6
  4. package/dist/builtin-memory/crouter-development/plugins.md +13 -13
  5. package/dist/builtin-memory/internal/examples/imessage-assistant.md +3 -3
  6. package/dist/builtin-memory/internal/nodes-and-canvas.md +4 -4
  7. package/dist/builtin-personas/developer/PERSONA.md +1 -1
  8. package/dist/builtin-personas/orchestration-kernel.md +1 -1
  9. package/dist/builtin-personas/waiting.md +1 -1
  10. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +71 -0
  11. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/crtr-help-gate.test.ts +41 -0
  12. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +663 -0
  13. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +52 -0
  14. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +418 -0
  15. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crouter-help.ts +87 -0
  16. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/filters.json +7 -0
  17. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +174 -0
  18. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-help-gate.ts +408 -0
  19. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +442 -0
  20. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +119 -0
  21. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/nested-context.ts +327 -0
  22. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +574 -0
  23. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +260 -0
  24. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/strip-skills-docs.ts +40 -0
  25. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +19 -0
  26. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/package.json +3 -0
  27. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.js +1 -0
  28. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +479 -0
  29. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/LICENSE +13 -0
  30. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/README.md +172 -0
  31. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/bin.mjs +11 -0
  32. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  33. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  34. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  35. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  36. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  37. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  38. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  39. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  40. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  41. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  42. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
  43. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  44. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  51. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  52. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  53. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/errors.js +57 -0
  54. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/index.js +17 -0
  55. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/log.js +11 -0
  56. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
  57. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  58. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  59. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  60. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  61. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  62. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  63. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  64. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  65. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  66. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  67. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  68. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  69. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  70. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  71. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  72. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  73. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/public-api.js +102 -0
  74. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  75. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  76. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  77. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  78. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  79. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  80. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  81. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  82. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  83. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  84. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  85. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  86. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  87. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  88. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  89. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  90. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  91. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  92. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  93. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  94. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  95. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  96. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  97. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  98. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  99. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  100. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  101. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  102. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  103. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/util.js +11 -0
  104. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/visit.js +233 -0
  105. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/index.js +5 -0
  106. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/package.json +3 -0
  107. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/cli.d.ts +8 -0
  108. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/cli.mjs +201 -0
  109. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  110. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  111. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  112. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  113. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  114. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-node.js +112 -0
  115. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  116. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  117. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  118. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/composer.js +224 -0
  119. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  120. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  121. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  122. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  123. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  124. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  125. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  126. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  127. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  128. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  129. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  130. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  131. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  132. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  133. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  134. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  135. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  136. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  137. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  138. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  139. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  140. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  141. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  142. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/Document.js +337 -0
  143. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  144. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/anchors.js +76 -0
  145. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  146. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  147. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  148. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/createNode.js +90 -0
  149. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  150. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/directives.js +178 -0
  151. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/errors.d.ts +21 -0
  152. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/errors.js +62 -0
  153. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/index.d.ts +25 -0
  154. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/index.js +50 -0
  155. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/log.d.ts +3 -0
  156. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/log.js +19 -0
  157. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  158. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Alias.js +118 -0
  159. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  160. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Collection.js +151 -0
  161. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  162. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Node.js +40 -0
  163. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  164. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Pair.js +39 -0
  165. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  166. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  167. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  168. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  169. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  170. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  171. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  172. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  173. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  174. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/identity.js +53 -0
  175. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  176. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/toJS.js +39 -0
  177. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/options.d.ts +350 -0
  178. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  179. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  180. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  181. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  182. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  183. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  184. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  185. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst.js +112 -0
  186. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  187. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/lexer.js +723 -0
  188. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  189. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/line-counter.js +41 -0
  190. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  191. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/parser.js +980 -0
  192. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/public-api.d.ts +44 -0
  193. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/public-api.js +107 -0
  194. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  195. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/Schema.js +39 -0
  196. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  197. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/map.js +19 -0
  198. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  199. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/null.js +17 -0
  200. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  201. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/seq.js +19 -0
  202. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  203. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/string.js +16 -0
  204. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  205. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/bool.js +21 -0
  206. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  207. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/float.js +47 -0
  208. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  209. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/int.js +42 -0
  210. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  211. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/schema.js +25 -0
  212. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  213. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/json/schema.js +64 -0
  214. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  215. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  216. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/tags.js +99 -0
  217. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/types.d.ts +92 -0
  218. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  219. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  220. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  221. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  222. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  223. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  224. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  225. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  226. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  227. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  228. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  229. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  230. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  231. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  232. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  233. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  234. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  235. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  236. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  237. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  238. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  239. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  240. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  241. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringify.js +132 -0
  242. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  243. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  244. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  245. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  246. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  247. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  248. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  249. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  250. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  251. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  252. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  253. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  254. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/test-events.d.ts +4 -0
  255. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/test-events.js +134 -0
  256. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/util.d.ts +16 -0
  257. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/util.js +28 -0
  258. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/visit.d.ts +102 -0
  259. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/visit.js +236 -0
  260. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/package.json +97 -0
  261. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/util.js +2 -0
  262. package/dist/builtin-pi-packages/pi-crtr-extensions/package-lock.json +3385 -0
  263. package/dist/builtin-pi-packages/pi-crtr-extensions/package.json +25 -0
  264. package/dist/builtin-pi-packages/pi-mode-switch/README.md +64 -0
  265. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +40 -0
  266. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +427 -0
  267. package/dist/builtin-pi-packages/pi-mode-switch/package.json +13 -0
  268. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +55 -0
  269. package/dist/clients/attach/__tests__/crtr-output-render.test.js +2340 -0
  270. package/dist/clients/attach/attach-cmd.js +843 -743
  271. package/dist/clients/attach/auth-pickers.js +2 -2
  272. package/dist/clients/attach/canvas-panels.js +1 -1
  273. package/dist/clients/attach/chat-view.d.ts +3 -2
  274. package/dist/clients/attach/chat-view.js +30 -10
  275. package/dist/clients/attach/clipboard-image.js +1 -1
  276. package/dist/clients/attach/clipboard-text.js +1 -1
  277. package/dist/clients/attach/config-load.js +1 -1
  278. package/dist/clients/attach/crtr-output-render.d.ts +48 -0
  279. package/dist/clients/attach/crtr-output-render.js +646 -0
  280. package/dist/clients/attach/extension-dialogs.js +1 -1
  281. package/dist/clients/attach/graph-overlay.js +3 -3
  282. package/dist/clients/attach/input-controller.js +1 -1
  283. package/dist/clients/attach/pickers.js +1 -1
  284. package/dist/clients/attach/slash-commands.js +5 -6
  285. package/dist/clients/attach/titled-editor.d.ts +4 -0
  286. package/dist/clients/attach/titled-editor.js +13 -1
  287. package/dist/clients/attach/view-socket.js +1 -1
  288. package/dist/clients/web/__tests__/source-cache.test.js +5 -5
  289. package/dist/clients/web/server.js +29 -5
  290. package/dist/clients/web/source-cache.js +3 -3
  291. package/dist/clients/web/web-cmd.js +7 -7
  292. package/dist/commands/canvas-issue.js +1 -1
  293. package/dist/commands/canvas-prune.js +24 -2
  294. package/dist/commands/canvas-snapshot.js +3 -0
  295. package/dist/commands/canvas-tmux-spread.js +3 -3
  296. package/dist/commands/human.js +1 -1
  297. package/dist/commands/memory/lint.js +15 -8
  298. package/dist/commands/memory/origin.d.ts +1 -0
  299. package/dist/commands/memory/origin.js +88 -0
  300. package/dist/commands/memory/shared.d.ts +8 -0
  301. package/dist/commands/memory/shared.js +22 -1
  302. package/dist/commands/memory/write.js +17 -12
  303. package/dist/commands/memory.js +4 -3
  304. package/dist/commands/node-context.js +4 -4
  305. package/dist/commands/node-snapshot.js +4 -1
  306. package/dist/commands/node.d.ts +2 -2
  307. package/dist/commands/node.js +814 -606
  308. package/dist/commands/pkg/market-inspect.d.ts +2 -1
  309. package/dist/commands/pkg/market-inspect.js +14 -32
  310. package/dist/commands/pkg/market-manage.d.ts +3 -1
  311. package/dist/commands/pkg/market-manage.js +58 -154
  312. package/dist/commands/pkg/market.js +7 -7
  313. package/dist/commands/pkg/plugin-inspect.d.ts +2 -1
  314. package/dist/commands/pkg/plugin-inspect.js +8 -24
  315. package/dist/commands/pkg/plugin-manage.d.ts +5 -1
  316. package/dist/commands/pkg/plugin-manage.js +245 -171
  317. package/dist/commands/pkg/plugin.js +6 -6
  318. package/dist/commands/pkg.js +5 -5
  319. package/dist/commands/revive.js +5 -3
  320. package/dist/commands/search/answer.js +1 -1
  321. package/dist/commands/search/contents.js +1 -1
  322. package/dist/commands/search/web.js +2 -2
  323. package/dist/commands/search.js +1 -1
  324. package/dist/commands/surface.d.ts +2 -0
  325. package/dist/commands/surface.js +43 -0
  326. package/dist/commands/sys/promptstudio.js +1 -1
  327. package/dist/commands/sys/settings.js +2 -2
  328. package/dist/commands/sys/setup-core.d.ts +88 -0
  329. package/dist/commands/sys/setup-core.js +352 -0
  330. package/dist/commands/sys/setup.d.ts +2 -0
  331. package/dist/commands/sys/setup.js +516 -0
  332. package/dist/commands/sys/sysprompt.js +3 -0
  333. package/dist/commands/sys.js +3 -2
  334. package/dist/commands/view-cycle.js +5 -5
  335. package/dist/commands/view-list.js +3 -3
  336. package/dist/commands/view-new.js +5 -5
  337. package/dist/commands/view-pick.js +6 -6
  338. package/dist/commands/view-run.js +14 -14
  339. package/dist/commands/view.js +3 -3
  340. package/dist/commands/workspace.js +10 -10
  341. package/dist/core/__tests__/boot.test.js +140 -0
  342. package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -27
  343. package/dist/core/__tests__/daemon-boot.test.js +22 -0
  344. package/dist/core/__tests__/fixtures/fake-engine.js +19 -9
  345. package/dist/core/__tests__/flagship-lifecycle.test.js +4 -1
  346. package/dist/core/__tests__/full/broker-attach-limits.test.js +1 -1
  347. package/dist/core/__tests__/full/broker-attach-stream.test.js +1 -1
  348. package/dist/core/__tests__/full/broker-crash-teardown.test.js +10 -5
  349. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +1 -1
  350. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +2 -2
  351. package/dist/core/__tests__/full/broker-pane-resolution.test.js +1 -1
  352. package/dist/core/__tests__/full/cascade-close.test.js +31 -18
  353. package/dist/core/__tests__/full/detach-focus.test.js +17 -3
  354. package/dist/core/__tests__/hearth-bootstrap.test.js +136 -0
  355. package/dist/core/__tests__/helpers/harness.js +1 -1
  356. package/dist/core/__tests__/live-mutation-verbs.test.js +17 -11
  357. package/dist/core/__tests__/live-mutation.test.js +15 -10
  358. package/dist/core/__tests__/migration.test.js +124 -0
  359. package/dist/core/__tests__/on-read-dedup-resume.test.js +40 -0
  360. package/dist/core/__tests__/preview-registry-sync.test.js +36 -0
  361. package/dist/core/__tests__/prune-to-limit.test.js +91 -0
  362. package/dist/core/__tests__/revive.test.js +64 -21
  363. package/dist/core/__tests__/trigger-migration.test.js +48 -0
  364. package/dist/core/__tests__/wake-bearings.test.js +23 -21
  365. package/dist/core/__tests__/wake-origin.test.js +36 -33
  366. package/dist/core/canvas/boot.d.ts +48 -0
  367. package/dist/core/canvas/boot.js +157 -0
  368. package/dist/core/canvas/canvas.d.ts +27 -1
  369. package/dist/core/canvas/canvas.js +86 -5
  370. package/dist/core/canvas/db.js +86 -1
  371. package/dist/core/canvas/index.d.ts +1 -1
  372. package/dist/core/canvas/index.js +1 -1
  373. package/dist/core/canvas/nav-model.js +1 -1
  374. package/dist/core/canvas/pid.d.ts +6 -0
  375. package/dist/core/canvas/pid.js +13 -0
  376. package/dist/core/canvas/triggers.d.ts +108 -0
  377. package/dist/core/canvas/triggers.js +320 -0
  378. package/dist/core/canvas/types.d.ts +128 -46
  379. package/dist/core/command.js +13 -4
  380. package/dist/core/hearth/__tests__/model-auth-guest.test.js +151 -0
  381. package/dist/core/hearth/config.d.ts +1 -0
  382. package/dist/core/hearth/config.js +36 -3
  383. package/dist/core/hearth/guest-env.d.ts +7 -0
  384. package/dist/core/hearth/guest-env.js +17 -1
  385. package/dist/core/hearth/index.d.ts +0 -1
  386. package/dist/core/hearth/index.js +0 -1
  387. package/dist/core/hearth/model-auth-guest.d.ts +8 -0
  388. package/dist/core/hearth/model-auth-guest.js +430 -0
  389. package/dist/core/hearth/provider.d.ts +13 -6
  390. package/dist/core/hearth/providers/blaxel-bootstrap.d.ts +2 -0
  391. package/dist/core/hearth/providers/blaxel-bootstrap.js +127 -19
  392. package/dist/core/hearth/providers/blaxel-home.d.ts +8 -4
  393. package/dist/core/hearth/providers/blaxel-home.js +85 -75
  394. package/dist/core/hearth/providers/blaxel.d.ts +5 -0
  395. package/dist/core/hearth/providers/blaxel.js +86 -12
  396. package/dist/core/hearth/providers/types.d.ts +6 -1
  397. package/dist/core/hearth/types.d.ts +35 -1
  398. package/dist/core/help.d.ts +16 -0
  399. package/dist/core/help.js +2 -0
  400. package/dist/core/memory-resolver.d.ts +8 -8
  401. package/dist/core/memory-resolver.js +58 -26
  402. package/dist/core/preview-registry.d.ts +25 -0
  403. package/dist/core/preview-registry.js +2047 -0
  404. package/dist/core/resolver.d.ts +1 -0
  405. package/dist/core/resolver.js +23 -16
  406. package/dist/core/runtime/bearings.d.ts +11 -10
  407. package/dist/core/runtime/bearings.js +8 -8
  408. package/dist/core/runtime/broker-protocol.d.ts +2 -2
  409. package/dist/core/runtime/broker-protocol.js +2 -2
  410. package/dist/core/runtime/close.js +2 -2
  411. package/dist/core/runtime/kickoff.js +1 -1
  412. package/dist/core/runtime/launch.d.ts +9 -3
  413. package/dist/core/runtime/launch.js +17 -9
  414. package/dist/core/runtime/lifecycle.js +7 -7
  415. package/dist/core/runtime/model-swap.js +1 -1
  416. package/dist/core/runtime/placement.d.ts +5 -5
  417. package/dist/core/runtime/placement.js +10 -10
  418. package/dist/core/runtime/recycle.js +7 -7
  419. package/dist/core/runtime/reset.d.ts +1 -1
  420. package/dist/core/runtime/reset.js +3 -3
  421. package/dist/core/runtime/revive-all.d.ts +5 -2
  422. package/dist/core/runtime/revive-all.js +5 -2
  423. package/dist/core/runtime/revive.d.ts +15 -8
  424. package/dist/core/runtime/revive.js +52 -16
  425. package/dist/core/runtime/spawn.d.ts +1 -1
  426. package/dist/core/runtime/spawn.js +7 -7
  427. package/dist/core/runtime/stop-guard.js +5 -5
  428. package/dist/core/runtime/surface-bg.js +1 -1
  429. package/dist/core/runtime/tmux.d.ts +1 -1
  430. package/dist/core/runtime/tmux.js +4 -4
  431. package/dist/core/scope.d.ts +9 -0
  432. package/dist/core/scope.js +37 -15
  433. package/dist/core/substrate/on-read.js +23 -21
  434. package/dist/core/substrate/render.js +3 -3
  435. package/dist/core/view/loader.js +2 -2
  436. package/dist/core/wake.d.ts +2 -2
  437. package/dist/core/wake.js +7 -7
  438. package/dist/daemon/__tests__/predicate-eval.test.js +109 -0
  439. package/dist/daemon/crtrd.js +222 -103
  440. package/dist/daemon/predicate-eval.d.ts +52 -0
  441. package/dist/daemon/predicate-eval.js +248 -0
  442. package/dist/hearth/control-plane/__tests__/node-message.test.js +60 -0
  443. package/dist/hearth/control-plane/__tests__/rate-limit-recurrence.test.js +49 -0
  444. package/dist/hearth/control-plane/__tests__/relay-security.test.js +314 -0
  445. package/dist/hearth/control-plane/__tests__/scheduler-scan-loop.test.js +133 -0
  446. package/dist/hearth/control-plane/__tests__/trigger-delivery.test.js +170 -0
  447. package/dist/hearth/control-plane/__tests__/webhook-ingress.test.js +167 -0
  448. package/dist/hearth/control-plane/config.d.ts +21 -0
  449. package/dist/hearth/control-plane/config.js +77 -0
  450. package/dist/hearth/control-plane/db.d.ts +30 -0
  451. package/dist/hearth/control-plane/db.js +534 -0
  452. package/dist/hearth/control-plane/ingress/rate-limit.d.ts +24 -0
  453. package/dist/hearth/control-plane/ingress/rate-limit.js +100 -0
  454. package/dist/hearth/control-plane/ingress/route-store.d.ts +31 -0
  455. package/dist/hearth/control-plane/ingress/route-store.js +61 -0
  456. package/dist/hearth/control-plane/ingress/webhook-delivery-store.d.ts +41 -0
  457. package/dist/hearth/control-plane/ingress/webhook-delivery-store.js +69 -0
  458. package/dist/hearth/control-plane/ingress/webhook-route.d.ts +55 -0
  459. package/dist/hearth/control-plane/ingress/webhook-route.js +285 -0
  460. package/dist/hearth/control-plane/main.js +88 -0
  461. package/dist/hearth/control-plane/node-message.d.ts +31 -0
  462. package/dist/hearth/control-plane/node-message.js +98 -0
  463. package/dist/hearth/control-plane/register.d.ts +15 -0
  464. package/dist/hearth/control-plane/register.js +34 -0
  465. package/dist/hearth/control-plane/registry.d.ts +17 -0
  466. package/dist/hearth/control-plane/registry.js +161 -0
  467. package/dist/hearth/control-plane/relay.d.ts +40 -0
  468. package/dist/hearth/{wake-proxy/proxy.js → control-plane/relay.js} +201 -275
  469. package/dist/hearth/control-plane/scheduler/fire-store.d.ts +36 -0
  470. package/dist/hearth/control-plane/scheduler/fire-store.js +73 -0
  471. package/dist/hearth/control-plane/scheduler/recurrence.d.ts +7 -0
  472. package/dist/hearth/control-plane/scheduler/recurrence.js +58 -0
  473. package/dist/hearth/control-plane/scheduler/scan-loop.d.ts +38 -0
  474. package/dist/hearth/control-plane/scheduler/scan-loop.js +138 -0
  475. package/dist/hearth/control-plane/scheduler/schedule-store.d.ts +32 -0
  476. package/dist/hearth/control-plane/scheduler/schedule-store.js +66 -0
  477. package/dist/hearth/control-plane/secrets.d.ts +17 -0
  478. package/dist/hearth/control-plane/secrets.js +113 -0
  479. package/dist/hearth/control-plane/server.d.ts +27 -0
  480. package/dist/hearth/control-plane/server.js +346 -0
  481. package/dist/hearth/control-plane/session.d.ts +68 -0
  482. package/dist/hearth/control-plane/session.js +273 -0
  483. package/dist/hearth/control-plane/triggers/acl.d.ts +14 -0
  484. package/dist/hearth/control-plane/triggers/acl.js +52 -0
  485. package/dist/hearth/control-plane/triggers/audit-store.d.ts +38 -0
  486. package/dist/hearth/control-plane/triggers/audit-store.js +79 -0
  487. package/dist/hearth/control-plane/triggers/deliver.d.ts +43 -0
  488. package/dist/hearth/control-plane/triggers/deliver.js +76 -0
  489. package/dist/hearth/control-plane/triggers/envelope.d.ts +29 -0
  490. package/dist/hearth/control-plane/triggers/envelope.js +38 -0
  491. package/dist/hearth/control-plane/types.d.ts +66 -0
  492. package/dist/hearth/control-plane/wake.d.ts +80 -0
  493. package/dist/hearth/control-plane/wake.js +312 -0
  494. package/dist/pi-extensions/canvas-doc-substrate.js +28 -2
  495. package/dist/pi-extensions/canvas-nav.js +1 -1
  496. package/dist/prompts/view.js +7 -8
  497. package/dist/types.js +4 -4
  498. package/dist/web-client/assets/index-DUThOUzU.css +2 -0
  499. package/dist/web-client/assets/index-IAJVtuVe.js +80 -0
  500. package/dist/web-client/index.html +2 -2
  501. package/package.json +12 -9
  502. package/scripts/postinstall.mjs +8 -0
  503. package/dist/clients/attach/__tests__/action-parity.test.js +0 -48
  504. package/dist/clients/attach/__tests__/autocomplete-and-bash-mode.test.js +0 -96
  505. package/dist/clients/attach/__tests__/bash-bang-routing.test.js +0 -58
  506. package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.js +0 -56
  507. package/dist/clients/attach/__tests__/clipboard-image.test.js +0 -76
  508. package/dist/clients/attach/__tests__/editor-newline.test.js +0 -82
  509. package/dist/clients/attach/__tests__/git-info.test.js +0 -31
  510. package/dist/clients/attach/__tests__/onrequest-wired.test.js +0 -20
  511. package/dist/clients/attach/__tests__/reconnect-giveup.test.js +0 -30
  512. package/dist/clients/attach/__tests__/slash-quit-copy.test.js +0 -42
  513. package/dist/clients/attach/__tests__/titled-editor.test.js +0 -60
  514. package/dist/commands/memory/__tests__/lint-schema.test.js +0 -52
  515. package/dist/core/__tests__/argv-parser.test.js +0 -217
  516. package/dist/core/__tests__/artifact-paths.test.js +0 -44
  517. package/dist/core/__tests__/draw-style.test.js +0 -258
  518. package/dist/core/__tests__/editor-label.test.d.ts +0 -1
  519. package/dist/core/__tests__/editor-label.test.js +0 -26
  520. package/dist/core/__tests__/fault-marker.test.d.ts +0 -1
  521. package/dist/core/__tests__/fault-marker.test.js +0 -112
  522. package/dist/core/__tests__/fault-retry-rewind.test.d.ts +0 -1
  523. package/dist/core/__tests__/fault-retry-rewind.test.js +0 -123
  524. package/dist/core/__tests__/frame-decoder-perf.test.d.ts +0 -1
  525. package/dist/core/__tests__/frame-decoder-perf.test.js +0 -224
  526. package/dist/core/__tests__/keystone.test.d.ts +0 -1
  527. package/dist/core/__tests__/keystone.test.js +0 -185
  528. package/dist/core/__tests__/listing-completeness.test.d.ts +0 -1
  529. package/dist/core/__tests__/listing-completeness.test.js +0 -31
  530. package/dist/core/__tests__/memory-resolver.test.d.ts +0 -1
  531. package/dist/core/__tests__/memory-resolver.test.js +0 -119
  532. package/dist/core/__tests__/memory.test.d.ts +0 -1
  533. package/dist/core/__tests__/memory.test.js +0 -60
  534. package/dist/core/__tests__/model-ladders.test.d.ts +0 -1
  535. package/dist/core/__tests__/model-ladders.test.js +0 -160
  536. package/dist/core/__tests__/node-env.test.d.ts +0 -1
  537. package/dist/core/__tests__/node-env.test.js +0 -26
  538. package/dist/core/__tests__/pane-column.test.d.ts +0 -1
  539. package/dist/core/__tests__/pane-column.test.js +0 -153
  540. package/dist/core/__tests__/persona-compose.test.d.ts +0 -1
  541. package/dist/core/__tests__/persona-compose.test.js +0 -53
  542. package/dist/core/__tests__/persona-subkind.test.d.ts +0 -1
  543. package/dist/core/__tests__/persona-subkind.test.js +0 -65
  544. package/dist/core/__tests__/persona.test.d.ts +0 -1
  545. package/dist/core/__tests__/persona.test.js +0 -107
  546. package/dist/core/__tests__/unknown-path.test.d.ts +0 -1
  547. package/dist/core/__tests__/unknown-path.test.js +0 -58
  548. package/dist/core/canvas/wakeups.d.ts +0 -76
  549. package/dist/core/canvas/wakeups.js +0 -185
  550. package/dist/core/hearth/registry.d.ts +0 -15
  551. package/dist/core/hearth/registry.js +0 -179
  552. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.d.ts +0 -1
  553. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.js +0 -289
  554. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.d.ts +0 -1
  555. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.js +0 -34
  556. package/dist/hearth/wake-proxy/__tests__/guest-source.test.d.ts +0 -1
  557. package/dist/hearth/wake-proxy/__tests__/guest-source.test.js +0 -203
  558. package/dist/hearth/wake-proxy/__tests__/hardening.test.d.ts +0 -1
  559. package/dist/hearth/wake-proxy/__tests__/hardening.test.js +0 -59
  560. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.d.ts +0 -1
  561. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.js +0 -372
  562. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.d.ts +0 -1
  563. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.js +0 -258
  564. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.d.ts +0 -1
  565. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.js +0 -437
  566. package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.d.ts +0 -1
  567. package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.js +0 -455
  568. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.d.ts +0 -1
  569. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.js +0 -15
  570. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.d.ts +0 -1
  571. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.js +0 -141
  572. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.d.ts +0 -1
  573. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.js +0 -143
  574. package/dist/hearth/wake-proxy/anthropic-oauth.d.ts +0 -58
  575. package/dist/hearth/wake-proxy/anthropic-oauth.js +0 -189
  576. package/dist/hearth/wake-proxy/auth.d.ts +0 -22
  577. package/dist/hearth/wake-proxy/auth.js +0 -128
  578. package/dist/hearth/wake-proxy/config.d.ts +0 -2
  579. package/dist/hearth/wake-proxy/config.js +0 -151
  580. package/dist/hearth/wake-proxy/guest-source.d.ts +0 -14
  581. package/dist/hearth/wake-proxy/guest-source.js +0 -130
  582. package/dist/hearth/wake-proxy/hearth-status.d.ts +0 -44
  583. package/dist/hearth/wake-proxy/hearth-status.js +0 -267
  584. package/dist/hearth/wake-proxy/home.d.ts +0 -67
  585. package/dist/hearth/wake-proxy/home.js +0 -297
  586. package/dist/hearth/wake-proxy/main.js +0 -134
  587. package/dist/hearth/wake-proxy/model-auth.d.ts +0 -13
  588. package/dist/hearth/wake-proxy/model-auth.js +0 -345
  589. package/dist/hearth/wake-proxy/proxy.d.ts +0 -35
  590. package/dist/hearth/wake-proxy/public-source-gate.d.ts +0 -9
  591. package/dist/hearth/wake-proxy/public-source-gate.js +0 -409
  592. package/dist/hearth/wake-proxy/redact.d.ts +0 -1
  593. package/dist/hearth/wake-proxy/redact.js +0 -17
  594. package/dist/hearth/wake-proxy/server.d.ts +0 -11
  595. package/dist/hearth/wake-proxy/server.js +0 -142
  596. package/dist/hearth/wake-proxy/state.d.ts +0 -18
  597. package/dist/hearth/wake-proxy/state.js +0 -342
  598. package/dist/hearth/wake-proxy/types.d.ts +0 -76
  599. package/dist/web-client/assets/index-BZUxTkv5.css +0 -2
  600. package/dist/web-client/assets/index-D36PNBj4.js +0 -80
  601. /package/dist/clients/attach/__tests__/{action-parity.test.d.ts → crtr-output-coverage.test.d.ts} +0 -0
  602. /package/dist/clients/attach/__tests__/{autocomplete-and-bash-mode.test.d.ts → crtr-output-render.test.d.ts} +0 -0
  603. /package/dist/{clients/attach/__tests__/bash-bang-routing.test.d.ts → core/__tests__/boot.test.d.ts} +0 -0
  604. /package/dist/{clients/attach/__tests__/bundle-pi-tui-dedup.test.d.ts → core/__tests__/hearth-bootstrap.test.d.ts} +0 -0
  605. /package/dist/{clients/attach/__tests__/clipboard-image.test.d.ts → core/__tests__/preview-registry-sync.test.d.ts} +0 -0
  606. /package/dist/{clients/attach/__tests__/editor-newline.test.d.ts → core/__tests__/prune-to-limit.test.d.ts} +0 -0
  607. /package/dist/{clients/attach/__tests__/git-info.test.d.ts → core/__tests__/trigger-migration.test.d.ts} +0 -0
  608. /package/dist/{clients/attach/__tests__/onrequest-wired.test.d.ts → core/hearth/__tests__/model-auth-guest.test.d.ts} +0 -0
  609. /package/dist/{clients/attach/__tests__/reconnect-giveup.test.d.ts → daemon/__tests__/predicate-eval.test.d.ts} +0 -0
  610. /package/dist/{clients/attach/__tests__/slash-quit-copy.test.d.ts → hearth/control-plane/__tests__/node-message.test.d.ts} +0 -0
  611. /package/dist/{clients/attach/__tests__/titled-editor.test.d.ts → hearth/control-plane/__tests__/rate-limit-recurrence.test.d.ts} +0 -0
  612. /package/dist/{commands/memory/__tests__/lint-schema.test.d.ts → hearth/control-plane/__tests__/relay-security.test.d.ts} +0 -0
  613. /package/dist/{core/__tests__/argv-parser.test.d.ts → hearth/control-plane/__tests__/scheduler-scan-loop.test.d.ts} +0 -0
  614. /package/dist/{core/__tests__/artifact-paths.test.d.ts → hearth/control-plane/__tests__/trigger-delivery.test.d.ts} +0 -0
  615. /package/dist/{core/__tests__/draw-style.test.d.ts → hearth/control-plane/__tests__/webhook-ingress.test.d.ts} +0 -0
  616. /package/dist/hearth/{wake-proxy → control-plane}/main.d.ts +0 -0
  617. /package/dist/hearth/{wake-proxy → control-plane}/types.js +0 -0
@@ -0,0 +1,248 @@
1
+ // src/daemon/predicate-eval.ts — the daemon-owned `--when` predicate
2
+ // evaluator: subprocess spawn/capture/timeout/capacity/lease mechanics ONLY.
3
+ // No enactment logic lives here (no appendInbox/reviveNode/spawnChild) — every
4
+ // settled outcome is handed to the caller's `onDone`/`onTimeout` callback, and
5
+ // crtrd.ts is the SINGLE place that turns a settled trigger into an inbox
6
+ // message / revive / spawn (reusing the exact same enactment code the clock-
7
+ // trigger pass uses). This keeps enactment in ONE place regardless of whether
8
+ // the trigger fired off a clock or a predicate.
9
+ //
10
+ // Fire-and-forget contract: evaluateDuePredicates NEVER awaits a subprocess —
11
+ // it kicks off child processes and returns immediately; each settles later via
12
+ // its own `close`/timeout handler calling `onDone`. The daemon tick must never
13
+ // block on a slow/hung predicate (spec §Predicate triggers: "cannot block the
14
+ // daemon tick").
15
+ import { spawn } from 'node:child_process';
16
+ import { randomUUID } from 'node:crypto';
17
+ import { duePredicateTriggers, duePredicateTimeouts, runningPredicateTriggers, acquirePredicateLease, recordPredicateEvalResult, resetPredicateLease, consumeTrigger, getNode, } from '../core/canvas/index.js';
18
+ import { isPidAlive, killProcessGroup } from '../core/canvas/pid.js';
19
+ import { nextSlotAfter } from '../core/wake.js';
20
+ export const STDOUT_CAP_BYTES = 16 * 1024;
21
+ export const STDERR_TAIL_BYTES = 4 * 1024;
22
+ /** Read fresh each pass (not cached at module load) so a test/operator can
23
+ * tune it via env without a daemon restart mid-run. */
24
+ export function predicateCapacity() {
25
+ const num = (name, fallback) => {
26
+ const raw = process.env[name];
27
+ const n = raw !== undefined ? Number(raw) : NaN;
28
+ return Number.isFinite(n) && n > 0 ? n : fallback;
29
+ };
30
+ return {
31
+ maxCanvas: num('CRTR_PREDICATE_MAX_CANVAS', 8),
32
+ maxPerOwner: num('CRTR_PREDICATE_MAX_OWNER', 2),
33
+ evalTimeoutMs: num('CRTR_PREDICATE_EVAL_TIMEOUT_MS', 10_000),
34
+ };
35
+ }
36
+ /** One id per daemon PROCESS instance — distinguishes THIS process's own
37
+ * in-flight leases from a stale 'running' row a prior (crashed/restarted)
38
+ * daemon left behind (spec §Lease / in-flight contract, daemon-restart
39
+ * recovery). Generated once per process; tests that want deterministic
40
+ * recovery behavior can ignore it (recovery only special-cases OWN leases). */
41
+ export const daemonInstanceId = randomUUID();
42
+ function nextEvalAfter(t, nowMs) {
43
+ return t.eval_every != null ? nextSlotAfter(t.eval_every, new Date(nowMs)) : new Date(nowMs).toISOString();
44
+ }
45
+ /** Recover stale in-flight rows left by a PRIOR daemon instance (crash/
46
+ * restart): a still-alive process group past its own eval timeout is killed +
47
+ * recorded as a timeout; a dead pid resets straight to idle with no
48
+ * diagnostics (spec: "if not alive, the row is reset to idle and eligible for
49
+ * the next evaluation slot"). Rows this SAME instance owns are left alone —
50
+ * they are genuinely in flight, not stale. */
51
+ export function recoverStalePredicateLeases(now, config) {
52
+ for (const t of runningPredicateTriggers()) {
53
+ if (t.eval_lease_owner === daemonInstanceId)
54
+ continue;
55
+ const pid = t.eval_pid;
56
+ if (pid == null || !isPidAlive(pid)) {
57
+ resetPredicateLease(t.trigger_id);
58
+ continue;
59
+ }
60
+ const startedAtMs = t.eval_started_at != null ? new Date(t.eval_started_at).getTime() : now;
61
+ if (now - startedAtMs < config.evalTimeoutMs)
62
+ continue; // still within its own window — leave it
63
+ killProcessGroup(pid);
64
+ recordPredicateEvalResult(t.trigger_id, {
65
+ completedAtIso: new Date(now).toISOString(),
66
+ nextEvalAtIso: nextEvalAfter(t, now),
67
+ exitCode: null,
68
+ stderrTail: `evaluation timed out after ${config.evalTimeoutMs}ms (recovered stale lease from a prior daemon instance)`,
69
+ });
70
+ }
71
+ }
72
+ /** Wall-clock `timeout_at` reap — independent of eval_state/next_eval_at.
73
+ * Kills any in-flight process group for a timed-out row, consumes it, and
74
+ * invokes `onTimeout` once per row so the caller can send the owner urgent
75
+ * notice (spec: "consume and notify owner"). Call BEFORE
76
+ * evaluateDuePredicates each tick so a timed-out row can never also be
77
+ * freshly evaluated in the same tick (consumeTrigger removes it from the due
78
+ * query). */
79
+ export function reapTimedOutPredicates(now, onTimeout) {
80
+ for (const t of duePredicateTimeouts(new Date(now).toISOString())) {
81
+ if (t.eval_state === 'running' && t.eval_pid != null)
82
+ killProcessGroup(t.eval_pid);
83
+ consumeTrigger(t.trigger_id);
84
+ onTimeout(t);
85
+ }
86
+ }
87
+ function runOneEvaluation(t, config, onDone) {
88
+ let cwd;
89
+ if (t.action === 'msg') {
90
+ const target = t.node_id != null ? getNode(t.node_id) : null;
91
+ if (target === null) {
92
+ // Shouldn't reach here — the caller checks target existence before
93
+ // calling this — but never spawn against an unresolved cwd.
94
+ return;
95
+ }
96
+ cwd = target.cwd;
97
+ }
98
+ else {
99
+ cwd = t.payload.cwd;
100
+ }
101
+ const env = {
102
+ ...process.env,
103
+ CRTR_TRIGGER_ID: t.trigger_id,
104
+ CRTR_TRIGGER_OWNER_ID: t.owner_id,
105
+ };
106
+ if (t.node_id != null)
107
+ env['CRTR_TRIGGER_TARGET_ID'] = t.node_id;
108
+ const startedAtIso = new Date().toISOString();
109
+ let child;
110
+ try {
111
+ child = spawn('bash', ['-c', t.when_script ?? 'exit 1'], {
112
+ cwd,
113
+ env,
114
+ detached: true, // own process group — killProcessGroup(-pid) reaps the whole tree
115
+ stdio: ['ignore', 'pipe', 'pipe'],
116
+ });
117
+ }
118
+ catch (err) {
119
+ recordPredicateEvalResult(t.trigger_id, {
120
+ completedAtIso: new Date().toISOString(),
121
+ nextEvalAtIso: nextEvalAfter(t, Date.now()),
122
+ exitCode: null,
123
+ stderrTail: `evaluation failed to spawn: ${err.message}`.slice(-STDERR_TAIL_BYTES),
124
+ });
125
+ return;
126
+ }
127
+ if (child.pid == null || !acquirePredicateLease(t.trigger_id, daemonInstanceId, child.pid, startedAtIso)) {
128
+ // Lost a race (canceled / grabbed between selection and spawn, or the
129
+ // process never got a pid) — abandon; never leave an unaccounted child.
130
+ if (child.pid != null)
131
+ killProcessGroup(child.pid);
132
+ return;
133
+ }
134
+ let stdout = '';
135
+ let stdoutBytes = 0;
136
+ let overflowed = false;
137
+ let stderrTail = '';
138
+ let settled = false;
139
+ const timer = setTimeout(() => {
140
+ if (settled)
141
+ return;
142
+ settled = true;
143
+ if (child.pid != null)
144
+ killProcessGroup(child.pid);
145
+ recordPredicateEvalResult(t.trigger_id, {
146
+ completedAtIso: new Date().toISOString(),
147
+ nextEvalAtIso: nextEvalAfter(t, Date.now()),
148
+ exitCode: null,
149
+ stderrTail: `evaluation timed out after ${config.evalTimeoutMs}ms`,
150
+ });
151
+ }, config.evalTimeoutMs);
152
+ timer.unref?.();
153
+ child.stdout?.on('data', (chunk) => {
154
+ stdoutBytes += chunk.length;
155
+ if (stdout.length < STDOUT_CAP_BYTES)
156
+ stdout += chunk.toString('utf8');
157
+ if (stdoutBytes > STDOUT_CAP_BYTES)
158
+ overflowed = true;
159
+ });
160
+ child.stderr?.on('data', (chunk) => {
161
+ stderrTail = (stderrTail + chunk.toString('utf8')).slice(-STDERR_TAIL_BYTES);
162
+ });
163
+ const finish = (code) => {
164
+ if (settled)
165
+ return;
166
+ settled = true;
167
+ clearTimeout(timer);
168
+ if (code === 0) {
169
+ // stdout only matters (and only needs a size cap) when it is ABOUT to
170
+ // become the message body: msg/inbox_message with no inline body
171
+ // supplied at arm time. A non-zero exit always reschedules below
172
+ // regardless of overflow — a verbose "not yet" predicate must stay armed
173
+ // (spec criterion 7) — and an exit-0 node_birth or a msg with a supplied
174
+ // body never reads stdout at all, so an overflow there is harmless noise,
175
+ // not a delivery failure.
176
+ const stdoutIsBody = t.action === 'msg' &&
177
+ t.action_mode === 'inbox_message' &&
178
+ t.payload.body === undefined;
179
+ if (overflowed && stdoutIsBody) {
180
+ // Guard against the narrow cross-path race: a wall-clock reaper
181
+ // (reapTimedOutPredicates) may have already killed + consumed this
182
+ // exact trigger between the kill signal and this close event firing
183
+ // (the `settled` guard above is local to this evaluation and doesn't
184
+ // see a racing reaper). consumeTrigger reports whether IT actually
185
+ // removed a live row; if the row is already gone, no-op instead of
186
+ // delivering a second, now-orphaned outcome.
187
+ if (!consumeTrigger(t.trigger_id))
188
+ return;
189
+ onDone({ kind: 'stdout_overflow', trigger: t });
190
+ return;
191
+ }
192
+ if (!consumeTrigger(t.trigger_id))
193
+ return; // settle-before-enact; no-op if a racing reaper already consumed it
194
+ onDone({ kind: 'fired', trigger: t, stdout: stdout.slice(0, STDOUT_CAP_BYTES).trim() });
195
+ return;
196
+ }
197
+ recordPredicateEvalResult(t.trigger_id, {
198
+ completedAtIso: new Date().toISOString(),
199
+ nextEvalAtIso: nextEvalAfter(t, Date.now()),
200
+ exitCode: code,
201
+ stderrTail: stderrTail === '' ? null : stderrTail,
202
+ });
203
+ };
204
+ child.on('close', (code) => finish(code));
205
+ child.on('error', (err) => {
206
+ if (settled)
207
+ return;
208
+ settled = true;
209
+ clearTimeout(timer);
210
+ recordPredicateEvalResult(t.trigger_id, {
211
+ completedAtIso: new Date().toISOString(),
212
+ nextEvalAtIso: nextEvalAfter(t, Date.now()),
213
+ exitCode: null,
214
+ stderrTail: `evaluation process error: ${err.message}`.slice(-STDERR_TAIL_BYTES),
215
+ });
216
+ });
217
+ }
218
+ /** Pass 3c: select due idle predicates (deterministic order from the DAO),
219
+ * enforce capacity in-memory (seeded from the current running-row snapshot),
220
+ * and kick off evaluations — NEVER awaited. `onDone` fires per trigger,
221
+ * whenever it settles (possibly after this call returns). Rows over capacity,
222
+ * or whose owner is at its per-owner cap, are left untouched (idle,
223
+ * next_eval_at unchanged) and are retried next tick. A `msg` trigger whose
224
+ * target no longer exists is reaped here (consumed + `target_gone`) instead
225
+ * of being spawned against a dangling id. */
226
+ export function evaluateDuePredicates(now, onDone) {
227
+ const config = predicateCapacity();
228
+ const running = runningPredicateTriggers();
229
+ let globalCount = running.length;
230
+ const perOwner = new Map();
231
+ for (const r of running)
232
+ perOwner.set(r.owner_id, (perOwner.get(r.owner_id) ?? 0) + 1);
233
+ for (const t of duePredicateTriggers(new Date(now).toISOString())) {
234
+ if (t.action === 'msg' && t.node_id != null && getNode(t.node_id) === null) {
235
+ consumeTrigger(t.trigger_id);
236
+ onDone({ kind: 'target_gone', trigger: t });
237
+ continue;
238
+ }
239
+ if (globalCount >= config.maxCanvas)
240
+ break; // no capacity left for anyone
241
+ const ownerCount = perOwner.get(t.owner_id) ?? 0;
242
+ if (ownerCount >= config.maxPerOwner)
243
+ continue; // this owner is at cap; try the next row
244
+ globalCount++;
245
+ perOwner.set(t.owner_id, ownerCount + 1);
246
+ runOneEvaluation(t, config, onDone);
247
+ }
248
+ }
@@ -0,0 +1,60 @@
1
+ import assert from 'node:assert/strict';
2
+ import { test } from 'node:test';
3
+ // Bug-regression test (CLAUDE.md "Testing policy" #2) — locks in the P5-review
4
+ // (mr1ganv3-e3401250) CRITICAL fix: `wakeAndExecNodeMessage` invoked a
5
+ // nonexistent `crtr node spine msg <target> --tier <tier>` command (no `node
6
+ // spine` branch exists, and the `msg` leaf takes its target via `--to`, not
7
+ // positionally). Every exec exited non-zero, so `deliverTrigger` recorded
8
+ // `failed` for every cron fire and webhook — the entire SEAM-5 delivery path
9
+ // was dead. This test fails if the argv regresses to `node spine msg` or a
10
+ // positional target.
11
+ test('wakeAndExecNodeMessage runs `crtr node msg --to <target> --tier <tier>` with the body on stdin', async () => {
12
+ const { wakeAndExecNodeMessage, nodeMessageInternals } = await import('../node-message.js');
13
+ const orig = { ...nodeMessageInternals };
14
+ const execCalls = [];
15
+ nodeMessageInternals.getHomeById = ((home_id) => ({
16
+ home_id,
17
+ tenant_id: 't1',
18
+ user_id: 'u1',
19
+ provider: 'blaxel',
20
+ provider_sandbox_id: 'sbx-1',
21
+ provider_volume_id: null,
22
+ preview_endpoint: null,
23
+ home_agent_target: 'home-agent-1',
24
+ relay_auth_ref: null,
25
+ status: 'running',
26
+ template_version: null,
27
+ last_ready_at: null,
28
+ last_wake_at: null,
29
+ last_suspend_at: null,
30
+ last_wake_latency_ms: null,
31
+ health_verdict: 'healthy',
32
+ created_at: '2026-06-30T00:00:00.000Z',
33
+ updated_at: '2026-06-30T00:00:00.000Z',
34
+ }));
35
+ nodeMessageInternals.ensureAwake = async () => ({ preview_endpoint: 'https://x.example', relayToken: 'tok' });
36
+ nodeMessageInternals.loadM0Config = (() => ({}));
37
+ nodeMessageInternals.getHomeBackend = (() => ({
38
+ wake: async () => ({ provider_sandbox_id: 'sbx-1', provider_volume_id: null, preview_endpoint: null }),
39
+ suspend: async () => ({ provider_sandbox_id: 'sbx-1', provider_volume_id: null, preview_endpoint: null }),
40
+ getMachine: async () => null,
41
+ exec: async (machineId, input) => {
42
+ execCalls.push({ machineId, argv: input.argv, stdin: input.stdin });
43
+ return { exitCode: 0, timedOut: false, stdout: '', stderr: '' };
44
+ },
45
+ }));
46
+ try {
47
+ await wakeAndExecNodeMessage('h1', '{"source":"cron","trigger_id":"f1"}', 'urgent');
48
+ assert.equal(execCalls.length, 1);
49
+ const call = execCalls[0];
50
+ assert.equal(call.machineId, 'sbx-1');
51
+ // The real CLI form: `crtr node msg --to <target> --tier <tier>` — never
52
+ // `node spine msg` and never a positional target.
53
+ assert.deepEqual(call.argv, ['crtr', 'node', 'msg', '--to', 'home-agent-1', '--tier', 'urgent']);
54
+ assert.equal(call.argv.includes('spine'), false);
55
+ assert.equal(call.stdin, '{"source":"cron","trigger_id":"f1"}');
56
+ }
57
+ finally {
58
+ Object.assign(nodeMessageInternals, orig);
59
+ }
60
+ });
@@ -0,0 +1,49 @@
1
+ import assert from 'node:assert/strict';
2
+ import { test } from 'node:test';
3
+ import { createRateLimiter } from '../ingress/rate-limit.js';
4
+ import { computeNextFire } from '../scheduler/recurrence.js';
5
+ // Category-2 (rate limiter) + category-3 (recurrence) test. The rate-limiter
6
+ // case locks the fix for an observed bug found during P5.5 implementation: an
7
+ // over-eager idle-prune deleted a per-key bucket right after its first draw,
8
+ // so per-key limiting never actually bit. The recurrence case locks the custom
9
+ // interval-parsing + timezone plumbing (my code, not cron-parser's) that cron
10
+ // firing depends on.
11
+ test('the per-key token bucket actually limits a burst and refills over time', () => {
12
+ let nowMs = 1_000_000;
13
+ const limiter = createRateLimiter({ capacity: 3, refillPerSec: 1, globalCapacity: 1_000, globalRefillPerSec: 1_000, now: () => nowMs });
14
+ // Three tokens available for one key, then it trips (the prune bug would let
15
+ // every request through by resetting the bucket to full each call).
16
+ assert.equal(limiter.checkRate('k').ok, true);
17
+ assert.equal(limiter.checkRate('k').ok, true);
18
+ assert.equal(limiter.checkRate('k').ok, true);
19
+ const tripped = limiter.checkRate('k');
20
+ assert.equal(tripped.ok, false);
21
+ assert.equal(typeof tripped.retryAfterMs, 'number');
22
+ // A different key has its own independent bucket.
23
+ assert.equal(limiter.checkRate('other').ok, true);
24
+ // After ~2s one key refills 2 tokens.
25
+ nowMs += 2_000;
26
+ assert.equal(limiter.checkRate('k').ok, true);
27
+ assert.equal(limiter.checkRate('k').ok, true);
28
+ assert.equal(limiter.checkRate('k').ok, false);
29
+ });
30
+ test('the global ceiling sheds a flood spread across many distinct keys', () => {
31
+ let nowMs = 0;
32
+ const limiter = createRateLimiter({ capacity: 100, refillPerSec: 100, globalCapacity: 5, globalRefillPerSec: 0.0001, now: () => nowMs });
33
+ let ok = 0;
34
+ for (let i = 0; i < 20; i++) {
35
+ if (limiter.checkRate(`key-${i}`).ok)
36
+ ok += 1;
37
+ }
38
+ assert.equal(ok, 5); // global ceiling caps total admits regardless of key spread
39
+ });
40
+ test('computeNextFire handles cron expressions, timezones, and @every intervals', () => {
41
+ assert.equal(computeNextFire('*/5 * * * *', 'UTC', '2026-06-30T12:01:00.000Z'), '2026-06-30T12:05:00.000Z');
42
+ // Interval form is timezone-independent, strictly after `after`.
43
+ assert.equal(computeNextFire('@every 30m', 'America/New_York', '2026-06-30T12:00:00.000Z'), '2026-06-30T12:30:00.000Z');
44
+ assert.equal(computeNextFire('@every 90s', 'UTC', '2026-06-30T12:00:00.000Z'), '2026-06-30T12:01:30.000Z');
45
+ // A tz-bearing daily schedule resolves to the correct UTC instant: 09:00
46
+ // EDT the same day is 13:00 UTC (after 08:00 EDT / 12:00 UTC).
47
+ assert.equal(computeNextFire('0 9 * * *', 'America/New_York', '2026-06-30T12:00:00.000Z'), '2026-06-30T13:00:00.000Z');
48
+ assert.throws(() => computeNextFire('not a cron', 'UTC', '2026-06-30T12:00:00.000Z'));
49
+ });
@@ -0,0 +1,314 @@
1
+ import assert from 'node:assert/strict';
2
+ import { EventEmitter } from 'node:events';
3
+ import http from 'node:http';
4
+ import { test } from 'node:test';
5
+ import { WebSocket, WebSocketServer } from 'ws';
6
+ import { buildUpstreamHttpUrl, proxyHttp, proxyUpgrade } from '../relay.js';
7
+ // Category-3 test (CLAUDE.md "Testing policy" #3 — load-bearing Hearth/CP
8
+ // security regression). Approved by Silas 2026-06-30 as a narrow carve-out
9
+ // after the P4.3 relay review (mr16xp6d-2a5061f5 / mr16z2lz-3cd35b0c) found
10
+ // these exact invariants had zero durable coverage — only a throwaway smoke
11
+ // that was deleted after the implementation pass. The invariants below are
12
+ // the ones part-plan T3.2's acceptance checks and design.md's R-CP-2/R-CP-3/
13
+ // R-CP-6 non-negotiables name explicitly:
14
+ // - R-CP-3: the browser leg never supplies, and never sees reflected, the
15
+ // CP->home relay token; the home leg sees ONLY `Authorization: Bearer
16
+ // <relayToken>`.
17
+ // - criterion 4 (origin-form-only request target): scheme-relative,
18
+ // absolute, raw/encoded-backslash, and encoded-CRLF request targets are
19
+ // rejected before any upstream contact (open-proxy/SSRF prevention).
20
+ // - R-CP-2/R-CP-6: `home` is resolved once, server-side, from the
21
+ // caller's session; no client-supplied `?target=`/`/node/<id>` can move
22
+ // the request onto a different home's preview origin or node target.
23
+ // A regression in any of these is silent (still typechecks, still serves
24
+ // chat) and is exactly the kind of defect this carve-out exists for.
25
+ const testConfig = {
26
+ host: '127.0.0.1',
27
+ port: 0,
28
+ publicOrigin: 'http://127.0.0.1:0',
29
+ cookieSecure: false,
30
+ wakeTimeoutMs: 2_000,
31
+ readyTimeoutMs: 2_000,
32
+ };
33
+ function makeHome(overrides = {}) {
34
+ const now = '2026-06-30T00:00:00.000Z';
35
+ return {
36
+ home_id: 'home-a',
37
+ tenant_id: 'tenant-1',
38
+ user_id: 'user-1',
39
+ provider: 'blaxel',
40
+ provider_sandbox_id: 'sandbox-a',
41
+ provider_volume_id: 'volume-a',
42
+ preview_endpoint: 'https://home-a.example.invalid',
43
+ home_agent_target: 'node-a',
44
+ relay_auth_ref: 'ref-a',
45
+ status: 'running',
46
+ template_version: null,
47
+ last_ready_at: null,
48
+ last_wake_at: null,
49
+ last_suspend_at: null,
50
+ last_wake_latency_ms: null,
51
+ health_verdict: 'healthy',
52
+ created_at: now,
53
+ updated_at: now,
54
+ ...overrides,
55
+ };
56
+ }
57
+ // --- Minimal req/res fakes (same shape as wake-proxy/__tests__'s FakeReq/
58
+ // FakeRes — only the surface proxyHttp actually touches). ------------------
59
+ class FakeReq extends EventEmitter {
60
+ url;
61
+ method;
62
+ headers;
63
+ constructor(path, headers = {}, method = 'GET') {
64
+ super();
65
+ this.url = path;
66
+ this.method = method;
67
+ this.headers = headers;
68
+ }
69
+ }
70
+ class FakeRes extends EventEmitter {
71
+ statusCode = 200;
72
+ statusMessage = '';
73
+ headersSent = false;
74
+ writableEnded = false;
75
+ headers = new Map();
76
+ chunks = [];
77
+ socket = { setNoDelay() { } };
78
+ setHeader(name, value) {
79
+ this.headers.set(name.toLowerCase(), value);
80
+ }
81
+ getHeader(name) {
82
+ return this.headers.get(name.toLowerCase());
83
+ }
84
+ hasHeader(name) {
85
+ return this.headers.has(name.toLowerCase());
86
+ }
87
+ writeHead(code, headers) {
88
+ this.statusCode = code;
89
+ this.headersSent = true;
90
+ if (headers)
91
+ for (const [k, v] of Object.entries(headers))
92
+ this.setHeader(k, v);
93
+ }
94
+ flushHeaders() {
95
+ this.headersSent = true;
96
+ }
97
+ write(chunk) {
98
+ this.headersSent = true;
99
+ this.chunks.push(Buffer.from(chunk));
100
+ return true;
101
+ }
102
+ end(chunk) {
103
+ this.headersSent = true;
104
+ if (chunk !== undefined)
105
+ this.chunks.push(Buffer.from(chunk));
106
+ this.writableEnded = true;
107
+ this.emit('finish');
108
+ }
109
+ destroy() {
110
+ this.writableEnded = true;
111
+ }
112
+ body() {
113
+ return Buffer.concat(this.chunks).toString('utf8');
114
+ }
115
+ }
116
+ function asReq(req) {
117
+ return req;
118
+ }
119
+ function asRes(res) {
120
+ return res;
121
+ }
122
+ async function listen(server) {
123
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
124
+ const address = server.address();
125
+ if (address === null || typeof address === 'string')
126
+ throw new Error('expected a network address');
127
+ return {
128
+ origin: `http://127.0.0.1:${address.port}`,
129
+ close: () => new Promise((resolve) => server.close(() => resolve())),
130
+ };
131
+ }
132
+ // --- 1. HTTP browser->home header/token isolation -------------------------
133
+ test('proxyHttp: browser auth/cookie/forwarding headers never reach upstream; only the relay Bearer token does; the token is never reflected to the browser', async () => {
134
+ let captured = null;
135
+ const upstream = http.createServer((req, res) => {
136
+ captured = req.headers;
137
+ // Deliberately reflect the relay token back in the response, the way a
138
+ // misbehaving or compromised home might — this is what makes the
139
+ // browser-side assertion below non-vacuous.
140
+ res.writeHead(200, { 'content-type': 'text/plain', authorization: 'Bearer RELAY_TOKEN_A' });
141
+ res.end('upstream-ok');
142
+ });
143
+ const { origin, close } = await listen(upstream);
144
+ try {
145
+ const req = new FakeReq('/views/chat', {
146
+ authorization: 'Bearer BROWSER_OWN_TOKEN',
147
+ cookie: 'session=browser-cookie',
148
+ forwarded: 'for=1.2.3.4;proto=https',
149
+ 'x-forwarded-for': '1.2.3.4',
150
+ 'x-forwarded-proto': 'https',
151
+ 'x-forwarded-host': 'evil.example',
152
+ 'x-real-ip': '1.2.3.4',
153
+ 'proxy-authorization': 'Basic evil',
154
+ 'sec-websocket-key': 'not-a-real-ws-request',
155
+ 'x-keep-me': 'safe-custom-header',
156
+ });
157
+ const res = new FakeRes();
158
+ await proxyHttp(asReq(req), asRes(res), makeHome(), {
159
+ ensureAwake: async () => ({ preview_endpoint: origin, relayToken: 'RELAY_TOKEN_A' }),
160
+ resolveRunning: () => null,
161
+ invalidateWarmVerdict: () => undefined,
162
+ loadConfig: () => testConfig,
163
+ });
164
+ assert.equal(res.statusCode, 200);
165
+ assert.equal(res.body(), 'upstream-ok');
166
+ assert.ok(captured, 'upstream must have received the forwarded request');
167
+ const upstreamHeaders = captured;
168
+ assert.equal(upstreamHeaders.authorization, 'Bearer RELAY_TOKEN_A', 'upstream must see only the relay token');
169
+ assert.equal(upstreamHeaders.cookie, undefined, 'browser cookie must not reach upstream');
170
+ assert.equal(upstreamHeaders.forwarded, undefined, 'client-supplied Forwarded must not reach upstream');
171
+ assert.equal(upstreamHeaders['x-forwarded-for'], undefined);
172
+ assert.equal(upstreamHeaders['x-forwarded-proto'], undefined);
173
+ assert.equal(upstreamHeaders['x-forwarded-host'], undefined);
174
+ assert.equal(upstreamHeaders['x-real-ip'], undefined);
175
+ assert.equal(upstreamHeaders['proxy-authorization'], undefined);
176
+ assert.equal(upstreamHeaders['sec-websocket-key'], undefined);
177
+ assert.equal(upstreamHeaders['x-keep-me'], 'safe-custom-header', 'a safe custom header must still pass through');
178
+ assert.equal(res.getHeader('authorization'), undefined, 'an upstream-reflected relay token must never reach the browser response');
179
+ }
180
+ finally {
181
+ await close();
182
+ }
183
+ });
184
+ // --- 2. Origin-form / SSRF rejection --------------------------------------
185
+ test('buildUpstreamHttpUrl: rejects dangerous request targets before any upstream contact', () => {
186
+ const previewEndpoint = 'https://home-a.example.invalid';
187
+ const dangerous = [
188
+ '//evil.example.com/path',
189
+ 'http://evil.example.com/path',
190
+ '\\evil.example.com/path',
191
+ '%5Cevil.example.com/path',
192
+ '%0d%0aHost:%20evil.example.com',
193
+ ];
194
+ for (const target of dangerous) {
195
+ assert.throws(() => buildUpstreamHttpUrl(previewEndpoint, target), `expected rejection for: ${target}`);
196
+ }
197
+ });
198
+ test('buildUpstreamHttpUrl: accepts an ordinary origin-form target and stays on the home origin', () => {
199
+ const url = buildUpstreamHttpUrl('https://home-a.example.invalid', '/views/chat?x=1');
200
+ assert.equal(url.origin, 'https://home-a.example.invalid');
201
+ assert.equal(url.pathname, '/views/chat');
202
+ });
203
+ // --- 3. Cross-home/target isolation ---------------------------------------
204
+ test('proxyHttp: a session-resolved home A is never widened by a client ?target= to home B', async () => {
205
+ let hitsA = 0;
206
+ let hitsB = 0;
207
+ const upstreamA = http.createServer((_req, res) => {
208
+ hitsA += 1;
209
+ res.writeHead(200);
210
+ res.end('home-a-ok');
211
+ });
212
+ const upstreamB = http.createServer((_req, res) => {
213
+ hitsB += 1;
214
+ res.writeHead(200);
215
+ res.end('home-b-ok');
216
+ });
217
+ const a = await listen(upstreamA);
218
+ const b = await listen(upstreamB);
219
+ try {
220
+ const req = new FakeReq('/views/chat?target=home-b');
221
+ const res = new FakeRes();
222
+ let ensureAwakeAskedFor = null;
223
+ let resolveRunningAskedFor = null;
224
+ await proxyHttp(asReq(req), asRes(res), makeHome({ home_id: 'home-a' }), {
225
+ ensureAwake: async (home_id) => {
226
+ ensureAwakeAskedFor = home_id;
227
+ // The relay's only home-selection input is the `home` row it was
228
+ // called with — never the request's own query string.
229
+ if (home_id !== 'home-a')
230
+ return { preview_endpoint: b.origin, relayToken: 'RELAY_TOKEN_B' };
231
+ return { preview_endpoint: a.origin, relayToken: 'RELAY_TOKEN_A' };
232
+ },
233
+ resolveRunning: (home_id) => {
234
+ resolveRunningAskedFor = home_id;
235
+ return null;
236
+ },
237
+ invalidateWarmVerdict: () => undefined,
238
+ loadConfig: () => testConfig,
239
+ });
240
+ assert.equal(resolveRunningAskedFor, 'home-a', 'resolveRunning must be asked for the session-resolved home, never a client-supplied target');
241
+ assert.equal(ensureAwakeAskedFor, 'home-a', 'ensureAwake must be asked for the session-resolved home, never a client-supplied target');
242
+ assert.equal(res.body(), 'home-a-ok');
243
+ assert.equal(hitsA, 1);
244
+ assert.equal(hitsB, 0, 'home B must never be contacted for a home-A-resolved request');
245
+ }
246
+ finally {
247
+ await Promise.all([a.close(), b.close()]);
248
+ }
249
+ });
250
+ test('proxyUpgrade: WS upstream target is always home.home_agent_target, never the client-claimed /node/<id> path or ?target=', async () => {
251
+ let upstreamAHits = [];
252
+ let upstreamBHits = 0;
253
+ const wssA = new WebSocketServer({ port: 0 });
254
+ wssA.on('connection', (ws, req) => {
255
+ upstreamAHits.push({ url: req.url, authorization: req.headers.authorization, cookie: req.headers.cookie });
256
+ ws.on('message', (data) => ws.send(data));
257
+ });
258
+ const wssB = new WebSocketServer({ port: 0 });
259
+ wssB.on('connection', () => {
260
+ upstreamBHits += 1;
261
+ });
262
+ const aPort = wssA.address().port;
263
+ const bPort = wssB.address().port;
264
+ const home = makeHome({ home_id: 'home-a', home_agent_target: 'node-a' });
265
+ let ensureAwakeAskedFor = null;
266
+ const relayServer = http.createServer((_req, res) => {
267
+ res.writeHead(404);
268
+ res.end();
269
+ });
270
+ relayServer.on('upgrade', (req, socket, head) => {
271
+ proxyUpgrade(req, socket, head, home, {
272
+ ensureAwake: async (home_id) => {
273
+ ensureAwakeAskedFor = home_id;
274
+ // Same DI seam as the HTTP cross-home test: a regression that derived
275
+ // the wake target from the client's `?target=` would make this
276
+ // resolve to home B's listener, and the assertions below would catch
277
+ // the resulting connection landing on wssB instead of wssA.
278
+ if (home_id !== 'home-a')
279
+ return { preview_endpoint: `http://127.0.0.1:${bPort}`, relayToken: 'RELAY_TOKEN_B' };
280
+ return { preview_endpoint: `http://127.0.0.1:${aPort}`, relayToken: 'RELAY_TOKEN_A' };
281
+ },
282
+ loadConfig: () => testConfig,
283
+ });
284
+ });
285
+ const relay = await listen(relayServer);
286
+ let client = null;
287
+ try {
288
+ client = new WebSocket(`${relay.origin.replace('http://', 'ws://')}/node/some-other-client-claimed-id?target=home-b`, {
289
+ headers: { authorization: 'Bearer BROWSER_OWN_TOKEN', cookie: 'session=browser-cookie' },
290
+ });
291
+ const echoed = await new Promise((resolve, reject) => {
292
+ client.once('open', () => client.send('ping'));
293
+ client.once('message', (data) => resolve(data.toString()));
294
+ client.once('error', reject);
295
+ });
296
+ assert.equal(echoed, 'ping');
297
+ assert.equal(ensureAwakeAskedFor, 'home-a', 'ensureAwake must be asked for the session-resolved home, never the client-claimed path/target');
298
+ assert.equal(upstreamAHits.length, 1);
299
+ assert.equal(upstreamAHits[0]?.url, '/node/node-a', 'upstream path must be the server-resolved home_agent_target, not the client path/target');
300
+ assert.equal(upstreamAHits[0]?.authorization, 'Bearer RELAY_TOKEN_A');
301
+ assert.equal(upstreamAHits[0]?.cookie, undefined, 'the browser cookie must never reach the upstream websocket');
302
+ assert.equal(upstreamBHits, 0, 'home B must never receive a connection for a home-A-resolved request');
303
+ }
304
+ finally {
305
+ if (client) {
306
+ if (client.readyState === WebSocket.OPEN || client.readyState === WebSocket.CONNECTING) {
307
+ client.terminate();
308
+ }
309
+ }
310
+ await new Promise((resolve) => wssA.close(() => resolve()));
311
+ await new Promise((resolve) => wssB.close(() => resolve()));
312
+ await relay.close();
313
+ }
314
+ });