@rubytech/create-maxy-code 0.1.83 → 0.1.85

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 (149) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-memory-write-revoke.test.sh +142 -24
  3. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +131 -218
  4. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +85 -17
  5. package/payload/platform/plugins/cloudflare/PLUGIN.md +2 -11
  6. package/payload/platform/plugins/cloudflare/scripts/__tests__/setup-tunnel-display-precedence.test.sh +194 -0
  7. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +43 -21
  8. package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +29 -10
  9. package/payload/platform/plugins/docs/references/cloudflare.md +10 -9
  10. package/payload/platform/scripts/seed-neo4j.sh +12 -0
  11. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  12. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +13 -18
  13. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  14. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
  15. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/SKILL.md +3 -1
  16. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/template.html +17 -7
  17. package/payload/server/{chunk-TFEIFU7F.js → chunk-BDFOTLPW.js} +1 -1
  18. package/payload/server/{chunk-W33UUYYR.js → chunk-BVDLDM6O.js} +1 -1
  19. package/payload/server/{chunk-VGMVEYX7.js → chunk-JRBCOVA4.js} +64 -5
  20. package/payload/server/{cloudflare-task-tracker-7P355PSD.js → cloudflare-task-tracker-M5ONAGUT.js} +2 -2
  21. package/payload/server/maxy-edge.js +2 -2
  22. package/payload/server/public/assets/Checkbox-B34vplI7.js +1 -0
  23. package/payload/server/public/assets/{admin-BHaOSIuo.js → admin-BkTlPuP0.js} +5 -5
  24. package/payload/server/public/assets/{arc-aUiRP9AS.js → arc-DMDAZHAN.js} +1 -1
  25. package/payload/server/public/assets/architecture-YZFGNWBL-COhEvUpo.js +1 -0
  26. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-B8o-_aT-.js → architectureDiagram-Q4EWVU46-DQMCKDU2.js} +1 -1
  27. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BcprLXNk.js → blockDiagram-DXYQGD6D-CqJNtiQY.js} +1 -1
  28. package/payload/server/public/assets/{brand-kwAWaknq.js → brand-HqTMr1bV.js} +1 -1
  29. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CAkKlTxa.js → c4Diagram-AHTNJAMY-BVAa1YL3.js} +1 -1
  30. package/payload/server/public/assets/channel-CZG4mVkt.js +1 -0
  31. package/payload/server/public/assets/{chunk-2KRD3SAO-BK3470lx.js → chunk-2KRD3SAO-Di4bO8ir.js} +1 -1
  32. package/payload/server/public/assets/chunk-336JU56O-XIsdqKyD.js +2 -0
  33. package/payload/server/public/assets/chunk-426QAEUC-Dw4mcMYK.js +1 -0
  34. package/payload/server/public/assets/{chunk-4BX2VUAB-BOvVdJLf.js → chunk-4BX2VUAB-DyEhFk-Z.js} +1 -1
  35. package/payload/server/public/assets/{chunk-4TB4RGXK-MLx8Jj8R.js → chunk-4TB4RGXK-BvrlG2FS.js} +1 -1
  36. package/payload/server/public/assets/{chunk-55IACEB6-BwZyF7vR.js → chunk-55IACEB6-BRJOZLpU.js} +1 -1
  37. package/payload/server/public/assets/{chunk-5FUZZQ4R-DFWTZhLd.js → chunk-5FUZZQ4R-3-UZ9191.js} +1 -1
  38. package/payload/server/public/assets/{chunk-5PVQY5BW-vTE3gFPo.js → chunk-5PVQY5BW-DOeY60Lp.js} +1 -1
  39. package/payload/server/public/assets/{chunk-67CJDMHE-D5bhMrtY.js → chunk-67CJDMHE-BG6-9r6c.js} +1 -1
  40. package/payload/server/public/assets/{chunk-7N4EOEYR-Si7Lgrwc.js → chunk-7N4EOEYR-BvMbitX7.js} +1 -1
  41. package/payload/server/public/assets/{chunk-AA7GKIK3-DMuHtDqO.js → chunk-AA7GKIK3-CE8mGBD5.js} +1 -1
  42. package/payload/server/public/assets/{chunk-BSJP7CBP-L79XKVcb.js → chunk-BSJP7CBP-DP7LTBll.js} +1 -1
  43. package/payload/server/public/assets/{chunk-CIAEETIT-C0O7Upmg.js → chunk-CIAEETIT-VfnIdN-h.js} +1 -1
  44. package/payload/server/public/assets/{chunk-EDXVE4YY-Bp1I_rQl.js → chunk-EDXVE4YY-BSbGSOxN.js} +1 -1
  45. package/payload/server/public/assets/{chunk-ENJZ2VHE-DsDBZ8WH.js → chunk-ENJZ2VHE-CszgAcWZ.js} +1 -1
  46. package/payload/server/public/assets/{chunk-FMBD7UC4-C_E43NFJ.js → chunk-FMBD7UC4-w-yBZsN2.js} +1 -1
  47. package/payload/server/public/assets/{chunk-FOC6F5B3-D9lWWHAu.js → chunk-FOC6F5B3-f9cFywhd.js} +1 -1
  48. package/payload/server/public/assets/{chunk-ICPOFSXX-BKO6vxzn.js → chunk-ICPOFSXX-rgw1I6pt.js} +2 -2
  49. package/payload/server/public/assets/{chunk-K5T4RW27-DuhsNH4c.js → chunk-K5T4RW27-B_ZUrFUq.js} +1 -1
  50. package/payload/server/public/assets/{chunk-KGLVRYIC-B4-A1Abi.js → chunk-KGLVRYIC-CcWTvRlI.js} +1 -1
  51. package/payload/server/public/assets/{chunk-LIHQZDEY-BxqgHRgT.js → chunk-LIHQZDEY-D-5-peQw.js} +1 -1
  52. package/payload/server/public/assets/{chunk-ORNJ4GCN-DEYQ5WaJ.js → chunk-ORNJ4GCN-B4Z5L25I.js} +1 -1
  53. package/payload/server/public/assets/{chunk-OYMX7WX6-D-ievGGw.js → chunk-OYMX7WX6-DL4v2Nx4.js} +1 -1
  54. package/payload/server/public/assets/chunk-QZHKN3VN-CWh_0JsP.js +1 -0
  55. package/payload/server/public/assets/{chunk-U2HBQHQK-D_5PbJhp.js → chunk-U2HBQHQK-CwMCwyfq.js} +1 -1
  56. package/payload/server/public/assets/{chunk-X2U36JSP-QmmoxQya.js → chunk-X2U36JSP-CvKfDVvq.js} +1 -1
  57. package/payload/server/public/assets/{chunk-XPW4576I-CBfZXZDB.js → chunk-XPW4576I-m1Y_r88I.js} +1 -1
  58. package/payload/server/public/assets/{chunk-YZCP3GAM-BXSWZZag.js → chunk-YZCP3GAM-D7vju2_U.js} +1 -1
  59. package/payload/server/public/assets/{chunk-ZZ45TVLE-oyzperET.js → chunk-ZZ45TVLE-sANOwJKn.js} +1 -1
  60. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BoqQ3pHg.js +1 -0
  61. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-FoKuBK7n.js +1 -0
  62. package/payload/server/public/assets/clone-CT8AM-bU.js +1 -0
  63. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-Br2gjtEO.js → cose-bilkent-S5V4N54A-BhtgY3T7.js} +1 -1
  64. package/payload/server/public/assets/{dagre-65Q3iWcL.js → dagre-CplqWwSs.js} +1 -1
  65. package/payload/server/public/assets/{dagre-KV5264BT-Cyc37LVU.js → dagre-KV5264BT-DNbl5g9o.js} +1 -1
  66. package/payload/server/public/assets/data-BIDM6J5V.js +1 -0
  67. package/payload/server/public/assets/{device-url-actions-BftdR4st.js → device-url-actions-nxh9PmIH.js} +1 -1
  68. package/payload/server/public/assets/{diagram-5BDNPKRD-DKItZE_3.js → diagram-5BDNPKRD-BCdMaYnY.js} +1 -1
  69. package/payload/server/public/assets/{diagram-G4DWMVQ6-DKlYJZby.js → diagram-G4DWMVQ6-8XhDBU0o.js} +1 -1
  70. package/payload/server/public/assets/{diagram-MMDJMWI5-DLqF5x2e.js → diagram-MMDJMWI5-M-RMQgtx.js} +1 -1
  71. package/payload/server/public/assets/{diagram-TYMM5635-Cdufrh7g.js → diagram-TYMM5635-BBHPIBvQ.js} +1 -1
  72. package/payload/server/public/assets/{erDiagram-SMLLAGMA-D6eSXJWj.js → erDiagram-SMLLAGMA-D6jOL-9s.js} +1 -1
  73. package/payload/server/public/assets/{flatten-Bo6YRmWl.js → flatten-BsWEYbBB.js} +1 -1
  74. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BB4luljp.js → flowDiagram-DWJPFMVM-CiyTYRlU.js} +1 -1
  75. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-USBgsV4V.js → ganttDiagram-T4ZO3ILL-DHSIpjfS.js} +1 -1
  76. package/payload/server/public/assets/gitGraph-7Q5UKJZL-DeTNsAO0.js +1 -0
  77. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BqyKsQZ9.js → gitGraphDiagram-UUTBAWPF-CEneVF3o.js} +1 -1
  78. package/payload/server/public/assets/graph-Cm-iWFqy.js +1 -0
  79. package/payload/server/public/assets/graph-labels-CFX6KkCz.js +1 -0
  80. package/payload/server/public/assets/{graphlib-C5MkULnV.js → graphlib-CuF7rLfE.js} +1 -1
  81. package/payload/server/public/assets/info-OMHHGYJF-DJJ9GlS6.js +1 -0
  82. package/payload/server/public/assets/infoDiagram-42DDH7IO-wGl-JoP7.js +2 -0
  83. package/payload/server/public/assets/{isEmpty-D6Kr-M1M.js → isEmpty-BWl67LAZ.js} +1 -1
  84. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CODjk_-5.js → ishikawaDiagram-UXIWVN3A-B3TxFNi_.js} +1 -1
  85. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-RyhxP8aB.js → journeyDiagram-VCZTEJTY-B5n8No7p.js} +1 -1
  86. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-jrm_4IpR.js → kanban-definition-6JOO6SKY-ByGF39_h.js} +1 -1
  87. package/payload/server/public/assets/{line-DsE8JMaX.js → line-Br0FyyFW.js} +1 -1
  88. package/payload/server/public/assets/{linear-DOh_6k2k.js → linear-0O14Y6uf.js} +1 -1
  89. package/payload/server/public/assets/{mermaid-parser.core-F27uElsX.js → mermaid-parser.core-BUcTjodx.js} +2 -2
  90. package/payload/server/public/assets/{mermaid.core-B0PzAHME.js → mermaid.core-BKzdtZgG.js} +3 -3
  91. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-GA-xLC9K.js → mindmap-definition-QFDTVHPH-CobGMF9l.js} +1 -1
  92. package/payload/server/public/assets/{ordinal-BDi6f4xk.js → ordinal-krseTxxN.js} +1 -1
  93. package/payload/server/public/assets/packet-4T2RLAQJ-CGbvGkvF.js +1 -0
  94. package/payload/server/public/assets/{page-vRUDyjk4.js → page-B5NRnW0t.js} +1 -1
  95. package/payload/server/public/assets/{page-CXFoiyRN.js → page-Ba0BAfpu.js} +2 -2
  96. package/payload/server/public/assets/pie-ZZUOXDRM-BZy8rjFn.js +1 -0
  97. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CkP9U2tn.js → pieDiagram-DEJITSTG-DXFmGcNR.js} +1 -1
  98. package/payload/server/public/assets/{public-B_gqH5Cf.js → public-DWfBzf83.js} +5 -5
  99. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-sYIgx5bu.js → quadrantDiagram-34T5L4WZ-BnChStlO.js} +1 -1
  100. package/payload/server/public/assets/radar-PYXPWWZC-DcfWIVXr.js +1 -0
  101. package/payload/server/public/assets/{reduce-CGi9ik8i.js → reduce-tk-xY6Fv.js} +1 -1
  102. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CKtMUXvK.js → requirementDiagram-MS252O5E-DdiBKsyO.js} +1 -1
  103. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-CP5qebN_.js → sankeyDiagram-XADWPNL6-16-np_56.js} +1 -1
  104. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-zvkjl2R6.js → sequenceDiagram-FGHM5R23-D67SCRpA.js} +1 -1
  105. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-D-1VwYNL.js → stateDiagram-FHFEXIEX-CvNJX0YC.js} +1 -1
  106. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CFw2U4iL.js +1 -0
  107. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BSd_xlMt.js → timeline-definition-GMOUNBTQ-BJE5YoBa.js} +1 -1
  108. package/payload/server/public/assets/treeView-SZITEDCU-3WugwVdj.js +1 -0
  109. package/payload/server/public/assets/treemap-W4RFUUIX-Cf5mDLlu.js +1 -0
  110. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-D1hxlYfF.js → vennDiagram-DHZGUBPP-DF17ddXt.js} +1 -1
  111. package/payload/server/public/assets/wardley-RL74JXVD-Bv4md4b3.js +1 -0
  112. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-yNOC0LD-.js → wardleyDiagram-NUSXRM2D-xn_2XUOo.js} +1 -1
  113. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-D9D_gyVi.js → xychartDiagram-5P7HB3ND-DVF8zf3f.js} +1 -1
  114. package/payload/server/public/data.html +4 -4
  115. package/payload/server/public/graph.html +5 -4
  116. package/payload/server/public/index.html +7 -6
  117. package/payload/server/public/public.html +4 -3
  118. package/payload/server/server.js +229 -22
  119. package/payload/server/public/assets/architecture-YZFGNWBL--v-pJPNp.js +0 -1
  120. package/payload/server/public/assets/channel-C9mhUrr8.js +0 -1
  121. package/payload/server/public/assets/chunk-336JU56O-DZ53mw2n.js +0 -2
  122. package/payload/server/public/assets/chunk-426QAEUC-3s5PxkHp.js +0 -1
  123. package/payload/server/public/assets/chunk-QZHKN3VN-Bd-GrQM6.js +0 -1
  124. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BXiYcaCJ.js +0 -1
  125. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BRxESuCS.js +0 -1
  126. package/payload/server/public/assets/clone-Bz40VsQ_.js +0 -1
  127. package/payload/server/public/assets/data-DU2ZQbl-.js +0 -1
  128. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CI0s_tqn.js +0 -1
  129. package/payload/server/public/assets/graph-BgLMP7mY.js +0 -1
  130. package/payload/server/public/assets/graph-labels-CUN_9NnB.js +0 -1
  131. package/payload/server/public/assets/info-OMHHGYJF-g3gYW7Qm.js +0 -1
  132. package/payload/server/public/assets/infoDiagram-42DDH7IO-BF1spWbk.js +0 -2
  133. package/payload/server/public/assets/packet-4T2RLAQJ-CT0TB9HI.js +0 -1
  134. package/payload/server/public/assets/pie-ZZUOXDRM-CXLe7TFF.js +0 -1
  135. package/payload/server/public/assets/radar-PYXPWWZC-DnPLBl-D.js +0 -1
  136. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BGmOYY_E.js +0 -1
  137. package/payload/server/public/assets/treeView-SZITEDCU-C3cb7Xwe.js +0 -1
  138. package/payload/server/public/assets/treemap-W4RFUUIX-Dc7G3Bgm.js +0 -1
  139. package/payload/server/public/assets/wardley-RL74JXVD-DtgibWAt.js +0 -1
  140. /package/payload/server/public/assets/{_baseFor-Cam2PbSt.js → _baseFor-BHtDrjIo.js} +0 -0
  141. /package/payload/server/public/assets/{array-DYRGGQae.js → array-DetWRiSa.js} +0 -0
  142. /package/payload/server/public/assets/{cytoscape.esm-nWsJMTNI.js → cytoscape.esm-C9yNhe1u.js} +0 -0
  143. /package/payload/server/public/assets/{defaultLocale-Du1XY3Dp.js → defaultLocale-_WRwicXn.js} +0 -0
  144. /package/payload/server/public/assets/{dist-BzAsli7o.js → dist-Bd4S37oi.js} +0 -0
  145. /package/payload/server/public/assets/{init-B5BXBRcm.js → init-sTEcj9YX.js} +0 -0
  146. /package/payload/server/public/assets/{katex-HOUACuRw.js → katex-s61Rgv6l.js} +0 -0
  147. /package/payload/server/public/assets/{path-CNO468J-.js → path-B0Ik7Tu9.js} +0 -0
  148. /package/payload/server/public/assets/{rough.esm-DRO6hWPh.js → rough.esm-DKRO8IF-.js} +0 -0
  149. /package/payload/server/public/assets/{src-CWiyyVfn.js → src-B6XdH6xq.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.83",
3
+ "version": "0.1.85",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -1,9 +1,15 @@
1
1
  #!/usr/bin/env bash
2
- # Task 213 regression test for the memory-write / memory-update revoke
3
- # block in pre-tool-use.sh. The block sits at the top of the admin branch
4
- # and ensures any admin tool_use targeting the two writers exits 2 with
5
- # stderr explaining the recorder ownership, and emits one structured
6
- # `admin-tool-revoke` line through `/api/admin/log-ingest`.
2
+ # Task 213 (rev. Task 222) regression test for the memory-write /
3
+ # memory-update gate in pre-tool-use.sh. The block sits at the top of the
4
+ # admin branch and:
5
+ # * Blocks an admin direct call (parent JSONL transcript_path) with
6
+ # exit 2, stderr explaining the delegation contract, and one structured
7
+ # `admin-tool-revoke` line carrying caller=admin source=hook result=rejected.
8
+ # * Allows a Task subagent call (transcript_path matches subagent path
9
+ # pattern) with exit 0 and a structured `admin-tool-revoke` line
10
+ # carrying caller=subagent:<type> source=hook-passthrough result=allowed.
11
+ # * Fail-closed blocks any payload with missing/malformed
12
+ # transcript_path, emitting caller=unknown source=hook result=rejected.
7
13
 
8
14
  set -u
9
15
 
@@ -58,17 +64,21 @@ PY
58
64
  run_with_tool() {
59
65
  local tool="$1"
60
66
  local sid="$2"
67
+ local transcript_path="${3:-}"
61
68
  local stdout_file; stdout_file=$(mktemp); TMPFILES+=("$stdout_file")
62
69
  local stderr_file; stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
63
70
  python3 -c '
64
71
  import json, sys
65
- print(json.dumps({
72
+ payload = {
66
73
  "hook_event_name": "PreToolUse",
67
74
  "session_id": sys.argv[1],
68
75
  "tool_name": sys.argv[2],
69
76
  "tool_input": {"name":"Smalleys","accountId":"acct-x","scope":"shared"},
70
- }, separators=(",", ":")))
71
- ' "$sid" "$tool" | \
77
+ }
78
+ if sys.argv[3]:
79
+ payload["transcript_path"] = sys.argv[3]
80
+ print(json.dumps(payload, separators=(",", ":")))
81
+ ' "$sid" "$tool" "$transcript_path" | \
72
82
  MAXY_UI_INTERNAL_PORT="$LISTENER_PORT" \
73
83
  bash "$HOOK" admin >"$stdout_file" 2>"$stderr_file"
74
84
  HOOK_RC=$?
@@ -76,33 +86,141 @@ print(json.dumps({
76
86
  sleep 0.1 # let listener flush
77
87
  }
78
88
 
89
+ # Helper: stage a synthetic parent transcript + subagent transcript pair
90
+ # under a temp dir. The parent transcript carries one Task tool_use whose
91
+ # input.subagent_type = "$1"; the subagent transcript is empty (the hook
92
+ # does not depend on its contents — only on its path).
93
+ stage_subagent_transcripts() {
94
+ local subagent_type="$1"
95
+ local tmp_root; tmp_root=$(mktemp -d); TMPFILES+=("$tmp_root")
96
+ local sess_id; sess_id="abc-session-uuid"
97
+ local agent_id; agent_id="a1234567890abcdef"
98
+ local parent_jsonl="${tmp_root}/${sess_id}.jsonl"
99
+ local subagent_dir="${tmp_root}/${sess_id}/subagents"
100
+ mkdir -p "$subagent_dir"
101
+ local subagent_jsonl="${subagent_dir}/agent-${agent_id}.jsonl"
102
+ # Parent: minimal assistant row with a Task tool_use carrying subagent_type
103
+ python3 -c '
104
+ import json, sys
105
+ row = {
106
+ "type": "assistant",
107
+ "uuid": "u-1",
108
+ "parentUuid": None,
109
+ "sessionId": "abc-session-uuid",
110
+ "message": {
111
+ "role": "assistant",
112
+ "content": [
113
+ {"type": "tool_use", "id": "toolu_T1", "name": "Task",
114
+ "input": {"subagent_type": sys.argv[1], "description": "write Beacons"}}
115
+ ]
116
+ }
117
+ }
118
+ print(json.dumps(row, separators=(",", ":")))
119
+ ' "$subagent_type" > "$parent_jsonl"
120
+ # Subagent: empty file is enough — the hook only checks the path pattern
121
+ : > "$subagent_jsonl"
122
+ echo "$subagent_jsonl"
123
+ }
124
+
79
125
  start_listener
80
126
 
81
- # --- memory-write rejected ---------------------------------------------
127
+ # A parent-transcript path is the default for admin-direct cases. The
128
+ # hook treats any non-subagent path as admin direct, so a synthetic file
129
+ # in a temp dir suffices — we don't need to populate it.
130
+ ADMIN_TRANSCRIPT=$(mktemp); TMPFILES+=("$ADMIN_TRANSCRIPT")
131
+ : > "$ADMIN_TRANSCRIPT"
132
+
133
+ # --- admin-direct memory-write rejected, emits caller=admin -----------
82
134
  : > "$REQ_LOG"
83
- run_with_tool "mcp__plugin_memory_memory__memory-write" "sess-abc"
84
- [[ "$HOOK_RC" -eq 2 ]] || fail "memory-write expected exit 2, got $HOOK_RC"
85
- echo "$HOOK_STDERR" | grep -qF "admin agent does not write to the graph" \
86
- || fail "memory-write stderr missing rationale, got: $HOOK_STDERR"
87
- if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-abc.*tool=mcp__plugin_memory_memory__memory-write.*source=permission-hook' "$REQ_LOG"; then
88
- pass "memory-write rejection emits admin-tool-revoke with sessionId, tool, source"
135
+ run_with_tool "mcp__plugin_memory_memory__memory-write" "sess-abc" "$ADMIN_TRANSCRIPT"
136
+ [[ "$HOOK_RC" -eq 2 ]] || fail "admin-direct memory-write expected exit 2, got $HOOK_RC"
137
+ echo "$HOOK_STDERR" | grep -qF "admin agent does not write to the graph directly" \
138
+ || fail "admin-direct memory-write stderr missing rationale, got: $HOOK_STDERR"
139
+ if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-abc.*tool=mcp__plugin_memory_memory__memory-write.*caller=admin.*source=hook.*result=rejected' "$REQ_LOG"; then
140
+ pass "admin-direct memory-write blocks with caller=admin source=hook result=rejected"
89
141
  else
90
- fail "memory-write rejection did not emit admin-tool-revoke; log: $(cat "$REQ_LOG")"
142
+ fail "admin-direct memory-write did not emit expected log line; log: $(cat "$REQ_LOG")"
91
143
  fi
92
144
 
93
- # --- memory-update rejected --------------------------------------------
145
+ # --- admin-direct memory-update rejected, emits caller=admin ----------
94
146
  : > "$REQ_LOG"
95
- run_with_tool "mcp__plugin_memory_memory__memory-update" "sess-xyz"
96
- [[ "$HOOK_RC" -eq 2 ]] || fail "memory-update expected exit 2, got $HOOK_RC"
97
- if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-xyz.*tool=mcp__plugin_memory_memory__memory-update.*source=permission-hook' "$REQ_LOG"; then
98
- pass "memory-update rejection emits admin-tool-revoke with sessionId, tool, source"
147
+ run_with_tool "mcp__plugin_memory_memory__memory-update" "sess-xyz" "$ADMIN_TRANSCRIPT"
148
+ [[ "$HOOK_RC" -eq 2 ]] || fail "admin-direct memory-update expected exit 2, got $HOOK_RC"
149
+ if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-xyz.*tool=mcp__plugin_memory_memory__memory-update.*caller=admin.*source=hook.*result=rejected' "$REQ_LOG"; then
150
+ pass "admin-direct memory-update blocks with caller=admin source=hook result=rejected"
99
151
  else
100
- fail "memory-update rejection did not emit admin-tool-revoke; log: $(cat "$REQ_LOG")"
152
+ fail "admin-direct memory-update did not emit expected log line; log: $(cat "$REQ_LOG")"
101
153
  fi
102
154
 
155
+ # --- Task-subagent memory-write ALLOWED, emits caller=subagent:<type> -
156
+ # The path-pattern match (*/subagents/agent-*.jsonl) is the deterministic
157
+ # discriminator; the parent transcript carries the subagent_type for
158
+ # enrichment.
159
+ : > "$REQ_LOG"
160
+ SUB_TRANSCRIPT=$(stage_subagent_transcripts "database-operator")
161
+ run_with_tool "mcp__plugin_memory_memory__memory-write" "sess-sub-1" "$SUB_TRANSCRIPT"
162
+ [[ "$HOOK_RC" -eq 0 ]] || fail "subagent memory-write expected exit 0, got $HOOK_RC stderr: $HOOK_STDERR"
163
+ if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-sub-1.*tool=mcp__plugin_memory_memory__memory-write.*caller=subagent:database-operator.*source=hook-passthrough.*result=allowed' "$REQ_LOG"; then
164
+ pass "subagent memory-write allowed with caller=subagent:database-operator source=hook-passthrough result=allowed"
165
+ else
166
+ fail "subagent memory-write did not emit expected allow log line; log: $(cat "$REQ_LOG")"
167
+ fi
168
+
169
+ # --- Task-subagent memory-update ALLOWED ------------------------------
170
+ : > "$REQ_LOG"
171
+ SUB_TRANSCRIPT=$(stage_subagent_transcripts "database-operator")
172
+ run_with_tool "mcp__plugin_memory_memory__memory-update" "sess-sub-2" "$SUB_TRANSCRIPT"
173
+ [[ "$HOOK_RC" -eq 0 ]] || fail "subagent memory-update expected exit 0, got $HOOK_RC stderr: $HOOK_STDERR"
174
+ if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-sub-2.*tool=mcp__plugin_memory_memory__memory-update.*caller=subagent:database-operator.*source=hook-passthrough.*result=allowed' "$REQ_LOG"; then
175
+ pass "subagent memory-update allowed with caller=subagent:database-operator source=hook-passthrough result=allowed"
176
+ else
177
+ fail "subagent memory-update did not emit expected allow log line; log: $(cat "$REQ_LOG")"
178
+ fi
179
+
180
+ # --- Subagent path with unreadable parent transcript falls back to bare
181
+ # `caller=subagent` (no name) but still ALLOWS the call. The hook never
182
+ # blocks a legitimate subagent caller because the parent enrichment fails.
183
+ : > "$REQ_LOG"
184
+ ORPHAN_TMP=$(mktemp -d); TMPFILES+=("$ORPHAN_TMP")
185
+ ORPHAN_DIR="${ORPHAN_TMP}/orphan-sess/subagents"
186
+ mkdir -p "$ORPHAN_DIR"
187
+ ORPHAN_SUB="${ORPHAN_DIR}/agent-aorphanid.jsonl"
188
+ : > "$ORPHAN_SUB"
189
+ run_with_tool "mcp__plugin_memory_memory__memory-write" "sess-orphan" "$ORPHAN_SUB"
190
+ [[ "$HOOK_RC" -eq 0 ]] || fail "subagent w/ missing parent expected exit 0, got $HOOK_RC"
191
+ if grep -qE '/api/admin/log-ingest .*caller=subagent[^:].*source=hook-passthrough.*result=allowed' "$REQ_LOG"; then
192
+ pass "subagent caller without resolvable subagent_type falls back to bare 'subagent' label and still allows"
193
+ else
194
+ fail "subagent w/ missing parent did not fall back to bare caller=subagent; log: $(cat "$REQ_LOG")"
195
+ fi
196
+
197
+ # --- Missing transcript_path → fail-closed block, caller=unknown ------
198
+ : > "$REQ_LOG"
199
+ run_with_tool "mcp__plugin_memory_memory__memory-write" "sess-no-tp" ""
200
+ [[ "$HOOK_RC" -eq 2 ]] || fail "missing transcript_path expected exit 2 (fail-closed), got $HOOK_RC"
201
+ if grep -qE '/api/admin/log-ingest .*"tag":\s*"admin-tool-revoke".*sessionId=sess-no-tp.*caller=unknown.*source=hook.*result=rejected' "$REQ_LOG"; then
202
+ pass "missing transcript_path fail-closes with caller=unknown source=hook result=rejected"
203
+ else
204
+ fail "missing transcript_path did not fail-closed with expected log; log: $(cat "$REQ_LOG")"
205
+ fi
206
+
207
+ # --- Malformed stdin payload → fail-closed block ----------------------
208
+ : > "$REQ_LOG"
209
+ stdout_file=$(mktemp); TMPFILES+=("$stdout_file")
210
+ stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
211
+ echo "not-valid-json{{{" | \
212
+ MAXY_UI_INTERNAL_PORT="$LISTENER_PORT" \
213
+ bash "$HOOK" admin >"$stdout_file" 2>"$stderr_file"
214
+ HOOK_RC=$?
215
+ # A non-JSON payload also defeats the upstream TOOL_NAME extraction (grep
216
+ # pattern matches nothing), so this confirms the hook reaches its fall-
217
+ # through path safely without parse-induced crash.
218
+ [[ "$HOOK_RC" -eq 0 ]] || [[ "$HOOK_RC" -eq 2 ]] || fail "malformed payload produced unexpected exit $HOOK_RC"
219
+ pass "malformed payload handled without crash (exit $HOOK_RC)"
220
+
103
221
  # --- memory-search (allowed read tool) NOT rejected --------------------
104
222
  : > "$REQ_LOG"
105
- run_with_tool "mcp__plugin_memory_memory__memory-search" "sess-read"
223
+ run_with_tool "mcp__plugin_memory_memory__memory-search" "sess-read" "$ADMIN_TRANSCRIPT"
106
224
  [[ "$HOOK_RC" -eq 0 ]] || fail "memory-search expected exit 0, got $HOOK_RC stderr: $HOOK_STDERR"
107
225
  if grep -qE '"tag":\s*"admin-tool-revoke"' "$REQ_LOG"; then
108
226
  fail "memory-search must NOT emit admin-tool-revoke; log: $(cat "$REQ_LOG")"
@@ -115,7 +233,7 @@ fi
115
233
  # old namespace was never the surface admin saw, so matching it would
116
234
  # be a regression.
117
235
  : > "$REQ_LOG"
118
- run_with_tool "mcp__memory__memory-write" "sess-old-ns"
236
+ run_with_tool "mcp__memory__memory-write" "sess-old-ns" "$ADMIN_TRANSCRIPT"
119
237
  [[ "$HOOK_RC" -eq 0 ]] || fail "pre-209 namespace expected exit 0, got $HOOK_RC"
120
238
  if grep -qE '"tag":\s*"admin-tool-revoke"' "$REQ_LOG"; then
121
239
  fail "pre-209 namespace must NOT emit admin-tool-revoke"