@ironbee-ai/cli 0.32.0 → 0.33.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 (36) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/clients/base.js +1 -1
  3. package/dist/clients/claude/agents/ironbee-scenario.md +36 -10
  4. package/dist/clients/claude/agents/ironbee-verifier.md +19 -1
  5. package/dist/clients/claude/commands/ironbee-manage-scenario.md +2 -1
  6. package/dist/clients/claude/index.js +4 -4
  7. package/dist/clients/codex/agents/ironbee-scenario.md +36 -10
  8. package/dist/clients/codex/agents/ironbee-verifier.md +19 -1
  9. package/dist/clients/codex/commands/ironbee-manage-scenario/SKILL.main.md +18 -6
  10. package/dist/clients/codex/commands/ironbee-manage-scenario/SKILL.md +2 -1
  11. package/dist/clients/codex/commands/ironbee-sync-scenario/SKILL.main.md +1 -1
  12. package/dist/clients/codex/commands/ironbee-verify/SKILL.main.md +1 -0
  13. package/dist/clients/codex/index.js +2 -2
  14. package/dist/clients/codex/skills/ironbee-verification.main.md +11 -0
  15. package/dist/clients/cursor/commands/ironbee-manage-scenario/SKILL.md +18 -6
  16. package/dist/clients/cursor/commands/ironbee-sync-scenario/SKILL.md +1 -1
  17. package/dist/clients/cursor/commands/ironbee-verify/SKILL.md +1 -0
  18. package/dist/clients/cursor/skills/ironbee-verification.md +5 -0
  19. package/dist/clients/registry.js +1 -1
  20. package/dist/commands/config.js +1 -1
  21. package/dist/commands/hook.js +22 -19
  22. package/dist/commands/install.js +1 -1
  23. package/dist/commands/platform-suggest.js +2 -0
  24. package/dist/hooks/core/actions.js +9 -7
  25. package/dist/hooks/core/run-checks.js +7 -0
  26. package/dist/hooks/core/verify-gate.js +30 -21
  27. package/dist/lib/config.js +1 -1
  28. package/dist/lib/event.js +1 -1
  29. package/dist/lib/headless.js +1 -0
  30. package/dist/lib/install-version.js +1 -1
  31. package/dist/lib/prompt.js +6 -5
  32. package/dist/tui/config/schema.js +1 -1
  33. package/dist/tui/platforms/area.js +2 -2
  34. package/dist/tui/projects/area.js +4 -4
  35. package/dist/tui/shell/session.js +5 -5
  36. package/package.json +1 -1
@@ -67,23 +67,35 @@ tools directly: that keeps it gate-orthogonal — no `verification_id`, can't fa
67
67
  > passes" means fixing the SCRIPT, never working around the app.)
68
68
 
69
69
  ## Script format
70
- JS run in the devtools sandbox (async — top-level `await`/`return` work); reads params from `args`:
70
+ JS run in the devtools sandbox (async — top-level `await`/`return` work); reads its inputs from `args`:
71
71
 
72
72
  ```js
73
- const { baseUrl } = args; // declared via argsSchema
73
+ const { baseUrl } = args; // declared in the scenario's `params` contract
74
74
  const result = await callTool('<bare-tool-name>', { /* tool input */ });
75
75
  return { ok: true };
76
76
  ```
77
77
 
78
78
  Discover the available `callTool` tool names for a platform from your connected MCP schemas — don't
