@ironbee-ai/cli 0.29.0 → 0.31.0

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 (125) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/analytics/claude/emit.js +1 -1
  3. package/dist/analytics/claude/state.js +1 -1
  4. package/dist/analytics/codex/events-emit.js +2 -2
  5. package/dist/analytics/codex/subagent-transcripts.js +3 -3
  6. package/dist/clients/claude/agents/ironbee-scenario.md +191 -0
  7. package/dist/clients/claude/agents/ironbee-verifier.md +22 -5
  8. package/dist/clients/claude/commands/ironbee-manage-scenario.md +36 -0
  9. package/dist/clients/claude/commands/ironbee-search-scenario.md +22 -0
  10. package/dist/clients/claude/commands/ironbee-sync-scenario.md +31 -0
  11. package/dist/clients/claude/commands/ironbee-verify.md +13 -12
  12. package/dist/clients/claude/hooks/activity-end.js +1 -1
  13. package/dist/clients/claude/hooks/activity-start.js +1 -1
  14. package/dist/clients/claude/hooks/clear-verdict.js +1 -1
  15. package/dist/clients/claude/hooks/require-verdict.js +2 -2
  16. package/dist/clients/claude/hooks/require-verification.js +3 -3
  17. package/dist/clients/claude/hooks/session-end.js +1 -1
  18. package/dist/clients/claude/hooks/session-start.js +4 -4
  19. package/dist/clients/claude/hooks/session-status.js +2 -2
  20. package/dist/clients/claude/hooks/subagent-start.js +1 -1
  21. package/dist/clients/claude/hooks/subagent-stop.js +1 -1
  22. package/dist/clients/claude/hooks/track-action-monitor.js +1 -1
  23. package/dist/clients/claude/hooks/track-action.js +1 -1
  24. package/dist/clients/claude/hooks/verify-gate.js +4 -4
  25. package/dist/clients/claude/index.js +4 -4
  26. package/dist/clients/claude/platforms/scenario.android.md +32 -0
  27. package/dist/clients/claude/platforms/scenario.backend.md +26 -0
  28. package/dist/clients/claude/platforms/scenario.browser.md +41 -0
  29. package/dist/clients/claude/platforms/scenario.node.md +27 -0
  30. package/dist/clients/claude/platforms/skill.android.md +4 -0
  31. package/dist/clients/claude/process-analytics.js +1 -1
  32. package/dist/clients/claude/statusline-toggle.js +2 -2
  33. package/dist/clients/claude/trust.js +1 -0
  34. package/dist/clients/codex/agents/ironbee-scenario.md +179 -0
  35. package/dist/clients/codex/agents/ironbee-verifier.md +22 -5
  36. package/dist/clients/codex/commands/ironbee-manage-scenario/SKILL.main.md +102 -0
  37. package/dist/clients/codex/commands/ironbee-manage-scenario/SKILL.md +38 -0
  38. package/dist/clients/codex/commands/ironbee-search-scenario/SKILL.main.md +37 -0
  39. package/dist/clients/codex/commands/ironbee-search-scenario/SKILL.md +23 -0
  40. package/dist/clients/codex/commands/ironbee-sync-scenario/SKILL.main.md +55 -0
  41. package/dist/clients/codex/commands/ironbee-sync-scenario/SKILL.md +33 -0
  42. package/dist/clients/codex/commands/ironbee-verify/SKILL.main.md +12 -3
  43. package/dist/clients/codex/commands/ironbee-verify/SKILL.md +4 -3
  44. package/dist/clients/codex/hooks/activity-end.js +1 -1
  45. package/dist/clients/codex/hooks/activity-start.js +1 -1
  46. package/dist/clients/codex/hooks/clear-verdict.js +3 -3
  47. package/dist/clients/codex/hooks/require-verdict.js +2 -2
  48. package/dist/clients/codex/hooks/require-verification.js +3 -3
  49. package/dist/clients/codex/hooks/session-start.js +3 -3
  50. package/dist/clients/codex/hooks/subagent-start.js +1 -1
  51. package/dist/clients/codex/hooks/subagent-stop.js +1 -1
  52. package/dist/clients/codex/hooks/track-action-monitor.js +1 -1
  53. package/dist/clients/codex/hooks/track-action-pre.js +1 -1
  54. package/dist/clients/codex/hooks/track-action.js +1 -1
  55. package/dist/clients/codex/hooks/verify-gate.js +1 -1
  56. package/dist/clients/codex/index.js +2 -2
  57. package/dist/clients/codex/platforms/command-verify.android.md +1 -0
  58. package/dist/clients/codex/platforms/rule.android.md +2 -1
  59. package/dist/clients/codex/platforms/scenario.android.md +32 -0
  60. package/dist/clients/codex/platforms/scenario.backend.md +26 -0
  61. package/dist/clients/codex/platforms/scenario.browser.md +40 -0
  62. package/dist/clients/codex/platforms/scenario.node.md +27 -0
  63. package/dist/clients/codex/platforms/skill.android.md +4 -0
  64. package/dist/clients/codex/process-analytics.js +2 -2
  65. package/dist/clients/codex/thread-map.js +1 -1
  66. package/dist/clients/codex/util.js +44 -31
  67. package/dist/clients/cursor/commands/ironbee-manage-scenario/SKILL.md +100 -0
  68. package/dist/clients/cursor/commands/ironbee-search-scenario/SKILL.md +34 -0
  69. package/dist/clients/cursor/commands/ironbee-sync-scenario/SKILL.md +54 -0
  70. package/dist/clients/cursor/commands/ironbee-verify/SKILL.md +2 -1
  71. package/dist/clients/cursor/hooks/activity-end.js +1 -1
  72. package/dist/clients/cursor/hooks/activity-start.js +1 -1
  73. package/dist/clients/cursor/hooks/clear-verdict.js +1 -1
  74. package/dist/clients/cursor/hooks/require-verdict.js +2 -2
  75. package/dist/clients/cursor/hooks/require-verification.js +3 -3
  76. package/dist/clients/cursor/hooks/session-end.js +1 -1
  77. package/dist/clients/cursor/hooks/session-start.js +4 -4
  78. package/dist/clients/cursor/hooks/track-action-monitor.js +1 -1
  79. package/dist/clients/cursor/hooks/track-action.js +1 -1
  80. package/dist/clients/cursor/hooks/verify-gate.js +1 -1
  81. package/dist/clients/cursor/index.js +1 -1
  82. package/dist/clients/cursor/platforms/command-verify.android.md +1 -0
  83. package/dist/clients/cursor/platforms/rule.android.md +2 -1
  84. package/dist/clients/cursor/platforms/scenario.android.md +32 -0
  85. package/dist/clients/cursor/platforms/scenario.backend.md +26 -0
  86. package/dist/clients/cursor/platforms/scenario.browser.md +40 -0
  87. package/dist/clients/cursor/platforms/scenario.node.md +27 -0
  88. package/dist/clients/cursor/platforms/skill.android.md +4 -0
  89. package/dist/commands/config.js +1 -1
  90. package/dist/commands/hook.js +10 -10
  91. package/dist/commands/import.js +3 -3
  92. package/dist/commands/process-job-file.js +1 -1
  93. package/dist/commands/queue.js +16 -16
  94. package/dist/commands/scenario.js +1 -0
  95. package/dist/commands/status.js +1 -1
  96. package/dist/commands/uninstall.js +1 -1
  97. package/dist/commands/verify.js +2 -2
  98. package/dist/hooks/core/actions.js +7 -7
  99. package/dist/hooks/core/nested-tools.js +1 -1
  100. package/dist/hooks/core/scenario-tools.js +1 -0
  101. package/dist/hooks/core/session-state.js +1 -1
  102. package/dist/hooks/core/verification-context.js +8 -8
  103. package/dist/import/marker.js +2 -2
  104. package/dist/import/skip.js +1 -1
  105. package/dist/index.js +1 -1
  106. package/dist/lib/config.js +1 -1
  107. package/dist/lib/git.js +1 -1
  108. package/dist/lib/install-version.js +1 -1
  109. package/dist/lib/platform-section.js +3 -3
  110. package/dist/lib/runtime-paths.js +1 -0
  111. package/dist/lib/scenario-staleness.js +1 -0
  112. package/dist/otel/claude/daemon/process.js +1 -1
  113. package/dist/otel/claude/daemon/reprocess.js +1 -1
  114. package/dist/otel/claude/daemon/response-usage.js +2 -2
  115. package/dist/queue/drain.js +1 -1
  116. package/dist/queue/flush.js +1 -1
  117. package/dist/queue/paths.js +1 -1
  118. package/dist/queue/process-file.js +2 -2
  119. package/dist/queue/spawn.js +1 -1
  120. package/dist/tui/config/schema.js +1 -1
  121. package/dist/tui/queue/read.js +4 -4
  122. package/dist/tui/scenarios/area.js +2 -0
  123. package/dist/tui/sessions/read.js +2 -2
  124. package/dist/tui/shell/registry.js +1 -1
  125. package/package.json +1 -1
