@rubytech/create-maxy-code 0.1.51 → 0.1.58

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 (304) hide show
  1. package/dist/__tests__/platform-port-stamp.test.js +24 -0
  2. package/dist/index.js +5 -2
  3. package/dist/port-resolution.js +2 -0
  4. package/package.json +1 -1
  5. package/payload/platform/lib/require-port-env/dist/index.d.ts +31 -0
  6. package/payload/platform/lib/require-port-env/dist/index.d.ts.map +1 -0
  7. package/payload/platform/lib/require-port-env/dist/index.js +52 -0
  8. package/payload/platform/lib/require-port-env/dist/index.js.map +1 -0
  9. package/payload/platform/lib/require-port-env/src/index.ts +56 -0
  10. package/payload/platform/lib/require-port-env/tsconfig.json +8 -0
  11. package/payload/platform/package-lock.json +0 -1
  12. package/payload/platform/package.json +2 -3
  13. package/payload/platform/plugins/admin/PLUGIN.md +16 -3
  14. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +183 -144
  15. package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +180 -99
  16. package/payload/platform/plugins/admin/mcp/dist/index.js +20 -12
  17. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  18. package/payload/platform/plugins/brochures/PLUGIN.md +2 -0
  19. package/payload/platform/plugins/brochures/skills/property-market-report/SKILL.md +100 -0
  20. package/payload/platform/plugins/brochures/skills/property-market-report/references/render.py +267 -0
  21. package/payload/platform/plugins/brochures/skills/property-market-report/references/template.html +266 -0
  22. package/payload/platform/plugins/brochures/skills/property-socials/SKILL.md +141 -0
  23. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts.map +1 -1
  24. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js +2 -1
  25. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js.map +1 -1
  26. package/payload/platform/plugins/docs/references/admin-session.md +33 -3
  27. package/payload/platform/plugins/docs/references/deployment.md +25 -0
  28. package/payload/platform/plugins/docs/references/internals.md +26 -0
  29. package/payload/platform/plugins/docs/references/platform.md +3 -1
  30. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  31. package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
  32. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +1 -1
  33. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +2 -1
  34. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -1
  35. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  36. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/index.js +6 -1
  38. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  39. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.d.ts +2 -0
  40. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.d.ts.map +1 -0
  41. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +107 -0
  42. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -0
  43. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts +4 -2
  44. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
  45. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +22 -13
  46. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
  47. package/payload/platform/plugins/memory/references/graph-primitives.md +42 -0
  48. package/payload/platform/plugins/memory/skills/concept-synthesis/SKILL.md +1 -1
  49. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -2
  50. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +1 -1
  51. package/payload/platform/plugins/property-data/.claude-plugin/plugin.json +17 -0
  52. package/payload/platform/plugins/property-data/PLUGIN.md +100 -0
  53. package/payload/platform/plugins/property-data/mcp/dist/index.d.ts +2 -0
  54. package/payload/platform/plugins/property-data/mcp/dist/index.d.ts.map +1 -0
  55. package/payload/platform/plugins/property-data/mcp/dist/index.js +153 -0
  56. package/payload/platform/plugins/property-data/mcp/dist/index.js.map +1 -0
  57. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.d.ts +3 -0
  58. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.d.ts.map +1 -0
  59. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.js +72 -0
  60. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.js.map +1 -0
  61. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.d.ts +5 -0
  62. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.d.ts.map +1 -0
  63. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.js +38 -0
  64. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.js.map +1 -0
  65. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts +29 -0
  66. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts.map +1 -0
  67. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.js +112 -0
  68. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.js.map +1 -0
  69. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.d.ts +14 -0
  70. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.d.ts.map +1 -0
  71. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.js +20 -0
  72. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.js.map +1 -0
  73. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.d.ts +4 -0
  74. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.d.ts.map +1 -0
  75. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.js +19 -0
  76. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.js.map +1 -0
  77. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.d.ts +4 -0
  78. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.d.ts.map +1 -0
  79. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.js +10 -0
  80. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.js.map +1 -0
  81. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.d.ts +5 -0
  82. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.d.ts.map +1 -0
  83. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.js +43 -0
  84. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.js.map +1 -0
  85. package/payload/platform/plugins/property-data/mcp/package-lock.json +2566 -0
  86. package/payload/platform/plugins/property-data/mcp/package.json +21 -0
  87. package/payload/platform/plugins/property-data/mcp/src/__tests__/key-roundtrip.test.ts +107 -0
  88. package/payload/platform/plugins/property-data/mcp/src/__tests__/propertydata-api.test.ts +184 -0
  89. package/payload/platform/plugins/property-data/mcp/src/__tests__/schema-parity.test.ts +48 -0
  90. package/payload/platform/plugins/property-data/mcp/src/index.ts +249 -0
  91. package/payload/platform/plugins/property-data/mcp/src/lib/crypto.ts +79 -0
  92. package/payload/platform/plugins/property-data/mcp/src/lib/neo4j.ts +47 -0
  93. package/payload/platform/plugins/property-data/mcp/src/lib/propertydata-api.ts +135 -0
  94. package/payload/platform/plugins/property-data/mcp/src/tools/endpoints.ts +27 -0
  95. package/payload/platform/plugins/property-data/mcp/src/tools/key-deregister.ts +21 -0
  96. package/payload/platform/plugins/property-data/mcp/src/tools/key-list.ts +10 -0
  97. package/payload/platform/plugins/property-data/mcp/src/tools/key-register.ts +58 -0
  98. package/payload/platform/plugins/property-data/mcp/tsconfig.json +20 -0
  99. package/payload/platform/plugins/property-data/mcp/vitest.config.ts +8 -0
  100. package/payload/platform/plugins/property-data/skills/property-data/SKILL.md +58 -0
  101. package/payload/platform/plugins/waitlist/PLUGIN.md +6 -8
  102. package/payload/platform/plugins/waitlist/mcp/dist/index.js +33 -0
  103. package/payload/platform/plugins/waitlist/mcp/dist/index.js.map +1 -1
  104. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.d.ts +16 -0
  105. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.d.ts.map +1 -0
  106. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.js +58 -0
  107. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.js.map +1 -0
  108. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts +34 -0
  109. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts.map +1 -0
  110. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js +129 -0
  111. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js.map +1 -0
  112. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.d.ts +12 -18
  113. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.d.ts.map +1 -1
  114. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.js +89 -86
  115. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.js.map +1 -1
  116. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.d.ts.map +1 -1
  117. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.js +15 -53
  118. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.js.map +1 -1
  119. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -0
  120. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +5 -5
  121. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  122. package/payload/platform/plugins/workflows/PLUGIN.md +10 -176
  123. package/payload/platform/plugins/workflows/mcp/dist/index.js +14 -142
  124. package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
  125. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.d.ts +1 -88
  126. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.d.ts.map +1 -1
  127. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.js +0 -86
  128. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.js.map +1 -1
  129. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.d.ts +5 -12
  130. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.d.ts.map +1 -1
  131. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.js +5 -46
  132. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.js.map +1 -1
  133. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.d.ts +1 -16
  134. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.d.ts.map +1 -1
  135. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +39 -75
  136. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
  137. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts +8 -21
  138. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts.map +1 -1
  139. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +39 -266
  140. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
  141. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts +3 -8
  142. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts.map +1 -1
  143. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js +3 -10
  144. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js.map +1 -1
  145. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.d.ts.map +1 -1
  146. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js +38 -86
  147. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js.map +1 -1
  148. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.d.ts.map +1 -1
  149. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js +8 -26
  150. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js.map +1 -1
  151. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
  152. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +1 -2
  153. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
  154. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  155. package/payload/platform/services/claude-session-manager/dist/http-server.js +204 -23
  156. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  157. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +39 -1
  158. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  159. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +109 -10
  160. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  161. package/payload/platform/services/claude-session-manager/dist/reaper.d.ts.map +1 -1
  162. package/payload/platform/services/claude-session-manager/dist/reaper.js +11 -0
  163. package/payload/platform/services/claude-session-manager/dist/reaper.js.map +1 -1
  164. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +21 -0
  165. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
  166. package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
  167. package/payload/platform/services/claude-session-manager/vitest.config.ts +14 -0
  168. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -0
  169. package/payload/platform/templates/agents/admin/SOUL.md +3 -1
  170. package/payload/premium-plugins/real-agent/BUNDLE.md +5 -3
  171. package/payload/premium-plugins/real-agent/agents/negotiator.md +1 -1
  172. package/payload/premium-plugins/real-agent/agents/valuer.md +1 -1
  173. package/payload/premium-plugins/real-agent/plugins/.claude-plugin/marketplace.json +5 -0
  174. package/payload/premium-plugins/real-agent/plugins/brochures/PLUGIN.md +2 -0
  175. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-market-report/SKILL.md +100 -0
  176. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-market-report/references/render.py +267 -0
  177. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-market-report/references/template.html +266 -0
  178. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-socials/SKILL.md +141 -0
  179. package/payload/premium-plugins/real-agent/plugins/property-data/.claude-plugin/plugin.json +17 -0
  180. package/payload/premium-plugins/real-agent/plugins/property-data/PLUGIN.md +100 -0
  181. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.d.ts +2 -0
  182. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.d.ts.map +1 -0
  183. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js +153 -0
  184. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js.map +1 -0
  185. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.d.ts +3 -0
  186. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.d.ts.map +1 -0
  187. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.js +72 -0
  188. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.js.map +1 -0
  189. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.d.ts +5 -0
  190. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.d.ts.map +1 -0
  191. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.js +38 -0
  192. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.js.map +1 -0
  193. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts +29 -0
  194. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts.map +1 -0
  195. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.js +112 -0
  196. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.js.map +1 -0
  197. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.d.ts +14 -0
  198. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.d.ts.map +1 -0
  199. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.js +20 -0
  200. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.js.map +1 -0
  201. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.d.ts +4 -0
  202. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.d.ts.map +1 -0
  203. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.js +19 -0
  204. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.js.map +1 -0
  205. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.d.ts +4 -0
  206. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.d.ts.map +1 -0
  207. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.js +10 -0
  208. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.js.map +1 -0
  209. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.d.ts +5 -0
  210. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.d.ts.map +1 -0
  211. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.js +43 -0
  212. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.js.map +1 -0
  213. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/package-lock.json +2566 -0
  214. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/package.json +21 -0
  215. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/__tests__/key-roundtrip.test.ts +107 -0
  216. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/__tests__/propertydata-api.test.ts +184 -0
  217. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/__tests__/schema-parity.test.ts +48 -0
  218. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/index.ts +249 -0
  219. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/lib/crypto.ts +79 -0
  220. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/lib/neo4j.ts +47 -0
  221. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/lib/propertydata-api.ts +135 -0
  222. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/endpoints.ts +27 -0
  223. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/key-deregister.ts +21 -0
  224. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/key-list.ts +10 -0
  225. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/key-register.ts +58 -0
  226. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/tsconfig.json +20 -0
  227. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/vitest.config.ts +8 -0
  228. package/payload/premium-plugins/real-agent/plugins/property-data/skills/property-data/SKILL.md +58 -0
  229. package/payload/server/{chunk-CWI7NOWK.js → chunk-2IKQERHN.js} +32 -4
  230. package/payload/server/maxy-edge.js +53 -25
  231. package/payload/server/public/assets/admin-2ZJmzJ_g.js +216 -0
  232. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DGHlapUl.js → architectureDiagram-Q4EWVU46-DgfgldJT.js} +1 -1
  233. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Dgnf9J14.js → blockDiagram-DXYQGD6D-agu8GDzA.js} +1 -1
  234. package/payload/server/public/assets/{brand-CtilcX3W.css → brand-BDASZqMG.css} +1 -1
  235. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-GBVmghhJ.js → c4Diagram-AHTNJAMY-CmNsUmAe.js} +1 -1
  236. package/payload/server/public/assets/channel-DXGOX55q.js +1 -0
  237. package/payload/server/public/assets/{chunk-336JU56O-CSVC_J3A.js → chunk-336JU56O-D9Uts7k9.js} +2 -2
  238. package/payload/server/public/assets/{chunk-426QAEUC-CK1Z0942.js → chunk-426QAEUC-D4ABqXMn.js} +1 -1
  239. package/payload/server/public/assets/{chunk-4TB4RGXK-CaqJYLxL.js → chunk-4TB4RGXK-D1KE4OAX.js} +1 -1
  240. package/payload/server/public/assets/{chunk-5FUZZQ4R-57BmPy_B.js → chunk-5FUZZQ4R-CAh0GXe2.js} +1 -1
  241. package/payload/server/public/assets/{chunk-5PVQY5BW-Ud03uYx_.js → chunk-5PVQY5BW-DBHa6HOv.js} +1 -1
  242. package/payload/server/public/assets/{chunk-EDXVE4YY-p5KO0PoG.js → chunk-EDXVE4YY-BDC-6mL3.js} +1 -1
  243. package/payload/server/public/assets/{chunk-ENJZ2VHE-CkxgLujt.js → chunk-ENJZ2VHE-CH3uROkW.js} +1 -1
  244. package/payload/server/public/assets/{chunk-ICPOFSXX-DwMkY8p7.js → chunk-ICPOFSXX-BzZf0nAw.js} +1 -1
  245. package/payload/server/public/assets/{chunk-OYMX7WX6-CyYOUKBw.js → chunk-OYMX7WX6-BrLHrI6O.js} +1 -1
  246. package/payload/server/public/assets/{chunk-U2HBQHQK-Dk5rfJM6.js → chunk-U2HBQHQK-Bw4UkLe_.js} +1 -1
  247. package/payload/server/public/assets/{chunk-X2U36JSP-D0qCg9Nq.js → chunk-X2U36JSP-23xgdk05.js} +1 -1
  248. package/payload/server/public/assets/{chunk-YZCP3GAM-C0uFHrdT.js → chunk-YZCP3GAM-BA8iGgRa.js} +1 -1
  249. package/payload/server/public/assets/{chunk-ZZ45TVLE-C7lSyGRs.js → chunk-ZZ45TVLE-B-ol4EgR.js} +1 -1
  250. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DTuuDxpK.js +1 -0
  251. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CIw8RU0q.js +1 -0
  252. package/payload/server/public/assets/clone-O4ZyuvYl.js +1 -0
  253. package/payload/server/public/assets/{dagre-BWZ4wr8y.js → dagre--kXszEIb.js} +1 -1
  254. package/payload/server/public/assets/{dagre-KV5264BT-C7mpqRpw.js → dagre-KV5264BT-amN1uU2d.js} +1 -1
  255. package/payload/server/public/assets/data-DlmoKxmN.js +1 -0
  256. package/payload/server/public/assets/{device-url-actions-347cMDY4.js → device-url-actions-CPoz5fqz.js} +1 -1
  257. package/payload/server/public/assets/{diagram-5BDNPKRD-BcQRB7_3.js → diagram-5BDNPKRD-Cwizs9tP.js} +1 -1
  258. package/payload/server/public/assets/{diagram-G4DWMVQ6-BLSGUKbc.js → diagram-G4DWMVQ6-BpSu5Uao.js} +1 -1
  259. package/payload/server/public/assets/{diagram-MMDJMWI5-Ra1VvGJh.js → diagram-MMDJMWI5-DiArtkto.js} +1 -1
  260. package/payload/server/public/assets/{diagram-TYMM5635-Bx_r1USn.js → diagram-TYMM5635-_tygK58Y.js} +1 -1
  261. package/payload/server/public/assets/{erDiagram-SMLLAGMA-CJhoN8dG.js → erDiagram-SMLLAGMA-CBV6LWYA.js} +1 -1
  262. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-Bd5CZIoq.js → flowDiagram-DWJPFMVM-CHZFrtOU.js} +1 -1
  263. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BNQJqJFh.js → ganttDiagram-T4ZO3ILL-B3vKq5ov.js} +1 -1
  264. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DoE1AFmA.js → gitGraphDiagram-UUTBAWPF-dnJPjbtj.js} +1 -1
  265. package/payload/server/public/assets/graph-BVvcFSEQ.js +1 -0
  266. package/payload/server/public/assets/graph-labels-cCvgu38Y.js +1 -0
  267. package/payload/server/public/assets/{graphlib-D7JFfLSw.js → graphlib-CNXtnega.js} +1 -1
  268. package/payload/server/public/assets/{infoDiagram-42DDH7IO-BtsKRO-J.js → infoDiagram-42DDH7IO-D8DYwVAF.js} +1 -1
  269. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DapnDR0V.js → ishikawaDiagram-UXIWVN3A-CfEVY2Ud.js} +1 -1
  270. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-BLqfwMMu.js → journeyDiagram-VCZTEJTY-FmoBq7Kh.js} +1 -1
  271. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DqiSbvUW.js → kanban-definition-6JOO6SKY-B-Q9qk99.js} +1 -1
  272. package/payload/server/public/assets/{line-DcwBbbhp.js → line-DZwbJENP.js} +1 -1
  273. package/payload/server/public/assets/{mermaid-parser.core-BZwNRInp.js → mermaid-parser.core-C3ahKykw.js} +1 -1
  274. package/payload/server/public/assets/{mermaid.core-DnsyVInc.js → mermaid.core-B8OFZIE8.js} +3 -3
  275. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-MPPO8aDx.js → mindmap-definition-QFDTVHPH-CqhkfbWa.js} +1 -1
  276. package/payload/server/public/assets/{page-Cz_pVOv_.js → page-BnAxPkmg.js} +1 -1
  277. package/payload/server/public/assets/{page-pXt2BdOS.js → page-BnaN3u86.js} +1 -1
  278. package/payload/server/public/assets/{pieDiagram-DEJITSTG-BKzbjD_5.js → pieDiagram-DEJITSTG-CJqQ6u3-.js} +1 -1
  279. package/payload/server/public/assets/{public-C-0V5aC8.js → public-rWe9ADCS.js} +3 -3
  280. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CvvvRvae.js → quadrantDiagram-34T5L4WZ-BtEqOXQM.js} +1 -1
  281. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BxXZA7z2.js → requirementDiagram-MS252O5E-DPHWUtE6.js} +1 -1
  282. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BRRFjjao.js → sankeyDiagram-XADWPNL6-FBmc3wHT.js} +1 -1
  283. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DOy_E8xe.js → sequenceDiagram-FGHM5R23-BMSd2-1M.js} +1 -1
  284. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CDqat01p.js → stateDiagram-FHFEXIEX-DqFbU-LT.js} +1 -1
  285. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CXTnsHGq.js +1 -0
  286. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-AK1yuR8Z.js → timeline-definition-GMOUNBTQ-DsfvHVK8.js} +1 -1
  287. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CCKJ7H16.js → vennDiagram-DHZGUBPP-kHU05mqC.js} +1 -1
  288. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CKHKJnG_.js → wardleyDiagram-NUSXRM2D-C696Mez_.js} +1 -1
  289. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-BBD35k9e.js → xychartDiagram-5P7HB3ND-yht-JyXJ.js} +1 -1
  290. package/payload/server/public/data.html +5 -5
  291. package/payload/server/public/graph.html +5 -5
  292. package/payload/server/public/index.html +7 -7
  293. package/payload/server/public/public.html +4 -4
  294. package/payload/server/server.js +211 -178
  295. package/payload/server/public/assets/admin-BbcN8otj.js +0 -216
  296. package/payload/server/public/assets/channel-p5ZCfK_I.js +0 -1
  297. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DqDM1D4-.js +0 -1
  298. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DeYvPD8H.js +0 -1
  299. package/payload/server/public/assets/clone-60k82qeh.js +0 -1
  300. package/payload/server/public/assets/data-oXs84UW6.js +0 -1
  301. package/payload/server/public/assets/graph-DcpqWbSs.js +0 -1
  302. package/payload/server/public/assets/graph-labels-DJvuUODB.js +0 -1
  303. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DHckg-aj.js +0 -1
  304. /package/payload/server/public/assets/{brand-B6pMzF6h.js → brand-BWCtpG7_.js} +0 -0
