@crouton-kit/crouter 0.3.32 → 0.3.34

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 (852) hide show
  1. package/README.md +10 -2
  2. package/dist/build-root.js +4 -6
  3. package/dist/builtin-memory/crouter-development/marketplaces.md +8 -8
  4. package/dist/builtin-memory/crouter-development/personas/base-prompt.md +2 -2
  5. package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +5 -5
  6. package/dist/builtin-memory/crouter-development/personas.md +3 -4
  7. package/dist/builtin-memory/crouter-development/plugins.md +31 -31
  8. package/dist/builtin-memory/design.md +4 -1
  9. package/dist/builtin-memory/development.md +4 -1
  10. package/dist/builtin-memory/internal/INDEX.md +1 -1
  11. package/dist/builtin-memory/internal/examples/imessage-assistant.md +3 -3
  12. package/dist/builtin-memory/internal/nodes-and-canvas.md +9 -9
  13. package/dist/builtin-memory/internal/storage-tiers.md +5 -5
  14. package/dist/builtin-memory/planning.md +4 -1
  15. package/dist/builtin-memory/product.md +80 -0
  16. package/dist/builtin-memory/spec.md +4 -1
  17. package/dist/builtin-personas/advisor/PERSONA.md +10 -0
  18. package/dist/builtin-personas/design/PERSONA.md +2 -2
  19. package/dist/builtin-personas/design/orchestrator.md +3 -3
  20. package/dist/builtin-personas/developer/PERSONA.md +1 -1
  21. package/dist/builtin-personas/developer/orchestrator.md +2 -2
  22. package/dist/builtin-personas/explore/PERSONA.md +3 -3
  23. package/dist/builtin-personas/explore/orchestrator.md +4 -2
  24. package/dist/builtin-personas/general/PERSONA.md +1 -1
  25. package/dist/builtin-personas/general/orchestrator.md +1 -1
  26. package/dist/builtin-personas/orchestration-kernel.md +8 -15
  27. package/dist/builtin-personas/plan/PERSONA.md +1 -1
  28. package/dist/builtin-personas/plan/orchestrator.md +2 -2
  29. package/dist/builtin-personas/plan/reviewers/architecture-fit/PERSONA.md +1 -1
  30. package/dist/builtin-personas/plan/reviewers/code-smells/PERSONA.md +1 -1
  31. package/dist/builtin-personas/plan/reviewers/pattern-consistency/PERSONA.md +1 -1
  32. package/dist/builtin-personas/plan/reviewers/requirements-coverage/PERSONA.md +1 -1
  33. package/dist/builtin-personas/plan/reviewers/security/PERSONA.md +1 -1
  34. package/dist/builtin-personas/product/PERSONA.md +18 -0
  35. package/dist/builtin-personas/product/orchestrator.md +14 -0
  36. package/dist/builtin-personas/product/teardown/PERSONA.md +13 -0
  37. package/dist/builtin-personas/review/PERSONA.md +1 -1
  38. package/dist/builtin-personas/review/orchestrator.md +1 -1
  39. package/dist/builtin-personas/runtime-base.md +5 -0
  40. package/dist/builtin-personas/spec/PERSONA.md +1 -1
  41. package/dist/builtin-personas/spec/orchestrator.md +2 -2
  42. package/dist/builtin-personas/spec/requirements/PERSONA.md +1 -1
  43. package/dist/builtin-personas/waiting.md +1 -1
  44. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +71 -0
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/crtr-help-gate.test.ts +41 -0
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +663 -0
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +52 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +418 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crouter-help.ts +87 -0
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/filters.json +7 -0
  51. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +174 -0
  52. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-help-gate.ts +408 -0
  53. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +442 -0
  54. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +119 -0
  55. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/nested-context.ts +327 -0
  56. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +574 -0
  57. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +260 -0
  58. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/strip-skills-docs.ts +40 -0
  59. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +19 -0
  60. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/package.json +3 -0
  61. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.js +1 -0
  62. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +479 -0
  63. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/LICENSE +13 -0
  64. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/README.md +172 -0
  65. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/bin.mjs +11 -0
  66. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  67. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  68. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  69. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  70. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  71. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  72. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  73. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  74. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  75. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  76. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
  77. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  78. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  79. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  80. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  81. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  82. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  83. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  84. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  85. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  86. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  87. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/errors.js +57 -0
  88. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/index.js +17 -0
  89. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/log.js +11 -0
  90. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
  91. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  92. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  93. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  94. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  95. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  96. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  97. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  98. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  99. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  100. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  101. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  102. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  103. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  104. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  105. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  106. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  107. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/public-api.js +102 -0
  108. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  109. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  110. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  111. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  112. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  113. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  114. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  115. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  116. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  117. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  118. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  119. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  120. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  121. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  122. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  123. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  124. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  125. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  126. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  127. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  128. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  129. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  130. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  131. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  132. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  133. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  134. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  135. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  136. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  137. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/util.js +11 -0
  138. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/dist/visit.js +233 -0
  139. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/index.js +5 -0
  140. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/browser/package.json +3 -0
  141. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/cli.d.ts +8 -0
  142. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/cli.mjs +201 -0
  143. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  144. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  145. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  146. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  147. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  148. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-node.js +112 -0
  149. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  150. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  151. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  152. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/composer.js +224 -0
  153. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  154. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  155. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  156. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  157. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  158. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  159. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  160. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  161. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  162. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  163. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  164. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  165. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  166. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  167. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  168. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  169. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  170. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  171. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  172. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  173. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  174. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  175. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  176. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/Document.js +337 -0
  177. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  178. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/anchors.js +76 -0
  179. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  180. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  181. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  182. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/createNode.js +90 -0
  183. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  184. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/doc/directives.js +178 -0
  185. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/errors.d.ts +21 -0
  186. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/errors.js +62 -0
  187. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/index.d.ts +25 -0
  188. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/index.js +50 -0
  189. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/log.d.ts +3 -0
  190. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/log.js +19 -0
  191. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  192. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Alias.js +118 -0
  193. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  194. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Collection.js +151 -0
  195. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  196. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Node.js +40 -0
  197. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  198. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Pair.js +39 -0
  199. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  200. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  201. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  202. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  203. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  204. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  205. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  206. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  207. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  208. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/identity.js +53 -0
  209. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  210. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/nodes/toJS.js +39 -0
  211. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/options.d.ts +350 -0
  212. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  213. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  214. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  215. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  216. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  217. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  218. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  219. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/cst.js +112 -0
  220. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  221. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/lexer.js +723 -0
  222. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  223. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/line-counter.js +41 -0
  224. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  225. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/parse/parser.js +980 -0
  226. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/public-api.d.ts +44 -0
  227. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/public-api.js +107 -0
  228. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  229. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/Schema.js +39 -0
  230. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  231. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/map.js +19 -0
  232. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  233. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/null.js +17 -0
  234. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  235. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/seq.js +19 -0
  236. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  237. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/common/string.js +16 -0
  238. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  239. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/bool.js +21 -0
  240. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  241. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/float.js +47 -0
  242. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  243. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/int.js +42 -0
  244. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  245. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/core/schema.js +25 -0
  246. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  247. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/json/schema.js +64 -0
  248. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  249. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  250. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/tags.js +99 -0
  251. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/types.d.ts +92 -0
  252. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  253. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  254. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  255. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  256. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  257. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  258. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  259. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  260. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  261. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  262. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  263. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  264. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  265. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  266. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  267. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  268. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  269. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  270. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  271. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  272. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  273. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  274. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  275. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringify.js +132 -0
  276. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  277. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  278. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  279. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  280. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  281. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  282. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  283. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  284. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  285. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  286. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  287. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  288. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/test-events.d.ts +4 -0
  289. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/test-events.js +134 -0
  290. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/util.d.ts +16 -0
  291. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/util.js +28 -0
  292. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/visit.d.ts +102 -0
  293. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/dist/visit.js +236 -0
  294. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/package.json +97 -0
  295. package/dist/builtin-pi-packages/pi-crtr-extensions/node_modules/yaml/util.js +2 -0
  296. package/dist/builtin-pi-packages/pi-crtr-extensions/package-lock.json +3385 -0
  297. package/dist/builtin-pi-packages/pi-crtr-extensions/package.json +25 -0
  298. package/dist/builtin-pi-packages/pi-mode-switch/README.md +64 -0
  299. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +40 -0
  300. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +422 -0
  301. package/dist/builtin-pi-packages/pi-mode-switch/package.json +13 -0
  302. package/dist/builtin-views/canvas/core.mjs +82 -1
  303. package/dist/builtin-views/canvas/tui.mjs +9 -5
  304. package/dist/builtin-views/canvas/web.jsx +3 -2
  305. package/dist/builtin-views/chat/core.mjs +725 -0
  306. package/dist/builtin-views/chat/text.mjs +101 -0
  307. package/dist/builtin-views/chat/tui.mjs +368 -0
  308. package/dist/builtin-views/chat/web.jsx +367 -0
  309. package/dist/builtin-views/prompt-review/core.mjs +863 -0
  310. package/dist/builtin-views/prompt-review/text.mjs +15 -0
  311. package/dist/builtin-views/prompt-review/tui.mjs +196 -0
  312. package/dist/builtin-views/prompt-review/web.jsx +484 -0
  313. package/dist/builtin-views/settings/core.mjs +397 -0
  314. package/dist/builtin-views/settings/text.mjs +40 -0
  315. package/dist/builtin-views/settings/tui.mjs +95 -0
  316. package/dist/builtin-views/settings/web.jsx +167 -0
  317. package/dist/cli.js +16 -3
  318. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +55 -0
  319. package/dist/clients/attach/__tests__/crtr-output-render.test.js +2340 -0
  320. package/dist/clients/attach/attach-cmd.d.ts +18 -0
  321. package/dist/clients/attach/attach-cmd.js +1797 -797
  322. package/dist/clients/attach/auth-pickers.js +2 -2
  323. package/dist/clients/attach/canvas-panels.js +3 -3
  324. package/dist/clients/attach/chat-view.d.ts +13 -2
  325. package/dist/clients/attach/chat-view.js +53 -10
  326. package/dist/clients/attach/clipboard-image.js +1 -1
  327. package/dist/clients/attach/clipboard-text.js +1 -1
  328. package/dist/clients/attach/config-load.d.ts +8 -4
  329. package/dist/clients/attach/config-load.js +3 -1
  330. package/dist/clients/attach/crtr-output-render.d.ts +48 -0
  331. package/dist/clients/attach/crtr-output-render.js +646 -0
  332. package/dist/clients/attach/extension-dialogs.d.ts +2 -3
  333. package/dist/clients/attach/extension-dialogs.js +8 -10
  334. package/dist/clients/attach/graph-overlay.js +6 -5
  335. package/dist/clients/attach/input-controller.d.ts +4 -3
  336. package/dist/clients/attach/input-controller.js +25 -4
  337. package/dist/clients/attach/pickers.js +1 -1
  338. package/dist/clients/attach/slash-commands.d.ts +7 -7
  339. package/dist/clients/attach/slash-commands.js +40 -17
  340. package/dist/clients/attach/titled-editor.d.ts +4 -0
  341. package/dist/clients/attach/titled-editor.js +31 -15
  342. package/dist/clients/attach/view-socket.d.ts +2 -1
  343. package/dist/clients/attach/view-socket.js +28 -9
  344. package/dist/clients/web/__tests__/source-cache.test.js +32 -0
  345. package/dist/clients/web/dev-server.js +1 -0
  346. package/dist/clients/web/events.js +9 -11
  347. package/dist/clients/web/server.d.ts +4 -3
  348. package/dist/clients/web/server.js +166 -35
  349. package/dist/clients/web/source-cache.d.ts +10 -0
  350. package/dist/clients/web/source-cache.js +57 -0
  351. package/dist/clients/web/web-cmd.js +32 -13
  352. package/dist/commands/__tests__/human.test.js +30 -28
  353. package/dist/commands/canvas-history/search.js +1 -1
  354. package/dist/commands/canvas-history.js +5 -8
  355. package/dist/commands/canvas-issue.d.ts +2 -0
  356. package/dist/commands/canvas-issue.js +148 -0
  357. package/dist/commands/canvas-prune.js +43 -2
  358. package/dist/commands/canvas-rebuild-index.d.ts +2 -0
  359. package/dist/commands/canvas-rebuild-index.js +57 -0
  360. package/dist/commands/canvas-snapshot.d.ts +2 -0
  361. package/dist/commands/canvas-snapshot.js +51 -0
  362. package/dist/commands/canvas-tmux-spread.d.ts +2 -0
  363. package/dist/commands/canvas-tmux-spread.js +188 -0
  364. package/dist/commands/canvas.d.ts +1 -0
  365. package/dist/commands/canvas.js +16 -1
  366. package/dist/commands/chord.js +143 -48
  367. package/dist/commands/daemon.js +3 -3
  368. package/dist/commands/human/prompts.d.ts +0 -1
  369. package/dist/commands/human/prompts.js +39 -54
  370. package/dist/commands/human/queue.d.ts +12 -1
  371. package/dist/commands/human/queue.js +468 -73
  372. package/dist/commands/human/shared.d.ts +3 -4
  373. package/dist/commands/human/shared.js +3 -3
  374. package/dist/commands/human.js +12 -11
  375. package/dist/commands/memory/find.js +3 -2
  376. package/dist/commands/memory/lint.js +15 -8
  377. package/dist/commands/memory/list.js +4 -3
  378. package/dist/commands/memory/origin.d.ts +1 -0
  379. package/dist/commands/memory/origin.js +88 -0
  380. package/dist/commands/memory/read.js +3 -3
  381. package/dist/commands/memory/shared.d.ts +9 -4
  382. package/dist/commands/memory/shared.js +28 -10
  383. package/dist/commands/memory/write.js +19 -14
  384. package/dist/commands/memory.js +6 -8
  385. package/dist/commands/node-context.d.ts +2 -0
  386. package/dist/commands/node-context.js +172 -0
  387. package/dist/commands/node-snapshot.d.ts +2 -0
  388. package/dist/commands/node-snapshot.js +126 -0
  389. package/dist/commands/node.d.ts +2 -2
  390. package/dist/commands/node.js +987 -603
  391. package/dist/commands/pkg/market-inspect.d.ts +2 -1
  392. package/dist/commands/pkg/market-inspect.js +14 -32
  393. package/dist/commands/pkg/market-manage.d.ts +3 -1
  394. package/dist/commands/pkg/market-manage.js +58 -154
  395. package/dist/commands/pkg/market.js +7 -7
  396. package/dist/commands/pkg/plugin-inspect.d.ts +2 -1
  397. package/dist/commands/pkg/plugin-inspect.js +13 -29
  398. package/dist/commands/pkg/plugin-manage.d.ts +5 -1
  399. package/dist/commands/pkg/plugin-manage.js +246 -172
  400. package/dist/commands/pkg/plugin.js +6 -6
  401. package/dist/commands/pkg.js +7 -7
  402. package/dist/commands/push.d.ts +2 -0
  403. package/dist/commands/push.js +79 -11
  404. package/dist/commands/revive.js +79 -4
  405. package/dist/commands/search/answer.d.ts +1 -0
  406. package/dist/commands/search/answer.js +50 -0
  407. package/dist/commands/search/contents.d.ts +1 -0
  408. package/dist/commands/search/contents.js +96 -0
  409. package/dist/commands/search/exa.d.ts +53 -0
  410. package/dist/commands/search/exa.js +155 -0
  411. package/dist/commands/search/puremd.d.ts +11 -0
  412. package/dist/commands/search/puremd.js +53 -0
  413. package/dist/commands/search/web.d.ts +1 -0
  414. package/dist/commands/search/web.js +65 -0
  415. package/dist/commands/search.d.ts +2 -0
  416. package/dist/commands/search.js +24 -0
  417. package/dist/commands/surface.d.ts +2 -0
  418. package/dist/commands/surface.js +43 -0
  419. package/dist/commands/sys/__tests__/sync-import.test.js +72 -0
  420. package/dist/commands/sys/config.js +59 -10
  421. package/dist/commands/sys/doctor.js +56 -4
  422. package/dist/commands/sys/prompt-review.d.ts +1 -0
  423. package/dist/commands/sys/prompt-review.js +178 -0
  424. package/dist/commands/sys/promptstudio.d.ts +2 -0
  425. package/dist/commands/sys/promptstudio.js +65 -0
  426. package/dist/commands/sys/settings.d.ts +2 -0
  427. package/dist/commands/sys/settings.js +16 -0
  428. package/dist/commands/sys/setup-core.d.ts +88 -0
  429. package/dist/commands/sys/setup-core.js +352 -0
  430. package/dist/commands/sys/setup.d.ts +2 -0
  431. package/dist/commands/sys/setup.js +516 -0
  432. package/dist/commands/sys/sync.js +311 -159
  433. package/dist/commands/sys/sysprompt.d.ts +1 -0
  434. package/dist/commands/sys/sysprompt.js +89 -0
  435. package/dist/commands/sys.js +10 -5
  436. package/dist/commands/view-cycle.js +5 -5
  437. package/dist/commands/view-list.js +3 -3
  438. package/dist/commands/view-new.js +6 -6
  439. package/dist/commands/view-pick.js +6 -6
  440. package/dist/commands/view-run.js +14 -14
  441. package/dist/commands/view.js +3 -3
  442. package/dist/commands/workspace.js +10 -10
  443. package/dist/core/__tests__/boot.test.js +140 -0
  444. package/dist/core/__tests__/broker-preflight.test.js +85 -0
  445. package/dist/core/__tests__/broker-sdk-wiring.test.js +10 -16
  446. package/dist/core/__tests__/canvas.test.js +37 -1
  447. package/dist/core/__tests__/chat-view-reconnect.test.js +70 -0
  448. package/dist/core/__tests__/child-death-wake.test.js +11 -2
  449. package/dist/core/__tests__/close.test.js +39 -1
  450. package/dist/core/__tests__/connection-reconnect-resume.test.js +37 -0
  451. package/dist/core/__tests__/context-intro.test.js +48 -14
  452. package/dist/core/__tests__/daemon-boot.test.js +204 -9
  453. package/dist/core/__tests__/fixtures/fake-engine.d.ts +30 -4
  454. package/dist/core/__tests__/fixtures/fake-engine.js +157 -18
  455. package/dist/core/__tests__/fixtures/fake-pi-host.js +10 -1
  456. package/dist/core/__tests__/full/broker-attach-limits.test.js +1 -1
  457. package/dist/core/__tests__/full/broker-attach-stream.test.js +1 -1
  458. package/dist/core/__tests__/full/broker-crash-teardown.test.js +10 -5
  459. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +1 -1
  460. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +1 -1
  461. package/dist/core/__tests__/full/broker-pane-resolution.test.js +1 -1
  462. package/dist/core/__tests__/full/cascade-close.test.js +31 -18
  463. package/dist/core/__tests__/full/detach-focus.test.js +2 -2
  464. package/dist/core/__tests__/full/human-new-window-regression.test.js +1 -1
  465. package/dist/core/__tests__/hearth-bootstrap.test.js +136 -0
  466. package/dist/core/__tests__/helpers/harness.d.ts +1 -1
  467. package/dist/core/__tests__/helpers/harness.js +3 -3
  468. package/dist/core/__tests__/human-stranded-deliver.test.js +38 -1
  469. package/dist/core/__tests__/human-surface-target.test.js +1 -1
  470. package/dist/core/__tests__/kickoff.test.js +18 -19
  471. package/dist/core/__tests__/live-mutation-verbs.test.js +10 -10
  472. package/dist/core/__tests__/live-mutation.test.js +8 -8
  473. package/dist/core/__tests__/migration.test.js +172 -13
  474. package/dist/core/__tests__/on-read-dedup-resume.test.js +40 -0
  475. package/dist/core/__tests__/preview-registry-sync.test.js +36 -0
  476. package/dist/core/__tests__/prune-to-limit.test.js +91 -0
  477. package/dist/core/__tests__/push-final-guard.test.js +7 -1
  478. package/dist/core/__tests__/relaunch-root.test.js +9 -9
  479. package/dist/core/__tests__/revive.test.js +100 -27
  480. package/dist/core/__tests__/spawn-root.test.js +24 -1
  481. package/dist/core/__tests__/stop-guard.test.js +10 -0
  482. package/dist/core/__tests__/stranded-relaunch.test.js +72 -0
  483. package/dist/core/__tests__/tmux-surface.test.js +5 -1
  484. package/dist/core/__tests__/trigger-migration.test.js +48 -0
  485. package/dist/core/__tests__/wake-bearings.test.js +23 -21
  486. package/dist/core/__tests__/wake-origin.test.js +36 -33
  487. package/dist/core/__tests__/yield-ensures-daemon.test.js +54 -0
  488. package/dist/core/artifact.d.ts +2 -33
  489. package/dist/core/artifact.js +27 -87
  490. package/dist/core/bootstrap.js +2 -0
  491. package/dist/core/canvas/boot.d.ts +48 -0
  492. package/dist/core/canvas/boot.js +157 -0
  493. package/dist/core/canvas/browse/__tests__/model.test.js +35 -1
  494. package/dist/core/canvas/browse/app.js +87 -17
  495. package/dist/core/canvas/browse/model.d.ts +10 -1
  496. package/dist/core/canvas/browse/model.js +37 -1
  497. package/dist/core/canvas/browse/render.js +35 -33
  498. package/dist/core/canvas/canvas.d.ts +33 -0
  499. package/dist/core/canvas/canvas.js +138 -8
  500. package/dist/core/canvas/db.js +121 -9
  501. package/dist/core/canvas/index.d.ts +1 -1
  502. package/dist/core/canvas/index.js +1 -1
  503. package/dist/core/canvas/labels.d.ts +6 -8
  504. package/dist/core/canvas/labels.js +8 -11
  505. package/dist/core/canvas/nav-model.d.ts +5 -4
  506. package/dist/core/canvas/nav-model.js +32 -18
  507. package/dist/core/canvas/paths.d.ts +18 -1
  508. package/dist/core/canvas/paths.js +31 -2
  509. package/dist/core/canvas/pid.d.ts +6 -0
  510. package/dist/core/canvas/pid.js +13 -0
  511. package/dist/core/canvas/render.d.ts +25 -0
  512. package/dist/core/canvas/render.js +96 -13
  513. package/dist/core/canvas/status-glyph.d.ts +35 -0
  514. package/dist/core/canvas/status-glyph.js +104 -0
  515. package/dist/core/canvas/triggers.d.ts +108 -0
  516. package/dist/core/canvas/triggers.js +320 -0
  517. package/dist/core/canvas/types.d.ts +130 -48
  518. package/dist/core/command.js +13 -4
  519. package/dist/core/config.js +114 -16
  520. package/dist/core/fault-classifier.d.ts +41 -0
  521. package/dist/core/fault-classifier.js +110 -0
  522. package/dist/core/feed/inbox.d.ts +15 -0
  523. package/dist/core/feed/inbox.js +40 -14
  524. package/dist/core/frontmatter.d.ts +1 -11
  525. package/dist/core/frontmatter.js +1 -55
  526. package/dist/core/hearth/__tests__/model-auth-guest.test.js +151 -0
  527. package/dist/core/hearth/config.d.ts +3 -0
  528. package/dist/core/hearth/config.js +111 -0
  529. package/dist/core/hearth/guest-env.d.ts +9 -0
  530. package/dist/core/hearth/guest-env.js +27 -0
  531. package/dist/core/hearth/index.d.ts +5 -0
  532. package/dist/core/hearth/index.js +5 -0
  533. package/dist/core/hearth/model-auth-guest.d.ts +8 -0
  534. package/dist/core/hearth/model-auth-guest.js +435 -0
  535. package/dist/core/hearth/provider.d.ts +28 -0
  536. package/dist/core/hearth/provider.js +10 -0
  537. package/dist/core/hearth/providers/blaxel-bootstrap.d.ts +12 -0
  538. package/dist/core/hearth/providers/blaxel-bootstrap.js +147 -0
  539. package/dist/core/hearth/providers/blaxel-home.d.ts +15 -0
  540. package/dist/core/hearth/providers/blaxel-home.js +136 -0
  541. package/dist/core/hearth/providers/blaxel.d.ts +31 -0
  542. package/dist/core/hearth/providers/blaxel.js +282 -0
  543. package/dist/core/hearth/providers/types.d.ts +77 -0
  544. package/dist/core/hearth/registry.d.ts +15 -0
  545. package/dist/core/hearth/registry.js +180 -0
  546. package/dist/core/hearth/types.d.ts +156 -0
  547. package/dist/core/help.d.ts +16 -0
  548. package/dist/core/help.js +2 -0
  549. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +79 -0
  550. package/dist/core/{skill-sync → host-exports}/builtins.d.ts +21 -13
  551. package/dist/core/host-exports/builtins.js +68 -0
  552. package/dist/core/{skill-sync → host-exports}/export.d.ts +9 -6
  553. package/dist/core/{skill-sync → host-exports}/export.js +37 -14
  554. package/dist/core/io.js +1 -1
  555. package/dist/core/log.d.ts +9 -0
  556. package/dist/core/log.js +113 -0
  557. package/dist/core/memory-resolver.d.ts +13 -13
  558. package/dist/core/memory-resolver.js +70 -51
  559. package/dist/core/personas/index.d.ts +4 -4
  560. package/dist/core/personas/index.js +2 -2
  561. package/dist/core/personas/loader.d.ts +51 -0
  562. package/dist/core/personas/loader.js +54 -50
  563. package/dist/core/personas/resolve.d.ts +43 -27
  564. package/dist/core/personas/resolve.js +336 -94
  565. package/dist/core/preview-registry.d.ts +25 -0
  566. package/dist/core/preview-registry.js +2047 -0
  567. package/dist/core/resolver.d.ts +1 -0
  568. package/dist/core/resolver.js +23 -16
  569. package/dist/core/runtime/auth-reload.d.ts +7 -0
  570. package/dist/core/runtime/auth-reload.js +69 -0
  571. package/dist/core/runtime/bearings.d.ts +46 -25
  572. package/dist/core/runtime/bearings.js +313 -52
  573. package/dist/core/runtime/branded-host.d.ts +4 -2
  574. package/dist/core/runtime/branded-host.js +66 -4
  575. package/dist/core/runtime/broker-protocol.d.ts +40 -5
  576. package/dist/core/runtime/broker-protocol.js +2 -2
  577. package/dist/core/runtime/broker.js +343 -18
  578. package/dist/core/runtime/close.js +39 -31
  579. package/dist/core/runtime/connectivity.d.ts +12 -0
  580. package/dist/core/runtime/connectivity.js +73 -0
  581. package/dist/core/runtime/fault-recovery-nudge.d.ts +2 -0
  582. package/dist/core/runtime/fault-recovery-nudge.js +2 -0
  583. package/dist/core/runtime/fault-recovery.d.ts +23 -0
  584. package/dist/core/runtime/fault-recovery.js +74 -0
  585. package/dist/core/runtime/fault.d.ts +25 -0
  586. package/dist/core/runtime/fault.js +176 -0
  587. package/dist/core/runtime/front-door.d.ts +1 -1
  588. package/dist/core/runtime/front-door.js +2 -2
  589. package/dist/core/runtime/host.d.ts +10 -0
  590. package/dist/core/runtime/host.js +71 -9
  591. package/dist/core/runtime/kickoff.js +32 -46
  592. package/dist/core/runtime/launch.d.ts +41 -21
  593. package/dist/core/runtime/launch.js +165 -52
  594. package/dist/core/runtime/lifecycle.js +7 -7
  595. package/dist/core/runtime/model-swap.d.ts +18 -0
  596. package/dist/core/runtime/model-swap.js +95 -0
  597. package/dist/core/runtime/naming.d.ts +7 -0
  598. package/dist/core/runtime/naming.js +61 -9
  599. package/dist/core/runtime/nodes.js +6 -1
  600. package/dist/core/runtime/persona.js +16 -17
  601. package/dist/core/runtime/placement.d.ts +41 -36
  602. package/dist/core/runtime/placement.js +159 -74
  603. package/dist/core/runtime/promote.d.ts +2 -0
  604. package/dist/core/runtime/promote.js +23 -3
  605. package/dist/core/runtime/recycle.js +13 -11
  606. package/dist/core/runtime/reset.d.ts +6 -3
  607. package/dist/core/runtime/reset.js +5 -5
  608. package/dist/core/runtime/revive-all.d.ts +5 -2
  609. package/dist/core/runtime/revive-all.js +5 -2
  610. package/dist/core/runtime/revive.d.ts +19 -8
  611. package/dist/core/runtime/revive.js +79 -25
  612. package/dist/core/runtime/roadmap.d.ts +1 -1
  613. package/dist/core/runtime/roadmap.js +1 -1
  614. package/dist/core/runtime/spawn.d.ts +3 -3
  615. package/dist/core/runtime/spawn.js +37 -13
  616. package/dist/core/runtime/stop-guard.js +11 -6
  617. package/dist/core/runtime/surface-bg.js +1 -1
  618. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  619. package/dist/core/runtime/tmux-chrome.js +1 -1
  620. package/dist/core/runtime/tmux.d.ts +30 -7
  621. package/dist/core/runtime/tmux.js +138 -84
  622. package/dist/core/runtime/view-socket-client.d.ts +46 -0
  623. package/dist/core/runtime/view-socket-client.js +203 -0
  624. package/dist/core/scope.d.ts +9 -0
  625. package/dist/core/scope.js +37 -15
  626. package/dist/core/substrate/index.d.ts +1 -1
  627. package/dist/core/substrate/index.js +1 -1
  628. package/dist/core/substrate/on-read.js +39 -25
  629. package/dist/core/substrate/render.d.ts +10 -13
  630. package/dist/core/substrate/render.js +56 -51
  631. package/dist/core/tui/host.js +83 -18
  632. package/dist/core/view/__tests__/transport-cache.test.js +62 -0
  633. package/dist/core/view/contract.d.ts +20 -0
  634. package/dist/core/view/loader.js +2 -2
  635. package/dist/core/view/stream-local.d.ts +3 -0
  636. package/dist/core/view/stream-local.js +184 -0
  637. package/dist/core/view/transport-cache.d.ts +8 -0
  638. package/dist/core/view/transport-cache.js +38 -0
  639. package/dist/core/view/transport-local.js +4 -0
  640. package/dist/core/view/transport.d.ts +7 -1
  641. package/dist/core/wake.d.ts +2 -2
  642. package/dist/core/wake.js +7 -7
  643. package/dist/daemon/__tests__/predicate-eval.test.js +109 -0
  644. package/dist/daemon/crtrd.d.ts +3 -19
  645. package/dist/daemon/crtrd.js +360 -280
  646. package/dist/daemon/manage.d.ts +18 -1
  647. package/dist/daemon/manage.js +54 -9
  648. package/dist/daemon/predicate-eval.d.ts +52 -0
  649. package/dist/daemon/predicate-eval.js +248 -0
  650. package/dist/hearth/control-plane/__tests__/node-message.test.js +60 -0
  651. package/dist/hearth/control-plane/__tests__/rate-limit-recurrence.test.js +49 -0
  652. package/dist/hearth/control-plane/__tests__/relay-security.test.js +314 -0
  653. package/dist/hearth/control-plane/__tests__/scheduler-scan-loop.test.d.ts +1 -0
  654. package/dist/hearth/control-plane/__tests__/scheduler-scan-loop.test.js +133 -0
  655. package/dist/hearth/control-plane/__tests__/trigger-delivery.test.d.ts +1 -0
  656. package/dist/hearth/control-plane/__tests__/trigger-delivery.test.js +170 -0
  657. package/dist/hearth/control-plane/__tests__/webhook-ingress.test.d.ts +1 -0
  658. package/dist/hearth/control-plane/__tests__/webhook-ingress.test.js +167 -0
  659. package/dist/hearth/control-plane/config.d.ts +21 -0
  660. package/dist/hearth/control-plane/config.js +77 -0
  661. package/dist/hearth/control-plane/db.d.ts +30 -0
  662. package/dist/hearth/control-plane/db.js +534 -0
  663. package/dist/hearth/control-plane/ingress/rate-limit.d.ts +24 -0
  664. package/dist/hearth/control-plane/ingress/rate-limit.js +100 -0
  665. package/dist/hearth/control-plane/ingress/route-store.d.ts +31 -0
  666. package/dist/hearth/control-plane/ingress/route-store.js +61 -0
  667. package/dist/hearth/control-plane/ingress/webhook-delivery-store.d.ts +41 -0
  668. package/dist/hearth/control-plane/ingress/webhook-delivery-store.js +69 -0
  669. package/dist/hearth/control-plane/ingress/webhook-route.d.ts +55 -0
  670. package/dist/hearth/control-plane/ingress/webhook-route.js +285 -0
  671. package/dist/hearth/control-plane/main.d.ts +1 -0
  672. package/dist/hearth/control-plane/main.js +88 -0
  673. package/dist/hearth/control-plane/node-message.d.ts +31 -0
  674. package/dist/hearth/control-plane/node-message.js +98 -0
  675. package/dist/hearth/control-plane/register.d.ts +15 -0
  676. package/dist/hearth/control-plane/register.js +34 -0
  677. package/dist/hearth/control-plane/registry.d.ts +17 -0
  678. package/dist/hearth/control-plane/registry.js +161 -0
  679. package/dist/hearth/control-plane/relay.d.ts +40 -0
  680. package/dist/hearth/control-plane/relay.js +642 -0
  681. package/dist/hearth/control-plane/scheduler/fire-store.d.ts +36 -0
  682. package/dist/hearth/control-plane/scheduler/fire-store.js +73 -0
  683. package/dist/hearth/control-plane/scheduler/recurrence.d.ts +7 -0
  684. package/dist/hearth/control-plane/scheduler/recurrence.js +58 -0
  685. package/dist/hearth/control-plane/scheduler/scan-loop.d.ts +38 -0
  686. package/dist/hearth/control-plane/scheduler/scan-loop.js +138 -0
  687. package/dist/hearth/control-plane/scheduler/schedule-store.d.ts +32 -0
  688. package/dist/hearth/control-plane/scheduler/schedule-store.js +66 -0
  689. package/dist/hearth/control-plane/secrets.d.ts +17 -0
  690. package/dist/hearth/control-plane/secrets.js +113 -0
  691. package/dist/hearth/control-plane/server.d.ts +27 -0
  692. package/dist/hearth/control-plane/server.js +346 -0
  693. package/dist/hearth/control-plane/session.d.ts +68 -0
  694. package/dist/hearth/control-plane/session.js +273 -0
  695. package/dist/hearth/control-plane/triggers/acl.d.ts +14 -0
  696. package/dist/hearth/control-plane/triggers/acl.js +52 -0
  697. package/dist/hearth/control-plane/triggers/audit-store.d.ts +38 -0
  698. package/dist/hearth/control-plane/triggers/audit-store.js +79 -0
  699. package/dist/hearth/control-plane/triggers/deliver.d.ts +43 -0
  700. package/dist/hearth/control-plane/triggers/deliver.js +76 -0
  701. package/dist/hearth/control-plane/triggers/envelope.d.ts +29 -0
  702. package/dist/hearth/control-plane/triggers/envelope.js +38 -0
  703. package/dist/hearth/control-plane/types.d.ts +66 -0
  704. package/dist/hearth/control-plane/types.js +1 -0
  705. package/dist/hearth/control-plane/wake.d.ts +80 -0
  706. package/dist/hearth/control-plane/wake.js +312 -0
  707. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.d.ts +1 -0
  708. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.js +289 -0
  709. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.d.ts +1 -0
  710. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.js +34 -0
  711. package/dist/hearth/wake-proxy/__tests__/guest-source.test.d.ts +1 -0
  712. package/dist/hearth/wake-proxy/__tests__/guest-source.test.js +203 -0
  713. package/dist/hearth/wake-proxy/__tests__/hardening.test.d.ts +1 -0
  714. package/dist/hearth/wake-proxy/__tests__/hardening.test.js +59 -0
  715. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.d.ts +1 -0
  716. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.js +372 -0
  717. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.d.ts +1 -0
  718. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.js +258 -0
  719. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.d.ts +1 -0
  720. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.js +437 -0
  721. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.d.ts +1 -0
  722. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.js +15 -0
  723. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.d.ts +1 -0
  724. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.js +141 -0
  725. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.d.ts +1 -0
  726. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.js +143 -0
  727. package/dist/hearth/wake-proxy/anthropic-oauth.d.ts +58 -0
  728. package/dist/hearth/wake-proxy/anthropic-oauth.js +189 -0
  729. package/dist/hearth/wake-proxy/auth.d.ts +22 -0
  730. package/dist/hearth/wake-proxy/auth.js +128 -0
  731. package/dist/hearth/wake-proxy/config.d.ts +2 -0
  732. package/dist/hearth/wake-proxy/config.js +151 -0
  733. package/dist/hearth/wake-proxy/guest-source.d.ts +14 -0
  734. package/dist/hearth/wake-proxy/guest-source.js +130 -0
  735. package/dist/hearth/wake-proxy/hearth-status.d.ts +44 -0
  736. package/dist/hearth/wake-proxy/hearth-status.js +267 -0
  737. package/dist/hearth/wake-proxy/home.d.ts +61 -0
  738. package/dist/hearth/wake-proxy/home.js +333 -0
  739. package/dist/hearth/wake-proxy/main.d.ts +1 -0
  740. package/dist/hearth/wake-proxy/main.js +134 -0
  741. package/dist/hearth/wake-proxy/model-auth.d.ts +13 -0
  742. package/dist/hearth/wake-proxy/model-auth.js +345 -0
  743. package/dist/hearth/wake-proxy/proxy.d.ts +35 -0
  744. package/dist/hearth/wake-proxy/proxy.js +716 -0
  745. package/dist/hearth/wake-proxy/public-source-gate.d.ts +9 -0
  746. package/dist/hearth/wake-proxy/public-source-gate.js +409 -0
  747. package/dist/hearth/wake-proxy/redact.d.ts +1 -0
  748. package/dist/hearth/wake-proxy/redact.js +17 -0
  749. package/dist/hearth/wake-proxy/server.d.ts +11 -0
  750. package/dist/hearth/wake-proxy/server.js +142 -0
  751. package/dist/hearth/wake-proxy/state.d.ts +18 -0
  752. package/dist/hearth/wake-proxy/state.js +342 -0
  753. package/dist/hearth/wake-proxy/types.d.ts +76 -0
  754. package/dist/hearth/wake-proxy/types.js +1 -0
  755. package/dist/index.js +3 -2
  756. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +6 -5
  757. package/dist/pi-extensions/canvas-context-intro.js +7 -7
  758. package/dist/pi-extensions/canvas-doc-substrate.js +47 -24
  759. package/dist/pi-extensions/canvas-nav.js +16 -9
  760. package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
  761. package/dist/pi-extensions/canvas-stophook.js +78 -11
  762. package/dist/prompts/view.js +7 -8
  763. package/dist/types.d.ts +39 -20
  764. package/dist/types.js +38 -13
  765. package/dist/web/runtime.js +141 -42
  766. package/dist/web/transport-http.js +7 -5
  767. package/dist/web/transport-stream.d.ts +3 -0
  768. package/dist/web/transport-stream.js +204 -0
  769. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  770. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  771. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  772. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  773. package/dist/web-client/assets/fraunces-latin-ext-wght-normal-Ca2vKHc0.woff2 +0 -0
  774. package/dist/web-client/assets/fraunces-latin-wght-normal-ukD16Tqj.woff2 +0 -0
  775. package/dist/web-client/assets/fraunces-vietnamese-wght-normal-CnvboYUG.woff2 +0 -0
  776. package/dist/web-client/assets/index-BRKxe-hy.js +80 -0
  777. package/dist/web-client/assets/index-BZUxTkv5.css +2 -0
  778. package/dist/web-client/assets/instrument-sans-latin-ext-wght-normal-B5bTHO_g.woff2 +0 -0
  779. package/dist/web-client/assets/instrument-sans-latin-wght-normal-BbzFLZTg.woff2 +0 -0
  780. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  781. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  782. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  783. package/dist/web-client/index.html +3 -2
  784. package/package.json +37 -11
  785. package/scripts/postinstall.mjs +8 -0
  786. package/dist/clients/attach/__tests__/action-parity.test.js +0 -48
  787. package/dist/clients/attach/__tests__/clipboard-image.test.js +0 -76
  788. package/dist/clients/attach/__tests__/editor-newline.test.js +0 -82
  789. package/dist/clients/attach/__tests__/git-info.test.js +0 -31
  790. package/dist/clients/attach/__tests__/onrequest-wired.test.js +0 -20
  791. package/dist/clients/attach/__tests__/reconnect-giveup.test.js +0 -30
  792. package/dist/clients/attach/__tests__/slash-quit-copy.test.js +0 -42
  793. package/dist/clients/attach/__tests__/titled-editor.test.js +0 -39
  794. package/dist/commands/memory/__tests__/lint-schema.test.js +0 -52
  795. package/dist/core/__tests__/argv-parser.test.js +0 -217
  796. package/dist/core/__tests__/draw-style.test.js +0 -258
  797. package/dist/core/__tests__/error-stall-recycle.test.js +0 -141
  798. package/dist/core/__tests__/frame-decoder-perf.test.js +0 -224
  799. package/dist/core/__tests__/keystone.test.js +0 -185
  800. package/dist/core/__tests__/listing-completeness.test.js +0 -31
  801. package/dist/core/__tests__/memory-resolver.test.js +0 -108
  802. package/dist/core/__tests__/memory.test.js +0 -60
  803. package/dist/core/__tests__/pane-column.test.js +0 -153
  804. package/dist/core/__tests__/persona-compose.test.js +0 -53
  805. package/dist/core/__tests__/persona-subkind.test.js +0 -65
  806. package/dist/core/__tests__/persona.test.js +0 -107
  807. package/dist/core/__tests__/unknown-path.test.js +0 -58
  808. package/dist/core/canvas/wakeups.d.ts +0 -76
  809. package/dist/core/canvas/wakeups.js +0 -185
  810. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.js +0 -57
  811. package/dist/core/skill-sync/builtins.js +0 -112
  812. package/dist/core/skill-sync/claude-plugins.d.ts +0 -23
  813. package/dist/core/skill-sync/claude-plugins.js +0 -71
  814. package/dist/core/skill-sync/engine.d.ts +0 -42
  815. package/dist/core/skill-sync/engine.js +0 -633
  816. package/dist/core/skill-sync/manifest.d.ts +0 -64
  817. package/dist/core/skill-sync/manifest.js +0 -181
  818. package/dist/core/skill-sync/profile.d.ts +0 -76
  819. package/dist/core/skill-sync/profile.js +0 -173
  820. package/dist/core/skill-sync/snapshot.d.ts +0 -57
  821. package/dist/core/skill-sync/snapshot.js +0 -120
  822. package/dist/pi-extensions/canvas-commands.d.ts +0 -37
  823. package/dist/pi-extensions/canvas-commands.js +0 -113
  824. package/dist/pi-extensions/canvas-resume.d.ts +0 -21
  825. package/dist/pi-extensions/canvas-resume.js +0 -83
  826. package/dist/pi-extensions/canvas-view.d.ts +0 -21
  827. package/dist/pi-extensions/canvas-view.js +0 -76
  828. package/dist/web-client/assets/index-BUvQb4hR.css +0 -2
  829. package/dist/web-client/assets/index-ClLQXYAE.js +0 -10
  830. /package/dist/clients/attach/__tests__/{action-parity.test.d.ts → crtr-output-coverage.test.d.ts} +0 -0
  831. /package/dist/clients/attach/__tests__/{clipboard-image.test.d.ts → crtr-output-render.test.d.ts} +0 -0
  832. /package/dist/clients/{attach/__tests__/editor-newline.test.d.ts → web/__tests__/source-cache.test.d.ts} +0 -0
  833. /package/dist/{clients/attach/__tests__/git-info.test.d.ts → commands/sys/__tests__/sync-import.test.d.ts} +0 -0
  834. /package/dist/{clients/attach/__tests__/onrequest-wired.test.d.ts → core/__tests__/boot.test.d.ts} +0 -0
  835. /package/dist/{clients/attach/__tests__/reconnect-giveup.test.d.ts → core/__tests__/broker-preflight.test.d.ts} +0 -0
  836. /package/dist/{clients/attach/__tests__/slash-quit-copy.test.d.ts → core/__tests__/chat-view-reconnect.test.d.ts} +0 -0
  837. /package/dist/{clients/attach/__tests__/titled-editor.test.d.ts → core/__tests__/connection-reconnect-resume.test.d.ts} +0 -0
  838. /package/dist/{commands/memory/__tests__/lint-schema.test.d.ts → core/__tests__/hearth-bootstrap.test.d.ts} +0 -0
  839. /package/dist/core/__tests__/{argv-parser.test.d.ts → preview-registry-sync.test.d.ts} +0 -0
  840. /package/dist/core/__tests__/{draw-style.test.d.ts → prune-to-limit.test.d.ts} +0 -0
  841. /package/dist/core/__tests__/{error-stall-recycle.test.d.ts → stranded-relaunch.test.d.ts} +0 -0
  842. /package/dist/core/__tests__/{frame-decoder-perf.test.d.ts → trigger-migration.test.d.ts} +0 -0
  843. /package/dist/core/__tests__/{keystone.test.d.ts → yield-ensures-daemon.test.d.ts} +0 -0
  844. /package/dist/core/{__tests__/listing-completeness.test.d.ts → hearth/__tests__/model-auth-guest.test.d.ts} +0 -0
  845. /package/dist/core/{__tests__/memory-resolver.test.d.ts → hearth/providers/types.js} +0 -0
  846. /package/dist/core/{__tests__/memory.test.d.ts → hearth/types.js} +0 -0
  847. /package/dist/core/{__tests__/pane-column.test.d.ts → host-exports/__tests__/export-prunes-boot-skill.test.d.ts} +0 -0
  848. /package/dist/core/{__tests__/persona-compose.test.d.ts → view/__tests__/transport-cache.test.d.ts} +0 -0
  849. /package/dist/{core/__tests__/persona-subkind.test.d.ts → daemon/__tests__/predicate-eval.test.d.ts} +0 -0
  850. /package/dist/{core/__tests__/persona.test.d.ts → hearth/control-plane/__tests__/node-message.test.d.ts} +0 -0
  851. /package/dist/{core/__tests__/unknown-path.test.d.ts → hearth/control-plane/__tests__/rate-limit-recurrence.test.d.ts} +0 -0
  852. /package/dist/{core/skill-sync/__tests__/dry-run-wrote-count.test.d.ts → hearth/control-plane/__tests__/relay-security.test.d.ts} +0 -0