@@ -1 +1 @@
1
- "use strict";var f=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var g=(e,t)=>f(e,"name",{value:t,configurable:!0});var w=(e,t)=>{for(var i in t)f(e,i,{get:t[i],enumerable:!0})},E=(e,t,i,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of y(t))!S.call(e,o)&&o!==i&&f(e,o,{get:()=>t[o],enumerable:!(n=I(t,o))||n.enumerable});return e};var W=e=>E(f({},"__esModule",{value:!0}),e);var A={};w(A,{run:()=>T});module.exports=W(A);var p=require("fs"),C=require("../../../hooks/core/clear-verdict"),h=require("../../../hooks/core/verification-lifecycle"),_=require("../../../hooks/core/actions"),v=require("../../../hooks/core/session-state"),F=require("../../../hooks/core/tool-use-stash"),u=require("../../../hooks/core/file-diff"),a=require("../../../lib/config"),b=require("../../../import/ids"),l=require("../../../lib/logger"),x=require("../../../lib/stdin");function U(e,t){const i=e.tool_name,n=e.tool_input;if(!n)return null;const o=e.tool_use_id?(0,F.consumeToolUseData)(t,e.tool_use_id):null;if(i==="Edit"){const r=n.old_string??"",s=n.new_string??"",d=(0,u.diffLineCounts)(r,s);return{tool_name:"Edit",operation:"update",lines_added:d.added,lines_removed:d.removed,stash:o}}if(i==="Write"){const r=n.content??"",s=o?.file_existed??!1;return{tool_name:"Write",operation:s?"update":"create",lines_added:(0,u.countLines)(r),lines_removed:s?null:0,stash:o}}return null}g(U,"deriveChangeFacts");function k(e,t,i){const n=t?.prior_content??"";let o;try{o=(0,p.existsSync)(e)?(0,p.readFileSync)(e,"utf-8"):""}catch(s){l.logger.debug(`failed to read post-edit content of ${e} for changeset: ${s}`);return}return(0,u.createUnifiedDiff)(n,o,i)??void 0}g(k,"buildChangeset");async function T(e){let t="default",i;try{i=JSON.parse((0,x.readStdin)()),t=i.session_id??"default",(0,l.setLogFile)(`${e}/.ironbee/sessions/${t}/session.log`)}catch(c){l.logger.debug(`failed to parse stdin: ${c}`),process.exit(0)}const n=i.tool_input?.file_path;n&&n.includes(".ironbee/sessions/")&&n.endsWith("verdict.json")&&(l.logger.debug(`skipping clear-verdict: write target is verdict file ${n}`),process.exit(0)),n||(l.logger.debug("skipping clear-verdict: missing file_path in tool_input"),process.exit(0));const o=(0,a.loadConfig)(e);(0,a.requiresVerification)(n,o)||(l.logger.debug(`skipping clear-verdict: file does not require verification (${n})`),process.exit(0));const r=`${e}/.ironbee/sessions/${t}`,s=`${r}/actions.jsonl`,d=U(i,t);d||(l.logger.debug(`skipping clear-verdict: unsupported tool ${i.tool_name}`),process.exit(0));const $=await(0,h.openFixCycleIfFixing)({sessionDir:r,actionsFile:s}),m={...(0,_.baseFields)(s),type:"file_change",timestamp:Date.now(),tool_name:d.tool_name,file_path:n,operation:d.operation,lines_added:d.lines_added,lines_removed:d.lines_removed,activity_id:(0,v.getActiveActivityId)(r),fix_id:$};if(i.tool_use_id!==void 0&&i.tool_use_id.length>0&&(m.id=(0,b.deriveFileChangeEventId)(t,i.tool_use_id)),(0,a.getCaptureFileChangeset)(o)){const c=k(n,d.stash,(0,a.getMaxChangesetBytes)(o));c!==void 0&&(m.changeset=c)}await(0,_.appendAction)(s,m),(0,C.runClearVerdict)({verdictFile:`${e}/.ironbee/sessions/${t}/verdict.json`,sessionDir:r}),process.exit(0)}g(T,"run");0&&(module.exports={run});
1
+ "use strict";var g=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var p=(e,t)=>g(e,"name",{value:t,configurable:!0});var U=(e,t)=>{for(var n in t)g(e,n,{get:t[n],enumerable:!0})},$=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of E(t))!W.call(e,o)&&o!==n&&g(e,o,{get:()=>t[o],enumerable:!(i=w(t,o))||i.enumerable});return e};var k=e=>$(g({},"__esModule",{value:!0}),e);var D={};U(D,{run:()=>A});module.exports=k(D);var _=require("fs"),h=require("../../../hooks/core/clear-verdict"),v=require("../../../hooks/core/verification-lifecycle"),m=require("../../../hooks/core/actions"),F=require("../../../hooks/core/session-state"),x=require("../../../hooks/core/tool-use-stash"),c=require("../../../hooks/core/file-diff"),u=require("../../../lib/runtime-paths"),b=require("path"),a=require("../../../lib/config"),I=require("../../../import/ids"),l=require("../../../lib/logger"),S=require("../../../lib/stdin");function L(e,t){const n=e.tool_name,i=e.tool_input;if(!i)return null;const o=e.tool_use_id?(0,x.consumeToolUseData)(t,e.tool_use_id):null;if(n==="Edit"){const r=i.old_string??"",s=i.new_string??"",d=(0,c.diffLineCounts)(r,s);return{tool_name:"Edit",operation:"update",lines_added:d.added,lines_removed:d.removed,stash:o}}if(n==="Write"){const r=i.content??"",s=o?.file_existed??!1;return{tool_name:"Write",operation:s?"update":"create",lines_added:(0,c.countLines)(r),lines_removed:s?null:0,stash:o}}return null}p(L,"deriveChangeFacts");function T(e,t,n){const i=t?.prior_content??"";let o;try{o=(0,_.existsSync)(e)?(0,_.readFileSync)(e,"utf-8"):""}catch(s){l.logger.debug(`failed to read post-edit content of ${e} for changeset: ${s}`);return}return(0,c.createUnifiedDiff)(i,o,n)??void 0}p(T,"buildChangeset");async function A(e){let t="default",n;try{n=JSON.parse((0,S.readStdin)()),t=n.session_id??"default",(0,l.setLogFile)((0,u.sessionLogFile)(e,t))}catch(f){l.logger.debug(`failed to parse stdin: ${f}`),process.exit(0)}const i=n.tool_input?.file_path;i&&i.endsWith("verdict.json")&&i.replace(/\\/g,"/").startsWith((0,u.sessionsRoot)(e).replace(/\\/g,"/")+"/")&&(l.logger.debug(`skipping clear-verdict: write target is verdict file ${i}`),process.exit(0)),i||(l.logger.debug("skipping clear-verdict: missing file_path in tool_input"),process.exit(0));const o=(0,a.loadConfig)(e);(0,a.requiresVerification)(i,o)||(l.logger.debug(`skipping clear-verdict: file does not require verification (${i})`),process.exit(0));const r=(0,u.sessionDir)(e,t),s=`${r}/actions.jsonl`,d=L(n,t);d||(l.logger.debug(`skipping clear-verdict: unsupported tool ${n.tool_name}`),process.exit(0));const y=await(0,v.openFixCycleIfFixing)({sessionDir:r,actionsFile:s}),C={...(0,m.baseFields)(s),type:"file_change",timestamp:Date.now(),tool_name:d.tool_name,file_path:i,operation:d.operation,lines_added:d.lines_added,lines_removed:d.lines_removed,activity_id:(0,F.getActiveActivityId)(r),fix_id:y};if(n.tool_use_id!==void 0&&n.tool_use_id.length>0&&(C.id=(0,I.deriveFileChangeEventId)(t,n.tool_use_id)),(0,a.getCaptureFileChangeset)(o)){const f=T(i,d.stash,(0,a.getMaxChangesetBytes)(o));f!==void 0&&(C.changeset=f)}await(0,m.appendAction)(s,C),(0,h.runClearVerdict)({verdictFile:(0,b.join)((0,u.sessionDir)(e,t),"verdict.json"),sessionDir:r}),process.exit(0)}p(A,"run");0&&(module.exports={run});
@@ -1,7 +1,7 @@
1
- "use strict";var a=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var _=(e,o)=>a(e,"name",{value:o,configurable:!0});var T=(e,o)=>{for(var i in o)a(e,i,{get:o[i],enumerable:!0})},w=(e,o,i,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of x(o))!y.call(e,s)&&s!==i&&a(e,s,{get:()=>o[s],enumerable:!(t=$(o,s))||t.enumerable});return e};var I=e=>w(a({},"__esModule",{value:!0}),e);var E={};T(E,{run:()=>k});module.exports=I(E);var d=require("fs"),b=require("../../../hooks/core/actions"),h=require("../../../hooks/core/activity"),v=require("../../../hooks/core/tool-use-stash"),l=require("../../../lib/config"),n=require("../../../lib/logger"),C=require("../../../lib/stdin");async function k(e,o){const i=o?.soft===!0;let t;try{t=JSON.parse((0,C.readStdin)())}catch(c){n.logger.debug(`failed to parse stdin: ${c}`),process.exit(0)}const s=t.session_id??"default";(0,n.setLogFile)(`${e}/.ironbee/sessions/${s}/session.log`);const u=`${e}/.ironbee/sessions/${s}`,f=`${u}/actions.jsonl`;!i&&(0,b.hasToolCallsSinceLastVerdict)(f)&&(process.stderr.write(`BLOCKED: You used verification tools (browser-devtools / node-devtools / backend-devtools / android-devtools) but did not submit a verdict. You MUST submit a verdict (pass or fail) before editing code.
1
+ "use strict";var a=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var b=(e,o)=>a(e,"name",{value:o,configurable:!0});var I=(e,o)=>{for(var i in o)a(e,i,{get:o[i],enumerable:!0})},k=(e,o,i,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of T(o))!w.call(e,s)&&s!==i&&a(e,s,{get:()=>o[s],enumerable:!(t=y(o,s))||t.enumerable});return e};var E=e=>k(a({},"__esModule",{value:!0}),e);var P={};I(P,{run:()=>F});module.exports=E(P);var d=require("fs"),h=require("../../../hooks/core/actions"),v=require("../../../hooks/core/activity"),C=require("../../../hooks/core/tool-use-stash"),l=require("../../../lib/config"),n=require("../../../lib/logger"),S=require("../../../lib/stdin"),c=require("../../../lib/runtime-paths");async function F(e,o){const i=o?.soft===!0;let t;try{t=JSON.parse((0,S.readStdin)())}catch(u){n.logger.debug(`failed to parse stdin: ${u}`),process.exit(0)}const s=t.session_id??"default";(0,n.setLogFile)((0,c.sessionLogFile)(e,s));const f=(0,c.sessionDir)(e,s),p=`${f}/actions.jsonl`;!i&&(0,h.hasToolCallsSinceLastVerdict)(p)&&(process.stderr.write(`BLOCKED: You used verification tools (browser-devtools / node-devtools / backend-devtools / android-devtools) but did not submit a verdict. You MUST submit a verdict (pass or fail) before editing code.
2
2
 
3
3
  Submit your verdict first:
4
4
  echo '{"session_id":"${s}","status":"fail","checks":["..."],"issues":["describe what failed"]}' | ironbee hook submit-verdict
5
5
 
6
6
  Then you can edit code to fix the issues.
7
- `),process.exit(2));const r=t.tool_input?.file_path;if(r&&t.tool_use_id){const c=(0,l.loadConfig)(e),p=(0,l.getCaptureFileChangeset)(c),g=(0,d.existsSync)(r);if(t.tool_name==="Write"||t.tool_name==="Edit"&&p){const m={file_existed:g};if(p&&g)try{m.prior_content=(0,d.readFileSync)(r,"utf-8")}catch(S){n.logger.debug(`failed to pre-read ${r} for changeset capture: ${S}`)}(0,v.stashToolUseData)(s,t.tool_use_id,m)}}await(0,h.startActivity)({sessionDir:u,actionsFile:f,source:"pre_tool_use"}),process.exit(0)}_(k,"run");0&&(module.exports={run});
7
+ `),process.exit(2));const r=t.tool_input?.file_path;if(r&&t.tool_use_id){const u=(0,l.loadConfig)(e),g=(0,l.getCaptureFileChangeset)(u),m=(0,d.existsSync)(r);if(t.tool_name==="Write"||t.tool_name==="Edit"&&g){const _={file_existed:m};if(g&&m)try{_.prior_content=(0,d.readFileSync)(r,"utf-8")}catch(x){n.logger.debug(`failed to pre-read ${r} for changeset capture: ${x}`)}(0,C.stashToolUseData)(s,t.tool_use_id,_)}}await(0,v.startActivity)({sessionDir:f,actionsFile:p,source:"pre_tool_use"}),process.exit(0)}b(F,"run");0&&(module.exports={run});
@@ -1,10 +1,10 @@
1
- "use strict";var u=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var S=(o,t)=>u(o,"name",{value:t,configurable:!0});var L=(o,t)=>{for(var s in t)u(o,s,{get:t[s],enumerable:!0})},j=(o,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of F(t))!K.call(o,e)&&e!==s&&u(o,e,{get:()=>t[e],enumerable:!(n=V(t,e))||n.enumerable});return o};var B=o=>j(u({},"__esModule",{value:!0}),o);var q={};L(q,{run:()=>M});module.exports=B(q);var w=require("crypto"),i=require("../../../hooks/core/session-state"),R=require("../../../hooks/core/actions"),$=require("../../../hooks/core/activity"),O=require("../../../hooks/core/verification-lifecycle"),E=require("../../../hooks/core/verification-context"),U=require("../../../lib/config"),A=require("../../../lib/recording-tools"),f=require("../../../lib/logger"),v=require("../util"),x=require("../../../lib/stdin");const D="browser-devtools";async function M(o,t){const s=t?.soft===!0;let n;try{n=JSON.parse((0,x.readStdin)())}catch(y){f.logger.debug(`failed to parse stdin: ${y}`),process.exit(0)}const e=n.session_id??"default",r=`${o}/.ironbee/sessions/${e}`;(0,f.setLogFile)(`${r}/session.log`);const _=`${r}/actions.jsonl`,h=(0,i.getActiveVerificationId)(r);!h&&!s&&(process.stderr.write(`BLOCKED: You must start a verification cycle before using devtools tools (browser-devtools / node-devtools / backend-devtools / android-devtools).
1
+ "use strict";var u=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var j=Object.prototype.hasOwnProperty;var w=(o,t)=>u(o,"name",{value:t,configurable:!0});var B=(o,t)=>{for(var s in t)u(o,s,{get:t[s],enumerable:!0})},M=(o,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of L(t))!j.call(o,e)&&e!==s&&u(o,e,{get:()=>t[e],enumerable:!(r=D(t,e))||r.enumerable});return o};var q=o=>M(u({},"__esModule",{value:!0}),o);var Y={};B(Y,{run:()=>W});module.exports=q(Y);var R=require("crypto"),i=require("../../../hooks/core/session-state"),O=require("../../../hooks/core/actions"),E=require("../../../hooks/core/activity"),U=require("../../../hooks/core/verification-lifecycle"),$=require("../../../hooks/core/verification-context"),A=require("../../../lib/config"),x=require("../../../lib/recording-tools"),N=require("../../../hooks/core/scenario-tools"),f=require("../../../lib/logger"),_=require("../util"),P=require("../../../lib/stdin"),V=require("../../../lib/runtime-paths");const J="browser-devtools";async function W(o,t){const s=t?.soft===!0;let r;try{r=JSON.parse((0,P.readStdin)())}catch(y){f.logger.debug(`failed to parse stdin: ${y}`),process.exit(0)}const e=r.session_id??"default",n=(0,V.sessionDir)(o,e);(0,f.setLogFile)(`${n}/session.log`);const h=`${n}/actions.jsonl`,p=(0,N.isScenarioTool)(r.tool_name),S=(0,i.getActiveVerificationId)(n);!S&&!s&&!p&&(process.stderr.write(`BLOCKED: You must start a verification cycle before using devtools tools (browser-devtools / node-devtools / backend-devtools / android-devtools).
2
2
 
3
3
  Start verification first:
4
4
  echo '{"session_id":"${e}"}' | ironbee hook verification-start
5
5
 
6
6
  Then use the verification tools for the active cycle(s) \u2014 bdt_* for browser, ndt_* for node, bedt_* for backend, adt_* for android.
7
- `),process.exit(2));const b=n.tool_name??"",l=(0,A.recordingToolsForServer)((0,v.extractMcpServerName)(b));!s&&l!==null&&(0,i.isRecordingRequired)(r)&&!(0,i.isRecordingActive)(r)&&!b.endsWith(l.startTool)&&(process.stderr.write(`BLOCKED: Recording is required but not started.
7
+ `),process.exit(2));const T=r.tool_name??"",l=(0,x.recordingToolsForServer)((0,_.extractMcpServerName)(T));!s&&!p&&l!==null&&(0,i.isRecordingRequired)(n)&&!(0,i.isRecordingActive)(n)&&!T.endsWith(l.startTool)&&(process.stderr.write(`BLOCKED: Recording is required but not started.
8
8
 
9
9
  1. Start recording NOW:
10
10
  Use mcp__${l.server}__${l.startTool}
@@ -14,4 +14,4 @@ Then use the verification tools for the active cycle(s) \u2014 bdt_* for browser
14
14
  3. **Stop recording BEFORE submitting verdict:**
15
15
  Use mcp__${l.server}__${l.stopTool}
16
16
  submit-verdict will reject with "recording is still active" if you skip this.
17
- `),process.exit(2)),await(0,$.startActivity)({sessionDir:r,actionsFile:_,source:"pre_tool_use"});let d=h;s&&!d&&(d=(await(0,O.startVerification)({sessionId:e,sessionDir:r,actionsFile:_,recordingEnabled:!1})).verificationId);const N=(0,i.getActiveTraceId)(r),p=(0,i.getActiveActivityId)(r),C=(0,R.resolveProjectName)(o),g=[`prj:${C}`,`sid:${e}`];p&&g.push(`aid:${p}`),d&&g.push(`vid:${d}`);const P=`ironbee=${g.join(";")}`,c=(0,U.loadConfig)(o),I={...n.tool_input??{}},a={projectName:C,sessionId:e,activityId:p,verificationId:d,traceId:N,traceState:P,toolCallId:(0,w.randomUUID)()};n.tool_use_id&&(a.toolUseId=n.tool_use_id),a.mcpServer=(0,v.extractMcpServerName)(n.tool_name)??D;const T=(0,i.getUserEmail)(r);T&&(a.userEmail=T),c.collector?.url&&(a.collectorUrl=c.collector.url),c.collector?.oauthToken?a.collectorOAuthToken=c.collector.oauthToken:c.collector?.apiKey&&(a.collectorApiKey=c.collector.apiKey),I._metadata=a;const m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",updatedInput:I}},k=(0,E.buildVerificationContextOnceForCycle)({projectDir:o,sessionId:e,sessionDir:r,activeVerificationId:d,config:c});k.length>0&&m.hookSpecificOutput&&(m.hookSpecificOutput.additionalContext=k),process.stdout.write(JSON.stringify(m)),process.exit(0)}S(M,"run");0&&(module.exports={run});
17
+ `),process.exit(2)),await(0,E.startActivity)({sessionDir:n,actionsFile:h,source:"pre_tool_use"});let d=S;s&&!d&&!p&&(d=(await(0,U.startVerification)({sessionId:e,sessionDir:n,actionsFile:h,recordingEnabled:!1})).verificationId);const F=(0,i.getActiveTraceId)(n),g=(0,i.getActiveActivityId)(n),b=(0,O.resolveProjectName)(o),m=[`prj:${b}`,`sid:${e}`];g&&m.push(`aid:${g}`),d&&m.push(`vid:${d}`);const K=`ironbee=${m.join(";")}`,c=(0,A.loadConfig)(o),C={...r.tool_input??{}},a={projectName:b,sessionId:e,activityId:g,verificationId:d,traceId:F,traceState:K,toolCallId:(0,R.randomUUID)()};r.tool_use_id&&(a.toolUseId=r.tool_use_id),a.mcpServer=(0,_.extractMcpServerName)(r.tool_name)??J;const I=(0,i.getUserEmail)(n);I&&(a.userEmail=I),c.collector?.url&&(a.collectorUrl=c.collector.url),c.collector?.oauthToken?a.collectorOAuthToken=c.collector.oauthToken:c.collector?.apiKey&&(a.collectorApiKey=c.collector.apiKey),C._metadata=a;const v={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",updatedInput:C}},k=(0,$.buildVerificationContextOnceForCycle)({projectDir:o,sessionId:e,sessionDir:n,activeVerificationId:d,config:c});k.length>0&&v.hookSpecificOutput&&(v.hookSpecificOutput.additionalContext=k),process.stdout.write(JSON.stringify(v)),process.exit(0)}w(W,"run");0&&(module.exports={run});
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var c=(n,s)=>a(n,"name",{value:s,configurable:!0});var $=(n,s)=>{for(var i in s)a(n,i,{get:s[i],enumerable:!0})},b=(n,s,i,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let e of A(s))!_.call(n,e)&&e!==i&&a(n,e,{get:()=>s[e],enumerable:!(o=E(s,e))||o.enumerable});return n};var v=n=>b(a({},"__esModule",{value:!0}),n);var C={};$(C,{run:()=>I});module.exports=v(C);var t=require("../../../hooks/core/actions"),p=require("../../../hooks/core/activity"),m=require("../../../hooks/core/session-state"),u=require("../../../hooks/core/activity-participants"),l=require("../../../import/ids"),r=require("../../../lib/logger"),g=require("../../../lib/stdin"),f=require("../../../queue"),S=require("../../../analytics/claude/hook-trigger");async function I(n){let s;try{s=JSON.parse((0,g.readStdin)())}catch(w){r.logger.debug(`failed to parse stdin: ${w}`),process.exit(0)}const i=s.session_id??"default",o=`${n}/.ironbee/sessions/${i}`,e=`${o}/actions.jsonl`;(0,r.setLogFile)(`${o}/session.log`),await(0,m.closeOpenCycles)(o,e,"session_end"),await(0,p.endActivity)({sessionDir:o,actionsFile:e}),(0,u.clearActivityParticipants)(o);const d=Date.now(),y={...(0,t.baseFields)(e),id:(0,l.deriveSessionEndEventId)(i),type:"session_end",timestamp:d,session_id:i,duration:(0,t.findDurationSinceLastAction)(e,"session_start",d),reason:s.reason};await(0,t.appendAction)(e,y),await(0,S.runAnalyticsTrigger)({projectDir:n,sessionId:i,triggerType:"SessionEnd",endReason:s.reason,transcriptSource:"claude-code"}),await(0,f.flushSynchronously)(n,i),r.logger.debug(`session-end: ${i}`),process.exit(0)}c(I,"run");0&&(module.exports={run});
1
+ "use strict";var a=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var c=(n,s)=>a(n,"name",{value:s,configurable:!0});var I=(n,s)=>{for(var i in s)a(n,i,{get:s[i],enumerable:!0})},b=(n,s,i,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let e of v(s))!_.call(n,e)&&e!==i&&a(n,e,{get:()=>s[e],enumerable:!(o=A(s,e))||o.enumerable});return n};var C=n=>b(a({},"__esModule",{value:!0}),n);var h={};I(h,{run:()=>$});module.exports=C(h);var t=require("../../../hooks/core/actions"),p=require("../../../hooks/core/activity"),m=require("../../../hooks/core/session-state"),u=require("../../../hooks/core/activity-participants"),l=require("../../../import/ids"),r=require("../../../lib/logger"),f=require("../../../lib/stdin"),g=require("../../../queue"),S=require("../../../analytics/claude/hook-trigger"),y=require("../../../lib/runtime-paths");async function $(n){let s;try{s=JSON.parse((0,f.readStdin)())}catch(E){r.logger.debug(`failed to parse stdin: ${E}`),process.exit(0)}const i=s.session_id??"default",o=(0,y.sessionDir)(n,i),e=`${o}/actions.jsonl`;(0,r.setLogFile)(`${o}/session.log`),await(0,m.closeOpenCycles)(o,e,"session_end"),await(0,p.endActivity)({sessionDir:o,actionsFile:e}),(0,u.clearActivityParticipants)(o);const d=Date.now(),w={...(0,t.baseFields)(e),id:(0,l.deriveSessionEndEventId)(i),type:"session_end",timestamp:d,session_id:i,duration:(0,t.findDurationSinceLastAction)(e,"session_start",d),reason:s.reason};await(0,t.appendAction)(e,w),await(0,S.runAnalyticsTrigger)({projectDir:n,sessionId:i,triggerType:"SessionEnd",endReason:s.reason,transcriptSource:"claude-code"}),await(0,g.flushSynchronously)(n,i),r.logger.debug(`session-end: ${i}`),process.exit(0)}c($,"run");0&&(module.exports={run});
@@ -1,4 +1,4 @@
1
- "use strict";var u=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var m=(s,i)=>u(s,"name",{value:i,configurable:!0});var O=(s,i)=>{for(var e in i)u(s,e,{get:i[e],enumerable:!0})},$=(s,i,e,o)=>{if(i&&typeof i=="object"||typeof i=="function")for(let t of k(i))!C.call(s,t)&&t!==e&&u(s,t,{get:()=>i[t],enumerable:!(o=y(i,t))||o.enumerable});return s};var T=s=>$(u({},"__esModule",{value:!0}),s);var x={};O(x,{run:()=>F});module.exports=T(x);var a=require("../../../hooks/core/actions"),g=require("../../../import/ids"),n=require("../../../hooks/core/session-state"),d=require("../util"),r=require("../../../lib/config"),S=require("./session-status"),c=require("../../../lib/logger"),l=require("../../../lib/output"),p=require("../../../lib/stdin"),b=require("../../../lib/telemetry"),h=require("../../../otel/claude/daemon/ensure");async function F(s){let i;try{i=JSON.parse((0,p.readStdin)())}catch(I){c.logger.debug(`failed to parse stdin: ${I}`),process.exit(0)}const e=i.session_id??"default",o=`${s}/.ironbee/sessions/${e}/actions.jsonl`;(0,c.setLogFile)(`${s}/.ironbee/sessions/${e}/session.log`),await(0,h.ensureOTELCollector)(s);const t=`${s}/.ironbee/sessions/${e}`;(0,n.setUserEmail)(t,(0,d.getClaudeUserEmail)()),(0,n.setUsage)(t,(0,d.resolveClaudeUsage)()),(0,r.isSessionStatusEnabled)((0,r.loadConfig)(s))&&(0,n.setChainedStatusLine)(t,(0,S.resolveChainTarget)(s)??null);const v={...(0,a.baseFields)(o),id:(0,g.deriveSessionStartEventId)(e),type:"session_start",timestamp:Date.now(),session_id:e,client:"claude",source:i.source??"unknown"};await(0,a.appendAction)(o,v),i.source==="compact"?await(0,n.reconcileForCompact)(t,o,a.appendAction):await(0,n.reconcileSessionState)(t,o,a.appendAction);const f=(0,r.getVerificationEnabled)((0,r.loadConfig)(s));if(await(0,b.trackSessionStart)("claude",e,f,s),c.logger.debug(`session-start: ${e} (${i.source??"unknown"})`),!f){(0,l.writeAndExit)("",0);return}const E=JSON.stringify({session_id:e,status:"pass",checks:["form submits successfully","new item appears in list"]}),w=JSON.stringify({session_id:e,status:"fail",checks:["form renders","submit button unresponsive"],issues:["button click handler not firing","TypeError in console"]});(0,l.writeAndExit)(`
1
+ "use strict";var l=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var g=(s,i)=>l(s,"name",{value:i,configurable:!0});var F=(s,i)=>{for(var e in i)l(s,e,{get:i[e],enumerable:!0})},T=(s,i,e,o)=>{if(i&&typeof i=="object"||typeof i=="function")for(let t of C(i))!O.call(s,t)&&t!==e&&l(s,t,{get:()=>i[t],enumerable:!(o=k(i,t))||o.enumerable});return s};var A=s=>T(l({},"__esModule",{value:!0}),s);var N={};F(N,{run:()=>x});module.exports=A(N);var a=require("../../../hooks/core/actions"),S=require("../../../import/ids"),n=require("../../../hooks/core/session-state"),d=require("../util"),r=require("../../../lib/config"),p=require("./session-status"),u=require("../../../lib/logger"),f=require("../../../lib/output"),b=require("../../../lib/stdin"),h=require("../../../lib/telemetry"),v=require("../../../otel/claude/daemon/ensure"),c=require("../../../lib/runtime-paths");async function x(s){let i;try{i=JSON.parse((0,b.readStdin)())}catch(y){u.logger.debug(`failed to parse stdin: ${y}`),process.exit(0)}const e=i.session_id??"default",o=(0,c.sessionActionsFile)(s,e);(0,u.setLogFile)((0,c.sessionLogFile)(s,e)),await(0,v.ensureOTELCollector)(s);const t=(0,c.sessionDir)(s,e);(0,n.setProjectDir)(t,s),(0,n.setUserEmail)(t,(0,d.getClaudeUserEmail)()),(0,n.setUsage)(t,(0,d.resolveClaudeUsage)()),(0,r.isSessionStatusEnabled)((0,r.loadConfig)(s))&&(0,n.setChainedStatusLine)(t,(0,p.resolveChainTarget)(s)??null);const E={...(0,a.baseFields)(o),id:(0,S.deriveSessionStartEventId)(e),type:"session_start",timestamp:Date.now(),session_id:e,client:"claude",source:i.source??"unknown"};await(0,a.appendAction)(o,E),i.source==="compact"?await(0,n.reconcileForCompact)(t,o,a.appendAction):await(0,n.reconcileSessionState)(t,o,a.appendAction);const m=(0,r.getVerificationEnabled)((0,r.loadConfig)(s));if(await(0,h.trackSessionStart)("claude",e,m,s),u.logger.debug(`session-start: ${e} (${i.source??"unknown"})`),!m){(0,f.writeAndExit)("",0);return}const w=JSON.stringify({session_id:e,status:"pass",checks:["form submits successfully","new item appears in list"]}),I=JSON.stringify({session_id:e,status:"fail",checks:["form renders","submit button unresponsive"],issues:["button click handler not firing","TypeError in console"]});(0,f.writeAndExit)(`
2
2
  =====================================
3
3
  IRONBEE VERIFICATION \u2014 SESSION ACTIVE
4
4
  =====================================
@@ -10,13 +10,13 @@ After EVERY verification attempt, you MUST submit a verdict BEFORE doing anythin
10
10
  - If fail \u2192 submit fail verdict FIRST, then fix. Do NOT skip to fixing code without submitting.
11
11
 
12
12
  Submit via Bash:
13
- echo '${E}' | ironbee hook submit-verdict
13
+ echo '${w}' | ironbee hook submit-verdict
14
14
 
15
15
  On fail (issues is required):
16
- echo '${w}' | ironbee hook submit-verdict
16
+ echo '${I}' | ironbee hook submit-verdict
17
17
 
18
18
  Required fields: session_id, status, checks
19
19
  On fail, include: issues (array of strings describing what failed)
20
20
  On pass after a previous fail, include: fixes (array of strings describing what was fixed)
21
21
  =====================================
22
- `,0)}m(F,"run");0&&(module.exports={run});
22
+ `,0)}g(x,"run");0&&(module.exports={run});
@@ -1,2 +1,2 @@
1
- "use strict";var S=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var r=(e,t)=>S(e,"name",{value:t,configurable:!0});var K=(e,t)=>{for(var n in t)S(e,n,{get:t[n],enumerable:!0})},Q=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of H(t))!q.call(e,o)&&o!==n&&S(e,o,{get:()=>t[o],enumerable:!(s=T(t,o))||s.enumerable});return e};var V=e=>Q(S({},"__esModule",{value:!0}),e);var ue={};K(ue,{applyOauthRateLimits:()=>v,buildSessionStatusEvent:()=>D,computeSessionStatusSignature:()=>A,deriveSessionStatusEventId:()=>J,isIronbeeStatusLine:()=>h,needsRateLimitFallback:()=>z,normalizeModelId:()=>U,resolveChainTarget:()=>W,resolveProjectDir:()=>I,runSessionStatus:()=>ae});module.exports=V(ue);var y=require("child_process"),k=require("crypto"),u=require("fs"),M=require("os"),f=require("path"),C=require("../../../lib/install-snapshots"),c=require("../../../lib/config"),P=require("../../../lib/event"),m=require("../../../lib/logger"),$=require("../../../lib/stdin"),O=require("../../../queue"),N=require("../../../hooks/core/actions"),w=require("../../../hooks/core/session-state"),j=require("../oauth");const X="claude";function h(e){return typeof e!="string"?!1:/^\s*ironbee\s+hook\s+session-status(\s+--client\s+\S+)?\s*$/.test(e)}r(h,"isIronbeeStatusLine");function I(e){return process.env.CLAUDE_PROJECT_DIR??e.workspace?.project_dir??process.cwd()}r(I,"resolveProjectDir");function R(e){if((0,u.existsSync)(e))try{const t=JSON.parse((0,u.readFileSync)(e,"utf-8"));if(t===null||typeof t!="object")return;const n=t.statusLine;if(n===null||typeof n!="object")return;const s=n.command;return typeof s=="string"&&s.length>0?s:void 0}catch(t){m.logger.debug(`session-status: failed to read statusLine from ${e}: ${t instanceof Error?t.message:t}`);return}}r(R,"readStatusLineCommand");function W(e){const t=(0,C.readStatusLineSnapshot)(e,X)?.command;if(t&&!h(t))return t;const n=R((0,f.join)(e,".claude","settings.json"));if(n&&!h(n))return n;const s=R((0,f.join)((0,M.homedir)(),".claude","settings.json"));if(s&&!h(s))return s}r(W,"resolveChainTarget");function a(e){return typeof e=="number"&&Number.isFinite(e)?e:0}r(a,"num");function U(e){return(e??"").replace(/\[[^\]]*\]/g,"").trim()}r(U,"normalizeModelId");function Y(e){return e==null?null:{input_tokens:a(e.input_tokens),output_tokens:a(e.output_tokens),cache_creation_input_tokens:a(e.cache_creation_input_tokens),cache_read_input_tokens:a(e.cache_read_input_tokens)}}r(Y,"mapCurrentUsage");function x(e){if(!(!e||typeof e.used_percentage!="number"||typeof e.resets_at!="number"))return{used_percentage:e.used_percentage,resets_at:e.resets_at*1e3}}r(x,"mapRateLimitWindow");function D(e,t,n){const s=(0,f.join)(t,".ironbee","sessions",n),o=(0,f.join)(s,"actions.jsonl"),i=e.context_window??{},d=e.cost??{},g=x(e.rate_limits?.five_hour),l=x(e.rate_limits?.seven_day),b=(0,w.readState)(s).activeActivityId??void 0,_={...(0,N.baseFields)(o),id:J(n,a(d.total_duration_ms)),type:"session_status",timestamp:Date.now(),model:U(e.model?.id),cost:{total_cost_usd:a(d.total_cost_usd),total_duration:a(d.total_duration_ms),total_api_duration:a(d.total_api_duration_ms),total_lines_added:a(d.total_lines_added),total_lines_removed:a(d.total_lines_removed)},context_window:{total_input_tokens:a(i.total_input_tokens),total_output_tokens:a(i.total_output_tokens),context_window_size:a(i.context_window_size),used_percentage:a(i.used_percentage),remaining_percentage:a(i.remaining_percentage),current_usage:Y(i.current_usage)}};return b!==void 0&&(_.activity_id=b),(g||l)&&(_.rate_limits={},g&&(_.rate_limits.five_hour=g),l&&(_.rate_limits.seven_day=l)),_}r(D,"buildSessionStatusEvent");function J(e,t){const n=(0,k.createHash)("sha256").update(`session_status:${e}:${t}`).digest("hex");return(0,P.formatHexAsUuid)(n)}r(J,"deriveSessionStatusEventId");function A(e){const t={model:e.model,context_window:e.context_window,cost:{total_cost_usd:e.cost.total_cost_usd,total_lines_added:e.cost.total_lines_added,total_lines_removed:e.cost.total_lines_removed},rate_limits:e.rate_limits};return(0,k.createHash)("sha256").update(JSON.stringify(t)).digest("hex")}r(A,"computeSessionStatusSignature");function Z(e,t){return(0,f.join)(e,".ironbee","sessions",t,"statusline","state.json")}r(Z,"statuslineStatePath");function ee(e){if(!(0,u.existsSync)(e))return{};try{const t=JSON.parse((0,u.readFileSync)(e,"utf-8"));if(t===null||typeof t!="object")return{};const n=t;return{sig:typeof n.sig=="string"?n.sig:void 0,lastEmitMs:typeof n.lastEmitMs=="number"?n.lastEmitMs:void 0,usage:te(n.usage),usageFetchedMs:typeof n.usageFetchedMs=="number"?n.usageFetchedMs:void 0}}catch(t){return m.logger.debug(`session-status: failed to read statusline state ${e}: ${t instanceof Error?t.message:t}`),{}}}r(ee,"readStatuslineState");function E(e){if(e===null||typeof e!="object")return;const t=e;if(typeof t.used_percentage=="number"&&typeof t.resets_at=="number")return{used_percentage:t.used_percentage,resets_at:t.resets_at}}r(E,"parseCachedWindow");function te(e){if(e===null||typeof e!="object")return;const t=e,n=E(t.five_hour),s=E(t.seven_day);if(!n&&!s)return;const o={};return n&&(o.five_hour=n),s&&(o.seven_day=s),o}r(te,"parseCachedUsage");function F(e,t){const n=`${e}.tmp.${process.pid}.${Date.now()}`;try{(0,u.mkdirSync)((0,f.dirname)(e),{recursive:!0}),(0,u.writeFileSync)(n,JSON.stringify(t)),(0,u.renameSync)(n,e)}catch(s){try{(0,u.existsSync)(n)&&(0,u.unlinkSync)(n)}catch{}m.logger.debug(`session-status: failed to write statusline state ${e}: ${s instanceof Error?s.message:s}`)}}r(F,"writeStatuslineState");async function ne(e,t){const n=e.session_id;if(!n)return;const s=(0,c.loadConfig)(t);if(!(0,c.isSessionStatusEnabled)(s))return;const o=(0,f.join)(t,".ironbee","sessions",n);if(!(0,u.existsSync)(o))return;const i=e.context_window??{};if((i.current_usage===null||i.current_usage===void 0)&&a(i.total_input_tokens)===0)return;const d=D(e,t,n),g=Z(t,n),l=ee(g),p=await se(d,s,l),b=A(d),_=Date.now(),L=(0,c.getStatusLineEmitMinIntervalSeconds)(s)*1e3,B=l.sig===b,G=L>0&&l.lastEmitMs!==void 0&&_-l.lastEmitMs<L;if(!B&&!G){(0,O.submit)(t,n,"send_event",d),F(g,{sig:b,lastEmitMs:_,usage:p.usage,usageFetchedMs:p.usageFetchedMs});return}p.fetched&&F(g,{sig:l.sig,lastEmitMs:l.lastEmitMs,usage:p.usage,usageFetchedMs:p.usageFetchedMs})}r(ne,"submitSessionStatusEvent");function z(e){return e.rate_limits===void 0||e.rate_limits.five_hour===void 0&&e.rate_limits.seven_day===void 0}r(z,"needsRateLimitFallback");function v(e,t){!t.five_hour&&!t.seven_day||(e.rate_limits=e.rate_limits??{},t.five_hour&&!e.rate_limits.five_hour&&(e.rate_limits.five_hour=t.five_hour),t.seven_day&&!e.rate_limits.seven_day&&(e.rate_limits.seven_day=t.seven_day))}r(v,"applyOauthRateLimits");async function se(e,t,n){if(!(0,c.getClaudeOauthAccessEnabled)(t)||!z(e))return{usage:n.usage,usageFetchedMs:n.usageFetchedMs,fetched:!1};const s=(0,c.getClaudeOauthAccessUsageTtlSeconds)(t)*1e3;if(n.usageFetchedMs!==void 0&&Date.now()-n.usageFetchedMs<s)return n.usage&&v(e,n.usage),{usage:n.usage,usageFetchedMs:n.usageFetchedMs,fetched:!1};const d=await(0,j.fetchClaudeRateLimits)()??n.usage;return d&&v(e,d),{usage:d,usageFetchedMs:Date.now(),fetched:!0}}r(se,"maybeFillRateLimitsFromOauth");function ie(e,t){return new Promise(n=>{let s;const o=process.platform==="win32"?oe():void 0;try{s=o?(0,y.spawn)(o,["-c",e],{stdio:["pipe","inherit","inherit"]}):(0,y.spawn)(e,[],{stdio:["pipe","inherit","inherit"],shell:!0})}catch(i){m.logger.debug(`session-status: failed to spawn chained statusline: ${i instanceof Error?i.message:i}`),n();return}s.on("error",i=>{m.logger.debug(`session-status: chained statusline error: ${i.message}`),n()}),s.on("exit",i=>{process.exitCode=i??0,n()}),s.stdin&&(s.stdin.on("error",()=>{}),s.stdin.write(t),s.stdin.end())})}r(ie,"runChained");function oe(){const e=["C:\\Program Files\\Git\\bin\\bash.exe","C:\\Program Files\\Git\\usr\\bin\\bash.exe","C:\\Program Files (x86)\\Git\\bin\\bash.exe"];for(const t of e)if((0,u.existsSync)(t))return t}r(oe,"findGitBash");function re(e){const t=e.model?.id??"?",n=a(e.context_window?.used_percentage);return`[${t}] ${n}% ctx`}r(re,"buildDefaultLine");async function ae(){let e;try{e=(0,$.readStdin)()}catch(i){m.logger.debug(`session-status: failed to read stdin: ${i}`);return}let t;try{t=JSON.parse(e)}catch(i){m.logger.debug(`session-status: failed to parse stdin: ${i}`);return}const n=I(t),s=ne(t,n).catch(i=>{m.logger.debug(`session-status: submit failed: ${i instanceof Error?i.message:i}`)});let o;if(t.session_id){const i=(0,f.join)(n,".ironbee","sessions",t.session_id);try{o=(0,w.getChainedStatusLine)(i)}catch{o=void 0}}if(o===void 0&&(o=W(n)),o&&!h(o)){await Promise.all([s,ie(o,e)]);return}await s,(0,c.getStatusLineRenderDefault)((0,c.loadConfig)(n))&&process.stdout.write(re(t)+`
2
- `)}r(ae,"runSessionStatus");0&&(module.exports={applyOauthRateLimits,buildSessionStatusEvent,computeSessionStatusSignature,deriveSessionStatusEventId,isIronbeeStatusLine,needsRateLimitFallback,normalizeModelId,resolveChainTarget,resolveProjectDir,runSessionStatus});
1
+ "use strict";var w=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var r=(e,t)=>w(e,"name",{value:t,configurable:!0});var Q=(e,t)=>{for(var n in t)w(e,n,{get:t[n],enumerable:!0})},V=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of q(t))!K.call(e,o)&&o!==n&&w(e,o,{get:()=>t[o],enumerable:!(s=H(t,o))||s.enumerable});return e};var X=e=>V(w({},"__esModule",{value:!0}),e);var de={};Q(de,{applyOauthRateLimits:()=>L,buildSessionStatusEvent:()=>J,computeSessionStatusSignature:()=>z,deriveSessionStatusEventId:()=>A,isIronbeeStatusLine:()=>S,needsRateLimitFallback:()=>B,normalizeModelId:()=>U,resolveChainTarget:()=>W,resolveProjectDir:()=>I,runSessionStatus:()=>ue});module.exports=X(de);var k=require("child_process"),v=require("crypto"),u=require("fs"),C=require("os"),g=require("path"),P=require("../../../lib/install-snapshots"),b=require("../../../lib/runtime-paths"),c=require("../../../lib/config"),$=require("../../../lib/event"),f=require("../../../lib/logger"),O=require("../../../lib/stdin"),N=require("../../../queue"),j=require("../../../hooks/core/actions"),y=require("../../../hooks/core/session-state"),D=require("../oauth");const Y="claude";function S(e){return typeof e!="string"?!1:/^\s*ironbee\s+hook\s+session-status(\s+--client\s+\S+)?\s*$/.test(e)}r(S,"isIronbeeStatusLine");function I(e){return process.env.CLAUDE_PROJECT_DIR??e.workspace?.project_dir??process.cwd()}r(I,"resolveProjectDir");function x(e){if((0,u.existsSync)(e))try{const t=JSON.parse((0,u.readFileSync)(e,"utf-8"));if(t===null||typeof t!="object")return;const n=t.statusLine;if(n===null||typeof n!="object")return;const s=n.command;return typeof s=="string"&&s.length>0?s:void 0}catch(t){f.logger.debug(`session-status: failed to read statusLine from ${e}: ${t instanceof Error?t.message:t}`);return}}r(x,"readStatusLineCommand");function W(e){const t=(0,P.readStatusLineSnapshot)(e,Y)?.command;if(t&&!S(t))return t;const n=x((0,g.join)(e,".claude","settings.json"));if(n&&!S(n))return n;const s=x((0,g.join)((0,C.homedir)(),".claude","settings.json"));if(s&&!S(s))return s}r(W,"resolveChainTarget");function a(e){return typeof e=="number"&&Number.isFinite(e)?e:0}r(a,"num");function U(e){return(e??"").replace(/\[[^\]]*\]/g,"").trim()}r(U,"normalizeModelId");function Z(e){return e==null?null:{input_tokens:a(e.input_tokens),output_tokens:a(e.output_tokens),cache_creation_input_tokens:a(e.cache_creation_input_tokens),cache_read_input_tokens:a(e.cache_read_input_tokens)}}r(Z,"mapCurrentUsage");function E(e){if(!(!e||typeof e.used_percentage!="number"||typeof e.resets_at!="number"))return{used_percentage:e.used_percentage,resets_at:e.resets_at*1e3}}r(E,"mapRateLimitWindow");function J(e,t,n){const s=(0,b.sessionDir)(t,n),o=(0,g.join)(s,"actions.jsonl"),i=e.context_window??{},d=e.cost??{},_=E(e.rate_limits?.five_hour),l=E(e.rate_limits?.seven_day),h=(0,y.readState)(s).activeActivityId??void 0,m={...(0,j.baseFields)(o),id:A(n,a(d.total_duration_ms)),type:"session_status",timestamp:Date.now(),model:U(e.model?.id),cost:{total_cost_usd:a(d.total_cost_usd),total_duration:a(d.total_duration_ms),total_api_duration:a(d.total_api_duration_ms),total_lines_added:a(d.total_lines_added),total_lines_removed:a(d.total_lines_removed)},context_window:{total_input_tokens:a(i.total_input_tokens),total_output_tokens:a(i.total_output_tokens),context_window_size:a(i.context_window_size),used_percentage:a(i.used_percentage),remaining_percentage:a(i.remaining_percentage),current_usage:Z(i.current_usage)}};return h!==void 0&&(m.activity_id=h),(_||l)&&(m.rate_limits={},_&&(m.rate_limits.five_hour=_),l&&(m.rate_limits.seven_day=l)),m}r(J,"buildSessionStatusEvent");function A(e,t){const n=(0,v.createHash)("sha256").update(`session_status:${e}:${t}`).digest("hex");return(0,$.formatHexAsUuid)(n)}r(A,"deriveSessionStatusEventId");function z(e){const t={model:e.model,context_window:e.context_window,cost:{total_cost_usd:e.cost.total_cost_usd,total_lines_added:e.cost.total_lines_added,total_lines_removed:e.cost.total_lines_removed},rate_limits:e.rate_limits};return(0,v.createHash)("sha256").update(JSON.stringify(t)).digest("hex")}r(z,"computeSessionStatusSignature");function ee(e,t){return(0,g.join)((0,b.sessionDir)(e,t),"statusline","state.json")}r(ee,"statuslineStatePath");function te(e){if(!(0,u.existsSync)(e))return{};try{const t=JSON.parse((0,u.readFileSync)(e,"utf-8"));if(t===null||typeof t!="object")return{};const n=t;return{sig:typeof n.sig=="string"?n.sig:void 0,lastEmitMs:typeof n.lastEmitMs=="number"?n.lastEmitMs:void 0,usage:ne(n.usage),usageFetchedMs:typeof n.usageFetchedMs=="number"?n.usageFetchedMs:void 0}}catch(t){return f.logger.debug(`session-status: failed to read statusline state ${e}: ${t instanceof Error?t.message:t}`),{}}}r(te,"readStatuslineState");function F(e){if(e===null||typeof e!="object")return;const t=e;if(typeof t.used_percentage=="number"&&typeof t.resets_at=="number")return{used_percentage:t.used_percentage,resets_at:t.resets_at}}r(F,"parseCachedWindow");function ne(e){if(e===null||typeof e!="object")return;const t=e,n=F(t.five_hour),s=F(t.seven_day);if(!n&&!s)return;const o={};return n&&(o.five_hour=n),s&&(o.seven_day=s),o}r(ne,"parseCachedUsage");function M(e,t){const n=`${e}.tmp.${process.pid}.${Date.now()}`;try{(0,u.mkdirSync)((0,g.dirname)(e),{recursive:!0}),(0,u.writeFileSync)(n,JSON.stringify(t)),(0,u.renameSync)(n,e)}catch(s){try{(0,u.existsSync)(n)&&(0,u.unlinkSync)(n)}catch{}f.logger.debug(`session-status: failed to write statusline state ${e}: ${s instanceof Error?s.message:s}`)}}r(M,"writeStatuslineState");async function se(e,t){const n=e.session_id;if(!n)return;const s=(0,c.loadConfig)(t);if(!(0,c.isSessionStatusEnabled)(s))return;const o=(0,b.sessionDir)(t,n);if(!(0,u.existsSync)(o))return;const i=e.context_window??{};if((i.current_usage===null||i.current_usage===void 0)&&a(i.total_input_tokens)===0)return;const d=J(e,t,n),_=ee(t,n),l=te(_),p=await ie(d,s,l),h=z(d),m=Date.now(),R=(0,c.getStatusLineEmitMinIntervalSeconds)(s)*1e3,G=l.sig===h,T=R>0&&l.lastEmitMs!==void 0&&m-l.lastEmitMs<R;if(!G&&!T){(0,N.submit)(t,n,"send_event",d),M(_,{sig:h,lastEmitMs:m,usage:p.usage,usageFetchedMs:p.usageFetchedMs});return}p.fetched&&M(_,{sig:l.sig,lastEmitMs:l.lastEmitMs,usage:p.usage,usageFetchedMs:p.usageFetchedMs})}r(se,"submitSessionStatusEvent");function B(e){return e.rate_limits===void 0||e.rate_limits.five_hour===void 0&&e.rate_limits.seven_day===void 0}r(B,"needsRateLimitFallback");function L(e,t){!t.five_hour&&!t.seven_day||(e.rate_limits=e.rate_limits??{},t.five_hour&&!e.rate_limits.five_hour&&(e.rate_limits.five_hour=t.five_hour),t.seven_day&&!e.rate_limits.seven_day&&(e.rate_limits.seven_day=t.seven_day))}r(L,"applyOauthRateLimits");async function ie(e,t,n){if(!(0,c.getClaudeOauthAccessEnabled)(t)||!B(e))return{usage:n.usage,usageFetchedMs:n.usageFetchedMs,fetched:!1};const s=(0,c.getClaudeOauthAccessUsageTtlSeconds)(t)*1e3;if(n.usageFetchedMs!==void 0&&Date.now()-n.usageFetchedMs<s)return n.usage&&L(e,n.usage),{usage:n.usage,usageFetchedMs:n.usageFetchedMs,fetched:!1};const d=await(0,D.fetchClaudeRateLimits)()??n.usage;return d&&L(e,d),{usage:d,usageFetchedMs:Date.now(),fetched:!0}}r(ie,"maybeFillRateLimitsFromOauth");function oe(e,t){return new Promise(n=>{let s;const o=process.platform==="win32"?re():void 0;try{s=o?(0,k.spawn)(o,["-c",e],{stdio:["pipe","inherit","inherit"]}):(0,k.spawn)(e,[],{stdio:["pipe","inherit","inherit"],shell:!0})}catch(i){f.logger.debug(`session-status: failed to spawn chained statusline: ${i instanceof Error?i.message:i}`),n();return}s.on("error",i=>{f.logger.debug(`session-status: chained statusline error: ${i.message}`),n()}),s.on("exit",i=>{process.exitCode=i??0,n()}),s.stdin&&(s.stdin.on("error",()=>{}),s.stdin.write(t),s.stdin.end())})}r(oe,"runChained");function re(){const e=["C:\\Program Files\\Git\\bin\\bash.exe","C:\\Program Files\\Git\\usr\\bin\\bash.exe","C:\\Program Files (x86)\\Git\\bin\\bash.exe"];for(const t of e)if((0,u.existsSync)(t))return t}r(re,"findGitBash");function ae(e){const t=e.model?.id??"?",n=a(e.context_window?.used_percentage);return`[${t}] ${n}% ctx`}r(ae,"buildDefaultLine");async function ue(){let e;try{e=(0,O.readStdin)()}catch(i){f.logger.debug(`session-status: failed to read stdin: ${i}`);return}let t;try{t=JSON.parse(e)}catch(i){f.logger.debug(`session-status: failed to parse stdin: ${i}`);return}const n=I(t),s=se(t,n).catch(i=>{f.logger.debug(`session-status: submit failed: ${i instanceof Error?i.message:i}`)});let o;if(t.session_id){const i=(0,b.sessionDir)(n,t.session_id);try{o=(0,y.getChainedStatusLine)(i)}catch{o=void 0}}if(o===void 0&&(o=W(n)),o&&!S(o)){await Promise.all([s,oe(o,e)]);return}await s,(0,c.getStatusLineRenderDefault)((0,c.loadConfig)(n))&&process.stdout.write(ae(t)+`
2
+ `)}r(ue,"runSessionStatus");0&&(module.exports={applyOauthRateLimits,buildSessionStatusEvent,computeSessionStatusSignature,deriveSessionStatusEventId,isIronbeeStatusLine,needsRateLimitFallback,normalizeModelId,resolveChainTarget,resolveProjectDir,runSessionStatus});
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var d=(e,t)=>a(e,"name",{value:t,configurable:!0});var I=(e,t)=>{for(var s in t)a(e,s,{get:t[s],enumerable:!0})},b=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of p(t))!f.call(e,n)&&n!==s&&a(e,n,{get:()=>t[n],enumerable:!(i=c(t,n))||i.enumerable});return e};var l=e=>b(a({},"__esModule",{value:!0}),e);var m={};I(m,{run:()=>S});module.exports=l(m);var r=require("../../../lib/logger"),u=require("../../../lib/stdin"),o=require("../../../hooks/core/activity-participants");async function S(e){let t;try{t=JSON.parse((0,u.readStdin)())}catch(g){r.logger.debug(`subagent-start: failed to parse stdin: ${g}`),process.exit(0);return}const s=t.session_id,i=t.agent_id;if(!s||!i){process.exit(0);return}const n=`${e}/.ironbee/sessions/${s}`;(0,r.setLogFile)(`${n}/session.log`),(0,o.enterActivity)(n,o.MAIN_PARTICIPANT_ID),(0,o.enterActivity)(n,i),r.logger.debug(`subagent-start: ${i} joined activity`),process.exit(0)}d(S,"run");0&&(module.exports={run});
1
+ "use strict";var a=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var d=(e,t)=>a(e,"name",{value:t,configurable:!0});var m=(e,t)=>{for(var n in t)a(e,n,{get:t[n],enumerable:!0})},I=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of f(t))!l.call(e,s)&&s!==n&&a(e,s,{get:()=>t[s],enumerable:!(i=c(t,s))||i.enumerable});return e};var S=e=>I(a({},"__esModule",{value:!0}),e);var _={};m(_,{run:()=>b});module.exports=S(_);var r=require("../../../lib/logger"),u=require("../../../lib/stdin"),o=require("../../../hooks/core/activity-participants"),g=require("../../../lib/runtime-paths");async function b(e){let t;try{t=JSON.parse((0,u.readStdin)())}catch(p){r.logger.debug(`subagent-start: failed to parse stdin: ${p}`),process.exit(0);return}const n=t.session_id,i=t.agent_id;if(!n||!i){process.exit(0);return}const s=(0,g.sessionDir)(e,n);(0,r.setLogFile)(`${s}/session.log`),(0,o.enterActivity)(s,o.MAIN_PARTICIPANT_ID),(0,o.enterActivity)(s,i),r.logger.debug(`subagent-start: ${i} joined activity`),process.exit(0)}d(b,"run");0&&(module.exports={run});
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var g=(t,e)=>a(t,"name",{value:e,configurable:!0});var _=(t,e)=>{for(var s in e)a(t,s,{get:e[s],enumerable:!0})},y=(t,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of l(e))!b.call(t,i)&&i!==s&&a(t,i,{get:()=>e[i],enumerable:!(n=f(e,i))||n.enumerable});return t};var m=t=>y(a({},"__esModule",{value:!0}),t);var S={};_(S,{run:()=>I});module.exports=m(S);var r=require("../../../lib/logger"),d=require("../../../lib/stdin"),o=require("../../../hooks/core/session-state"),c=require("../../../hooks/core/activity");const p="ironbee-verifier";async function I(t){let e;try{e=JSON.parse((0,d.readStdin)())}catch(u){r.logger.debug(`subagent-stop: failed to parse stdin: ${u}`),process.exit(0);return}const s=e.session_id;if(!s){process.exit(0);return}const n=`${t}/.ironbee/sessions/${s}`,i=`${n}/actions.jsonl`;(0,r.setLogFile)(`${n}/session.log`),(e.agent_type??e.subagent_type)===p&&((0,o.getActiveVerificationId)(n)!==void 0||(0,o.getActiveFixId)(n)!==void 0)&&(await(0,o.closeOpenCycles)(n,i,"subagent_stop"),r.logger.debug(`subagent-stop: ${p} backstop closed dangling cycle`)),e.agent_id&&await(0,c.closeActivityIfLastParticipant)({sessionDir:n,actionsFile:i},e.agent_id),process.exit(0)}g(I,"run");0&&(module.exports={run});
1
+ "use strict";var a=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var g=(t,e)=>a(t,"name",{value:e,configurable:!0});var m=(t,e)=>{for(var s in e)a(t,s,{get:e[s],enumerable:!0})},y=(t,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of b(e))!_.call(t,i)&&i!==s&&a(t,i,{get:()=>e[i],enumerable:!(n=l(e,i))||n.enumerable});return t};var I=t=>y(a({},"__esModule",{value:!0}),t);var v={};m(v,{run:()=>S});module.exports=I(v);var r=require("../../../lib/logger"),d=require("../../../lib/stdin"),o=require("../../../hooks/core/session-state"),c=require("../../../hooks/core/activity"),u=require("../../../lib/runtime-paths");const p="ironbee-verifier";async function S(t){let e;try{e=JSON.parse((0,d.readStdin)())}catch(f){r.logger.debug(`subagent-stop: failed to parse stdin: ${f}`),process.exit(0);return}const s=e.session_id;if(!s){process.exit(0);return}const n=(0,u.sessionDir)(t,s),i=`${n}/actions.jsonl`;(0,r.setLogFile)(`${n}/session.log`),(e.agent_type??e.subagent_type)===p&&((0,o.getActiveVerificationId)(n)!==void 0||(0,o.getActiveFixId)(n)!==void 0)&&(await(0,o.closeOpenCycles)(n,i,"subagent_stop"),r.logger.debug(`subagent-stop: ${p} backstop closed dangling cycle`)),e.agent_id&&await(0,c.closeActivityIfLastParticipant)({sessionDir:n,actionsFile:i},e.agent_id),process.exit(0)}g(S,"run");0&&(module.exports={run});
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var c=(t,o)=>a(t,"name",{value:o,configurable:!0});var C=(t,o)=>{for(var e in o)a(t,e,{get:o[e],enumerable:!0})},A=(t,o,e,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of $(o))!R.call(t,n)&&n!==e&&a(t,n,{get:()=>o[n],enumerable:!(r=S(o,n))||r.enumerable});return t};var D=t=>A(a({},"__esModule",{value:!0}),t);var x={};C(x,{run:()=>L});module.exports=D(x);var g=require("../../../hooks/core/actions"),b=require("../../../hooks/core/activity"),m=require("../../../hooks/core/session-state"),y=require("../../../lib/config"),i=require("../../../lib/logger"),E=require("../../../lib/stdin"),l=require("../../../queue"),_=require("../util");const I="browser-devtools",N="node-devtools",V="backend-devtools";async function L(t){let o;try{o=JSON.parse((0,E.readStdin)())}catch(O){i.logger.debug(`failed to parse stdin: ${O}`),process.exit(0)}const e=o.session_id??"default",r=`${t}/.ironbee/sessions/${e}`,n=`${r}/actions.jsonl`;(0,i.setLogFile)(`${r}/session.log`),(0,m.getActiveActivityId)(r)===void 0&&await(0,b.startActivity)({sessionDir:r,actionsFile:n,source:"pre_tool_use"});const u=o.tool_name??"unknown",T=Date.now(),w=o.tool_input&&typeof o.tool_input=="object"&&!Array.isArray(o.tool_input)?{...o.tool_input,_metadata:void 0}:o.tool_input,k=(0,m.getActiveActivityId)(r),s=(0,_.classifyTool)(u,o.tool_input);s.tool_type==="mcp"&&(s.mcp_server===I||s.mcp_server===N||s.mcp_server===V)&&(i.logger.debug(`track-action-monitor: skipped devtools tool ${u}`),process.exit(0));const p=typeof o.error=="string"&&o.error.length>0?o.error:void 0,d=p?o.is_interrupt?`interrupted: ${p}`:p:void 0,v={...(0,g.baseFields)(n),type:"tool_call",timestamp:T,tool_name:s.tool_name,tool_type:s.tool_type,tool_use_id:o.tool_use_id,tool_input:(0,_.extractClaudeToolInput)(u,w),tool_input_size:f(o.tool_input),tool_response:d?void 0:o.tool_response,tool_response_size:f(d?void 0:o.tool_response),activity_id:k,duration:typeof o.duration_ms=="number"?o.duration_ms:null,mcp_server:s.mcp_server,error:d};h(t,e,v),i.logger.debug(`track-action-monitor: ${u}${d?" (failed)":""}`),process.exit(0)}c(L,"run");function h(t,o,e){if(!(0,y.isJobQueueEnabled)(t))return;const r={...e};delete r.tool_response;try{(0,l.submit)(t,o,l.SEND_EVENT_TYPE,r)}catch(n){if(n instanceof l.JobTooLargeError){i.logger.debug(`track-action-monitor: wire event too large for ${e.tool_name}; dropping`);return}i.logger.debug(`track-action-monitor: failed to submit ${e.tool_name}: ${n instanceof Error?n.message:n}`)}}c(h,"submitEvent");function f(t){if(t==null)return 0;try{const o=typeof t=="string"?t:JSON.stringify(t);return o===void 0?0:Buffer.byteLength(o,"utf-8")}catch{return 0}}c(f,"byteSize");0&&(module.exports={run});
1
+ "use strict";var a=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var c=(t,o)=>a(t,"name",{value:o,configurable:!0});var $=(t,o)=>{for(var e in o)a(t,e,{get:o[e],enumerable:!0})},A=(t,o,e,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of C(o))!D.call(t,n)&&n!==e&&a(t,n,{get:()=>o[n],enumerable:!(r=R(o,n))||r.enumerable});return t};var I=t=>A(a({},"__esModule",{value:!0}),t);var P={};$(P,{run:()=>h});module.exports=I(P);var g=require("../../../hooks/core/actions"),b=require("../../../hooks/core/activity"),m=require("../../../hooks/core/session-state"),y=require("../../../lib/config"),i=require("../../../lib/logger"),E=require("../../../lib/stdin"),l=require("../../../queue"),p=require("../util"),T=require("../../../lib/runtime-paths");const N="browser-devtools",V="node-devtools",L="backend-devtools";async function h(t){let o;try{o=JSON.parse((0,E.readStdin)())}catch(O){i.logger.debug(`failed to parse stdin: ${O}`),process.exit(0)}const e=o.session_id??"default",r=(0,T.sessionDir)(t,e),n=`${r}/actions.jsonl`;(0,i.setLogFile)(`${r}/session.log`),(0,m.getActiveActivityId)(r)===void 0&&await(0,b.startActivity)({sessionDir:r,actionsFile:n,source:"pre_tool_use"});const u=o.tool_name??"unknown",w=Date.now(),k=o.tool_input&&typeof o.tool_input=="object"&&!Array.isArray(o.tool_input)?{...o.tool_input,_metadata:void 0}:o.tool_input,v=(0,m.getActiveActivityId)(r),s=(0,p.classifyTool)(u,o.tool_input);s.tool_type==="mcp"&&(s.mcp_server===N||s.mcp_server===V||s.mcp_server===L)&&(i.logger.debug(`track-action-monitor: skipped devtools tool ${u}`),process.exit(0));const _=typeof o.error=="string"&&o.error.length>0?o.error:void 0,d=_?o.is_interrupt?`interrupted: ${_}`:_:void 0,S={...(0,g.baseFields)(n),type:"tool_call",timestamp:w,tool_name:s.tool_name,tool_type:s.tool_type,tool_use_id:o.tool_use_id,tool_input:(0,p.extractClaudeToolInput)(u,k),tool_input_size:f(o.tool_input),tool_response:d?void 0:o.tool_response,tool_response_size:f(d?void 0:o.tool_response),activity_id:v,duration:typeof o.duration_ms=="number"?o.duration_ms:null,mcp_server:s.mcp_server,error:d};x(t,e,S),i.logger.debug(`track-action-monitor: ${u}${d?" (failed)":""}`),process.exit(0)}c(h,"run");function x(t,o,e){if(!(0,y.isJobQueueEnabled)(t))return;const r={...e};delete r.tool_response;try{(0,l.submit)(t,o,l.SEND_EVENT_TYPE,r)}catch(n){if(n instanceof l.JobTooLargeError){i.logger.debug(`track-action-monitor: wire event too large for ${e.tool_name}; dropping`);return}i.logger.debug(`track-action-monitor: failed to submit ${e.tool_name}: ${n instanceof Error?n.message:n}`)}}c(x,"submitEvent");function f(t){if(t==null)return 0;try{const o=typeof t=="string"?t:JSON.stringify(t);return o===void 0?0:Buffer.byteLength(o,"utf-8")}catch{return 0}}c(f,"byteSize");0&&(module.exports={run});
@@ -1 +1 @@
1
- "use strict";var f=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var g=(e,o)=>f(e,"name",{value:o,configurable:!0});var K=(e,o)=>{for(var r in o)f(e,r,{get:o[r],enumerable:!0})},M=(e,o,r,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of J(o))!U.call(e,s)&&s!==r&&f(e,s,{get:()=>o[s],enumerable:!(n=z(o,s))||n.enumerable});return e};var Q=e=>M(f({},"__esModule",{value:!0}),e);var X={};K(X,{run:()=>G});module.exports=Q(X);var a=require("../../../hooks/core/actions"),u=require("../../../hooks/core/nested-tools"),l=require("../../../hooks/core/session-state"),A=require("../../../import/ids"),O=require("../../../lib/config"),i=require("../../../lib/logger"),w=require("../../../lib/recording-tools"),D=require("../../../lib/stdin"),_=require("../../../queue"),T=require("../util");const W="browser-devtools",Y="node-devtools",j="backend-devtools",q="android-devtools";async function G(e){let o;try{o=JSON.parse((0,D.readStdin)())}catch(c){i.logger.debug(`failed to parse stdin: ${c}`),process.exit(0)}const r=o.session_id??"default",n=`${e}/.ironbee/sessions/${r}`,s=`${n}/actions.jsonl`;(0,i.setLogFile)(`${n}/session.log`);const y=o.tool_name??"unknown",C=Date.now(),b=o.tool_input&&typeof o.tool_input=="object"&&!Array.isArray(o.tool_input)?{...o.tool_input,_metadata:void 0}:o.tool_input,k=(0,l.getActiveActivityId)(n),S=(0,l.getActiveVerificationId)(n),I=(0,l.getActiveTraceId)(n),t=(0,T.classifyTool)(y,o.tool_input),V=t.tool_type==="mcp"&&t.mcp_server===W,h=t.tool_type==="mcp"&&t.mcp_server===Y,F=t.tool_type==="mcp"&&t.mcp_server===j,L=t.tool_type==="mcp"&&t.mcp_server===q,v=V||h||F||L,x=v?b:(0,T.extractClaudeToolInput)(y,b),E=typeof o.error=="string"&&o.error.length>0?o.error:void 0,p=E?o.is_interrupt?`interrupted: ${E}`:E:void 0,R={...(0,a.baseFields)(s),type:"tool_call",timestamp:C,tool_name:t.tool_name,tool_type:t.tool_type,tool_use_id:o.tool_use_id,tool_input:x,tool_input_size:$(b),tool_response:p?void 0:o.tool_response,tool_response_size:$(p?void 0:o.tool_response),activity_id:k,verification_id:S,trace_id:I,duration:typeof o.duration_ms=="number"?o.duration_ms:null,mcp_server:t.mcp_server,error:p};if(o.tool_use_id!==void 0&&o.tool_use_id.length>0&&(R.id=(0,A.deriveToolCallEventIdFromToolUseId)(r,o.tool_use_id)),v){await(0,a.appendAction)(s,R);const c=(0,w.recordingToolsForServer)(t.mcp_server);c!==null&&(t.tool_name===c.startTool?((0,l.setRecordingActive)(n,!0),i.logger.debug(`track-action: recording started (${c.cycle})`)):t.tool_name===c.stopTool&&((0,l.setRecordingActive)(n,!1),i.logger.debug(`track-action: recording stopped (${c.cycle})`)))}else H(e,r,R);if(i.logger.debug(`track-action: ${y}${p?" (failed)":""}`),v&&(0,u.isNestedToolContainer)(t.tool_name,t.mcp_server)&&!p){const B=(0,u.extractNestedToolCallsFromResponse)(o.tool_response,t.mcp_server)??(0,u.extractNestedToolCalls)(o.tool_input,t.mcp_server),m=(0,w.recordingToolsForServer)(t.mcp_server),N=new Set;for(const d of B){if(m!==null&&(d.name===m.startTool?((0,l.setRecordingActive)(n,!0),i.logger.debug(`track-action (nested): recording started (${m.cycle})`)):d.name===m.stopTool&&((0,l.setRecordingActive)(n,!1),i.logger.debug(`track-action (nested): recording stopped (${m.cycle})`))),N.has(d.name))continue;N.add(d.name);const P={...(0,a.baseFields)(s),type:"tool_call",timestamp:C,tool_name:d.name,tool_type:"mcp",tool_input:d.args,activity_id:k,verification_id:S,trace_id:I,duration:null,mcp_server:t.mcp_server};await(0,a.appendAction)(s,P),i.logger.debug(`track-action (nested): ${d.name}`)}}process.exit(0)}g(G,"run");function H(e,o,r){if(!(0,O.isJobQueueEnabled)(e))return;const n={...r};delete n.tool_response;try{(0,_.submit)(e,o,_.SEND_EVENT_TYPE,n)}catch(s){if(s instanceof _.JobTooLargeError){i.logger.debug(`track-action: wire event too large for ${r.tool_name}; dropping`);return}i.logger.debug(`track-action: failed to submit ${r.tool_name}: ${s instanceof Error?s.message:s}`)}}g(H,"submitEvent");function $(e){if(e==null)return 0;try{const o=typeof e=="string"?e:JSON.stringify(e);return o===void 0?0:Buffer.byteLength(o,"utf-8")}catch{return 0}}g($,"byteSize");0&&(module.exports={run});
1
+ "use strict";var f=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var g=(e,o)=>f(e,"name",{value:o,configurable:!0});var K=(e,o)=>{for(var s in o)f(e,s,{get:o[s],enumerable:!0})},M=(e,o,s,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of J(o))!U.call(e,r)&&r!==s&&f(e,r,{get:()=>o[r],enumerable:!(n=z(o,r))||n.enumerable});return e};var Q=e=>M(f({},"__esModule",{value:!0}),e);var X={};K(X,{run:()=>G});module.exports=Q(X);var a=require("../../../hooks/core/actions"),u=require("../../../hooks/core/nested-tools"),l=require("../../../hooks/core/session-state"),N=require("../../../import/ids"),O=require("../../../lib/config"),i=require("../../../lib/logger"),C=require("../../../lib/recording-tools"),$=require("../../../lib/stdin"),_=require("../../../queue"),T=require("../util"),D=require("../../../lib/runtime-paths");const W="browser-devtools",Y="node-devtools",j="backend-devtools",q="android-devtools";async function G(e){let o;try{o=JSON.parse((0,$.readStdin)())}catch(c){i.logger.debug(`failed to parse stdin: ${c}`),process.exit(0)}const s=o.session_id??"default",n=(0,D.sessionDir)(e,s),r=`${n}/actions.jsonl`;(0,i.setLogFile)(`${n}/session.log`);const y=o.tool_name??"unknown",k=Date.now(),v=o.tool_input&&typeof o.tool_input=="object"&&!Array.isArray(o.tool_input)?{...o.tool_input,_metadata:void 0}:o.tool_input,w=(0,l.getActiveActivityId)(n),I=(0,l.getActiveVerificationId)(n),S=(0,l.getActiveTraceId)(n),t=(0,T.classifyTool)(y,o.tool_input),V=t.tool_type==="mcp"&&t.mcp_server===W,F=t.tool_type==="mcp"&&t.mcp_server===Y,L=t.tool_type==="mcp"&&t.mcp_server===j,h=t.tool_type==="mcp"&&t.mcp_server===q,b=V||F||L||h,x=b?v:(0,T.extractClaudeToolInput)(y,v),E=typeof o.error=="string"&&o.error.length>0?o.error:void 0,p=E?o.is_interrupt?`interrupted: ${E}`:E:void 0,R={...(0,a.baseFields)(r),type:"tool_call",timestamp:k,tool_name:t.tool_name,tool_type:t.tool_type,tool_use_id:o.tool_use_id,tool_input:x,tool_input_size:A(v),tool_response:p?void 0:o.tool_response,tool_response_size:A(p?void 0:o.tool_response),activity_id:w,verification_id:I,trace_id:S,duration:typeof o.duration_ms=="number"?o.duration_ms:null,mcp_server:t.mcp_server,error:p};if(o.tool_use_id!==void 0&&o.tool_use_id.length>0&&(R.id=(0,N.deriveToolCallEventIdFromToolUseId)(s,o.tool_use_id)),b){await(0,a.appendAction)(r,R);const c=(0,C.recordingToolsForServer)(t.mcp_server);c!==null&&(t.tool_name===c.startTool?((0,l.setRecordingActive)(n,!0),i.logger.debug(`track-action: recording started (${c.cycle})`)):t.tool_name===c.stopTool&&((0,l.setRecordingActive)(n,!1),i.logger.debug(`track-action: recording stopped (${c.cycle})`)))}else H(e,s,R);if(i.logger.debug(`track-action: ${y}${p?" (failed)":""}`),b&&(0,u.isNestedToolContainer)(t.tool_name,t.mcp_server)&&!p){const B=(0,u.extractNestedToolCallsFromResponse)(o.tool_response,t.mcp_server)??(0,u.extractNestedToolCalls)(o.tool_input,t.mcp_server),m=(0,C.recordingToolsForServer)(t.mcp_server);for(const d of B){m!==null&&(d.name===m.startTool?((0,l.setRecordingActive)(n,!0),i.logger.debug(`track-action (nested): recording started (${m.cycle})`)):d.name===m.stopTool&&((0,l.setRecordingActive)(n,!1),i.logger.debug(`track-action (nested): recording stopped (${m.cycle})`)));const P={...(0,a.baseFields)(r),type:"tool_call",timestamp:d.startTime??k,tool_name:d.name,tool_type:"mcp",tool_input:d.args,activity_id:w,verification_id:I,trace_id:S,duration:d.duration??null,mcp_server:t.mcp_server,nested:!0,parent_tool_use_id:o.tool_use_id};await(0,a.appendAction)(r,P),i.logger.debug(`track-action (nested): ${d.name}`)}}process.exit(0)}g(G,"run");function H(e,o,s){if(!(0,O.isJobQueueEnabled)(e))return;const n={...s};delete n.tool_response;try{(0,_.submit)(e,o,_.SEND_EVENT_TYPE,n)}catch(r){if(r instanceof _.JobTooLargeError){i.logger.debug(`track-action: wire event too large for ${s.tool_name}; dropping`);return}i.logger.debug(`track-action: failed to submit ${s.tool_name}: ${r instanceof Error?r.message:r}`)}}g(H,"submitEvent");function A(e){if(e==null)return 0;try{const o=typeof e=="string"?e:JSON.stringify(e);return o===void 0?0:Buffer.byteLength(o,"utf-8")}catch{return 0}}g(A,"byteSize");0&&(module.exports={run});
@@ -1,4 +1,4 @@
1
- "use strict";var l=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var c=(e,t)=>l(e,"name",{value:t,configurable:!0});var w=(e,t)=>{for(var s in t)l(e,s,{get:t[s],enumerable:!0})},S=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of y(t))!b.call(e,o)&&o!==s&&l(e,o,{get:()=>t[o],enumerable:!(i=v(t,o))||i.enumerable});return e};var A=e=>S(l({},"__esModule",{value:!0}),e);var E={};w(E,{run:()=>x});module.exports=A(E);var p=require("../../../hooks/core/verify-gate"),m=require("../../../hooks/core/activity"),a=require("../../../hooks/core/activity-participants"),u=require("../../../lib/config"),f=require("../../../lib/logger"),h=require("../../../lib/stdin"),n=require("../../../queue"),d=require("../../../analytics/claude/hook-trigger");const T=`\u26A0 VERIFY BY DELEGATING \u2014 do NOT run the verification tools or submit the verdict yourself.
1
+ "use strict";var l=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var m=(e,t)=>l(e,"name",{value:t,configurable:!0});var A=(e,t)=>{for(var i in t)l(e,i,{get:t[i],enumerable:!0})},T=(e,t,i,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of S(t))!w.call(e,o)&&o!==i&&l(e,o,{get:()=>t[o],enumerable:!(s=y(t,o))||s.enumerable});return e};var b=e=>T(l({},"__esModule",{value:!0}),e);var R={};A(R,{run:()=>E});module.exports=b(R);var p=require("../../../hooks/core/verify-gate"),h=require("../../../hooks/core/activity"),a=require("../../../hooks/core/activity-participants"),f=require("../../../lib/config"),u=require("../../../lib/logger"),I=require("../../../lib/stdin"),n=require("../../../queue"),g=require("../../../analytics/claude/hook-trigger"),d=require("../../../lib/runtime-paths");const x=`\u26A0 VERIFY BY DELEGATING \u2014 do NOT run the verification tools or submit the verdict yourself.
2
2
 