@@ -1,26 +1,25 @@
1
1
  #!/usr/bin/env bash
2
- # Regression test for the Stop-hook gate that fires the database-operator
3
- # per completed admin-agent turn.
2
+ # Task 129/131 regression test for the Stop hook.
4
3
  #
5
- # Task 122 redesign: the hook routes through the admin wrapper's
6
- # loopback-only recorder route (POST /api/admin/claude-sessions/recorder-spawn)
7
- # in ONE HTTP call. The wrapper internally calls /spawn then /<id>/input on
8
- # the claude-session-manager the multi-line submit path is owned by the
9
- # wrapper, not duplicated in bash.
4
+ # Contract:
5
+ # - Every log emission goes through `POST /api/admin/log-ingest`. Hook
6
+ # stderr is silent on every path.
7
+ # - Every gated-off path emits one `trigger-skipped` line carrying a
8
+ # distinct `reason=` (role-not-admin | is-recorder | empty-stdin |
9
+ # missing-transcript | last-turn-empty).
10
+ # - Happy path emits exactly ONE `trigger` line carrying
11
+ # `lastTurnBytes=<n>` (Task 131 replaces `filteredRecords`) and
12
+ # exactly ONE `recorder-spawn` POST. The body carries the operator
13
+ # session id as `originatingSessionId` and an `initialMessage` of
14
+ # the form `<instruction>\n\n<last-turn-text>` — no transcript tail,
15
+ # no `Conversation id:` prose.
16
+ # - The hook never writes the legacy `spawn-with-input` / `fired` stderr
17
+ # lines.
10
18
  #