@@ -10,8 +10,8 @@
10
10
  // reaps a node on pane/window state. All node liveness routes through
11
11
  // handleNodeLiveness:
12
12
  // • Poll every intervalMs (default 2000ms).
13
- // • pid alive → leave; but enforce a stuck refresh-yield (§H) and a
14
- // wedged-engine error-stall (§I, see below).
13
+ // • pid alive → leave; but enforce a stuck refresh-yield and active-fault
14
+ // recovery when a parked broker is due.
15
15
  // • pid null + pi_session_id set → relaunch in flight; leave.
16
16
  // • pid null + pi_session_id null → after a boot grace, crash + surface boot
17
17
  // failure (the broker exited before session_start).
@@ -28,35 +28,46 @@
28
28
  // grace, it force-kills the engine itself (handleYieldStall) so the dead-pid
29
29
  // refresh path then revives it fresh.
30
30
  //
31
- // §I error-stall: an engine whose turn ends with stopReason 'error' (e.g. a
32
- // provider outage exhausted the SDK retry budget) is left PARKED by the
33
- // stophook ("stay alive for re-steering") — but a headless node has no human to
34
- // re-steer it, so the broker stays alive, status stays 'active', and the pid-only
35
- // liveness check reads it healthy FOREVER (gh issue #4: a 9h zombie). The daemon
36
- // is the authority here too: when a live, not-busy node with no pending intent
37
- // has a session file that is QUIET past a grace AND whose last assistant message
38
- // stopped with 'error', it kills the engine (handleErrorStall) so the ordinary
39
- // dead-pid crash path grace-revives RESUME on the saved session the exact
40
- // manual recovery (kill broker + canvas revive) that fixes these by hand.
31
+ // An engine whose turn ends with stopReason 'error' (e.g. a provider outage
32
+ // exhausted the SDK retry budget) is left parked by the stophook ("stay alive
33
+ // for re-steering") — but a headless node has no human to re-steer it, so the
34
+ // broker stays alive, status stays 'active', and the pid-only liveness check
35
+ // reads it healthy forever. The daemon is the authority here too: when a live,
36
+ // not-busy node with no pending intent has a session file that is quiet past
37
+ // the recovery window and whose last assistant message stops with 'error', the
38
+ // daemon keeps the live broker parked and retries it via the inbox-based
39
+ // fault-recovery pass so the ordinary dead-pid crash path never needs an
40
+ // out-of-band launch.
41
+ // dead-pid crash path grace-revives RESUME on the saved session — the manual
42
+ // recovery (kill broker + canvas revive) that fixes these by hand.
41
43
  //