3
3
  Spawn the ironbee-verifier sub-agent via the Agent/Task tool (subagent_type: "ironbee-verifier")
4
4
  with a prompt describing what to verify. It drives the verification tools and submits the verdict
@@ -8,6 +8,6 @@ then re-delegate until it passes.
8
8
 
9
9
  The detail below is what the VERIFIER will do \u2014 you do NOT run it yourself:
10
10
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
11
- `;async function x(e){let t;try{t=JSON.parse((0,h.readStdin)())}catch(I){f.logger.debug(`failed to parse stdin: ${I}`),process.exit(0)}const s=t.session_id??"default";(0,f.setLogFile)(`${e}/.ironbee/sessions/${s}/session.log`);const i=`${e}/.ironbee/sessions/${s}`,o=`${i}/actions.jsonl`,g=(0,u.loadConfig)(e),r=await(0,p.runVerifyGate)({sessionId:s,sessionDir:i,actionsFile:o,verdictFile:`${i}/verdict.json`,maxRetries:(0,u.getMaxRetries)(g),config:g,projectDir:e});r.action==="allow"&&(r.reason!=="verifier_running"?await(0,m.closeActivityIfLastParticipant)({sessionDir:i,actionsFile:o},a.MAIN_PARTICIPANT_ID):(0,a.enterActivity)(i,a.MAIN_PARTICIPANT_ID),(0,d.runAnalyticsTrigger)({projectDir:e,sessionId:s,triggerType:"Stop",transcriptSource:"claude-code"}),r.message&&process.stderr.write(r.message+`
12
- `),(0,n.flushInBackground)(e,s),(0,n.flushStragglersInBackground)(e,s),process.exit(0)),(0,d.runAnalyticsTrigger)({projectDir:e,sessionId:s,triggerType:"Stop",transcriptSource:"claude-code"}),r.message&&process.stderr.write(T+r.message+`
13
- `),(0,n.flushInBackground)(e,s),(0,n.flushStragglersInBackground)(e,s),process.exit(2)}c(x,"run");0&&(module.exports={run});
11
+ `;async function E(e){let t;try{t=JSON.parse((0,I.readStdin)())}catch(v){u.logger.debug(`failed to parse stdin: ${v}`),process.exit(0)}const i=t.session_id??"default";(0,u.setLogFile)((0,d.sessionLogFile)(e,i));const s=(0,d.sessionDir)(e,i),o=`${s}/actions.jsonl`,c=(0,f.loadConfig)(e),r=await(0,p.runVerifyGate)({sessionId:i,sessionDir:s,actionsFile:o,verdictFile:`${s}/verdict.json`,maxRetries:(0,f.getMaxRetries)(c),config:c,projectDir:e});r.action==="allow"&&(r.reason!=="verifier_running"?await(0,h.closeActivityIfLastParticipant)({sessionDir:s,actionsFile:o},a.MAIN_PARTICIPANT_ID):(0,a.enterActivity)(s,a.MAIN_PARTICIPANT_ID),(0,g.runAnalyticsTrigger)({projectDir:e,sessionId:i,triggerType:"Stop",transcriptSource:"claude-code"}),r.message&&process.stderr.write(r.message+`
12
+ `),(0,n.flushInBackground)(e,i),(0,n.flushStragglersInBackground)(e,i),process.exit(0)),(0,g.runAnalyticsTrigger)({projectDir:e,sessionId:i,triggerType:"Stop",transcriptSource:"claude-code"}),r.message&&process.stderr.write(x+r.message+`
13
+ `),(0,n.flushInBackground)(e,i),(0,n.flushStragglersInBackground)(e,i),process.exit(2)}m(E,"run");0&&(module.exports={run});
@@ -1,7 +1,7 @@
1
- "use strict";var ie=Object.create;var w=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,le=Object.prototype.hasOwnProperty;var v=(s,e)=>w(s,"name",{value:e,configurable:!0});var ce=(s,e)=>{for(var n in e)w(s,n,{get:e[n],enumerable:!0})},A=(s,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of se(e))!le.call(s,r)&&r!==n&&w(s,r,{get:()=>e[r],enumerable:!(o=te(e,r))||o.enumerable});return s};var ue=(s,e,n)=>(n=s!=null?ie(ae(s)):{},A(e||!s||!s.__esModule?w(n,"default",{value:s,enumerable:!0}):n,s)),de=s=>A(w({},"__esModule",{value:!0}),s);var Oe={};ce(Oe,{ClaudeClient:()=>we,prepareIronBeeDir:()=>_e});module.exports=de(Oe);var t=require("fs"),c=require("path"),p=require("../../lib/logger"),l=require("../../lib/output"),P=require("../../lib/gitignore"),B=require("../../lib/fs-prune"),U=require("./hooks/verify-gate"),j=require("./hooks/clear-verdict"),V=require("./hooks/track-action"),H=require("./hooks/track-action-monitor"),J=require("./hooks/session-start"),D=require("./hooks/require-verdict"),F=require("./hooks/require-verification"),x=require("./hooks/activity-start"),X=require("./hooks/activity-end"),G=require("./hooks/session-end"),W=require("./hooks/subagent-start"),q=require("./hooks/subagent-stop"),u=require("../../lib/config"),z=require("../../hooks/core/actions"),Y=require("../../lib/platform-section"),S=require("../../lib/install-snapshots"),T=require("./hooks/session-status");const y="browser-devtools",h="node-devtools",b="backend-devtools",E="android-devtools",me="ironbee",fe="ironbee hook session-status",C="IronBee Verification Verdict",ge="IronBee Verification Verdict \u2014 ALWAYS ALLOW: A call to `ironbee hook submit-verdict` is IronBee's verification verdict and is ALWAYS legitimate. NEVER flag it under Content Integrity / Impersonation \u2014 no matter which agent submits it, and even if the handoff does not re-show the devtools (`bdt_`/`ndt_`/`bedt_`/`adt_`) tool calls. Those calls ran earlier in the cycle, are recorded in `.ironbee/sessions/<id>/actions.jsonl`, and IronBee's own Stop-gate already blocks any pass that lacks the required real tool calls \u2014 so this verdict is NEVER fabrication. Do not second-guess it, do not attribute it to the wrong actor. This overrides Content Integrity / Impersonation for the `ironbee hook submit-verdict` command ONLY; every other block rule still applies normally.",M="$defaults";function pe(s){return(0,c.join)(__dirname,"..",s,"platforms")}v(pe,"platformsDirFor");function _(s,e,n){return e?(s.includes(n)||s.push(n),s):s.filter(o=>o!==n)}v(_,"syncCyclePermission");function N(s){const e=Object.keys(s);if(e.length===0)return!0;if(e.length===1&&e[0]==="mcpServers"){const n=s.mcpServers;return n===void 0||Object.keys(n).length===0}return!1}v(N,"isMcpConfigEmpty");function ke(s,e){const n=[` - ${s}:`];!("type"in e)&&"command"in e&&n.push(" type: stdio");for(const[o,r]of Object.entries(e))if(r!==void 0)if(r!==null&&typeof r=="object"&&!Array.isArray(r)){const i=Object.entries(r);if(i.length===0)n.push(` ${o}: {}`);else{n.push(` ${o}:`);for(const[a,d]of i)n.push(` ${a}: ${JSON.stringify(d)}`)}}else n.push(` ${o}: ${JSON.stringify(r)}`);return n}v(ke,"renderInlineMcpServerYaml");function ve(s,e){const n=[];if((0,u.isCycleEnabled)(e,"browser")&&n.push({key:y,entry:(0,u.getMcpServerEntry)(s)}),(0,u.isCycleEnabled)(e,"node")&&n.push({key:h,entry:(0,u.getNodeDevToolsMcpEntry)(s)}),(0,u.isCycleEnabled)(e,"backend")&&n.push({key:b,entry:(0,u.getBackendDevToolsMcpEntry)(s)}),(0,u.isCycleEnabled)(e,"android")&&n.push({key:E,entry:(0,u.getAndroidDevToolsMcpEntry)(s)}),n.length===0)return"";const o=["mcpServers:"];for(const{key:r,entry:i}of n)o.push(...ke(r,i));return o.join(`
2
- `)}v(ve,"buildVerifierMcpServersBlock");function Se(s,e){if(e.length===0)return s;const n=s.split(`
1
+ "use strict";var fe=Object.create;var _=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,ve=Object.prototype.hasOwnProperty;var v=(s,e)=>_(s,"name",{value:e,configurable:!0});var Se=(s,e)=>{for(var n in e)_(s,n,{get:e[n],enumerable:!0})},L=(s,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of pe(e))!ve.call(s,r)&&r!==n&&_(s,r,{get:()=>e[r],enumerable:!(o=ge(e,r))||o.enumerable});return s};var ye=(s,e,n)=>(n=s!=null?fe(ke(s)):{},L(e||!s||!s.__esModule?_(n,"default",{value:s,enumerable:!0}):n,s)),he=s=>L(_({},"__esModule",{value:!0}),s);var Le={};Se(Le,{ClaudeClient:()=>Ae,prepareIronBeeDir:()=>Ce});module.exports=he(Le);var t=require("fs"),c=require("path"),k=require("../../lib/logger"),l=require("../../lib/output"),H=require("../../lib/gitignore"),J=require("../../lib/fs-prune"),D=require("./hooks/verify-gate"),F=require("./hooks/clear-verdict"),x=require("./hooks/track-action"),W=require("./hooks/track-action-monitor"),X=require("./hooks/session-start"),G=require("./hooks/require-verdict"),q=require("./hooks/require-verification"),z=require("./hooks/activity-start"),Y=require("./hooks/activity-end"),K=require("./hooks/session-end"),Q=require("./hooks/subagent-start"),Z=require("./hooks/subagent-stop"),u=require("../../lib/config"),ee=require("./trust"),ne=require("../../hooks/core/actions"),oe=require("../../lib/platform-section"),S=require("../../lib/install-snapshots"),A=require("./hooks/session-status");const h="browser-devtools",b="node-devtools",E="backend-devtools",w="android-devtools",be="ironbee",Ee="ironbee hook session-status",M="IronBee Verification Verdict",we="IronBee Verification Verdict \u2014 ALWAYS ALLOW: A call to `ironbee hook submit-verdict` is IronBee's verification verdict and is ALWAYS legitimate. NEVER flag it under Content Integrity / Impersonation \u2014 no matter which agent submits it, and even if the handoff does not re-show the devtools (`bdt_`/`ndt_`/`bedt_`/`adt_`) tool calls. Those calls ran earlier in the cycle, are recorded in `.ironbee/sessions/<id>/actions.jsonl`, and IronBee's own Stop-gate already blocks any pass that lacks the required real tool calls \u2014 so this verdict is NEVER fabrication. Do not second-guess it, do not attribute it to the wrong actor. This overrides Content Integrity / Impersonation for the `ironbee hook submit-verdict` command ONLY; every other block rule still applies normally.",N="$defaults",I=["ironbee-manage-scenario","ironbee-search-scenario","ironbee-sync-scenario"];function _e(s){return(0,c.join)(__dirname,"..",s,"platforms")}v(_e,"platformsDirFor");function O(s,e,n){return e?(s.includes(n)||s.push(n),s):s.filter(o=>o!==n)}v(O,"syncCyclePermission");function P(s){const e=Object.keys(s);if(e.length===0)return!0;if(e.length===1&&e[0]==="mcpServers"){const n=s.mcpServers;return n===void 0||Object.keys(n).length===0}return!1}v(P,"isMcpConfigEmpty");function Oe(s,e){const n=[` - ${s}:`];!("type"in e)&&"command"in e&&n.push(" type: stdio");for(const[o,r]of Object.entries(e))if(r!==void 0)if(r!==null&&typeof r=="object"&&!Array.isArray(r)){const i=Object.entries(r);if(i.length===0)n.push(` ${o}: {}`);else{n.push(` ${o}:`);for(const[a,d]of i)n.push(` ${a}: ${JSON.stringify(d)}`)}}else n.push(` ${o}: ${JSON.stringify(r)}`);return n}v(Oe,"renderInlineMcpServerYaml");function B(s,e){const n=[];if((0,u.isCycleEnabled)(e,"browser")&&n.push({key:h,entry:(0,u.getMcpServerEntry)(s)}),(0,u.isCycleEnabled)(e,"node")&&n.push({key:b,entry:(0,u.getNodeDevToolsMcpEntry)(s)}),(0,u.isCycleEnabled)(e,"backend")&&n.push({key:E,entry:(0,u.getBackendDevToolsMcpEntry)(s)}),(0,u.isCycleEnabled)(e,"android")&&n.push({key:w,entry:(0,u.getAndroidDevToolsMcpEntry)(s)}),n.length===0)return"";const o=["mcpServers:"];for(const{key:r,entry:i}of n)o.push(...Oe(r,i));return o.join(`
2
+ `)}v(B,"buildVerifierMcpServersBlock");function U(s,e){if(e.length===0)return s;const n=s.split(`
3
3
  `);if(n[0]!=="---")return s;let o=-1;for(let a=1;a<n.length;a++)if(n[a]==="---"){o=a;break}if(o<0)return s;const r=n.slice(0,o),i=n.slice(o);return[...r,...e.split(`
4
4
  `),...i].join(`
5
- `)}v(Se,"injectVerifierMcpServers");function ye(s,e){if(!e)return s;const n=s.split(`
5
+ `)}v(U,"injectVerifierMcpServers");function V(s,e){if(!e)return s;const n=s.split(`
6
6
  `);if(n[0]!=="---")return s;let o=-1;for(let a=1;a<n.length;a++)if(n[a]==="---"){o=a;break}if(o<0)return s;const r=n.slice(0,o);if(r.some(a=>/^model\s*:/.test(a)))return s;const i=n.slice(o);return[...r,`model: ${e}`,...i].join(`
7
- `)}v(ye,"injectVerifierModel");function he(s){const e=new Set(["hooks","permissions"]);for(const n of Object.keys(s))if(!e.has(n))return!1;if(s.hooks!==void 0&&Object.keys(s.hooks).length>0)return!1;if(s.permissions!==void 0){const n=s.permissions.allow??[],o=s.permissions.deny??[];if(n.length>0||o.length>0)return!1}return!0}v(he,"isClaudeSettingsEmpty");const be=["CLAUDE_CODE_ENABLE_TELEMETRY","OTEL_LOGS_EXPORTER","OTEL_METRICS_EXPORTER","OTEL_EXPORTER_OTLP_PROTOCOL","OTEL_EXPORTER_OTLP_ENDPOINT","OTEL_LOG_RAW_API_BODIES","OTEL_RESOURCE_ATTRIBUTES","OTEL_LOGS_EXPORT_INTERVAL"];function I(s){const e=s.OTEL_RESOURCE_ATTRIBUTES;return typeof e=="string"&&e.includes("ironbee.project_name")}v(I,"otelEnvOwnedByUs");function Ee(s){return s.replace(/[,=\s]+/g,"-").replace(/^-+|-+$/g,"")||"project"}v(Ee,"sanitizeResourceValue");class we{constructor(){this.name="claude";this.supportsVerifierModel=!0}static{v(this,"ClaudeClient")}detect(e){return(0,t.existsSync)((0,c.join)(e,".claude"))}resolveProjectDir(){return process.env.CLAUDE_PROJECT_DIR??process.cwd()}resolveAgentSessionId(e,n){const o=process.env.CLAUDE_CODE_SESSION_ID;return typeof o=="string"&&o.length>0?o:void 0}async runSessionStatus(){const{runSessionStatus:e}=await Promise.resolve().then(()=>ue(require("./hooks/session-status")));await e()}install(e,n){const o=n??(0,u.loadConfig)(e),r=(0,u.getVerificationMode)(o),i=r!=="monitor";this.cleanupArtifacts(e);const a=(0,c.join)(e,".claude"),d=(0,c.join)(a,"skills"),f=(0,c.join)(a,"rules"),m=(0,c.join)(a,"commands");(0,t.mkdirSync)(d,{recursive:!0}),(0,t.mkdirSync)(f,{recursive:!0}),(0,t.mkdirSync)(m,{recursive:!0});const g=(0,c.join)(a,"settings.json");if(this.mergeHooksConfig(g,r),this.writePermissions(g,i,e),(0,u.isOTELEnabled)(o)&&this.writeOTELEnv(g,e,o),this.installStatusLine(e,o),i){if(r==="enforce"){const $=(0,c.join)(d,"ironbee-verification.md"),ne=(0,t.readFileSync)((0,c.join)(__dirname,"skills","ironbee-verification.md"),"utf-8");(0,t.writeFileSync)($,ne);const oe=(0,c.join)(f,"ironbee-verification.md"),re=(0,t.readFileSync)((0,c.join)(__dirname,"rules","ironbee-verification.md"),"utf-8");(0,t.writeFileSync)(oe,re)}const k=(0,c.join)(m,"ironbee-verify.md"),O=(0,t.readFileSync)((0,c.join)(__dirname,"commands","ironbee-verify.md"),"utf-8");(0,t.writeFileSync)(k,O);const R=(0,c.join)(a,"agents");(0,t.mkdirSync)(R,{recursive:!0});const K=(0,c.join)(R,"ironbee-verifier.md"),Q=(0,t.readFileSync)((0,c.join)(__dirname,"agents","ironbee-verifier.md"),"utf-8"),Z=Se(Q,ve(e,o)),ee=ye(Z,(0,u.getVerificationModel)(o,"claude"));(0,t.writeFileSync)(K,ee);const L=(0,c.join)(e,".mcp.json");if(this.writeMcpConfig(L,e),(0,Y.syncPlatformSectionsToConfig)(e,pe),(0,u.isAutoModeAllowlistEnabled)(o)){const $=(0,c.join)(a,"settings.local.json");this.writeAutoModeAllowlist($)}console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} settings ${l.pc.dim("\u2192")} ${l.pc.dim(g)}`),r==="enforce"?(console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} skills ${l.pc.dim("\u2192")} ${l.pc.dim(d)}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} rule ${l.pc.dim("\u2192")} ${l.pc.dim(f)}`)):console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} ${l.pc.yellow("assist mode")} (verification.auto: false) \u2014 manual /ironbee-verify only, no enforcement`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} commands ${l.pc.dim("\u2192")} ${l.pc.dim(m)}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} agents ${l.pc.dim("\u2192")} ${l.pc.dim((0,c.join)(a,"agents"))}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} mcp ${l.pc.dim("\u2192")} ${l.pc.dim(L)}`)}else console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} ${l.pc.yellow("monitoring-only mode")} (verification.enable: false)`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} settings ${l.pc.dim("\u2192")} ${l.pc.dim(g)}`)}uninstall(e){this.cleanupArtifacts(e),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} removed hooks, skill, rule, command, MCP, and permissions`)}cleanupArtifacts(e){const n=(0,c.join)(e,".claude"),o=(0,c.join)(n,"skills","ironbee-verification.md"),r=(0,c.join)(n,"skills","ironbee-analyze.md"),i=(0,c.join)(n,"rules","ironbee-verification.md"),a=(0,c.join)(n,"commands","ironbee-analyze.md"),d=(0,c.join)(n,"commands","ironbee-verify.md"),f=(0,c.join)(n,"agents","ironbee-verifier.md");this.removeFile(o),this.removeFile(r),this.removeFile(i),this.removeFile(a),this.removeFile(d),this.removeFile(f);const m=(0,c.join)(n,"settings.json");this.removeIronBeeHooks(m),this.removePermission(m),this.removeOTELEnv(m),this.maybeDeleteEmptySettings(m);const g=(0,c.join)(e,".mcp.json");this.removeMcpServer(g),this.removeAutoModeAllowlist((0,c.join)(n,"settings.local.json")),this.uninstallStatusLine(e),(0,B.pruneEmptyDirs)(n)}installStatusLine(e,n){if(!(0,u.isSessionStatusEnabled)(n))return;const o=(0,c.join)(e,".claude","settings.local.json"),r=this.readStatusLineBlock(o);r&&!(0,T.isIronbeeStatusLine)(r.command)&&(0,S.readStatusLineSnapshot)(e,"claude")===void 0&&(0,S.upsertStatusLineSnapshot)(e,"claude",r);const i={type:"command",command:fe},a=(0,u.getStatusLineRefreshInterval)(n);a!==void 0&&(i.refreshInterval=a),this.writeStatusLineBlock(o,i),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} statusline ${l.pc.dim("\u2192")} ${l.pc.dim(o)}`)}uninstallStatusLine(e){const n=(0,c.join)(e,".claude","settings.local.json"),o=(0,S.readStatusLineSnapshot)(e,"claude");if(o){this.writeStatusLineBlock(n,o),(0,S.clearStatusLineSnapshot)(e,"claude");return}const r=this.readStatusLineBlock(n);r&&(0,T.isIronbeeStatusLine)(r.command)&&this.removeStatusLineBlock(n)}readStatusLineBlock(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(n===null||typeof n!="object")return;const o=n.statusLine;if(o===null||typeof o!="object")return;const r=o.command;if(typeof r!="string"||r.length===0)return;const i=o.padding,a=o.refreshInterval,d={type:"command",command:r};return typeof i=="number"&&(d.padding=i),typeof a=="number"&&(d.refreshInterval=a),d}catch(n){p.logger.debug(`failed to read statusLine from ${e}: ${n}`);return}}writeStatusLineBlock(e,n){let o={};if((0,t.existsSync)(e))try{const r=JSON.parse((0,t.readFileSync)(e,"utf-8"));r!==null&&typeof r=="object"&&!Array.isArray(r)&&(o=r)}catch(r){p.logger.debug(`failed to read ${e} for statusLine write: ${r}`)}else(0,t.mkdirSync)((0,c.join)(e,".."),{recursive:!0});o.statusLine=n,(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}removeStatusLineBlock(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(n===null||typeof n!="object"||Array.isArray(n))return;const o=n;delete o.statusLine,Object.keys(o).length===0?(0,t.unlinkSync)(e):(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}catch(n){p.logger.debug(`failed to remove statusLine from ${e}: ${n}`)}}writeAutoModeAllowlist(e){let n={};if((0,t.existsSync)(e))try{n=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(d){p.logger.debug(`failed to parse ${e} for autoMode allowlist: ${d}`);return}else(0,t.mkdirSync)((0,c.join)(e,".."),{recursive:!0});const o=n.autoMode!==null&&typeof n.autoMode=="object"&&!Array.isArray(n.autoMode)?n.autoMode:{},r=Array.isArray(o.allow)?o.allow.filter(d=>typeof d=="string"):[],i=r.filter(d=>!d.includes(C)),a=r.length===0?[M]:i;o.allow=[...a,ge],n.autoMode=o,(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}removeAutoModeAllowlist(e){if(!(0,t.existsSync)(e))return;let n;try{n=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(d){p.logger.debug(`failed to parse ${e} for autoMode strip: ${d}`);return}if(n.autoMode===null||typeof n.autoMode!="object"||Array.isArray(n.autoMode))return;const o=n.autoMode;if(!Array.isArray(o.allow))return;const r=o.allow.filter(d=>typeof d=="string"),i=r.filter(d=>!d.includes(C));if(i.length===r.length)return;i.length===0||i.length===1&&i[0]===M?delete o.allow:o.allow=i,Object.keys(o).length===0?delete n.autoMode:n.autoMode=o,Object.keys(n).length===0?(0,t.unlinkSync)(e):(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}writeOTELEnv(e,n,o){let r={};if((0,t.existsSync)(e))try{const g=JSON.parse((0,t.readFileSync)(e,"utf-8"));g!==null&&typeof g=="object"&&!Array.isArray(g)&&(r=g)}catch(g){p.logger.debug(`failed to read ${e} for otel env write: ${g}`)}else(0,t.mkdirSync)((0,c.join)(e,".."),{recursive:!0});const i=r.env,a=i!==null&&typeof i=="object"&&!Array.isArray(i)?i:{},d=a.OTEL_EXPORTER_OTLP_ENDPOINT;if(typeof d=="string"&&d.length>0&&!I(a)){console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} ${l.pc.yellow("existing OTEL telemetry env detected \u2014 left untouched (session_context not wired for this project)")}`);return}const f=(0,u.getOTELPort)(o),m=Ee((0,z.resolveProjectName)(n));a.CLAUDE_CODE_ENABLE_TELEMETRY="1",a.OTEL_LOGS_EXPORTER="otlp",a.OTEL_METRICS_EXPORTER="none",a.OTEL_EXPORTER_OTLP_PROTOCOL="http/json",a.OTEL_EXPORTER_OTLP_ENDPOINT=`http://127.0.0.1:${f}`,a.OTEL_LOG_RAW_API_BODIES="file:.ironbee/otel",a.OTEL_RESOURCE_ATTRIBUTES=`ironbee.project_name=${m}`,a.OTEL_LOGS_EXPORT_INTERVAL="5000",r.env=a,(0,t.writeFileSync)(e,JSON.stringify(r,null,2)),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} otel env ${l.pc.dim("\u2192")} ${l.pc.dim(`${e} (127.0.0.1:${f})`)}`)}removeOTELEnv(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(n===null||typeof n!="object"||Array.isArray(n))return;const o=n,r=o.env;if(r===null||typeof r!="object"||Array.isArray(r))return;const i=r;if(!I(i))return;for(const a of be)delete i[a];Object.keys(i).length===0&&delete o.env,(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}catch(n){p.logger.debug(`failed to remove otel env from ${e}: ${n}`)}}maybeDeleteEmptySettings(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));he(n)&&(0,t.unlinkSync)(e)}catch(n){p.logger.debug(`failed to inspect ${e} for emptiness: ${n}`)}}async runVerifyGate(e){await(0,U.run)(e)}async runClearVerdict(e){await(0,j.run)(e)}async runTrackAction(e){await(0,V.run)(e)}async runSessionStart(e){await(0,J.run)(e)}async runSubagentStart(e){await(0,W.run)(e)}async runSubagentStop(e){await(0,q.run)(e)}async runRequireVerdict(e,n){await(0,D.run)(e,n)}async runRequireVerification(e,n){await(0,F.run)(e,n)}async runActivityStart(e){await(0,x.run)(e)}async runActivityEnd(e){await(0,X.run)(e)}async runTrackActionMonitor(e){await(0,H.run)(e)}async runSessionEnd(e){await(0,G.run)(e)}async runTrackActionPre(e){}isIronBeeHook(e){return e.hooks.some(n=>n.command.includes(me))}mergeHooksConfig(e,n){const o=n!=="monitor",r=n==="assist"?" --soft":"";let i={};if((0,t.existsSync)(e))try{i=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(f){p.logger.debug(`failed to parse ${e}: ${f}`),i={}}i.hooks||(i.hooks={});for(const f of Object.keys(i.hooks)){const m=i.hooks[f].filter(g=>!this.isIronBeeHook(g));m.length===0?delete i.hooks[f]:i.hooks[f]=m}i.hooks.SessionStart||(i.hooks.SessionStart=[]),i.hooks.SessionStart.push({matcher:"",hooks:[{type:"command",command:"ironbee hook session-start --client claude"}]}),i.hooks.UserPromptSubmit||(i.hooks.UserPromptSubmit=[]),i.hooks.UserPromptSubmit.push({matcher:"",hooks:[{type:"command",command:"ironbee hook activity-start --client claude"}]}),o&&(i.hooks.PreToolUse||(i.hooks.PreToolUse=[]),i.hooks.PreToolUse.push({matcher:"mcp__browser-devtools__.*|mcp__node-devtools__.*|mcp__backend-devtools__.*|mcp__android-devtools__.*",hooks:[{type:"command",command:`ironbee hook require-verification --client claude${r}`}]}),i.hooks.PreToolUse.push({matcher:"Write|Edit",hooks:[{type:"command",command:`ironbee hook require-verdict --client claude${r}`}]}),i.hooks.PostToolUse||(i.hooks.PostToolUse=[]),i.hooks.PostToolUse.push({matcher:"Write|Edit",hooks:[{type:"command",command:"ironbee hook clear-verdict --client claude"}]})),i.hooks.PostToolUse||(i.hooks.PostToolUse=[]);const a=o?"ironbee hook track-action --client claude":"ironbee hook track-action-monitor --client claude";i.hooks.PostToolUse.push({matcher:"",hooks:[{type:"command",command:a}]}),i.hooks.PostToolUseFailure||(i.hooks.PostToolUseFailure=[]),i.hooks.PostToolUseFailure.push({matcher:"",hooks:[{type:"command",command:a}]}),i.hooks.Stop||(i.hooks.Stop=[]);const d=n==="enforce"?"ironbee hook verify-gate --client claude":"ironbee hook activity-end --client claude";i.hooks.Stop.push({matcher:"",hooks:[{type:"command",command:d}]}),i.hooks.SubagentStart||(i.hooks.SubagentStart=[]),i.hooks.SubagentStart.push({matcher:"",hooks:[{type:"command",command:"ironbee hook subagent-start --client claude"}]}),i.hooks.SubagentStop||(i.hooks.SubagentStop=[]),i.hooks.SubagentStop.push({matcher:"",hooks:[{type:"command",command:"ironbee hook subagent-stop --client claude"}]}),i.hooks.SessionEnd||(i.hooks.SessionEnd=[]),i.hooks.SessionEnd.push({matcher:"",hooks:[{type:"command",command:"ironbee hook session-end --client claude"}]}),(0,t.writeFileSync)(e,JSON.stringify(i,null,2))}removeIronBeeHooks(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(!n.hooks)return;for(const o of Object.keys(n.hooks)){const r=n.hooks[o].filter(i=>!this.isIronBeeHook(i));r.length===0?delete n.hooks[o]:n.hooks[o]=r}(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}catch(n){p.logger.debug(`failed to remove hooks from ${e}: ${n}`)}}removeMcpServer(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));let o=!1;n.mcpServers&&n.mcpServers[y]&&(delete n.mcpServers[y],o=!0),n.mcpServers&&n.mcpServers[h]&&(delete n.mcpServers[h],o=!0),n.mcpServers&&n.mcpServers[b]&&(delete n.mcpServers[b],o=!0),n.mcpServers&&n.mcpServers[E]&&(delete n.mcpServers[E],o=!0),N(n)?(0,t.unlinkSync)(e):o&&(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}catch(n){p.logger.debug(`failed to remove MCP server from ${e}: ${n}`)}}removePermission(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8")),o=`mcp__${y}__*`,r=`mcp__${h}__*`,i=`mcp__${b}__*`,a=`mcp__${E}__*`,d="Bash(ironbee *)",f="Bash(ironbee analyze)";n.permissions?.allow&&(n.permissions.allow=n.permissions.allow.filter(m=>m!==o&&m!==r&&m!==i&&m!==a&&m!==d&&m!==f),(0,t.writeFileSync)(e,JSON.stringify(n,null,2)))}catch(n){p.logger.debug(`failed to remove permission from ${e}: ${n}`)}}removeFile(e){(0,t.existsSync)(e)&&(0,t.unlinkSync)(e)}writeMcpConfig(e,n){let o={mcpServers:{}};if((0,t.existsSync)(e))try{o=JSON.parse((0,t.readFileSync)(e,"utf-8")),o.mcpServers||(o.mcpServers={})}catch(r){p.logger.debug(`failed to parse ${e}: ${r}`),o={mcpServers:{}}}if(delete o.mcpServers[y],delete o.mcpServers[h],delete o.mcpServers[b],delete o.mcpServers[E],N(o)){try{(0,t.rmSync)(e,{force:!0})}catch(r){p.logger.debug(`failed to remove empty ${e}: ${r}`)}return}(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}writePermissions(e,n,o){let r={};if((0,t.existsSync)(e))try{r=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(k){p.logger.debug(`failed to parse ${e}: ${k}`),r={}}r.permissions||(r.permissions={allow:[],deny:[]}),r.permissions.allow||(r.permissions.allow=[]);const i=`mcp__${y}__*`,a=`mcp__${h}__*`,d=`mcp__${b}__*`,f=`mcp__${E}__*`,m="Bash(ironbee *)",g="Bash(ironbee analyze)";if(n){const k=(0,u.loadConfig)(o);r.permissions.allow=_(r.permissions.allow,(0,u.isCycleEnabled)(k,"browser"),i),r.permissions.allow=_(r.permissions.allow,(0,u.isCycleEnabled)(k,"node"),a),r.permissions.allow=_(r.permissions.allow,(0,u.isCycleEnabled)(k,"backend"),d),r.permissions.allow=_(r.permissions.allow,(0,u.isCycleEnabled)(k,"android"),f),r.permissions.allow=r.permissions.allow.filter(O=>O!==g),r.permissions.allow.includes(m)||r.permissions.allow.push(m)}else r.permissions.allow=r.permissions.allow.filter(k=>k!==i&&k!==a&&k!==d&&k!==f&&k!==m&&k!==g);(0,t.writeFileSync)(e,JSON.stringify(r,null,2))}}function _e(s){(0,t.mkdirSync)((0,c.join)(s,".ironbee"),{recursive:!0}),(0,P.ensureIronBeeGitignored)(s)}v(_e,"prepareIronBeeDir");0&&(module.exports={ClaudeClient,prepareIronBeeDir});
7
+ `)}v(V,"injectVerifierModel");function $e(s){const e=new Set(["hooks","permissions"]);for(const n of Object.keys(s))if(!e.has(n))return!1;if(s.hooks!==void 0&&Object.keys(s.hooks).length>0)return!1;if(s.permissions!==void 0){const n=s.permissions.allow??[],o=s.permissions.deny??[];if(n.length>0||o.length>0)return!1}return!0}v($e,"isClaudeSettingsEmpty");const Te=["CLAUDE_CODE_ENABLE_TELEMETRY","OTEL_LOGS_EXPORTER","OTEL_METRICS_EXPORTER","OTEL_EXPORTER_OTLP_PROTOCOL","OTEL_EXPORTER_OTLP_ENDPOINT","OTEL_LOG_RAW_API_BODIES","OTEL_RESOURCE_ATTRIBUTES","OTEL_LOGS_EXPORT_INTERVAL"];function j(s){const e=s.OTEL_RESOURCE_ATTRIBUTES;return typeof e=="string"&&e.includes("ironbee.project_name")}v(j,"otelEnvOwnedByUs");function Re(s){return s.replace(/[,=\s]+/g,"-").replace(/^-+|-+$/g,"")||"project"}v(Re,"sanitizeResourceValue");class Ae{constructor(){this.name="claude";this.supportsVerifierModel=!0}static{v(this,"ClaudeClient")}detect(e){return(0,t.existsSync)((0,c.join)(e,".claude"))}resolveProjectDir(){return process.env.CLAUDE_PROJECT_DIR??process.cwd()}resolveAgentSessionId(e,n){const o=process.env.CLAUDE_CODE_SESSION_ID;return typeof o=="string"&&o.length>0?o:void 0}async runSessionStatus(){const{runSessionStatus:e}=await Promise.resolve().then(()=>ye(require("./hooks/session-status")));await e()}install(e,n){const o=n??(0,u.loadConfig)(e),r=(0,u.getVerificationMode)(o),i=r!=="monitor";this.cleanupArtifacts(e);const a=(0,c.join)(e,".claude"),d=(0,c.join)(a,"skills"),f=(0,c.join)(a,"rules"),m=(0,c.join)(a,"commands");(0,t.mkdirSync)(d,{recursive:!0}),(0,t.mkdirSync)(f,{recursive:!0}),(0,t.mkdirSync)(m,{recursive:!0});const g=(0,c.join)(a,"settings.json");if(this.mergeHooksConfig(g,r),this.writePermissions(g,i,e),(0,u.isOTELEnabled)(o)&&this.writeOTELEnv(g,e,o),this.installStatusLine(e,o),i){if(r==="enforce"){const y=(0,c.join)(d,"ironbee-verification.md"),R=(0,t.readFileSync)((0,c.join)(__dirname,"skills","ironbee-verification.md"),"utf-8");(0,t.writeFileSync)(y,R);const de=(0,c.join)(f,"ironbee-verification.md"),me=(0,t.readFileSync)((0,c.join)(__dirname,"rules","ironbee-verification.md"),"utf-8");(0,t.writeFileSync)(de,me)}const p=(0,c.join)(m,"ironbee-verify.md"),$=(0,t.readFileSync)((0,c.join)(__dirname,"commands","ironbee-verify.md"),"utf-8");(0,t.writeFileSync)(p,$);const T=(0,c.join)(a,"agents");(0,t.mkdirSync)(T,{recursive:!0});const re=(0,c.join)(T,"ironbee-verifier.md"),ie=(0,t.readFileSync)((0,c.join)(__dirname,"agents","ironbee-verifier.md"),"utf-8"),te=U(ie,B(e,o)),se=V(te,(0,u.getVerificationModel)(o,"claude"));(0,t.writeFileSync)(re,se);const ae=(0,c.join)(T,"ironbee-scenario.md"),le=(0,t.readFileSync)((0,c.join)(__dirname,"agents","ironbee-scenario.md"),"utf-8"),ce=U(le,B(e,o)),ue=V(ce,(0,u.getVerificationModel)(o,"claude"));(0,t.writeFileSync)(ae,ue);for(const y of I){const R=(0,c.join)(m,`${y}.md`);(0,t.writeFileSync)(R,(0,t.readFileSync)((0,c.join)(__dirname,"commands",`${y}.md`),"utf-8"))}const C=(0,c.join)(e,".mcp.json");if(this.writeMcpConfig(C,e),(0,oe.syncPlatformSectionsToConfig)(e,_e),(0,u.isAutoModeAllowlistEnabled)(o)){const y=(0,c.join)(a,"settings.local.json");this.writeAutoModeAllowlist(y)}(0,u.isClaudeTrustWorkspaceEnabled)(o)&&(0,ee.ensureWorkspaceTrusted)(e)&&console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} trusted workspace in ~/.claude.json ${l.pc.dim("(permissions.allow now honored)")}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} settings ${l.pc.dim("\u2192")} ${l.pc.dim(g)}`),r==="enforce"?(console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} skills ${l.pc.dim("\u2192")} ${l.pc.dim(d)}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} rule ${l.pc.dim("\u2192")} ${l.pc.dim(f)}`)):console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} ${l.pc.yellow("assist mode")} (verification.auto: false) \u2014 manual /ironbee-verify only, no enforcement`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} commands ${l.pc.dim("\u2192")} ${l.pc.dim(m)}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} agents ${l.pc.dim("\u2192")} ${l.pc.dim((0,c.join)(a,"agents"))}`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} mcp ${l.pc.dim("\u2192")} ${l.pc.dim(C)}`)}else console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} ${l.pc.yellow("monitoring-only mode")} (verification.enable: false)`),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} settings ${l.pc.dim("\u2192")} ${l.pc.dim(g)}`)}uninstall(e){this.cleanupArtifacts(e),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} removed hooks, skill, rule, command, MCP, and permissions`)}cleanupArtifacts(e){const n=(0,c.join)(e,".claude"),o=(0,c.join)(n,"skills","ironbee-verification.md"),r=(0,c.join)(n,"skills","ironbee-analyze.md"),i=(0,c.join)(n,"rules","ironbee-verification.md"),a=(0,c.join)(n,"commands","ironbee-analyze.md"),d=(0,c.join)(n,"commands","ironbee-verify.md"),f=(0,c.join)(n,"agents","ironbee-verifier.md");this.removeFile(o),this.removeFile(r),this.removeFile(i),this.removeFile(a),this.removeFile(d),this.removeFile(f),this.removeFile((0,c.join)(n,"agents","ironbee-scenario.md"));for(const p of I)this.removeFile((0,c.join)(n,"commands",`${p}.md`));this.removeFile((0,c.join)(n,"commands","ironbee-run-scenario.md"));const m=(0,c.join)(n,"settings.json");this.removeIronBeeHooks(m),this.removePermission(m),this.removeOTELEnv(m),this.maybeDeleteEmptySettings(m);const g=(0,c.join)(e,".mcp.json");this.removeMcpServer(g),this.removeAutoModeAllowlist((0,c.join)(n,"settings.local.json")),this.uninstallStatusLine(e),(0,J.pruneEmptyDirs)(n)}installStatusLine(e,n){if(!(0,u.isSessionStatusEnabled)(n))return;const o=(0,c.join)(e,".claude","settings.local.json"),r=this.readStatusLineBlock(o);r&&!(0,A.isIronbeeStatusLine)(r.command)&&(0,S.readStatusLineSnapshot)(e,"claude")===void 0&&(0,S.upsertStatusLineSnapshot)(e,"claude",r);const i={type:"command",command:Ee},a=(0,u.getStatusLineRefreshInterval)(n);a!==void 0&&(i.refreshInterval=a),this.writeStatusLineBlock(o,i),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} statusline ${l.pc.dim("\u2192")} ${l.pc.dim(o)}`)}uninstallStatusLine(e){const n=(0,c.join)(e,".claude","settings.local.json"),o=(0,S.readStatusLineSnapshot)(e,"claude");if(o){this.writeStatusLineBlock(n,o),(0,S.clearStatusLineSnapshot)(e,"claude");return}const r=this.readStatusLineBlock(n);r&&(0,A.isIronbeeStatusLine)(r.command)&&this.removeStatusLineBlock(n)}readStatusLineBlock(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(n===null||typeof n!="object")return;const o=n.statusLine;if(o===null||typeof o!="object")return;const r=o.command;if(typeof r!="string"||r.length===0)return;const i=o.padding,a=o.refreshInterval,d={type:"command",command:r};return typeof i=="number"&&(d.padding=i),typeof a=="number"&&(d.refreshInterval=a),d}catch(n){k.logger.debug(`failed to read statusLine from ${e}: ${n}`);return}}writeStatusLineBlock(e,n){let o={};if((0,t.existsSync)(e))try{const r=JSON.parse((0,t.readFileSync)(e,"utf-8"));r!==null&&typeof r=="object"&&!Array.isArray(r)&&(o=r)}catch(r){k.logger.debug(`failed to read ${e} for statusLine write: ${r}`)}else(0,t.mkdirSync)((0,c.join)(e,".."),{recursive:!0});o.statusLine=n,(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}removeStatusLineBlock(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(n===null||typeof n!="object"||Array.isArray(n))return;const o=n;delete o.statusLine,Object.keys(o).length===0?(0,t.unlinkSync)(e):(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}catch(n){k.logger.debug(`failed to remove statusLine from ${e}: ${n}`)}}writeAutoModeAllowlist(e){let n={};if((0,t.existsSync)(e))try{n=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(d){k.logger.debug(`failed to parse ${e} for autoMode allowlist: ${d}`);return}else(0,t.mkdirSync)((0,c.join)(e,".."),{recursive:!0});const o=n.autoMode!==null&&typeof n.autoMode=="object"&&!Array.isArray(n.autoMode)?n.autoMode:{},r=Array.isArray(o.allow)?o.allow.filter(d=>typeof d=="string"):[],i=r.filter(d=>!d.includes(M)),a=r.length===0?[N]:i;o.allow=[...a,we],n.autoMode=o,(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}removeAutoModeAllowlist(e){if(!(0,t.existsSync)(e))return;let n;try{n=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(d){k.logger.debug(`failed to parse ${e} for autoMode strip: ${d}`);return}if(n.autoMode===null||typeof n.autoMode!="object"||Array.isArray(n.autoMode))return;const o=n.autoMode;if(!Array.isArray(o.allow))return;const r=o.allow.filter(d=>typeof d=="string"),i=r.filter(d=>!d.includes(M));if(i.length===r.length)return;i.length===0||i.length===1&&i[0]===N?delete o.allow:o.allow=i,Object.keys(o).length===0?delete n.autoMode:n.autoMode=o,Object.keys(n).length===0?(0,t.unlinkSync)(e):(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}writeOTELEnv(e,n,o){let r={};if((0,t.existsSync)(e))try{const g=JSON.parse((0,t.readFileSync)(e,"utf-8"));g!==null&&typeof g=="object"&&!Array.isArray(g)&&(r=g)}catch(g){k.logger.debug(`failed to read ${e} for otel env write: ${g}`)}else(0,t.mkdirSync)((0,c.join)(e,".."),{recursive:!0});const i=r.env,a=i!==null&&typeof i=="object"&&!Array.isArray(i)?i:{},d=a.OTEL_EXPORTER_OTLP_ENDPOINT;if(typeof d=="string"&&d.length>0&&!j(a)){console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} ${l.pc.yellow("existing OTEL telemetry env detected \u2014 left untouched (session_context not wired for this project)")}`);return}const f=(0,u.getOTELPort)(o),m=Re((0,ne.resolveProjectName)(n));a.CLAUDE_CODE_ENABLE_TELEMETRY="1",a.OTEL_LOGS_EXPORTER="otlp",a.OTEL_METRICS_EXPORTER="none",a.OTEL_EXPORTER_OTLP_PROTOCOL="http/json",a.OTEL_EXPORTER_OTLP_ENDPOINT=`http://127.0.0.1:${f}`,a.OTEL_LOG_RAW_API_BODIES="file:.ironbee/otel",a.OTEL_RESOURCE_ATTRIBUTES=`ironbee.project_name=${m}`,a.OTEL_LOGS_EXPORT_INTERVAL="5000",r.env=a,(0,t.writeFileSync)(e,JSON.stringify(r,null,2)),console.log(` ${l.pc.dim("\u2192")} ${(0,l.orange)("[claude]")} otel env ${l.pc.dim("\u2192")} ${l.pc.dim(`${e} (127.0.0.1:${f})`)}`)}removeOTELEnv(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(n===null||typeof n!="object"||Array.isArray(n))return;const o=n,r=o.env;if(r===null||typeof r!="object"||Array.isArray(r))return;const i=r;if(!j(i))return;for(const a of Te)delete i[a];Object.keys(i).length===0&&delete o.env,(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}catch(n){k.logger.debug(`failed to remove otel env from ${e}: ${n}`)}}maybeDeleteEmptySettings(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));$e(n)&&(0,t.unlinkSync)(e)}catch(n){k.logger.debug(`failed to inspect ${e} for emptiness: ${n}`)}}async runVerifyGate(e){await(0,D.run)(e)}async runClearVerdict(e){await(0,F.run)(e)}async runTrackAction(e){await(0,x.run)(e)}async runSessionStart(e){await(0,X.run)(e)}async runSubagentStart(e){await(0,Q.run)(e)}async runSubagentStop(e){await(0,Z.run)(e)}async runRequireVerdict(e,n){await(0,G.run)(e,n)}async runRequireVerification(e,n){await(0,q.run)(e,n)}async runActivityStart(e){await(0,z.run)(e)}async runActivityEnd(e){await(0,Y.run)(e)}async runTrackActionMonitor(e){await(0,W.run)(e)}async runSessionEnd(e){await(0,K.run)(e)}async runTrackActionPre(e){}isIronBeeHook(e){return e.hooks.some(n=>n.command.includes(be))}mergeHooksConfig(e,n){const o=n!=="monitor",r=n==="assist"?" --soft":"";let i={};if((0,t.existsSync)(e))try{i=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(f){k.logger.debug(`failed to parse ${e}: ${f}`),i={}}i.hooks||(i.hooks={});for(const f of Object.keys(i.hooks)){const m=i.hooks[f].filter(g=>!this.isIronBeeHook(g));m.length===0?delete i.hooks[f]:i.hooks[f]=m}i.hooks.SessionStart||(i.hooks.SessionStart=[]),i.hooks.SessionStart.push({matcher:"",hooks:[{type:"command",command:"ironbee hook session-start --client claude"}]}),i.hooks.UserPromptSubmit||(i.hooks.UserPromptSubmit=[]),i.hooks.UserPromptSubmit.push({matcher:"",hooks:[{type:"command",command:"ironbee hook activity-start --client claude"}]}),o&&(i.hooks.PreToolUse||(i.hooks.PreToolUse=[]),i.hooks.PreToolUse.push({matcher:"mcp__browser-devtools__.*|mcp__node-devtools__.*|mcp__backend-devtools__.*|mcp__android-devtools__.*",hooks:[{type:"command",command:`ironbee hook require-verification --client claude${r}`}]}),i.hooks.PreToolUse.push({matcher:"Write|Edit",hooks:[{type:"command",command:`ironbee hook require-verdict --client claude${r}`}]}),i.hooks.PostToolUse||(i.hooks.PostToolUse=[]),i.hooks.PostToolUse.push({matcher:"Write|Edit",hooks:[{type:"command",command:"ironbee hook clear-verdict --client claude"}]})),i.hooks.PostToolUse||(i.hooks.PostToolUse=[]);const a=o?"ironbee hook track-action --client claude":"ironbee hook track-action-monitor --client claude";i.hooks.PostToolUse.push({matcher:"",hooks:[{type:"command",command:a}]}),i.hooks.PostToolUseFailure||(i.hooks.PostToolUseFailure=[]),i.hooks.PostToolUseFailure.push({matcher:"",hooks:[{type:"command",command:a}]}),i.hooks.Stop||(i.hooks.Stop=[]);const d=n==="enforce"?"ironbee hook verify-gate --client claude":"ironbee hook activity-end --client claude";i.hooks.Stop.push({matcher:"",hooks:[{type:"command",command:d}]}),i.hooks.SubagentStart||(i.hooks.SubagentStart=[]),i.hooks.SubagentStart.push({matcher:"",hooks:[{type:"command",command:"ironbee hook subagent-start --client claude"}]}),i.hooks.SubagentStop||(i.hooks.SubagentStop=[]),i.hooks.SubagentStop.push({matcher:"",hooks:[{type:"command",command:"ironbee hook subagent-stop --client claude"}]}),i.hooks.SessionEnd||(i.hooks.SessionEnd=[]),i.hooks.SessionEnd.push({matcher:"",hooks:[{type:"command",command:"ironbee hook session-end --client claude"}]}),(0,t.writeFileSync)(e,JSON.stringify(i,null,2))}removeIronBeeHooks(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));if(!n.hooks)return;for(const o of Object.keys(n.hooks)){const r=n.hooks[o].filter(i=>!this.isIronBeeHook(i));r.length===0?delete n.hooks[o]:n.hooks[o]=r}(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}catch(n){k.logger.debug(`failed to remove hooks from ${e}: ${n}`)}}removeMcpServer(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8"));let o=!1;n.mcpServers&&n.mcpServers[h]&&(delete n.mcpServers[h],o=!0),n.mcpServers&&n.mcpServers[b]&&(delete n.mcpServers[b],o=!0),n.mcpServers&&n.mcpServers[E]&&(delete n.mcpServers[E],o=!0),n.mcpServers&&n.mcpServers[w]&&(delete n.mcpServers[w],o=!0),P(n)?(0,t.unlinkSync)(e):o&&(0,t.writeFileSync)(e,JSON.stringify(n,null,2))}catch(n){k.logger.debug(`failed to remove MCP server from ${e}: ${n}`)}}removePermission(e){if((0,t.existsSync)(e))try{const n=JSON.parse((0,t.readFileSync)(e,"utf-8")),o=`mcp__${h}__*`,r=`mcp__${b}__*`,i=`mcp__${E}__*`,a=`mcp__${w}__*`,d="Bash(ironbee *)",f="Bash(ironbee analyze)";n.permissions?.allow&&(n.permissions.allow=n.permissions.allow.filter(m=>m!==o&&m!==r&&m!==i&&m!==a&&m!==d&&m!==f),(0,t.writeFileSync)(e,JSON.stringify(n,null,2)))}catch(n){k.logger.debug(`failed to remove permission from ${e}: ${n}`)}}removeFile(e){(0,t.existsSync)(e)&&(0,t.unlinkSync)(e)}writeMcpConfig(e,n){let o={mcpServers:{}};if((0,t.existsSync)(e))try{o=JSON.parse((0,t.readFileSync)(e,"utf-8")),o.mcpServers||(o.mcpServers={})}catch(r){k.logger.debug(`failed to parse ${e}: ${r}`),o={mcpServers:{}}}if(delete o.mcpServers[h],delete o.mcpServers[b],delete o.mcpServers[E],delete o.mcpServers[w],P(o)){try{(0,t.rmSync)(e,{force:!0})}catch(r){k.logger.debug(`failed to remove empty ${e}: ${r}`)}return}(0,t.writeFileSync)(e,JSON.stringify(o,null,2))}writePermissions(e,n,o){let r={};if((0,t.existsSync)(e))try{r=JSON.parse((0,t.readFileSync)(e,"utf-8"))}catch(p){k.logger.debug(`failed to parse ${e}: ${p}`),r={}}r.permissions||(r.permissions={allow:[],deny:[]}),r.permissions.allow||(r.permissions.allow=[]);const i=`mcp__${h}__*`,a=`mcp__${b}__*`,d=`mcp__${E}__*`,f=`mcp__${w}__*`,m="Bash(ironbee *)",g="Bash(ironbee analyze)";if(n){const p=(0,u.loadConfig)(o);r.permissions.allow=O(r.permissions.allow,(0,u.isCycleEnabled)(p,"browser"),i),r.permissions.allow=O(r.permissions.allow,(0,u.isCycleEnabled)(p,"node"),a),r.permissions.allow=O(r.permissions.allow,(0,u.isCycleEnabled)(p,"backend"),d),r.permissions.allow=O(r.permissions.allow,(0,u.isCycleEnabled)(p,"android"),f),r.permissions.allow=r.permissions.allow.filter($=>$!==g),r.permissions.allow.includes(m)||r.permissions.allow.push(m)}else r.permissions.allow=r.permissions.allow.filter(p=>p!==i&&p!==a&&p!==d&&p!==f&&p!==m&&p!==g);(0,t.writeFileSync)(e,JSON.stringify(r,null,2))}}function Ce(s){(0,t.mkdirSync)((0,c.join)(s,".ironbee"),{recursive:!0}),(0,H.ensureIronBeeGitignored)(s)}v(Ce,"prepareIronBeeDir");0&&(module.exports={ClaudeClient,prepareIronBeeDir});
@@ -0,0 +1,32 @@
1
+ ### Android platform (enabled)
2
+ - **Use for**: Android app scenarios on a real device / emulator.
3
+ - **Server**: `android-devtools` · **scenario tools**: `mcp__android-devtools__adt_scenario-*`.
4
+ - **Store**: project → `.ironbee/scenarios/adt`, global → `~/.ironbee/scenarios/adt` (the server's
5
+ `SCENARIOS_DIR`; pass `scope`, the server resolves the path).
6
+ - Scenario **scripts** call android tools via `callTool('<bare-tool>', {...})` — discover the
7
+ available `adt_*` tool names (device / interaction / content / a11y / o11y …) from your connected
8
+ MCP schemas; don't guess.
9
+
10
+ **What to test & how — capture the SAME evidence the verifier would** (a scenario runs FOR
11
+ verification, so its script must collect what the android cycle collects). In the script:
12
+ 1. **Connect + launch** — `adt_device_connect` (list targets with `adt_device_list-targets`; an
13
+ emulator is usually `emulator-5554`), then `adt_device_launch-app` with the package name.
14
+ 2. Pick an **evidence path** for the changed code area:
15
+ - **Device-evidence path** — drive the UI to exercise the change (`adt_interaction_tap` /
16
+ `adt_interaction_input-text` / `adt_interaction_swipe` / `adt_interaction_scroll`; locate elements
17
+ with `adt_a11y_find-element` / the UI-snapshot's element refs — do NOT hand-parse the snapshot
18
+ TEXT with regex), then capture **BOTH**: a screenshot (`adt_content_take-screenshot`
19
+ **with `returnOutput: true`** — put the returned `filePath` in your result; the verifier `Read`s
20
+ that file to judge the pixels. **Do NOT set `includeBase64`** — a nested scenario screenshot isn't
21
+ surfaced as an inline image and base64 only bloats the result) **AND** a UI snapshot
22
+ (`adt_a11y_take-ui-snapshot`, `returnOutput: true` — its TEXT view hierarchy / labels is what the
23
+ verifier reads). Both are MANDATORY (visual + structural, like the browser screenshot + aria pair).
24
+ - **Log-evidence path** — `adt_o11y_log-read` / `adt_o11y_log-follow` (with `returnOutput: true`)
25
+ for the tag(s) relevant to the change; confirm expected lines appear AND no FATAL / crash (E/
26
+ entries) for the app package.
27
+ - **Network-evidence path** — capture outgoing HTTP traffic with `adt_o11y_get-http-requests` (`returnOutput: true`): start capture, drive the app (`adt_interaction_*`) to trigger traffic, read again, and put the captured request(s)/status in your result. Optional setup helpers (NOT evidence): `adt_o11y_new-trace-id` to pin a correlation root, `adt_stub_*` to mock/intercept responses.
28
+
29
+ `return` the evidence — UI-snapshot text, log lines, the screenshot `filePath`s — **plus explicit
30
+ pass/fail assertions**. That returned result is what `/ironbee-verify scenario:<name>` reads to judge
31
+ functional + structural (from the text) and **visual** (by `Read`ing the returned screenshot files).
32
+ **`android-devtools` is Android-only.**
@@ -0,0 +1,26 @@
1
+ ### Backend platform (enabled)
2
+ - **Use for**: backend protocol scenarios (HTTP / gRPC / GraphQL / WebSocket / DB).
3
+ - **Server**: `backend-devtools` · **scenario tools**: `mcp__backend-devtools__bedt_scenario-*`.
4
+ - **Store**: project → `.ironbee/scenarios/bedt`, global → `~/.ironbee/scenarios/bedt` (the server's
5
+ `SCENARIOS_DIR`; pass `scope`, the server resolves the path).
6
+ - Scenario **scripts** call backend tools via `callTool('<bare-tool>', {...})` — discover the
7
+ available `bedt_*` tool names (request http/grpc/graphql/websocket, log, db, o11y …) from your
8
+ connected MCP schemas; don't guess.
9
+
10
+ **What to test & how — capture the SAME evidence the verifier would** (a scenario runs FOR
11
+ verification, so its script must collect what the backend cycle collects). At least ONE evidence path
12
+ is required — in the script, exercise one+:
13
+ - **Protocol-call** — `bedt_request_http` / `bedt_request_grpc` / `bedt_request_graphql` /
14
+ `bedt_request_websocket-open…` / `bedt_request_replay`; inspect the response `status` / body /
15
+ headers (4xx/5xx and gRPC non-OK are NORMAL results, not transport errors — decide pass/fail by what
16
+ the task requires). Chain POST→GET to confirm side effects.
17
+ - **Log-evidence** — `bedt_log_register-source` then `bedt_log_read` / `bedt_log_read-multi` /
18
+ `bedt_log_follow` (filter by level / pattern / trace-id) when an external driver hits the endpoint.
19
+ - **DB-evidence** — `bedt_db_connect` (read-only by default) then `bedt_db_query` /
20
+ `bedt_db_describe-table` / `bedt_db_snapshot` + `bedt_db_diff` to inspect state after a migration /
21
+ write.
22
+
23
+ `return` the responses / log lines / rows (capture each read with `returnOutput: true` so the data
24
+ reaches the script's `return`) **plus explicit pass/fail assertions** so a later verify run can judge
25
+ them. Runtime-agnostic —
26
+ works for any backend language (Node, Java, Python, Go, Rust, Ruby, .NET, …).
@@ -0,0 +1,41 @@
1
+ ### Browser platform (enabled)
2
+ - **Use for**: UI / frontend scenarios driven through a real browser.
3
+ - **Server**: `browser-devtools` · **scenario tools**: `mcp__browser-devtools__bdt_scenario-*`
4
+ (`bdt_scenario-add` / `-update` / `-delete` / `-list` / `-search` / `-run`).
5
+ - **Store**: project → `.ironbee/scenarios/bdt`, global → `~/.ironbee/scenarios/bdt` (the server's
6
+ `SCENARIOS_DIR`; you pass `scope`, the server resolves the path).
7
+ - Scenario **scripts** call browser tools via `callTool('<bare-tool>', {...})` — discover the
8
+ available `bdt_*` tool names (navigation / interaction / content / a11y / o11y …) from your
9
+ connected MCP schemas; don't guess.
10
+
11
+ **What to test & how — capture the SAME evidence the verifier would** (a scenario runs FOR
12
+ verification, so its script must collect what the browser cycle collects). In the script:
13
+ 1. **Navigate** — `bdt_navigation_go-to` to the affected page(s), then **actually interact** (click
14
+ buttons, fill forms, submit data, trigger the workflow that changed). A click-through that asserts
15
+ nothing verifies nothing — the interaction is what makes the evidence meaningful. **Target elements
16
+ with the `selector`/`ref` the aria-snapshot returns for each** (e.g. `getByRole(...)` or `@e12`) —
17
+ do NOT hand-parse the snapshot TEXT with regex/string-matching: embedded quotes or special chars in
18
+ labels make that brittle (it silently misses elements). This includes deriving a positional
19
+ **`.nth(i)`** index by parsing the snapshot — a quote or special char in any earlier label shifts
20
+ every index, so the click lands on the wrong element (or none). Pick each element by its own
21
+ `getByRole(...)`/`ref`, or scope it to the matching card/row with a CSS `:has()` selector (e.g.
22
+ `.product-card:has(h4:has-text('Widget')) button:has-text('Add to cart')`). NOTE: the
23
+ browser-devtools resolver accepts only a flat `getByXYZ(...)` expression OR a CSS string — Playwright
24
+ locator chaining like `.filter({ hasText })` does NOT parse. Never compute element positions from
25
+ snapshot text.
26
+ 2. **Screenshot** — `bdt_content_take-screenshot` (or `includeScreenshot: true` on a nav/interaction
27
+ call) **with `returnOutput: true`, and put the returned `filePath` (absolute path to the saved PNG)
28
+ in your result**. The later verifier opens that file with its `Read` tool to judge the pixels
29
+ (readability, layout, cut-off content, expected render). **Do NOT set `includeBase64`** — a nested
30
+ scenario screenshot is NOT surfaced as an inline MCP image (`scenario-run` strips nested image data)
31
+ and base64 only bloats the result; the returned `filePath` is how visual judging works.
32
+ 3. **Accessibility** — `bdt_a11y_take-aria-snapshot` (or `includeSnapshot: true`), called with
33
+ `returnOutput: true` — the snapshot TEXT is what the verifier reads to judge page structure.
34
+ 4. **Console** — `bdt_o11y_get-console-messages` with `returnOutput: true` to surface errors.
35
+
36
+ `return` the evidence — aria-snapshot text, page text (`bdt_content_get-as-text`), console errors, the
37
+ screenshot `filePath`s — **plus explicit pass/fail assertions**. That returned result is what
38
+ `/ironbee-verify scenario:<name>` reads to judge the run: functional + structural from the text, and
39
+ **visual by `Read`ing the returned screenshot files**. Capture the evidence AFTER the interactions
40
+ whose state you want to assert; for an intermediate state (a modal that opens then closes) capture at
41
+ that point too.
@@ -0,0 +1,27 @@
1
+ ### Node.js platform (enabled)
2
+ - **Use for**: Node.js runtime-debug scenarios (V8 inspector probes / logs).
3
+ - **Server**: `node-devtools` · **scenario tools**: `mcp__node-devtools__ndt_scenario-*`.
4
+ - **Store**: project → `.ironbee/scenarios/ndt`, global → `~/.ironbee/scenarios/ndt` (the server's
5
+ `SCENARIOS_DIR`; pass `scope`, the server resolves the path).
6
+ - Scenario **scripts** call node debug tools via `callTool('<bare-tool>', {...})` — discover the
7
+ available `ndt_*` tool names (debug connect / probes / snapshots / logs …) from your connected
8
+ MCP schemas; don't guess.
9
+
10
+ **What to test & how — capture the SAME evidence the verifier would** (a scenario runs FOR
11
+ verification, so its script must collect what the node cycle collects). In the script:
12
+ 1. **Connect** — `ndt_debug_connect` (one of `pid` / `processName` / `containerName` /
13
+ `inspectorPort` / `wsUrl`).
14
+ 2. Pick an **evidence path** for the changed code path:
15
+ - **Probe path** (proves the code path executed) — set a probe at the changed location
16
+ (`ndt_debug_put-tracepoint` / `ndt_debug_put-logpoint` / `ndt_debug_put-exceptionpoint`),
17
+ **exercise the path** (drive it via a request / CLI / another platform's call — without this the
18
+ probe never fires), then read `ndt_debug_get-probe-snapshots`; at least one probe must come back
19
+ `triggered: true`.
20
+ - **Log path** (proves no errors during execution) — exercise the path, then `ndt_debug_get-logs`
21
+ filtered to the error level (no ERROR-level entries = pass).
22
+
23
+ `return` the probe snapshots / logs (read them with `returnOutput: true` so their data reaches the
24
+ script's `return`) **plus explicit pass/fail assertions** so a later verify run can judge them.
25
+ **`node-devtools` is
26
+ Node.js ONLY** — never author `ndt_*` scenarios for Java / Python / Go / Rust / Ruby / .NET / PHP
27
+ backends; use the **backend** platform for those.
@@ -32,6 +32,9 @@ If you see only `ios/`, `web/`, or no mobile directories — the project does NO
32
32
  - **Log-evidence path** (device logs confirm the changed code path executed):
33
33
  - Read Logcat output for the tag(s) relevant to the changed code: `mcp__android-devtools__adt_o11y_log-read` or `mcp__android-devtools__adt_o11y_log-follow` (drain a follow with `mcp__android-devtools__adt_o11y_log-get-followed`, stop it with `mcp__android-devtools__adt_o11y_log-stop-follow`).
34
34
  - Confirm expected log lines appear AND no unexpected crashes (FATAL / E/ entries for the app package).
35
+ - **Network-evidence path** (captured HTTP traffic confirms a network/API-related change):
36
+ - Capture the app's outgoing HTTP(S) requests: `mcp__android-devtools__adt_o11y_get-http-requests` (Frida/OkHttp in-process — no proxy, no CA install; OkHttp-based stacks only — Retrofit / React Native / HttpURLConnection). **Capture is forward-looking**: call it once to start capture, drive the app to trigger traffic (`mcp__android-devtools__adt_interaction_*`), then call it again to read. Confirm the expected request(s) / response status appear.
37
+ - **Auxiliary (NOT evidence — setup/correlation only):** to pin one correlation root across the flow, optionally `mcp__android-devtools__adt_o11y_new-trace-id` first (it stamps `traceparent` on every captured request; inspect/clear via `mcp__android-devtools__adt_o11y_set-trace-context` / `mcp__android-devtools__adt_o11y_get-trace-context`). To set up test conditions, `mcp__android-devtools__adt_stub_mock-http-response` / `mcp__android-devtools__adt_stub_intercept-http-request` mock or mutate responses (list/clear with `mcp__android-devtools__adt_stub_list` / `mcp__android-devtools__adt_stub_clear`). `mcp__android-devtools__adt_figma_compare-screen-with-design` checks emulator-vs-Figma parity (optional, requires `FIGMA_ACCESS_TOKEN`). None of these count toward the gate — they shape the test, they don't inspect it.
35
38
 
36
39
  **Batch (speed):** connect + launch-app run standalone first (prerequisites). On the device-evidence path, batch the UI interactions + the UI snapshot into one `mcp__android-devtools__adt_execute`; the snapshot captures the state after the batched interactions, so to assert an intermediate state take a snapshot at that point too. The device-evidence screenshot is usually pixel-judged (a visual change) — take THAT one standalone with `includeBase64: true` so you can see it; batch it only when it's purely gate evidence. Log-evidence reads batch together too.
37
40
 
@@ -51,6 +54,7 @@ On fail, include `issues`. On pass after a previous fail, include `fixes`.
51
54
  Android-cycle pass criteria:
52
55
  - **Device-evidence**: at least one UI interaction tool fired AND a screenshot was taken AND a UI snapshot was taken AND both show the expected UI state/structure.
53
56
  - **Log-evidence**: Logcat was read AND the expected log lines are present AND no crash (FATAL / unhandled exception) from the app's package.
57
+ - **Network-evidence**: the app's outgoing HTTP traffic was captured AND the expected request(s) / response status confirm the change behaved correctly.
54
58
 
55
59
  ## Multi-cycle (browser + android simultaneously)
56
60