11
- # Behaviour verified:
12
- # 1. MAXY_SESSION_ROLE!=admin → exit 0, no POST attempt, no log line.
13
- # 2. MAXY_HIDDEN_SPAWN=1 → exit 0, no POST attempt, no log line.
14
- # 3. Empty stdin → exit 0 silently.
15
- # 4. Missing transcript_path → exit 0 silently.
16
- # 5. Happy path → exactly ONE POST to
17
- # /api/admin/claude-sessions/recorder-spawn whose body carries
18
- # senderId='turn-recorder', specialist='database-operator', and an
19
- # initialMessage containing the Task 114 instruction + the filtered
20
- # transcript. The hook still emits the
21
- # `[turn-recorder] spawn-with-input sessionId=<8> bytes=<n>
22
- # filtered-from-records=<n> input-http=200` log envelope unchanged
23
- # (Task 122 keeps the envelope so existing greps survive).
19
+ # The mock listener accepts both routes:
20
+ # POST /api/admin/log-ingest — log-ingest
21
+ # POST /api/admin/claude-sessions — wrapper
22
+ # Both record their bodies (with route path) into REQ_LOG.
24
23
 
25
24
  set -u
26
25
 
@@ -30,6 +29,8 @@ if [[ ! -x "$HOOK" ]]; then
30
29
  exit 1