42
44
  // Single-instance guarantee
43
- // A PID file at crtrHome()/crtrd.pid prevents double-runs. On start, if the
44
- // file exists and the recorded pid is alive, we refuse to start (exit 0).
45
- // On stop (SIGINT/SIGTERM/exit) we remove the file.
46
- import { writeFileSync, readFileSync, rmSync, existsSync, mkdirSync, statSync, openSync, readSync, closeSync, } from 'node:fs';
47
- import { join } from 'node:path';
45
+ // A PID file prevents double-runs. On start, if the file exists and the
46
+ // recorded pid is alive, we refuse to start (exit 0). Hearth guests set
47
+ // CRTR_PIDFILE to keep this process-local on recreate; otherwise it defaults
48
+ // to crtrHome()/crtrd.pid. On stop (SIGINT/SIGTERM/exit) we remove the file.
49
+ import { writeFileSync, readFileSync, rmSync, existsSync, mkdirSync, statSync, } from 'node:fs';
50
+ import { dirname, join } from 'node:path';
51
+ import { homedir } from 'node:os';
48
52
  import { crtrHome, nodeDir, jobDir } from '../core/canvas/paths.js';
49
- import { listNodes, getRow, getNode, dueWakes, consumeWake, advanceWake, listFocuses, closeFocusRow, } from '../core/canvas/index.js';
53
+ import { listNodes, getRow, getNode, dueClockTriggers, consumeTrigger, advanceTrigger, listFocuses, closeFocusRow, pruneToLimit, } from '../core/canvas/index.js';
50
54
  import { transition } from '../core/runtime/lifecycle.js';
