@rubytech/create-realagent-code 0.1.255 → 0.1.257

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 (217) hide show
  1. package/dist/__tests__/plugin-install.test.js +58 -40
  2. package/dist/index.js +77 -26
  3. package/dist/lib/plugin-install.js +31 -29
  4. package/package.json +1 -1
  5. package/payload/platform/config/brand-registry.json +8 -0
  6. package/payload/platform/config/brand.json +2 -2
  7. package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +12 -0
  8. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
  9. package/payload/platform/lib/graph-write/dist/index.js +2 -0
  10. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  11. package/payload/platform/lib/graph-write/src/index.ts +2 -0
  12. package/payload/platform/neo4j/schema.cypher +126 -0
  13. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  14. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  15. package/payload/platform/plugins/admin/PLUGIN.md +3 -6
  16. package/payload/platform/plugins/admin/mcp/dist/index.js +0 -60
  17. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  18. package/payload/platform/plugins/admin/skills/insight/SKILL.md +24 -0
  19. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +63 -10
  20. package/payload/platform/plugins/business-assistant/PLUGIN.md +1 -1
  21. package/payload/platform/plugins/business-assistant/references/document-management.md +1 -1
  22. package/payload/platform/plugins/business-assistant/references/invoicing.md +2 -2
  23. package/payload/platform/plugins/business-assistant/references/quoting.md +1 -1
  24. package/payload/platform/plugins/docs/PLUGIN.md +1 -0
  25. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  26. package/payload/platform/plugins/docs/references/deployment.md +18 -5
  27. package/payload/platform/plugins/docs/references/memory-guide.md +4 -0
  28. package/payload/platform/plugins/docs/references/platform.md +1 -1
  29. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  30. package/payload/platform/plugins/docs/references/slides.md +31 -0
  31. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +1 -1
  32. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  33. package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
  34. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  35. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
  36. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +10 -0
  39. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  40. package/payload/platform/plugins/memory/references/schema-construction.md +72 -0
  41. package/payload/platform/plugins/slides/.claude-plugin/plugin.json +8 -0
  42. package/payload/platform/plugins/slides/LICENSE +21 -0
  43. package/payload/platform/plugins/slides/PLUGIN.md +18 -0
  44. package/payload/platform/plugins/slides/PROVENANCE.md +40 -0
  45. package/payload/platform/plugins/slides/commands/add-slide.md +29 -0
  46. package/payload/platform/plugins/slides/commands/slides-claus.md +39 -0
  47. package/payload/platform/plugins/slides/commands/slides-new-component.md +39 -0
  48. package/payload/platform/plugins/slides/commands/slides-outline.md +43 -0
  49. package/payload/platform/plugins/slides/commands/slides-review.md +52 -0
  50. package/payload/platform/plugins/slides/commands/slides-theme.md +64 -0
  51. package/payload/platform/plugins/slides/commands/slides.md +59 -0
  52. package/payload/platform/plugins/slides/skills/deck-system/REFERENCE.md +581 -0
  53. package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +607 -0
  54. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-board.md +426 -0
  55. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-claus.md +185 -0
  56. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-mbb.md +450 -0
  57. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-product-launch.md +579 -0
  58. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sales.md +464 -0
  59. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sequoia.md +489 -0
  60. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING.md +273 -0
  61. package/payload/platform/plugins/slides/skills/deck-system/deck-craft.html +1371 -0
  62. package/payload/platform/plugins/slides/skills/deck-system/deck-solid.html +1667 -0
  63. package/payload/platform/plugins/slides/skills/deck-system/deck.html +1359 -0
  64. package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +1 -1
  65. package/payload/platform/plugins/url-get/PLUGIN.md +26 -21
  66. package/payload/platform/plugins/url-get/mcp/dist/index.js +3 -3
  67. package/payload/platform/plugins/url-get/mcp/dist/index.js.map +1 -1
  68. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts +1 -2
  69. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts.map +1 -1
  70. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js +20 -40
  71. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js.map +1 -1
  72. package/payload/platform/scripts/setup-account.sh +1 -10
  73. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  74. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
  75. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  76. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +5 -0
  77. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  78. package/payload/platform/services/claude-session-manager/dist/http-server.js +32 -2
  79. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  80. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +2 -2
  81. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  82. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  83. package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +1 -1
  84. package/payload/server/public/assets/AdminShell-T-YknnBn.js +1 -0
  85. package/payload/server/public/assets/Checkbox-DmDxpqVv.js +1 -0
  86. package/payload/server/public/assets/admin-COUV-jgt.js +1 -0
  87. package/payload/server/public/assets/{arc-aUiRP9AS.js → arc-B2CweJq3.js} +1 -1
  88. package/payload/server/public/assets/architecture-YZFGNWBL-Dnn6Hc65.js +1 -0
  89. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-c09loTER.js → architectureDiagram-Q4EWVU46-DP2o-MFV.js} +1 -1
  90. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Cjdeyoq1.js → blockDiagram-DXYQGD6D-DO4mcYDJ.js} +1 -1
  91. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-NY6Wlzo2.js → c4Diagram-AHTNJAMY-Sy1giHbj.js} +1 -1
  92. package/payload/server/public/assets/channel-CEpR_0rE.js +1 -0
  93. package/payload/server/public/assets/{chunk-2KRD3SAO-BK3470lx.js → chunk-2KRD3SAO-CKsCYCsN.js} +1 -1
  94. package/payload/server/public/assets/chunk-336JU56O-C0-P-aUF.js +2 -0
  95. package/payload/server/public/assets/chunk-426QAEUC-DFjEt3Zb.js +1 -0
  96. package/payload/server/public/assets/{chunk-4BX2VUAB-BOvVdJLf.js → chunk-4BX2VUAB-B8bqAmBa.js} +1 -1
  97. package/payload/server/public/assets/{chunk-4TB4RGXK-BXpto3yW.js → chunk-4TB4RGXK-D1k0VSlW.js} +1 -1
  98. package/payload/server/public/assets/{chunk-55IACEB6-BwZyF7vR.js → chunk-55IACEB6-B-p_QNqz.js} +1 -1
  99. package/payload/server/public/assets/{chunk-5FUZZQ4R-C403gCUk.js → chunk-5FUZZQ4R-D6U6tV_j.js} +1 -1
  100. package/payload/server/public/assets/{chunk-5PVQY5BW-CjVzXQEp.js → chunk-5PVQY5BW-CYK76xfs.js} +1 -1
  101. package/payload/server/public/assets/{chunk-67CJDMHE-D5bhMrtY.js → chunk-67CJDMHE-BC9js-lf.js} +1 -1
  102. package/payload/server/public/assets/{chunk-7N4EOEYR-Si7Lgrwc.js → chunk-7N4EOEYR-4j2OqKkv.js} +1 -1
  103. package/payload/server/public/assets/{chunk-AA7GKIK3-DMuHtDqO.js → chunk-AA7GKIK3-Coen-fXN.js} +1 -1
  104. package/payload/server/public/assets/{chunk-BSJP7CBP-L79XKVcb.js → chunk-BSJP7CBP-CAiOBvec.js} +1 -1
  105. package/payload/server/public/assets/{chunk-CIAEETIT-C0O7Upmg.js → chunk-CIAEETIT-AJzzpZVb.js} +1 -1
  106. package/payload/server/public/assets/{chunk-EDXVE4YY-DJcJAsAg.js → chunk-EDXVE4YY-BL4BKozX.js} +1 -1
  107. package/payload/server/public/assets/{chunk-ENJZ2VHE-CFDNvYu1.js → chunk-ENJZ2VHE-mhAFG8UD.js} +1 -1
  108. package/payload/server/public/assets/{chunk-FMBD7UC4-C_E43NFJ.js → chunk-FMBD7UC4-H231gZA_.js} +1 -1
  109. package/payload/server/public/assets/{chunk-FOC6F5B3-D9lWWHAu.js → chunk-FOC6F5B3-Cl3ZZjYG.js} +1 -1
  110. package/payload/server/public/assets/{chunk-ICPOFSXX-ecLOxGhL.js → chunk-ICPOFSXX-DOEzvzJa.js} +2 -2
  111. package/payload/server/public/assets/{chunk-K5T4RW27-DuhsNH4c.js → chunk-K5T4RW27-C_ipbUDD.js} +1 -1
  112. package/payload/server/public/assets/{chunk-KGLVRYIC-B4-A1Abi.js → chunk-KGLVRYIC-CTsDNSCU.js} +1 -1
  113. package/payload/server/public/assets/{chunk-LIHQZDEY-BxqgHRgT.js → chunk-LIHQZDEY-DvSXhkGf.js} +1 -1
  114. package/payload/server/public/assets/{chunk-ORNJ4GCN-DEYQ5WaJ.js → chunk-ORNJ4GCN-p574NOI7.js} +1 -1
  115. package/payload/server/public/assets/{chunk-OYMX7WX6-B7MW66KB.js → chunk-OYMX7WX6-BlEgFM6U.js} +1 -1
  116. package/payload/server/public/assets/chunk-QZHKN3VN-DpF06ZZQ.js +1 -0
  117. package/payload/server/public/assets/{chunk-U2HBQHQK-BMawmsyk.js → chunk-U2HBQHQK-B2bDK0jv.js} +1 -1
  118. package/payload/server/public/assets/{chunk-X2U36JSP-CT6g7pno.js → chunk-X2U36JSP-D69BxKFw.js} +1 -1
  119. package/payload/server/public/assets/{chunk-XPW4576I-CBfZXZDB.js → chunk-XPW4576I-Dm-PcyUi.js} +1 -1
  120. package/payload/server/public/assets/{chunk-YZCP3GAM-xeAluiAH.js → chunk-YZCP3GAM-Be8RnXgx.js} +1 -1
  121. package/payload/server/public/assets/{chunk-ZZ45TVLE-BRN9qUC5.js → chunk-ZZ45TVLE-Ck8PCTa4.js} +1 -1
  122. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CYbXvKLI.js +1 -0
  123. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DEyHzRhq.js +1 -0
  124. package/payload/server/public/assets/clone-y8gexbBy.js +1 -0
  125. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-Br2gjtEO.js → cose-bilkent-S5V4N54A-CmkW2Eaj.js} +1 -1
  126. package/payload/server/public/assets/{dagre-DTjePoco.js → dagre-Dqp-ns8F.js} +1 -1
  127. package/payload/server/public/assets/{dagre-KV5264BT-DHBkRke4.js → dagre-KV5264BT-ZgWWXPLc.js} +1 -1
  128. package/payload/server/public/assets/data-gy6QH9c1.js +1 -0
  129. package/payload/server/public/assets/{diagram-5BDNPKRD-BIq1-idL.js → diagram-5BDNPKRD-CTX5-ScM.js} +1 -1
  130. package/payload/server/public/assets/{diagram-G4DWMVQ6-BsIUDzV6.js → diagram-G4DWMVQ6-BovIsO6H.js} +1 -1
  131. package/payload/server/public/assets/{diagram-MMDJMWI5-CgHSri2i.js → diagram-MMDJMWI5-DcETsQy-.js} +1 -1
  132. package/payload/server/public/assets/{diagram-TYMM5635-Ce2Wh9ZX.js → diagram-TYMM5635-yyq6peoZ.js} +1 -1
  133. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BU0Kh6OQ.js → erDiagram-SMLLAGMA-CiNToftB.js} +1 -1
  134. package/payload/server/public/assets/{flatten-Bo6YRmWl.js → flatten-BtFI066E.js} +1 -1
  135. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B0N06MF7.js → flowDiagram-DWJPFMVM-Xnl3SpIM.js} +1 -1
  136. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BVbx4ARZ.js → ganttDiagram-T4ZO3ILL-C1iyWe0f.js} +1 -1
  137. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CNs-LD5i.js +1 -0
  138. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C-xRJ94t.js → gitGraphDiagram-UUTBAWPF-D97pbMQb.js} +1 -1
  139. package/payload/server/public/assets/graph-labels-cZu4pK16.js +1 -0
  140. package/payload/server/public/assets/{graph-g48ZcA5M.js → graph-qz5tFKqU.js} +3 -3
  141. package/payload/server/public/assets/{graphlib-YmNcoMjY.js → graphlib-Lq8ijgON.js} +1 -1
  142. package/payload/server/public/assets/info-OMHHGYJF-DsTNigSS.js +1 -0
  143. package/payload/server/public/assets/infoDiagram-42DDH7IO-C_OarRTA.js +2 -0
  144. package/payload/server/public/assets/{isEmpty-D6Kr-M1M.js → isEmpty-D6QovjYR.js} +1 -1
  145. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DTrq54yC.js → ishikawaDiagram-UXIWVN3A-B8XBdjJn.js} +1 -1
  146. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-OZZZMrFX.js → journeyDiagram-VCZTEJTY-CZYbiOaQ.js} +1 -1
  147. package/payload/server/public/assets/{kanban-definition-6JOO6SKY--w-IP9pN.js → kanban-definition-6JOO6SKY-B1PybFoh.js} +1 -1
  148. package/payload/server/public/assets/{line-Ckeulv5T.js → line-D-tw3hHp.js} +1 -1
  149. package/payload/server/public/assets/{linear-DOh_6k2k.js → linear-BHhXD3cd.js} +1 -1
  150. package/payload/server/public/assets/{mermaid-parser.core-CVRAxYRD.js → mermaid-parser.core-C9RAnysF.js} +2 -2
  151. package/payload/server/public/assets/{mermaid.core-B-mE18I1.js → mermaid.core-B532LT1r.js} +3 -3
  152. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Bm8mDicL.js → mindmap-definition-QFDTVHPH-DGlgeeTV.js} +1 -1
  153. package/payload/server/public/assets/{ordinal-BDi6f4xk.js → ordinal-Bl-aM5b9.js} +1 -1
  154. package/payload/server/public/assets/packet-4T2RLAQJ-DGES22b-.js +1 -0
  155. package/payload/server/public/assets/pie-ZZUOXDRM-ChKeDbzt.js +1 -0
  156. package/payload/server/public/assets/{pieDiagram-DEJITSTG-BCmRLgGO.js → pieDiagram-DEJITSTG-DV9FIWko.js} +1 -1
  157. package/payload/server/public/assets/{public-DknO-g9S.js → public-Bu2_Xi0a.js} +5 -5
  158. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CniTIUTm.js → quadrantDiagram-34T5L4WZ-Betwya4l.js} +1 -1
  159. package/payload/server/public/assets/radar-PYXPWWZC-FGG5Fs7N.js +1 -0
  160. package/payload/server/public/assets/{reduce-CGi9ik8i.js → reduce-BD4xUd2c.js} +1 -1
  161. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CoxBSj9M.js → requirementDiagram-MS252O5E-Cq3vODdg.js} +1 -1
  162. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BjS-4jzq.js → sankeyDiagram-XADWPNL6-x8krXWcS.js} +1 -1
  163. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-B9jVOnPR.js → sequenceDiagram-FGHM5R23-i-_uH-Yl.js} +1 -1
  164. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BvOQPzP8.js → stateDiagram-FHFEXIEX-il4KqSgI.js} +1 -1
  165. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B6zNJ6Tv.js +1 -0
  166. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CdfgWLo1.js → timeline-definition-GMOUNBTQ-DATdZkA5.js} +1 -1
  167. package/payload/server/public/assets/treeView-SZITEDCU-VAQQdbtf.js +1 -0
  168. package/payload/server/public/assets/treemap-W4RFUUIX-DKchO3zI.js +1 -0
  169. package/payload/server/public/assets/useSelectionMode-A5KItZ2T.js +13 -0
  170. package/payload/server/public/assets/{brand-D0gNihp7.css → useSelectionMode-C-Ojh7W9.css} +1 -1
  171. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-JCgpIbj-.js → vennDiagram-DHZGUBPP-BJh9tJTt.js} +1 -1
  172. package/payload/server/public/assets/wardley-RL74JXVD-CBGtx0bS.js +1 -0
  173. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Dei3VqHo.js → wardleyDiagram-NUSXRM2D-EMN1Hdfg.js} +1 -1
  174. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DUtIyoIb.js → xychartDiagram-5P7HB3ND-DbUWXa7T.js} +1 -1
  175. package/payload/server/public/data.html +5 -5
  176. package/payload/server/public/graph.html +6 -6
  177. package/payload/server/public/index.html +5 -6
  178. package/payload/server/public/public.html +4 -5
  179. package/payload/server/server.js +65 -23
  180. package/payload/platform/plugins/admin/hooks/__tests__/insight.test.sh +0 -395
  181. package/payload/platform/plugins/admin/hooks/insight.sh +0 -219
  182. package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +0 -239
  183. package/payload/server/public/assets/AdminShell-892Jy_rs.js +0 -1
  184. package/payload/server/public/assets/Checkbox-Bc2QzX9b.js +0 -1
  185. package/payload/server/public/assets/admin-D3K13ndi.js +0 -1
  186. package/payload/server/public/assets/architecture-YZFGNWBL--v-pJPNp.js +0 -1
  187. package/payload/server/public/assets/brand-CcN3dELF.js +0 -9
  188. package/payload/server/public/assets/channel-B1IT7to2.js +0 -1
  189. package/payload/server/public/assets/chunk-336JU56O-CdKRCIeE.js +0 -2
  190. package/payload/server/public/assets/chunk-426QAEUC-BybuQ3Ve.js +0 -1
  191. package/payload/server/public/assets/chunk-QZHKN3VN-Bd-GrQM6.js +0 -1
  192. package/payload/server/public/assets/classDiagram-6PBFFD2Q-rjCize6i.js +0 -1
  193. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BORWOUt0.js +0 -1
  194. package/payload/server/public/assets/clone-Csqv5U6T.js +0 -1
  195. package/payload/server/public/assets/data-Br-pdljK.js +0 -1
  196. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CI0s_tqn.js +0 -1
  197. package/payload/server/public/assets/graph-labels-BYH-IPCb.js +0 -1
  198. package/payload/server/public/assets/info-OMHHGYJF-g3gYW7Qm.js +0 -1
  199. package/payload/server/public/assets/infoDiagram-42DDH7IO-Di6oPQ_-.js +0 -2
  200. package/payload/server/public/assets/packet-4T2RLAQJ-CT0TB9HI.js +0 -1
  201. package/payload/server/public/assets/pie-ZZUOXDRM-CXLe7TFF.js +0 -1
  202. package/payload/server/public/assets/radar-PYXPWWZC-DnPLBl-D.js +0 -1
  203. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-v4ND10uR.js +0 -1
  204. package/payload/server/public/assets/treeView-SZITEDCU-C3cb7Xwe.js +0 -1
  205. package/payload/server/public/assets/treemap-W4RFUUIX-Dc7G3Bgm.js +0 -1
  206. package/payload/server/public/assets/useSelectionMode-DwsyptOw.js +0 -5
  207. package/payload/server/public/assets/wardley-RL74JXVD-DtgibWAt.js +0 -1
  208. /package/payload/server/public/assets/{_baseFor-Cam2PbSt.js → _baseFor-Cs8Y-rGh.js} +0 -0
  209. /package/payload/server/public/assets/{array-DYRGGQae.js → array-iHZP4KWJ.js} +0 -0
  210. /package/payload/server/public/assets/{cytoscape.esm-nWsJMTNI.js → cytoscape.esm-BR2GOQ8_.js} +0 -0
  211. /package/payload/server/public/assets/{defaultLocale-Du1XY3Dp.js → defaultLocale-B9aLeOTg.js} +0 -0
  212. /package/payload/server/public/assets/{dist-BzAsli7o.js → dist-DB-VPj_8.js} +0 -0
  213. /package/payload/server/public/assets/{init-B5BXBRcm.js → init-BNFRgqHM.js} +0 -0
  214. /package/payload/server/public/assets/{katex-HOUACuRw.js → katex-B-EfS3nw.js} +0 -0
  215. /package/payload/server/public/assets/{path-CNO468J-.js → path-DmWWdwp7.js} +0 -0
  216. /package/payload/server/public/assets/{rough.esm-DRO6hWPh.js → rough.esm-Ci7Kjt46.js} +0 -0
  217. /package/payload/server/public/assets/{src-CWiyyVfn.js → src-C1jfwBq0.js} +0 -0