31
30
  fi
32
31
 
32
+ OP_ID='aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb'
33
+
33
34
  TMPFILES=()
34
35
  LISTENER_PIDS=()
35
36
  cleanup_test_state() {
@@ -50,61 +51,10 @@ FAIL=0
50
51
  pass() { echo "PASS: $1"; PASS=$((PASS + 1)); }
51
52
  fail() { echo "FAIL: $1" >&2; FAIL=$((FAIL + 1)); }
52
53
 
53
- run_hook() {
54
- local role="$1"; local hidden="$2"; local stdin_json="$3"
55
- local stderr_file; stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
56
- local stdout_file; stdout_file=$(mktemp); TMPFILES+=("$stdout_file")
57
- printf '%s' "$stdin_json" | \
58
- MAXY_SESSION_ROLE="$role" \
59
- MAXY_HIDDEN_SPAWN="$hidden" \
60
- MAXY_UI_INTERNAL_PORT="${UI_PORT:-19199}" \
61
- bash "$HOOK" >"$stdout_file" 2>"$stderr_file"
62
- local rc=$?
63
- HOOK_RC="$rc"
64
- HOOK_STDERR=$(cat "$stderr_file")
65
- HOOK_STDOUT=$(cat "$stdout_file")
66
- }
67
-
68
- # --- Case 1: role != admin → no fire --------------------------------------
69
- TRANSCRIPT=$(mktemp); TMPFILES+=("$TRANSCRIPT")
70
- printf '{"type":"user","message":{"content":"hi"}}\n' > "$TRANSCRIPT"
71
- ENVELOPE=$(python3 -c '
72
- import json, sys
73
- print(json.dumps({"session_id": "abcd1234-deadbeef", "transcript_path": sys.argv[1]}))
74
- ' "$TRANSCRIPT")
75
-
76
- run_hook "public" "0" "$ENVELOPE"
77
- if [[ "$HOOK_RC" -ne 0 ]]; then fail "case-1 expected rc=0 got=$HOOK_RC"
78
- elif [[ -n "$HOOK_STDERR" ]]; then fail "case-1 expected empty stderr, got: $HOOK_STDERR"
79
- else pass "case-1 role=public → no fire (rc=0, stderr empty)"
80
- fi
81
-
82
- # --- Case 2: hidden=1 → no fire ----------------------------------------
83
- run_hook "admin" "1" "$ENVELOPE"
84
- if [[ "$HOOK_RC" -ne 0 ]]; then fail "case-2 expected rc=0 got=$HOOK_RC"
85
- elif [[ -n "$HOOK_STDERR" ]]; then fail "case-2 expected empty stderr, got: $HOOK_STDERR"
86
- else pass "case-2 hidden=1 → silent"
87
- fi
88
-
89
- # --- Case 3: empty stdin → silent --------------------------------------
90
- run_hook "admin" "0" ""
91
- if [[ "$HOOK_RC" -ne 0 ]]; then fail "case-3 expected rc=0 got=$HOOK_RC"
92
- elif [[ -n "$HOOK_STDERR" ]]; then fail "case-3 expected empty stderr, got: $HOOK_STDERR"
93
- else pass "case-3 empty stdin → silent (rc=0)"
94
- fi
95
-
96
- # --- Case 4: missing transcript_path → silent -------------------------
97
- BAD_ENVELOPE='{"session_id":"x"}'
98
- run_hook "admin" "0" "$BAD_ENVELOPE"
99
- if [[ "$HOOK_RC" -ne 0 ]]; then fail "case-4 expected rc=0 got=$HOOK_RC"
100
- elif [[ -n "$HOOK_STDERR" ]]; then fail "case-4 expected empty stderr, got: $HOOK_STDERR"
101
- else pass "case-4 missing transcript_path → silent (rc=0)"
102
- fi
103
-
104
- # --- Case 5: happy path → exactly ONE POST to /api/admin/claude-sessions/recorder-spawn
105
- REQ_LOG=$(mktemp); TMPFILES+=("$REQ_LOG")
106
- LISTENER_PORT=39406
107
- python3 - "$LISTENER_PORT" "$REQ_LOG" <<'PY' &
54
+ start_listener() {
55
+ REQ_LOG=$(mktemp); TMPFILES+=("$REQ_LOG")
56
+ LISTENER_PORT=$((39400 + RANDOM % 100))
57
+ python3 - "$LISTENER_PORT" "$REQ_LOG" <<'PY' &
108
58
  import sys, http.server, json
109
59
  port = int(sys.argv[1])
110
60
  log_path = sys.argv[2]
@@ -118,107 +68,196 @@ class H(http.server.BaseHTTPRequestHandler):
118
68
  self.send_response(200)
119
69
  self.send_header('Content-Type','application/json')
120
70
  self.end_headers()
121
- if self.path.endswith('/recorder-spawn'):
122
- self.wfile.write(json.dumps({"sessionId":"rec00001-feedfeed"}).encode('utf-8'))
71
+ if self.path == '/api/admin/claude-sessions':
72
+ self.wfile.write(json.dumps({"sessionId":"rec00001-feedfeed","pid":99999}).encode('utf-8'))
123
73
  else:
124
74
  self.wfile.write(json.dumps({"ok": True}).encode('utf-8'))
125
75
  http.server.HTTPServer(('127.0.0.1', port), H).serve_forever()
126
76
  PY
127
- LISTENER_PIDS+=("$!")
128
-
129
- # Wait up to 2s for the listener to bind.
130
- for _ in $(seq 1 20); do
131
- if curl -sS --max-time 1 -X POST "http://127.0.0.1:${LISTENER_PORT}/ping" -d '{}' >/dev/null 2>&1; then
132
- break
133
- fi
134
- sleep 0.1
135
- done
77
+ LISTENER_PIDS+=("$!")
78
+ for _ in $(seq 1 20); do
79
+ if curl -sS --max-time 1 -X POST "http://127.0.0.1:${LISTENER_PORT}/ping" -d '{}' >/dev/null 2>&1; then
80
+ break
81
+ fi
82
+ sleep 0.1
83
+ done
84
+ : > "$REQ_LOG"
85
+ }
136
86
 
137
- # Clear the request log of the ping write.
138
- : > "$REQ_LOG"
87
+ run_hook() {
88
+ local role="$1"; local is_recorder="$2"; local stdin_json="$3"
89
+ local stderr_file; stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
90
+ local stdout_file; stdout_file=$(mktemp); TMPFILES+=("$stdout_file")
91
+ printf '%s' "$stdin_json" | \
92
+ MAXY_SESSION_ROLE="$role" \
93
+ MAXY_IS_RECORDER="$is_recorder" \
94
+ MAXY_UI_INTERNAL_PORT="$LISTENER_PORT" \
95
+ bash "$HOOK" >"$stdout_file" 2>"$stderr_file"
96
+ HOOK_RC=$?
97
+ HOOK_STDERR=$(cat "$stderr_file")
98
+ HOOK_STDOUT=$(cat "$stdout_file")
99
+ sleep 0.1 # let listener flush
100
+ }
139
101
 
140
- UI_PORT="$LISTENER_PORT"
141
- run_hook "admin" "0" "$ENVELOPE"
142
- unset UI_PORT
102
+ # Extract the `line` field of every log-ingest POST in REQ_LOG.
103
+ ingest_lines() {
104
+ grep -E '^/api/admin/log-ingest ' "$REQ_LOG" 2>/dev/null | python3 -c '
105
+ import sys, json
106
+ for raw in sys.stdin:
107
+ try:
108
+ _, body = raw.rstrip("\n").split("\t", 1)
109
+ d = json.loads(body)
110
+ if isinstance(d, dict) and isinstance(d.get("line"), str):
111
+ print(d["line"])
112
+ except Exception:
113
+ pass
114
+ ' || true
115
+ }
143
116
 
144
- # Give the listener time to flush.
145
- sleep 0.1
117
+ # Common envelope: a valid Stop-hook stdin shape with a real UUID + a
118
+ # transcript file the hook can read. Transcript has one user turn and
119
+ # one assistant turn — Task 131 picks the most-recent assistant text as
120
+ # the last-turn payload.
121
+ start_listener
122
+ TRANSCRIPT=$(mktemp); TMPFILES+=("$TRANSCRIPT")
123
+ {
124
+ printf '{"type":"user","message":{"role":"user","content":"hello operator"}}\n'
125
+ printf '{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"hello, assistant reply"}]}}\n'
126
+ } > "$TRANSCRIPT"
127
+ ENVELOPE=$(python3 -c '
128
+ import json, sys
129
+ print(json.dumps({"session_id": sys.argv[1], "transcript_path": sys.argv[2]}))
130
+ ' "$OP_ID" "$TRANSCRIPT")
146
131
 
147
- if [[ "$HOOK_RC" -ne 0 ]]; then
148
- fail "case-5 expected rc=0 got=$HOOK_RC stderr=$HOOK_STDERR"
132
+ # --- Case 1: role != admin → trigger-skipped reason=role-not-admin -----
133
+ : > "$REQ_LOG"
134
+ run_hook "public" "0" "$ENVELOPE"
135
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-1 rc=$HOOK_RC"
136
+ [[ -z "$HOOK_STDERR" ]] || fail "case-1 stderr must be empty, got: $HOOK_STDERR"
137
+ if ingest_lines | grep -qE '^trigger-skipped sessionId=.* reason=role-not-admin$'; then
138
+ pass "case-1 role=public → trigger-skipped reason=role-not-admin emitted"
139
+ else
140
+ fail "case-1 expected trigger-skipped role-not-admin, got log-ingest lines: $(ingest_lines)"
149
141
  fi
150
-
151
- # Assert: spawn-with-input log line emitted.
152
- if ! echo "$HOOK_STDERR" | grep -qE '^\[turn-recorder\] spawn-with-input sessionId=rec00001 bytes=[0-9]+ filtered-from-records=[0-9]+ input-http=[0-9]+'; then
153
- fail "case-5a expected spawn-with-input log line, got: $HOOK_STDERR"
142
+ if grep -qE '^/api/admin/claude-sessions ' "$REQ_LOG"; then
143
+ fail "case-1 recorder-spawn must NOT be called when role!=admin"
154
144
  else
155
- pass "case-5a spawn-with-input log line emitted"
145
+ pass "case-1 no recorder-spawn POST"
156
146
  fi
157
147
 
158
- # Assert: no legacy spawn-with-stdin log line.
159
- if echo "$HOOK_STDERR" | grep -q 'spawn-with-stdin'; then
160
- fail "case-5b legacy spawn-with-stdin line must not be emitted"
148
+ # --- Case 2: MAXY_IS_RECORDER=1 trigger-skipped reason=is-recorder ----
149
+ : > "$REQ_LOG"
150
+ run_hook "admin" "1" "$ENVELOPE"
151
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-2 rc=$HOOK_RC"
152
+ [[ -z "$HOOK_STDERR" ]] || fail "case-2 stderr must be empty, got: $HOOK_STDERR"
153
+ if ingest_lines | grep -qE '^trigger-skipped sessionId=.* reason=is-recorder$'; then
154
+ pass "case-2 MAXY_IS_RECORDER=1 → trigger-skipped reason=is-recorder emitted"
161
155
  else
162
- pass "case-5b legacy spawn-with-stdin log line absent"
156
+ fail "case-2 expected trigger-skipped is-recorder, got: $(ingest_lines)"
163
157
  fi
164
158
 
165
- # Assert: exactly ONE POST to the wrapper recorder-spawn route, and no
166
- # direct /spawn or /<id>/input POSTs (the wrapper-internal calls do not
167
- # touch this test listener — the listener mocks the wrapper, not the
168
- # manager).
169
- RECORDER_LINES=$(grep -cE '^/api/admin/claude-sessions/recorder-spawn ' "$REQ_LOG" || true)
170
- LEGACY_SPAWN_LINES=$(grep -cE '^/spawn ' "$REQ_LOG" || true)
171
- LEGACY_INPUT_LINES=$(grep -cE '^/[A-Za-z0-9_-]+/input ' "$REQ_LOG" || true)
172
- STOP_LINES=$(grep -cE '^/[A-Za-z0-9_-]+/stop ' "$REQ_LOG" || true)
173
- if [[ "$RECORDER_LINES" -ne 1 ]]; then
174
- fail "case-5c expected exactly 1 /api/admin/claude-sessions/recorder-spawn POST, got $RECORDER_LINES (log: $(cat "$REQ_LOG"))"
159
+ # --- Case 3: empty stdin trigger-skipped reason=empty-stdin ------------
160
+ : > "$REQ_LOG"
161
+ run_hook "admin" "0" ""
162
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-3 rc=$HOOK_RC"
163
+ if ingest_lines | grep -qE '^trigger-skipped sessionId=.* reason=empty-stdin$'; then
164
+ pass "case-3 empty stdin trigger-skipped reason=empty-stdin emitted"
175
165
  else
176
- pass "case-5c exactly one recorder-spawn POST observed"
166
+ fail "case-3 expected trigger-skipped empty-stdin, got: $(ingest_lines)"
177
167
  fi
178
- if [[ "$LEGACY_SPAWN_LINES" -ne 0 ]]; then
179
- fail "case-5d hook must not POST /spawn directly any more, got $LEGACY_SPAWN_LINES"
168
+
169
+ # --- Case 4: missing transcript_path trigger-skipped missing-transcript -
170
+ : > "$REQ_LOG"
171
+ BAD_ENVELOPE=$(python3 -c 'import json,sys; print(json.dumps({"session_id": sys.argv[1]}))' "$OP_ID")
172
+ run_hook "admin" "0" "$BAD_ENVELOPE"
173
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-4 rc=$HOOK_RC"
174
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=missing-transcript$"; then
175
+ pass "case-4 missing transcript → trigger-skipped reason=missing-transcript emitted"
180
176
  else
181
- pass "case-5d no direct /spawn POST"
177
+ fail "case-4 expected trigger-skipped missing-transcript, got: $(ingest_lines)"
182
178
  fi
183
- if [[ "$LEGACY_INPUT_LINES" -ne 0 ]]; then
184
- fail "case-5e hook must not POST /<id>/input directly any more, got $LEGACY_INPUT_LINES"
179
+
180
+ # --- Case 5: happy path -------------------------------------------------
181
+ : > "$REQ_LOG"
182
+ run_hook "admin" "0" "$ENVELOPE"
183
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-5 rc=$HOOK_RC stderr=$HOOK_STDERR"
184
+ [[ -z "$HOOK_STDERR" ]] || fail "case-5 stderr must be empty, got: $HOOK_STDERR"
185
+
186
+ # 5a. exactly ONE `trigger` log-ingest line carrying the operator session id
187
+ # and `lastTurnBytes=<n>` (Task 131 replaces `filteredRecords`).
188
+ TRIGGER_COUNT=$(ingest_lines | grep -cE "^trigger sessionId=${OP_ID} turnIndex=0 transcriptBytes=[0-9]+ lastTurnBytes=[0-9]+$" || true)
189
+ if [[ "$TRIGGER_COUNT" -eq 1 ]]; then
190
+ pass "case-5a exactly one trigger line emitted via log-ingest carrying operator id + lastTurnBytes"
185
191
  else
186
- pass "case-5e no direct /<id>/input POST"
192
+ fail "case-5a expected exactly 1 trigger line carrying ${OP_ID}, got $TRIGGER_COUNT (lines: $(ingest_lines))"
187
193
  fi
188
- if [[ "$STOP_LINES" -ne 0 ]]; then
189
- fail "case-5f hook must not POST /<id>/stop, got $STOP_LINES"
194
+
195
+ # 5b. exactly ONE POST to /api/admin/claude-sessions
196
+ RECORDER_LINES=$(grep -cE '^/api/admin/claude-sessions ' "$REQ_LOG" || true)
197
+ if [[ "$RECORDER_LINES" -eq 1 ]]; then
198
+ pass "case-5b exactly one recorder-spawn POST observed"
190
199
  else
191
- pass "case-5f no /<id>/stop POSTs"
200
+ fail "case-5b expected exactly 1 recorder-spawn POST, got $RECORDER_LINES"
192
201
  fi
193
202
 
194
- # Assert: recorder-spawn body carries senderId, specialist, and a multi-line
195
- # initialMessage with the Task 114 instruction + transcript section header.
196
- RECORDER_BODY=$(grep -E '^/api/admin/claude-sessions/recorder-spawn ' "$REQ_LOG" | head -1 | cut -f2-)
203
+ # 5c. recorder-spawn body has originatingSessionId == operator id; initialMessage
204
+ # equals "<instruction>\n\n<last-turn-text>" verbatim. No transcript prose.
205
+ RECORDER_BODY=$(grep -E '^/api/admin/claude-sessions ' "$REQ_LOG" | head -1 | cut -f2-)
197
206
  BODY_OK=$(printf '%s' "$RECORDER_BODY" | python3 -c '
198
207
  import sys, json
208
+ op = sys.argv[1]
209
+ INSTRUCTION = "update the graph with any new or missing information or intent"
210
+ EXPECTED_LAST = "hello, assistant reply"
199
211
  try:
200
212
  b = json.load(sys.stdin)
201
- senderOK = b.get("senderId") == "turn-recorder"
202
- specOK = b.get("specialist") == "database-operator"
203
- msg = b.get("initialMessage", "") or ""
204
- hasInstr = "update the graph with any missing information or intent that can be derived from this conversation" in msg
205
- hasTx = "Conversation transcript:" in msg
206
- hasMultiline = "\n" in msg
207
- print("yes" if (senderOK and specOK and hasInstr and hasTx and hasMultiline) else "no")
208
- except Exception:
209
- print("parse-fail")
210
- ' 2>/dev/null)
211
- if [[ "$BODY_OK" != "yes" ]]; then
212
- fail "case-5g recorder-spawn body shape wrong: $RECORDER_BODY"
213
+ msg = b.get("initialMessage") or ""
214
+ conds = (
215
+ # Task 134: no synthetic senderId marker — loopback bypass is
216
+ # method+path-scoped; the body only carries the recorder discriminators.
217
+ "senderId" not in b,
218
+ b.get("specialist") == "database-operator",
219
+ b.get("originatingSessionId") == op,
220
+ msg == INSTRUCTION + "\n\n" + EXPECTED_LAST,
221
+ "Conversation id:" not in msg,
222
+ "Conversation transcript:" not in msg,
223
+ )
224
+ print("yes" if all(conds) else "no:"+repr(conds)+"|msg="+repr(msg))
225
+ except Exception as e:
226
+ print("parse-fail:"+str(e))
227
+ ' "$OP_ID" 2>/dev/null)
228
+ if [[ "$BODY_OK" == "yes" ]]; then
229
+ pass "case-5c recorder-spawn body carries originatingSessionId + verbatim instruction + last-turn text"
230
+ else
231
+ fail "case-5c body shape wrong ($BODY_OK): $RECORDER_BODY"
232
+ fi
233
+
234
+ # 5d. no legacy stderr emissions
235
+ if echo "$HOOK_STDERR" | grep -qE 'spawn-with-input|spawn-with-stdin|turn-completed-graph-write fired'; then
236
+ fail "case-5d legacy stderr line emitted: $HOOK_STDERR"
213
237
  else
214
- pass "case-5g recorder-spawn body carries senderId, specialist, multi-line initialMessage"
238
+ pass "case-5d no legacy stderr emissions"
215
239
  fi
216
240
 
217
- # Assert: final fired log line still emitted.
218
- if ! echo "$HOOK_STDERR" | grep -qE '^turn-completed-graph-write fired conversationId=abcd1234 recorderSessionId=rec00001 filtered=[0-9]+ ms=[0-9]+'; then
219
- fail "case-5h expected fired summary log line, got: $HOOK_STDERR"
241
+ # --- Case 6 (Task 131): transcript has no assistant/user text → ---------
242
+ # trigger-skipped reason=last-turn-empty. The hook emits the trigger
243
+ # line first (lastTurnBytes=0) and then the new skip reason.
244
+ EMPTY_TRANSCRIPT=$(mktemp); TMPFILES+=("$EMPTY_TRANSCRIPT")
245
+ printf '{"type":"system","summary":"noop"}\n' > "$EMPTY_TRANSCRIPT"
246
+ EMPTY_ENVELOPE=$(python3 -c '
247
+ import json, sys
248
+ print(json.dumps({"session_id": sys.argv[1], "transcript_path": sys.argv[2]}))
249
+ ' "$OP_ID" "$EMPTY_TRANSCRIPT")
250
+ : > "$REQ_LOG"
251
+ run_hook "admin" "0" "$EMPTY_ENVELOPE"
252
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-6 rc=$HOOK_RC"
253
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=last-turn-empty$"; then
254
+ pass "case-6 empty last-turn text → trigger-skipped reason=last-turn-empty emitted"
220
255
  else
221
- pass "case-5h fired summary log line emitted"
256
+ fail "case-6 expected trigger-skipped last-turn-empty, got: $(ingest_lines)"
257
+ fi
258
+ # And no recorder-spawn POST is made.
259
+ if grep -qE '^/api/admin/claude-sessions ' "$REQ_LOG"; then
260
+ fail "case-6 recorder-spawn must NOT be called when last-turn-empty"
222
261
  fi
223
262
 
224
263
  # --- Summary ------------------------------------------------------------