51
55
  import { isBusy } from '../core/runtime/busy.js';
56
+ import { FAULT_QUIET_MS } from '../core/runtime/fault.js';
57
+ import { logger } from '../core/log.js';
58
+ export { FAULT_QUIET_MS };
52
59
  import { isPidAlive } from '../core/canvas/pid.js';
60
+ import { reconcileBootLiveness } from '../core/canvas/boot.js';
53
61
  import { listLivePanes, tearDownNode } from '../core/runtime/placement.js';
54
62
  import { reviveNode } from '../core/runtime/revive.js';
63
+ import { isBrokerLive } from '../core/runtime/model-swap.js';
64
+ import { reloadAuthLive } from '../core/runtime/auth-reload.js';
55
65
  import { spawnChild } from '../core/runtime/spawn.js';
56
66
  import { wakeOriginFrom } from '../core/runtime/bearings.js';
57
67
  import { pushUrgent } from '../core/feed/feed.js';
58
68
  import { appendInbox, readInboxSince, readCursor } from '../core/feed/inbox.js';
59
69
  import { nextSlotAfter } from '../core/wake.js';
70
+ import { evaluateDuePredicates, reapTimedOutPredicates, recoverStalePredicateLeases, predicateCapacity, } from './predicate-eval.js';
60
71
  /** Surface a vehicle that never booted.
61
72
  *
62
73
  * `spawnChild` returns status="active" the instant the tmux window opens — it
@@ -78,6 +89,19 @@ async function surfaceBootFailure(meta) {
78
89
  await pushUrgent(meta.node_id, body, { from: meta.node_id });
79
90
  }
80
91
  const DEFAULT_INTERVAL_MS = 2000;
92
+ // Count-based auto-prune of the canvas (pruneToLimit). The canvas grows
93
+ // unbounded — the TTL `crtr canvas prune` is manual, so without this a long-lived
94
+ // daemon's canvas accumulates thousands of terminal nodes, making every scan +
95
+ // `canvas snapshot` expensive. Keep the AUTO_PRUNE_MAX most-recently-active nodes
96
+ // (live nodes are NEVER deleted, so the real floor is max(AUTO_PRUNE_MAX,
97
+ // liveCount)). It's a DB sweep, not per-tick work — throttled to PRUNE_INTERVAL_MS.
98
+ const AUTO_PRUNE_MAX = 2000;
99
+ const PRUNE_INTERVAL_MS = 60 * 60 * 1000;
100
+ // Last auto-prune wall-clock. -Infinity so the FIRST tick after start runs it
101
+ // (the canvas may already be huge at boot); thereafter every PRUNE_INTERVAL_MS.
102
+ // In-memory only — a daemon restart re-runs it once, which is harmless.
103
+ let lastPruneAt = Number.NEGATIVE_INFINITY;
104
+ const log = logger('crtrd');
81
105
  // How long a node's broker pid may be observed dead before the daemon revives
82
106
  // it. MUST exceed worst-case broker boot time: a refresh / crash-revive
83
107
  // transiently shows a dead OLD pid for the gap between the old broker exiting
@@ -106,13 +130,13 @@ const KILL_ESCALATE_MS = 20_000;
106
130
  // unhealthySince — a daemon restart resets them (worst case: one extra grace).
107
131
  const yieldStallSince = new Map();
108
132
  const yieldTermAt = new Map();
109
- // Wake-failure dedup latch (third pass): wakeup_ids we've already fail-loud
133
+ // Trigger-failure dedup latch (third pass): trigger_ids we've already fail-loud
110
134
  // notified about, so a permanently-broken spawn-cron (or a quarantined recurrence)
111
135
  // notifies the armer ONCE and then stays quiet until the next success or cancel —
112
136
  // the unrotated, append-only inbox.jsonl must not be flooded (Min-9). In-memory
113
137
  // only, like unhealthySince; a daemon restart resets it (worst case: one repeat
114
138
  // notice). A successful spawn clears its entry so a future failure re-notifies.
115
- const notifiedWakeFailures = new Set();
139
+ const notifiedTriggerFailures = new Set();
116
140
  /** Refresh-stall decision (§H refresh-authority; audit 2026-06-09, Bug 1 — node
117
141
  * mq5v9hfa-74493d45 and siblings; stuck-refresh — parent mq7s5o93): a `node
118
142
  * yield` / refresh records intent='refresh' and relies on the in-process
@@ -184,151 +208,77 @@ function handleYieldStall(row, pid, now) {
184
208
  }
185
209
  }
186
210
  }
187
- // §I error-stall grace: how long a node's session .jsonl must have been QUIET
188
- // (no append mtime is the clock, so it survives daemon restarts) before a
189
- // trailing-error engine is declared wedged and killed. Generous enough that an
190
- // in-flight recovery (the human re-steering, a parent's message waking a new
191
- // turn via the live inbox-watcher — both of which append and reset the clock)
192
- // always wins, while a true zombie recovers in minutes instead of never.
193
- export const ERROR_STALL_QUIET_MS = 5 * 60_000;
194
- // Per-node SIGTERM timestamps for §I kill escalation, mirroring yieldTermAt.
195
- const errorTermAt = new Map();
196
- // Memoized tail inspection per node, keyed on the session file's mtime so the
197
- // (rare) 64KB tail read happens once per file change, not once per 2s tick.
198
- const errorTailMemo = new Map();
199
- const TAIL_BYTES = 64 * 1024;
200
- /** Read the last TAIL_BYTES of a file. null on any failure (absent file reads
201
- * as "nothing to inspect", never as evidence of a wedge). */
202
- function readTail(path) {
203
- try {
204
- const size = statSync(path).size;
205
- const len = Math.min(TAIL_BYTES, size);
206
- if (len === 0)
207
- return null;
208
- const fd = openSync(path, 'r');
209
- try {
210
- const buf = Buffer.alloc(len);
211
- readSync(fd, buf, 0, len, size - len);
212
- return buf.toString('utf8');
213
- }
214
- finally {
215
- closeSync(fd);
216
- }
217
- }
218
- catch {
219
- return null;
220
- }
221
- }
222
- /** The §I wedge signature, from a session-jsonl tail: the LAST assistant
223
- * message stopped with 'error' (retry budget exhausted — pi appends the error
224
- * turn and parks). Returns its errorMessage for the daemon log (the "why it
225
- * wedged" trace), or null when the last assistant turn ended any other way —
226
- * 'stop'/'length' is a healthy park, 'aborted' is a human Esc, and trailing
227
- * non-assistant lines (toolResults, an injected user message) are walked past.
228
- * The first line of a mid-file tail cut fails JSON.parse and is skipped. */
229
- export function trailingEngineError(tail) {
230
- if (tail === null)
231
- return null;
232
- const lines = tail.split('\n');
233
- for (let i = lines.length - 1; i >= 0; i--) {
234
- const line = lines[i].trim();
235
- if (line === '')
236
- continue;
237
- let msg;
238
- try {
239
- msg = JSON.parse(line)?.message;
240
- }
241
- catch {
242
- continue; // a cut fragment (tail boundary) or non-JSON line
243
- }
244
- if (msg?.role !== 'assistant')
245
- continue;
246
- if (msg.stopReason !== 'error')
247
- return null;
248
- return typeof msg.errorMessage === 'string' && msg.errorMessage !== ''
249
- ? msg.errorMessage
250
- : 'engine error (no errorMessage recorded)';
251
- }
252
- return null;
211
+ // ---------------------------------------------------------------------------
212
+ // Auth-reload fan (one /login every live broker follows)
213
+ // ---------------------------------------------------------------------------
214
+ /** Path of the shared pi credentials file every broker reads. VENDORED from pi
215
+ * `config.getAuthPath()` (= `<agentDir>/auth.json`) the same way spawn.ts
216
+ * vendors the sessions root: a ROOT import of pi's `getAgentDir` would eager-
217
+ * load the heavy pi SDK index, so we mirror its resolution — `PI_CODING_AGENT_DIR`
218
+ * env, else `~/.pi/agent`. Re-sync on a pi SDK bump that moves auth.json. */
219
+ function piAuthPath() {
220
+ const env = process.env['PI_CODING_AGENT_DIR'];
221
+ const agentDir = env !== undefined && env !== '' ? env : join(homedir(), '.pi', 'agent');
222
+ return join(agentDir, 'auth.json');
253
223
  }
254
- /** Error-stall decision (§I; gh issue #4 — node mqaeqzdu-0746b3b7, a 9h zombie
255
- * after an Anthropic outage). Pure, mirroring yieldStallVerdict; the kill side
256
- * effects live in handleErrorStall.
224
+ // Last-observed auth.json mtime, for the daemon's change-watch. Lazily seeded on
225
+ // the first poll that sees the file (so daemon start never fans a spurious
226
+ // reload), then updated on every detected change. In-memory only — a daemon
227
+ // restart re-seeds from the current file, so at most one missed change spans the
228
+ // restart gap (re-login during a ~1s restart), which a human just redoes.
229
+ let knownAuthMtimeMs = null;
230
+ /** Watch the shared auth.json mtime and, on a change, fan a live `reload_auth`
231
+ * to every live broker so one `/login` propagates across the whole canvas. The
232
+ * broker that performed the login already self-reloaded; re-reloading it is
233
+ * harmless (authStorage.reload() is idempotent), so we don't exclude it.
257
234
  *
258
- * 'kill' ONLY when ALL of: engine alive, NO pending intent (refresh is §H's
259
- * domain; idle-release chose dormancy), the turn is over (busy absent a node
260
- * wedged mid-bash must be recovered by killing the subprocess, never the node),
261
- * the session file has been quiet past ERROR_STALL_QUIET_MS, and its last
262
- * assistant message stopped with 'error'. */
263
- export function errorStallVerdict(piPidAlive, intent, busy, quietForMs, trailingError) {
264
- if (piPidAlive !== true)
265
- return 'leave';
266
- if (intent !== null)
267
- return 'leave';
268
- if (busy)
269
- return 'leave';
270
- if (quietForMs === null || quietForMs < ERROR_STALL_QUIET_MS)
271
- return 'leave';
272
- if (!trailingError)
273
- return 'leave';
274
- return 'kill';
275
- }
276
- /** Enact an error-stall (§I): when the verdict is 'kill', SIGTERM the parked
277
- * engine (escalating to SIGKILL after KILL_ESCALATE_MS, like §H — a broker
278
- * wedged after an outage may not run graceful handlers). intent is null, so
279
- * once the pid dies the ordinary crash branch in handleNodeLiveness grace-
280
- * revives RESUME on the saved session — the conversation is preserved and the
281
- * revive kickoff prompts the node to continue. No grace clock of our own: the
282
- * session file's mtime IS the clock (any append — a re-steer, an inbox-watcher
283
- * wake, a new turn — resets it). */
284
- function handleErrorStall(row, pid, now) {
285
- const id = row.node_id;
286
- if (row.intent !== null || isBusy(id)) {
287
- errorTermAt.delete(id);
288
- return;
289
- }
290
- const file = getNode(id)?.pi_session_file;
291
- if (file == null)
292
- return;
235
+ * Rides the existing ~2s poll, so several rapid writes from one login collapse
236
+ * to a single observed mtime change a single fan. Each broker is reloaded
237
+ * under its own try/catch (Promise.allSettled): a broker mid-shutdown or whose
238
+ * socket refuses connect is logged and skipped, never aborting the others. */
239
+ async function handleAuthReload(now) {
293
240
  let mtimeMs;
294
241
  try {
295
- mtimeMs = statSync(file).mtimeMs;
242
+ mtimeMs = statSync(piAuthPath()).mtimeMs;
296
243
  }
297
244
  catch {
298
- return; // session file unreadable no evidence, never kill on "can't tell"
245
+ return; // no auth.json yet (never logged in) nothing to watch
299
246
  }
300
- const quietFor = now - mtimeMs;
301
- if (quietFor < ERROR_STALL_QUIET_MS) {
302
- errorTermAt.delete(id);
247
+ if (knownAuthMtimeMs === null) {
248
+ knownAuthMtimeMs = mtimeMs; // seed on first sight; never fan on daemon start
303
249
  return;
304
250
  }
305
- let memo = errorTailMemo.get(id);
306
- if (memo === undefined || memo.mtimeMs !== mtimeMs) {
307
- memo = { mtimeMs, error: trailingEngineError(readTail(file)) };
308
- errorTailMemo.set(id, memo);
251
+ if (mtimeMs === knownAuthMtimeMs)
252
+ return;
253
+ knownAuthMtimeMs = mtimeMs;
254
+ // Enumerate live brokers (pid alive + view.sock present) only when auth
255
+ // actually changed — the rare path, so the extra list/stat cost is paid only
256
+ // on a real login, never every tick.
257
+ let live;
258
+ try {
259
+ live = listNodes({ status: ['active', 'idle'] })
260
+ .filter((r) => r.kind !== 'human')
261
+ .map((r) => getNode(r.node_id))
262
+ .filter((m) => m !== null && isBrokerLive(m))
263
+ .map((m) => m.node_id);
309
264
  }
310
- if (errorStallVerdict(true, row.intent, false, quietFor, memo.error !== null) !== 'kill')
265
+ catch (err) {
266
+ process.stderr.write(`[crtrd] auth-reload enumerate error: ${err.message}\n`);
311
267
  return;
312
- const termed = errorTermAt.get(id);
313
- if (termed === undefined) {
314
- process.stderr.write(`[crtrd] kill ${id} (error-stall: engine parked on a trailing error turn, session quiet ${Math.round(quietFor / 1000)}s — SIGTERM; last error: ${String(memo.error).slice(0, 200)})\n`);
315
- try {
316
- process.kill(pid, 'SIGTERM');
317
- }
318
- catch {
319
- /* already gone */
320
- }
321
- errorTermAt.set(id, now);
322
268
  }
323
- else if (now - termed >= KILL_ESCALATE_MS) {
324
- process.stderr.write(`[crtrd] kill ${id} (error-stall: pi ${pid} survived SIGTERM — SIGKILL)\n`);
269
+ if (live.length === 0)
270
+ return;
271
+ const results = await Promise.allSettled(live.map(async (id) => {
325
272
  try {
326
- process.kill(pid, 'SIGKILL');
273
+ await reloadAuthLive(id);
327
274
  }
328
- catch {
329
- /* already gone */
275
+ catch (err) {
276
+ process.stderr.write(`[crtrd] auth-reload ${id} failed: ${err.message}\n`);
277
+ throw err;
330
278
  }
331
- }
279
+ }));
280
+ const ok = results.filter((r) => r.status === 'fulfilled').length;
281
+ process.stderr.write(`[crtrd] auth-reload: auth.json changed — fanned to ${live.length} live broker(s) (${ok} ok, ${live.length - ok} failed)\n`);
332
282
  }
333
283
  /** Decide what to do with a node whose engine pid is DEAD, from how long it's
334
284
  * been dead. Pure — the time/revive side effects live in handleNodeLiveness;
@@ -354,12 +304,19 @@ export function livenessVerdict(piPidAlive, deadFor) {
354
304
  * with the turn over) and, once the engine has sat alive past the grace,
355
305
  * kills it — so the daemon, not the (possibly stale) in-process stophook, is
356
306
  * the authority on refresh, and the dead-pid refresh branch below then
357
- * revives it fresh. AND enforce §I: handleErrorStall self-guards (no-op
358
- * unless intent is null with the turn over) and kills an engine parked on a
359
- * trailing-error turn whose session has been quiet past the grace, so the
360
- * crash branch below grace-revives it RESUME.
307
+ * revives it fresh. Fault recovery now runs in a separate pass: live,
308
+ * daemon-owned provider faults are retried by inbox nudge, while dead-pid
309
+ * crashes still fall through the ordinary resume path below.
310
+ * pid null + intent==='idle-release' dormant by choice; its pid may have
311
+ * just been cleared by boot reconciliation, but a null pid here is still
312
+ * that chosen dormancy, not a stranded relaunch — leave it, the second pass
313
+ * revives (resume) on the next unseen inbox entry (mirrors the dead-pid
314
+ * idle-release case).
361
315
  * • pid null + pi_session_id set (a relaunch in flight — reviveNode clears
362
- * pi_pid right after launch) → leave; the fresh engine re-records its pid.
316
+ * pi_pid right after launch) → leave through a boot grace; a healthy engine
317
+ * re-records its pid well within it. If the grace ELAPSES with still no pid,
318
+ * the relaunch died after the pid-clear → grace-revive RESUME on the saved
319
+ * session (else the node strands 'active' with no engine forever).
363
320
  * • pid null + pi_session_id null (NEVER booted) → normally the sub-second SDK
364
321
  * boot gap, but a broker that throws BEFORE session_start records no pid and
365
322
  * no session ever — so after a boot grace with STILL nothing, crash +
@@ -380,37 +337,62 @@ async function handleNodeLiveness(row, now, revivedThisTick) {
380
337
  if (pid != null && isPidAlive(pid)) {
381
338
  unhealthySince.delete(id);
382
339
  handleYieldStall(row, pid, now);
383
- handleErrorStall(row, pid, now);
384
340
  return;
385
341
  }
386
342
  if (pid == null) {
387
- // No supervised pid recorded. Two very different cases turn on pi_session_id:
388
- // a relaunch in flight reviveNode clears pi_pid right after launch, but
389
- // the node ALREADY booted once (pi_session_id captured), so the fresh
390
- // engine re-records its pid within a tick or two; leave it.
391
- // a NEVER-BOOTED broker (pi_session_id null) normally the sub-second SDK
392
- // boot gap, BUT a broker that THROWS before session_start (malformed
393
- // broker-launch.json, SessionManager.open on a missing .jsonl, a loader/
394
- // registry/createAgentSession failure, the fork / bare-id guards, or
395
- // broker-cli's own fatal catch) records NO pid and NO session — EVER.
396
- // With pid==null read unconditionally as "still booting" that strands the
397
- // node 'active' with no engine forever and its parent waits on a dead
398
- // child. After a boot grace with STILL no pid AND no session, crash +
343
+ // No supervised pid recorded. BOTH sub-cases run the SAME boot grace clock and
344
+ // differ only in how it ENDS, keyed on pi_session_id:
345
+ // session SET either a relaunch in flight (reviveNode clears pi_pid right
346
+ // after launch; the fresh engine re-records within a tick or two, well
347
+ // inside the grace, and the pid-alive branch above clears the clock) OR a
348
+ // relaunch whose broker DIED after the pid-clear and before it re-recorded.
349
+ // The healthy case never reaches the grace; if the grace DOES elapse with
350
+ // still no pid, the relaunch is dead → grace-revive RESUME on the saved
351
+ // session. Returning unconditionally here (the old behavior) read null+
352
+ // session as "in flight" FOREVER and stranded such a node 'active' with no
353
+ // engine its parent waiting on a dead child indefinitely.
354
+ // session NULL normally the sub-second SDK boot gap, BUT a broker that
355
+ // THROWS before session_start (malformed broker-launch.json, SessionManager
356
+ // .open on a missing .jsonl, a loader/registry/createAgentSession failure,
357
+ // the fork / bare-id guards, or broker-cli's own fatal catch) records NO
358
+ // pid and NO session — EVER. After the grace with STILL nothing, crash +
399
359
  // surfaceBootFailure up the spine (M-1).
360
+ // The 20s grace doubles as the double-spawn guard: a healthy relaunch always
361
+ // re-records its pid well within it, so neither branch can fire on one.
400
362
  const meta = getNode(id);
401
- if (meta === null || meta.pi_session_id != null) {
402
- unhealthySince.delete(id); // relaunch in flight (or identity already bound)
363
+ if (meta === null) {
364
+ unhealthySince.delete(id); // row gone from meta nothing to supervise
365
+ return;
366
+ }
367
+ // Dormant by choice: an idle-release node freed itself while dormant. Boot
368
+ // reconciliation may have just cleared its recorded pid to null, but a null
369
+ // pid here is still that chosen dormancy — NOT a stranded relaunch and NOT a
370
+ // failed boot. Honor it exactly like the dead-pid idle-release branch below:
371
+ // leave it idle; the second pass revives it (resume) the moment its inbox
372
+ // gains an unseen entry. Without this, boot reconciliation clearing the pid
373
+ // would drop this node into the boot-grace path and spuriously wake it after
374
+ // the grace with no work waiting.
375
+ if (row.intent === 'idle-release') {
376
+ unhealthySince.delete(id);
403
377
  return;
404
378
  }
405
379
  const since = unhealthySince.get(id);
406
380
  if (since === undefined) {
407
- unhealthySince.set(id, now); // start the boot-grace clock
381
+ unhealthySince.set(id, now); // start the boot grace clock
408
382
  return;
409
383
  }
410
384
  if (now - since < REVIVE_GRACE_MS)
411
385
  return; // still inside the boot grace
412
- // Boot grace elapsed, still no pid and no session → the broker never booted.
413
386
  unhealthySince.delete(id);
387
+ if (meta.pi_session_id != null) {
388
+ // Grace elapsed with a session but still no pid → a relaunch that died after
389
+ // the pid-clear, before re-record. Resume it on the saved session.
390
+ process.stderr.write(`[crtrd] revive ${id} (stranded relaunch — pid never re-recorded)\n`);
391
+ reviveNode(id, { resume: true });
392
+ revivedThisTick.add(id); // third-pass bare double-spawn guard (Maj-4)
393
+ return;
394
+ }
395
+ // Grace elapsed with no pid AND no session → the broker never booted.
414
396
  process.stderr.write(`[crtrd] boot-failed ${id} (broker exited before session_start)\n`);
415
397
  transition(id, 'crash');
416
398
  try {
@@ -421,12 +403,10 @@ async function handleNodeLiveness(row, now, revivedThisTick) {
421
403
  }
422
404
  return;
423
405
  }
424
- // The engine pid is DEAD — any pending refresh/error-stall clock is moot (the
425
- // dead-pid paths below own recovery now). Branch on intent.
406
+ // The engine pid is DEAD — the dead-pid paths below own recovery now. Branch
407
+ // on intent.
426
408
  yieldStallSince.delete(id);
427
409
  yieldTermAt.delete(id);
428
- errorTermAt.delete(id);
429
- errorTailMemo.delete(id);
430
410
  if (row.intent === 'refresh') {
431
411
  // Clean yield — or the §H force-kill above just landed — → respawn FRESH,
432
412
  // immediately (no grace wait).
@@ -456,19 +436,20 @@ async function handleNodeLiveness(row, now, revivedThisTick) {
456
436
  reviveNode(id, { resume: true });
457
437
  revivedThisTick.add(id); // third-pass bare double-spawn guard (Maj-4)
458
438
  }
459
- /** Fail loud for a drifted/broken wake (design §6.6/Q5): wake the ARMER DIRECTLY
460
- * via appendInbox — NOT pushUrgent, which fans to subscribersOf(owner), and a
461
- * DETACHED spawn has no subscribers (so the armer would never be reached); the
462
- * literal {from:null} is also a type error for pushUrgent. Deduped per wakeup_id
463
- * (notify once, suppress until the next success/cancel via notifiedWakeFailures)
464
- * so a broken spawn-cron can't flood the unrotated inbox.jsonl. Falls back to a
465
- * loud daemon-log line when the owner no longer resolves to a node. */
466
- function failLoudWake(w, label, body) {
467
- if (notifiedWakeFailures.has(w.wakeup_id))
439
+ /** Fail loud for a drifted/broken trigger (design §6.6/Q5): wake the ARMER
440
+ * DIRECTLY via appendInbox — NOT pushUrgent, which fans to subscribersOf(owner),
441
+ * and a DETACHED spawn has no subscribers (so the armer would never be
442
+ * reached); the literal {from:null} is also a type error for pushUrgent.
443
+ * Deduped per trigger_id (notify once, suppress until the next success/cancel
444
+ * via notifiedTriggerFailures) so a broken spawn-cron can't flood the
445
+ * unrotated inbox.jsonl. Falls back to a loud daemon-log line when the owner
446
+ * no longer resolves to a node. */
447
+ function failLoudTrigger(t, label, body) {
448
+ if (notifiedTriggerFailures.has(t.trigger_id))
468
449
  return;
469
- notifiedWakeFailures.add(w.wakeup_id);
470
- if (getRow(w.owner_id) !== null) {
471
- appendInbox(w.owner_id, {
450
+ notifiedTriggerFailures.add(t.trigger_id);
451
+ if (getRow(t.owner_id) !== null) {
452
+ appendInbox(t.owner_id, {
472
453
  from: null,
473
454
  tier: 'urgent',
474
455
  kind: 'urgent',
@@ -477,7 +458,63 @@ function failLoudWake(w, label, body) {
477
458
  });
478
459
  }
479
460
  else {
480
- process.stderr.write(`[crtrd] wake ${w.wakeup_id} failed (owner ${w.owner_id} gone): ${body}\n`);
461
+ process.stderr.write(`[crtrd] trigger ${t.trigger_id} failed (owner ${t.owner_id} gone): ${body}\n`);
462
+ }
463
+ }
464
+ /** Notify the owner once for a settled (already-consumed) predicate outcome —
465
+ * never deduped like failLoudTrigger, because the trigger is gone by the time
466
+ * this fires so there is no repeat-notification risk to guard against. */
467
+ function notifyOwnerUrgent(t, label, body) {
468
+ if (getRow(t.owner_id) !== null) {
469
+ appendInbox(t.owner_id, { from: null, tier: 'urgent', kind: 'urgent', label, data: { body } });
470
+ }
471
+ else {
472
+ process.stderr.write(`[crtrd] trigger ${t.trigger_id} notice undelivered (owner ${t.owner_id} gone): ${body}\n`);
473
+ }
474
+ }
475
+ /** Settle a predicate outcome onto the SAME enactment paths pass 3 uses
476
+ * (appendInbox / spawnChild) — fresh_revive/deadline_message never reach here
477
+ * (the command surface never pairs `--when` with those action_modes; see the
478
+ * spec's valid flag matrix). stdout_overflow/target_gone are terminal
479
+ * failures the trigger was already consumed for by predicate-eval.ts — this
480
+ * only sends the owner notice. */
481
+ async function handlePredicateOutcome(outcome) {
482
+ const t = outcome.trigger;
483
+ if (outcome.kind === 'stdout_overflow') {
484
+ notifyOwnerUrgent(t, '⚠ predicate stdout too large', `Trigger ${t.trigger_id}'s predicate exceeded the 16 KiB stdout limit — the action was not delivered and the trigger has been canceled.`);
485
+ return;
486
+ }
487
+ if (outcome.kind === 'target_gone') {
488
+ notifyOwnerUrgent(t, '⚠ predicate target gone', `Trigger ${t.trigger_id}'s target no longer exists — the trigger has been canceled.`);
489
+ return;
490
+ }
491
+ // outcome.kind === 'fired'
492
+ if (t.action === 'msg' && t.action_mode === 'inbox_message') {
493
+ const p = t.payload;
494
+ const body = (p.body ?? outcome.stdout).trim();
495
+ if (body === '') {
496
+ notifyOwnerUrgent(t, '⚠ predicate fired with no message', `Trigger ${t.trigger_id}'s predicate exited 0 but produced no body (no supplied body, empty stdout) — nothing was delivered.`);
497
+ return;
498
+ }
499
+ if (t.node_id == null)
500
+ return; // integrity backstop only — armTrigger requires a target here
501
+ appendInbox(t.node_id, {
502
+ from: t.owner_id ?? null,
503
+ tier: p.tier ?? 'normal',
504
+ kind: 'message',
505
+ label: `⏰ predicate fired — ${p.label}`,
506
+ data: { body },
507
+ });
508
+ }
509
+ else if (t.action === 'new' && t.action_mode === 'node_birth') {
510
+ const recipe = t.payload;
511
+ try {
512
+ await spawnChild({ ...recipe, wakeOrigin: wakeOriginFrom(t) });
513
+ }
514
+ catch (err) {
515
+ failLoudTrigger(t, '⚠ deferred predicate spawn failed', `Deferred spawn (${recipe.kind} @ ${recipe.cwd}) failed after its predicate fired: ` +
516
+ `${err.message}\n\nRe-home (fix the cwd/parent) or re-arm the trigger.`);
517
+ }
481
518
  }
482
519
  }
483
520
  // How long a dead node's on-disk record must have been QUIET (no meta/telemetry
@@ -578,11 +615,12 @@ function gcStaleFocuses() {
578
615
  // Pidfile
579
616
  // ---------------------------------------------------------------------------
580
617
  function pidfilePath() {
581
- return join(crtrHome(), 'crtrd.pid');
618
+ const override = process.env['CRTR_PIDFILE'];
619
+ return override !== undefined && override !== '' ? override : join(crtrHome(), 'crtrd.pid');
582
620
  }
583
621
  function writePidfile() {
584
- // Ensure the canvas home exists before writing.
585
- mkdirSync(crtrHome(), { recursive: true });
622
+ // Ensure the pidfile parent exists before writing.
623
+ mkdirSync(dirname(pidfilePath()), { recursive: true });
586
624
  writeFileSync(pidfilePath(), String(process.pid), 'utf8');
587
625
  }
588
626
  function removePidfile() {
@@ -615,7 +653,18 @@ export function isDaemonRunning() {
615
653
  // ---------------------------------------------------------------------------
616
654
  // Supervisor tick
617
655
  // ---------------------------------------------------------------------------
656
+ /** Supervision tick over the daemon's current live set. */
618
657
  export async function superviseTick(now = Date.now()) {
658
+ // Auth-reload fan FIRST, independent of node supervision: a change to the
659
+ // shared auth.json propagates a live credential reload to every broker. Kept
660
+ // ahead of the listNodes guard below so a transient list error in the
661
+ // supervision passes never skips an auth fan (it does its own enumeration).
662
+ try {
663
+ await handleAuthReload(now);
664
+ }
665
+ catch (err) {
666
+ process.stderr.write(`[crtrd] handleAuthReload error: ${err.message}\n`);
667
+ }
619
668
  let rows;
620
669
  try {
621
670
  rows = listNodes({ status: ['active', 'idle'] });
@@ -681,143 +730,142 @@ export async function superviseTick(now = Date.now()) {
681
730
  process.stderr.write(`[crtrd] error polling inbox ${row.node_id}: ${err.message}\n`);
682
731
  }
683
732
  }
684
- // Third pass: FIRE DUE SCHEDULED WAKES (the wakeups engine, migration v7).
733
+ // Third pass: FIRE DUE CLOCK TRIGGERS (the triggers engine, migration v9).
685
734
  // Runs immediately AFTER the inbox second pass — the ordering is load-bearing
686
735
  // (design §6.4): a same-tick inbox revive runs cancelDeadlinesFor (inside
687
- // reviveNode) BEFORE this pass's dueWakes query, so an event that wins a
688
- // deadline deletes its row before it can fire. The pass-2 inbox loop above is
689
- // otherwise untouched (design D3) — it stays the generic wake-on-message path
690
- // that noted/deadline rely on; the only addition is the revivedThisTick.add
691
- // observation that the bare branch below needs to avoid a double-spawn.
736
+ // reviveNode) BEFORE this pass's dueClockTriggers query, so an event that wins
737
+ // a deadline deletes its row before it can fire. The pass-2 inbox loop above
738
+ // is otherwise untouched (design D3) — it stays the generic wake-on-message
739
+ // path that inbox_message/deadline_message rely on; the only addition is the
740
+ // revivedThisTick.add observation that the fresh_revive branch below needs to
741
+ // avoid a double-spawn.
692
742
  // For each due row, in fire_at order, settle the row FIRST (advance-or-consume
693
- // — crash-safety, design D4) THEN enact by kind, wrapped per-row so one bad
694
- // wake never kills the tick.
743
+ // — crash-safety, design D4) THEN enact by action/action_mode, wrapped per-row
744
+ // so one bad trigger never kills the tick.
695
745
  const nowIso = new Date(now).toISOString();
696
746
  const nowDate = new Date(now);
697
747
  let due;
698
748
  try {
699
- due = dueWakes(nowIso);
749
+ due = dueClockTriggers(nowIso);
700
750
  }
701
751
  catch (err) {
702
- process.stderr.write(`[crtrd] dueWakes error: ${err.message}\n`);
752
+ process.stderr.write(`[crtrd] dueClockTriggers error: ${err.message}\n`);
703
753
  due = [];
704
754
  }
705
- for (const w of due) {
755
+ for (const t of due) {
706
756
  try {
707
- // 1. Advance-or-consume FIRST (design D4): settle the row's pending state
708
- // before ANY side effect, so a daemon crash mid-fire can never double-
709
- // fire (a double SPAWN is the worst case — structurally prevented here).
710
- if (w.recur == null) {
711
- consumeWake(w.wakeup_id);
757
+ // 1. Settle FIRST: crash-safety advance/consume the trigger before
758
+ // enacting it, so a crash between settle and enact never re-fires.
759
+ if (t.recur == null) {
760
+ consumeTrigger(t.trigger_id);
712
761
  }
713
762
  else {
714
763
  let nextFire;
715
764
  try {
716
- nextFire = nextSlotAfter(w.recur, nowDate);
765
+ nextFire = nextSlotAfter(t.recur, nowDate);
717
766
  }
718
767
  catch (err) {
719
- // The recur is unparseable (parseCadence validates at arm time, so this
720
- // is a rare backstop a corrupted/foreign row). Leaving a past-fire_at
721
- // row pending would re-qualify it EVERY tick (silent CPU spin, enact
722
- // never reached), so quarantine it (consume) + fail loud ONCE; never
723
- // re-query it each tick (Min-8).
724
- consumeWake(w.wakeup_id);
725
- failLoudWake(w, '⚠ recurrence quarantined', `Scheduled wake ${w.wakeup_id} has an unparseable recurrence and was removed: ` +
768
+ consumeTrigger(t.trigger_id);
769
+ failLoudTrigger(t, '⚠ recurrence quarantined', `Scheduled trigger ${t.trigger_id} has an unparseable recurrence and was removed: ` +
726
770
  `${err.message}\n\nRe-arm it with a valid cadence.`);
727
771
  continue;
728
772
  }
729
- advanceWake(w.wakeup_id, nextFire);
773
+ advanceTrigger(t.trigger_id, nextFire);
730
774
  }
731
- // 2. Enact by kind.
732
- if (w.kind === 'bare') {
733
- // A bare wake leaves NO inbox entry, so pass 2 can never wake it — it
734
- // must revive DIRECTLY with resume:false (re-reads roadmap; AC-N2).
735
- const target = w.node_id == null ? null : getRow(w.node_id);
736
- if (target === null)
737
- continue; // target gone (the FK cascade reaped it)
738
- // Same-tick double-spawn guard (Maj-4): pass 1/2 (or an earlier bare row
739
- // this pass) may have revived this node THIS tick — reviveNode clears
740
- // pi_pid to NULL before the fresh pi re-records it, so the pi_pid==null
741
- // liveness check below would falsely read "not live" and a second
742
- // reviveNode would launch a SECOND pi on the same .jsonl (corruption).
743
- // (Pane-existence is the WRONG guard — it would no-op a frozen-focus bare
744
- // wake, which is pane-alive/pi-dead by design.)
775
+ // 2. Enact by action/action_mode.
776
+ if (t.action === 'msg' && t.action_mode === 'fresh_revive') {
777
+ const target = t.node_id == null ? null : getRow(t.node_id);
778
+ if (target === null) {
779
+ notifyOwnerUrgent(t, '⚠ scheduled trigger target gone', `Trigger ${t.trigger_id}'s target no longer exists no revive happened.`);
780
+ continue;
781
+ }
745
782
  if (revivedThisTick.has(target.node_id))
746
783
  continue;
747
- // pi live → no-op (AC-E3 bare): an already-awake node needs no revive.
748
784
  if (target.pi_pid != null && isPidAlive(target.pi_pid))
749
785
  continue;
750
786
  process.stderr.write(`[crtrd] wake ${target.node_id} (bare alarm)\n`);
751
- // wakeReason carries the timer provenance so the fresh-revive kickoff
752
- // leads with a <crtr-wake> block (Invariant B/D: the node learns a clock,
753
- // not an event, woke it) instead of a generic context-refresh framing.
754
- reviveNode(target.node_id, { resume: false, wakeReason: wakeOriginFrom(w) });
787
+ reviveNode(target.node_id, { resume: false, wakeReason: wakeOriginFrom(t) });
755
788
  revivedThisTick.add(target.node_id);
756
789
  }
757
- else if (w.kind === 'noted') {
758
- // Deliver the note; the UNMODIFIED pass 2 wakes the dormant target next
759
- // tick (AC-N1), or its live in-process watcher delivers it (AC-E3 noted).
760
- if (w.node_id == null)
790
+ else if (t.action === 'msg' && t.action_mode === 'inbox_message') {
791
+ if (t.node_id == null) {
792
+ notifyOwnerUrgent(t, '⚠ scheduled trigger target gone', `Trigger ${t.trigger_id}'s target no longer exists nothing was delivered.`);
761
793
  continue;
762
- const p = w.payload;
763
- // Mark the delivery as a SCHEDULED wake (Invariant D): the woken node sees
764
- // only the rendered digest (inbox inlines label/body, never arbitrary
765
- // data keys), so the timer signal MUST ride the visible label — the same
766
- // family deadline uses — so a noted wake is distinguishable from a plain
767
- // `node msg`, not indistinguishable from it.
768
- appendInbox(w.node_id, {
769
- from: w.owner_id ?? null,
770
- tier: 'normal',
794
+ }
795
+ const p = t.payload;
796
+ appendInbox(t.node_id, {
797
+ from: t.owner_id ?? null,
798
+ tier: p.tier ?? 'normal',
771
799
  kind: 'message',
772
800
  label: `⏰ scheduled wake — ${p.label}`,
773
- data: { body: p.body },
801
+ data: { body: p.body ?? '' },
774
802
  });
775
803
  }
776
- else if (w.kind === 'deadline') {
777
- // Same delivery as noted but URGENT tier. The woken node sees only the
778
- // RENDERED digest (inbox inlines label/body, NEVER arbitrary data keys),
779
- // so the timeout signal MUST ride the visible label/body (Maj-8);
780
- // data.timeout is a machine-readable mirror only. body is always non-
781
- // empty (the surface supplies a default timeout note when none is
782
- // authored, Maj-7). One-shot — already consumed in step 1.
783
- if (w.node_id == null)
804
+ else if (t.action === 'msg' && t.action_mode === 'deadline_message') {
805
+ if (t.node_id == null) {
806
+ notifyOwnerUrgent(t, '⚠ scheduled trigger target gone', `Trigger ${t.trigger_id}'s target no longer exists — nothing was delivered.`);
784
807
  continue;
785
- const p = w.payload;
786
- appendInbox(w.node_id, {
787
- from: w.owner_id ?? null,
808
+ }
809
+ const p = t.payload;
810
+ appendInbox(t.node_id, {
811
+ from: t.owner_id ?? null,
788
812
  tier: 'urgent',
789
813
  kind: 'message',
790
814
  label: `⏰ deadline reached — ${p.label}`,
791
815
  data: { body: p.body, timeout: true },
792
816
  });
793
817
  }
794
- else if (w.kind === 'spawn') {
795
- // Re-derives LaunchSpec live (AC-W2); payload.parent is the non-null
796
- // resolved armer id (T2/T7 guarantee it), so spawnChild never throws the
797
- // "requires a calling node" error even for a --root recipe.
798
- const recipe = w.payload;
818
+ else if (t.action === 'new' && t.action_mode === 'node_birth') {
819
+ const recipe = t.payload;
799
820
  try {
800
- // Spread in the wake provenance at fire time (in-memory only; never the
801
- // stored recipe) so the born node's kickoff leads with a <crtr-wake>
802
- // block — it learns, by construction, that a timer birthed it (and, for
803
- // a spawn-cron, that it is one run of a standing job).
804
- spawnChild({ ...recipe, wakeOrigin: wakeOriginFrom(w) });
805
- notifiedWakeFailures.delete(w.wakeup_id); // success clears the dedup latch
821
+ await spawnChild({ ...recipe, wakeOrigin: wakeOriginFrom(t) });
822
+ notifiedTriggerFailures.delete(t.trigger_id);
806
823
  }
807
824
  catch (err) {
808
- // Fail loud by waking the ARMER DIRECTLY (design §6.6/Q5). The row was
809
- // already settled in step 1, so this is never a hot retry loop; a
810
- // permanently-broken spawn-cron stays deduped-noisy until cancel.
811
- failLoudWake(w, '⚠ deferred spawn failed', `Deferred spawn (${recipe.kind} @ ${recipe.cwd}) failed: ` +
812
- `${err.message}\n\nRe-home (fix the cwd/parent) or re-arm the wake.`);
825
+ failLoudTrigger(t, '⚠ deferred spawn failed', `Deferred spawn (${recipe.kind} @ ${recipe.cwd}) failed: ` +
826
+ `${err.message}\n\nRe-home (fix the cwd/parent) or re-arm the trigger.`);
813
827
  }
814
828
  }
815
829
  }
816
830
  catch (err) {
817
- // One bad wake never kills the tick.
818
- process.stderr.write(`[crtrd] error firing wake ${w.wakeup_id}: ${err.message}\n`);
831
+ process.stderr.write(`[crtrd] error firing trigger ${t.trigger_id}: ${err.message}\n`);
819
832
  }
820
833
  }
834
+ // Pass 3a: recover stale predicate leases stranded by a PRIOR daemon
835
+ // instance (crash/restart mid-evaluation) — BEFORE 3b/3c, so a row a dead
836
+ // daemon left `eval_state='running'` forever can rejoin the idle pool
837
+ // instead of being wedged out of duePredicateTriggers' idle-only filter
838
+ // (spec §Daemon-behavior step 1, acceptance criterion 9: survives restart).
839
+ try {
840
+ recoverStalePredicateLeases(now, predicateCapacity());
841
+ }
842
+ catch (err) {
843
+ process.stderr.write(`[crtrd] recoverStalePredicateLeases error: ${err.message}\n`);
844
+ }
845
+ // Pass 3b: wall-clock predicate timeouts — reap regardless of eval_state,
846
+ // BEFORE selecting fresh evaluations (so a timed-out row can never also be
847
+ // evaluated this same tick — consumeTrigger removes it from the due query).
848
+ try {
849
+ reapTimedOutPredicates(now, (t) => {
850
+ notifyOwnerUrgent(t, '⚠ predicate timed out', `Trigger ${t.trigger_id}'s wall-clock timeout was reached before its predicate ever fired — it has been canceled.`);
851
+ });
852
+ }
853
+ catch (err) {
854
+ process.stderr.write(`[crtrd] reapTimedOutPredicates error: ${err.message}\n`);
855
+ }
856
+ // Pass 3c: kick off due predicate evaluations. Fire-and-forget — settlement
857
+ // happens async via onDone, decoupled from this tick (never awaited; a slow/
858
+ // hung predicate must never block supervision, spec §Predicate triggers).
859
+ try {
860
+ evaluateDuePredicates(now, (outcome) => {
861
+ handlePredicateOutcome(outcome).catch((err) => {
862
+ process.stderr.write(`[crtrd] predicate outcome error: ${err.message}\n`);
863
+ });
864
+ });
865
+ }
866
+ catch (err) {
867
+ process.stderr.write(`[crtrd] evaluateDuePredicates error: ${err.message}\n`);
868
+ }
821
869
  // Fourth pass: reap the leftover placement of long-dead nodes (Bug 3), then
822
870
  // sweep focus rows whose pane died outside the sanctioned teardown paths
823
871
  // (Bug 5). Reap first so the GC also catches any focus row a reaped pane
@@ -825,6 +873,25 @@ export async function superviseTick(now = Date.now()) {
825
873
  // re-anchored.
826
874
  reapDeadResidue(now);
827
875
  gcStaleFocuses();
876
+ // Fifth pass: count-based auto-prune, throttled to once per PRUNE_INTERVAL_MS
877
+ // (NOT every 2s tick — it's a full-canvas DB sweep). Keeps the AUTO_PRUNE_MAX
878
+ // most-recently-active nodes; live nodes are never deleted (pruneToLimit's
879
+ // floor is max(AUTO_PRUNE_MAX, liveCount)). Wrapped so a sweep failure never
880
+ // crashes the tick; the tick is already serialized (recursive setTimeout), so
881
+ // this runs sequentially within it.
882
+ if (now - lastPruneAt >= PRUNE_INTERVAL_MS) {
883
+ lastPruneAt = now;
884
+ try {
885
+ const before = listNodes().length;
886
+ const { pruned } = pruneToLimit({ maxNodes: AUTO_PRUNE_MAX });
887
+ if (pruned.length > 0) {
888
+ process.stderr.write(`[crtrd] auto-prune: removed ${pruned.length} nodes (kept ${before - pruned.length})\n`);
889
+ }
890
+ }
891
+ catch (err) {
892
+ process.stderr.write(`[crtrd] auto-prune error: ${err.message}\n`);
893
+ }
894
+ }
828
895
  }
829
896
  /** Start the supervisor loop.
830
897
  *
@@ -841,8 +908,21 @@ export function runDaemon(opts = {}) {
841
908
  process.exit(0);
842
909
  }
843
910
  const interval = opts.intervalMs ?? DEFAULT_INTERVAL_MS;
911
+ // Once, before the first tick ever inspects a single `pi_pid`: detect a boot
912
+ // change (a host reboot, or a sandbox/VM destroy+recreate — canvas.db is
913
+ // durable and survives either, but every `pi_pid` it carries is a raw OS pid
914
+ // from the process table THAT reset) and clear every stale pid up front. This
915
+ // must run before the tick loop, not lazily inside reviveNode: the daemon's
916
+ // OWN liveness poll (handleNodeLiveness) treats `isPidAlive(pid) === true` as
917
+ // "leave it, nothing to revive" and never calls reviveNode at all — a
918
+ // pid-reuse collision on the first post-boot tick would silently no-op
919
+ // forever with no revive attempt to even hit reviveNode's own reconcile call.
920
+ const { changed, cleared } = reconcileBootLiveness();
921
+ if (changed) {
922
+ process.stderr.write(`[crtrd] boot change detected — cleared ${cleared.length} stale pi_pid(s) recorded before this boot\n`);
923
+ }
844
924
  writePidfile();
845
- process.stderr.write(`[crtrd] started (pid ${process.pid}, interval ${interval}ms)\n`);
925
+ log.info(`started (pid ${process.pid}, interval ${interval}ms)`);
846
926
  let running = true;
847
927
  // Cleanup — idempotent.
848
928
  const cleanup = () => {