79
- guess. Document the expected `args` in the `description` + the `argsSchema` metadata.
79
+ guess. Declare each input via the first-class **`params`** contract (§Parameters), not `argsSchema`.
80
+
81
+ ## Parameters (`params`) — typed, defaulted, validated
82
+ Declare a parametric scenario's inputs via the first-class **`params`** array on
83
+ `scenario-add` / `scenario-update` (top-level field, NOT metadata — supersedes the old `argsSchema`
84
+ convention). Each entry: `name` (required — the `args` key the script reads), `description`, `type`
85
+ (`string`/`number`/`boolean`/`object`/`array`; `object`/`array` shallow-checked at the top level),
86
+ `default` (applied when the arg is omitted — **capture it from the live-authoring run** so the
87
+ scenario re-runs "as captured" with zero args), `example` (doc-only shape when there's no `default`),
88
+ `required` (reject the run when there's no value AND no `default`). `scenario-run` applies defaults,
89
+ enforces `required`, shallow-validates declared types, and surfaces `params` in list/search/run
90
+ output. Pass `args` only to OVERRIDE a default. `scenario-update` shallow-replaces `params` (re-send
91
+ the full array; omit to keep the stored contract).
80
92
 
81
93
  ## Metadata conventions (stamp on add/update)
82
- - `argsSchema` — declared params, e.g. `{ "baseUrl": "string" }`. **Mandatory for parametric scenarios.**
83
94
  - `ironbee.coveredPaths` — source paths exercised (array), when derivable.
84
95
  - `ironbee.group` / `ironbee.order` — for a cross-platform split.
85
- - `*_scenario-update` does a **shallow replace** of metadata — to change one key, re-send the FULL
86
- metadata object (read it first, merge, write back).
96
+ - `*_scenario-update` does a **shallow replace** of metadata (and of `params`) — to change one key,
97
+ re-send the FULL object / array (read it first, merge, write back). The typed input contract is the
98
+ first-class `params` field (§Parameters), not a metadata key.
87
99
 
88
100
  The platform sections below list each enabled cycle's server, tool prefix, and store dir.
89
101
 
@@ -22,7 +22,7 @@ directly. This is NOT a verification cycle — no verdict, no gate.
22
22
  - **passes** → still current; (non-check) `*_scenario-update` to stamp `ironbee.commit` → HEAD
23
23
  (read via `git rev-parse HEAD`) + `ironbee.liveValidated: true`. `*_scenario-update`
24
24
  shallow-replaces metadata — read current metadata and re-send it MERGED with these two keys
25
- (don't drop `coveredPaths` / `group` / `argsSchema`).
25
+ (don't drop `coveredPaths` / `group`; omit `params` to keep the stored typed contract).
26
26
  - **mechanical DRIFT** (the way to reach / drive the flow changed, not the expected outcome) →
27
27
  repair the SCRIPT mechanics only, `*_scenario-update`, re-run until green, then stamp.
28
28
  - **real DEFECT** (the expected outcome is unreachable — the app broke) → **STOP, report, do NOT
@@ -35,6 +35,7 @@ Whatever the scenario directs, the gate is unchanged — you must still call eve
35
35
  1. **Start verification**: Run `echo '{"session_id":"<your-session-id>"}' | ironbee hook verification-start` via terminal.
36
36
  **In fix mode**, add the intent flag so IronBee's completion gate enforces fix-until-pass:
37
37
  `echo '{"session_id":"<your-session-id>"}' | ironbee hook verification-start --intent fix`
38
+ 1.5. **Run the project checks FIRST (lint/test/…)**: `echo '{"session_id":"<your-session-id>"}' | ironbee hook run-checks` (generous shell timeout — they may take minutes). Runs the configured `verification.checks` and records the results the gate reads. 🛑 **IF ANY REQUIRED CHECK FAILS, THE VERIFICATION HAS ALREADY FAILED — STOP.** It is **NOT your call** whether the failure is "just a fixture", "unrelated", or "pre-existing" — a required non-zero exit **IS** a failure. Do **NOT** touch the devtools tools or submit a pass; submit a **fail** verdict whose `issues` are the failing checks (the gate enforces the fix). Only when **every** required check PASSES do you continue. ("no checks configured" → just continue.)
38
39
  2. **Build and start** the application if not already running.
39
40
  3. **For every active cycle, run its flow** — driven by the **Verification scenario** above when one was supplied, otherwise as described in the platform sections near the bottom of this file. All active cycles must be exercised within this same verification cycle.
40
41
  4. **Stop** the dev server when verification is complete (every cycle — including the final one).
@@ -49,6 +49,11 @@ This holds even when the consumer was not itself edited: the place you should ha
49
49
  echo '{"session_id":"<your-session-id>"}' | ironbee hook verification-start
50
50
  ```
51
51
  Devtools tools are blocked without this.
52
+ 2.5. **Run the project checks FIRST (lint/test/…)** — the deterministic first step of verification:
53
+ ```
54
+ echo '{"session_id":"<your-session-id>"}' | ironbee hook run-checks
55
+ ```
56
+ Use a generous shell timeout (they may take minutes). This runs the project's configured `verification.checks` and records the results the gate reads. 🛑 **IF ANY REQUIRED CHECK FAILS, THE VERIFICATION HAS ALREADY FAILED — STOP.** It is **NOT your call** whether the failure is "just a fixture", "unrelated", or "pre-existing" — a required non-zero exit **IS** a failure. Do **NOT** drive the devtools tools, do **NOT** submit a pass; submit a **fail** verdict whose `issues` are the failing checks (the gate enforces the fix). Only when **every** required check PASSES do you continue. (If it reports "no checks configured", just continue.)
52
57
  3. Build and start the application if not already running.
53
58
  4. **Run the per-cycle flows for every active cycle.** See the platform sections near the bottom of this file — each enabled cycle's section has its own flow steps and mandatory tools. All active cycles must be exercised within this one verification cycle.
54
59
  5. Stop the dev server when verification is complete (every cycle — including the final one).
@@ -1 +1 @@
1
- "use strict";var f=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var n=(t,e)=>f(t,"name",{value:e,configurable:!0});var j=(t,e)=>{for(var r in e)f(t,r,{get:e[r],enumerable:!0})},w=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of h(e))!E.call(t,l)&&l!==r&&f(t,l,{get:()=>e[l],enumerable:!(o=b(e,l))||o.enumerable});return t};var y=t=>w(f({},"__esModule",{value:!0}),t);var A={};j(A,{REGISTERED_CLIENTS:()=>i,clientNames:()=>g,detectClients:()=>I,findClient:()=>p,isProjectActive:()=>x,listActiveProjects:()=>v,resolveTargetClients:()=>P});module.exports=y(A);var s=require("fs"),u=require("path"),a=require("./claude"),C=require("./cursor"),m=require("./codex"),d=require("../lib/projects-registry");const i=[new a.ClaudeClient,new C.CursorClient,new m.CodexClient];function p(t){return i.find(e=>e.name===t)}n(p,"findClient");function I(t){return i.filter(e=>e.detect(t))}n(I,"detectClients");function g(){return i.map(t=>t.name).join(", ")}n(g,"clientNames");function P(t,e){if(e==="all")return i;if(e!==void 0){const o=p(e);if(!o)throw new Error(`Unknown client: '${e}'. Available: ${g()}.`);return[o]}const r=I(t);return r.length>0?r:[i[0]]}n(P,"resolveTargetClients");function x(t){return!c(t.path)||!S(t.path)?!1:i.some(e=>D(e,t.path))?!0:c((0,u.join)(t.path,".ironbee"))}n(x,"isProjectActive");function v(){return(0,d.listProjects)().filter(x)}n(v,"listActiveProjects");function D(t,e){try{return t.detect(e)}catch{return!1}}n(D,"safeDetect");function c(t){try{return(0,s.existsSync)(t)}catch{return!1}}n(c,"safeExists");function S(t){try{return(0,s.statSync)(t).isDirectory()}catch{return!1}}n(S,"safeIsDir");0&&(module.exports={REGISTERED_CLIENTS,clientNames,detectClients,findClient,isProjectActive,listActiveProjects,resolveTargetClients});
1
+ "use strict";var s=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var n=(e,t)=>s(e,"name",{value:t,configurable:!0});var j=(e,t)=>{for(var i in t)s(e,i,{get:t[i],enumerable:!0})},P=(e,t,i,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of E(t))!y.call(e,o)&&o!==i&&s(e,o,{get:()=>t[o],enumerable:!(r=h(t,o))||r.enumerable});return e};var S=e=>P(s({},"__esModule",{value:!0}),e);var A={};j(A,{REGISTERED_CLIENTS:()=>l,SUGGESTION_PRIORITY:()=>c,clientNames:()=>b,detectClients:()=>g,findClient:()=>p,isProjectActive:()=>x,listActiveProjects:()=>T,resolveSuggestionClient:()=>w,resolveTargetClients:()=>v});module.exports=S(A);var u=require("fs"),a=require("path"),C=require("./claude"),d=require("./cursor"),I=require("./codex"),m=require("../lib/projects-registry");const l=[new C.ClaudeClient,new d.CursorClient,new I.CodexClient];function p(e){return l.find(t=>t.name===e)}n(p,"findClient");const c=["claude","codex","cursor"];function w(e){const t=e.filter(r=>typeof r.runHeadlessPrompt=="function");if(t.length===0)return;const i=n(r=>{const o=c.indexOf(r.name);return o===-1?c.length:o},"rank");return t.slice().sort((r,o)=>i(r)-i(o))[0]}n(w,"resolveSuggestionClient");function g(e){return l.filter(t=>t.detect(e))}n(g,"detectClients");function b(){return l.map(e=>e.name).join(", ")}n(b,"clientNames");function v(e,t){if(t==="all")return l;if(t!==void 0){const r=p(t);if(!r)throw new Error(`Unknown client: '${t}'. Available: ${b()}.`);return[r]}const i=g(e);return i.length>0?i:[l[0]]}n(v,"resolveTargetClients");function x(e){return!f(e.path)||!R(e.path)?!1:l.some(t=>D(t,e.path))?!0:f((0,a.join)(e.path,".ironbee"))}n(x,"isProjectActive");function T(){return(0,m.listProjects)().filter(x)}n(T,"listActiveProjects");function D(e,t){try{return e.detect(t)}catch{return!1}}n(D,"safeDetect");function f(e){try{return(0,u.existsSync)(e)}catch{return!1}}n(f,"safeExists");function R(e){try{return(0,u.statSync)(e).isDirectory()}catch{return!1}}n(R,"safeIsDir");0&&(module.exports={REGISTERED_CLIENTS,SUGGESTION_PRIORITY,clientNames,detectClients,findClient,isProjectActive,listActiveProjects,resolveSuggestionClient,resolveTargetClients});
@@ -1,2 +1,2 @@
1
1
  "use strict";var m=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var l=(e,o)=>m(e,"name",{value:o,configurable:!0});var q=(e,o)=>{for(var n in o)m(e,n,{get:o[n],enumerable:!0})},M=(e,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of K(o))!L.call(e,i)&&i!==n&&m(e,i,{get:()=>o[i],enumerable:!(r=V(o,i))||r.enumerable});return e};var Y=e=>M(m({},"__esModule",{value:!0}),e);var le={};q(le,{configCommand:()=>u,runGet:()=>B,runList:()=>U,runPath:()=>W,runSet:()=>F,runUnset:()=>_});module.exports=Y(le);var D=require("commander"),g=require("fs"),N=require("os"),d=require("path"),f=require("../clients/registry"),I=require("./install"),b=require("../lib/config"),G=require("../lib/gitignore"),k=require("../lib/logger"),t=require("../lib/output"),h=require("../lib/prompt"),J=require("../lib/projects-registry");const z=new Set(["verification","collector","browser","node","backend","android","terminal","browserDevTools","nodeDevTools","backendDevTools","androidDevTools","terminalDevTools","telemetry","privacy","statusLine","otel","codex","runtime"]);function S(e){return(0,d.join)((0,d.resolve)(e),".ironbee","config.json")}l(S,"projectConfigPath");function C(e){return(0,d.join)((0,d.resolve)(e),".ironbee","config.local.json")}l(C,"projectLocalConfigPath");function O(){return(0,d.join)((0,N.homedir)(),".ironbee","config.json")}l(O,"globalConfigPath");function w(e){if(!(0,g.existsSync)(e))return{};try{const o=(0,g.readFileSync)(e,"utf-8");return o.trim().length===0?{}:JSON.parse(o)}catch(o){throw k.logger.debug(`failed to read ${e}: ${o}`),new Error(`Config at ${e} is not valid JSON: ${o instanceof Error?o.message:o}`)}}l(w,"readConfigFile");function j(e,o){(0,g.mkdirSync)((0,d.join)(e,".."),{recursive:!0}),(0,g.writeFileSync)(e,JSON.stringify(o,null,2)+`
2
- `)}l(j,"writeConfigFile");function H(e){const o=e.indexOf(".");return o===-1?e:e.slice(0,o)}l(H,"topKey");const X=["verification.context"];function v(e){for(const o of X)if(e===o||e.startsWith(o+"."))return!1;return z.has(H(e))}l(v,"affectsArtifacts");function Q(e,o){if(o.length===0)return e;const n=o.split(".");let r=e;for(const i of n){if(r==null||typeof r!="object"||Array.isArray(r))return;r=r[i]}return r}l(Q,"getAtPath");function Z(e,o,n){if(o.length===0)throw new Error("Cannot set the root config \u2014 pass a dotted key (e.g. `collector.url`).");const r=o.split(".");let i=e;for(let a=0;a<r.length-1;a++){const s=r[a],c=i[s];(c==null||typeof c!="object"||Array.isArray(c))&&(i[s]={}),i=i[s]}i[r[r.length-1]]=n}l(Z,"setAtPath");function ee(e,o){if(o.length===0)return!1;const n=o.split(".");let r=e;for(let a=0;a<n.length-1;a++){const s=n[a],c=r[s];if(c==null||typeof c!="object"||Array.isArray(c))return!1;r=c}const i=n[n.length-1];return Object.prototype.hasOwnProperty.call(r,i)?(delete r[i],!0):!1}l(ee,"unsetAtPath");function oe(e,o){if(o)try{return JSON.parse(e)}catch(n){throw new Error(`--json was set but value is not valid JSON: ${n instanceof Error?n.message:n}`)}try{return JSON.parse(e)}catch{return e}}l(oe,"parseValue");function $(e){if(e.global===!0&&e.local===!0)throw new Error("Pass at most one of --global / --local.");if(e.global===!0)return{path:O(),label:"global",useGlobal:!0};const o=e.projectDir??process.cwd();return e.local===!0?{path:C(o),label:"local",useGlobal:!1}:{path:S(o),label:"project",useGlobal:!1}}l($,"resolveWriteTarget");function E(e){if((e.global===!0?1:0)+(e.project===!0?1:0)+(e.local===!0?1:0)>1)throw new Error("Pass at most one of --global / --project / --local.");if(e.global===!0)return{label:"global",path:O()};const n=e.projectDir??process.cwd();return e.project===!0?{label:"project",path:S(n)}:e.local===!0?{label:"local",path:C(n)}:{label:"merged",path:n}}l(E,"resolveReadTarget");function A(e){return e.label==="merged"?(0,b.loadConfig)(e.path):w(e.path)}l(A,"readForGet");function ne(e){return e===void 0?"(unset)":typeof e=="string"?e:JSON.stringify(e,null,2)}l(ne,"formatValue");function te(e,o){const n=(0,f.detectClients)(e);if(o===void 0&&n.length===0)return console.log(` ${t.pc.dim("\xB7")} ${t.pc.dim("no clients detected in")} ${t.pc.dim(e)} ${t.pc.dim("\u2014 skipping artifact rerender")}`),[];const r=(0,b.loadConfig)(e),i=(0,f.resolveTargetClients)(e,o);for(const a of i)a.install(e,r);return(0,G.ensureIronBeeGitignored)(e),i.map(a=>a.name)}l(te,"rerenderArtifacts");function P(e,o,n,r){const i=(0,g.existsSync)(e)?(0,g.readFileSync)(e,"utf-8"):null;j(e,o);try{return te(n,r)}catch(a){try{i===null?(0,g.existsSync)(e)&&(0,g.unlinkSync)(e):(0,g.writeFileSync)(e,i)}catch(s){k.logger.debug(`config rollback failed: ${s}`)}throw a}}l(P,"writeAndRerender");const R=10;function re(e){const o=(0,f.listActiveProjects)(),n=(0,J.canonicalizePath)(e);return o.filter(r=>r.path!==n)}l(re,"listOtherProjects");function ie(e){const o=e.length===1?"other project":"other projects";console.log(` ${t.pc.yellow("\u26A0")} ${t.pc.bold(String(e.length))} ${o} registered in the inventory still on the prior state:`);const n=e.slice(0,R);for(const r of n)console.log(` ${t.pc.dim("\xB7")} ${t.pc.dim(r.path)}`);e.length>R&&console.log(` ${t.pc.dim("\u2026and")} ${t.pc.bold(String(e.length-R))} ${t.pc.dim("more")}`)}l(ie,"printOtherProjectsBanner");async function T(e,o,n){if(!o)return;const r=re(e);if(r.length===0)return;ie(r);let i;if(n===!0)i=!0;else if(n===!1){console.log(` ${t.pc.dim("Run")} ${t.pc.cyan("ironbee install --all")} ${t.pc.dim("later to apply, or")} ${t.pc.cyan("ironbee install")} ${t.pc.dim("in selected projects.")}`);return}else if((0,h.isInteractive)()){const a=r.length===1?"this project":`these ${r.length} projects`;i=await(0,h.promptYesNo)(` Apply this change to ${a} now?`,!0)}else{console.log(` ${t.pc.dim("Run")} ${t.pc.cyan("ironbee install --all")} ${t.pc.dim("to apply everywhere, or pass")} ${t.pc.cyan("--apply-all")} ${t.pc.dim("to skip this prompt.")}`);return}if(!i){console.log(` ${t.pc.dim("Skipped. Run")} ${t.pc.cyan("ironbee install --all")} ${t.pc.dim("later to apply.")}`);return}console.log(),await(0,I.runInstallAll)({})}l(T,"maybeApplyToOtherProjects");async function F(e,o,n){if(e.length===0)throw new Error("Key is required (dotted path, e.g. `collector.url`).");const r=$(n),i=oe(o,n.json===!0),a=w(r.path),s=JSON.parse(JSON.stringify(a));Z(s,e,i);const c=n.projectDir??process.cwd(),p=n.rerender!==!1&&v(e);let y=[];p?y=P(r.path,s,c,n.client):j(r.path,s),console.log(`${t.pc.green("\u2713")} Set ${t.pc.cyan(e)} = ${t.pc.bold(ne(i))} in ${r.label} config (${t.pc.dim(r.path)}).`),p?y.length>0&&(console.log(` ${t.pc.dim("Re-rendered artifacts for:")} ${t.pc.bold(y.join(", "))}`),console.log(` ${t.pc.yellow("\u26A0")} Restart your editor / agent session for the change to take effect.`)):n.rerender===!1&&v(e)&&console.log(` ${t.pc.yellow("\u26A0")} --no-rerender set: artifacts may now be out of sync with config. Run ${t.pc.cyan("ironbee install")} to resync.`),x(e),r.useGlobal&&await T(c,p,n.applyAll)}l(F,"runSet");function x(e){const o=(0,b.findActiveEnvOverride)(e);o!==void 0&&console.log(` ${t.pc.yellow("\u26A0")} ${t.pc.cyan(o.envVar)} is set in this shell \u2014 env overrides file config, so ${t.pc.cyan(e)} reads will return the env value until ${t.pc.cyan(o.envVar)} is unset.`)}l(x,"warnIfEnvShadowed");async function _(e,o){if(e.length===0)throw new Error("Key is required (dotted path, e.g. `collector.url`).");const n=$(o),r=w(n.path),i=JSON.parse(JSON.stringify(r));if(!ee(i,e)){console.log(`${t.pc.dim("\xB7")} ${t.pc.cyan(e)} not present in ${n.label} config (${t.pc.dim(n.path)}). No-op.`);return}const s=o.projectDir??process.cwd(),c=o.rerender!==!1&&v(e);let p=[];c?p=P(n.path,i,s,o.client):j(n.path,i),console.log(`${t.pc.green("\u2713")} Unset ${t.pc.cyan(e)} in ${n.label} config (${t.pc.dim(n.path)}).`),c&&p.length>0&&(console.log(` ${t.pc.dim("Re-rendered artifacts for:")} ${t.pc.bold(p.join(", "))}`),console.log(` ${t.pc.yellow("\u26A0")} Restart your editor / agent session for the change to take effect.`)),x(e),n.useGlobal&&await T(s,c,o.applyAll)}l(_,"runUnset");function B(e,o){const n=E(o),r=A(n),i=Q(r,e);i===void 0&&(console.error(`${t.pc.dim("\xB7")} ${t.pc.cyan(e)} ${t.pc.dim("not set in")} ${n.label} ${t.pc.dim("config")}`),process.exit(1)),console.log(typeof i=="string"?i:JSON.stringify(i,null,2))}l(B,"runGet");function U(e){const o=E(e),n=A(o);console.log(JSON.stringify(n,null,2))}l(U,"runList");function W(e){const o=$(e);console.log(o.path)}l(W,"runPath");const u=new D.Command("config").description("Read or write IronBee configuration values (project or global). Smart re-render: artifact-affecting keys auto-update installed client files.");u.command("get <key>").description("Print the value at a dotted path. Default: merged effective value (global + project + local). --global / --project / --local narrow to one source.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Read from global config only (~/.ironbee/config.json).").option("--project","Read from project config only (<project>/.ironbee/config.json).").option("--local","Read from project-local config only (<project>/.ironbee/config.local.json \u2014 gitignored).").action((e,o)=>{try{B(e,o)}catch(n){console.error(`${t.pc.red("\u2717")} ${n instanceof Error?n.message:n}`),process.exit(1)}}),u.command("set <key> <value>").description("Set a config value. Type-coerces (true/42/[\u2026]/{\u2026}) unless --json forces strict parsing. Re-renders client artifacts when the top-level key affects them. After a global write (`-g`) on an artifact-affecting key, prompts whether to apply the change to every other registered project. Use --local to write to the gitignored personal-override layer instead of the committed project config.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Write to global config (~/.ironbee/config.json).").option("--local","Write to the gitignored project-local override (<project>/.ironbee/config.local.json) instead of the committed project config. Mutually exclusive with --global.").option("--client <name>",`Filter clients for artifact rerender (${(0,f.clientNames)()}), or "all". Default: detected clients.`).option("--no-rerender","Skip artifact rerender even when the key normally triggers it.").option("--json","Require value to parse as strict JSON (no string fallback).").option("--apply-all","After a global write on an artifact-affecting key, apply the change to every registered project without prompting.").option("--no-apply-all","After a global write on an artifact-affecting key, do NOT apply to other registered projects (suppress the prompt).").action(async(e,o,n)=>{try{await F(e,o,n)}catch(r){console.error(`${t.pc.red("\u2717")} ${r instanceof Error?r.message:r}`),process.exit(1)}}),u.command("unset <key>").description("Remove a config key. Idempotent \u2014 no-op when the key is absent. Re-renders client artifacts when the top-level key affects them. After a global unset (`-g`) on an artifact-affecting key, prompts whether to apply the change to every other registered project. Use --local to remove from the gitignored personal-override layer instead of the committed project config.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Write to global config (~/.ironbee/config.json).").option("--local","Write to the gitignored project-local override (<project>/.ironbee/config.local.json) instead of the committed project config. Mutually exclusive with --global.").option("--client <name>",`Filter clients for artifact rerender (${(0,f.clientNames)()}), or "all". Default: detected clients.`).option("--no-rerender","Skip artifact rerender even when the key normally triggers it.").option("--apply-all","After a global unset on an artifact-affecting key, apply the change to every registered project without prompting.").option("--no-apply-all","After a global unset on an artifact-affecting key, do NOT apply to other registered projects (suppress the prompt).").action(async(e,o)=>{try{await _(e,o)}catch(n){console.error(`${t.pc.red("\u2717")} ${n instanceof Error?n.message:n}`),process.exit(1)}}),u.command("list").description("Print the entire config. Default: merged effective config; --global / --project / --local narrow to one source.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Read from global config only.").option("--project","Read from project config only.").option("--local","Read from project-local config only (<project>/.ironbee/config.local.json \u2014 gitignored).").action(e=>{try{U(e)}catch(o){console.error(`${t.pc.red("\u2717")} ${o instanceof Error?o.message:o}`),process.exit(1)}}),u.command("path").description("Print the on-disk path of the targeted config file (project by default; --global for global, --local for the gitignored personal-override layer).").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Print global config path (~/.ironbee/config.json).").option("--local","Print project-local config path (<project>/.ironbee/config.local.json).").action(e=>{try{W(e)}catch(o){console.error(`${t.pc.red("\u2717")} ${o instanceof Error?o.message:o}`),process.exit(1)}});0&&(module.exports={configCommand,runGet,runList,runPath,runSet,runUnset});
2
+ `)}l(j,"writeConfigFile");function H(e){const o=e.indexOf(".");return o===-1?e:e.slice(0,o)}l(H,"topKey");const X=["verification.context","verification.checks"];function v(e){for(const o of X)if(e===o||e.startsWith(o+"."))return!1;return z.has(H(e))}l(v,"affectsArtifacts");function Q(e,o){if(o.length===0)return e;const n=o.split(".");let r=e;for(const i of n){if(r==null||typeof r!="object"||Array.isArray(r))return;r=r[i]}return r}l(Q,"getAtPath");function Z(e,o,n){if(o.length===0)throw new Error("Cannot set the root config \u2014 pass a dotted key (e.g. `collector.url`).");const r=o.split(".");let i=e;for(let a=0;a<r.length-1;a++){const s=r[a],c=i[s];(c==null||typeof c!="object"||Array.isArray(c))&&(i[s]={}),i=i[s]}i[r[r.length-1]]=n}l(Z,"setAtPath");function ee(e,o){if(o.length===0)return!1;const n=o.split(".");let r=e;for(let a=0;a<n.length-1;a++){const s=n[a],c=r[s];if(c==null||typeof c!="object"||Array.isArray(c))return!1;r=c}const i=n[n.length-1];return Object.prototype.hasOwnProperty.call(r,i)?(delete r[i],!0):!1}l(ee,"unsetAtPath");function oe(e,o){if(o)try{return JSON.parse(e)}catch(n){throw new Error(`--json was set but value is not valid JSON: ${n instanceof Error?n.message:n}`)}try{return JSON.parse(e)}catch{return e}}l(oe,"parseValue");function $(e){if(e.global===!0&&e.local===!0)throw new Error("Pass at most one of --global / --local.");if(e.global===!0)return{path:O(),label:"global",useGlobal:!0};const o=e.projectDir??process.cwd();return e.local===!0?{path:C(o),label:"local",useGlobal:!1}:{path:S(o),label:"project",useGlobal:!1}}l($,"resolveWriteTarget");function E(e){if((e.global===!0?1:0)+(e.project===!0?1:0)+(e.local===!0?1:0)>1)throw new Error("Pass at most one of --global / --project / --local.");if(e.global===!0)return{label:"global",path:O()};const n=e.projectDir??process.cwd();return e.project===!0?{label:"project",path:S(n)}:e.local===!0?{label:"local",path:C(n)}:{label:"merged",path:n}}l(E,"resolveReadTarget");function A(e){return e.label==="merged"?(0,b.loadConfig)(e.path):w(e.path)}l(A,"readForGet");function ne(e){return e===void 0?"(unset)":typeof e=="string"?e:JSON.stringify(e,null,2)}l(ne,"formatValue");function te(e,o){const n=(0,f.detectClients)(e);if(o===void 0&&n.length===0)return console.log(` ${t.pc.dim("\xB7")} ${t.pc.dim("no clients detected in")} ${t.pc.dim(e)} ${t.pc.dim("\u2014 skipping artifact rerender")}`),[];const r=(0,b.loadConfig)(e),i=(0,f.resolveTargetClients)(e,o);for(const a of i)a.install(e,r);return(0,G.ensureIronBeeGitignored)(e),i.map(a=>a.name)}l(te,"rerenderArtifacts");function P(e,o,n,r){const i=(0,g.existsSync)(e)?(0,g.readFileSync)(e,"utf-8"):null;j(e,o);try{return te(n,r)}catch(a){try{i===null?(0,g.existsSync)(e)&&(0,g.unlinkSync)(e):(0,g.writeFileSync)(e,i)}catch(s){k.logger.debug(`config rollback failed: ${s}`)}throw a}}l(P,"writeAndRerender");const R=10;function re(e){const o=(0,f.listActiveProjects)(),n=(0,J.canonicalizePath)(e);return o.filter(r=>r.path!==n)}l(re,"listOtherProjects");function ie(e){const o=e.length===1?"other project":"other projects";console.log(` ${t.pc.yellow("\u26A0")} ${t.pc.bold(String(e.length))} ${o} registered in the inventory still on the prior state:`);const n=e.slice(0,R);for(const r of n)console.log(` ${t.pc.dim("\xB7")} ${t.pc.dim(r.path)}`);e.length>R&&console.log(` ${t.pc.dim("\u2026and")} ${t.pc.bold(String(e.length-R))} ${t.pc.dim("more")}`)}l(ie,"printOtherProjectsBanner");async function T(e,o,n){if(!o)return;const r=re(e);if(r.length===0)return;ie(r);let i;if(n===!0)i=!0;else if(n===!1){console.log(` ${t.pc.dim("Run")} ${t.pc.cyan("ironbee install --all")} ${t.pc.dim("later to apply, or")} ${t.pc.cyan("ironbee install")} ${t.pc.dim("in selected projects.")}`);return}else if((0,h.isInteractive)()){const a=r.length===1?"this project":`these ${r.length} projects`;i=await(0,h.promptYesNo)(` Apply this change to ${a} now?`,!0)}else{console.log(` ${t.pc.dim("Run")} ${t.pc.cyan("ironbee install --all")} ${t.pc.dim("to apply everywhere, or pass")} ${t.pc.cyan("--apply-all")} ${t.pc.dim("to skip this prompt.")}`);return}if(!i){console.log(` ${t.pc.dim("Skipped. Run")} ${t.pc.cyan("ironbee install --all")} ${t.pc.dim("later to apply.")}`);return}console.log(),await(0,I.runInstallAll)({})}l(T,"maybeApplyToOtherProjects");async function F(e,o,n){if(e.length===0)throw new Error("Key is required (dotted path, e.g. `collector.url`).");const r=$(n),i=oe(o,n.json===!0),a=w(r.path),s=JSON.parse(JSON.stringify(a));Z(s,e,i);const c=n.projectDir??process.cwd(),p=n.rerender!==!1&&v(e);let y=[];p?y=P(r.path,s,c,n.client):j(r.path,s),console.log(`${t.pc.green("\u2713")} Set ${t.pc.cyan(e)} = ${t.pc.bold(ne(i))} in ${r.label} config (${t.pc.dim(r.path)}).`),p?y.length>0&&(console.log(` ${t.pc.dim("Re-rendered artifacts for:")} ${t.pc.bold(y.join(", "))}`),console.log(` ${t.pc.yellow("\u26A0")} Restart your editor / agent session for the change to take effect.`)):n.rerender===!1&&v(e)&&console.log(` ${t.pc.yellow("\u26A0")} --no-rerender set: artifacts may now be out of sync with config. Run ${t.pc.cyan("ironbee install")} to resync.`),x(e),r.useGlobal&&await T(c,p,n.applyAll)}l(F,"runSet");function x(e){const o=(0,b.findActiveEnvOverride)(e);o!==void 0&&console.log(` ${t.pc.yellow("\u26A0")} ${t.pc.cyan(o.envVar)} is set in this shell \u2014 env overrides file config, so ${t.pc.cyan(e)} reads will return the env value until ${t.pc.cyan(o.envVar)} is unset.`)}l(x,"warnIfEnvShadowed");async function _(e,o){if(e.length===0)throw new Error("Key is required (dotted path, e.g. `collector.url`).");const n=$(o),r=w(n.path),i=JSON.parse(JSON.stringify(r));if(!ee(i,e)){console.log(`${t.pc.dim("\xB7")} ${t.pc.cyan(e)} not present in ${n.label} config (${t.pc.dim(n.path)}). No-op.`);return}const s=o.projectDir??process.cwd(),c=o.rerender!==!1&&v(e);let p=[];c?p=P(n.path,i,s,o.client):j(n.path,i),console.log(`${t.pc.green("\u2713")} Unset ${t.pc.cyan(e)} in ${n.label} config (${t.pc.dim(n.path)}).`),c&&p.length>0&&(console.log(` ${t.pc.dim("Re-rendered artifacts for:")} ${t.pc.bold(p.join(", "))}`),console.log(` ${t.pc.yellow("\u26A0")} Restart your editor / agent session for the change to take effect.`)),x(e),n.useGlobal&&await T(s,c,o.applyAll)}l(_,"runUnset");function B(e,o){const n=E(o),r=A(n),i=Q(r,e);i===void 0&&(console.error(`${t.pc.dim("\xB7")} ${t.pc.cyan(e)} ${t.pc.dim("not set in")} ${n.label} ${t.pc.dim("config")}`),process.exit(1)),console.log(typeof i=="string"?i:JSON.stringify(i,null,2))}l(B,"runGet");function U(e){const o=E(e),n=A(o);console.log(JSON.stringify(n,null,2))}l(U,"runList");function W(e){const o=$(e);console.log(o.path)}l(W,"runPath");const u=new D.Command("config").description("Read or write IronBee configuration values (project or global). Smart re-render: artifact-affecting keys auto-update installed client files.");u.command("get <key>").description("Print the value at a dotted path. Default: merged effective value (global + project + local). --global / --project / --local narrow to one source.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Read from global config only (~/.ironbee/config.json).").option("--project","Read from project config only (<project>/.ironbee/config.json).").option("--local","Read from project-local config only (<project>/.ironbee/config.local.json \u2014 gitignored).").action((e,o)=>{try{B(e,o)}catch(n){console.error(`${t.pc.red("\u2717")} ${n instanceof Error?n.message:n}`),process.exit(1)}}),u.command("set <key> <value>").description("Set a config value. Type-coerces (true/42/[\u2026]/{\u2026}) unless --json forces strict parsing. Re-renders client artifacts when the top-level key affects them. After a global write (`-g`) on an artifact-affecting key, prompts whether to apply the change to every other registered project. Use --local to write to the gitignored personal-override layer instead of the committed project config.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Write to global config (~/.ironbee/config.json).").option("--local","Write to the gitignored project-local override (<project>/.ironbee/config.local.json) instead of the committed project config. Mutually exclusive with --global.").option("--client <name>",`Filter clients for artifact rerender (${(0,f.clientNames)()}), or "all". Default: detected clients.`).option("--no-rerender","Skip artifact rerender even when the key normally triggers it.").option("--json","Require value to parse as strict JSON (no string fallback).").option("--apply-all","After a global write on an artifact-affecting key, apply the change to every registered project without prompting.").option("--no-apply-all","After a global write on an artifact-affecting key, do NOT apply to other registered projects (suppress the prompt).").action(async(e,o,n)=>{try{await F(e,o,n)}catch(r){console.error(`${t.pc.red("\u2717")} ${r instanceof Error?r.message:r}`),process.exit(1)}}),u.command("unset <key>").description("Remove a config key. Idempotent \u2014 no-op when the key is absent. Re-renders client artifacts when the top-level key affects them. After a global unset (`-g`) on an artifact-affecting key, prompts whether to apply the change to every other registered project. Use --local to remove from the gitignored personal-override layer instead of the committed project config.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Write to global config (~/.ironbee/config.json).").option("--local","Write to the gitignored project-local override (<project>/.ironbee/config.local.json) instead of the committed project config. Mutually exclusive with --global.").option("--client <name>",`Filter clients for artifact rerender (${(0,f.clientNames)()}), or "all". Default: detected clients.`).option("--no-rerender","Skip artifact rerender even when the key normally triggers it.").option("--apply-all","After a global unset on an artifact-affecting key, apply the change to every registered project without prompting.").option("--no-apply-all","After a global unset on an artifact-affecting key, do NOT apply to other registered projects (suppress the prompt).").action(async(e,o)=>{try{await _(e,o)}catch(n){console.error(`${t.pc.red("\u2717")} ${n instanceof Error?n.message:n}`),process.exit(1)}}),u.command("list").description("Print the entire config. Default: merged effective config; --global / --project / --local narrow to one source.").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Read from global config only.").option("--project","Read from project config only.").option("--local","Read from project-local config only (<project>/.ironbee/config.local.json \u2014 gitignored).").action(e=>{try{U(e)}catch(o){console.error(`${t.pc.red("\u2717")} ${o instanceof Error?o.message:o}`),process.exit(1)}}),u.command("path").description("Print the on-disk path of the targeted config file (project by default; --global for global, --local for the gitignored personal-override layer).").option("-p, --project-dir <dir>","Project directory (default: cwd).").option("-g, --global","Print global config path (~/.ironbee/config.json).").option("--local","Print project-local config path (<project>/.ironbee/config.local.json).").action(e=>{try{W(e)}catch(o){console.error(`${t.pc.red("\u2717")} ${o instanceof Error?o.message:o}`),process.exit(1)}});0&&(module.exports={configCommand,runGet,runList,runPath,runSet,runUnset});
@@ -1,24 +1,27 @@
1
- "use strict";var g=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var E=(i,e)=>g(i,"name",{value:e,configurable:!0});var x=(i,e)=>{for(var t in e)g(i,t,{get:e[t],enumerable:!0})},D=(i,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of C(e))!P.call(i,n)&&n!==t&&g(i,n,{get:()=>e[n],enumerable:!(o=N(e,n))||o.enumerable});return i};var _=i=>D(g({},"__esModule",{value:!0}),i);var O={};x(O,{hookCommand:()=>r});module.exports=_(O);var S=require("commander"),w=require("../clients/registry"),k=require("../hooks/core/submit-verdict"),y=require("../hooks/core/verification-lifecycle"),u=require("../lib/config"),l=require("../lib/logger"),d=require("../lib/output"),m=require("../lib/stdin"),j=require("../hooks/core/session-state"),v=require("../clients/session-id"),f=require("../clients/agent-project-dir"),p=require("../lib/runtime-paths");function h(i,e){return(0,u.getVerificationEnabled)((0,u.loadConfig)(i))?!1:(l.logger.debug(`${e}: verification is disabled \u2014 silent no-op`),!0)}E(h,"isVerificationDisabled");function s(i){const e=i??process.env.IRONBEE_CLIENT;e||(process.stderr.write(`Error: client not specified. Use --client <name> or set IRONBEE_CLIENT env var.
1
+ "use strict";var h=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var E=(i,e)=>h(i,"name",{value:e,configurable:!0});var x=(i,e)=>{for(var t in e)h(i,t,{get:e[t],enumerable:!0})},O=(i,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of R(e))!P.call(i,n)&&n!==t&&h(i,n,{get:()=>e[n],enumerable:!(o=C(e,n))||o.enumerable});return i};var D=i=>O(h({},"__esModule",{value:!0}),i);var _={};x(_,{hookCommand:()=>r});module.exports=D(_);var S=require("commander"),w=require("../clients/registry"),I=require("../hooks/core/submit-verdict"),y=require("../hooks/core/verification-lifecycle"),N=require("../hooks/core/run-checks"),p=require("../lib/config"),l=require("../lib/logger"),a=require("../lib/output"),u=require("../lib/stdin"),j=require("../hooks/core/session-state"),m=require("../clients/session-id"),f=require("../clients/agent-project-dir"),v=require("../lib/runtime-paths");function g(i,e){return(0,p.getVerificationEnabled)((0,p.loadConfig)(i))?!1:(l.logger.debug(`${e}: verification is disabled \u2014 silent no-op`),!0)}E(g,"isVerificationDisabled");function s(i){const e=i??process.env.IRONBEE_CLIENT;e||(process.stderr.write(`Error: client not specified. Use --client <name> or set IRONBEE_CLIENT env var.
2
2
  `),process.exit(1));const t=(0,w.findClient)(e);return t||(process.stderr.write(`Error: unknown client "${e}". Run \`ironbee install\` to set up.
3
- `),process.exit(1)),t}E(s,"resolveClient");const r=new S.Command("hook").description("Internal hook runners (invoked by the AI coding client)");r.command("verify-gate").description("Stop hook \u2014 gates task completion until browser verification passes").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runVerifyGate(t)}),r.command("clear-verdict").description("PostToolUse hook \u2014 clears stale verdict after code edits").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runClearVerdict(t)}),r.command("track-action").description("PostToolUse hook \u2014 tracks browser-devtools tool calls in actions.jsonl").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runTrackAction(t)}),r.command("track-action-monitor").description("PostToolUse hook (monitoring-only mode) \u2014 submits send_event jobs for non-devtools tools and falls back to starting an activity if needed").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runTrackActionMonitor(t)}),r.command("track-action-pre").description("Codex PreToolUse hook \u2014 stashes a hrtime timestamp keyed by tool_use_id so the matching PostToolUse can derive tool_call.duration (Codex hook stdin does not carry duration_ms). No-op on Claude/Cursor \u2014 their hosts provide duration natively.").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runTrackActionPre(t)}),r.command("subagent-start").description("SubagentStart hook \u2014 dispatched per client via IClient.runSubagentStart. Codex: writes the agent_id \u2192 parent session_id bridge (codex-threads.json). Claude: joins the sub-agent as an activity participant so the activity closes only when the last participant (main + all sub-agents) leaves.").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSubagentStart?.(t)}),r.command("subagent-stop").description("SubagentStop hook \u2014 dispatched per client via IClient.runSubagentStop. Codex: prune the thread map + record the sub-agent's agent_transcript_path for the analytics fold. Claude: backstop that closes a verifier-owned activity/cycle the sub-agent left open without a verdict.").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSubagentStop?.(t)}),r.command("activity-end").description("Stop hook (monitoring-only mode) \u2014 closes the active activity and triggers a background queue flush").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runActivityEnd(t)}),r.command("session-start").description("SessionStart hook \u2014 records session start in actions.jsonl").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSessionStart(t)}),r.command("session-status").description("Statusline command (Claude) \u2014 emits a session_status event and chains the user's original statusline").action(async()=>{await(0,w.findClient)("claude")?.runSessionStatus?.()}),r.command("require-verdict").description("PreToolUse hook \u2014 blocks file edits until verdict is submitted after browser tool usage").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").option("--soft","non-blocking assist-mode variant: stash file_change state but never block the edit").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runRequireVerdict(t,{soft:i.soft===!0})}),r.command("session-end").description("SessionEnd hook \u2014 records session end in actions.jsonl").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSessionEnd(t)}),r.command("activity-start").description("UserPromptSubmit/beforeSubmitPrompt hook \u2014 starts activity tracking on each agent turn").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runActivityStart(t)}),r.command("require-verification").description("PreToolUse hook \u2014 blocks browser tools until verification-start is called").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").option("--soft","non-blocking assist-mode variant: inject _metadata but never block the devtools call").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runRequireVerification(t,{soft:i.soft===!0})}),r.command("verification-start").description(`Start a verification cycle (called by agent via Bash). Optional --intent flag: "fix" arms the verify-gate's fix-until-pass backstop (a fail verdict keeps blocking even in a zero-edit window); "report" or omitted = verify-only run (clears any stale intent \u2014 "report" is a tolerated alias of omitting the flag, mirroring the command's mode token).`).option("--intent <mode>",'declared intent of this verification run: "fix" or "report"').action(async i=>{const e=(0,f.resolveAgentProjectDir)();if(h(e,"verification-start")){(0,d.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
3
+ `),process.exit(1)),t}E(s,"resolveClient");const r=new S.Command("hook").description("Internal hook runners (invoked by the AI coding client)");r.command("verify-gate").description("Stop hook \u2014 gates task completion until browser verification passes").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runVerifyGate(t)}),r.command("clear-verdict").description("PostToolUse hook \u2014 clears stale verdict after code edits").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runClearVerdict(t)}),r.command("track-action").description("PostToolUse hook \u2014 tracks browser-devtools tool calls in actions.jsonl").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runTrackAction(t)}),r.command("track-action-monitor").description("PostToolUse hook (monitoring-only mode) \u2014 submits send_event jobs for non-devtools tools and falls back to starting an activity if needed").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runTrackActionMonitor(t)}),r.command("track-action-pre").description("Codex PreToolUse hook \u2014 stashes a hrtime timestamp keyed by tool_use_id so the matching PostToolUse can derive tool_call.duration (Codex hook stdin does not carry duration_ms). No-op on Claude/Cursor \u2014 their hosts provide duration natively.").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runTrackActionPre(t)}),r.command("subagent-start").description("SubagentStart hook \u2014 dispatched per client via IClient.runSubagentStart. Codex: writes the agent_id \u2192 parent session_id bridge (codex-threads.json). Claude: joins the sub-agent as an activity participant so the activity closes only when the last participant (main + all sub-agents) leaves.").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSubagentStart?.(t)}),r.command("subagent-stop").description("SubagentStop hook \u2014 dispatched per client via IClient.runSubagentStop. Codex: prune the thread map + record the sub-agent's agent_transcript_path for the analytics fold. Claude: backstop that closes a verifier-owned activity/cycle the sub-agent left open without a verdict.").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSubagentStop?.(t)}),r.command("activity-end").description("Stop hook (monitoring-only mode) \u2014 closes the active activity and triggers a background queue flush").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runActivityEnd(t)}),r.command("session-start").description("SessionStart hook \u2014 records session start in actions.jsonl").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSessionStart(t)}),r.command("session-status").description("Statusline command (Claude) \u2014 emits a session_status event and chains the user's original statusline").action(async()=>{await(0,w.findClient)("claude")?.runSessionStatus?.()}),r.command("require-verdict").description("PreToolUse hook \u2014 blocks file edits until verdict is submitted after browser tool usage").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").option("--soft","non-blocking assist-mode variant: stash file_change state but never block the edit").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runRequireVerdict(t,{soft:i.soft===!0})}),r.command("session-end").description("SessionEnd hook \u2014 records session end in actions.jsonl").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runSessionEnd(t)}),r.command("activity-start").description("UserPromptSubmit/beforeSubmitPrompt hook \u2014 starts activity tracking on each agent turn").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runActivityStart(t)}),r.command("require-verification").description("PreToolUse hook \u2014 blocks browser tools until verification-start is called").option("--client <name>","client name (overrides IRONBEE_CLIENT env var)").option("--soft","non-blocking assist-mode variant: inject _metadata but never block the devtools call").action(async i=>{const e=s(i.client);if(!e)return;const t=e.resolveProjectDir();await e.runRequireVerification(t,{soft:i.soft===!0})}),r.command("verification-start").description(`Start a verification cycle (called by agent via Bash). Optional --intent flag: "fix" arms the verify-gate's fix-until-pass backstop (a fail verdict keeps blocking even in a zero-edit window); "report" or omitted = verify-only run (clears any stale intent \u2014 "report" is a tolerated alias of omitting the flag, mirroring the command's mode token).`).option("--intent <mode>",'declared intent of this verification run: "fix" or "report"').action(async i=>{const e=(0,f.resolveAgentProjectDir)();if(g(e,"verification-start")){(0,a.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
4
4
  `,0);return}i.intent!==void 0&&i.intent!=="fix"&&i.intent!=="report"&&(process.stderr.write(`Error: --intent must be "fix" or "report".
5
- `),process.exit(1));const t=i.intent;let o;try{o=JSON.parse((0,m.readStdin)())}catch{process.stderr.write(`Error: no JSON provided via stdin.
6
- `),process.exit(1)}const n=(0,v.resolveAgentSessionId)(o,e);n||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
7
- `),process.exit(1));const c=(0,p.sessionDir)(e,n);(0,l.setLogFile)(`${c}/session.log`);const a=(0,u.isRecordingEnabled)(e),I=await(0,y.startVerification)({sessionId:n,sessionDir:c,actionsFile:`${c}/actions.jsonl`,recordingEnabled:a,intent:t}),b={verification_id:I.verificationId,trace_id:I.traceId};a&&(b.recording_required=!0,b.message="Recording is required. Call bdt_content_start-recording BEFORE using any other browser tools."),(0,d.writeAndExit)(JSON.stringify(b)+`
8
- `,0)}),r.command("verification-end").description("End a verification cycle (called by agent via Bash)").action(async()=>{const i=(0,f.resolveAgentProjectDir)();if(h(i,"verification-end")){(0,d.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
9
- `,0);return}let e;try{e=JSON.parse((0,m.readStdin)())}catch{process.stderr.write(`Error: no JSON provided via stdin.
10
- `),process.exit(1)}const t=(0,v.resolveAgentSessionId)(e,i);t||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
11
- `),process.exit(1));const o=(0,p.sessionDir)(i,t);(0,l.setLogFile)(`${o}/session.log`);const n=await(0,y.endVerification)({sessionId:t,sessionDir:o,actionsFile:`${o}/actions.jsonl`});n.success?(0,d.writeAndExit)(JSON.stringify({verification_id:n.verificationId,trace_id:n.traceId})+`
5
+ `),process.exit(1));const t=i.intent;let o;try{o=JSON.parse((0,u.readStdin)())}catch{process.stderr.write(`Error: no JSON provided via stdin.
6
+ `),process.exit(1)}const n=(0,m.resolveAgentSessionId)(o,e);n||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
7
+ `),process.exit(1));const c=(0,v.sessionDir)(e,n);(0,l.setLogFile)(`${c}/session.log`);const d=(0,p.isRecordingEnabled)(e),k=await(0,y.startVerification)({sessionId:n,sessionDir:c,actionsFile:`${c}/actions.jsonl`,recordingEnabled:d,intent:t}),b={verification_id:k.verificationId,trace_id:k.traceId};d&&(b.recording_required=!0,b.message="Recording is required. Call bdt_content_start-recording BEFORE using any other browser tools."),(0,a.writeAndExit)(JSON.stringify(b)+`
8
+ `,0)}),r.command("run-checks").description("Run the configured verification.checks (lint/test/\u2026) at the START of verification and record one check_result per check (called by the verifier via Bash; session_id from stdin JSON OR the client env fallback). Records to actions.jsonl ONLY; the verify-gate reads them to enforce. Always exits 0.").action(async()=>{const i=(0,f.resolveAgentProjectDir)();if(g(i,"run-checks")){(0,a.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
9
+ `,0);return}let e;try{e=JSON.parse((0,u.readStdin)())}catch{e={}}const t=(0,m.resolveAgentSessionId)(e,i);t||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
10
+ `),process.exit(1));const o=(0,v.sessionDir)(i,t);(0,l.setLogFile)(`${o}/session.log`);const n=await(0,N.runChecks)(i,t);(0,a.writeAndExit)(`${n.summary}
11
+ `,0)}),r.command("verification-end").description("End a verification cycle (called by agent via Bash)").action(async()=>{const i=(0,f.resolveAgentProjectDir)();if(g(i,"verification-end")){(0,a.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
12
+ `,0);return}let e;try{e=JSON.parse((0,u.readStdin)())}catch{process.stderr.write(`Error: no JSON provided via stdin.
13
+ `),process.exit(1)}const t=(0,m.resolveAgentSessionId)(e,i);t||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
14
+ `),process.exit(1));const o=(0,v.sessionDir)(i,t);(0,l.setLogFile)(`${o}/session.log`);const n=await(0,y.endVerification)({sessionId:t,sessionDir:o,actionsFile:`${o}/actions.jsonl`});n.success?(0,a.writeAndExit)(JSON.stringify({verification_id:n.verificationId,trace_id:n.traceId})+`
12
15
  `,0):(process.stderr.write(n.message+`
13
- `),process.exit(1))}),r.command("submit-verdict").description("Submit verification verdict (called by agent via Bash)").option("--project-dir <dir>","project directory (overrides env vars)").action(async i=>{const e=(0,f.resolveAgentProjectDir)(i.projectDir);if(h(e,"submit-verdict")){(0,d.writeAndExit)(`verification is disabled in this project; verdict ignored
14
- `,0);return}let t;try{t=(0,m.readStdin)()}catch{process.stderr.write(`Error: no verdict JSON provided via stdin.
16
+ `),process.exit(1))}),r.command("submit-verdict").description("Submit verification verdict (called by agent via Bash)").option("--project-dir <dir>","project directory (overrides env vars)").action(async i=>{const e=(0,f.resolveAgentProjectDir)(i.projectDir);if(g(e,"submit-verdict")){(0,a.writeAndExit)(`verification is disabled in this project; verdict ignored
17
+ `,0);return}let t;try{t=(0,u.readStdin)()}catch{process.stderr.write(`Error: no verdict JSON provided via stdin.
15
18
  `),process.exit(1)}let o;try{o=JSON.parse(t)}catch{process.stderr.write(`Error: verdict is not valid JSON.
16
- `),process.exit(1)}const n=(0,v.resolveAgentSessionId)(o,e);n||(process.stderr.write(`Error: verdict JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
17
- `),process.exit(1));const c=(0,p.sessionDir)(e,n);(0,l.setLogFile)(`${c}/session.log`);const a=await(0,k.runSubmitVerdict)({sessionId:n,sessionDir:c,verdictFile:`${c}/verdict.json`,actionsFile:`${c}/actions.jsonl`,verdictJson:t,projectDir:e});a.success?(0,d.writeAndExit)(a.message+`
18
- `,0):(process.stderr.write(a.message+`
19
- `),process.exit(1))}),r.command("record-fix").description("Record what was fixed after a fail verdict (called by agent via Bash). Stashed locally in state.json; merged into the next pass verdict's fixes. Emits no collector event.").action(async()=>{const i=(0,f.resolveAgentProjectDir)();if(h(i,"record-fix")){(0,d.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
20
- `,0);return}let e;try{e=JSON.parse((0,m.readStdin)())}catch{process.stderr.write(`Error: no JSON provided via stdin.
21
- `),process.exit(1)}const t=(0,v.resolveAgentSessionId)(e,i);t||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
22
- `),process.exit(1));const o=e.fixes,n=Array.isArray(o)?o.filter(a=>typeof a=="string"&&a.length>0):[];n.length===0&&(process.stderr.write(`Error: JSON must include a non-empty "fixes" array of strings.
23
- `),process.exit(1));const c=(0,p.sessionDir)(i,t);(0,l.setLogFile)(`${c}/session.log`),(0,j.addPendingFixes)(c,n),l.logger.debug(`record-fix: session=${t} recorded ${n.length} fix note(s)`),(0,d.writeAndExit)(JSON.stringify({recorded:n.length})+`
19
+ `),process.exit(1)}const n=(0,m.resolveAgentSessionId)(o,e);n||(process.stderr.write(`Error: verdict JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
20
+ `),process.exit(1));const c=(0,v.sessionDir)(e,n);(0,l.setLogFile)(`${c}/session.log`);const d=await(0,I.runSubmitVerdict)({sessionId:n,sessionDir:c,verdictFile:`${c}/verdict.json`,actionsFile:`${c}/actions.jsonl`,verdictJson:t,projectDir:e});d.success?(0,a.writeAndExit)(d.message+`
21
+ `,0):(process.stderr.write(d.message+`
22
+ `),process.exit(1))}),r.command("record-fix").description("Record what was fixed after a fail verdict (called by agent via Bash). Stashed locally in state.json; merged into the next pass verdict's fixes. Emits no collector event.").action(async()=>{const i=(0,f.resolveAgentProjectDir)();if(g(i,"record-fix")){(0,a.writeAndExit)(JSON.stringify({message:"verification is disabled in this project; ignoring"})+`
23
+ `,0);return}let e;try{e=JSON.parse((0,u.readStdin)())}catch{process.stderr.write(`Error: no JSON provided via stdin.
24
+ `),process.exit(1)}const t=(0,m.resolveAgentSessionId)(e,i);t||(process.stderr.write(`Error: JSON must include a "session_id" field, or run as a delegated sub-agent (your client resolves the session automatically).
25
+ `),process.exit(1));const o=e.fixes,n=Array.isArray(o)?o.filter(d=>typeof d=="string"&&d.length>0):[];n.length===0&&(process.stderr.write(`Error: JSON must include a non-empty "fixes" array of strings.
26
+ `),process.exit(1));const c=(0,v.sessionDir)(i,t);(0,l.setLogFile)(`${c}/session.log`),(0,j.addPendingFixes)(c,n),l.logger.debug(`record-fix: session=${t} recorded ${n.length} fix note(s)`),(0,a.writeAndExit)(JSON.stringify({recorded:n.length})+`
24
27
  `,0)});0&&(module.exports={hookCommand});