@@ -1,395 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Task 634 — on-demand `/insight` UserPromptSubmit hook test suite.
3
- #
4
- # Listener-mock pattern: a local Python HTTP server stands in for
5
- # /api/admin/log-ingest and records every POST so the assertions can read
6
- # every log line the hook emitted.
7
- #
8
- # Contract under test (run-and-continue, no Stop gate):
9
- # - Event is UserPromptSubmit. Trigger detection reads the `prompt` field
10
- # of the stdin envelope, NOT the transcript. The token `/insight` is
11
- # matched case-insensitively, as the whole message (after strip) OR as a
12
- # standalone line — never embedded in prose.
13
- # - On match: the four-pass instruction is printed to STDOUT (UserPromptSubmit
14
- # stdout is injected as turn context), `trigger sessionId=<id> token=/insight`
15
- # is emitted via log-ingest, exit 0. No stderr instruction, no exit 2.
16
- # - Every gated-off / non-match path emits one `trigger-skipped reason=<r>`
17
- # line and exits 0:
18
- # role-not-admin | is-specialist | empty-stdin | missing-transcript |
19
- # no-insight-token
20
- # - Standing reconciliation: on every invocation the hook scans the
21
- # transcript (`transcript_path`) for the latest real-user turn whose text
22
- # matches `/insight`; if no `session-retrospective-mark-complete` tool_use
23
- # appears after that turn, it emits
24
- # `prior-incomplete sessionId=<id> triggered-turn=<idx>`. A sentinel after
25
- # the latest `/insight` turn suppresses the emit.
26
- # - All log emissions go through POST /api/admin/log-ingest. The only stdout
27
- # writer is the instruction block on the trigger path.
28
-
29
- set -u
30
-
31
- HOOK="$(cd "$(dirname "$0")/.." && pwd)/insight.sh"
32
- if [[ ! -x "$HOOK" ]]; then
33
- echo "FAIL: $HOOK not executable" >&2
34
- exit 1
35
- fi
36
-
37
- OP_ID='aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb'
38
-
39
- TMPFILES=()
40
- LISTENER_PIDS=()
41
- cleanup_test_state() {
42
- for pid in "${LISTENER_PIDS[@]:-}"; do
43
- if [[ -n "$pid" ]]; then
44
- kill "$pid" 2>/dev/null || true
45
- wait "$pid" 2>/dev/null || true
46
- fi
47
- done
48
- for f in "${TMPFILES[@]:-}"; do
49
- [[ -n "$f" ]] && rm -f "$f" 2>/dev/null || true
50
- done
51
- }
52
- trap cleanup_test_state EXIT
53
-
54
- PASS=0
55
- FAIL=0
56
- pass() { echo "PASS: $1"; PASS=$((PASS + 1)); }
57
- fail() { echo "FAIL: $1" >&2; FAIL=$((FAIL + 1)); }
58
-
59
- start_listener() {
60
- REQ_LOG=$(mktemp); TMPFILES+=("$REQ_LOG")
61
- LISTENER_PORT=$((39500 + RANDOM % 100))
62
- python3 - "$LISTENER_PORT" "$REQ_LOG" <<'PY' &
63
- import sys, http.server, json
64
- port = int(sys.argv[1])
65
- log_path = sys.argv[2]
66
- class H(http.server.BaseHTTPRequestHandler):
67
- def log_message(self, *a, **k): pass
68
- def do_POST(self):
69
- n = int(self.headers.get('Content-Length','0') or 0)
70
- body = self.rfile.read(n).decode('utf-8','replace')
71
- with open(log_path, 'a', encoding='utf-8') as f:
72
- f.write(self.path + '\t' + body + '\n')
73
- self.send_response(200)
74
- self.send_header('Content-Type','application/json')
75
- self.end_headers()
76
- self.wfile.write(json.dumps({"ok": True}).encode('utf-8'))
77
- http.server.HTTPServer(('127.0.0.1', port), H).serve_forever()
78
- PY
79
- LISTENER_PIDS+=("$!")
80
- for _ in $(seq 1 20); do
81
- if curl -sS --max-time 1 -X POST "http://127.0.0.1:${LISTENER_PORT}/ping" -d '{}' >/dev/null 2>&1; then
82
- break
83
- fi
84
- sleep 0.1
85
- done
86
- : > "$REQ_LOG"
87
- }
88
-
89
- run_hook() {
90
- local role="$1"; local specialist="$2"; local stdin_json="$3"
91
- local stderr_file; stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
92
- local stdout_file; stdout_file=$(mktemp); TMPFILES+=("$stdout_file")
93
- printf '%s' "$stdin_json" | \
94
- MAXY_SESSION_ROLE="$role" \
95
- MAXY_SPECIALIST="$specialist" \
96
- MAXY_UI_INTERNAL_PORT="$LISTENER_PORT" \
97
- bash "$HOOK" >"$stdout_file" 2>"$stderr_file"
98
- HOOK_RC=$?
99
- HOOK_STDERR=$(cat "$stderr_file")
100
- HOOK_STDOUT=$(cat "$stdout_file")
101
- sleep 0.1
102
- }
103
-
104
- ingest_lines() {
105
- grep -E '^/api/admin/log-ingest ' "$REQ_LOG" 2>/dev/null | python3 -c '
106
- import sys, json
107
- for raw in sys.stdin:
108
- try:
109
- _, body = raw.rstrip("\n").split("\t", 1)
110
- d = json.loads(body)
111
- if isinstance(d, dict) and isinstance(d.get("line"), str):
112
- print(d["line"])
113
- except Exception:
114
- pass
115
- ' || true
116
- }
117
-
118
- # Build a JSONL transcript from positional triples. Each triple is
119
- # role|text|extra where extra is one of:
120
- # "" → plain user/assistant text record
121
- # "tool_use:<NAME>" → assistant record carrying a tool_use block
122
- # "tool_result" → user record carrying only a tool_result block
123
- write_transcript() {
124
- local out="$1"; shift
125
- : > "$out"
126
- python3 - "$out" "$@" <<'PY'
127
- import sys, json
128
- out = sys.argv[1]
129
- spec = sys.argv[2:]
130
- with open(out, "w", encoding="utf-8") as f:
131
- for entry in spec:
132
- role, text, extra = entry.split("|", 2)
133
- rec = {"type": role, "timestamp": "2026-06-05T10:00:00.000Z"}
134
- if role == "user":
135
- if extra == "tool_result":
136
- rec["message"] = {
137
- "role": "user",
138
- "content": [
139
- {"type": "tool_result",
140
- "tool_use_id": "tu_x",
141
- "content": text or "ok"},
142
- ],
143
- }
144
- else:
145
- rec["message"] = {"role": "user", "content": text}
146
- else:
147
- content_blocks = []
148
- if text:
149
- content_blocks.append({"type": "text", "text": text})
150
- if extra.startswith("tool_use:"):
151
- tool_name = extra.split(":", 1)[1]
152
- content_blocks.append({
153
- "type": "tool_use",
154
- "id": f"toolu_{tool_name}",
155
- "name": tool_name,
156
- "input": {},
157
- })
158
- rec["message"] = {
159
- "id": f"msg_{role}_{hash(text) & 0xffff:04x}",
160
- "role": "assistant",
161
- "content": content_blocks,
162
- }
163
- f.write(json.dumps(rec) + "\n")
164
- PY
165
- }
166
-
167
- # UserPromptSubmit envelope: session_id, transcript_path, prompt, hook_event_name.
168
- envelope_for() {
169
- python3 -c '
170
- import json, sys
171
- print(json.dumps({
172
- "session_id": sys.argv[1],
173
- "transcript_path": sys.argv[2],
174
- "prompt": sys.argv[3],
175
- "hook_event_name": "UserPromptSubmit",
176
- }))
177
- ' "$1" "$2" "$3"
178
- }
179
-
180
- # A transcript with no prior /insight turn — used whenever the test is about
181
- # trigger detection and reconciliation must stay silent.
182
- NEUTRAL_TRANSCRIPT=$(mktemp); TMPFILES+=("$NEUTRAL_TRANSCRIPT")
183
-
184
- # ---------------------------------------------------------------------------
185
- # Case 1: role != admin → trigger-skipped reason=role-not-admin
186
- # ---------------------------------------------------------------------------
187
- start_listener
188
- write_transcript "$NEUTRAL_TRANSCRIPT" "user|hello|" "assistant|hi|"
189
- ENV_INSIGHT=$(envelope_for "$OP_ID" "$NEUTRAL_TRANSCRIPT" "/insight")
190
- : > "$REQ_LOG"
191
- run_hook "public" "" "$ENV_INSIGHT"
192
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-1 rc=$HOOK_RC"
193
- [[ -z "$HOOK_STDOUT" ]] || fail "case-1 stdout must be empty, got: $HOOK_STDOUT"
194
- if ingest_lines | grep -qE '^trigger-skipped sessionId=.* reason=role-not-admin$'; then
195
- pass "case-1 role=public → trigger-skipped reason=role-not-admin"
196
- else
197
- fail "case-1 expected role-not-admin, got: $(ingest_lines)"
198
- fi
199
-
200
- # ---------------------------------------------------------------------------
201
- # Case 2: MAXY_SPECIALIST set → trigger-skipped is-specialist
202
- # ---------------------------------------------------------------------------
203
- : > "$REQ_LOG"
204
- run_hook "admin" "database-operator" "$ENV_INSIGHT"
205
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-2 rc=$HOOK_RC"
206
- [[ -z "$HOOK_STDOUT" ]] || fail "case-2 stdout must be empty, got: $HOOK_STDOUT"
207
- if ingest_lines | grep -qE '^trigger-skipped sessionId=.* reason=is-specialist specialist=database-operator$'; then
208
- pass "case-2 specialist=database-operator → trigger-skipped is-specialist"
209
- else
210
- fail "case-2 expected is-specialist, got: $(ingest_lines)"
211
- fi
212
-
213
- # ---------------------------------------------------------------------------
214
- # Case 3: empty stdin → trigger-skipped reason=empty-stdin
215
- # ---------------------------------------------------------------------------
216
- : > "$REQ_LOG"
217
- run_hook "admin" "" ""
218
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-3 rc=$HOOK_RC"
219
- if ingest_lines | grep -qE '^trigger-skipped sessionId=.* reason=empty-stdin$'; then
220
- pass "case-3 empty stdin → trigger-skipped reason=empty-stdin"
221
- else
222
- fail "case-3 expected empty-stdin, got: $(ingest_lines)"
223
- fi
224
-
225
- # ---------------------------------------------------------------------------
226
- # Case 4: missing transcript_path → trigger-skipped missing-transcript
227
- # ---------------------------------------------------------------------------
228
- : > "$REQ_LOG"
229
- BAD_ENV=$(python3 -c 'import json,sys; print(json.dumps({"session_id": sys.argv[1], "prompt": "/insight"}))' "$OP_ID")
230
- run_hook "admin" "" "$BAD_ENV"
231
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-4 rc=$HOOK_RC"
232
- if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=missing-transcript$"; then
233
- pass "case-4 missing transcript → trigger-skipped reason=missing-transcript"
234
- else
235
- fail "case-4 expected missing-transcript, got: $(ingest_lines)"
236
- fi
237
-
238
- # ---------------------------------------------------------------------------
239
- # Case 5: prompt has no /insight token → trigger-skipped reason=no-insight-token
240
- # ---------------------------------------------------------------------------
241
- ENV_BORING=$(envelope_for "$OP_ID" "$NEUTRAL_TRANSCRIPT" "what's the weather today")
242
- : > "$REQ_LOG"
243
- run_hook "admin" "" "$ENV_BORING"
244
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-5 rc=$HOOK_RC"
245
- [[ -z "$HOOK_STDOUT" ]] || fail "case-5 stdout must be empty"
246
- if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=no-insight-token$"; then
247
- pass "case-5 no token → trigger-skipped reason=no-insight-token"
248
- else
249
- fail "case-5 expected no-insight-token, got: $(ingest_lines)"
250
- fi
251
-
252
- # ---------------------------------------------------------------------------
253
- # Case 6: prompt is exactly /insight → instruction on stdout, trigger logged
254
- # ---------------------------------------------------------------------------
255
- : > "$REQ_LOG"
256
- run_hook "admin" "" "$ENV_INSIGHT"
257
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-6 expected rc=0, got $HOOK_RC"
258
- [[ -z "$HOOK_STDERR" ]] || fail "case-6 stderr must be empty (no exit-2 instruction path), got: $HOOK_STDERR"
259
- if ! printf '%s' "$HOOK_STDOUT" | grep -q "session-retrospective-mark-complete"; then
260
- fail "case-6 instruction (stdout) missing sentinel tool name"
261
- fi
262
- if ! printf '%s' "$HOOK_STDOUT" | grep -q "database-operator"; then
263
- fail "case-6 instruction (stdout) missing database-operator reference"
264
- fi
265
- if ! printf '%s' "$HOOK_STDOUT" | grep -qi "keep going\|continue"; then
266
- fail "case-6 instruction (stdout) missing run-and-continue wording"
267
- fi
268
- if ingest_lines | grep -qE "^trigger sessionId=${OP_ID} token=/insight$"; then
269
- pass "case-6 /insight whole-message → instruction on stdout + trigger logged"
270
- else
271
- fail "case-6 expected trigger line, got: $(ingest_lines)"
272
- fi
273
-
274
- # ---------------------------------------------------------------------------
275
- # Case 7: /insight as a standalone line among other lines → triggers
276
- # ---------------------------------------------------------------------------
277
- ENV_LINE=$(envelope_for "$OP_ID" "$NEUTRAL_TRANSCRIPT" $'here is some context\n/insight\nthanks')
278
- : > "$REQ_LOG"
279
- run_hook "admin" "" "$ENV_LINE"
280
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-7 rc=$HOOK_RC"
281
- if ingest_lines | grep -qE "^trigger sessionId=${OP_ID} token=/insight$"; then
282
- pass "case-7 /insight standalone line → triggers"
283
- else
284
- fail "case-7 expected trigger, got: $(ingest_lines)"
285
- fi
286
-
287
- # ---------------------------------------------------------------------------
288
- # Case 8: case-insensitive — /INSIGHT triggers, logged as /insight
289
- # ---------------------------------------------------------------------------
290
- ENV_CASE=$(envelope_for "$OP_ID" "$NEUTRAL_TRANSCRIPT" "/INSIGHT")
291
- : > "$REQ_LOG"
292
- run_hook "admin" "" "$ENV_CASE"
293
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-8 rc=$HOOK_RC"
294
- if ingest_lines | grep -qE "^trigger sessionId=${OP_ID} token=/insight$"; then
295
- pass "case-8 case-insensitive: /INSIGHT normalises to /insight"
296
- else
297
- fail "case-8 expected token=/insight, got: $(ingest_lines)"
298
- fi
299
-
300
- # ---------------------------------------------------------------------------
301
- # Case 9: embedded prose does NOT trigger
302
- # ---------------------------------------------------------------------------
303
- ENV_PROSE=$(envelope_for "$OP_ID" "$NEUTRAL_TRANSCRIPT" "can you give me some /insight into the numbers")
304
- : > "$REQ_LOG"
305
- run_hook "admin" "" "$ENV_PROSE"
306
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-9 rc=$HOOK_RC"
307
- [[ -z "$HOOK_STDOUT" ]] || fail "case-9 stdout must be empty (prose must not trigger)"
308
- if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=no-insight-token$"; then
309
- pass "case-9 embedded '/insight' prose does not trigger"
310
- else
311
- fail "case-9 expected no-insight-token, got: $(ingest_lines)"
312
- fi
313
-
314
- # ---------------------------------------------------------------------------
315
- # Case 10: reconciliation — prior /insight turn with NO sentinel after it →
316
- # prior-incomplete emitted (and current non-token prompt skips)
317
- # ---------------------------------------------------------------------------
318
- T_INCOMPLETE=$(mktemp); TMPFILES+=("$T_INCOMPLETE")
319
- write_transcript "$T_INCOMPLETE" \
320
- "user|hi|" \
321
- "assistant|hello|" \
322
- "user|/insight|" \
323
- "assistant|here is a prose summary|"
324
- ENV_RECON=$(envelope_for "$OP_ID" "$T_INCOMPLETE" "what's next")
325
- : > "$REQ_LOG"
326
- run_hook "admin" "" "$ENV_RECON"
327
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-10 rc=$HOOK_RC"
328
- if ! ingest_lines | grep -qE "^prior-incomplete sessionId=${OP_ID} triggered-turn=[0-9]+$"; then
329
- fail "case-10 expected prior-incomplete, got: $(ingest_lines)"
330
- elif ! ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=no-insight-token$"; then
331
- fail "case-10 expected current prompt skip, got: $(ingest_lines)"
332
- else
333
- pass "case-10 prior /insight without sentinel → prior-incomplete"
334
- fi
335
-
336
- # ---------------------------------------------------------------------------
337
- # Case 11: reconciliation negative — prior /insight turn WITH a sentinel
338
- # tool_use after it → no prior-incomplete
339
- # ---------------------------------------------------------------------------
340
- T_COMPLETE=$(mktemp); TMPFILES+=("$T_COMPLETE")
341
- write_transcript "$T_COMPLETE" \
342
- "user|hi|" \
343
- "user|/insight|" \
344
- "assistant|running passes|" \
345
- "assistant||tool_use:mcp__admin__session-retrospective-mark-complete"
346
- ENV_DONE=$(envelope_for "$OP_ID" "$T_COMPLETE" "what's next")
347
- : > "$REQ_LOG"
348
- run_hook "admin" "" "$ENV_DONE"
349
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-11 rc=$HOOK_RC"
350
- if ingest_lines | grep -qE "^prior-incomplete"; then
351
- fail "case-11 sentinel present must suppress prior-incomplete, got: $(ingest_lines)"
352
- else
353
- pass "case-11 prior /insight with sentinel → no prior-incomplete"
354
- fi
355
-
356
- # ---------------------------------------------------------------------------
357
- # Case 13: the just-submitted /insight turn is already in the transcript with
358
- # no assistant response yet → must NOT self-report prior-incomplete.
359
- # (Guards against the false positive if Claude Code writes the
360
- # current prompt to the transcript before UserPromptSubmit fires.)
361
- # ---------------------------------------------------------------------------
362
- T_CURRENT=$(mktemp); TMPFILES+=("$T_CURRENT")
363
- write_transcript "$T_CURRENT" \
364
- "user|hi|" \
365
- "assistant|hello|" \
366
- "user|/insight|"
367
- ENV_CURRENT=$(envelope_for "$OP_ID" "$T_CURRENT" "/insight")
368
- : > "$REQ_LOG"
369
- run_hook "admin" "" "$ENV_CURRENT"
370
- [[ "$HOOK_RC" -eq 0 ]] || fail "case-13 rc=$HOOK_RC"
371
- if ingest_lines | grep -qE "^prior-incomplete"; then
372
- fail "case-13 current /insight turn must not self-report prior-incomplete, got: $(ingest_lines)"
373
- elif ingest_lines | grep -qE "^trigger sessionId=${OP_ID} token=/insight$"; then
374
- pass "case-13 current /insight (in transcript, no response yet) → trigger only, no prior-incomplete"
375
- else
376
- fail "case-13 expected trigger without prior-incomplete, got: $(ingest_lines)"
377
- fi
378
-
379
- # ---------------------------------------------------------------------------
380
- # Case 12: no path returns exit 2 — /insight must not block the turn
381
- # ---------------------------------------------------------------------------
382
- : > "$REQ_LOG"
383
- run_hook "admin" "" "$ENV_INSIGHT"
384
- if [[ "$HOOK_RC" -eq 2 ]]; then
385
- fail "case-12 hook must never exit 2 (run-and-continue), got rc=$HOOK_RC"
386
- else
387
- pass "case-12 trigger path exits 0, never 2"
388
- fi
389
-
390
- # ---------------------------------------------------------------------------
391
- # Summary
392
- # ---------------------------------------------------------------------------
393
- echo
394
- echo "insight tests: $PASS passed, $FAIL failed"
395
- [[ "$FAIL" -eq 0 ]]
@@ -1,219 +0,0 @@
1
- #!/usr/bin/env bash
2
- # UserPromptSubmit hook — on-demand `/insight`. When the operator types the
3
- # literal token `/insight` as a standalone message (or a standalone line), the
4
- # admin agent runs a four-pass review (technical learnings, operator-
5
- # relationship updates, graph-completeness sweep, typed-edge auto-extraction)
6
- # over the session so far and calls the deterministic
7
- # `session-retrospective-mark-complete` MCP sentinel — then the session
8
- # CONTINUES. Nothing is blocked, terminated, reset, or cleared. Task 634
9
- # replaced the Task 282 session-end Stop gate with this trigger; the four
10
- # passes and the sentinel call are byte-for-byte the same process — only the
11
- # trigger and timing changed.
12
- #
13
- # Trigger detection. The token is read from the `prompt` field of the
14
- # UserPromptSubmit stdin envelope, case-insensitively, matching the whole
15
- # message (after .strip()) OR a standalone line within it — never embedded in
16
- # prose. This is the same whole-message / standalone-line discipline the
17
- # session-end gate applied to its end-intent tokens; it keeps "give me some
18
- # /insight into the numbers" from false-triggering.
19
- #
20
- # Injection. On a match the four-pass instruction is printed to STDOUT.
21
- # UserPromptSubmit stdout is appended to the turn as additional context, so the
22
- # agent receives the instruction alongside the operator's `/insight` message.
23
- # Structured logs go through POST /api/admin/log-ingest (never stdout), so the
24
- # injected context stays clean. There is no exit-2 path and no stderr
25
- # instruction — UserPromptSubmit cannot and must not block the turn.
26
- #
27
- # Standing reconciliation (no-event failure detector). The run-and-continue
28
- # model removes the Stop gate that previously forced completion, so the
29
- # dominant failure mode is "triggered but never completed" — the agent injects
30
- # the instruction, returns prose, and never calls the sentinel. Because this
31
- # hook fires on every prompt, it scans the transcript (`transcript_path`) each
32
- # invocation for the latest real-user turn whose text matches `/insight`; when
33
- # no `session-retrospective-mark-complete` tool_use appears after that turn it
34
- # emits `[insight] prior-incomplete sessionId=<id> triggered-turn=<idx>`. This
35
- # surfaces an unfinished pass on the next prompt without waiting for session
36
- # end and without reproducing the failure.
37
- # [[feedback_no_stdout_parsing_for_control_flow]] — the trigger is a literal
38
- # token match, never prose parsing.
39
- #
40
- # Gating (common guards live in `lib/admin-graph-pass-common.sh`):
41
- # - role-not-admin / is-specialist / empty-stdin / missing-transcript:
42
- # handled by the shared helper, emit `trigger-skipped` and exit 0.
43
- # - no-insight-token: the prompt carries no standalone `/insight` token,
44
- # emit `trigger-skipped` and exit 0.
45
- #
46
- # Input: Claude Code's UserPromptSubmit stdin shape
47
- # { "session_id": "<id>", "transcript_path": "<jsonl path>",
48
- # "prompt": "<operator message>", "hook_event_name": "UserPromptSubmit" }
49
-
50
- set -uo pipefail
51
-
52
- AGP_LOG_TAG="insight"
53
- AGP_LIB="$(dirname "$0")/lib/admin-graph-pass-common.sh"
54
- if [ ! -f "$AGP_LIB" ]; then
55
- echo "[${AGP_LOG_TAG}] trigger-skipped sessionId=unknown reason=missing-helper path=${AGP_LIB}" >&2
56
- exit 0
57
- fi
58
- # shellcheck source=lib/admin-graph-pass-common.sh
59
- source "$AGP_LIB"
60
-
61
- agp_setup_logging
62
- agp_read_stdin
63
- agp_parse_stdin
64
- agp_guard_role_specialist
65
- agp_guard_transcript require-stdin
66
-
67
- # Extract the operator's raw prompt from the envelope. Empty when absent.
68
- PROMPT=$(printf '%s' "$INPUT" | python3 -c '
69
- import sys, json
70
- try:
71
- d = json.load(sys.stdin)
72
- p = d.get("prompt", "") or ""
73
- sys.stdout.write(p if isinstance(p, str) else "")
74
- except Exception:
75
- pass
76
- ' 2>/dev/null)
77
-
78
- # Single Python pass reports two facts on one line:
79
- # 1. Whether PROMPT carries a standalone `/insight` token → token or empty.
80
- # 2. Reconciliation: the index of the latest real-user transcript turn whose
81
- # text matches `/insight` that has NO subsequent
82
- # `session-retrospective-mark-complete` tool_use → index or empty.
83
- # Output: <trigger-token-or-empty>\t<prior-incomplete-idx-or-empty>
84
- INSPECTION=$(PROMPT="$PROMPT" TRANSCRIPT_PATH="$TRANSCRIPT_PATH" python3 - <<'PY'
85
- import os, json
86
-
87
- SENTINEL_TOOL = "mcp__admin__session-retrospective-mark-complete"
88
- TOKEN = "/insight"
89
-
90
- def text_has_standalone_token(text):
91
- # Case-insensitive: token is the whole message (after strip) OR a
92
- # standalone line within it. Never matches the token embedded in prose.
93
- if not text:
94
- return False
95
- haystacks = {text.strip().lower()}
96
- for line in text.splitlines():
97
- s = line.strip().lower()
98
- if s:
99
- haystacks.add(s)
100
- return TOKEN in haystacks
101
-
102
- def is_real_user(rec):
103
- if not isinstance(rec, dict) or rec.get("type") != "user":
104
- return False
105
- msg = rec.get("message")
106
- if not isinstance(msg, dict) or msg.get("role") != "user":
107
- return False
108
- content = msg.get("content")
109
- if isinstance(content, str):
110
- return True
111
- if isinstance(content, list):
112
- for b in content:
113
- if isinstance(b, dict) and b.get("type") != "tool_result":
114
- return True
115
- return False
116
- return True
117
-
118
- def extract_user_text(rec):
119
- msg = rec.get("message", {}) or {}
120
- content = msg.get("content")
121
- if isinstance(content, str):
122
- return content
123
- if isinstance(content, list):
124
- out = []
125
- for b in content:
126
- if isinstance(b, dict) and b.get("type") == "text":
127
- t = b.get("text")
128
- if isinstance(t, str):
129
- out.append(t)
130
- return "".join(out)
131
- return ""
132
-
133
- def is_assistant(rec):
134
- return (isinstance(rec, dict) and rec.get("type") == "assistant"
135
- and isinstance(rec.get("message"), dict)
136
- and rec["message"].get("role") == "assistant")
137
-
138
- def assistant_tool_use_names(rec):
139
- if not is_assistant(rec):
140
- return []
141
- content = rec["message"].get("content")
142
- if not isinstance(content, list):
143
- return []
144
- return [b.get("name") for b in content
145
- if isinstance(b, dict) and b.get("type") == "tool_use"
146
- and isinstance(b.get("name"), str)]
147
-
148
- # Trigger — read from the prompt field, not the transcript.
149
- trigger = TOKEN if text_has_standalone_token(os.environ.get("PROMPT", "")) else ""
150
-
151
- # Reconciliation — scan the transcript for the latest real-user `/insight`
152
- # turn and check whether a sentinel tool_use follows it.
153
- records = []
154
- try:
155
- with open(os.environ["TRANSCRIPT_PATH"], "r", encoding="utf-8") as f:
156
- for raw in f:
157
- raw = raw.strip()
158
- if not raw:
159
- continue
160
- try:
161
- records.append(json.loads(raw))
162
- except Exception:
163
- continue
164
- except Exception:
165
- records = []
166
-
167
- latest_insight_idx = -1
168
- for i in range(len(records) - 1, -1, -1):
169
- if is_real_user(records[i]) and text_has_standalone_token(extract_user_text(records[i])):
170
- latest_insight_idx = i
171
- break
172
-
173
- prior_incomplete = ""
174
- if latest_insight_idx != -1:
175
- after = records[latest_insight_idx + 1:]
176
- # "Triggered but never completed" means the agent RESPONDED to the
177
- # `/insight` turn (≥1 assistant record after it) yet never called the
178
- # sentinel. Requiring an assistant record excludes the just-submitted
179
- # `/insight` turn — which has no response yet — so a genuine trigger
180
- # never self-reports as incomplete, regardless of whether Claude Code
181
- # has already written the current prompt to the transcript.
182
- assistant_after = any(is_assistant(r) for r in after)
183
- sentinel_after = any(SENTINEL_TOOL in assistant_tool_use_names(r) for r in after)
184
- if assistant_after and not sentinel_after:
185
- prior_incomplete = str(latest_insight_idx)
186
-
187
- print(f"{trigger}\t{prior_incomplete}")
188
- PY
189
- )
190
- TRIGGER_TOKEN="${INSPECTION%% *}"
191
- PRIOR_INCOMPLETE_IDX="${INSPECTION#* }"
192
-
193
- # Standing reconciliation emit — independent of the current trigger.
194
- if [ -n "$PRIOR_INCOMPLETE_IDX" ]; then
195
- agp_emit_log "prior-incomplete sessionId=${SESSION_ID} triggered-turn=${PRIOR_INCOMPLETE_IDX}"
196
- fi
197
-
198
- if [ -z "$TRIGGER_TOKEN" ]; then
199
- agp_emit_log "trigger-skipped sessionId=${SESSION_ID} reason=no-insight-token"
200
- exit 0
201
- fi
202
-
203
- agp_emit_log "trigger sessionId=${SESSION_ID} token=${TRIGGER_TOKEN}"
204
-
205
- cat <<'INSTRUCTION'
206
- The operator requested an insight pass — run the four passes now over the session so far, then keep going in this same session. Do NOT call `session-reset`, do NOT clear the context, do NOT end the session: the conversation continues afterward and the operator (or a parallel session) keeps working against the same live state. Use the tools you already have.
207
-
208
- Pass 1 — Technical learnings. Walk this session for operator corrections and self-detected mistakes. For each one, delegate one graph write to `database-operator` via the Task tool, persisting a Learning or Correction node per the schema. Count what you write.
209
-
210
- Pass 2 — Operator-relationship updates. Walk this session for tonal signals, rejected phrasings, and working-style preferences. For each one worth carrying forward, Write the observation into `SOUL.md` at the account-scoped path. Count what you write.
211
-
212
- Pass 3 — Graph completeness sweep. Walk this session for any node, edge, or commitment that was discussed but not written to the graph in-flight. For each missing write, delegate to `database-operator` via the Task tool. Count what you write.
213
-
214
- Pass 4 — Typed-edge auto-extraction. Delegate to `database-operator` via the Task tool with a prompt naming the typed-edge pass and the session-start timestamp. The specialist calls `memory-typed-edge-pass` with that timestamp and returns the counters. Capture `nodesProcessed` and the accepted count from its reply.
215
-
216
- Then call `session-retrospective-mark-complete` with all five counts (learningsCount, preferencesCount, graphWriteCount, typedEdgesCount, nodesProcessed) and reply with one short paragraph in your house voice summarising what you wrote — then carry on with the operator's work.
217
- INSTRUCTION
218
-
219
- exit 0