@@ -1 +1 @@
1
- "use strict";var S=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var g=(n,e)=>S(n,"name",{value:e,configurable:!0});var V=(n,e)=>{for(var r in e)S(n,r,{get:e[r],enumerable:!0})},_=(n,e,r,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let d of N(e))!R.call(n,d)&&d!==r&&S(n,d,{get:()=>e[d],enumerable:!(c=A(e,d))||c.enumerable});return n};var B=n=>_(S({},"__esModule",{value:!0}),n);var Y={};V(Y,{CYCLE_HINTS:()=>D,installCommand:()=>F,runInstallAll:()=>j,syncSchemaIfChanged:()=>W});module.exports=B(Y);var P=require("commander"),T=require("fs"),L=require("path"),f=require("../clients/registry"),M=require("../clients/claude"),p=require("../lib/config"),t=require("../lib/output"),k=require("../lib/projects-registry"),m=require("../lib/prompt"),v=require("../lib/telemetry"),I=require("../lib/install-version"),h=require("../lib/schema-sync"),C=require("./cycle-toggle"),o=require("./mode-select");const D={browser:"web UI \xB7 DOM \xB7 console \xB7 a11y \xB7 screenshots \xB7 recording",node:"Node.js runtime \xB7 tracepoints \xB7 logpoints \xB7 exceptions \xB7 variables \xB7 logs",backend:"HTTP \xB7 gRPC \xB7 GraphQL \xB7 WebSocket \xB7 DB \xB7 logs",android:"Android device / emulator \xB7 UI interactions \xB7 screenshots \xB7 Logcat \xB7 HTTP capture",terminal:"CLI \xB7 REPL \xB7 TUI \xB7 PTY drive \xB7 output capture"};async function O(n,e,r){if(e!==void 0)return r&&e!=="enforce"&&t.log.warn(`--strict ignored: it only applies to --mode enforce (strict is inert in ${e}).`),{mode:e,strict:e==="enforce"&&r?!0:void 0};if(r&&t.log.warn("--strict ignored: pass it together with --mode enforce."),!(0,m.isInteractive)())return;const c=Math.max(0,o.ALL_MODES.indexOf((0,o.resolveInstallDefaultMode)(n))),d=o.ALL_MODES.map(u=>({label:o.MODE_LABELS[u],hint:o.MODE_HINTS[u]})),i=(0,o.resolveInstallDefaultStrict)(n)?1:0,a=o.STRICT_OPTIONS.map(u=>({label:o.STRICT_LABELS[u?"true":"false"],hint:o.STRICT_HINTS[u?"true":"false"]}));for(;;){const u=await(0,m.promptSelect)("Which verification mode?",d,c),l=o.ALL_MODES[u];if(l!=="enforce")return{mode:l};const s=await(0,m.promptSelect)(`How strict should verification be? (${t.pc.cyan("Esc")} = back)`,a,i,{allowBack:!0});if(s!==m.PROMPT_BACK)return{mode:l,strict:o.STRICT_OPTIONS[s]}}}g(O,"resolveModeSelection");function E(n,e){if(e===void 0)return;const{mode:r,strict:c}=e,i=(0,o.applyModeToLayer)(n,"project",r,c)?"":t.pc.dim(" (unchanged)"),a=r==="enforce"&&c!==void 0?t.pc.dim(` \xB7 ${o.STRICT_LABELS[c?"true":"false"]}`):"";t.log.info(`Mode: ${t.pc.bold(o.MODE_LABELS[r])}${a}${i}`)}g(E,"applyModeSelection");async function H(n,e,r){if(e!==void 0)return e;const c=(0,p.loadConfig)(n);if((r??(0,p.getVerificationMode)(c))==="monitor"||!(0,m.isInteractive)())return;const i=p.ALL_CYCLES.map(l=>({label:l,hint:D[l]})),a=p.ALL_CYCLES.map((l,s)=>(0,p.isCyclePatternsActive)(c,l)?s:-1).filter(l=>l>=0);return(await(0,m.promptMultiSelect)("Which platforms should require verification?",i,a)).map(l=>p.ALL_CYCLES[l])}g(H,"resolvePlatformSelection");function $(n,e){if(e===void 0)return;const r=(0,C.reconcileCyclesInLayer)(n,"project",e,!0),c=e.length>0?t.pc.bold(e.join(", ")):t.pc.dim("none (monitoring tools only)"),d=r.length>0?t.pc.dim(` \u2014 updated: ${r.join(", ")}`):"";t.log.info(`Platforms: ${c}${d}`)}g($,"applyPlatformSelection");function U(n,e){return e!==void 0?(0,f.resolveTargetClients)(n.path,e):(0,f.detectClients)(n.path)}g(U,"clientsForBatchEntry");async function j(n){const e=(0,f.listActiveProjects)();if(e.length===0)return t.log.info("No registered projects to install. Run `ironbee install` somewhere first."),{failures:0,total:0};t.log.info(`Installing across ${t.pc.bold(String(e.length))} registered project(s)\u2026`),t.log.blank();let r=0;const c=[];for(const i of e)try{const a=U(i,n.client);if(a.length===0){t.log.warn(`Skipping ${i.path} \u2014 no resolvable clients`);continue}const u=a.map(l=>l.name);t.log.label("project",t.pc.dim(i.path)),t.log.step(`installing ${t.pc.bold(u.join(", "))}`),(0,M.prepareIronBeeDir)(i.path),E(i.path,n.mode!==void 0?{mode:n.mode,strict:n.mode==="enforce"&&n.strict?!0:void 0}:void 0),$(i.path,n.platforms);for(const l of a)l.install(i.path);(0,k.upsertProject)(i.path),c.push(...u)}catch(a){r++,t.log.error(` ${i.path}: ${a instanceof Error?a.message:String(a)}`)}t.log.blank(),r===0?t.log.success(`Installed across ${e.length} project(s). ${t.pc.dim("Restart your AI coding client(s) to apply.")}`):t.log.warn(`Completed with ${r} failure(s) \u2014 see above.`);const d=Array.from(new Set(c));return d.length>0&&await(0,v.trackInstall)(d),{failures:r,total:e.length}}g(j,"runInstallAll");async function W(){try{if((0,h.isAutoRerenderDisabled)()||(0,h.readSyncedSchemaVersion)()>=I.INSTALL_SCHEMA_VERSION)return!1;const e=(0,f.listActiveProjects)();if(e.length===0)return(0,h.writeSyncedSchemaVersion)(I.INSTALL_SCHEMA_VERSION),!1;if(!(0,m.isInteractive)())return!1;t.log.blank(),t.log.warn(`IronBee's installed setup structure changed in this version \u2014 re-rendering ${t.pc.bold(String(e.length))} registered project(s):`);for(const r of e.slice(0,10))t.log.label("project",t.pc.dim(r.path));return e.length>10&&t.log.info(t.pc.dim(` \u2026and ${e.length-10} more`)),await(0,m.promptAcknowledge)(t.pc.dim(" Press Enter to update them now\u2026 ")),await j({}),(0,h.writeSyncedSchemaVersion)(I.INSTALL_SCHEMA_VERSION),!0}catch(n){return t.log.blank(),t.log.warn(`IronBee schema sync skipped: ${n instanceof Error?n.message:String(n)}`),!1}}g(W,"syncSchemaIfChanged");const F=new P.Command("install").description("Install IronBee hooks and guidance files into a project. Use --all to install across every registered project (e.g. after a global config change).").argument("[project-dir]","target project directory",".").option("--client <name>",`client to install for (${(0,f.clientNames)()}), or "all"`).option("--all","Install across every project in the user-home inventory (~/.ironbee/projects.json) instead of just one. The [project-dir] argument is ignored when --all is set.").option("--platforms <list>",`comma-separated platforms to enable (${p.ALL_CYCLES.join(", ")}); skips the interactive picker. Empty ("") disables all. Default: interactive picker (pre-checked from current config), browser-only on a fresh non-interactive install.`).option("--mode <mode>",`verification mode (${o.ALL_MODES.join(", ")}); skips the interactive picker. enforce = full enforcement, assist = tools installed but not enforced (default), monitor = monitoring-only. Default: interactive picker (pre-selecting the current mode), untouched on a non-interactive install.`).option("--strict","with --mode enforce: always make the agent actually try every change in the app \u2014 it can't skip any. Enforce-only (ignored for assist/monitor or with no --mode). Default: the agent may skip changes with nothing to try (refactors, type-only edits, docs). Interactively, picking enforce opens this as a sub-choice.").action(async(n,e)=>{let r;if(e.platforms!==void 0)try{r=(0,C.parsePlatformsFlag)(e.platforms)}catch(s){t.log.error(s instanceof Error?s.message:String(s)),process.exit(1)}let c;if(e.mode!==void 0)try{c=(0,o.parseModeFlag)(e.mode)}catch(s){t.log.error(s instanceof Error?s.message:String(s)),process.exit(1)}const d=e.strict===!0;if(e.all===!0){(await j({client:e.client,platforms:r,mode:c,strict:d})).failures>0&&process.exit(1);return}const i=(0,L.resolve)(n);(0,T.existsSync)(i)||(t.log.error(`Directory not found: ${i}`),process.exit(1));let a;if(e.client!==void 0)try{a=(0,f.resolveTargetClients)(i,e.client)}catch(s){t.log.error(s instanceof Error?s.message:String(s)),process.exit(1)}else{const s=(0,f.detectClients)(i);if(s.length>0){a=s;const b=s.map(w=>w.name).join(", ");t.log.info(`Detected client(s): ${t.pc.bold(b)}`)}else if((0,m.isInteractive)()){const b=[...f.REGISTERED_CLIENTS.map(y=>y.name),"all"],w=b.map(y=>({label:y,hint:y==="all"?"every registered client":void 0}));t.log.warn(`No client detected in ${t.pc.dim(i)}.`);const x=await(0,m.promptSelect)("Which client(s) to install for?",w,0);a=(0,f.resolveTargetClients)(i,b[x])}else t.log.warn(`No client detected. Defaulting to: ${f.REGISTERED_CLIENTS[0].name}`),a=[f.REGISTERED_CLIENTS[0]]}const u=await O(i,c,d),l=await H(i,r,u?.mode);t.log.blank(),(0,M.prepareIronBeeDir)(i),E(i,u),$(i,l);for(const s of a)s.install(i);(0,k.upsertProject)(i),t.log.blank(),t.log.label("project",t.pc.dim(i)),t.log.blank(),t.log.success(`IronBee installed. ${t.pc.dim("Restart your AI coding client to activate the hooks.")}`),await(0,v.trackInstall)(a.map(s=>s.name),i)});0&&(module.exports={CYCLE_HINTS,installCommand,runInstallAll,syncSchemaIfChanged});
1
+ "use strict";var C=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var h=(n,e)=>C(n,"name",{value:e,configurable:!0});var V=(n,e)=>{for(var r in e)C(n,r,{get:e[r],enumerable:!0})},B=(n,e,r,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of _(e))!O.call(n,l)&&l!==r&&C(n,l,{get:()=>e[l],enumerable:!(c=R(e,l))||c.enumerable});return n};var H=n=>B(C({},"__esModule",{value:!0}),n);var q={};V(q,{CYCLE_HINTS:()=>D,SUGGEST_TIMEOUT_MS:()=>N,installCommand:()=>Y,runInstallAll:()=>E,syncSchemaIfChanged:()=>F});module.exports=H(q);var T=require("commander"),L=require("fs"),x=require("path"),d=require("../clients/registry"),v=require("../clients/claude"),p=require("../lib/config"),t=require("../lib/output"),k=require("../lib/projects-registry"),u=require("../lib/prompt"),j=require("../lib/telemetry"),w=require("../lib/install-version"),y=require("../lib/schema-sync"),M=require("./cycle-toggle"),A=require("./platform-suggest"),o=require("./mode-select");const D={browser:"web UI \xB7 DOM \xB7 console \xB7 a11y \xB7 screenshots \xB7 recording",node:"Node.js runtime \xB7 tracepoints \xB7 logpoints \xB7 exceptions \xB7 variables \xB7 logs",backend:"HTTP \xB7 gRPC \xB7 GraphQL \xB7 WebSocket \xB7 DB \xB7 logs",android:"Android device / emulator \xB7 UI interactions \xB7 screenshots \xB7 Logcat \xB7 HTTP capture",terminal:"CLI \xB7 REPL \xB7 TUI \xB7 PTY drive \xB7 output capture"},N=6e4;async function U(n,e,r){if(e!==void 0)return r&&e!=="enforce"&&t.log.warn(`--strict ignored: it only applies to --mode enforce (strict is inert in ${e}).`),{mode:e,strict:e==="enforce"&&r?!0:void 0};if(r&&t.log.warn("--strict ignored: pass it together with --mode enforce."),!(0,u.isInteractive)())return;const c=Math.max(0,o.ALL_MODES.indexOf((0,o.resolveInstallDefaultMode)(n))),l=o.ALL_MODES.map(f=>({label:o.MODE_LABELS[f],hint:o.MODE_HINTS[f]})),i=(0,o.resolveInstallDefaultStrict)(n)?1:0,a=o.STRICT_OPTIONS.map(f=>({label:o.STRICT_LABELS[f?"true":"false"],hint:o.STRICT_HINTS[f?"true":"false"]}));for(;;){const f=await(0,u.promptSelect)("Which verification mode?",l,c),g=o.ALL_MODES[f];if(g!=="enforce")return{mode:g};const s=await(0,u.promptSelect)(`How strict should verification be? (${t.pc.cyan("Esc")} = back)`,a,i,{allowBack:!0});if(s!==u.PROMPT_BACK)return{mode:g,strict:o.STRICT_OPTIONS[s]}}}h(U,"resolveModeSelection");function P(n,e){if(e===void 0)return;const{mode:r,strict:c}=e,i=(0,o.applyModeToLayer)(n,"project",r,c)?"":t.pc.dim(" (unchanged)"),a=r==="enforce"&&c!==void 0?t.pc.dim(` \xB7 ${o.STRICT_LABELS[c?"true":"false"]}`):"";t.log.info(`Mode: ${t.pc.bold(o.MODE_LABELS[r])}${a}${i}`)}h(P,"applyModeSelection");async function G(n,e,r,c){if(e!==void 0)return e;const l=(0,p.loadConfig)(n);if((r??(0,p.getVerificationMode)(l))==="monitor"||!(0,u.isInteractive)())return;const a=p.ALL_CYCLES.map(m=>({label:m,hint:D[m]})),f=p.ALL_CYCLES.map((m,S)=>(0,p.isCyclePatternsActive)(l,m)?S:-1).filter(m=>m>=0),g=(0,d.resolveSuggestionClient)(c),s=g?{suggestLabel:g.name,onSuggest:h(async m=>{const S=await(0,A.suggestPlatforms)(g,{projectDir:n,timeoutMs:N,signal:m});return S===null?null:S.map(b=>p.ALL_CYCLES.indexOf(b)).filter(b=>b>=0)},"onSuggest")}:void 0;return(await(0,u.promptMultiSelect)("Which platforms should require verification?",a,f,s)).map(m=>p.ALL_CYCLES[m])}h(G,"resolvePlatformSelection");function $(n,e){if(e===void 0)return;const r=(0,M.reconcileCyclesInLayer)(n,"project",e,!0),c=e.length>0?t.pc.bold(e.join(", ")):t.pc.dim("none (monitoring tools only)"),l=r.length>0?t.pc.dim(` \u2014 updated: ${r.join(", ")}`):"";t.log.info(`Platforms: ${c}${l}`)}h($,"applyPlatformSelection");function W(n,e){return e!==void 0?(0,d.resolveTargetClients)(n.path,e):(0,d.detectClients)(n.path)}h(W,"clientsForBatchEntry");async function E(n){const e=(0,d.listActiveProjects)();if(e.length===0)return t.log.info("No registered projects to install. Run `ironbee install` somewhere first."),{failures:0,total:0};t.log.info(`Installing across ${t.pc.bold(String(e.length))} registered project(s)\u2026`),t.log.blank();let r=0;const c=[];for(const i of e)try{const a=W(i,n.client);if(a.length===0){t.log.warn(`Skipping ${i.path} \u2014 no resolvable clients`);continue}const f=a.map(g=>g.name);t.log.label("project",t.pc.dim(i.path)),t.log.step(`installing ${t.pc.bold(f.join(", "))}`),(0,v.prepareIronBeeDir)(i.path),P(i.path,n.mode!==void 0?{mode:n.mode,strict:n.mode==="enforce"&&n.strict?!0:void 0}:void 0),$(i.path,n.platforms);for(const g of a)g.install(i.path);(0,k.upsertProject)(i.path),c.push(...f)}catch(a){r++,t.log.error(` ${i.path}: ${a instanceof Error?a.message:String(a)}`)}t.log.blank(),r===0?t.log.success(`Installed across ${e.length} project(s). ${t.pc.dim("Restart your AI coding client(s) to apply.")}`):t.log.warn(`Completed with ${r} failure(s) \u2014 see above.`);const l=Array.from(new Set(c));return l.length>0&&await(0,j.trackInstall)(l),{failures:r,total:e.length}}h(E,"runInstallAll");async function F(){try{if((0,y.isAutoRerenderDisabled)()||(0,y.readSyncedSchemaVersion)()>=w.INSTALL_SCHEMA_VERSION)return!1;const e=(0,d.listActiveProjects)();if(e.length===0)return(0,y.writeSyncedSchemaVersion)(w.INSTALL_SCHEMA_VERSION),!1;if(!(0,u.isInteractive)())return!1;t.log.blank(),t.log.warn(`IronBee's installed setup structure changed in this version \u2014 re-rendering ${t.pc.bold(String(e.length))} registered project(s):`);for(const r of e.slice(0,10))t.log.label("project",t.pc.dim(r.path));return e.length>10&&t.log.info(t.pc.dim(` \u2026and ${e.length-10} more`)),await(0,u.promptAcknowledge)(t.pc.dim(" Press Enter to update them now\u2026 ")),await E({}),(0,y.writeSyncedSchemaVersion)(w.INSTALL_SCHEMA_VERSION),!0}catch(n){return t.log.blank(),t.log.warn(`IronBee schema sync skipped: ${n instanceof Error?n.message:String(n)}`),!1}}h(F,"syncSchemaIfChanged");const Y=new T.Command("install").description("Install IronBee hooks and guidance files into a project. Use --all to install across every registered project (e.g. after a global config change).").argument("[project-dir]","target project directory",".").option("--client <name>",`client to install for (${(0,d.clientNames)()}), or "all"`).option("--all","Install across every project in the user-home inventory (~/.ironbee/projects.json) instead of just one. The [project-dir] argument is ignored when --all is set.").option("--platforms <list>",`comma-separated platforms to enable (${p.ALL_CYCLES.join(", ")}); skips the interactive picker. Empty ("") disables all. Default: interactive picker (pre-checked from current config), browser-only on a fresh non-interactive install.`).option("--mode <mode>",`verification mode (${o.ALL_MODES.join(", ")}); skips the interactive picker. enforce = full enforcement, assist = tools installed but not enforced (default), monitor = monitoring-only. Default: interactive picker (pre-selecting the current mode), untouched on a non-interactive install.`).option("--strict","with --mode enforce: always make the agent actually try every change in the app \u2014 it can't skip any. Enforce-only (ignored for assist/monitor or with no --mode). Default: the agent may skip changes with nothing to try (refactors, type-only edits, docs). Interactively, picking enforce opens this as a sub-choice.").action(async(n,e)=>{let r;if(e.platforms!==void 0)try{r=(0,M.parsePlatformsFlag)(e.platforms)}catch(s){t.log.error(s instanceof Error?s.message:String(s)),process.exit(1)}let c;if(e.mode!==void 0)try{c=(0,o.parseModeFlag)(e.mode)}catch(s){t.log.error(s instanceof Error?s.message:String(s)),process.exit(1)}const l=e.strict===!0;if(e.all===!0){(await E({client:e.client,platforms:r,mode:c,strict:l})).failures>0&&process.exit(1);return}const i=(0,x.resolve)(n);(0,L.existsSync)(i)||(t.log.error(`Directory not found: ${i}`),process.exit(1));let a;if(e.client!==void 0)try{a=(0,d.resolveTargetClients)(i,e.client)}catch(s){t.log.error(s instanceof Error?s.message:String(s)),process.exit(1)}else{const s=(0,d.detectClients)(i);if(s.length>0){a=s;const I=s.map(m=>m.name).join(", ");t.log.info(`Detected client(s): ${t.pc.bold(I)}`)}else if((0,u.isInteractive)()){const I=[...d.REGISTERED_CLIENTS.map(b=>b.name),"all"],m=I.map(b=>({label:b,hint:b==="all"?"every registered client":void 0}));t.log.warn(`No client detected in ${t.pc.dim(i)}.`);const S=await(0,u.promptSelect)("Which client(s) to install for?",m,0);a=(0,d.resolveTargetClients)(i,I[S])}else t.log.warn(`No client detected. Defaulting to: ${d.REGISTERED_CLIENTS[0].name}`),a=[d.REGISTERED_CLIENTS[0]]}const f=await U(i,c,l),g=await G(i,r,f?.mode,a);t.log.blank(),(0,v.prepareIronBeeDir)(i),P(i,f),$(i,g);for(const s of a)s.install(i);(0,k.upsertProject)(i),t.log.blank(),t.log.label("project",t.pc.dim(i)),t.log.blank(),t.log.success(`IronBee installed. ${t.pc.dim("Restart your AI coding client to activate the hooks.")}`),await(0,j.trackInstall)(a.map(s=>s.name),i)});0&&(module.exports={CYCLE_HINTS,SUGGEST_TIMEOUT_MS,installCommand,runInstallAll,syncSchemaIfChanged});
@@ -0,0 +1,2 @@
1
+ "use strict";var u=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var l=(e,n)=>u(e,"name",{value:n,configurable:!0});var w=(e,n)=>{for(var r in n)u(e,r,{get:n[r],enumerable:!0})},y=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of h(n))!b.call(e,o)&&o!==r&&u(e,o,{get:()=>n[o],enumerable:!(t=m(n,o))||t.enumerable});return e};var j=e=>y(u({},"__esModule",{value:!0}),e);var C={};w(C,{buildPlatformSuggestionPrompt:()=>p,parsePlatformSuggestion:()=>d,suggestPlatforms:()=>x});module.exports=j(C);var f=require("../lib/config"),g=require("../lib/logger");const S={browser:"the project has a web/browser UI \u2014 frontend pages, components, or styles rendered in a browser",node:"the project has a Node.js runtime whose server-side behavior is worth debugging (Node/Next/Express servers, API routes)",backend:"the project exposes backend protocols to call and verify (HTTP/REST, gRPC, GraphQL, or WebSocket endpoints) in ANY language",android:"the project is an Android app (Kotlin/Java + Gradle, or a React Native Android target)",terminal:"the project is a CLI, REPL, or TUI driven from a terminal"};function p(e){return["You are helping configure IronBee verification platforms for a software project.","Inspect the project in the current working directory (read files as needed) and decide which","of the following verification platforms apply. Enable a platform ONLY when the project","actually has that surface; omit anything that doesn't clearly apply.","","Platforms:",...e.map(r=>{const t=S[r]??`the project uses the ${r} surface`;return`- ${r}: ${t}`}),"","Respond with ONLY a JSON object, no prose, no markdown, in EXACTLY this shape:",'{"platforms": ["browser", "backend"]}',"","Use only platform names from the list above. Returning several is fine. If unsure about one, omit it."].join(`
2
+ `)}l(p,"buildPlatformSuggestionPrompt");function c(e){let n=0,r=-1,t=!1,o=!1,s=null;for(let i=0;i<e.length;i++){const a=e[i];if(t){o?o=!1:a==="\\"?o=!0:a==='"'&&(t=!1);continue}if(a==='"'){t=!0;continue}a==="{"||a==="["?(n===0&&(r=i),n++):(a==="}"||a==="]")&&n>0&&(n--,n===0&&r>=0&&(s=e.slice(r,i+1),r=-1))}return s}l(c,"extractLastBalancedJson");function k(e){const n=[],r=/```(?:json)?\s*([\s\S]*?)```/gi,t=[];let o=r.exec(e);for(;o!==null;)t.push(o[1]),o=r.exec(e);for(const i of t.reverse())n.push(c(i)??i.trim());const s=c(e);return s!==null&&n.push(s),n}l(k,"jsonCandidates");function P(e,n){const r=new Set(e.filter(t=>typeof t=="string").map(t=>t.trim().toLowerCase()));return n.filter(t=>r.has(t.toLowerCase()))}l(P,"normalizePlatforms");function d(e,n){if(typeof e!="string"||e.trim().length===0)return null;for(const r of k(e)){let t;try{t=JSON.parse(r)}catch{continue}let o=null;if(Array.isArray(t)?o=t:t!==null&&typeof t=="object"&&Array.isArray(t.platforms)&&(o=t.platforms),o===null)continue;const s=P(o,n);if(s.length>0)return s}return null}l(d,"parsePlatformSuggestion");async function x(e,n){if(typeof e.runHeadlessPrompt!="function")return null;try{const r=p(f.ALL_CYCLES),t=await e.runHeadlessPrompt(r,n);return d(t,f.ALL_CYCLES)}catch(r){return g.logger.debug(`platform suggestion failed: ${r instanceof Error?r.message:String(r)}`),null}}l(x,"suggestPlatforms");0&&(module.exports={buildPlatformSuggestionPrompt,parsePlatformSuggestion,suggestPlatforms});
@@ -1,7 +1,9 @@
1
- "use strict";var h=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var c=(t,e)=>h(t,"name",{value:e,configurable:!0});var N=(t,e)=>{for(var i in e)h(t,i,{get:e[i],enumerable:!0})},D=(t,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of P(e))!R.call(t,r)&&r!==i&&h(t,r,{get:()=>e[r],enumerable:!(n=j(e,r))||n.enumerable});return t};var q=t=>D(h({},"__esModule",{value:!0}),t);var ne={};N(ne,{ActivityAwareEvent:()=>d.ActivityAwareEvent,Event:()=>d.Event,EventType:()=>d.EventType,EventTypeValue:()=>d.EventTypeValue,FixAwareEvent:()=>d.FixAwareEvent,VerificationAwareEvent:()=>d.VerificationAwareEvent,appendAction:()=>J,baseFields:()=>T,deterministicSessionEndId:()=>I,findDurationSinceLastAction:()=>W,findLastActionTimestamp:()=>z,getFileChangesSinceLastFailVerdict:()=>Z,getFileChangesSinceLastVerification:()=>Y,getToolCallsSinceLastFileChange:()=>B,getToolCallsSinceLastVerification:()=>K,hasFileChangesSinceLastVerification:()=>H,hasToolCallsSinceLastVerdict:()=>Q,hasVerifierEverEngaged:()=>ee,readActionsSinceLastMarker:()=>w,resolveProjectName:()=>F,summarizeFixFileChanges:()=>te});module.exports=q(ne);var l=require("fs"),b=require("crypto"),a=require("path"),f=require("../../lib/logger"),_=require("../../lib/collector"),k=require("../../lib/config"),C=require("../../queue/submit"),S=require("../../queue/types"),V=require("../../queue/register-handlers"),d=require("../../lib/event");function F(t){let e=t,i;for(;;){const n=(0,a.join)(e,".git");if((0,l.existsSync)(n)){const s=L(n);if(s==="directory"){const o=A(n);return o||(0,a.basename)(e)}if(s==="linked-pointer"){const o=E(n),u=o!==void 0?A(o):void 0;return u||(0,a.basename)(e)}s==="worktree-pointer"&&i===void 0&&(i=M(n))}const r=(0,a.dirname)(e);if(r===e)break;e=r}return i??(0,a.basename)(t)}c(F,"resolveProjectName");function L(t){try{const e=(0,l.statSync)(t);if(e.isDirectory())return"directory";if(!e.isFile())return"other";const i=E(t);return i===void 0?"other":(0,l.existsSync)((0,a.join)(i,"commondir"))?"worktree-pointer":"linked-pointer"}catch(e){return f.logger.debug(`resolveProjectName: stat failed for ${t}: ${e instanceof Error?e.message:e}`),"other"}}c(L,"classifyGitEntry");function E(t){try{const i=(0,l.readFileSync)(t,"utf-8").trim().match(/^gitdir:\s*(.+)$/m);if(!i)return;const n=i[1].trim();return(0,a.isAbsolute)(n)?n:(0,a.resolve)((0,a.dirname)(t),n)}catch(e){f.logger.debug(`resolveProjectName: pointer at ${t} unreadable: ${e instanceof Error?e.message:e}`);return}}c(E,"readGitdirPointer");function A(t){try{const e=(0,a.join)(t,"config");if(!(0,l.existsSync)(e))return;const i=U((0,l.readFileSync)(e,"utf-8"));return i?O(i):void 0}catch(e){f.logger.debug(`resolveProjectName: failed to read git config at ${t}: ${e instanceof Error?e.message:e}`);return}}c(A,"repoNameFromGitConfig");function M(t){const e=E(t);if(e===void 0)return;const i=(0,a.join)(e,"commondir");let n;try{if((0,l.existsSync)(i)){const o=(0,l.readFileSync)(i,"utf-8").trim();n=(0,a.isAbsolute)(o)?o:(0,a.resolve)(e,o)}else n=e}catch(o){f.logger.debug(`resolveProjectName: commondir at ${i} unreadable: ${o instanceof Error?o.message:o}`);return}const r=A(n);if(r)return r;const s=(0,a.basename)(n)===".git"?(0,a.basename)((0,a.dirname)(n)):(0,a.basename)(n);return s.length>0?s:void 0}c(M,"repoNameFromWorktreePointer");function U(t){const e=t.split(/\r?\n/);let i=null,n=null,r,s;for(const o of e){const u=o.trim();if(u.length===0||u.startsWith("#")||u.startsWith(";"))continue;const g=u.match(/^\[([^\s\]]+)(?:\s+"([^"]*)")?\]$/);if(g){i=g[1].toLowerCase(),n=g[2]??null;continue}if(i!=="remote"||n===null)continue;const p=u.match(/^url\s*=\s*(.+?)\s*$/i);if(!p)continue;const m=p[1];n==="origin"&&(r=m),s===void 0&&(s=m)}return r??s}c(U,"readFirstRemoteUrl");function O(t){let e=t.trim();if(e.length===0)return;const i=e.match(/^[^/@]+@[^/:]+:(.+)$/);if(i?e=i[1]:e=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*\//i,""),e=e.replace(/[?#].*$/,"").replace(/\/+$/,""),e.length===0)return;const r=(e.split("/").pop()??"").replace(/\.git$/i,"");return r.length>0?r:void 0}c(O,"repoNameFromRemoteUrl");function T(t){const e=(0,a.basename)((0,a.dirname)(t)),i=(0,a.dirname)(t),{getUserEmail:n,getUsageType:r,getUsagePlan:s,getProjectDir:o}=require("./session-state"),u=o(i)??(0,a.dirname)((0,a.dirname)((0,a.dirname)(i))),g=n(i),p=r(i),m=s(i),v={id:(0,b.randomUUID)(),session_id:e,project_name:F(u)};return g&&(v.user_email=g),p&&(v.usage_type=p),m&&(v.usage_plan=m),v}c(T,"baseFields");function I(t){const e=(0,b.createHash)("sha256").update("session_end:"+t).digest("hex");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20,32)}`}c(I,"deterministicSessionEndId");async function J(t,e){const i=T(t);e.id||(e.id=i.id),e.session_id||(e.session_id=i.session_id),e.project_name||(e.project_name=i.project_name);try{(0,l.mkdirSync)((0,a.dirname)(t),{recursive:!0}),(0,l.appendFileSync)(t,JSON.stringify(e)+`
2
- `)}catch(n){f.logger.debug(`failed to append action to ${t}: ${n}`)}if(e.type!=="tool_call"){const n=(0,a.dirname)(t),r=(0,a.basename)(n),{getProjectDir:s}=require("./session-state"),o=s(n)??(0,a.dirname)((0,a.dirname)((0,a.dirname)(n)));try{await(0,_.sendToCollector)(e,r,o)}catch(u){u instanceof _.RetriableCollectorError?G(o,r,e,u):f.logger.debug(`failed to send action to collector: ${u}`)}}}c(J,"appendAction");function G(t,e,i,n){if(!(0,k.isJobQueueEnabled)(t)){f.logger.debug(`collector fallback: jobQueue disabled, dropping type=${i.type} id=${i.id} (cause: ${n.message})`);return}try{(0,C.submit)(t,e,V.SEND_EVENT_TYPE,i),f.logger.debug(`collector fallback: enqueued type=${i.type} id=${i.id} as send_event (cause: ${n.message})`)}catch(r){if(r instanceof S.JobTooLargeError){f.logger.debug(`collector fallback: event too large for queue (${r.sizeBytes} bytes), dropping type=${i.type} id=${i.id}`);return}f.logger.debug(`collector fallback: queue submit failed for type=${i.type} id=${i.id}: ${r}`)}}c(G,"enqueueCollectorFallback");function W(t,e,i){if((0,l.existsSync)(t))try{const r=(0,l.readFileSync)(t,"utf-8").trim().split(`
3
- `).filter(s=>s.length>0);for(let s=r.length-1;s>=0;s--)try{const o=JSON.parse(r[s]);if(o.type===e&&typeof o.timestamp=="number")return i-o.timestamp}catch{}}catch(n){f.logger.debug(`failed to find duration for ${e}: ${n}`)}}c(W,"findDurationSinceLastAction");function w(t,e){return y(t,i=>i.type===e)}c(w,"readActionsSinceLastMarker");function z(t){if((0,l.existsSync)(t))try{const i=(0,l.readFileSync)(t,"utf-8").trim().split(`
4
- `).filter(n=>n.length>0);for(let n=i.length-1;n>=0;n--)try{const r=JSON.parse(i[n]);if(typeof r.timestamp=="number")return r.timestamp}catch{}}catch(e){f.logger.debug(`failed to read last action timestamp from ${t}: ${e}`)}}c(z,"findLastActionTimestamp");function y(t,e){if(!(0,l.existsSync)(t))return[];try{const n=(0,l.readFileSync)(t,"utf-8").trim().split(`
5
- `).filter(o=>o.length>0);let r=-1;const s=[];for(let o=0;o<n.length;o++)try{const u=JSON.parse(n[o]);s.push(u),e(u)&&(r=o)}catch{}return s.slice(r+1)}catch(i){return f.logger.debug(`failed to read actions from ${t}: ${i}`),[]}}c(y,"readActionsSinceMatch");function x(t){return t.type!=="verification_requested"?!1:t.action==="allow"}c(x,"isAllowVerificationRequested");function $(t){if(t.type!=="tool_call")return!1;const e=t.verification_id;return typeof e=="string"&&e.length>0}c($,"isVerificationScopedToolCall");function K(t){return y(t,x).filter($)}c(K,"getToolCallsSinceLastVerification");function B(t){return w(t,"file_change").filter($)}c(B,"getToolCallsSinceLastFileChange");function Q(t){return w(t,"verdict_write").some($)}c(Q,"hasToolCallsSinceLastVerdict");function H(t){return y(t,x).some(i=>i.type==="file_change")}c(H,"hasFileChangesSinceLastVerification");function Y(t){return y(t,x).filter(i=>i.type==="file_change")}c(Y,"getFileChangesSinceLastVerification");function X(t){return t.type!=="verdict_write"?!1:t.verdict?.status==="fail"}c(X,"isFailVerdictWrite");function Z(t){if(!(0,l.existsSync)(t))return[];try{const n=(0,l.readFileSync)(t,"utf-8").trim().split(`
6
- `).filter(o=>o.length>0).map(o=>{try{return JSON.parse(o)}catch{return null}});let r=-1;for(let o=0;o<n.length;o++){const u=n[o];u!==null&&X(u)&&(r=o)}if(r<0)return[];const s=[];for(let o=r+1;o<n.length;o++){const u=n[o];u!==null&&u.type==="file_change"&&s.push(u)}return s}catch(e){return f.logger.debug(`failed to read file changes since last fail verdict: ${e}`),[]}}c(Z,"getFileChangesSinceLastFailVerdict");function ee(t){if(!(0,l.existsSync)(t))return!1;try{const i=(0,l.readFileSync)(t,"utf-8").trim().split(`
7
- `).filter(n=>n.length>0);for(const n of i){let r;try{r=JSON.parse(n)}catch{continue}if(r.type==="verification_start")return!0;if(r.type==="tool_call"){const s=r;if(s.tool_type==="mcp"&&typeof s.mcp_server=="string"&&s.mcp_server.endsWith("-devtools"))return!0}}return!1}catch(e){return f.logger.debug(`failed to scan verifier engagement in ${t}: ${e}`),!1}}c(ee,"hasVerifierEverEngaged");function te(t){if(t.length===0)return[];const e=new Map,i=[];for(const n of t){const r=n.file_path;let s=e.get(r);s||(s={op:n.operation,added:0,removed:0},e.set(r,s),i.push(r)),s.op=s.op==="create"||n.operation==="create"?"create":n.operation,s.added+=typeof n.lines_added=="number"?n.lines_added:0,s.removed+=typeof n.lines_removed=="number"?n.lines_removed:0}return i.map(n=>{const r=e.get(n);return`${r.op} ${n} (+${r.added}/-${r.removed})`})}c(te,"summarizeFixFileChanges");0&&(module.exports={ActivityAwareEvent,Event,EventType,EventTypeValue,FixAwareEvent,VerificationAwareEvent,appendAction,baseFields,deterministicSessionEndId,findDurationSinceLastAction,findLastActionTimestamp,getFileChangesSinceLastFailVerdict,getFileChangesSinceLastVerification,getToolCallsSinceLastFileChange,getToolCallsSinceLastVerification,hasFileChangesSinceLastVerification,hasToolCallsSinceLastVerdict,hasVerifierEverEngaged,readActionsSinceLastMarker,resolveProjectName,summarizeFixFileChanges});
1
+ "use strict";var v=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var a=(t,e)=>v(t,"name",{value:e,configurable:!0});var P=(t,e)=>{for(var i in e)v(t,i,{get:e[i],enumerable:!0})},D=(t,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of j(e))!N.call(t,r)&&r!==i&&v(t,r,{get:()=>e[r],enumerable:!(n=F(e,r))||n.enumerable});return t};var L=t=>D(v({},"__esModule",{value:!0}),t);var re={};P(re,{ActivityAwareEvent:()=>f.ActivityAwareEvent,Event:()=>f.Event,EventType:()=>f.EventType,EventTypeValue:()=>f.EventTypeValue,FixAwareEvent:()=>f.FixAwareEvent,VerificationAwareEvent:()=>f.VerificationAwareEvent,appendAction:()=>I,baseFields:()=>T,deterministicSessionEndId:()=>J,findDurationSinceLastAction:()=>W,findLastActionTimestamp:()=>z,getCheckResultsForLatestVerification:()=>X,getFileChangesSinceLastFailVerdict:()=>te,getFileChangesSinceLastVerification:()=>Y,getLatestVerificationId:()=>Z,getToolCallsSinceLastFileChange:()=>B,getToolCallsSinceLastVerification:()=>K,hasFileChangesSinceLastVerification:()=>H,hasToolCallsSinceLastVerdict:()=>Q,hasVerifierEverEngaged:()=>ne,readActionsSinceLastMarker:()=>w,resolveProjectName:()=>R,summarizeFixFileChanges:()=>ie});module.exports=L(re);var u=require("fs"),_=require("crypto"),c=require("path"),d=require("../../lib/logger"),b=require("../../lib/collector"),$=require("../../lib/config"),C=require("../../queue/submit"),S=require("../../queue/types"),V=require("../../queue/register-handlers"),f=require("../../lib/event");function R(t){let e=t,i;for(;;){const n=(0,c.join)(e,".git");if((0,u.existsSync)(n)){const s=q(n);if(s==="directory"){const o=A(n);return o||(0,c.basename)(e)}if(s==="linked-pointer"){const o=E(n),l=o!==void 0?A(o):void 0;return l||(0,c.basename)(e)}s==="worktree-pointer"&&i===void 0&&(i=M(n))}const r=(0,c.dirname)(e);if(r===e)break;e=r}return i??(0,c.basename)(t)}a(R,"resolveProjectName");function q(t){try{const e=(0,u.statSync)(t);if(e.isDirectory())return"directory";if(!e.isFile())return"other";const i=E(t);return i===void 0?"other":(0,u.existsSync)((0,c.join)(i,"commondir"))?"worktree-pointer":"linked-pointer"}catch(e){return d.logger.debug(`resolveProjectName: stat failed for ${t}: ${e instanceof Error?e.message:e}`),"other"}}a(q,"classifyGitEntry");function E(t){try{const i=(0,u.readFileSync)(t,"utf-8").trim().match(/^gitdir:\s*(.+)$/m);if(!i)return;const n=i[1].trim();return(0,c.isAbsolute)(n)?n:(0,c.resolve)((0,c.dirname)(t),n)}catch(e){d.logger.debug(`resolveProjectName: pointer at ${t} unreadable: ${e instanceof Error?e.message:e}`);return}}a(E,"readGitdirPointer");function A(t){try{const e=(0,c.join)(t,"config");if(!(0,u.existsSync)(e))return;const i=U((0,u.readFileSync)(e,"utf-8"));return i?O(i):void 0}catch(e){d.logger.debug(`resolveProjectName: failed to read git config at ${t}: ${e instanceof Error?e.message:e}`);return}}a(A,"repoNameFromGitConfig");function M(t){const e=E(t);if(e===void 0)return;const i=(0,c.join)(e,"commondir");let n;try{if((0,u.existsSync)(i)){const o=(0,u.readFileSync)(i,"utf-8").trim();n=(0,c.isAbsolute)(o)?o:(0,c.resolve)(e,o)}else n=e}catch(o){d.logger.debug(`resolveProjectName: commondir at ${i} unreadable: ${o instanceof Error?o.message:o}`);return}const r=A(n);if(r)return r;const s=(0,c.basename)(n)===".git"?(0,c.basename)((0,c.dirname)(n)):(0,c.basename)(n);return s.length>0?s:void 0}a(M,"repoNameFromWorktreePointer");function U(t){const e=t.split(/\r?\n/);let i=null,n=null,r,s;for(const o of e){const l=o.trim();if(l.length===0||l.startsWith("#")||l.startsWith(";"))continue;const g=l.match(/^\[([^\s\]]+)(?:\s+"([^"]*)")?\]$/);if(g){i=g[1].toLowerCase(),n=g[2]??null;continue}if(i!=="remote"||n===null)continue;const p=l.match(/^url\s*=\s*(.+?)\s*$/i);if(!p)continue;const m=p[1];n==="origin"&&(r=m),s===void 0&&(s=m)}return r??s}a(U,"readFirstRemoteUrl");function O(t){let e=t.trim();if(e.length===0)return;const i=e.match(/^[^/@]+@[^/:]+:(.+)$/);if(i?e=i[1]:e=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*\//i,""),e=e.replace(/[?#].*$/,"").replace(/\/+$/,""),e.length===0)return;const r=(e.split("/").pop()??"").replace(/\.git$/i,"");return r.length>0?r:void 0}a(O,"repoNameFromRemoteUrl");function T(t){const e=(0,c.basename)((0,c.dirname)(t)),i=(0,c.dirname)(t),{getUserEmail:n,getUsageType:r,getUsagePlan:s,getProjectDir:o}=require("./session-state"),l=o(i)??(0,c.dirname)((0,c.dirname)((0,c.dirname)(i))),g=n(i),p=r(i),m=s(i),h={id:(0,_.randomUUID)(),session_id:e,project_name:R(l)};return g&&(h.user_email=g),p&&(h.usage_type=p),m&&(h.usage_plan=m),h}a(T,"baseFields");function J(t){const e=(0,_.createHash)("sha256").update("session_end:"+t).digest("hex");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20,32)}`}a(J,"deterministicSessionEndId");async function I(t,e){const i=T(t);e.id||(e.id=i.id),e.session_id||(e.session_id=i.session_id),e.project_name||(e.project_name=i.project_name);try{(0,u.mkdirSync)((0,c.dirname)(t),{recursive:!0}),(0,u.appendFileSync)(t,JSON.stringify(e)+`
2
+ `)}catch(n){d.logger.debug(`failed to append action to ${t}: ${n}`)}if(e.type!=="tool_call"&&e.type!=="check_result"){const n=(0,c.dirname)(t),r=(0,c.basename)(n),{getProjectDir:s}=require("./session-state"),o=s(n)??(0,c.dirname)((0,c.dirname)((0,c.dirname)(n)));try{await(0,b.sendToCollector)(e,r,o)}catch(l){l instanceof b.RetriableCollectorError?G(o,r,e,l):d.logger.debug(`failed to send action to collector: ${l}`)}}}a(I,"appendAction");function G(t,e,i,n){if(!(0,$.isJobQueueEnabled)(t)){d.logger.debug(`collector fallback: jobQueue disabled, dropping type=${i.type} id=${i.id} (cause: ${n.message})`);return}try{(0,C.submit)(t,e,V.SEND_EVENT_TYPE,i),d.logger.debug(`collector fallback: enqueued type=${i.type} id=${i.id} as send_event (cause: ${n.message})`)}catch(r){if(r instanceof S.JobTooLargeError){d.logger.debug(`collector fallback: event too large for queue (${r.sizeBytes} bytes), dropping type=${i.type} id=${i.id}`);return}d.logger.debug(`collector fallback: queue submit failed for type=${i.type} id=${i.id}: ${r}`)}}a(G,"enqueueCollectorFallback");function W(t,e,i){if((0,u.existsSync)(t))try{const r=(0,u.readFileSync)(t,"utf-8").trim().split(`
3
+ `).filter(s=>s.length>0);for(let s=r.length-1;s>=0;s--)try{const o=JSON.parse(r[s]);if(o.type===e&&typeof o.timestamp=="number")return i-o.timestamp}catch{}}catch(n){d.logger.debug(`failed to find duration for ${e}: ${n}`)}}a(W,"findDurationSinceLastAction");function w(t,e){return y(t,i=>i.type===e)}a(w,"readActionsSinceLastMarker");function z(t){if((0,u.existsSync)(t))try{const i=(0,u.readFileSync)(t,"utf-8").trim().split(`
4
+ `).filter(n=>n.length>0);for(let n=i.length-1;n>=0;n--)try{const r=JSON.parse(i[n]);if(typeof r.timestamp=="number")return r.timestamp}catch{}}catch(e){d.logger.debug(`failed to read last action timestamp from ${t}: ${e}`)}}a(z,"findLastActionTimestamp");function y(t,e){if(!(0,u.existsSync)(t))return[];try{const n=(0,u.readFileSync)(t,"utf-8").trim().split(`
5
+ `).filter(o=>o.length>0);let r=-1;const s=[];for(let o=0;o<n.length;o++)try{const l=JSON.parse(n[o]);s.push(l),e(l)&&(r=o)}catch{}return s.slice(r+1)}catch(i){return d.logger.debug(`failed to read actions from ${t}: ${i}`),[]}}a(y,"readActionsSinceMatch");function x(t){return t.type!=="verification_requested"?!1:t.action==="allow"}a(x,"isAllowVerificationRequested");function k(t){if(t.type!=="tool_call")return!1;const e=t.verification_id;return typeof e=="string"&&e.length>0}a(k,"isVerificationScopedToolCall");function K(t){return y(t,x).filter(k)}a(K,"getToolCallsSinceLastVerification");function B(t){return w(t,"file_change").filter(k)}a(B,"getToolCallsSinceLastFileChange");function Q(t){return w(t,"verdict_write").some(k)}a(Q,"hasToolCallsSinceLastVerdict");function H(t){return y(t,x).some(i=>i.type==="file_change")}a(H,"hasFileChangesSinceLastVerification");function Y(t){return y(t,x).filter(i=>i.type==="file_change")}a(Y,"getFileChangesSinceLastVerification");function X(t){if(!(0,u.existsSync)(t))return[];try{const i=(0,u.readFileSync)(t,"utf-8").trim().split(`
6
+ `).filter(s=>s.length>0);let n;const r=[];for(const s of i){let o;try{o=JSON.parse(s)}catch{continue}if(o.type==="verification_start"){const l=o.verification_id;typeof l=="string"&&l.length>0&&(n=l)}else o.type==="check_result"&&r.push(o)}return n===void 0?[]:r.filter(s=>s.verification_id===n)}catch(e){return d.logger.debug(`failed to read check_results from ${t}: ${e}`),[]}}a(X,"getCheckResultsForLatestVerification");function Z(t){if((0,u.existsSync)(t))try{const i=(0,u.readFileSync)(t,"utf-8").trim().split(`
7
+ `).filter(r=>r.length>0);let n;for(const r of i)try{const s=JSON.parse(r);if(s.type==="verification_start"){const o=s.verification_id;typeof o=="string"&&o.length>0&&(n=o)}}catch{continue}return n}catch(e){d.logger.debug(`failed to read latest verification_id from ${t}: ${e}`);return}}a(Z,"getLatestVerificationId");function ee(t){return t.type!=="verdict_write"?!1:t.verdict?.status==="fail"}a(ee,"isFailVerdictWrite");function te(t){if(!(0,u.existsSync)(t))return[];try{const n=(0,u.readFileSync)(t,"utf-8").trim().split(`
8
+ `).filter(o=>o.length>0).map(o=>{try{return JSON.parse(o)}catch{return null}});let r=-1;for(let o=0;o<n.length;o++){const l=n[o];l!==null&&ee(l)&&(r=o)}if(r<0)return[];const s=[];for(let o=r+1;o<n.length;o++){const l=n[o];l!==null&&l.type==="file_change"&&s.push(l)}return s}catch(e){return d.logger.debug(`failed to read file changes since last fail verdict: ${e}`),[]}}a(te,"getFileChangesSinceLastFailVerdict");function ne(t){if(!(0,u.existsSync)(t))return!1;try{const i=(0,u.readFileSync)(t,"utf-8").trim().split(`
9
+ `).filter(n=>n.length>0);for(const n of i){let r;try{r=JSON.parse(n)}catch{continue}if(r.type==="verification_start")return!0;if(r.type==="tool_call"){const s=r;if(s.tool_type==="mcp"&&typeof s.mcp_server=="string"&&s.mcp_server.endsWith("-devtools"))return!0}}return!1}catch(e){return d.logger.debug(`failed to scan verifier engagement in ${t}: ${e}`),!1}}a(ne,"hasVerifierEverEngaged");function ie(t){if(t.length===0)return[];const e=new Map,i=[];for(const n of t){const r=n.file_path;let s=e.get(r);s||(s={op:n.operation,added:0,removed:0},e.set(r,s),i.push(r)),s.op=s.op==="create"||n.operation==="create"?"create":n.operation,s.added+=typeof n.lines_added=="number"?n.lines_added:0,s.removed+=typeof n.lines_removed=="number"?n.lines_removed:0}return i.map(n=>{const r=e.get(n);return`${r.op} ${n} (+${r.added}/-${r.removed})`})}a(ie,"summarizeFixFileChanges");0&&(module.exports={ActivityAwareEvent,Event,EventType,EventTypeValue,FixAwareEvent,VerificationAwareEvent,appendAction,baseFields,deterministicSessionEndId,findDurationSinceLastAction,findLastActionTimestamp,getCheckResultsForLatestVerification,getFileChangesSinceLastFailVerdict,getFileChangesSinceLastVerification,getLatestVerificationId,getToolCallsSinceLastFileChange,getToolCallsSinceLastVerification,hasFileChangesSinceLastVerification,hasToolCallsSinceLastVerdict,hasVerifierEverEngaged,readActionsSinceLastMarker,resolveProjectName,summarizeFixFileChanges});
@@ -0,0 +1,7 @@
1
+ "use strict";var h=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var f=(e,t)=>h(e,"name",{value:t,configurable:!0});var V=(e,t)=>{for(var n in t)h(e,n,{get:t[n],enumerable:!0})},D=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of O(t))!U.call(e,s)&&s!==n&&h(e,s,{get:()=>t[s],enumerable:!(r=M(t,s))||r.enumerable});return e};var L=e=>D(h({},"__esModule",{value:!0}),e);var G={};V(G,{isShellShimName:()=>E,runChecks:()=>Y});module.exports=L(G);var $=require("child_process"),l=require("path"),_=require("../../lib/logger"),a=require("../../lib/config"),p=require("../../lib/runtime-paths"),m=require("./session-state"),k=require("./actions");const P=8*1024,q=16*1024*1024;function N(e,t){const n=Buffer.from(e,"utf-8");if(n.length<=t)return e;let r=n.length-t;for(;r<n.length&&(n[r]&192)===128;)r++;return`\u2026(truncated, last ${n.length-r} of ${n.length} bytes shown)\u2026
2
+ ${n.subarray(r).toString("utf-8")}`}f(N,"tailCap");const H=["npm","npx","yarn","pnpm","bun","corepack"];function E(e){const t=(0,l.basename)(e).toLowerCase();if(/\.(cmd|bat)$/.test(t))return!0;const n=t.replace(/\.[^.]+$/,"");return H.includes(n)}f(E,"isShellShimName");function W(e){return process.platform==="win32"&&E(e)}f(W,"needsWindowsShell");function J(e){if(e.length===0)return"no checks ran";const t=e.map(s=>{const d=s.status==="pass"?"PASS":s.status==="fail"?"FAIL":"ERROR",g=s.required?"":" (optional)";return` [${d}] ${s.name}${g}`}),n=e.find(s=>s.status==="fail"),r=n?`
3
+
4
+ --- ${n.name} output ---
5
+ ${n.output}`:"";return`Verification checks:
6
+ ${t.join(`
7
+ `)}${r}`}f(J,"buildSummary");async function Y(e,t){const n=(0,a.loadConfig)(e);if(!(0,a.getVerificationEnabled)(n))return{ran:!1,reason:"monitor",results:[],summary:"checks skipped (monitoring mode)"};const r=(0,a.getVerificationChecks)(n),s=Array.isArray(n.verification?.checks)?n.verification.checks.length:0;if(s>r.length&&_.logger.debug(`run-checks: ${s-r.length} malformed verification.checks entr(ies) dropped (missing name/command) \u2014 not run, not enforced`),r.length===0)return{ran:!1,reason:"no_checks",results:[],summary:"no checks configured"};const d=(0,p.sessionDir)(e,t),g=(0,m.getActiveVerificationId)(d);if(g===void 0)return{ran:!1,reason:"no_cycle",results:[],summary:"no active verification cycle \u2014 run `ironbee hook verification-start` before `run-checks`"};const I=(0,m.getActiveActivityId)(d),x=(0,m.getActiveTraceId)(d),w=(0,p.sessionActionsFile)(e,t),b=[];for(const o of r){const T=o.cwd?(0,l.isAbsolute)(o.cwd)?o.cwd:(0,l.resolve)(e,o.cwd):e,A=o.timeoutMs??a.DEFAULT_CHECK_TIMEOUT_MS,F={...process.env,...o.env??{}},B=Date.now();let u="pass",C=null,S=!1,y=!1,c="";try{const i=(0,$.spawnSync)(o.command,o.args??[],{cwd:T,env:F,timeout:A,encoding:"utf-8",maxBuffer:q,shell:W(o.command)});if(c=N(`${i.stdout??""}${i.stderr??""}`,P),i.error){const v=i.error.code;v==="ETIMEDOUT"?(u="fail",S=!0,c=c||`timed out after ${A}ms`):(u="error",y=!0,c=`spawn error (${v??"unknown"}): ${i.error.message}`)}else i.signal!==null?(u="fail",S=i.signal==="SIGTERM",C=null,c=c||`killed by ${i.signal}`):(C=i.status,u=i.status===0?"pass":"fail")}catch(i){u="error",y=!0,c=`spawn error: ${i instanceof Error?i.message:String(i)}`}const R={...(0,k.baseFields)(w),type:"check_result",timestamp:Date.now(),verification_id:g,activity_id:I??"",trace_id:x,name:o.name,command:(0,l.basename)(o.command),status:u,exit_code:C,required:o.required!==!1,duration:Date.now()-B,timed_out:S,output:c};if(y&&(R.error="spawn"),await(0,k.appendAction)(w,R),b.push(R),u==="fail")break}return{ran:!0,results:b,summary:J(b)}}f(Y,"runChecks");0&&(module.exports={isShellShimName,runChecks});